Skip to content

Commit 8086e1e

Browse files
committed
feat(electrum): batch transaction.get_merkle calls via batch_call
1 parent f60ebe0 commit 8086e1e

2 files changed

Lines changed: 46 additions & 42 deletions

File tree

crates/electrum/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ workspace = true
1515
[dependencies]
1616
bdk_core = { path = "../core", version = "0.6.0" }
1717
electrum-client = { version = "0.23.1", features = [ "proxy" ], default-features = false }
18+
serde_json = "1.0"
1819

1920
[dev-dependencies]
2021
bdk_testenv = { path = "../testenv" }

crates/electrum/src/bdk_electrum_client.rs

Lines changed: 45 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ use std::sync::{Arc, Mutex};
1212
/// We include a chain suffix of a certain length for the purpose of robustness.
1313
const CHAIN_SUFFIX_LENGTH: u32 = 8;
1414

15-
/// Maximum batch size for proof validation requests
16-
const MAX_BATCH_SIZE: usize = 100;
17-
1815
/// Wrapper around an [`electrum_client::ElectrumApi`] which includes an internal in-memory
1916
/// transaction cache to avoid re-fetching already downloaded transactions.
2017
#[derive(Debug)]
@@ -499,51 +496,57 @@ impl<E: ElectrumApi> BdkElectrumClient<E> {
499496
}
500497
}
501498

502-
// Fetch missing proofs in batches
503-
for chunk in to_fetch.chunks(MAX_BATCH_SIZE) {
504-
for &(txid, height, hash) in chunk {
505-
// Fetch the raw proof.
506-
let proof = self.inner.transaction_get_merkle(&txid, height)?;
499+
// Batch all get_merkle calls.
500+
let mut batch = electrum_client::Batch::default();
501+
for &(txid, height, _) in &to_fetch {
502+
batch.raw(
503+
"blockchain.transaction.get_merkle".into(),
504+
vec![
505+
electrum_client::Param::String(format!("{:x}", txid)),
506+
electrum_client::Param::Usize(height),
507+
],
508+
);
509+
}
510+
let resps = self.inner.batch_call(&batch)?;
507511

508-
// Validate against header, retrying once on stale header.
509-
let mut header = {
510-
let cache = self.block_header_cache.lock().unwrap();
511-
cache[&(height as u32)]
512-
};
513-
let mut valid = electrum_client::utils::validate_merkle_proof(
512+
// Validate each proof, retrying once for each stale header.
513+
for ((txid, height, hash), resp) in to_fetch.into_iter().zip(resps.into_iter()) {
514+
let proof: electrum_client::GetMerkleRes = serde_json::from_value(resp)?;
515+
516+
let mut header = {
517+
let cache = self.block_header_cache.lock().unwrap();
518+
cache[&(height as u32)]
519+
};
520+
let mut valid =
521+
electrum_client::utils::validate_merkle_proof(&txid, &header.merkle_root, &proof);
522+
if !valid {
523+
let new_header = self.inner.block_header(height)?;
524+
self.block_header_cache
525+
.lock()
526+
.unwrap()
527+
.insert(height as u32, new_header);
528+
header = new_header;
529+
valid = electrum_client::utils::validate_merkle_proof(
514530
&txid,
515531
&header.merkle_root,
516532
&proof,
517533
);
518-
if !valid {
519-
let new_header = self.inner.block_header(height)?;
520-
self.block_header_cache
521-
.lock()
522-
.unwrap()
523-
.insert(height as u32, new_header);
524-
header = new_header;
525-
valid = electrum_client::utils::validate_merkle_proof(
526-
&txid,
527-
&header.merkle_root,
528-
&proof,
529-
);
530-
}
534+
}
531535

532-
// Build and cache the anchor if merkle proof is valid.
533-
if valid {
534-
let anchor = ConfirmationBlockTime {
535-
confirmation_time: header.time as u64,
536-
block_id: BlockId {
537-
height: height as u32,
538-
hash,
539-
},
540-
};
541-
self.anchor_cache
542-
.lock()
543-
.unwrap()
544-
.insert((txid, hash), anchor);
545-
results.push((txid, anchor));
546-
}
536+
// Build and cache the anchor if merkle proof is valid.
537+
if valid {
538+
let anchor = ConfirmationBlockTime {
539+
confirmation_time: header.time as u64,
540+
block_id: BlockId {
541+
height: height as u32,
542+
hash,
543+
},
544+
};
545+
self.anchor_cache
546+
.lock()
547+
.unwrap()
548+
.insert((txid, hash), anchor);
549+
results.push((txid, anchor));
547550
}
548551
}
549552

0 commit comments

Comments
 (0)