@@ -2284,7 +2284,7 @@ mod tests {
2284
2284
use rand:: { thread_rng, Rng } ;
2285
2285
2286
2286
use std:: cell:: RefCell ;
2287
- use std:: collections:: HashMap ;
2287
+ use std:: collections:: { BTreeSet , HashMap } ;
2288
2288
use std:: default:: Default ;
2289
2289
use std:: rc:: Rc ;
2290
2290
use std:: sync:: { Arc , Mutex } ;
@@ -3494,6 +3494,74 @@ mod tests {
3494
3494
get_announce_close_broadcast_events ( & nodes, 0 , 1 ) ;
3495
3495
}
3496
3496
3497
+ #[ test]
3498
+ fn claim_htlc_outputs_shared_tx ( ) {
3499
+ // Node revoked old state, htlcs haven't time out yet, claim them in shared justice tx
3500
+ let nodes = create_network ( 2 ) ;
3501
+
3502
+ // Create some new channel:
3503
+ let chan_1 = create_announced_chan_between_nodes ( & nodes, 0 , 1 ) ;
3504
+
3505
+ // Rebalance the network to generate htlc in the two directions
3506
+ send_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] ) [ ..] , 8000000 ) ;
3507
+ // node[0] is gonna to revoke an old state thus node[1] should be able to claim both offered/received HTLC outputs on top of commitment tx
3508
+ let payment_preimage_1 = route_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] ) [ ..] , 3000000 ) . 0 ;
3509
+ let _payment_preimage_2 = route_payment ( & nodes[ 1 ] , & vec ! ( & nodes[ 0 ] ) [ ..] , 3000000 ) . 0 ;
3510
+
3511
+ // Get the will-be-revoked local txn from node[0]
3512
+ let revoked_local_txn = nodes[ 0 ] . node . channel_state . lock ( ) . unwrap ( ) . by_id . get ( & chan_1. 2 ) . unwrap ( ) . last_local_commitment_txn . clone ( ) ;
3513
+ assert_eq ! ( revoked_local_txn. len( ) , 2 ) ; // commitment tx + 1 HTLC-Timeout tx
3514
+ assert_eq ! ( revoked_local_txn[ 0 ] . input. len( ) , 1 ) ;
3515
+ assert_eq ! ( revoked_local_txn[ 0 ] . input[ 0 ] . previous_output. txid, chan_1. 3 . txid( ) ) ;
3516
+ assert_eq ! ( revoked_local_txn[ 1 ] . input. len( ) , 1 ) ;
3517
+ assert_eq ! ( revoked_local_txn[ 1 ] . input[ 0 ] . previous_output. txid, revoked_local_txn[ 0 ] . txid( ) ) ;
3518
+ assert_eq ! ( revoked_local_txn[ 1 ] . input[ 0 ] . witness. last( ) . unwrap( ) . len( ) , 133 ) ; // HTLC-Timeout
3519
+
3520
+ //Revoke the old state
3521
+ claim_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] ) [ ..] , payment_preimage_1) ;
3522
+
3523
+ {
3524
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : Default :: default ( ) , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
3525
+
3526
+ nodes[ 0 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ revoked_local_txn[ 0 ] . clone( ) ] } , 1 ) ;
3527
+
3528
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ revoked_local_txn[ 0 ] . clone( ) ] } , 1 ) ;
3529
+ let node_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
3530
+ assert_eq ! ( node_txn. len( ) , 4 ) ;
3531
+
3532
+ let mut revoked_tx_map = HashMap :: new ( ) ;
3533
+ revoked_tx_map. insert ( revoked_local_txn[ 0 ] . txid ( ) , revoked_local_txn[ 0 ] . clone ( ) ) ;
3534
+
3535
+ assert_eq ! ( node_txn[ 0 ] . input. len( ) , 3 ) ; // Claim the revoked output + both revoked HTLC outputs
3536
+ node_txn[ 0 ] . verify ( & revoked_tx_map) . unwrap ( ) ;
3537
+ assert_eq ! ( node_txn[ 0 ] , node_txn[ 3 ] ) ; // justice tx is duplicated due to block re-scanning
3538
+
3539
+ let mut witness_lens = BTreeSet :: new ( ) ;
3540
+ witness_lens. insert ( node_txn[ 0 ] . input [ 0 ] . witness . last ( ) . unwrap ( ) . len ( ) ) ;
3541
+ witness_lens. insert ( node_txn[ 0 ] . input [ 1 ] . witness . last ( ) . unwrap ( ) . len ( ) ) ;
3542
+ witness_lens. insert ( node_txn[ 0 ] . input [ 2 ] . witness . last ( ) . unwrap ( ) . len ( ) ) ;
3543
+ assert_eq ! ( witness_lens. len( ) , 3 ) ;
3544
+ assert_eq ! ( * witness_lens. iter( ) . skip( 0 ) . next( ) . unwrap( ) , 77 ) ; // revoked to_local
3545
+ assert_eq ! ( * witness_lens. iter( ) . skip( 1 ) . next( ) . unwrap( ) , 133 ) ; // revoked offered HTLC
3546
+ assert_eq ! ( * witness_lens. iter( ) . skip( 2 ) . next( ) . unwrap( ) , 138 ) ; // revoked received HTLC
3547
+
3548
+ // Next nodes[1] broadcasts its current local tx state:
3549
+ assert_eq ! ( node_txn[ 1 ] . input. len( ) , 1 ) ;
3550
+ assert_eq ! ( node_txn[ 1 ] . input[ 0 ] . previous_output. txid, chan_1. 3 . txid( ) ) ; //Spending funding tx unique txouput, tx broadcasted by ChannelManager
3551
+
3552
+ assert_eq ! ( node_txn[ 2 ] . input. len( ) , 1 ) ;
3553
+ let witness_script = node_txn[ 2 ] . clone ( ) . input [ 0 ] . witness . pop ( ) . unwrap ( ) ;
3554
+ assert_eq ! ( witness_script. len( ) , 133 ) ; //Spending an offered htlc output
3555
+ assert_eq ! ( node_txn[ 2 ] . input[ 0 ] . previous_output. txid, node_txn[ 1 ] . txid( ) ) ;
3556
+ assert_ne ! ( node_txn[ 2 ] . input[ 0 ] . previous_output. txid, node_txn[ 0 ] . input[ 0 ] . previous_output. txid) ;
3557
+ assert_ne ! ( node_txn[ 2 ] . input[ 0 ] . previous_output. txid, node_txn[ 0 ] . input[ 1 ] . previous_output. txid) ;
3558
+ }
3559
+ get_announce_close_broadcast_events ( & nodes, 0 , 1 ) ;
3560
+ assert_eq ! ( nodes[ 0 ] . node. list_channels( ) . len( ) , 0 ) ;
3561
+ assert_eq ! ( nodes[ 1 ] . node. list_channels( ) . len( ) , 0 ) ;
3562
+ }
3563
+
3564
+ #[ test]
3497
3565
fn test_htlc_ignore_latest_remote_commitment ( ) {
3498
3566
// Test that HTLC transactions spending the latest remote commitment transaction are simply
3499
3567
// ignored if we cannot claim them. This originally tickled an invalid unwrap().
0 commit comments