From e659cf27df628a850d6ea47927c2c61c0cde2347 Mon Sep 17 00:00:00 2001 From: Alexander Wiederin Date: Fri, 14 Aug 2026 11:47:53 +0200 Subject: [PATCH 1/2] fix(core): fix TxOutIter::size_hint to use output count --- CHANGELOG.md | 1 + src/core/transaction.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1155c881..fef5b502 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - `verify` now uses an infallible conversion for the internal `ScriptVerifyStatus`, since an unrecognized status can only indicate a build-time mismatch between the bindings and the vendored `libbitcoinkernel` subtree rather than a runtime condition. - `ChainstateManager::get_block_tree_entry` now resolves the requested block instead of returning `None` for every input. It passed the address of the `BlockHash` wrapper to the kernel rather than the block hash handle the wrapper owns, so no lookup ever matched an entry in the block tree. +- `TxOutIter::size_hint` returned the transaction's input count instead of its output count, giving an incorrect hint (and an incorrect `ExactSizeIterator::len`). ## [0.2.1] 2026-05-20 diff --git a/src/core/transaction.rs b/src/core/transaction.rs index a30bb070..6c93f198 100644 --- a/src/core/transaction.rs +++ b/src/core/transaction.rs @@ -821,7 +821,7 @@ impl<'a> Iterator for TxOutIter<'a> { fn size_hint(&self) -> (usize, Option) { let remaining = self .transaction - .input_count() + .output_count() .saturating_sub(self.current_index); (remaining, Some(remaining)) } From aec4a436cdedb9912f8f542f9006daa963459994 Mon Sep 17 00:00:00 2001 From: Alexander Wiederin Date: Fri, 14 Aug 2026 11:49:02 +0200 Subject: [PATCH 2/2] feat(core): Add tests for TxInIter and TxOutIter size_hint --- src/core/transaction.rs | 44 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/core/transaction.rs b/src/core/transaction.rs index 6c93f198..40531987 100644 --- a/src/core/transaction.rs +++ b/src/core/transaction.rs @@ -2498,6 +2498,28 @@ mod tests { assert!(!script_bytes.is_empty()); } + #[test] + fn test_txout_iter_size_hint_matches_len() { + let (tx, _) = get_test_transactions(); + let count = tx.output_count(); + + let mut iter = tx.outputs(); + for remaining in (0..=count).rev() { + assert_eq!(iter.size_hint(), (remaining, Some(remaining))); + assert_eq!(iter.len(), remaining); + iter.next(); + } + + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.len(), 0); + } + + #[test] + fn test_txout_iter_collect_length() { + let (tx, _) = get_test_transactions(); + assert_eq!(tx.outputs().collect::>().len(), tx.output_count()); + } + // TxIn tests #[test] fn test_txin_from_transaction() { @@ -2594,6 +2616,28 @@ mod tests { assert_eq!(iter_count, len); } + #[test] + fn test_txin_iter_size_hint_matches_len() { + let (tx, _) = get_test_transactions(); + let count = tx.input_count(); + + let mut iter = tx.inputs(); + for remaining in (0..=count).rev() { + assert_eq!(iter.size_hint(), (remaining, Some(remaining))); + assert_eq!(iter.len(), remaining); + iter.next(); + } + + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.len(), 0); + } + + #[test] + fn test_txin_iter_collect_length() { + let (tx, _) = get_test_transactions(); + assert_eq!(tx.inputs().collect::>().len(), tx.input_count()); + } + // TxOutPoint tests #[test] fn test_txoutpoint_index() {