11#![ cfg( any( feature = "esplora-blocking" , feature = "esplora-async" ) ) ]
22use 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 } ;
55use lightning:: util:: test_utils:: TestLogger ;
66
77use electrsd:: { bitcoind, bitcoind:: BitcoinD , ElectrsD } ;
@@ -166,8 +166,12 @@ fn test_esplora_syncs() {
166166 assert_eq ! ( events. len( ) , 1 ) ;
167167
168168 // 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 ( ) ;
171175 tx_sync. register_tx ( & txid, & new_address. script_pubkey ( ) ) ;
172176
173177 tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ;
@@ -185,6 +189,29 @@ fn test_esplora_syncs() {
185189 assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & txid) ) ;
186190 assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
187191
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+
188215 // Check previously confirmed transactions are marked unconfirmed when they are reorged.
189216 let best_block_hash = bitcoind. client . get_best_block_hash ( ) . unwrap ( ) ;
190217 bitcoind. client . invalidate_block ( & best_block_hash) . unwrap ( ) ;
@@ -201,32 +228,54 @@ fn test_esplora_syncs() {
201228 assert_ne ! ( bitcoind. client. get_best_block_hash( ) . unwrap( ) , best_block_hash) ;
202229 tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ;
203230
204- // Transaction still confirmed but under new tip.
231+ // Transactions still confirmed but under new tip.
205232 assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & txid) ) ;
233+ assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & second_txid) ) ;
206234 assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
207235
208236 // Check we got unconfirmed, then reconfirmed in the meantime.
237+ let mut seen_txids = HashSet :: new ( ) ;
209238 let events = std:: mem:: take ( & mut * confirmable. events . lock ( ) . unwrap ( ) ) ;
210- assert_eq ! ( events. len( ) , 3 ) ;
239+ assert_eq ! ( events. len( ) , 5 ) ;
211240
212241 match events[ 0 ] {
213242 TestConfirmableEvent :: Unconfirmed ( t) => {
214- assert_eq ! ( t, txid) ;
243+ assert ! ( t == txid || t == second_txid) ;
244+ assert ! ( seen_txids. insert( t) ) ;
215245 } ,
216246 _ => panic ! ( "Unexpected event" ) ,
217247 }
218248
219249 match events[ 1 ] {
220- TestConfirmableEvent :: BestBlockUpdated ( ..) => { } ,
250+ TestConfirmableEvent :: Unconfirmed ( t) => {
251+ assert ! ( t == txid || t == second_txid) ;
252+ assert ! ( seen_txids. insert( t) ) ;
253+ } ,
221254 _ => panic ! ( "Unexpected event" ) ,
222255 }
223256
224257 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 ] {
225271 TestConfirmableEvent :: Confirmed ( t, _, _) => {
226- assert_eq ! ( t, txid) ;
272+ assert ! ( t == txid || t == second_txid) ;
273+ assert ! ( seen_txids. remove( & t) ) ;
227274 } ,
228275 _ => panic ! ( "Unexpected event" ) ,
229276 }
277+
278+ assert_eq ! ( seen_txids. len( ) , 0 ) ;
230279}
231280
232281#[ tokio:: test]
@@ -249,8 +298,12 @@ async fn test_esplora_syncs() {
249298 assert_eq ! ( events. len( ) , 1 ) ;
250299
251300 // 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 ( ) ;
254307 tx_sync. register_tx ( & txid, & new_address. script_pubkey ( ) ) ;
255308
256309 tx_sync. sync ( vec ! [ & confirmable] ) . await . unwrap ( ) ;
@@ -268,6 +321,29 @@ async fn test_esplora_syncs() {
268321 assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & txid) ) ;
269322 assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
270323
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+
271347 // Check previously confirmed transactions are marked unconfirmed when they are reorged.
272348 let best_block_hash = bitcoind. client . get_best_block_hash ( ) . unwrap ( ) ;
273349 bitcoind. client . invalidate_block ( & best_block_hash) . unwrap ( ) ;
@@ -284,30 +360,52 @@ async fn test_esplora_syncs() {
284360 assert_ne ! ( bitcoind. client. get_best_block_hash( ) . unwrap( ) , best_block_hash) ;
285361 tx_sync. sync ( vec ! [ & confirmable] ) . await . unwrap ( ) ;
286362
287- // Transaction still confirmed but under new tip.
363+ // Transactions still confirmed but under new tip.
288364 assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & txid) ) ;
365+ assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & second_txid) ) ;
289366 assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
290367
291368 // Check we got unconfirmed, then reconfirmed in the meantime.
369+ let mut seen_txids = HashSet :: new ( ) ;
292370 let events = std:: mem:: take ( & mut * confirmable. events . lock ( ) . unwrap ( ) ) ;
293- assert_eq ! ( events. len( ) , 3 ) ;
371+ assert_eq ! ( events. len( ) , 5 ) ;
294372
295373 match events[ 0 ] {
296374 TestConfirmableEvent :: Unconfirmed ( t) => {
297- assert_eq ! ( t, txid) ;
375+ assert ! ( t == txid || t == second_txid) ;
376+ assert ! ( seen_txids. insert( t) ) ;
298377 } ,
299378 _ => panic ! ( "Unexpected event" ) ,
300379 }
301380
302381 match events[ 1 ] {
303- TestConfirmableEvent :: BestBlockUpdated ( ..) => { } ,
382+ TestConfirmableEvent :: Unconfirmed ( t) => {
383+ assert ! ( t == txid || t == second_txid) ;
384+ assert ! ( seen_txids. insert( t) ) ;
385+ } ,
304386 _ => panic ! ( "Unexpected event" ) ,
305387 }
306388
307389 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 ] {
308403 TestConfirmableEvent :: Confirmed ( t, _, _) => {
309- assert_eq ! ( t, txid) ;
404+ assert ! ( t == txid || t == second_txid) ;
405+ assert ! ( seen_txids. remove( & t) ) ;
310406 } ,
311407 _ => panic ! ( "Unexpected event" ) ,
312408 }
409+
410+ assert_eq ! ( seen_txids. len( ) , 0 ) ;
313411}
0 commit comments