@@ -12,9 +12,6 @@ use std::sync::{Arc, Mutex};
1212/// We include a chain suffix of a certain length for the purpose of robustness.
1313const 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 ) ]
@@ -502,51 +499,57 @@ impl<E: ElectrumApi> BdkElectrumClient<E> {
502499 }
503500 }
504501
505- // Fetch missing proofs in batches
506- for chunk in to_fetch. chunks ( MAX_BATCH_SIZE ) {
507- for & ( txid, height, hash) in chunk {
508- // Fetch the raw proof.
509- let proof = self . inner . transaction_get_merkle ( & txid, height) ?;
502+ // Batch all get_merkle calls.
503+ let mut batch = electrum_client:: Batch :: default ( ) ;
504+ for & ( txid, height, _) in & to_fetch {
505+ batch. raw (
506+ "blockchain.transaction.get_merkle" . into ( ) ,
507+ vec ! [
508+ electrum_client:: Param :: String ( format!( "{:x}" , txid) ) ,
509+ electrum_client:: Param :: Usize ( height) ,
510+ ] ,
511+ ) ;
512+ }
513+ let resps = self . inner . batch_call ( & batch) ?;
510514
511- // Validate against header, retrying once on stale header.
512- let mut header = {
513- let cache = self . block_header_cache . lock ( ) . unwrap ( ) ;
514- cache[ & ( height as u32 ) ]
515- } ;
516- let mut valid = electrum_client:: utils:: validate_merkle_proof (
515+ // Validate each proof, retrying once for each stale header.
516+ for ( ( txid, height, hash) , resp) in to_fetch. into_iter ( ) . zip ( resps. into_iter ( ) ) {
517+ let proof: electrum_client:: GetMerkleRes = serde_json:: from_value ( resp) ?;
518+
519+ let mut header = {
520+ let cache = self . block_header_cache . lock ( ) . unwrap ( ) ;
521+ cache[ & ( height as u32 ) ]
522+ } ;
523+ let mut valid =
524+ electrum_client:: utils:: validate_merkle_proof ( & txid, & header. merkle_root , & proof) ;
525+ if !valid {
526+ let new_header = self . inner . block_header ( height) ?;
527+ self . block_header_cache
528+ . lock ( )
529+ . unwrap ( )
530+ . insert ( height as u32 , new_header) ;
531+ header = new_header;
532+ valid = electrum_client:: utils:: validate_merkle_proof (
517533 & txid,
518534 & header. merkle_root ,
519535 & proof,
520536 ) ;
521- if !valid {
522- let new_header = self . inner . block_header ( height) ?;
523- self . block_header_cache
524- . lock ( )
525- . unwrap ( )
526- . insert ( height as u32 , new_header) ;
527- header = new_header;
528- valid = electrum_client:: utils:: validate_merkle_proof (
529- & txid,
530- & header. merkle_root ,
531- & proof,
532- ) ;
533- }
537+ }
534538
535- // Build and cache the anchor if merkle proof is valid.
536- if valid {
537- let anchor = ConfirmationBlockTime {
538- confirmation_time : header. time as u64 ,
539- block_id : BlockId {
540- height : height as u32 ,
541- hash : header. block_hash ( ) ,
542- } ,
543- } ;
544- self . anchor_cache
545- . lock ( )
546- . unwrap ( )
547- . insert ( ( txid, hash) , anchor) ;
548- results. push ( ( txid, anchor) ) ;
549- }
539+ // Build and cache the anchor if merkle proof is valid.
540+ if valid {
541+ let anchor = ConfirmationBlockTime {
542+ confirmation_time : header. time as u64 ,
543+ block_id : BlockId {
544+ height : height as u32 ,
545+ hash : header. block_hash ( ) ,
546+ } ,
547+ } ;
548+ self . anchor_cache
549+ . lock ( )
550+ . unwrap ( )
551+ . insert ( ( txid, hash) , anchor) ;
552+ results. push ( ( txid, anchor) ) ;
550553 }
551554 }
552555
0 commit comments