@@ -3,7 +3,7 @@ use bdk_chain::BlockId;
33use bdk_esplora:: EsploraExt ;
44use electrsd:: bitcoind:: anyhow;
55use electrsd:: bitcoind:: bitcoincore_rpc:: RpcApi ;
6- use esplora_client:: { self , Builder } ;
6+ use esplora_client:: { self , BlockHash , Builder } ;
77use std:: collections:: { BTreeMap , BTreeSet , HashSet } ;
88use std:: str:: FromStr ;
99use std:: thread:: sleep;
@@ -68,13 +68,35 @@ pub fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> {
6868 sleep ( Duration :: from_millis ( 10 ) )
6969 }
7070
71- let graph_update = client. sync (
71+ // use a full checkpoint linked list (since this is not what we are testing)
72+ let cp_tip = env. make_checkpoint_tip ( ) ;
73+
74+ let sync_update = client. sync (
75+ cp_tip. clone ( ) ,
7276 misc_spks. into_iter ( ) ,
7377 vec ! [ ] . into_iter ( ) ,
7478 vec ! [ ] . into_iter ( ) ,
7579 1 ,
7680 ) ?;
7781
82+ assert ! (
83+ {
84+ let update_cps = sync_update
85+ . local_chain
86+ . tip
87+ . iter( )
88+ . map( |cp| cp. block_id( ) )
89+ . collect:: <BTreeSet <_>>( ) ;
90+ let superset_cps = cp_tip
91+ . iter( )
92+ . map( |cp| cp. block_id( ) )
93+ . collect:: <BTreeSet <_>>( ) ;
94+ superset_cps. is_superset( & update_cps)
95+ } ,
96+ "update should not alter original checkpoint tip since we already started with all checkpoints" ,
97+ ) ;
98+
99+ let graph_update = sync_update. tx_graph ;
78100 // Check to see if we have the floating txouts available from our two created transactions'
79101 // previous outputs in order to calculate transaction fees.
80102 for tx in graph_update. full_txs ( ) {
@@ -155,14 +177,20 @@ pub fn test_update_tx_graph_stop_gap() -> anyhow::Result<()> {
155177 sleep ( Duration :: from_millis ( 10 ) )
156178 }
157179
180+ // use a full checkpoint linked list (since this is not what we are testing)
181+ let cp_tip = env. make_checkpoint_tip ( ) ;
182+
158183 // A scan with a stop_gap of 3 won't find the transaction, but a scan with a gap limit of 4
159184 // will.
160- let ( graph_update, active_indices) = client. full_scan ( keychains. clone ( ) , 3 , 1 ) ?;
161- assert ! ( graph_update. full_txs( ) . next( ) . is_none( ) ) ;
162- assert ! ( active_indices. is_empty( ) ) ;
163- let ( graph_update, active_indices) = client. full_scan ( keychains. clone ( ) , 4 , 1 ) ?;
164- assert_eq ! ( graph_update. full_txs( ) . next( ) . unwrap( ) . txid, txid_4th_addr) ;
165- assert_eq ! ( active_indices[ & 0 ] , 3 ) ;
185+ let full_scan_update = client. full_scan ( cp_tip. clone ( ) , keychains. clone ( ) , 3 , 1 ) ?;
186+ assert ! ( full_scan_update. tx_graph. full_txs( ) . next( ) . is_none( ) ) ;
187+ assert ! ( full_scan_update. last_active_indices. is_empty( ) ) ;
188+ let full_scan_update = client. full_scan ( cp_tip. clone ( ) , keychains. clone ( ) , 4 , 1 ) ?;
189+ assert_eq ! (
190+ full_scan_update. tx_graph. full_txs( ) . next( ) . unwrap( ) . txid,
191+ txid_4th_addr
192+ ) ;
193+ assert_eq ! ( full_scan_update. last_active_indices[ & 0 ] , 3 ) ;
166194
167195 // Now receive a coin on the last address.
168196 let txid_last_addr = env. bitcoind . client . send_to_address (
@@ -182,16 +210,24 @@ pub fn test_update_tx_graph_stop_gap() -> anyhow::Result<()> {
182210
183211 // A scan with gap limit 5 won't find the second transaction, but a scan with gap limit 6 will.
184212 // The last active indice won't be updated in the first case but will in the second one.
185- let ( graph_update, active_indices) = client. full_scan ( keychains. clone ( ) , 5 , 1 ) ?;
186- let txs: HashSet < _ > = graph_update. full_txs ( ) . map ( |tx| tx. txid ) . collect ( ) ;
213+ let full_scan_update = client. full_scan ( cp_tip. clone ( ) , keychains. clone ( ) , 5 , 1 ) ?;
214+ let txs: HashSet < _ > = full_scan_update
215+ . tx_graph
216+ . full_txs ( )
217+ . map ( |tx| tx. txid )
218+ . collect ( ) ;
187219 assert_eq ! ( txs. len( ) , 1 ) ;
188220 assert ! ( txs. contains( & txid_4th_addr) ) ;
189- assert_eq ! ( active_indices[ & 0 ] , 3 ) ;
190- let ( graph_update, active_indices) = client. full_scan ( keychains, 6 , 1 ) ?;
191- let txs: HashSet < _ > = graph_update. full_txs ( ) . map ( |tx| tx. txid ) . collect ( ) ;
221+ assert_eq ! ( full_scan_update. last_active_indices[ & 0 ] , 3 ) ;
222+ let full_scan_update = client. full_scan ( cp_tip. clone ( ) , keychains, 6 , 1 ) ?;
223+ let txs: HashSet < _ > = full_scan_update
224+ . tx_graph
225+ . full_txs ( )
226+ . map ( |tx| tx. txid )
227+ . collect ( ) ;
192228 assert_eq ! ( txs. len( ) , 2 ) ;
193229 assert ! ( txs. contains( & txid_4th_addr) && txs. contains( & txid_last_addr) ) ;
194- assert_eq ! ( active_indices [ & 0 ] , 9 ) ;
230+ assert_eq ! ( full_scan_update . last_active_indices [ & 0 ] , 9 ) ;
195231
196232 Ok ( ( ) )
197233}
@@ -317,14 +353,38 @@ fn update_local_chain() -> anyhow::Result<()> {
317353 for ( i, t) in test_cases. into_iter ( ) . enumerate ( ) {
318354 println ! ( "Case {}: {}" , i, t. name) ;
319355 let mut chain = t. chain ;
356+ let cp_tip = chain. tip ( ) ;
320357
321- let update = client
322- . update_local_chain ( chain. tip ( ) , t. request_heights . iter ( ) . copied ( ) )
323- . map_err ( |err| {
324- anyhow:: format_err!( "[{}:{}] `update_local_chain` failed: {}" , i, t. name, err)
358+ let new_blocks =
359+ bdk_esplora:: init_chain_update_blocking ( & client, & cp_tip) . map_err ( |err| {
360+ anyhow:: format_err!( "[{}:{}] `init_chain_update` failed: {}" , i, t. name, err)
325361 } ) ?;
326362
327- let update_blocks = update
363+ let mock_anchors = t
364+ . request_heights
365+ . iter ( )
366+ . map ( |& h| {
367+ let anchor_blockhash: BlockHash = bdk_chain:: bitcoin:: hashes:: Hash :: hash (
368+ & format ! ( "hash_at_height_{}" , h) . into_bytes ( ) ,
369+ ) ;
370+ let txid: Txid = bdk_chain:: bitcoin:: hashes:: Hash :: hash (
371+ & format ! ( "txid_at_height_{}" , h) . into_bytes ( ) ,
372+ ) ;
373+ let anchor = BlockId {
374+ height : h,
375+ hash : anchor_blockhash,
376+ } ;
377+ ( anchor, txid)
378+ } )
379+ . collect :: < BTreeSet < _ > > ( ) ;
380+
381+ let chain_update = bdk_esplora:: finalize_chain_update_blocking (
382+ & client,
383+ & cp_tip,
384+ & mock_anchors,
385+ new_blocks,
386+ ) ?;
387+ let update_blocks = chain_update
328388 . tip
329389 . iter ( )
330390 . map ( |cp| cp. block_id ( ) )
@@ -346,14 +406,15 @@ fn update_local_chain() -> anyhow::Result<()> {
346406 )
347407 . collect :: < BTreeSet < _ > > ( ) ;
348408
349- assert_eq ! (
350- update_blocks, exp_update_blocks,
409+ assert ! (
410+ update_blocks. is_superset ( & exp_update_blocks) ,
351411 "[{}:{}] unexpected update" ,
352- i, t. name
412+ i,
413+ t. name
353414 ) ;
354415
355416 let _ = chain
356- . apply_update ( update )
417+ . apply_update ( chain_update )
357418 . unwrap_or_else ( |err| panic ! ( "[{}:{}] update failed to apply: {}" , i, t. name, err) ) ;
358419
359420 // all requested heights must exist in the final chain
0 commit comments