@@ -13,10 +13,15 @@ use lightning::{log_debug, log_error, log_trace};
13
13
use bitcoin:: block:: Header ;
14
14
use bitcoin:: { BlockHash , Script , Transaction , Txid } ;
15
15
16
+ use bitcoin:: hashes:: Hash as BitcoinHash ;
17
+ use electrum_client:: bitcoin:: hashes:: Hash as ElectrumHash ;
18
+
16
19
use std:: collections:: HashSet ;
17
20
use std:: ops:: Deref ;
18
21
use std:: sync:: Mutex ;
19
22
use std:: time:: Instant ;
23
+ use bitcoin:: consensus:: { Decodable as BitcoinDecodable , Encodable as BitcoinEncodable } ;
24
+ use electrum_client:: bitcoin:: consensus:: { Decodable as ElectrumDecodable , Encodable as ElectrumEncodable } ;
20
25
21
26
/// Synchronizes LDK with a given Electrum server.
22
27
///
97
102
98
103
loop {
99
104
let pending_registrations = self . queue . lock ( ) . unwrap ( ) . process_queues ( & mut sync_state) ;
100
- let tip_is_new = Some ( tip_header. block_hash ( ) ) != sync_state. last_sync_hash ;
105
+ let tip_is_new = Some ( tip_header. block_hash ( ) ) != sync_state. last_sync_hash . map ( |h| electrum_client :: bitcoin :: BlockHash :: from_slice ( h . as_ref ( ) ) . unwrap ( ) ) ;
101
106
102
107
// We loop until any registered transactions have been processed at least once, or the
103
108
// tip hasn't been updated during the last iteration.
@@ -112,7 +117,14 @@ where
112
117
Ok ( unconfirmed_txs) => {
113
118
// Double-check the tip hash. If it changed, a reorg happened since
114
119
// we started syncing and we need to restart last-minute.
115
- match self . check_update_tip ( & mut tip_header, & mut tip_height) {
120
+
121
+ let mut header_buffer = Vec :: new ( ) ;
122
+ tip_header. consensus_encode ( & mut header_buffer) . unwrap ( ) ;
123
+ let mut header_slice = & header_buffer[ ..] ;
124
+ let header_reader = & mut lightning:: util:: ser:: BufReader :: < _ , 4096 > :: new ( & mut header_slice) ;
125
+ let mut bitcoin_header = bitcoin:: block:: Header :: consensus_decode ( header_reader) . unwrap ( ) ;
126
+
127
+ match self . check_update_tip ( & mut bitcoin_header, & mut tip_height) {
116
128
Ok ( false ) => {
117
129
num_unconfirmed += unconfirmed_txs. len ( ) ;
118
130
sync_state. sync_unconfirmed_transactions (
@@ -150,9 +162,15 @@ where
150
162
} ,
151
163
}
152
164
165
+ let mut header_buffer = Vec :: new ( ) ;
166
+ tip_header. consensus_encode ( & mut header_buffer) . unwrap ( ) ;
167
+ let mut header_slice = & header_buffer[ ..] ;
168
+ let header_reader = & mut lightning:: util:: ser:: BufReader :: < _ , 4096 > :: new ( & mut header_slice) ;
169
+ let bitcoin_header = bitcoin:: block:: Header :: consensus_decode ( header_reader) . unwrap ( ) ;
170
+
153
171
// Update the best block.
154
172
for c in & confirmables {
155
- c. best_block_updated ( & tip_header , tip_height) ;
173
+ c. best_block_updated ( & bitcoin_header , tip_height) ;
156
174
}
157
175
158
176
// Prune any sufficiently confirmed output spends
@@ -161,9 +179,16 @@ where
161
179
162
180
match self . get_confirmed_transactions ( & sync_state) {
163
181
Ok ( confirmed_txs) => {
182
+
183
+ let mut header_buffer = Vec :: new ( ) ;
184
+ tip_header. consensus_encode ( & mut header_buffer) . unwrap ( ) ;
185
+ let mut header_slice = & header_buffer[ ..] ;
186
+ let header_reader = & mut lightning:: util:: ser:: BufReader :: < _ , 4096 > :: new ( & mut header_slice) ;
187
+ let mut bitcoin_header = bitcoin:: block:: Header :: consensus_decode ( header_reader) . unwrap ( ) ;
188
+
164
189
// Double-check the tip hash. If it changed, a reorg happened since
165
190
// we started syncing and we need to restart last-minute.
166
- match self . check_update_tip ( & mut tip_header , & mut tip_height) {
191
+ match self . check_update_tip ( & mut bitcoin_header , & mut tip_height) {
167
192
Ok ( false ) => {
168
193
num_confirmed += confirmed_txs. len ( ) ;
169
194
sync_state
@@ -207,7 +232,7 @@ where
207
232
return Err ( TxSyncError :: from ( err) ) ;
208
233
} ,
209
234
}
210
- sync_state. last_sync_hash = Some ( tip_header. block_hash ( ) ) ;
235
+ sync_state. last_sync_hash = Some ( bitcoin :: BlockHash :: from_slice ( tip_header. block_hash ( ) . as_ref ( ) ) . unwrap ( ) ) ;
211
236
sync_state. pending_sync = false ;
212
237
}
213
238
}
@@ -240,15 +265,21 @@ where
240
265
// Restart if either the tip changed or we got some divergent tip
241
266
// change notification since we started. In the latter case we
242
267
// make sure we clear the queue before continuing.
243
- let mut restart_sync = check_tip_hash != cur_tip_header. block_hash ( ) ;
268
+ let mut restart_sync = check_tip_hash != electrum_client :: bitcoin :: BlockHash :: from_slice ( cur_tip_header. block_hash ( ) . as_ref ( ) ) . unwrap ( ) ;
244
269
while let Some ( queued_notif) = self . client . block_headers_pop ( ) ? {
245
270
if queued_notif. header . block_hash ( ) != check_tip_hash {
246
271
restart_sync = true
247
272
}
248
273
}
249
274
250
275
if restart_sync {
251
- * cur_tip_header = check_notification. header ;
276
+ let mut header_buffer = Vec :: new ( ) ;
277
+ check_notification. header . consensus_encode ( & mut header_buffer) . unwrap ( ) ;
278
+ let mut header_slice = & header_buffer[ ..] ;
279
+ let header_reader = & mut lightning:: util:: ser:: BufReader :: < _ , 4096 > :: new ( & mut header_slice) ;
280
+ let bitcoin_header = bitcoin:: block:: Header :: consensus_decode ( header_reader) . unwrap ( ) ;
281
+
282
+ * cur_tip_header = bitcoin_header;
252
283
* cur_tip_height = check_notification. height as u32 ;
253
284
Ok ( true )
254
285
} else {
@@ -268,7 +299,7 @@ where
268
299
let mut watched_txs = Vec :: with_capacity ( sync_state. watched_transactions . len ( ) ) ;
269
300
270
301
for txid in & sync_state. watched_transactions {
271
- match self . client . transaction_get ( & txid) {
302
+ match self . client . transaction_get ( & electrum_client :: bitcoin :: Txid :: from_slice ( txid. as_ref ( ) ) . unwrap ( ) ) {
272
303
Ok ( tx) => {
273
304
watched_txs. push ( ( txid, tx. clone ( ) ) ) ;
274
305
if let Some ( tx_out) = tx. output . first ( ) {
@@ -296,7 +327,7 @@ where
296
327
debug_assert_eq ! ( num_tx_lookups, watched_txs. len( ) ) ;
297
328
298
329
for output in sync_state. watched_outputs . values ( ) {
299
- watched_script_pubkeys. push ( output. script_pubkey . clone ( ) ) ;
330
+ watched_script_pubkeys. push ( electrum_client :: bitcoin :: ScriptBuf :: from_bytes ( output. script_pubkey . to_bytes ( ) ) ) ;
300
331
}
301
332
302
333
let num_output_spend_lookups = watched_script_pubkeys. len ( ) - num_tx_lookups;
@@ -314,10 +345,17 @@ where
314
345
continue ;
315
346
}
316
347
let mut filtered_history =
317
- script_history. iter ( ) . filter ( |h| h. tx_hash == * * txid) ;
348
+ script_history. iter ( ) . filter ( |h| h. tx_hash == electrum_client :: bitcoin :: Txid :: from_slice ( txid. as_ref ( ) ) . unwrap ( ) ) ;
318
349
if let Some ( history) = filtered_history. next ( ) {
350
+
351
+ let mut tx_buffer = Vec :: new ( ) ;
352
+ tx. consensus_encode ( & mut tx_buffer) . unwrap ( ) ;
353
+ let mut tx_slice = & tx_buffer[ ..] ;
354
+ let tx_reader = & mut lightning:: util:: ser:: BufReader :: < _ , 4096 > :: new ( & mut tx_slice) ;
355
+ let bitcoin_transaction = bitcoin:: Transaction :: consensus_decode ( tx_reader) . unwrap ( ) ;
356
+
319
357
let prob_conf_height = history. height as u32 ;
320
- let confirmed_tx = self . get_confirmed_tx ( tx , prob_conf_height) ?;
358
+ let confirmed_tx = self . get_confirmed_tx ( & bitcoin_transaction , prob_conf_height) ?;
321
359
confirmed_txs. push ( confirmed_tx) ;
322
360
}
323
361
debug_assert ! ( filtered_history. next( ) . is_none( ) ) ;
@@ -332,7 +370,7 @@ where
332
370
}
333
371
334
372
let txid = possible_output_spend. tx_hash ;
335
- if confirmed_txs. iter ( ) . any ( |ctx| ctx. txid == txid) {
373
+ if confirmed_txs. iter ( ) . any ( |ctx| ctx. txid == bitcoin :: Txid :: from_slice ( txid. as_ref ( ) ) . unwrap ( ) ) {
336
374
continue ;
337
375
}
338
376
@@ -342,7 +380,13 @@ where
342
380
for txin in & tx. input {
343
381
let watched_outpoint =
344
382
watched_output. outpoint . into_bitcoin_outpoint ( ) ;
345
- if txin. previous_output == watched_outpoint {
383
+
384
+ let mut outpoint_buffer = Vec :: new ( ) ;
385
+ watched_outpoint. consensus_encode ( & mut outpoint_buffer) . unwrap ( ) ;
386
+ let mut outpoint_slice = & outpoint_buffer[ ..] ;
387
+ let esplora_outpoint = electrum_client:: bitcoin:: OutPoint :: consensus_decode ( & mut outpoint_slice) . unwrap ( ) ;
388
+
389
+ if txin. previous_output == esplora_outpoint {
346
390
is_spend = true ;
347
391
break ;
348
392
}
@@ -353,7 +397,14 @@ where
353
397
}
354
398
355
399
let prob_conf_height = possible_output_spend. height as u32 ;
356
- let confirmed_tx = self . get_confirmed_tx ( & tx, prob_conf_height) ?;
400
+
401
+ let mut tx_buffer = Vec :: new ( ) ;
402
+ tx. consensus_encode ( & mut tx_buffer) . unwrap ( ) ;
403
+ let mut tx_slice = & tx_buffer[ ..] ;
404
+ let tx_reader = & mut lightning:: util:: ser:: BufReader :: < _ , 4096 > :: new ( & mut tx_slice) ;
405
+ let bitcoin_transaction = bitcoin:: Transaction :: consensus_decode ( tx_reader) . unwrap ( ) ;
406
+
407
+ let confirmed_tx = self . get_confirmed_tx ( & bitcoin_transaction, prob_conf_height) ?;
357
408
confirmed_txs. push ( confirmed_tx) ;
358
409
} ,
359
410
Err ( e) => {
@@ -402,7 +453,7 @@ where
402
453
for ( txid, conf_height, block_hash_opt) in relevant_txids {
403
454
if let Some ( block_hash) = block_hash_opt {
404
455
let block_header = self . client . block_header ( conf_height as usize ) ?;
405
- if block_header. block_hash ( ) == block_hash {
456
+ if block_header. block_hash ( ) == electrum_client :: bitcoin :: BlockHash :: from_slice ( block_hash. as_ref ( ) ) . unwrap ( ) {
406
457
// Skip if the tx is still confirmed in the block in question.
407
458
continue ;
408
459
}
@@ -421,24 +472,31 @@ where
421
472
& self , tx : & Transaction , prob_conf_height : u32 ,
422
473
) -> Result < ConfirmedTx , InternalError > {
423
474
let txid = tx. txid ( ) ;
424
- match self . client . transaction_get_merkle ( & txid, prob_conf_height as usize ) {
475
+ match self . client . transaction_get_merkle ( & electrum_client :: bitcoin :: Txid :: from_slice ( txid. as_ref ( ) ) . unwrap ( ) , prob_conf_height as usize ) {
425
476
Ok ( merkle_res) => {
426
477
debug_assert_eq ! ( prob_conf_height, merkle_res. block_height as u32 ) ;
427
478
match self . client . block_header ( prob_conf_height as usize ) {
428
479
Ok ( block_header) => {
429
480
let pos = merkle_res. pos ;
430
- if !validate_merkle_proof ( & txid, & block_header. merkle_root , & merkle_res) {
481
+ if !validate_merkle_proof ( & electrum_client :: bitcoin :: Txid :: from_slice ( txid. as_ref ( ) ) . unwrap ( ) , & block_header. merkle_root , & merkle_res) {
431
482
log_trace ! (
432
483
self . logger,
433
484
"Inconsistency: Block {} was unconfirmed during syncing." ,
434
485
block_header. block_hash( )
435
486
) ;
436
487
return Err ( InternalError :: Inconsistency ) ;
437
488
}
489
+
490
+ let mut header_buffer = Vec :: new ( ) ;
491
+ block_header. consensus_encode ( & mut header_buffer) . unwrap ( ) ;
492
+ let mut header_slice = & header_buffer[ ..] ;
493
+ let header_reader = & mut lightning:: util:: ser:: BufReader :: < _ , 4096 > :: new ( & mut header_slice) ;
494
+ let bitcoin_header = bitcoin:: block:: Header :: consensus_decode ( header_reader) . unwrap ( ) ;
495
+
438
496
let confirmed_tx = ConfirmedTx {
439
497
tx : tx. clone ( ) ,
440
498
txid,
441
- block_header,
499
+ block_header : bitcoin_header ,
442
500
block_height : prob_conf_height,
443
501
pos,
444
502
} ;
0 commit comments