@@ -6455,3 +6455,111 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
6455
6455
}
6456
6456
check_closed_broadcast ! ( nodes[ 0 ] ) ;
6457
6457
}
6458
+
6459
+ #[ test]
6460
+ fn test_bump_penalty_txn_on_remote_commitment ( ) {
6461
+ // In case of claim txn with too low feerates for getting into mempools, RBF-bump them to be sure
6462
+ // we're able to claim outputs on remote commitment transaction before timelocks expiration
6463
+
6464
+ // Create 2 HTLCs
6465
+ // Provide preimage for one
6466
+ // Check aggregation
6467
+
6468
+ let nodes = create_network ( 2 , & [ None , None ] ) ;
6469
+
6470
+ let chan = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1000000 , 59000000 , LocalFeatures :: new ( ) , LocalFeatures :: new ( ) ) ;
6471
+ let payment_preimage = route_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] ) [ ..] , 3000000 ) . 0 ;
6472
+ route_payment ( & nodes[ 1 ] , & vec ! ( & nodes[ 0 ] ) [ ..] , 3000000 ) . 0 ;
6473
+
6474
+ // Remote commitment txn with 4 outputs : to_local, to_remote, 1 outgoing HTLC, 1 incoming HTLC
6475
+ let remote_txn = nodes[ 0 ] . node . channel_state . lock ( ) . unwrap ( ) . by_id . get ( & chan. 2 ) . unwrap ( ) . last_local_commitment_txn . clone ( ) ;
6476
+ assert_eq ! ( remote_txn[ 0 ] . output. len( ) , 4 ) ;
6477
+ assert_eq ! ( remote_txn[ 0 ] . input. len( ) , 1 ) ;
6478
+ assert_eq ! ( remote_txn[ 0 ] . input[ 0 ] . previous_output. txid, chan. 3 . txid( ) ) ;
6479
+
6480
+ // Claim a HTLC without revocation (provide B monitor with preimage)
6481
+ nodes[ 1 ] . node . claim_funds ( payment_preimage, 3_000_000 ) ;
6482
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : Default :: default ( ) , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
6483
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ remote_txn[ 0 ] . clone( ) ] } , 1 ) ;
6484
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
6485
+
6486
+ // One or more claim tx should have been broadcast, check it
6487
+ let timeout;
6488
+ let preimage;
6489
+ let feerate_timeout;
6490
+ let feerate_preimage;
6491
+ {
6492
+ let mut node_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
6493
+ assert_eq ! ( node_txn. len( ) , 6 ) ; // 2 * claim tx (broadcasted from ChannelMonitor) * 2 (block-reparsing) + local commitment tx + local HTLC-timeout (broadcasted from ChannelManager)
6494
+ assert_eq ! ( node_txn[ 0 ] , node_txn[ 4 ] ) ;
6495
+ assert_eq ! ( node_txn[ 1 ] , node_txn[ 5 ] ) ;
6496
+ assert_eq ! ( node_txn[ 0 ] . input. len( ) , 1 ) ;
6497
+ assert_eq ! ( node_txn[ 1 ] . input. len( ) , 1 ) ;
6498
+ check_spends ! ( node_txn[ 0 ] , remote_txn[ 0 ] . clone( ) ) ;
6499
+ check_spends ! ( node_txn[ 1 ] , remote_txn[ 0 ] . clone( ) ) ;
6500
+ if node_txn[ 0 ] . input [ 0 ] . witness . last ( ) . unwrap ( ) . len ( ) == ACCEPTED_HTLC_SCRIPT_WEIGHT {
6501
+ timeout = node_txn[ 0 ] . txid ( ) ;
6502
+ let index = node_txn[ 0 ] . input [ 0 ] . previous_output . vout ;
6503
+ let fee = remote_txn[ 0 ] . output [ index as usize ] . value - node_txn[ 0 ] . output [ 0 ] . value ;
6504
+ feerate_timeout = fee * 1000 / node_txn[ 0 ] . get_weight ( ) as u64 ;
6505
+
6506
+ preimage = node_txn[ 1 ] . txid ( ) ;
6507
+ let index = node_txn[ 1 ] . input [ 0 ] . previous_output . vout ;
6508
+ let fee = remote_txn[ 0 ] . output [ index as usize ] . value - node_txn[ 1 ] . output [ 0 ] . value ;
6509
+ feerate_preimage = fee * 1000 / node_txn[ 1 ] . get_weight ( ) as u64 ;
6510
+ } else {
6511
+ timeout = node_txn[ 1 ] . txid ( ) ;
6512
+ let index = node_txn[ 1 ] . input [ 0 ] . previous_output . vout ;
6513
+ let fee = remote_txn[ 0 ] . output [ index as usize ] . value - node_txn[ 1 ] . output [ 0 ] . value ;
6514
+ feerate_timeout = fee * 1000 / node_txn[ 1 ] . get_weight ( ) as u64 ;
6515
+
6516
+ preimage = node_txn[ 0 ] . txid ( ) ;
6517
+ let index = node_txn[ 0 ] . input [ 0 ] . previous_output . vout ;
6518
+ let fee = remote_txn[ 0 ] . output [ index as usize ] . value - node_txn[ 0 ] . output [ 0 ] . value ;
6519
+ feerate_preimage = fee * 1000 / node_txn[ 0 ] . get_weight ( ) as u64 ;
6520
+ }
6521
+ node_txn. clear ( ) ;
6522
+ } ;
6523
+ assert_ne ! ( feerate_timeout, 0 ) ;
6524
+ assert_ne ! ( feerate_preimage, 0 ) ;
6525
+
6526
+ // After exhaustion of height timer, new bumped claim txn should have been broadcast, check it
6527
+ connect_blocks ( & nodes[ 1 ] . chain_monitor , 15 , 1 , true , header. bitcoin_hash ( ) ) ;
6528
+ {
6529
+ let mut node_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
6530
+ assert_eq ! ( node_txn. len( ) , 2 ) ;
6531
+ assert_eq ! ( node_txn[ 0 ] . input. len( ) , 1 ) ;
6532
+ assert_eq ! ( node_txn[ 1 ] . input. len( ) , 1 ) ;
6533
+ check_spends ! ( node_txn[ 0 ] , remote_txn[ 0 ] . clone( ) ) ;
6534
+ check_spends ! ( node_txn[ 1 ] , remote_txn[ 0 ] . clone( ) ) ;
6535
+ if node_txn[ 0 ] . input [ 0 ] . witness . last ( ) . unwrap ( ) . len ( ) == ACCEPTED_HTLC_SCRIPT_WEIGHT {
6536
+ let index = node_txn[ 0 ] . input [ 0 ] . previous_output . vout ;
6537
+ let fee = remote_txn[ 0 ] . output [ index as usize ] . value - node_txn[ 0 ] . output [ 0 ] . value ;
6538
+ let new_feerate = fee * 1000 / node_txn[ 0 ] . get_weight ( ) as u64 ;
6539
+ assert ! ( new_feerate * 100 > feerate_timeout * 125 ) ;
6540
+ assert_ne ! ( timeout, node_txn[ 0 ] . txid( ) ) ;
6541
+
6542
+ let index = node_txn[ 1 ] . input [ 0 ] . previous_output . vout ;
6543
+ let fee = remote_txn[ 0 ] . output [ index as usize ] . value - node_txn[ 1 ] . output [ 0 ] . value ;
6544
+ let new_feerate = fee * 1000 / node_txn[ 1 ] . get_weight ( ) as u64 ;
6545
+ assert ! ( new_feerate * 100 > feerate_preimage * 125 ) ;
6546
+ assert_ne ! ( preimage, node_txn[ 1 ] . txid( ) ) ;
6547
+ } else {
6548
+ let index = node_txn[ 1 ] . input [ 0 ] . previous_output . vout ;
6549
+ let fee = remote_txn[ 0 ] . output [ index as usize ] . value - node_txn[ 1 ] . output [ 0 ] . value ;
6550
+ let new_feerate = fee * 1000 / node_txn[ 1 ] . get_weight ( ) as u64 ;
6551
+ assert ! ( new_feerate * 100 > feerate_timeout * 125 ) ;
6552
+ assert_ne ! ( timeout, node_txn[ 1 ] . txid( ) ) ;
6553
+
6554
+ let index = node_txn[ 0 ] . input [ 0 ] . previous_output . vout ;
6555
+ let fee = remote_txn[ 0 ] . output [ index as usize ] . value - node_txn[ 0 ] . output [ 0 ] . value ;
6556
+ let new_feerate = fee * 1000 / node_txn[ 0 ] . get_weight ( ) as u64 ;
6557
+ assert ! ( new_feerate * 100 > feerate_preimage * 125 ) ;
6558
+ assert_ne ! ( preimage, node_txn[ 0 ] . txid( ) ) ;
6559
+ }
6560
+ node_txn. clear ( ) ;
6561
+ }
6562
+
6563
+ nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
6564
+ nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
6565
+ }
0 commit comments