@@ -20,31 +20,40 @@ pub trait ElectrumExt {
2020 ///
2121 /// - `request`: struct with data required to perform a spk-based blockchain client full scan,
2222 /// see [`FullScanRequest`]
23- ///
24- /// The full scan for each keychain stops after a gap of `stop_gap` script pubkeys with no associated
25- /// transactions. `batch_size` specifies the max number of script pubkeys to request for in a
26- /// single batch request.
23+ /// - `stop_gap`: the full scan for each keychain stops after a gap of script pubkeys with no
24+ /// associated transactions
25+ /// - `batch_size`: specifies the max number of script pubkeys to request for in a single batch
26+ /// request
27+ /// - `fetch_prev_txouts`: specifies whether or not we want previous `TxOut`s for fee
28+ /// calculation
2729 fn full_scan < K : Ord + Clone > (
2830 & self ,
2931 request : FullScanRequest < K > ,
3032 stop_gap : usize ,
3133 batch_size : usize ,
34+ fetch_prev_txouts : bool ,
3235 ) -> Result < ElectrumFullScanResult < K > , Error > ;
3336
3437 /// Sync a set of scripts with the blockchain (via an Electrum client) for the data specified
3538 /// and returns updates for [`bdk_chain`] data structures.
3639 ///
3740 /// - `request`: struct with data required to perform a spk-based blockchain client sync,
3841 /// see [`SyncRequest`]
39- ///
40- /// `batch_size` specifies the max number of script pubkeys to request for in a single batch
41- /// request.
42+ /// - `batch_size`: specifies the max number of script pubkeys to request for in a single batch
43+ /// request
44+ /// - `fetch_prev_txouts`: specifies whether or not we want previous `TxOut`s for fee
45+ /// calculation
4246 ///
4347 /// If the scripts to sync are unknown, such as when restoring or importing a keychain that
4448 /// may include scripts that have been used, use [`full_scan`] with the keychain.
4549 ///
4650 /// [`full_scan`]: ElectrumExt::full_scan
47- fn sync ( & self , request : SyncRequest , batch_size : usize ) -> Result < ElectrumSyncResult , Error > ;
51+ fn sync (
52+ & self ,
53+ request : SyncRequest ,
54+ batch_size : usize ,
55+ fetch_prev_txouts : bool ,
56+ ) -> Result < ElectrumSyncResult , Error > ;
4857}
4958
5059impl < E : ElectrumApi > ElectrumExt for E {
@@ -53,6 +62,7 @@ impl<E: ElectrumApi> ElectrumExt for E {
5362 mut request : FullScanRequest < K > ,
5463 stop_gap : usize ,
5564 batch_size : usize ,
65+ fetch_prev_txouts : bool ,
5666 ) -> Result < ElectrumFullScanResult < K > , Error > {
5767 let mut request_spks = request. spks_by_keychain ;
5868
@@ -110,6 +120,11 @@ impl<E: ElectrumApi> ElectrumExt for E {
110120 continue ; // reorg
111121 }
112122
123+ // Fetch previous `TxOut`s for fee calculation if flag is enabled.
124+ if fetch_prev_txouts {
125+ fetch_prev_txout ( self , & mut request. tx_cache , & mut graph_update) ?;
126+ }
127+
113128 let chain_update = tip;
114129
115130 let keychain_update = request_spks
@@ -133,14 +148,19 @@ impl<E: ElectrumApi> ElectrumExt for E {
133148 Ok ( ElectrumFullScanResult ( update) )
134149 }
135150
136- fn sync ( & self , request : SyncRequest , batch_size : usize ) -> Result < ElectrumSyncResult , Error > {
151+ fn sync (
152+ & self ,
153+ request : SyncRequest ,
154+ batch_size : usize ,
155+ fetch_prev_txouts : bool ,
156+ ) -> Result < ElectrumSyncResult , Error > {
137157 let mut tx_cache = request. tx_cache . clone ( ) ;
138158
139159 let full_scan_req = FullScanRequest :: from_chain_tip ( request. chain_tip . clone ( ) )
140160 . cache_txs ( request. tx_cache )
141161 . set_spks_for_keychain ( ( ) , request. spks . enumerate ( ) . map ( |( i, spk) | ( i as u32 , spk) ) ) ;
142162 let mut full_scan_res = self
143- . full_scan ( full_scan_req, usize:: MAX , batch_size) ?
163+ . full_scan ( full_scan_req, usize:: MAX , batch_size, false ) ?
144164 . with_confirmation_height_anchor ( ) ;
145165
146166 let ( tip, _) = construct_update_tip ( self , request. chain_tip ) ?;
@@ -165,6 +185,11 @@ impl<E: ElectrumApi> ElectrumExt for E {
165185 request. outpoints ,
166186 ) ?;
167187
188+ // Fetch previous `TxOut`s for fee calculation if flag is enabled.
189+ if fetch_prev_txouts {
190+ fetch_prev_txout ( self , & mut tx_cache, & mut full_scan_res. graph_update ) ?;
191+ }
192+
168193 Ok ( ElectrumSyncResult ( SyncResult {
169194 chain_update : full_scan_res. chain_update ,
170195 graph_update : full_scan_res. graph_update ,
@@ -374,7 +399,7 @@ fn populate_with_outpoints(
374399 client : & impl ElectrumApi ,
375400 cps : & BTreeMap < u32 , CheckPoint > ,
376401 tx_cache : & mut TxCache ,
377- tx_graph : & mut TxGraph < ConfirmationHeightAnchor > ,
402+ graph_update : & mut TxGraph < ConfirmationHeightAnchor > ,
378403 outpoints : impl IntoIterator < Item = OutPoint > ,
379404) -> Result < ( ) , Error > {
380405 for outpoint in outpoints {
@@ -399,18 +424,18 @@ fn populate_with_outpoints(
399424 continue ;
400425 }
401426 has_residing = true ;
402- if tx_graph . get_tx ( res. tx_hash ) . is_none ( ) {
403- let _ = tx_graph . insert_tx ( tx. clone ( ) ) ;
427+ if graph_update . get_tx ( res. tx_hash ) . is_none ( ) {
428+ let _ = graph_update . insert_tx ( tx. clone ( ) ) ;
404429 }
405430 } else {
406431 if has_spending {
407432 continue ;
408433 }
409- let res_tx = match tx_graph . get_tx ( res. tx_hash ) {
434+ let res_tx = match graph_update . get_tx ( res. tx_hash ) {
410435 Some ( tx) => tx,
411436 None => {
412437 let res_tx = fetch_tx ( client, tx_cache, res. tx_hash ) ?;
413- let _ = tx_graph . insert_tx ( Arc :: clone ( & res_tx) ) ;
438+ let _ = graph_update . insert_tx ( Arc :: clone ( & res_tx) ) ;
414439 res_tx
415440 }
416441 } ;
@@ -424,7 +449,7 @@ fn populate_with_outpoints(
424449 } ;
425450
426451 if let Some ( anchor) = determine_tx_anchor ( cps, res. height , res. tx_hash ) {
427- let _ = tx_graph . insert_anchor ( res. tx_hash , anchor) ;
452+ let _ = graph_update . insert_anchor ( res. tx_hash , anchor) ;
428453 }
429454 }
430455 }
@@ -484,6 +509,27 @@ fn fetch_tx<C: ElectrumApi>(
484509 } )
485510}
486511
512+ // Helper function which fetches the `TxOut`s of our relevant transactions' previous transactions,
513+ // which we do not have by default. This data is needed to calculate the transaction fee.
514+ fn fetch_prev_txout < C : ElectrumApi > (
515+ client : & C ,
516+ tx_cache : & mut TxCache ,
517+ graph_update : & mut TxGraph < ConfirmationHeightAnchor > ,
518+ ) -> Result < ( ) , Error > {
519+ let full_txs: Vec < Arc < Transaction > > =
520+ graph_update. full_txs ( ) . map ( |tx_node| tx_node. tx ) . collect ( ) ;
521+ for tx in full_txs {
522+ for vin in & tx. input {
523+ let outpoint = vin. previous_output ;
524+ let prev_tx = fetch_tx ( client, tx_cache, outpoint. txid ) ?;
525+ for txout in prev_tx. output . clone ( ) {
526+ let _ = graph_update. insert_txout ( outpoint, txout) ;
527+ }
528+ }
529+ }
530+ Ok ( ( ) )
531+ }
532+
487533fn populate_with_spks < I : Ord + Clone > (
488534 client : & impl ElectrumApi ,
489535 cps : & BTreeMap < u32 , CheckPoint > ,
0 commit comments