@@ -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, fetch_prev_txouts ) ?
144164 . with_confirmation_height_anchor ( ) ;
145165
146166 let ( tip, _) = construct_update_tip ( self , request. chain_tip ) ?;
@@ -374,7 +394,7 @@ fn populate_with_outpoints(
374394 client : & impl ElectrumApi ,
375395 cps : & BTreeMap < u32 , CheckPoint > ,
376396 tx_cache : & mut TxCache ,
377- tx_graph : & mut TxGraph < ConfirmationHeightAnchor > ,
397+ graph_update : & mut TxGraph < ConfirmationHeightAnchor > ,
378398 outpoints : impl IntoIterator < Item = OutPoint > ,
379399) -> Result < ( ) , Error > {
380400 for outpoint in outpoints {
@@ -399,18 +419,18 @@ fn populate_with_outpoints(
399419 continue ;
400420 }
401421 has_residing = true ;
402- if tx_graph . get_tx ( res. tx_hash ) . is_none ( ) {
403- let _ = tx_graph . insert_tx ( tx. clone ( ) ) ;
422+ if graph_update . get_tx ( res. tx_hash ) . is_none ( ) {
423+ let _ = graph_update . insert_tx ( tx. clone ( ) ) ;
404424 }
405425 } else {
406426 if has_spending {
407427 continue ;
408428 }
409- let res_tx = match tx_graph . get_tx ( res. tx_hash ) {
429+ let res_tx = match graph_update . get_tx ( res. tx_hash ) {
410430 Some ( tx) => tx,
411431 None => {
412432 let res_tx = fetch_tx ( client, tx_cache, res. tx_hash ) ?;
413- let _ = tx_graph . insert_tx ( Arc :: clone ( & res_tx) ) ;
433+ let _ = graph_update . insert_tx ( Arc :: clone ( & res_tx) ) ;
414434 res_tx
415435 }
416436 } ;
@@ -424,7 +444,7 @@ fn populate_with_outpoints(
424444 } ;
425445
426446 if let Some ( anchor) = determine_tx_anchor ( cps, res. height , res. tx_hash ) {
427- let _ = tx_graph . insert_anchor ( res. tx_hash , anchor) ;
447+ let _ = graph_update . insert_anchor ( res. tx_hash , anchor) ;
428448 }
429449 }
430450 }
@@ -484,6 +504,27 @@ fn fetch_tx<C: ElectrumApi>(
484504 } )
485505}
486506
507+ // Helper function which fetches the `TxOut`s of our relevant transactions' previous transactions,
508+ // which we do not have by default. This data is needed to calculate the transaction fee.
509+ fn fetch_prev_txout < C : ElectrumApi > (
510+ client : & C ,
511+ tx_cache : & mut TxCache ,
512+ graph_update : & mut TxGraph < ConfirmationHeightAnchor > ,
513+ ) -> Result < ( ) , Error > {
514+ let full_txs: Vec < Arc < Transaction > > =
515+ graph_update. full_txs ( ) . map ( |tx_node| tx_node. tx ) . collect ( ) ;
516+ for tx in full_txs {
517+ for vin in & tx. input {
518+ let outpoint = vin. previous_output ;
519+ let prev_tx = fetch_tx ( client, tx_cache, outpoint. txid ) ?;
520+ for txout in prev_tx. output . clone ( ) {
521+ let _ = graph_update. insert_txout ( outpoint, txout) ;
522+ }
523+ }
524+ }
525+ Ok ( ( ) )
526+ }
527+
487528fn populate_with_spks < I : Ord + Clone > (
488529 client : & impl ElectrumApi ,
489530 cps : & BTreeMap < u32 , CheckPoint > ,
0 commit comments