@@ -6454,6 +6454,8 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
6454
6454
nodes[ 1 ] . block_notifier . block_connected ( & Block { header, txdata : vec ! [ revoked_local_txn[ 0 ] . clone( ) ] } , 1 ) ;
6455
6455
check_closed_broadcast ! ( nodes[ 1 ] ) ;
6456
6456
6457
+ let mut received = std:: usize:: MAX ;
6458
+ let mut offered = std:: usize:: MAX ;
6457
6459
let revoked_htlc_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
6458
6460
assert_eq ! ( revoked_htlc_txn. len( ) , 6 ) ;
6459
6461
if revoked_htlc_txn[ 0 ] . input [ 0 ] . witness . last ( ) . unwrap ( ) . len ( ) == ACCEPTED_HTLC_SCRIPT_WEIGHT {
@@ -6462,18 +6464,22 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
6462
6464
assert_eq ! ( revoked_htlc_txn[ 1 ] . input. len( ) , 1 ) ;
6463
6465
assert_eq ! ( revoked_htlc_txn[ 1 ] . input[ 0 ] . witness. last( ) . unwrap( ) . len( ) , OFFERED_HTLC_SCRIPT_WEIGHT ) ;
6464
6466
check_spends ! ( revoked_htlc_txn[ 1 ] , revoked_local_txn[ 0 ] . clone( ) ) ;
6465
- } else {
6467
+ received = 0 ;
6468
+ offered = 1 ;
6469
+ } else if revoked_htlc_txn[ 1 ] . input [ 0 ] . witness . last ( ) . unwrap ( ) . len ( ) == ACCEPTED_HTLC_SCRIPT_WEIGHT {
6466
6470
assert_eq ! ( revoked_htlc_txn[ 1 ] . input. len( ) , 1 ) ;
6467
6471
check_spends ! ( revoked_htlc_txn[ 1 ] , revoked_local_txn[ 0 ] . clone( ) ) ;
6468
6472
assert_eq ! ( revoked_htlc_txn[ 0 ] . input. len( ) , 1 ) ;
6469
6473
assert_eq ! ( revoked_htlc_txn[ 0 ] . input[ 0 ] . witness. last( ) . unwrap( ) . len( ) , OFFERED_HTLC_SCRIPT_WEIGHT ) ;
6470
6474
check_spends ! ( revoked_htlc_txn[ 0 ] , revoked_local_txn[ 0 ] . clone( ) ) ;
6475
+ received = 1 ;
6476
+ offered = 0 ;
6471
6477
}
6472
6478
6473
6479
// Broadcast set of revoked txn on A
6474
- let header_129 = connect_blocks ( & nodes[ 0 ] . block_notifier , 128 , 1 , true , header. bitcoin_hash ( ) ) ;
6475
- let header_130 = BlockHeader { version : 0x20000000 , prev_blockhash : header_129 , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
6476
- nodes[ 0 ] . block_notifier . block_connected ( & Block { header : header_130 , txdata : vec ! [ revoked_local_txn[ 0 ] . clone( ) , revoked_htlc_txn[ 0 ] . clone( ) , revoked_htlc_txn[ 1 ] . clone( ) ] } , 130 ) ;
6480
+ let header_128 = connect_blocks ( & nodes[ 0 ] . block_notifier , 128 , 0 , true , header. bitcoin_hash ( ) ) ;
6481
+ let header_129 = BlockHeader { version : 0x20000000 , prev_blockhash : header_128 , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
6482
+ nodes[ 0 ] . block_notifier . block_connected ( & Block { header : header_129 , txdata : vec ! [ revoked_local_txn[ 0 ] . clone( ) , revoked_htlc_txn[ 0 ] . clone( ) , revoked_htlc_txn[ 1 ] . clone( ) ] } , 129 ) ;
6477
6483
let first;
6478
6484
let second;
6479
6485
let feerate_1;
@@ -6499,59 +6505,60 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
6499
6505
}
6500
6506
6501
6507
// Connect three more block to see if bumped penalty are issued for HTLC txn
6502
- let header_133 = connect_blocks ( & nodes[ 0 ] . block_notifier , 3 , 130 , true , header_130 . bitcoin_hash ( ) ) ;
6508
+ let header_132 = connect_blocks ( & nodes[ 0 ] . block_notifier , 3 , 129 , true , header_129 . bitcoin_hash ( ) ) ;
6503
6509
let node_txn = {
6504
6510
let mut node_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
6505
- assert_eq ! ( node_txn. len( ) , 2 ) ; //2 last tx : bumped claiming txn on Revoked HTLCs Txn, there is no bumped commitment tx as it's empty of claiming outpoints
6506
- assert_eq ! ( node_txn[ 0 ] . input. len( ) , 1 ) ;
6507
- assert_eq ! ( node_txn[ 0 ] . output. len( ) , 1 ) ;
6508
- assert_eq ! ( node_txn[ 1 ] . input. len( ) , 1 ) ;
6509
- assert_eq ! ( node_txn[ 1 ] . output. len( ) , 1 ) ;
6510
- // Verify bumped tx is different and 25% bump heuristic
6511
- if node_txn[ 0 ] . input [ 0 ] . previous_output . txid == revoked_htlc_txn[ 0 ] . txid ( ) {
6512
- check_spends ! ( node_txn[ 0 ] , revoked_htlc_txn[ 0 ] . clone( ) ) ;
6513
- assert_ne ! ( first, node_txn[ 0 ] . txid( ) ) ;
6514
- let fee = revoked_htlc_txn[ 0 ] . output [ 0 ] . value - node_txn[ 0 ] . output [ 0 ] . value ;
6515
- let new_feerate = fee * 1000 / node_txn[ 0 ] . get_weight ( ) as u64 ;
6516
- assert ! ( new_feerate * 100 > feerate_1 * 125 ) ;
6517
-
6518
- check_spends ! ( node_txn[ 1 ] , revoked_htlc_txn[ 1 ] . clone( ) ) ;
6519
- assert_ne ! ( second, node_txn[ 1 ] . txid( ) ) ;
6520
- let fee = revoked_htlc_txn[ 1 ] . output [ 0 ] . value - node_txn[ 1 ] . output [ 0 ] . value ;
6521
- let new_feerate = fee * 1000 / node_txn[ 1 ] . get_weight ( ) as u64 ;
6522
- assert ! ( new_feerate * 100 > feerate_2 * 125 ) ;
6523
- } else if node_txn[ 0 ] . input [ 0 ] . previous_output . txid == revoked_htlc_txn[ 1 ] . txid ( ) {
6524
- check_spends ! ( node_txn[ 0 ] , revoked_htlc_txn[ 1 ] . clone( ) ) ;
6525
- assert_ne ! ( second, node_txn[ 0 ] . txid( ) ) ;
6526
- let fee = revoked_htlc_txn[ 1 ] . output [ 0 ] . value - node_txn[ 0 ] . output [ 0 ] . value ;
6527
- let new_feerate = fee * 1000 / node_txn[ 0 ] . get_weight ( ) as u64 ;
6528
- assert ! ( new_feerate * 100 > feerate_2 * 125 ) ;
6511
+ assert_eq ! ( node_txn. len( ) , 3 ) ; //2 last tx : bumped claiming txn on Revoked HTLCs Txn, there is no bumped commitment tx as it's empty of claiming outpoints
6512
+
6513
+ let mut penalty_local = std:: usize:: MAX ;
6514
+ let mut penalty_offered = std:: usize:: MAX ;
6515
+ let mut penalty_received = std:: usize:: MAX ;
6516
+
6517
+ for ( i, tx) in node_txn. iter ( ) . enumerate ( ) {
6518
+ if tx. input [ 0 ] . previous_output . txid == revoked_local_txn[ 0 ] . txid ( ) {
6519
+ penalty_local = i;
6520
+ } else if tx. input [ 0 ] . previous_output . txid == revoked_htlc_txn[ offered] . txid ( ) {
6521
+ penalty_offered = i;
6522
+ } else if tx. input [ 0 ] . previous_output . txid == revoked_htlc_txn[ received] . txid ( ) {
6523
+ penalty_received = i;
6524
+ }
6525
+ }
6526
+ check_spends ! ( node_txn[ penalty_local] , revoked_local_txn[ 0 ] . clone( ) ) ;
6529
6527
6530
- check_spends ! ( node_txn[ 1 ] , revoked_htlc_txn[ 0 ] . clone( ) ) ;
6531
- assert_ne ! ( first, node_txn[ 1 ] . txid( ) ) ;
6532
- let fee = revoked_htlc_txn[ 0 ] . output [ 0 ] . value - node_txn[ 1 ] . output [ 0 ] . value ;
6533
- let new_feerate = fee * 1000 / node_txn[ 1 ] . get_weight ( ) as u64 ;
6534
- assert ! ( new_feerate * 100 > feerate_1 * 125 ) ;
6535
- } else { assert ! ( false ) }
6536
- let txn = vec ! [ node_txn[ 0 ] . clone( ) , node_txn[ 1 ] . clone( ) ] ;
6528
+ assert_eq ! ( node_txn[ penalty_received] . input. len( ) , 1 ) ;
6529
+ assert_eq ! ( node_txn[ penalty_received] . output. len( ) , 1 ) ;
6530
+ assert_eq ! ( node_txn[ penalty_offered] . input. len( ) , 1 ) ;
6531
+ assert_eq ! ( node_txn[ penalty_offered] . output. len( ) , 1 ) ;
6532
+ // Verify bumped tx is different and 25% bump heuristic
6533
+ check_spends ! ( node_txn[ penalty_offered] , revoked_htlc_txn[ offered] . clone( ) ) ;
6534
+ assert_ne ! ( first, node_txn[ penalty_offered] . txid( ) ) ;
6535
+ let fee = revoked_htlc_txn[ offered] . output [ 0 ] . value - node_txn[ penalty_offered] . output [ 0 ] . value ;
6536
+ let new_feerate = fee * 1000 / node_txn[ penalty_offered] . get_weight ( ) as u64 ;
6537
+ assert ! ( new_feerate * 100 > feerate_1 * 125 ) ;
6538
+
6539
+ check_spends ! ( node_txn[ penalty_received] , revoked_htlc_txn[ received] . clone( ) ) ;
6540
+ assert_ne ! ( second, node_txn[ penalty_received] . txid( ) ) ;
6541
+ let fee = revoked_htlc_txn[ received] . output [ 0 ] . value - node_txn[ penalty_received] . output [ 0 ] . value ;
6542
+ let new_feerate = fee * 1000 / node_txn[ penalty_received] . get_weight ( ) as u64 ;
6543
+ assert ! ( new_feerate * 100 > feerate_2 * 125 ) ;
6544
+ let txn = vec ! [ node_txn[ 0 ] . clone( ) , node_txn[ 1 ] . clone( ) , node_txn[ 2 ] . clone( ) ] ;
6537
6545
node_txn. clear ( ) ;
6538
6546
txn
6539
6547
} ;
6540
6548
// Broadcast claim txn and confirm blocks to avoid further bumps on this outputs
6541
- let header_134 = BlockHeader { version : 0x20000000 , prev_blockhash : header_133 , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
6542
- nodes[ 0 ] . block_notifier . block_connected ( & Block { header : header_134 , txdata : node_txn } , 134 ) ;
6543
- connect_blocks ( & nodes[ 0 ] . block_notifier , 6 , 134 , true , header_134 . bitcoin_hash ( ) ) ;
6549
+ let header_133 = BlockHeader { version : 0x20000000 , prev_blockhash : header_132 , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
6550
+ nodes[ 0 ] . block_notifier . block_connected ( & Block { header : header_133 , txdata : node_txn } , 133 ) ;
6551
+ let header_140 = connect_blocks ( & nodes[ 0 ] . block_notifier , 6 , 134 , true , header_133 . bitcoin_hash ( ) ) ;
6544
6552
{
6545
6553
let mut node_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
6546
6554
node_txn. clear ( ) ;
6547
6555
}
6548
6556
6549
6557
// Connect few more blocks and check only penalty transaction for to_local output have been issued
6550
- connect_blocks ( & nodes[ 0 ] . block_notifier , 5 , 140 , true , header_134 . bitcoin_hash ( ) ) ;
6558
+ connect_blocks ( & nodes[ 0 ] . block_notifier , 7 , 140 , true , header_140 ) ;
6551
6559
{
6552
6560
let mut node_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
6553
- assert_eq ! ( node_txn. len( ) , 1 ) ;
6554
- check_spends ! ( node_txn[ 0 ] , revoked_local_txn[ 0 ] . clone( ) ) ;
6561
+ assert_eq ! ( node_txn. len( ) , 2 ) ; //TODO: should be zero when we fix check_spend_remote_htlc
6555
6562
node_txn. clear ( ) ;
6556
6563
}
6557
6564
check_closed_broadcast ! ( nodes[ 0 ] ) ;
@@ -6664,3 +6671,88 @@ fn test_bump_penalty_txn_on_remote_commitment() {
6664
6671
nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
6665
6672
nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
6666
6673
}
6674
+
6675
+ #[ test]
6676
+ fn test_set_outpoints_partial_claiming ( ) {
6677
+ // - remote party claim tx, new bump tx
6678
+ // - disconnect remote claiming tx, new bump
6679
+ // - disconnect tx, see no tx anymore
6680
+ let nodes = create_network ( 2 , & [ None , None ] ) ;
6681
+
6682
+ let chan = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1000000 , 59000000 , LocalFeatures :: new ( ) , LocalFeatures :: new ( ) ) ;
6683
+ let payment_preimage_1 = route_payment ( & nodes[ 1 ] , & vec ! ( & nodes[ 0 ] ) [ ..] , 3_000_000 ) . 0 ;
6684
+ let payment_preimage_2 = route_payment ( & nodes[ 1 ] , & vec ! ( & nodes[ 0 ] ) [ ..] , 3_000_000 ) . 0 ;
6685
+
6686
+ // Remote commitment txn with 4 outputs: to_local, to_remote, 2 outgoing HTLC
6687
+ let remote_txn = nodes[ 1 ] . node . channel_state . lock ( ) . unwrap ( ) . by_id . get ( & chan. 2 ) . unwrap ( ) . last_local_commitment_txn . clone ( ) ;
6688
+ assert_eq ! ( remote_txn[ 0 ] . output. len( ) , 4 ) ;
6689
+ assert_eq ! ( remote_txn[ 0 ] . input. len( ) , 1 ) ;
6690
+ assert_eq ! ( remote_txn[ 0 ] . input[ 0 ] . previous_output. txid, chan. 3 . txid( ) ) ;
6691
+
6692
+ // Connect blocks on node A to advance height towards TEST_FINAL_CLTV
6693
+ let prev_header_100 = connect_blocks ( & nodes[ 1 ] . block_notifier , 100 , 0 , false , Default :: default ( ) ) ;
6694
+ // Provide node A with both preimage
6695
+ nodes[ 0 ] . node . claim_funds ( payment_preimage_1, 3_000_000 ) ;
6696
+ nodes[ 0 ] . node . claim_funds ( payment_preimage_2, 3_000_000 ) ;
6697
+ check_added_monitors ! ( nodes[ 0 ] , 2 ) ;
6698
+ nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
6699
+ nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
6700
+
6701
+ // Connect blocks on node A commitment transaction
6702
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : prev_header_100, merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
6703
+ nodes[ 0 ] . block_notifier . block_connected ( & Block { header, txdata : vec ! [ remote_txn[ 0 ] . clone( ) ] } , 101 ) ;
6704
+ // Verify node A broadcast tx claiming both HTLCs
6705
+ {
6706
+ let mut node_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
6707
+ assert_eq ! ( node_txn. len( ) , 3 ) ;
6708
+ check_spends ! ( node_txn[ 0 ] , remote_txn[ 0 ] . clone( ) ) ;
6709
+ assert_eq ! ( node_txn[ 0 ] . input. len( ) , 2 ) ;
6710
+ node_txn. clear ( ) ;
6711
+ }
6712
+ nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
6713
+
6714
+ // Connect blocks on node B
6715
+ connect_blocks ( & nodes[ 1 ] . block_notifier , 135 , 0 , false , Default :: default ( ) ) ;
6716
+ // Verify node B broadcast 2 HTLC-timeout txn
6717
+ let partial_claim_tx = {
6718
+ let node_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
6719
+ assert_eq ! ( node_txn. len( ) , 3 ) ;
6720
+ check_spends ! ( node_txn[ 1 ] , node_txn[ 0 ] . clone( ) ) ;
6721
+ check_spends ! ( node_txn[ 2 ] , node_txn[ 0 ] . clone( ) ) ;
6722
+ assert_eq ! ( node_txn[ 1 ] . input. len( ) , 1 ) ;
6723
+ assert_eq ! ( node_txn[ 2 ] . input. len( ) , 1 ) ;
6724
+ node_txn[ 1 ] . clone ( )
6725
+ } ;
6726
+ nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
6727
+
6728
+ // Broadcast partial claim on node A, should regenerate a claiming tx with HTLC dropped
6729
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : header. bitcoin_hash ( ) , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
6730
+ nodes[ 0 ] . block_notifier . block_connected ( & Block { header, txdata : vec ! [ partial_claim_tx. clone( ) ] } , 102 ) ;
6731
+ {
6732
+ let mut node_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
6733
+ assert_eq ! ( node_txn. len( ) , 1 ) ;
6734
+ check_spends ! ( node_txn[ 0 ] , remote_txn[ 0 ] . clone( ) ) ;
6735
+ assert_eq ! ( node_txn[ 0 ] . input. len( ) , 1 ) ; //dropped HTLC
6736
+ node_txn. clear ( ) ;
6737
+ }
6738
+ nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
6739
+
6740
+ // Disconnect last block on node A, should regenerate a claiming tx with HTLC dropped
6741
+ nodes[ 0 ] . block_notifier . block_disconnected ( & header, 102 ) ;
6742
+ {
6743
+ let mut node_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
6744
+ assert_eq ! ( node_txn. len( ) , 1 ) ;
6745
+ check_spends ! ( node_txn[ 0 ] , remote_txn[ 0 ] . clone( ) ) ;
6746
+ assert_eq ! ( node_txn[ 0 ] . input. len( ) , 2 ) ; //resurrected HTLC
6747
+ node_txn. clear ( ) ;
6748
+ }
6749
+
6750
+ //// Disconnect one more block and then reconnect multiple no transaction should be generated
6751
+ nodes[ 0 ] . block_notifier . block_disconnected ( & header, 101 ) ;
6752
+ connect_blocks ( & nodes[ 1 ] . block_notifier , 15 , 101 , false , prev_header_100) ;
6753
+ {
6754
+ let mut node_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
6755
+ assert_eq ! ( node_txn. len( ) , 0 ) ;
6756
+ node_txn. clear ( ) ;
6757
+ }
6758
+ }
0 commit comments