@@ -17,7 +17,7 @@ use bdk::{SignOptions, SyncOptions};
1717use bitcoin:: { BlockHash , Script , Transaction , Txid } ;
1818
1919use std:: collections:: HashSet ;
20- use std:: sync:: { Arc , Mutex } ;
20+ use std:: sync:: { Arc , Mutex , MutexGuard } ;
2121
2222/// The minimum feerate we are allowed to send, as specify by LDK.
2323const MIN_FEERATE : u32 = 253 ;
@@ -80,143 +80,156 @@ where
8080
8181 let mut locked_last_sync_height = self . last_sync_height . lock ( ) . unwrap ( ) ;
8282 if cur_height >= locked_last_sync_height. unwrap_or ( 0 ) {
83- {
84- // First, inform the interface of the new block.
85- let cur_block_header = client. get_header ( cur_height) ?;
86- for c in & confirmables {
87- c. best_block_updated ( & cur_block_header, cur_height) ;
88- }
83+ self . sync_best_block_updated ( confirmables. clone ( ) , cur_height, & mut locked_last_sync_height) ?;
84+ self . sync_transactions_confirmed ( confirmables. clone ( ) ) ?;
85+ self . sync_transaction_unconfirmed ( confirmables. clone ( ) ) ?;
86+ }
87+ // TODO: check whether new outputs have been registered by now and process them
88+ Ok ( ( ) )
89+ }
8990
90- * locked_last_sync_height = Some ( cur_height) ;
91- }
91+ fn sync_best_block_updated ( & self , confirmables : Vec < & ( dyn Confirm + Sync ) > , cur_height : u32 , locked_last_sync_height : & mut MutexGuard < Option < u32 > > ) -> Result < ( ) , Error > {
92+ let client = & * self . blockchain ;
9293
93- {
94- // First, check the confirmation status of registered transactions as well as the
95- // status of dependent transactions of registered outputs.
96- let mut locked_queued_transactions = self . queued_transactions . lock ( ) . unwrap ( ) ;
97- let mut locked_queued_outputs = self . queued_outputs . lock ( ) . unwrap ( ) ;
98- let mut locked_watched_transactions = self . watched_transactions . lock ( ) . unwrap ( ) ;
99- let mut locked_watched_outputs = self . watched_outputs . lock ( ) . unwrap ( ) ;
100-
101- let mut confirmed_txs = Vec :: new ( ) ;
102-
103- // Check in the current queue, as well as in registered transactions leftover from
104- // previous iterations.
105- let registered_txs: HashSet < Txid > = locked_watched_transactions
106- . iter ( )
107- . chain ( locked_queued_transactions. iter ( ) )
108- . cloned ( )
109- . collect ( ) ;
110-
111- // Remember all registered but unconfirmed transactions for future processing.
112- let mut unconfirmed_registered_txs = Vec :: new ( ) ;
113-
114- for txid in registered_txs {
115- if let Some ( tx_status) = client. get_tx_status ( & txid) ? {
116- if tx_status. confirmed {
117- if let Some ( tx) = client. get_tx ( & txid) ? {
118- if let Some ( block_height) = tx_status. block_height {
119- let block_header = client. get_header ( block_height) ?;
120- if let Some ( merkle_proof) = client. get_merkle_proof ( & txid) ? {
121- confirmed_txs. push ( (
122- tx,
123- block_height,
124- block_header,
125- merkle_proof. pos ,
94+ // Inform the interface of the new block.
95+ let cur_block_header = client. get_header ( cur_height) ?;
96+ for c in & confirmables {
97+ c. best_block_updated ( & cur_block_header, cur_height) ;
98+ }
99+
100+ * * locked_last_sync_height = Some ( cur_height) ;
101+ Ok ( ( ) )
102+ }
103+
104+ fn sync_transactions_confirmed ( & self , confirmables : Vec < & ( dyn Confirm + Sync ) > ) -> Result < ( ) , Error > {
105+ let client = & * self . blockchain ;
106+
107+ // First, check the confirmation status of registered transactions as well as the
108+ // status of dependent transactions of registered outputs.
109+ let mut locked_queued_transactions = self . queued_transactions . lock ( ) . unwrap ( ) ;
110+ let mut locked_queued_outputs = self . queued_outputs . lock ( ) . unwrap ( ) ;
111+ let mut locked_watched_transactions = self . watched_transactions . lock ( ) . unwrap ( ) ;
112+ let mut locked_watched_outputs = self . watched_outputs . lock ( ) . unwrap ( ) ;
113+
114+ let mut confirmed_txs = Vec :: new ( ) ;
115+
116+ // Check in the current queue, as well as in registered transactions leftover from
117+ // previous iterations.
118+ let registered_txs: HashSet < Txid > = locked_watched_transactions
119+ . iter ( )
120+ . chain ( locked_queued_transactions. iter ( ) )
121+ . cloned ( )
122+ . collect ( ) ;
123+
124+ // Remember all registered but unconfirmed transactions for future processing.
125+ let mut unconfirmed_registered_txs = Vec :: new ( ) ;
126+
127+ for txid in registered_txs {
128+ if let Some ( tx_status) = client. get_tx_status ( & txid) ? {
129+ if tx_status. confirmed {
130+ if let Some ( tx) = client. get_tx ( & txid) ? {
131+ if let Some ( block_height) = tx_status. block_height {
132+ let block_header = client. get_header ( block_height) ?;
133+ if let Some ( merkle_proof) = client. get_merkle_proof ( & txid) ? {
134+ confirmed_txs. push ( (
135+ tx,
136+ block_height,
137+ block_header,
138+ merkle_proof. pos ,
126139 ) ) ;
127- continue ;
128- }
129- }
140+ continue ;
130141 }
131142 }
132143 }
133- unconfirmed_registered_txs. push ( txid) ;
134144 }
145+ }
146+ unconfirmed_registered_txs. push ( txid) ;
147+ }
135148
136- // Check all registered outputs for dependent spending transactions.
137- let registered_outputs: Vec < WatchedOutput > = locked_watched_outputs
138- . iter ( )
139- . chain ( locked_queued_outputs. iter ( ) )
140- . cloned ( )
141- . collect ( ) ;
142-
143- // Remember all registered outputs that haven't been spent for future processing.
144- let mut unspent_registered_outputs = Vec :: new ( ) ;
145-
146- for output in registered_outputs {
147- if let Some ( output_status) = client
148- . get_output_status ( & output. outpoint . txid , output. outpoint . index as u64 ) ?
149- {
150- if output_status. spent {
151- if let Some ( spending_tx_status) = output_status. status {
152- if spending_tx_status. confirmed {
153- let spending_txid = output_status. txid . unwrap ( ) ;
154- if let Some ( spending_tx) = client. get_tx ( & spending_txid) ? {
155- let block_height = spending_tx_status. block_height . unwrap ( ) ;
156- let block_header = client. get_header ( block_height) ?;
157- if let Some ( merkle_proof) =
158- client. get_merkle_proof ( & spending_txid) ?
149+ // Check all registered outputs for dependent spending transactions.
150+ let registered_outputs: Vec < WatchedOutput > = locked_watched_outputs
151+ . iter ( )
152+ . chain ( locked_queued_outputs. iter ( ) )
153+ . cloned ( )
154+ . collect ( ) ;
155+
156+ // Remember all registered outputs that haven't been spent for future processing.
157+ let mut unspent_registered_outputs = Vec :: new ( ) ;
158+
159+ for output in registered_outputs {
160+ if let Some ( output_status) = client
161+ . get_output_status ( & output. outpoint . txid , output. outpoint . index as u64 ) ?
162+ {
163+ if output_status. spent {
164+ if let Some ( spending_tx_status) = output_status. status {
165+ if spending_tx_status. confirmed {
166+ let spending_txid = output_status. txid . unwrap ( ) ;
167+ if let Some ( spending_tx) = client. get_tx ( & spending_txid) ? {
168+ let block_height = spending_tx_status. block_height . unwrap ( ) ;
169+ let block_header = client. get_header ( block_height) ?;
170+ if let Some ( merkle_proof) =
171+ client. get_merkle_proof ( & spending_txid) ?
159172 {
160173 confirmed_txs. push ( (
161- spending_tx,
162- block_height,
163- block_header,
164- merkle_proof. pos ,
165- ) ) ;
174+ spending_tx,
175+ block_height,
176+ block_header,
177+ merkle_proof. pos ,
178+ ) ) ;
166179 continue ;
167180 }
168- }
169181 }
170182 }
171183 }
172184 }
173- unspent_registered_outputs. push ( output) ;
174- }
175-
176- // Sort all confirmed transactions first by block height, then by in-block
177- // position, and finally feed them to the interface in order.
178- confirmed_txs. sort_unstable_by (
179- |( _, block_height1, _, pos1) , ( _, block_height2, _, pos2) | {
180- block_height1. cmp ( & block_height2) . then_with ( || pos1. cmp ( & pos2) )
181- } ,
182- ) ;
183- for ( tx, block_height, block_header, pos) in confirmed_txs {
184- for c in & confirmables {
185- c. transactions_confirmed ( & block_header, & [ ( pos, & tx) ] , block_height) ;
186- }
187185 }
186+ unspent_registered_outputs. push ( output) ;
187+ }
188188
189- * locked_watched_transactions = unconfirmed_registered_txs;
190- * locked_queued_transactions = Vec :: new ( ) ;
191- * locked_watched_outputs = unspent_registered_outputs;
192- * locked_queued_outputs = Vec :: new ( ) ;
189+ // Sort all confirmed transactions first by block height, then by in-block
190+ // position, and finally feed them to the interface in order.
191+ confirmed_txs. sort_unstable_by (
192+ |( _, block_height1, _, pos1) , ( _, block_height2, _, pos2) | {
193+ block_height1. cmp ( & block_height2) . then_with ( || pos1. cmp ( & pos2) )
194+ } ,
195+ ) ;
196+ for ( tx, block_height, block_header, pos) in confirmed_txs {
197+ for c in & confirmables {
198+ c. transactions_confirmed ( & block_header, & [ ( pos, & tx) ] , block_height) ;
193199 }
200+ }
194201
195- {
196- // Query the interface for relevant txids and check whether they have been
197- // reorged-out of the chain.
198- let unconfirmed_txids = confirmables
199- . iter ( )
200- . flat_map ( |c| c. get_relevant_txids ( ) )
201- . filter ( |txid| {
202- client
203- . get_tx_status ( txid)
204- . ok ( )
205- . unwrap_or ( None )
206- . map_or ( true , |status| !status. confirmed )
207- } )
208- . collect :: < Vec < Txid > > ( ) ;
209-
210- // Mark all relevant unconfirmed transactions as unconfirmed.
211- for txid in & unconfirmed_txids {
212- for c in & confirmables {
213- c. transaction_unconfirmed ( txid) ;
214- }
215- }
202+ * locked_watched_transactions = unconfirmed_registered_txs;
203+ * locked_queued_transactions = Vec :: new ( ) ;
204+ * locked_watched_outputs = unspent_registered_outputs;
205+ * locked_queued_outputs = Vec :: new ( ) ;
206+
207+ Ok ( ( ) )
208+ }
209+
210+ fn sync_transaction_unconfirmed ( & self , confirmables : Vec < & ( dyn Confirm + Sync ) > ) -> Result < ( ) , Error > {
211+ let client = & * self . blockchain ;
212+ // Query the interface for relevant txids and check whether they have been
213+ // reorged-out of the chain.
214+ let unconfirmed_txids = confirmables
215+ . iter ( )
216+ . flat_map ( |c| c. get_relevant_txids ( ) )
217+ . filter ( |txid| {
218+ client
219+ . get_tx_status ( txid)
220+ . ok ( )
221+ . unwrap_or ( None )
222+ . map_or ( true , |status| !status. confirmed )
223+ } )
224+ . collect :: < Vec < Txid > > ( ) ;
225+
226+ // Mark all relevant unconfirmed transactions as unconfirmed.
227+ for txid in & unconfirmed_txids {
228+ for c in & confirmables {
229+ c. transaction_unconfirmed ( txid) ;
216230 }
217231 }
218232
219- // TODO: check whether new outputs have been registered by now and process them
220233 Ok ( ( ) )
221234 }
222235
0 commit comments