@@ -501,17 +501,16 @@ impl<E: ElectrumApi> BdkElectrumClient<E> {
501
501
if let Some ( anchor) = anchor_cache. get ( & ( txid, hash) ) {
502
502
results. push ( ( txid, * anchor) ) ;
503
503
} else {
504
- to_fetch. push ( ( txid, height, hash ) ) ;
504
+ to_fetch. push ( ( txid, height) ) ;
505
505
}
506
506
}
507
507
}
508
508
509
509
// Fetch merkle proofs.
510
- let txids_and_heights = to_fetch. iter ( ) . map ( |& ( txid, height, _) | ( txid, height) ) ;
511
- let proofs = self . inner . batch_transaction_get_merkle ( txids_and_heights) ?;
510
+ let proofs = self . inner . batch_transaction_get_merkle ( to_fetch. iter ( ) ) ?;
512
511
513
512
// Validate each proof, retrying once for each stale header.
514
- for ( ( txid, height, hash ) , proof) in to_fetch. into_iter ( ) . zip ( proofs. into_iter ( ) ) {
513
+ for ( ( txid, height) , proof) in to_fetch. into_iter ( ) . zip ( proofs. into_iter ( ) ) {
515
514
let mut header = {
516
515
let cache = self . block_header_cache . lock ( ) . unwrap ( ) ;
517
516
cache
@@ -536,6 +535,7 @@ impl<E: ElectrumApi> BdkElectrumClient<E> {
536
535
537
536
// Build and cache the anchor if merkle proof is valid.
538
537
if valid {
538
+ let hash = header. block_hash ( ) ;
539
539
let anchor = ConfirmationBlockTime {
540
540
confirmation_time : header. time as u64 ,
541
541
block_id : BlockId {
@@ -679,11 +679,13 @@ fn chain_update(
679
679
#[ cfg( test) ]
680
680
#[ cfg_attr( coverage_nightly, coverage( off) ) ]
681
681
mod test {
682
- use crate :: { bdk_electrum_client:: TxUpdate , BdkElectrumClient } ;
682
+ use crate :: { bdk_electrum_client:: TxUpdate , electrum_client:: ElectrumApi , BdkElectrumClient } ;
683
+ use bdk_chain:: bitcoin:: Amount ;
683
684
use bdk_chain:: bitcoin:: { constants, Network , OutPoint , ScriptBuf , Transaction , TxIn } ;
684
685
use bdk_chain:: { BlockId , CheckPoint } ;
685
686
use bdk_core:: { collections:: BTreeMap , spk_client:: SyncRequest } ;
686
- use bdk_testenv:: { anyhow, utils:: new_tx, TestEnv } ;
687
+ use bdk_testenv:: { anyhow, bitcoincore_rpc:: RpcApi , utils:: new_tx, TestEnv } ;
688
+ use core:: time:: Duration ;
687
689
use electrum_client:: Error as ElectrumError ;
688
690
use std:: sync:: Arc ;
689
691
@@ -747,4 +749,59 @@ mod test {
747
749
748
750
Ok ( ( ) )
749
751
}
752
+
753
+ #[ cfg( feature = "default" ) ]
754
+ #[ test]
755
+ fn test_batch_fetch_anchors_reorg_uses_new_hash ( ) -> anyhow:: Result < ( ) > {
756
+ let env = TestEnv :: new ( ) ?;
757
+ let client = electrum_client:: Client :: new ( env. electrsd . electrum_url . as_str ( ) ) . unwrap ( ) ;
758
+ let electrum_client = BdkElectrumClient :: new ( client) ;
759
+
760
+ env. mine_blocks ( 101 , None ) ?;
761
+ env. wait_until_electrum_sees_block ( Duration :: from_secs ( 6 ) ) ?;
762
+
763
+ let addr = env
764
+ . rpc_client ( )
765
+ . get_new_address ( None , None ) ?
766
+ . assume_checked ( ) ;
767
+ let txid = env. send ( & addr, Amount :: from_sat ( 50_000 ) ) ?;
768
+ env. wait_until_electrum_sees_txid ( txid, Duration :: from_secs ( 6 ) ) ?;
769
+
770
+ // Mine block that confirms transaction.
771
+ env. mine_blocks ( 1 , None ) ?;
772
+ env. wait_until_electrum_sees_block ( Duration :: from_secs ( 6 ) ) ?;
773
+ let height: u32 = env. rpc_client ( ) . get_block_count ( ) ? as u32 ;
774
+
775
+ // Populate header cache.
776
+ let header = electrum_client. inner . block_header ( height as usize ) ?;
777
+ {
778
+ electrum_client
779
+ . block_header_cache
780
+ . lock ( )
781
+ . unwrap ( )
782
+ . insert ( height, header) ;
783
+ }
784
+
785
+ // Reorg to create a new header and hash.
786
+ env. reorg ( 1 ) ?;
787
+ env. wait_until_electrum_sees_block ( Duration :: from_secs ( 6 ) ) ?;
788
+
789
+ // Calling `batch_fetch_anchors` should fetch new header.
790
+ let anchors = electrum_client. batch_fetch_anchors ( & [ ( txid, height as usize ) ] ) ?;
791
+ assert_eq ! ( anchors. len( ) , 1 ) ;
792
+
793
+ let new_header = electrum_client. inner . block_header ( height as usize ) ?;
794
+ let new_hash = new_header. block_hash ( ) ;
795
+
796
+ // Anchor should contain new hash.
797
+ let ( _, anchor) = anchors[ 0 ] ;
798
+ assert_eq ! ( anchor. block_id. height, height) ;
799
+ assert_eq ! ( anchor. block_id. hash, new_hash) ;
800
+
801
+ // Anchor cache should also contain new hash.
802
+ let cache = electrum_client. anchor_cache . lock ( ) . unwrap ( ) ;
803
+ assert ! ( cache. get( & ( txid, new_hash) ) . is_some( ) ) ;
804
+
805
+ Ok ( ( ) )
806
+ }
750
807
}
0 commit comments