@@ -17,7 +17,7 @@ use bdk::{SignOptions, SyncOptions};
17
17
use bitcoin:: { BlockHash , Script , Transaction , Txid } ;
18
18
19
19
use std:: collections:: HashSet ;
20
- use std:: sync:: { Arc , Mutex } ;
20
+ use std:: sync:: { Arc , Mutex , MutexGuard } ;
21
21
22
22
/// The minimum feerate we are allowed to send, as specify by LDK.
23
23
const MIN_FEERATE : u32 = 253 ;
@@ -80,143 +80,156 @@ where
80
80
81
81
let mut locked_last_sync_height = self . last_sync_height . lock ( ) . unwrap ( ) ;
82
82
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
+ }
89
90
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 ;
92
93
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 ,
126
139
) ) ;
127
- continue ;
128
- }
129
- }
140
+ continue ;
130
141
}
131
142
}
132
143
}
133
- unconfirmed_registered_txs. push ( txid) ;
134
144
}
145
+ }
146
+ unconfirmed_registered_txs. push ( txid) ;
147
+ }
135
148
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) ?
159
172
{
160
173
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
+ ) ) ;
166
179
continue ;
167
180
}
168
- }
169
181
}
170
182
}
171
183
}
172
184
}
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
- }
187
185
}
186
+ unspent_registered_outputs. push ( output) ;
187
+ }
188
188
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) ;
193
199
}
200
+ }
194
201
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) ;
216
230
}
217
231
}
218
232
219
- // TODO: check whether new outputs have been registered by now and process them
220
233
Ok ( ( ) )
221
234
}
222
235
0 commit comments