@@ -44,6 +44,8 @@ pub struct RpcBlockchain {
4444 wallet_name : String ,
4545 /// This is a fixed Address used as a key to store information on the node
4646 satoshi_address : Address ,
47+ /// Skip this many blocks of the blockchain at the first rescan, if None the rescan is done from the genesis block
48+ skip_blocks : Option < u32 > ,
4749}
4850
4951/// RpcBlockchain configuration options
@@ -57,15 +59,19 @@ pub struct RpcConfig {
5759 pub network : Network ,
5860 /// The wallet name in the bitcoin node, consider using [wallet_name_from_descriptor] for this
5961 pub wallet_name : String ,
62+ /// Skip this many blocks of the blockchain at the first rescan, if None the rescan is done from the genesis block
63+ pub skip_blocks : Option < u32 > ,
6064}
6165
6266impl RpcBlockchain {
6367 fn get_node_synced_height ( & self ) -> Result < u32 , Error > {
6468 let info = self . client . get_address_info ( & self . satoshi_address ) ?;
6569 if let Some ( GetAddressInfoResultLabel :: Simple ( label) ) = info. labels . first ( ) {
66- Ok ( label. parse :: < u32 > ( ) . unwrap_or ( 0 ) )
70+ Ok ( label
71+ . parse :: < u32 > ( )
72+ . unwrap_or ( self . skip_blocks . unwrap_or ( 0 ) ) )
6773 } else {
68- Ok ( 0 )
74+ Ok ( self . skip_blocks . unwrap_or ( 0 ) )
6975 }
7076 }
7177
@@ -124,7 +130,13 @@ impl Blockchain for RpcBlockchain {
124130
125131 //TODO if current_height == node_synced should check only the mempool
126132
127- //TODO if it's a big rescan, spawn a thread that checks getwalletinfo and update progress
133+ //TODO if it's a big rescan, spawn a thread that checks getwalletinfo and update progress?
134+ // maybe better to call rescan in chunks (updating node_synced_height) so that in case of
135+ // interruption work can be partially recovered
136+ debug ! (
137+ "rescan_blockchain from:{} to:{}" ,
138+ node_synced, current_height
139+ ) ;
128140 self . client
129141 . rescan_blockchain ( Some ( node_synced as usize ) , Some ( current_height as usize ) ) ?;
130142 progress_update. update ( 1.0 , None ) ?;
@@ -137,7 +149,9 @@ impl Blockchain for RpcBlockchain {
137149 let known_utxos: HashSet < _ > = db. iter_utxos ( ) ?. into_iter ( ) . collect ( ) ;
138150
139151 //TODO list_since_blocks would be more efficient
140- let current_utxo = self . client . list_unspent ( Some ( 0 ) , None , None , None , None ) ?;
152+ let current_utxo = self
153+ . client
154+ . list_unspent ( Some ( 0 ) , None , None , Some ( true ) , None ) ?;
141155 debug ! ( "current_utxo len {}" , current_utxo. len( ) ) ;
142156 let current_txs = self
143157 . client
@@ -299,6 +313,7 @@ impl ConfigurableBlockchain for RpcBlockchain {
299313 capabilities,
300314 wallet_name,
301315 satoshi_address,
316+ skip_blocks : config. skip_blocks . clone ( ) ,
302317 } )
303318 }
304319}
@@ -359,6 +374,7 @@ fn local_rpc() -> RpcBlockchain {
359374 auth : Auth :: CookieFile ( bitcoind. cookie_file . clone ( ) ) ,
360375 network : Network :: Regtest ,
361376 wallet_name : "bdk-test" . to_string ( ) ,
377+ skip_blocks : None ,
362378 } ;
363379 RpcBlockchain :: from_config ( & config) . unwrap ( )
364380}
@@ -395,6 +411,7 @@ mod test {
395411 auth : Auth :: CookieFile ( bitcoind. cookie_file . clone ( ) ) ,
396412 network,
397413 wallet_name,
414+ skip_blocks : None ,
398415 } ;
399416 RpcBlockchain :: from_config ( & config)
400417 }
@@ -412,8 +429,7 @@ mod test {
412429 let node_address = bitcoind. client . get_new_address ( None , None ) . unwrap ( ) ;
413430 let blockchain = create_rpc ( & bitcoind, DESCRIPTOR_PUB , Network :: Regtest ) . unwrap ( ) ;
414431 let db = MemoryDatabase :: new ( ) ;
415- let wallet =
416- Wallet :: new ( DESCRIPTOR_PRIV , None , Network :: Regtest , db, blockchain) . unwrap ( ) ;
432+ let wallet = Wallet :: new ( DESCRIPTOR_PRIV , None , Network :: Regtest , db, blockchain) . unwrap ( ) ;
417433
418434 wallet. sync ( noop_progress ( ) , None ) . unwrap ( ) ;
419435 generate ( & bitcoind, 101 ) ;
@@ -425,13 +441,40 @@ mod test {
425441
426442 let mut builder = wallet. build_tx ( ) ;
427443 builder. add_recipient ( node_address. script_pubkey ( ) , 50_000 ) ;
428- let ( mut psbt, details) = builder. finish ( ) . unwrap ( ) ;
444+ let ( mut psbt, details) = builder. finish ( ) . unwrap ( ) ;
429445 let finalized = wallet. sign ( & mut psbt, Default :: default ( ) ) . unwrap ( ) ;
430446 assert ! ( finalized, "Cannot finalize transaction" ) ;
431447 let tx = psbt. extract_tx ( ) ;
432448 wallet. broadcast ( tx) . unwrap ( ) ;
433449 wallet. sync ( noop_progress ( ) , None ) . unwrap ( ) ;
434- assert_eq ! ( wallet. get_balance( ) . unwrap( ) , 100_000 - 50_000 - details. fees) ;
450+ assert_eq ! (
451+ wallet. get_balance( ) . unwrap( ) ,
452+ 100_000 - 50_000 - details. fees
453+ ) ;
454+ drop ( wallet) ;
455+
456+ // test skip_blocks
457+ generate ( & bitcoind, 5 ) ;
458+ let config = RpcConfig {
459+ url : bitcoind. url . clone ( ) ,
460+ auth : Auth :: CookieFile ( bitcoind. cookie_file . clone ( ) ) ,
461+ network : Network :: Regtest ,
462+ wallet_name : "another-name" . to_string ( ) ,
463+ skip_blocks : Some ( 103 ) ,
464+ } ;
465+ let blockchain_skip = RpcBlockchain :: from_config ( & config) . unwrap ( ) ;
466+ let db = MemoryDatabase :: new ( ) ;
467+ let wallet_skip =
468+ Wallet :: new ( DESCRIPTOR_PRIV , None , Network :: Regtest , db, blockchain_skip) . unwrap ( ) ;
469+ send_to_address ( & bitcoind, & address, 100_000 ) ;
470+ assert_eq ! (
471+ "bcrt1q8dyvgt4vhr8ald4xuwewcxhdjha9a5k78wxm5t" ,
472+ address. to_string( )
473+ ) ;
474+ println ! ( "address:{}" , & address) ;
475+ generate ( & bitcoind, 1 ) ; // TODO why this is needed even if list_unspent should include zero conf and unsafe?
476+ wallet_skip. sync ( noop_progress ( ) , None ) . unwrap ( ) ;
477+ assert_eq ! ( wallet_skip. get_balance( ) . unwrap( ) , 100_000 ) ;
435478 }
436479
437480 #[ test]
@@ -450,8 +493,7 @@ mod test {
450493 let capabilities = rpc. get_capabilities ( ) ;
451494 assert ! ( capabilities. contains( & Capability :: FullHistory ) && capabilities. len( ) == 1 ) ;
452495 let bitcoind_indexed = create_bitcoind ( vec ! [ "-txindex" . to_string( ) ] ) ;
453- let rpc_indexed =
454- create_rpc ( & bitcoind_indexed, DESCRIPTOR_PUB , Network :: Regtest ) . unwrap ( ) ;
496+ let rpc_indexed = create_rpc ( & bitcoind_indexed, DESCRIPTOR_PUB , Network :: Regtest ) . unwrap ( ) ;
455497 assert_eq ! ( rpc_indexed. get_capabilities( ) . len( ) , 3 ) ;
456498 let address = generate ( & bitcoind_indexed, 101 ) ;
457499 let txid = send_to_address ( & bitcoind_indexed, & address, 100_000 ) ;
0 commit comments