11use std:: {
2- collections:: BTreeMap ,
2+ collections:: { BTreeMap , BTreeSet } ,
33 io:: { self , Write } ,
44 sync:: Mutex ,
55} ;
66
77use bdk_chain:: {
88 bitcoin:: { Address , Network , OutPoint , ScriptBuf , Txid } ,
9- indexed_tx_graph:: { self , IndexedTxGraph } ,
9+ indexed_tx_graph:: IndexedTxGraph ,
1010 keychain:: WalletChangeSet ,
1111 local_chain:: { CheckPoint , LocalChain } ,
1212 Append , ConfirmationTimeAnchor ,
@@ -114,17 +114,15 @@ fn main() -> anyhow::Result<()> {
114114 }
115115 } ;
116116
117- // This is where we will accumulate changes of `IndexedTxGraph` and `LocalChain` and persist
118- // these changes as a batch at the end.
119- let mut changeset = WalletChangeSet :: < Keychain , ConfirmationTimeAnchor > :: default ( ) ;
120-
121117 // Prepare the `IndexedTxGraph` update based on whether we are scanning or syncing.
122118 // Scanning: We are iterating through spks of all keychains and scanning for transactions for
123119 // each spk. We start with the lowest derivation index spk and stop scanning after `stop_gap`
124- // number of consecutive spks have no transaction history.
120+ // number of consecutive spks have no transaction history. A Scan is done in situations of
121+ // wallet restoration. It is a special case. Applications should use "sync" style updates
122+ // after an initial scan.
125123 // Syncing: We only check for specified spks, utxos and txids to update their confirmation
126124 // status or fetch missing transactions.
127- let graph_update = match & esplora_cmd {
125+ let indexed_tx_graph_changeset = match & esplora_cmd {
128126 EsploraCommands :: Scan {
129127 stop_gap,
130128 scan_options,
@@ -155,7 +153,7 @@ fn main() -> anyhow::Result<()> {
155153 // is reached. It returns a `TxGraph` update (`graph_update`) and a structure that
156154 // represents the last active spk derivation indices of keychains
157155 // (`keychain_indices_update`).
158- let ( graph_update, keychain_indices_update ) = client
156+ let ( graph_update, last_active_indices ) = client
159157 . update_tx_graph (
160158 keychain_spks,
161159 core:: iter:: empty ( ) ,
@@ -165,18 +163,15 @@ fn main() -> anyhow::Result<()> {
165163 )
166164 . context ( "scanning for transactions" ) ?;
167165
168- // Update the index in `IndexedTxGraph` with `keychain_indices_update`. The resultant
169- // changes are appended to `changeset`.
170- changeset. append ( {
171- let ( _, index_additions) = graph
172- . lock ( )
173- . expect ( "mutex must not be poisoned" )
174- . index
175- . reveal_to_target_multi ( & keychain_indices_update) ;
176- WalletChangeSet :: from ( indexed_tx_graph:: ChangeSet :: from ( index_additions) )
177- } ) ;
178-
179- graph_update
166+ let mut graph = graph. lock ( ) . expect ( "mutex must not be poisoned" ) ;
167+ // Because we did a stop gap based scan we are likely to have some updates to our
168+ // deriviation indices. Usually before a scan you are on a fresh wallet with no
169+ // addresses derived so we need to derive up to last active addresses the scan found
170+ // before adding the transactions.
171+ let ( _, index_changeset) = graph. index . reveal_to_target_multi ( & last_active_indices) ;
172+ let mut indexed_tx_graph_changeset = graph. apply_update ( graph_update) ;
173+ indexed_tx_graph_changeset. append ( index_changeset. into ( ) ) ;
174+ indexed_tx_graph_changeset
180175 }
181176 EsploraCommands :: Sync {
182177 mut unused_spks,
@@ -281,42 +276,31 @@ fn main() -> anyhow::Result<()> {
281276 }
282277 }
283278
284- client. update_tx_graph_without_keychain (
279+ let graph_update = client. update_tx_graph_without_keychain (
285280 spks,
286281 txids,
287282 outpoints,
288283 scan_options. parallel_requests ,
289- ) ?
284+ ) ?;
285+
286+ graph. lock ( ) . unwrap ( ) . apply_update ( graph_update)
290287 }
291288 } ;
292289
293290 println ! ( ) ;
294291
295- // We apply the `TxGraph` update, and append the resultant changes to `changeset`
296- // (for persistance)
297- changeset. append ( {
298- let indexed_graph_additions = graph. lock ( ) . unwrap ( ) . apply_update ( graph_update) ;
299- WalletChangeSet :: from ( indexed_graph_additions)
300- } ) ;
301-
302- // Now that we're done updating the `TxGraph`, it's time to update the `LocalChain`!
303- // We want the `LocalChain` to have data about all the anchors in the `TxGraph` - for this
304- // reason, we want retrieve the heights of the newly added anchors, and fetch the corresponding
305- // blocks.
306-
307- // We get the heights of all the anchors introduced by the changeset, and the local chain tip.
308- // Note that the latter is only used for logging.
292+ // Now that we're done updating the `IndexedTxGraph`, it's time to update the `LocalChain`! We
293+ // want the `LocalChain` to have data about all the anchors in the `TxGraph` - for this reason,
294+ // we want retrieve the blocks at the heights of the newly added anchors that are missing from
295+ // our view of the chain.
309296 let ( missing_block_heights, tip) = {
310297 let chain = & * chain. lock ( ) . unwrap ( ) ;
311- let heights_to_fetch = changeset
312- . indexed_tx_graph
298+ let missing_block_heights = indexed_tx_graph_changeset
313299 . graph
314- . anchors
315- . iter ( )
316- . map ( |( a, _) | a. confirmation_height )
317- . collect :: < Vec < _ > > ( ) ;
300+ . missing_heights_from ( chain)
301+ . collect :: < BTreeSet < _ > > ( ) ;
318302 let tip = chain. tip ( ) ;
319- ( heights_to_fetch , tip)
303+ ( missing_block_heights , tip)
320304 } ;
321305
322306 println ! ( "prev tip: {}" , tip. as_ref( ) . map_or( 0 , CheckPoint :: height) ) ;
@@ -329,16 +313,12 @@ fn main() -> anyhow::Result<()> {
329313
330314 println ! ( "new tip: {}" , chain_update. tip. height( ) ) ;
331315
332- // We apply the `LocalChain` update, and append the resultant changes to `changeset`
333- // (for persistance).
334- changeset. append ( {
335- let chain_additions = chain. lock ( ) . unwrap ( ) . apply_update ( chain_update) ?;
336- WalletChangeSet :: from ( chain_additions)
337- } ) ;
338-
339- // We persist `changeset`.
316+ // We persist the changes
340317 let mut db = db. lock ( ) . unwrap ( ) ;
341- db. stage ( changeset) ;
318+ db. stage ( WalletChangeSet {
319+ chain : chain. lock ( ) . unwrap ( ) . apply_update ( chain_update) ?,
320+ indexed_tx_graph : indexed_tx_graph_changeset,
321+ } ) ;
342322 db. commit ( ) ?;
343323 Ok ( ( ) )
344324}
0 commit comments