@@ -3561,6 +3561,79 @@ mod tests {
3561
3561
assert_eq ! ( nodes[ 1 ] . node. list_channels( ) . len( ) , 0 ) ;
3562
3562
}
3563
3563
3564
+ #[ test]
3565
+ fn claim_htlc_outputs_single_tx ( ) {
3566
+ // Node revoked old state, htlcs have timed out, claim each of them in separated justice tx
3567
+ let nodes = create_network ( 2 ) ;
3568
+
3569
+ let chan_1 = create_announced_chan_between_nodes ( & nodes, 0 , 1 ) ;
3570
+
3571
+ // Rebalance the network to generate htlc in the two directions
3572
+ send_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] ) [ ..] , 8000000 ) ;
3573
+ // 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, but this
3574
+ // time as two different claim transactions as we're gonna to timeout htlc with given a high current height
3575
+ let payment_preimage_1 = route_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] ) [ ..] , 3000000 ) . 0 ;
3576
+ let _payment_preimage_2 = route_payment ( & nodes[ 1 ] , & vec ! ( & nodes[ 0 ] ) [ ..] , 3000000 ) . 0 ;
3577
+
3578
+ // Get the will-be-revoked local txn from node[0]
3579
+ let revoked_local_txn = nodes[ 0 ] . node . channel_state . lock ( ) . unwrap ( ) . by_id . get ( & chan_1. 2 ) . unwrap ( ) . last_local_commitment_txn . clone ( ) ;
3580
+
3581
+ //Revoke the old state
3582
+ claim_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] ) [ ..] , payment_preimage_1) ;
3583
+
3584
+ {
3585
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : Default :: default ( ) , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
3586
+
3587
+ nodes[ 0 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ revoked_local_txn[ 0 ] . clone( ) ] } , 200 ) ;
3588
+
3589
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ revoked_local_txn[ 0 ] . clone( ) ] } , 200 ) ;
3590
+ let node_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
3591
+ assert_eq ! ( node_txn. len( ) , 12 ) ; // ChannelManager : 2, ChannelMontitor: 8 (1 standard revoked output, 2 revocation htlc tx, 1 local commitment tx + 1 htlc timeout tx) * 2 (block-rescan)
3592
+
3593
+ assert_eq ! ( node_txn[ 0 ] , node_txn[ 7 ] ) ;
3594
+ assert_eq ! ( node_txn[ 1 ] , node_txn[ 8 ] ) ;
3595
+ assert_eq ! ( node_txn[ 2 ] , node_txn[ 9 ] ) ;
3596
+ assert_eq ! ( node_txn[ 3 ] , node_txn[ 10 ] ) ;
3597
+ assert_eq ! ( node_txn[ 4 ] , node_txn[ 11 ] ) ;
3598
+ assert_eq ! ( node_txn[ 3 ] , node_txn[ 5 ] ) ; //local commitment tx + htlc timeout tx broadcated by ChannelManger
3599
+ assert_eq ! ( node_txn[ 4 ] , node_txn[ 6 ] ) ;
3600
+
3601
+ assert_eq ! ( node_txn[ 0 ] . input. len( ) , 1 ) ;
3602
+ assert_eq ! ( node_txn[ 1 ] . input. len( ) , 1 ) ;
3603
+ assert_eq ! ( node_txn[ 2 ] . input. len( ) , 1 ) ;
3604
+
3605
+ let mut revoked_tx_map = HashMap :: new ( ) ;
3606
+ revoked_tx_map. insert ( revoked_local_txn[ 0 ] . txid ( ) , revoked_local_txn[ 0 ] . clone ( ) ) ;
3607
+ node_txn[ 0 ] . verify ( & revoked_tx_map) . unwrap ( ) ;
3608
+ node_txn[ 1 ] . verify ( & revoked_tx_map) . unwrap ( ) ;
3609
+ node_txn[ 2 ] . verify ( & revoked_tx_map) . unwrap ( ) ;
3610
+
3611
+ let mut witness_lens = BTreeSet :: new ( ) ;
3612
+ witness_lens. insert ( node_txn[ 0 ] . input [ 0 ] . witness . last ( ) . unwrap ( ) . len ( ) ) ;
3613
+ witness_lens. insert ( node_txn[ 1 ] . input [ 0 ] . witness . last ( ) . unwrap ( ) . len ( ) ) ;
3614
+ witness_lens. insert ( node_txn[ 2 ] . input [ 0 ] . witness . last ( ) . unwrap ( ) . len ( ) ) ;
3615
+ assert_eq ! ( witness_lens. len( ) , 3 ) ;
3616
+ assert_eq ! ( * witness_lens. iter( ) . skip( 0 ) . next( ) . unwrap( ) , 77 ) ; // revoked to_local
3617
+ assert_eq ! ( * witness_lens. iter( ) . skip( 1 ) . next( ) . unwrap( ) , 133 ) ; // revoked offered HTLC
3618
+ assert_eq ! ( * witness_lens. iter( ) . skip( 2 ) . next( ) . unwrap( ) , 138 ) ; // revoked received HTLC
3619
+
3620
+ let mut funding_tx_map = HashMap :: new ( ) ;
3621
+ funding_tx_map. insert ( chan_1. 3 . txid ( ) , chan_1. 3 . clone ( ) ) ;
3622
+ node_txn[ 3 ] . verify ( & funding_tx_map) . unwrap ( ) ;
3623
+ assert_eq ! ( node_txn[ 3 ] . input. len( ) , 1 ) ;
3624
+
3625
+ assert_eq ! ( node_txn[ 4 ] . input. len( ) , 1 ) ;
3626
+ let witness_script = node_txn[ 4 ] . input [ 0 ] . witness . last ( ) . unwrap ( ) ;
3627
+ assert_eq ! ( witness_script. len( ) , 133 ) ; //Spending an offered htlc output
3628
+ assert_eq ! ( node_txn[ 4 ] . input[ 0 ] . previous_output. txid, node_txn[ 3 ] . txid( ) ) ;
3629
+ assert_ne ! ( node_txn[ 4 ] . input[ 0 ] . previous_output. txid, node_txn[ 0 ] . input[ 0 ] . previous_output. txid) ;
3630
+ assert_ne ! ( node_txn[ 4 ] . input[ 0 ] . previous_output. txid, node_txn[ 1 ] . input[ 0 ] . previous_output. txid) ;
3631
+ }
3632
+ get_announce_close_broadcast_events ( & nodes, 0 , 1 ) ;
3633
+ assert_eq ! ( nodes[ 0 ] . node. list_channels( ) . len( ) , 0 ) ;
3634
+ assert_eq ! ( nodes[ 1 ] . node. list_channels( ) . len( ) , 0 ) ;
3635
+ }
3636
+
3564
3637
#[ test]
3565
3638
fn test_htlc_ignore_latest_remote_commitment ( ) {
3566
3639
// Test that HTLC transactions spending the latest remote commitment transaction are simply
0 commit comments