1
1
#![ cfg( any( feature = "esplora-blocking" , feature = "esplora-async" ) ) ]
2
2
use lightning_transaction_sync:: EsploraSyncClient ;
3
- use lightning:: chain:: { Confirm , Filter } ;
4
- use lightning:: chain:: transaction:: TransactionData ;
3
+ use lightning:: chain:: { Confirm , Filter , WatchedOutput } ;
4
+ use lightning:: chain:: transaction:: { OutPoint , TransactionData } ;
5
5
use lightning:: util:: test_utils:: TestLogger ;
6
6
7
7
use electrsd:: { bitcoind, bitcoind:: BitcoinD , ElectrsD } ;
@@ -166,8 +166,12 @@ fn test_esplora_syncs() {
166
166
assert_eq ! ( events. len( ) , 1 ) ;
167
167
168
168
// Check registered confirmed transactions are marked confirmed
169
- let new_address = bitcoind. client . get_new_address ( Some ( "test" ) , Some ( AddressType :: Legacy ) ) . unwrap ( ) ;
170
- let txid = bitcoind. client . send_to_address ( & new_address, Amount :: from_sat ( 5000 ) , None , None , None , None , None , None ) . unwrap ( ) ;
169
+ let new_address = bitcoind. client . get_new_address ( Some ( "test" ) ,
170
+ Some ( AddressType :: Legacy ) ) . unwrap ( ) ;
171
+ let txid = bitcoind. client . send_to_address ( & new_address, Amount :: from_sat ( 5000 ) , None , None ,
172
+ None , None , None , None ) . unwrap ( ) ;
173
+ let second_txid = bitcoind. client . send_to_address ( & new_address, Amount :: from_sat ( 5000 ) , None ,
174
+ None , None , None , None , None ) . unwrap ( ) ;
171
175
tx_sync. register_tx ( & txid, & new_address. script_pubkey ( ) ) ;
172
176
173
177
tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ;
@@ -185,6 +189,29 @@ fn test_esplora_syncs() {
185
189
assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & txid) ) ;
186
190
assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
187
191
192
+ // Now take an arbitrary output of the second transaction and check we'll confirm its spend.
193
+ let tx_res = bitcoind. client . get_transaction ( & second_txid, None ) . unwrap ( ) ;
194
+ let block_hash = tx_res. info . blockhash . unwrap ( ) ;
195
+ let tx = tx_res. transaction ( ) . unwrap ( ) ;
196
+ let prev_outpoint = tx. input . first ( ) . unwrap ( ) . previous_output ;
197
+ let prev_tx = bitcoind. client . get_transaction ( & prev_outpoint. txid , None ) . unwrap ( ) . transaction ( )
198
+ . unwrap ( ) ;
199
+ let prev_script_pubkey = prev_tx. output [ prev_outpoint. vout as usize ] . script_pubkey . clone ( ) ;
200
+ let output = WatchedOutput {
201
+ block_hash : Some ( block_hash) ,
202
+ outpoint : OutPoint { txid : prev_outpoint. txid , index : prev_outpoint. vout as u16 } ,
203
+ script_pubkey : prev_script_pubkey
204
+ } ;
205
+
206
+ tx_sync. register_output ( output) ;
207
+ tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ;
208
+
209
+ let events = std:: mem:: take ( & mut * confirmable. events . lock ( ) . unwrap ( ) ) ;
210
+ assert_eq ! ( events. len( ) , 1 ) ;
211
+ assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & second_txid) ) ;
212
+ assert_eq ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . len( ) , 2 ) ;
213
+ assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
214
+
188
215
// Check previously confirmed transactions are marked unconfirmed when they are reorged.
189
216
let best_block_hash = bitcoind. client . get_best_block_hash ( ) . unwrap ( ) ;
190
217
bitcoind. client . invalidate_block ( & best_block_hash) . unwrap ( ) ;
@@ -201,32 +228,54 @@ fn test_esplora_syncs() {
201
228
assert_ne ! ( bitcoind. client. get_best_block_hash( ) . unwrap( ) , best_block_hash) ;
202
229
tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ;
203
230
204
- // Transaction still confirmed but under new tip.
231
+ // Transactions still confirmed but under new tip.
205
232
assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & txid) ) ;
233
+ assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & second_txid) ) ;
206
234
assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
207
235
208
236
// Check we got unconfirmed, then reconfirmed in the meantime.
237
+ let mut seen_txids = HashSet :: new ( ) ;
209
238
let events = std:: mem:: take ( & mut * confirmable. events . lock ( ) . unwrap ( ) ) ;
210
- assert_eq ! ( events. len( ) , 3 ) ;
239
+ assert_eq ! ( events. len( ) , 5 ) ;
211
240
212
241
match events[ 0 ] {
213
242
TestConfirmableEvent :: Unconfirmed ( t) => {
214
- assert_eq ! ( t, txid) ;
243
+ assert ! ( t == txid || t == second_txid) ;
244
+ assert ! ( seen_txids. insert( t) ) ;
215
245
} ,
216
246
_ => panic ! ( "Unexpected event" ) ,
217
247
}
218
248
219
249
match events[ 1 ] {
220
- TestConfirmableEvent :: BestBlockUpdated ( ..) => { } ,
250
+ TestConfirmableEvent :: Unconfirmed ( t) => {
251
+ assert ! ( t == txid || t == second_txid) ;
252
+ assert ! ( seen_txids. insert( t) ) ;
253
+ } ,
221
254
_ => panic ! ( "Unexpected event" ) ,
222
255
}
223
256
224
257
match events[ 2 ] {
258
+ TestConfirmableEvent :: BestBlockUpdated ( ..) => { } ,
259
+ _ => panic ! ( "Unexpected event" ) ,
260
+ }
261
+
262
+ match events[ 3 ] {
263
+ TestConfirmableEvent :: Confirmed ( t, _, _) => {
264
+ assert ! ( t == txid || t == second_txid) ;
265
+ assert ! ( seen_txids. remove( & t) ) ;
266
+ } ,
267
+ _ => panic ! ( "Unexpected event" ) ,
268
+ }
269
+
270
+ match events[ 4 ] {
225
271
TestConfirmableEvent :: Confirmed ( t, _, _) => {
226
- assert_eq ! ( t, txid) ;
272
+ assert ! ( t == txid || t == second_txid) ;
273
+ assert ! ( seen_txids. remove( & t) ) ;
227
274
} ,
228
275
_ => panic ! ( "Unexpected event" ) ,
229
276
}
277
+
278
+ assert_eq ! ( seen_txids. len( ) , 0 ) ;
230
279
}
231
280
232
281
#[ tokio:: test]
@@ -249,8 +298,12 @@ async fn test_esplora_syncs() {
249
298
assert_eq ! ( events. len( ) , 1 ) ;
250
299
251
300
// Check registered confirmed transactions are marked confirmed
252
- let new_address = bitcoind. client . get_new_address ( Some ( "test" ) , Some ( AddressType :: Legacy ) ) . unwrap ( ) ;
253
- let txid = bitcoind. client . send_to_address ( & new_address, Amount :: from_sat ( 5000 ) , None , None , None , None , None , None ) . unwrap ( ) ;
301
+ let new_address = bitcoind. client . get_new_address ( Some ( "test" ) ,
302
+ Some ( AddressType :: Legacy ) ) . unwrap ( ) ;
303
+ let txid = bitcoind. client . send_to_address ( & new_address, Amount :: from_sat ( 5000 ) , None , None ,
304
+ None , None , None , None ) . unwrap ( ) ;
305
+ let second_txid = bitcoind. client . send_to_address ( & new_address, Amount :: from_sat ( 5000 ) , None ,
306
+ None , None , None , None , None ) . unwrap ( ) ;
254
307
tx_sync. register_tx ( & txid, & new_address. script_pubkey ( ) ) ;
255
308
256
309
tx_sync. sync ( vec ! [ & confirmable] ) . await . unwrap ( ) ;
@@ -268,6 +321,29 @@ async fn test_esplora_syncs() {
268
321
assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & txid) ) ;
269
322
assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
270
323
324
+ // Now take an arbitrary output of the second transaction and check we'll confirm its spend.
325
+ let tx_res = bitcoind. client . get_transaction ( & second_txid, None ) . unwrap ( ) ;
326
+ let block_hash = tx_res. info . blockhash . unwrap ( ) ;
327
+ let tx = tx_res. transaction ( ) . unwrap ( ) ;
328
+ let prev_outpoint = tx. input . first ( ) . unwrap ( ) . previous_output ;
329
+ let prev_tx = bitcoind. client . get_transaction ( & prev_outpoint. txid , None ) . unwrap ( ) . transaction ( )
330
+ . unwrap ( ) ;
331
+ let prev_script_pubkey = prev_tx. output [ prev_outpoint. vout as usize ] . script_pubkey . clone ( ) ;
332
+ let output = WatchedOutput {
333
+ block_hash : Some ( block_hash) ,
334
+ outpoint : OutPoint { txid : prev_outpoint. txid , index : prev_outpoint. vout as u16 } ,
335
+ script_pubkey : prev_script_pubkey
336
+ } ;
337
+
338
+ tx_sync. register_output ( output) ;
339
+ tx_sync. sync ( vec ! [ & confirmable] ) . await . unwrap ( ) ;
340
+
341
+ let events = std:: mem:: take ( & mut * confirmable. events . lock ( ) . unwrap ( ) ) ;
342
+ assert_eq ! ( events. len( ) , 1 ) ;
343
+ assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & second_txid) ) ;
344
+ assert_eq ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . len( ) , 2 ) ;
345
+ assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
346
+
271
347
// Check previously confirmed transactions are marked unconfirmed when they are reorged.
272
348
let best_block_hash = bitcoind. client . get_best_block_hash ( ) . unwrap ( ) ;
273
349
bitcoind. client . invalidate_block ( & best_block_hash) . unwrap ( ) ;
@@ -284,30 +360,52 @@ async fn test_esplora_syncs() {
284
360
assert_ne ! ( bitcoind. client. get_best_block_hash( ) . unwrap( ) , best_block_hash) ;
285
361
tx_sync. sync ( vec ! [ & confirmable] ) . await . unwrap ( ) ;
286
362
287
- // Transaction still confirmed but under new tip.
363
+ // Transactions still confirmed but under new tip.
288
364
assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & txid) ) ;
365
+ assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & second_txid) ) ;
289
366
assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
290
367
291
368
// Check we got unconfirmed, then reconfirmed in the meantime.
369
+ let mut seen_txids = HashSet :: new ( ) ;
292
370
let events = std:: mem:: take ( & mut * confirmable. events . lock ( ) . unwrap ( ) ) ;
293
- assert_eq ! ( events. len( ) , 3 ) ;
371
+ assert_eq ! ( events. len( ) , 5 ) ;
294
372
295
373
match events[ 0 ] {
296
374
TestConfirmableEvent :: Unconfirmed ( t) => {
297
- assert_eq ! ( t, txid) ;
375
+ assert ! ( t == txid || t == second_txid) ;
376
+ assert ! ( seen_txids. insert( t) ) ;
298
377
} ,
299
378
_ => panic ! ( "Unexpected event" ) ,
300
379
}
301
380
302
381
match events[ 1 ] {
303
- TestConfirmableEvent :: BestBlockUpdated ( ..) => { } ,
382
+ TestConfirmableEvent :: Unconfirmed ( t) => {
383
+ assert ! ( t == txid || t == second_txid) ;
384
+ assert ! ( seen_txids. insert( t) ) ;
385
+ } ,
304
386
_ => panic ! ( "Unexpected event" ) ,
305
387
}
306
388
307
389
match events[ 2 ] {
390
+ TestConfirmableEvent :: BestBlockUpdated ( ..) => { } ,
391
+ _ => panic ! ( "Unexpected event" ) ,
392
+ }
393
+
394
+ match events[ 3 ] {
395
+ TestConfirmableEvent :: Confirmed ( t, _, _) => {
396
+ assert ! ( t == txid || t == second_txid) ;
397
+ assert ! ( seen_txids. remove( & t) ) ;
398
+ } ,
399
+ _ => panic ! ( "Unexpected event" ) ,
400
+ }
401
+
402
+ match events[ 4 ] {
308
403
TestConfirmableEvent :: Confirmed ( t, _, _) => {
309
- assert_eq ! ( t, txid) ;
404
+ assert ! ( t == txid || t == second_txid) ;
405
+ assert ! ( seen_txids. remove( & t) ) ;
310
406
} ,
311
407
_ => panic ! ( "Unexpected event" ) ,
312
408
}
409
+
410
+ assert_eq ! ( seen_txids. len( ) , 0 ) ;
313
411
}
0 commit comments