|
| 1 | +use bdk_chain::{ |
| 2 | + keychain_txout::{InsertDescriptorError, KeychainTxOutIndex}, |
| 3 | + local_chain::LocalChain, |
| 4 | + CanonicalizationParams, IndexedTxGraph, |
| 5 | +}; |
| 6 | +use bdk_core::{BlockId, CheckPoint, ConfirmationBlockTime, TxUpdate}; |
| 7 | +use bitcoin::{ |
| 8 | + absolute, constants, hashes::Hash, key::Secp256k1, transaction, Amount, BlockHash, Network, |
| 9 | + Transaction, TxIn, TxOut, |
| 10 | +}; |
| 11 | +use criterion::{black_box, criterion_group, criterion_main, Criterion}; |
| 12 | +use miniscript::Descriptor; |
| 13 | +use std::sync::Arc; |
| 14 | + |
| 15 | +type Keychain = (); |
| 16 | +type KeychainTxGraph = IndexedTxGraph<ConfirmationBlockTime, KeychainTxOutIndex<Keychain>>; |
| 17 | + |
| 18 | +const DESC: &str = "tr([ab28dc00/86h/1h/0h]tpubDCdDtzAMZZrkwKBxwNcGCqe4FRydeD9rfMisoi7qLdraG79YohRfPW4YgdKQhpgASdvh612xXNY5xYzoqnyCgPbkpK4LSVcH5Xv4cK7johH/0/*)"; |
| 19 | +const LOOKAHEAD: u32 = 10; |
| 20 | +const LAST_REVEALED: u32 = 500; |
| 21 | +const TX_CT: u32 = 21; |
| 22 | +const USE_SPK_CACHE: bool = true; |
| 23 | +const AMOUNT: Amount = Amount::from_sat(1_000); |
| 24 | + |
| 25 | +fn new_tx(lt: u32) -> Transaction { |
| 26 | + Transaction { |
| 27 | + version: transaction::Version::TWO, |
| 28 | + lock_time: absolute::LockTime::from_consensus(lt), |
| 29 | + input: vec![], |
| 30 | + output: vec![TxOut::NULL], |
| 31 | + } |
| 32 | +} |
| 33 | + |
| 34 | +fn genesis_block_id() -> BlockId { |
| 35 | + BlockId { |
| 36 | + height: 0, |
| 37 | + hash: constants::genesis_block(Network::Regtest).block_hash(), |
| 38 | + } |
| 39 | +} |
| 40 | + |
| 41 | +fn tip_block_id() -> BlockId { |
| 42 | + BlockId { |
| 43 | + height: 100, |
| 44 | + hash: BlockHash::all_zeros(), |
| 45 | + } |
| 46 | +} |
| 47 | + |
| 48 | +fn setup<F: Fn(&mut KeychainTxGraph, &LocalChain)>(f: F) -> (KeychainTxGraph, LocalChain) { |
| 49 | + let desc = Descriptor::parse_descriptor(&Secp256k1::new(), DESC) |
| 50 | + .unwrap() |
| 51 | + .0; |
| 52 | + |
| 53 | + let cp = CheckPoint::from_block_ids([genesis_block_id(), tip_block_id()]).unwrap(); |
| 54 | + let chain = LocalChain::from_tip(cp).unwrap(); |
| 55 | + |
| 56 | + let mut index = KeychainTxOutIndex::new(LOOKAHEAD, USE_SPK_CACHE); |
| 57 | + index.insert_descriptor((), desc).unwrap(); |
| 58 | + let mut tx_graph = KeychainTxGraph::new(index); |
| 59 | + |
| 60 | + f(&mut tx_graph, &chain); |
| 61 | + |
| 62 | + (tx_graph, chain) |
| 63 | +} |
| 64 | + |
| 65 | +/// Bench performance of recovering `KeychainTxOutIndex` from changeset. |
| 66 | +fn do_bench(indexed_tx_graph: &KeychainTxGraph, chain: &LocalChain) { |
| 67 | + let desc = indexed_tx_graph.index.get_descriptor(()).unwrap(); |
| 68 | + let changeset = indexed_tx_graph.initial_changeset(); |
| 69 | + |
| 70 | + // Now recover |
| 71 | + let (graph, _cs) = |
| 72 | + KeychainTxGraph::from_changeset(changeset, |cs| -> Result<_, InsertDescriptorError<_>> { |
| 73 | + let mut index = KeychainTxOutIndex::from_changeset(LOOKAHEAD, USE_SPK_CACHE, cs); |
| 74 | + let _ = index.insert_descriptor((), desc.clone())?; |
| 75 | + Ok(index) |
| 76 | + }) |
| 77 | + .unwrap(); |
| 78 | + |
| 79 | + // Check balance |
| 80 | + let chain_tip = chain.tip().block_id(); |
| 81 | + let op = graph.index.outpoints().clone(); |
| 82 | + let bal = graph.graph().balance( |
| 83 | + chain, |
| 84 | + chain_tip, |
| 85 | + CanonicalizationParams::default(), |
| 86 | + op, |
| 87 | + |_, _| false, |
| 88 | + ); |
| 89 | + assert_eq!(bal.total(), AMOUNT * TX_CT as u64); |
| 90 | +} |
| 91 | + |
| 92 | +pub fn reindex_tx_graph(c: &mut Criterion) { |
| 93 | + let (graph, chain) = black_box(setup(|graph, _chain| { |
| 94 | + // Add relevant txs to graph |
| 95 | + for i in 0..TX_CT { |
| 96 | + let script_pubkey = graph.index.reveal_next_spk(()).unwrap().0 .1; |
| 97 | + let tx = Transaction { |
| 98 | + input: vec![TxIn::default()], |
| 99 | + output: vec![TxOut { |
| 100 | + script_pubkey, |
| 101 | + value: AMOUNT, |
| 102 | + }], |
| 103 | + ..new_tx(i) |
| 104 | + }; |
| 105 | + let txid = tx.compute_txid(); |
| 106 | + let mut update = TxUpdate::default(); |
| 107 | + update.seen_ats = [(txid, i as u64)].into(); |
| 108 | + update.txs = vec![Arc::new(tx)]; |
| 109 | + let _ = graph.apply_update(update); |
| 110 | + } |
| 111 | + // Reveal some SPKs |
| 112 | + let _ = graph.index.reveal_to_target((), LAST_REVEALED); |
| 113 | + })); |
| 114 | + |
| 115 | + c.bench_function("reindex_tx_graph", { |
| 116 | + move |b| b.iter(|| do_bench(&graph, &chain)) |
| 117 | + }); |
| 118 | +} |
| 119 | + |
| 120 | +criterion_group!(benches, reindex_tx_graph); |
| 121 | +criterion_main!(benches); |
0 commit comments