Skip to content

Commit d121446

Browse files
committed
redo canonical benchmarks using TxTemplate
- use TxTemplate to setup test scenarios - add generated files to gitignore [Ticket: X]
1 parent afe0f79 commit d121446

File tree

2 files changed

+266
-4
lines changed

2 files changed

+266
-4
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ Cargo.lock
88
# Example persisted files.
99
*.db
1010
*.sqlite*
11+
12+
# Canonical benchmark generated files
13+
crates/chain/target

crates/chain/benches/canonicalization.rs

Lines changed: 263 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use bdk_chain::{keychain_txout::KeychainTxOutIndex, local_chain::LocalChain, IndexedTxGraph};
22
use bdk_core::{BlockId, CheckPoint};
33
use bdk_core::{ConfirmationBlockTime, TxUpdate};
4-
use bdk_testenv::hash;
4+
use bdk_testenv::tx_template::{init_graph, TxInTemplate, TxOutTemplate, TxTemplate};
5+
use bdk_testenv::utils::DESCRIPTORS;
6+
use bdk_testenv::{block_id, hash, local_chain};
57
use bitcoin::{
68
absolute, constants, hashes::Hash, key::Secp256k1, transaction, Amount, BlockHash, Network,
79
OutPoint, ScriptBuf, Transaction, TxIn, TxOut,
@@ -241,10 +243,267 @@ pub fn nested_conflicts(c: &mut Criterion) {
241243
});
242244
}
243245

