@@ -23,12 +23,14 @@ pub trait ElectrumExt {
2323 ///
2424 /// The full scan for each keychain stops after a gap of `stop_gap` script pubkeys with no associated
2525 /// transactions. `batch_size` specifies the max number of script pubkeys to request for in a
26- /// single batch request.
26+ /// single batch request. `fetch_prev_txouts` specifies whether or not we want previous `TxOut`s
27+ /// for fee calculation.
2728 fn full_scan < K : Ord + Clone > (
2829 & self ,
2930 request : FullScanRequest < K > ,
3031 stop_gap : usize ,
3132 batch_size : usize ,
33+ fetch_prev_txouts : bool ,
3234 ) -> Result < ElectrumFullScanResult < K > , Error > ;
3335
3436 /// Sync a set of scripts with the blockchain (via an Electrum client) for the data specified
@@ -38,13 +40,19 @@ pub trait ElectrumExt {
3840 /// see [`SyncRequest`]
3941 ///
4042 /// `batch_size` specifies the max number of script pubkeys to request for in a single batch
41- /// request.
43+ /// request. `fetch_prev_txouts` specifies whether or not we want previous `TxOut`s for fee
44+ /// calculation.
4245 ///
4346 /// If the scripts to sync are unknown, such as when restoring or importing a keychain that
4447 /// may include scripts that have been used, use [`full_scan`] with the keychain.
4548 ///
4649 /// [`full_scan`]: ElectrumExt::full_scan
47- fn sync ( & self , request : SyncRequest , batch_size : usize ) -> Result < ElectrumSyncResult , Error > ;
50+ fn sync (
51+ & self ,
52+ request : SyncRequest ,
53+ batch_size : usize ,
54+ fetch_prev_txouts : bool ,
55+ ) -> Result < ElectrumSyncResult , Error > ;
4856}
4957
5058impl < E : ElectrumApi > ElectrumExt for E {
@@ -53,6 +61,7 @@ impl<E: ElectrumApi> ElectrumExt for E {
5361 mut request : FullScanRequest < K > ,
5462 stop_gap : usize ,
5563 batch_size : usize ,
64+ fetch_prev_txouts : bool ,
5665 ) -> Result < ElectrumFullScanResult < K > , Error > {
5766 let mut request_spks = request. spks_by_keychain ;
5867
@@ -104,6 +113,18 @@ impl<E: ElectrumApi> ElectrumExt for E {
104113 }
105114 }
106115
116+ // Fetch previous `TxOut`s for fee calculation if flag is enabled.
117+ if fetch_prev_txouts {
118+ let _ = graph_update. apply_update ( fetch_prev_txout (
119+ self ,
120+ & mut request. tx_cache ,
121+ graph_update
122+ . full_txs ( )
123+ . map ( |tx_node| tx_node. tx )
124+ . collect :: < Vec < _ > > ( ) ,
125+ ) ?) ;
126+ }
127+
107128 // check for reorgs during scan process
108129 let server_blockhash = self . block_header ( tip. height ( ) as usize ) ?. block_hash ( ) ;
109130 if tip. hash ( ) != server_blockhash {
@@ -133,14 +154,19 @@ impl<E: ElectrumApi> ElectrumExt for E {
133154 Ok ( ElectrumFullScanResult ( update) )
134155 }
135156
136- fn sync ( & self , request : SyncRequest , batch_size : usize ) -> Result < ElectrumSyncResult , Error > {
157+ fn sync (
158+ & self ,
159+ request : SyncRequest ,
160+ batch_size : usize ,
161+ fetch_prev_txouts : bool ,
162+ ) -> Result < ElectrumSyncResult , Error > {
137163 let mut tx_cache = request. tx_cache . clone ( ) ;
138164
139165 let full_scan_req = FullScanRequest :: from_chain_tip ( request. chain_tip . clone ( ) )
140166 . cache_txs ( request. tx_cache )
141167 . set_spks_for_keychain ( ( ) , request. spks . enumerate ( ) . map ( |( i, spk) | ( i as u32 , spk) ) ) ;
142168 let mut full_scan_res = self
143- . full_scan ( full_scan_req, usize:: MAX , batch_size) ?
169+ . full_scan ( full_scan_req, usize:: MAX , batch_size, fetch_prev_txouts ) ?
144170 . with_confirmation_height_anchor ( ) ;
145171
146172 let ( tip, _) = construct_update_tip ( self , request. chain_tip ) ?;
@@ -165,6 +191,19 @@ impl<E: ElectrumApi> ElectrumExt for E {
165191 request. outpoints ,
166192 ) ?;
167193
194+ // Fetch previous `TxOut`s for fee calculation if flag is enabled.
195+ if fetch_prev_txouts {
196+ let _ = full_scan_res. graph_update . apply_update ( fetch_prev_txout (
197+ self ,
198+ & mut tx_cache,
199+ full_scan_res
200+ . graph_update
201+ . full_txs ( )
202+ . map ( |tx_node| tx_node. tx )
203+ . collect :: < Vec < _ > > ( ) ,
204+ ) ?) ;
205+ }
206+
168207 Ok ( ElectrumSyncResult ( SyncResult {
169208 chain_update : full_scan_res. chain_update ,
170209 graph_update : full_scan_res. graph_update ,
@@ -374,7 +413,7 @@ fn populate_with_outpoints(
374413 client : & impl ElectrumApi ,
375414 cps : & BTreeMap < u32 , CheckPoint > ,
376415 tx_cache : & mut TxCache ,
377- tx_graph : & mut TxGraph < ConfirmationHeightAnchor > ,
416+ graph_update : & mut TxGraph < ConfirmationHeightAnchor > ,
378417 outpoints : impl IntoIterator < Item = OutPoint > ,
379418) -> Result < ( ) , Error > {
380419 for outpoint in outpoints {
@@ -399,18 +438,18 @@ fn populate_with_outpoints(
399438 continue ;
400439 }
401440 has_residing = true ;
402- if tx_graph . get_tx ( res. tx_hash ) . is_none ( ) {
403- let _ = tx_graph . insert_tx ( tx. clone ( ) ) ;
441+ if graph_update . get_tx ( res. tx_hash ) . is_none ( ) {
442+ let _ = graph_update . insert_tx ( tx. clone ( ) ) ;
404443 }
405444 } else {
406445 if has_spending {
407446 continue ;
408447 }
409- let res_tx = match tx_graph . get_tx ( res. tx_hash ) {
448+ let res_tx = match graph_update . get_tx ( res. tx_hash ) {
410449 Some ( tx) => tx,
411450 None => {
412451 let res_tx = fetch_tx ( client, tx_cache, res. tx_hash ) ?;
413- let _ = tx_graph . insert_tx ( Arc :: clone ( & res_tx) ) ;
452+ let _ = graph_update . insert_tx ( Arc :: clone ( & res_tx) ) ;
414453 res_tx
415454 }
416455 } ;
@@ -424,7 +463,7 @@ fn populate_with_outpoints(
424463 } ;
425464
426465 if let Some ( anchor) = determine_tx_anchor ( cps, res. height , res. tx_hash ) {
427- let _ = tx_graph . insert_anchor ( res. tx_hash , anchor) ;
466+ let _ = graph_update . insert_anchor ( res. tx_hash , anchor) ;
428467 }
429468 }
430469 }
@@ -484,6 +523,26 @@ fn fetch_tx<C: ElectrumApi>(
484523 } )
485524}
486525
526+ // Helper function which fetches the `TxOut`s of our relevant transactions' previous transactions,
527+ // which we do not have by default. This data is needed to calculate the transaction fee.
528+ fn fetch_prev_txout < C : ElectrumApi > (
529+ client : & C ,
530+ tx_cache : & mut TxCache ,
531+ full_txs : Vec < Arc < Transaction > > ,
532+ ) -> Result < TxGraph < ConfirmationHeightAnchor > , Error > {
533+ let mut graph_update = TxGraph :: < ConfirmationHeightAnchor > :: default ( ) ;
534+ for tx in full_txs {
535+ for vin in tx. input . clone ( ) {
536+ let outpoint = vin. previous_output ;
537+ let prev_tx = fetch_tx ( client, tx_cache, outpoint. txid ) ?;
538+ for txout in prev_tx. output . clone ( ) {
539+ let _ = graph_update. insert_txout ( outpoint, txout) ;
540+ }
541+ }
542+ }
543+ Ok ( graph_update)
544+ }
545+
487546fn populate_with_spks < I : Ord + Clone > (
488547 client : & impl ElectrumApi ,
489548 cps : & BTreeMap < u32 , CheckPoint > ,
0 commit comments