benches: Add witness decode benchmarks
What changed, and why it matters
This commit only adds new performance benchmarks for decoding Bitcoin transaction witness data. It does not change any production code, fix any bug, or alter program behavior. There is no security relevance.
No action required; this is a benign benchmark-only change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff adds benchmark cases to benches/bitcoin/witness.rs exercising Witness decoding via decode_from_slice and the streaming WitnessDecoder::push_bytes API. It introduces helper decode_chunked and imports encoding::decode_from_slice and WitnessDecoder. No library or application code is modified.
Changed components
benches/bitcoin/witness.rsInspect captured patch +39 / −1
diff --git a/benches/bitcoin/witness.rs b/benches/bitcoin/witness.rs
index 22adf16f..85a15f54 100644
--- a/benches/bitcoin/witness.rs
+++ b/benches/bitcoin/witness.rs
@@ -2,8 +2,10 @@
use std::hint::black_box;
-use bitcoin::blockdata::witness::Witness;
+use bitcoin::blockdata::witness::{Witness, WitnessDecoder};
+use bitcoin::consensus::encode;
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
+use encoding::{decode_from_slice, Decoder as _};
fn bench_witness(c: &mut Criterion) {
let mut g = c.benchmark_group("witness");
@@ -24,8 +26,44 @@ fn bench_witness(c: &mut Criterion) {
});
});
+ // Many small elements (100 and 1000).
+ for count in [100, 1000] {
+ let witness = Witness::from_slice(&vec![vec![0u8; 4]; count]);
+ let bytes = encode::serialize(&witness);
+ g.bench_with_input(BenchmarkId::new("many_elements", count), &bytes, |b, bytes| {
+ b.iter(|| black_box(decode_from_slice::<Witness>(bytes).unwrap()));
+ });
+ }
+
+ // Single element of different sizes.
+ for size in [64, 256, 1024, 2048, 4096] {
+ let witness = Witness::from_slice(&[vec![0u8; size]]);
+ let bytes = encode::serialize(&witness);
+ g.bench_with_input(BenchmarkId::new("one_element", size), &bytes, |b, bytes| {
+ b.iter(|| black_box(decode_from_slice::<Witness>(bytes).unwrap()));
+ });
+ }
+
+ // 64 KB element fed in different chunk sizes.
+ let witness = Witness::from_slice(&[vec![0u8; 65536]]);
+ let bytes = encode::serialize(&witness);
+ for chunk in [1, 64, 256, 1024, 4096] {
+ g.bench_with_input(BenchmarkId::new("chunk_64kb", chunk), &bytes, |b, bytes| {
+ b.iter(|| black_box(decode_chunked(bytes, chunk)));
+ });
+ }
+
g.finish();
}
+fn decode_chunked(bytes: &[u8], chunk: usize) -> Witness {
+ let mut decoder = WitnessDecoder::new();
+ for piece in bytes.chunks(chunk) {
+ let mut slice = piece;
+ decoder.push_bytes(&mut slice).unwrap();
+ }
+ decoder.end().unwrap()
+}
+
criterion_group!(benches, bench_witness);
criterion_main!(benches);
Why this scored 15/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.