Remove excess allocations from Witness::from_iter
What changed, and why it matters
This commit is a routine performance optimization. It rewrites how a Bitcoin transaction witness is built from an iterator so that it uses a single decoder pass instead of allocating many small temporary vectors. There is no indication of a security bug being fixed.
No security action required. Treat as a normal performance refactor.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The FromIterator implementation for Witness is refactored to avoid collecting into Vec
Changed components
primitives/src/witness.rsWitness::from_iterInspect captured patch +26 / −2
diff --git a/primitives/src/witness.rs b/primitives/src/witness.rs
index 13385f92..e3b20e71 100644
--- a/primitives/src/witness.rs
+++ b/primitives/src/witness.rs
@@ -660,8 +660,32 @@ impl<'a> IntoIterator for &'a Witness {
impl<T: AsRef<[u8]>> FromIterator<T> for Witness {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
- let v: Vec<Vec<u8>> = iter.into_iter().map(|item| Vec::from(item.as_ref())).collect();
- Self::from(v)
+ let mut decoder = WitnessDecoder::new();
+
+ // We can't count the number of witness elements without consuming the iterator.
+ // So instead, we build up the full push_bytes buffer and then push it all at once.
+ // We'll start with a 256 byte buffer to double the initial WitnessDecoder size.
+ let mut buffer = Vec::with_capacity(256);
+ let mut witness_elements = 0;
+
+ // For each witness element, the decoder expects an element length, followed by
+ // the data itself. The iterator's yielded elements do not include the length prefix,
+ // so we add them.
+ for elem in iter {
+ let encoded = crate::compact_size_encode(elem.as_ref().len());
+ buffer.extend_from_slice(encoded.as_slice());
+ buffer.extend_from_slice(elem.as_ref());
+ witness_elements += 1;
+ }
+
+ let witness_count = crate::compact_size_encode(witness_elements);
+ let _ = decoder.push_bytes(&mut witness_count.as_slice());
+
+ let _ = decoder.push_bytes(&mut buffer.as_slice());
+
+ decoder
+ .end()
+ .expect("witness_elements in decoder is equal to number of provided elements")
}
}
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.