From 156cbab67f4ff91276f9f03749944f4c46210f7f Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E5=BF=97=E5=AE=87?= Date: Wed, 25 Jun 2025 23:34:50 +0000 Subject: [PATCH] test(electrum): Improve benchmark * Actually use different spks * Do not benchmark applying updates (only fetching/contructing) * Have two benches: One with cache, one without. * Remove `black_box`. --- crates/electrum/benches/test_sync.rs | 113 ++++++++++++++------------- 1 file changed, 60 insertions(+), 53 deletions(-) diff --git a/crates/electrum/benches/test_sync.rs b/crates/electrum/benches/test_sync.rs index 8a0191f2..063fdd62 100644 --- a/crates/electrum/benches/test_sync.rs +++ b/crates/electrum/benches/test_sync.rs @@ -1,46 +1,44 @@ -use bdk_chain::{ - bitcoin::{Address, Amount, ScriptBuf}, - local_chain::LocalChain, - spk_client::{SyncRequest, SyncResponse}, - spk_txout::SpkTxOutIndex, - ConfirmationBlockTime, IndexedTxGraph, Indexer, Merge, -}; -use bdk_core::bitcoin::{ - key::{Secp256k1, UntweakedPublicKey}, - Network, +use bdk_chain::bitcoin::{Address, Amount, ScriptBuf}; +use bdk_core::{ + bitcoin::{ + consensus::WriteExt, + hashes::Hash, + key::{Secp256k1, UntweakedPublicKey}, + Network, TapNodeHash, + }, + spk_client::SyncRequest, + CheckPoint, }; use bdk_electrum::BdkElectrumClient; use bdk_testenv::{anyhow, bitcoincore_rpc::RpcApi, TestEnv}; use criterion::{criterion_group, criterion_main, Criterion}; -use std::time::Duration; +use electrum_client::ElectrumApi; +use std::{collections::BTreeSet, time::Duration}; // Batch size for `sync_with_electrum`. -const BATCH_SIZE: usize = 5; +const BATCH_SIZE: usize = 100; -pub fn get_test_spk() -> ScriptBuf { +pub fn get_test_spk(i: usize) -> ScriptBuf { const PK_BYTES: &[u8] = &[ 12, 244, 72, 4, 163, 4, 211, 81, 159, 82, 153, 123, 125, 74, 142, 40, 55, 237, 191, 231, 31, 114, 89, 165, 83, 141, 8, 203, 93, 240, 53, 101, ]; let secp = Secp256k1::new(); let pk = UntweakedPublicKey::from_slice(PK_BYTES).expect("Must be valid PK"); - ScriptBuf::new_p2tr(&secp, pk, None) + let mut engine = TapNodeHash::engine(); + engine.emit_u64(i as u64).expect("must emit"); + ScriptBuf::new_p2tr(&secp, pk, Some(TapNodeHash::from_engine(engine))) } -fn sync_with_electrum( - client: &BdkElectrumClient, - spks: Spks, - chain: &mut LocalChain, - graph: &mut IndexedTxGraph, -) -> anyhow::Result -where - I: Indexer, - I::ChangeSet: Default + Merge, - Spks: IntoIterator, - Spks::IntoIter: ExactSizeIterator + Send + 'static, -{ +fn sync_with_electrum( + client: &BdkElectrumClient, + spks: &[ScriptBuf], + chain_tip: &CheckPoint, +) -> anyhow::Result<()> { let update = client.sync( - SyncRequest::builder().chain_tip(chain.tip()).spks(spks), + SyncRequest::builder() + .chain_tip(chain_tip.clone()) + .spks(spks.iter().cloned()), BATCH_SIZE, true, )?; @@ -50,20 +48,11 @@ where "expected some transactions from sync, but got none" ); - if let Some(chain_update) = update.chain_update.clone() { - let _ = chain - .apply_update(chain_update) - .map_err(|err| anyhow::anyhow!("LocalChain update error: {:?}", err))?; - } - let _ = graph.apply_update(update.tx_update.clone()); - - Ok(update) + Ok(()) } pub fn test_sync_performance(c: &mut Criterion) { let env = TestEnv::new().unwrap(); - let electrum_client = electrum_client::Client::new(env.electrsd.electrum_url.as_str()).unwrap(); - let client = BdkElectrumClient::new(electrum_client); const NUM_BLOCKS: usize = 100; let mut spks = Vec::with_capacity(NUM_BLOCKS); @@ -72,8 +61,8 @@ pub fn test_sync_performance(c: &mut Criterion) { env.mine_blocks(101, None).unwrap(); // Scatter UTXOs across many blocks. - for _ in 0..NUM_BLOCKS { - let spk = get_test_spk(); + for i in 0..NUM_BLOCKS { + let spk = get_test_spk(i); let addr = Address::from_script(&spk, Network::Regtest).unwrap(); env.send(&addr, Amount::from_sat(10_000)).unwrap(); env.mine_blocks(1, None).unwrap(); @@ -81,25 +70,43 @@ pub fn test_sync_performance(c: &mut Criterion) { spks.push(spk); } let _ = env.wait_until_electrum_sees_block(Duration::from_secs(6)); + assert_eq!( + spks.iter().cloned().collect::>().len(), + spks.len(), + "all spks must be unique", + ); // Setup receiver. - let genesis = env.bitcoind.client.get_block_hash(0).unwrap(); - let (chain, _) = LocalChain::from_genesis_hash(genesis); - let graph = IndexedTxGraph::::new({ - let mut idx = SpkTxOutIndex::default(); - idx.insert_spk((), spks[0].clone()); - idx + let genesis_cp = CheckPoint::new(bdk_core::BlockId { + height: 0, + hash: env.bitcoind.client.get_block_hash(0).unwrap(), }); - c.bench_function("sync_with_electrum", move |b| { - b.iter(|| { - let spks = spks.clone(); - let mut recv_chain = chain.clone(); - let mut recv_graph = graph.clone(); + { + let electrum_client = + electrum_client::Client::new(env.electrsd.electrum_url.as_str()).unwrap(); + let spks = spks.clone(); + let genesis_cp = genesis_cp.clone(); + c.bench_function("sync_with_electrum", move |b| { + b.iter(|| { + sync_with_electrum( + &BdkElectrumClient::new(&electrum_client), + &spks, + &genesis_cp, + ) + .expect("must not error") + }) + }); + } - let _ = sync_with_electrum(&client, spks, &mut recv_chain, &mut recv_graph); - }) - }); + { + let client = BdkElectrumClient::new( + electrum_client::Client::new(env.electrsd.electrum_url.as_str()).unwrap(), + ); + c.bench_function("sync_with_electrum_cached", move |b| { + b.iter(|| sync_with_electrum(&client, &spks, &genesis_cp).expect("must not error")) + }); + } } criterion_group! { -- 2.49.0