246+
// start of using TxTemplate
247+
fn initialize_graph_and_keychain() -> (KeychainTxGraph, LocalChain) {
248+
let chain = local_chain![(0, hash!("genesis")), (100, hash!("abcd"))];
249+
250+
let mut keychain_index = KeychainTxOutIndex::new(10);
251+
let (desc, _) = Descriptor::parse_descriptor(&Secp256k1::new(), DESCRIPTORS[2]).unwrap();
252+
keychain_index.insert_descriptor((), desc).unwrap();
253+
254+
let new_graph = KeychainTxGraph::new(keychain_index);
255+
(new_graph, chain)
256+
}
257+
258+
fn setup_many_conflicting_unconfirmed(tx_count: u32) -> (KeychainTxGraph, LocalChain) {
259+
let (mut tx_graph, chain) = initialize_graph_and_keychain();
260+
let mut templates = Vec::new();
261+
262+
templates.push(TxTemplate {
263+
tx_name: "ancestor_tx".into(),
264+
inputs: vec![TxInTemplate::Bogus],
265+
outputs: vec![TxOutTemplate::new(Amount::ONE_BTC.to_sat(), Some(0))],
266+
anchors: vec![block_id!(100, "abcd")],
267+
last_seen: None,
268+
});
269+
270+
for i in 1..=tx_count {
271+
templates.push(TxTemplate {
272+
tx_name: format!("conflict_tx_{}", i).into(),
273+
inputs: vec![TxInTemplate::PrevTx("ancestor_tx".into(), 0)],
274+
outputs: vec![TxOutTemplate::new(
275+
Amount::ONE_BTC.to_sat() - (i as u64 * 10),
276+
Some(1),
277+
)],
278+
anchors: vec![],
279+
last_seen: Some(i as u64),
280+
});
281+
}
282+
283+
let (graph, _, _) = init_graph(templates);
284+
let _ = tx_graph.batch_insert_unconfirmed(graph.full_txs().map(|tx_node| {
285+
(
286+
tx_node.tx,
287+
tx_node.last_seen_unconfirmed.unwrap_or_default(),
288+
)
289+
}));
290+
291+
(tx_graph, chain)
292+
}
293+
294+
/// Utility function to create a benchmark-ready graph with a chain of unconfirmed transactions
295+
fn setup_many_chained_unconfirmed(tx_chain_count: u32) -> (KeychainTxGraph, LocalChain) {
296+
let mut templates = Vec::new();
297+
let (mut tx_graph, chain) = initialize_graph_and_keychain();
298+
299+
templates.push(TxTemplate {
300+
tx_name: "ancestor_tx".into(),
301+
inputs: vec![TxInTemplate::Bogus],
302+
outputs: vec![TxOutTemplate::new(Amount::ONE_BTC.to_sat(), Some(0))],
303+
anchors: vec![block_id!(100, "abcd")],
304+
last_seen: None,
305+
});
306+
307+
for i in 0..tx_chain_count {
308+
templates.push(TxTemplate {
309+
tx_name: format!("chain_tx_{}", i).into(),
310+
inputs: if i == 0 {
311+
vec![TxInTemplate::PrevTx("ancestor_tx".into(), 0)]
312+
} else {
313+
vec![TxInTemplate::PrevTx(
314+
format!("chain_tx_{}", i - 1).into(),
315+
0,
316+
)]
317+
},
318+
outputs: vec![TxOutTemplate::new(Amount::ONE_BTC.to_sat(), Some(1))],
319+
anchors: vec![],
320+
last_seen: Some(i as u64),
321+
});
322+
}
323+
324+
let (graph, _, _) = init_graph(templates);
325+
let _ = tx_graph.batch_insert_unconfirmed(graph.full_txs().map(|tx_node| {
326+
(
327+
tx_node.tx,
328+
tx_node.last_seen_unconfirmed.unwrap_or_default(),
329+
)
330+
}));
331+
332+
(tx_graph, chain)
333+
}
334+
335+
/// Utility function to create a benchmark-ready graph with nested conflicting transactions
336+
fn setup_nested_conflicts(
337+
graph_depth: usize,
338+
conflicts_per_output: usize,
339+
) -> (KeychainTxGraph, LocalChain) {
340+
let mut templates = Vec::new();
341+
let (mut tx_graph, chain) = initialize_graph_and_keychain();
342+
343+
templates.push(TxTemplate {
344+
tx_name: "ancestor_tx".into(),
345+
inputs: vec![TxInTemplate::Bogus],
346+
outputs: vec![TxOutTemplate::new(Amount::ONE_BTC.to_sat(), Some(0))],
347+
anchors: vec![block_id!(100, "abcd")],
348+
last_seen: None,
349+
});
350+
351+
let mut previous_outputs = vec!["ancestor_tx".to_string()];
352+
353+
for depth in 1..graph_depth {
354+
let mut next_outputs = Vec::new();
355+
for previous_output_name in previous_outputs.drain(..) {
356+
for conflict_i in 1..=conflicts_per_output {
357+
let tx_name = format!("depth_{}_conflict_{}", depth, conflict_i);
358+
let mut last_seen = depth * conflict_i;
359+
if last_seen % 2 == 0 {
360+
last_seen /= 2;
361+
}
362+
363+
templates.push(TxTemplate {
364+
tx_name: tx_name.clone().into(),
365+
inputs: vec![TxInTemplate::PrevTx(previous_output_name.clone().into(), 0)],
366+
outputs: vec![TxOutTemplate::new(
367+
Amount::ONE_BTC.to_sat() - (depth as u64 * 200 - conflict_i as u64),
368+
Some((depth + conflict_i) as u32),
369+
)],
370+
anchors: vec![],
371+
last_seen: Some(last_seen as u64),
372+
});
373+
374+
next_outputs.push(tx_name);
375+
}
376+
}
377+
previous_outputs = next_outputs;
378+
}
379+
380+
let (graph, _, _) = init_graph(templates);
381+
let _ = tx_graph.batch_insert_unconfirmed(graph.full_txs().map(|tx_node| {
382+
(
383+
tx_node.tx,
384+
tx_node.last_seen_unconfirmed.unwrap_or_default(),
385+
)
386+
}));
387+
388+
(tx_graph, chain)
389+
}
390+
391+
/// Benchmark scenario for many conflicting unconfirmed transactions
392+
fn bench_many_conflicting_unconfirmed(c: &mut Criterion) {
393+
const CONFLICTING_TX_COUNT: u32 = 2100;
394+
395+
let (tx_graph, chain) = setup_many_conflicting_unconfirmed(CONFLICTING_TX_COUNT);
396+
397+
c.bench_function("many_conflicting_unconfirmed::list_canonical_txs", {
398+
let tx_graph = tx_graph.clone();
399+
let chain = chain.clone();
400+
move |b| {
401+
b.iter(|| run_list_canonical_txs(&tx_graph, &chain, 2));
402+
}
403+
});
404+
405+
c.bench_function("many_conflicting_unconfirmed::filter_chain_txouts", {
406+
let tx_graph = tx_graph.clone();
407+
let chain = chain.clone();
408+
move |b| {
409+
b.iter(|| run_filter_chain_txouts(&tx_graph, &chain, 2));
410+
}
411+
});
412+
413+
c.bench_function(
414+
"many_conflicting_unconfirmed::filter_chain_unspents",
415+
move |b| {
416+
let tx_graph = tx_graph.clone();
417+
b.iter(|| {
418+
run_filter_chain_unspents(&tx_graph, &chain, 1);
419+
});
420+
},
421+
);
422+
}
423+
424+
/// Benchmark scenario for many chained unconfirmed transactions
425+
pub fn bench_many_chained_unconfirmed(c: &mut Criterion) {
426+
const TX_CHAIN_COUNT: u32 = 2100;
427+
428+
let (tx_graph, chain) = setup_many_chained_unconfirmed(TX_CHAIN_COUNT);
429+
430+
c.bench_function("many_chained_unconfirmed::list_canonical_txs", {
431+
let tx_graph = tx_graph.clone();
432+
let chain = chain.clone();
433+
move |b| {
434+
b.iter(|| {
435+
run_list_canonical_txs(&tx_graph, &chain, (TX_CHAIN_COUNT + 1).try_into().unwrap());
436+
});
437+
}
438+
});
439+
440+
c.bench_function("many_chained_unconfirmed::filter_chain_txouts", {
441+
let tx_graph = tx_graph.clone();
442+
let chain = chain.clone();
443+
move |b| {
444+
b.iter(|| {
445+
run_filter_chain_txouts(&tx_graph, &chain, 1);
446+
});
447+
}
448+
});
449+
450+
c.bench_function("many_chained_unconfirmed::filter_chain_unspents", {
451+
let tx_graph = tx_graph.clone();
452+
let chain = chain.clone();
453+
move |b| {
454+
b.iter(|| {
455+
run_filter_chain_unspents(&tx_graph, &chain, 0);
456+
});
457+
}
458+
});
459+
}
460+
461+
/// Benchmark scenario for nested conflicts
462+
pub fn bench_nested_conflicts(c: &mut Criterion) {
463+
const CONFLICTS_PER_OUTPUT: usize = 3;
464+
const GRAPH_DEPTH: usize = 7;
465+
466+
let (tx_graph, chain) = setup_nested_conflicts(GRAPH_DEPTH, CONFLICTS_PER_OUTPUT);
467+
468+
c.bench_function("nested_conflicts_unconfirmed::list_canonical_txs", {
469+
let tx_graph = tx_graph.clone();
470+
let chain = chain.clone();
471+
move |b| {
472+
b.iter(|| {
473+
run_list_canonical_txs(&tx_graph, &chain, GRAPH_DEPTH);
474+
});
475+
}
476+
});
477+
478+
c.bench_function("nested_conflicts_unconfirmed::filter_chain_txouts", {
479+
let tx_graph = tx_graph.clone();
480+
let chain = chain.clone();
481+
move |b| {
482+
b.iter(|| {
483+
run_filter_chain_txouts(&tx_graph, &chain, GRAPH_DEPTH);
484+
});
485+
}
486+
});
487+
488+
c.bench_function("nested_conflicts_unconfirmed::filter_chain_unspents", {
489+
let tx_graph = tx_graph.clone();
490+
let chain = chain.clone();
491+
move |b| {
492+
b.iter(|| {
493+
run_filter_chain_unspents(&tx_graph, &chain, 1);
494+
});
495+
}
496+
});
497+
}
498+
// end of using TxTemplate
499+
244500
criterion_group!(
245501
benches,
246-
many_conflicting_unconfirmed,
247-
many_chained_unconfirmed,
248-
nested_conflicts,
502+
// many_conflicting_unconfirmed,
503+
// many_chained_unconfirmed,
504+
// nested_conflicts,
505+
bench_many_conflicting_unconfirmed,
506+
bench_many_chained_unconfirmed,
507+
bench_nested_conflicts,
249508
);
250509
criterion_main!(benches);

0 commit comments

Comments
 (0)