Skip to content

Commit 156cbab

Browse files
evanlinjinLagginTimes
authored andcommitted
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`.
1 parent 4ea5ea6 commit 156cbab

File tree

1 file changed

+60
-53
lines changed

1 file changed

+60
-53
lines changed

crates/electrum/benches/test_sync.rs

Lines changed: 60 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,44 @@
1-
use bdk_chain::{
2-
bitcoin::{Address, Amount, ScriptBuf},
3-
local_chain::LocalChain,
4-
spk_client::{SyncRequest, SyncResponse},
5-
spk_txout::SpkTxOutIndex,
6-
ConfirmationBlockTime, IndexedTxGraph, Indexer, Merge,
7-
};
8-
use bdk_core::bitcoin::{
9-
key::{Secp256k1, UntweakedPublicKey},
10-
Network,
1+
use bdk_chain::bitcoin::{Address, Amount, ScriptBuf};
2+
use bdk_core::{
3+
bitcoin::{
4+
consensus::WriteExt,
5+
hashes::Hash,
6+
key::{Secp256k1, UntweakedPublicKey},
7+
Network, TapNodeHash,
8+
},
9+
spk_client::SyncRequest,
10+
CheckPoint,
1111
};
1212
use bdk_electrum::BdkElectrumClient;
1313
use bdk_testenv::{anyhow, bitcoincore_rpc::RpcApi, TestEnv};
1414
use criterion::{criterion_group, criterion_main, Criterion};
15-
use std::time::Duration;
15+
use electrum_client::ElectrumApi;
16+
use std::{collections::BTreeSet, time::Duration};
1617

1718
// Batch size for `sync_with_electrum`.
18-
const BATCH_SIZE: usize = 5;
19+
const BATCH_SIZE: usize = 100;
1920

20-
pub fn get_test_spk() -> ScriptBuf {
21+
pub fn get_test_spk(i: usize) -> ScriptBuf {
2122
const PK_BYTES: &[u8] = &[
2223
12, 244, 72, 4, 163, 4, 211, 81, 159, 82, 153, 123, 125, 74, 142, 40, 55, 237, 191, 231,
2324
31, 114, 89, 165, 83, 141, 8, 203, 93, 240, 53, 101,
2425
];
2526
let secp = Secp256k1::new();
2627
let pk = UntweakedPublicKey::from_slice(PK_BYTES).expect("Must be valid PK");
27-
ScriptBuf::new_p2tr(&secp, pk, None)
28+
let mut engine = TapNodeHash::engine();
29+
engine.emit_u64(i as u64).expect("must emit");
30+
ScriptBuf::new_p2tr(&secp, pk, Some(TapNodeHash::from_engine(engine)))
2831
}
2932

30-
fn sync_with_electrum<I, Spks>(
31-
client: &BdkElectrumClient<electrum_client::Client>,
32-
spks: Spks,
33-
chain: &mut LocalChain,
34-
graph: &mut IndexedTxGraph<ConfirmationBlockTime, I>,
35-
) -> anyhow::Result<SyncResponse>
36-
where
37-
I: Indexer,
38-
I::ChangeSet: Default + Merge,
39-
Spks: IntoIterator<Item = ScriptBuf>,
40-
Spks::IntoIter: ExactSizeIterator + Send + 'static,
41-
{
33+
fn sync_with_electrum<E: ElectrumApi>(
34+
client: &BdkElectrumClient<E>,
35+
spks: &[ScriptBuf],
36+
chain_tip: &CheckPoint,
37+
) -> anyhow::Result<()> {
4238
let update = client.sync(
43-
SyncRequest::builder().chain_tip(chain.tip()).spks(spks),
39+
SyncRequest::builder()
40+
.chain_tip(chain_tip.clone())
41+
.spks(spks.iter().cloned()),
4442
BATCH_SIZE,
4543
true,
4644
)?;
@@ -50,20 +48,11 @@ where
5048
"expected some transactions from sync, but got none"
5149
);
5250

53-
if let Some(chain_update) = update.chain_update.clone() {
54-
let _ = chain
55-
.apply_update(chain_update)
56-
.map_err(|err| anyhow::anyhow!("LocalChain update error: {:?}", err))?;
57-
}
58-
let _ = graph.apply_update(update.tx_update.clone());
59-
60-
Ok(update)
51+
Ok(())
6152
}
6253

6354
pub fn test_sync_performance(c: &mut Criterion) {
6455
let env = TestEnv::new().unwrap();
65-
let electrum_client = electrum_client::Client::new(env.electrsd.electrum_url.as_str()).unwrap();
66-
let client = BdkElectrumClient::new(electrum_client);
6756

6857
const NUM_BLOCKS: usize = 100;
6958
let mut spks = Vec::with_capacity(NUM_BLOCKS);
@@ -72,34 +61,52 @@ pub fn test_sync_performance(c: &mut Criterion) {
7261
env.mine_blocks(101, None).unwrap();
7362

7463
// Scatter UTXOs across many blocks.
75-
for _ in 0..NUM_BLOCKS {
76-
let spk = get_test_spk();
64+
for i in 0..NUM_BLOCKS {
65+
let spk = get_test_spk(i);
7766
let addr = Address::from_script(&spk, Network::Regtest).unwrap();
7867
env.send(&addr, Amount::from_sat(10_000)).unwrap();
7968
env.mine_blocks(1, None).unwrap();
8069

8170
spks.push(spk);
8271
}
8372
let _ = env.wait_until_electrum_sees_block(Duration::from_secs(6));
73+
assert_eq!(
74+
spks.iter().cloned().collect::<BTreeSet<_>>().len(),
75+
spks.len(),
76+
"all spks must be unique",
77+
);
8478

8579
// Setup receiver.
86-
let genesis = env.bitcoind.client.get_block_hash(0).unwrap();
87-
let (chain, _) = LocalChain::from_genesis_hash(genesis);
88-
let graph = IndexedTxGraph::<ConfirmationBlockTime, _>::new({
89-
let mut idx = SpkTxOutIndex::default();
90-
idx.insert_spk((), spks[0].clone());
91-
idx
80+
let genesis_cp = CheckPoint::new(bdk_core::BlockId {
81+
height: 0,
82+
hash: env.bitcoind.client.get_block_hash(0).unwrap(),
9283
});
9384

94-
c.bench_function("sync_with_electrum", move |b| {
95-
b.iter(|| {
96-
let spks = spks.clone();
97-
let mut recv_chain = chain.clone();
98-
let mut recv_graph = graph.clone();
85+
{
86+
let electrum_client =
87+
electrum_client::Client::new(env.electrsd.electrum_url.as_str()).unwrap();
88+
let spks = spks.clone();
89+
let genesis_cp = genesis_cp.clone();
90+
c.bench_function("sync_with_electrum", move |b| {
91+
b.iter(|| {
92+
sync_with_electrum(
93+
&BdkElectrumClient::new(&electrum_client),
94+
&spks,
95+
&genesis_cp,
96+
)
97+
.expect("must not error")
98+
})
99+
});
100+
}
99101

100-
let _ = sync_with_electrum(&client, spks, &mut recv_chain, &mut recv_graph);
101-
})
102-
});
102+
{
103+
let client = BdkElectrumClient::new(
104+
electrum_client::Client::new(env.electrsd.electrum_url.as_str()).unwrap(),
105+
);
106+
c.bench_function("sync_with_electrum_cached", move |b| {
107+
b.iter(|| sync_with_electrum(&client, &spks, &genesis_cp).expect("must not error"))
108+
});
109+
}
103110
}
104111

105112
criterion_group! {

0 commit comments

Comments
 (0)