@@ -6659,3 +6659,88 @@ fn test_bump_penalty_txn_on_remote_commitment() {
6659
6659
nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
6660
6660
nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
6661
6661
}
6662
+
6663
+ #[ test]
6664
+ fn test_set_outpoints_partial_claiming ( ) {
6665
+ // - remote party claim tx, new bump tx
6666
+ // - disconnect remote claiming tx, new bump
6667
+ // - disconnect tx, see no tx anymore
6668
+ let nodes = create_network ( 2 , & [ None , None ] ) ;
6669
+
6670
+ let chan = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1000000 , 59000000 , LocalFeatures :: new ( ) , LocalFeatures :: new ( ) ) ;
6671
+ let payment_preimage_1 = route_payment ( & nodes[ 1 ] , & vec ! ( & nodes[ 0 ] ) [ ..] , 3_000_000 ) . 0 ;
6672
+ let payment_preimage_2 = route_payment ( & nodes[ 1 ] , & vec ! ( & nodes[ 0 ] ) [ ..] , 3_000_000 ) . 0 ;
6673
+
6674
+ // Remote commitment txn with 4 outputs: to_local, to_remote, 2 outgoing HTLC
6675
+ let remote_txn = nodes[ 1 ] . node . channel_state . lock ( ) . unwrap ( ) . by_id . get ( & chan. 2 ) . unwrap ( ) . last_local_commitment_txn . clone ( ) ;
6676
+ assert_eq ! ( remote_txn[ 0 ] . output. len( ) , 4 ) ;
6677
+ assert_eq ! ( remote_txn[ 0 ] . input. len( ) , 1 ) ;
6678
+ assert_eq ! ( remote_txn[ 0 ] . input[ 0 ] . previous_output. txid, chan. 3 . txid( ) ) ;
6679
+
6680
+ // Connect blocks on node A to advance height towards TEST_FINAL_CLTV
6681
+ let prev_header_100 = connect_blocks ( & nodes[ 1 ] . block_notifier , 100 , 0 , false , Default :: default ( ) ) ;
6682
+ // Provide node A with both preimage
6683
+ nodes[ 0 ] . node . claim_funds ( payment_preimage_1, 3_000_000 ) ;
6684
+ nodes[ 0 ] . node . claim_funds ( payment_preimage_2, 3_000_000 ) ;
6685
+ check_added_monitors ! ( nodes[ 0 ] , 2 ) ;
6686
+ nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
6687
+ nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
6688
+
6689
+ // Connect blocks on node A commitment transaction
6690
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : prev_header_100, merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
6691
+ nodes[ 0 ] . block_notifier . block_connected ( & Block { header, txdata : vec ! [ remote_txn[ 0 ] . clone( ) ] } , 101 ) ;
6692
+ // Verify node A broadcast tx claiming both HTLCs
6693
+ {
6694
+ let mut node_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
6695
+ assert_eq ! ( node_txn. len( ) , 3 ) ;
6696
+ check_spends ! ( node_txn[ 0 ] , remote_txn[ 0 ] . clone( ) ) ;
6697
+ assert_eq ! ( node_txn[ 0 ] . input. len( ) , 2 ) ;
6698
+ node_txn. clear ( ) ;
6699
+ }
6700
+ nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
6701
+
6702
+ // Connect blocks on node B
6703
+ connect_blocks ( & nodes[ 1 ] . block_notifier , 135 , 0 , false , Default :: default ( ) ) ;
6704
+ // Verify node B broadcast 2 HTLC-timeout txn
6705
+ let partial_claim_tx = {
6706
+ let node_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
6707
+ assert_eq ! ( node_txn. len( ) , 3 ) ;
6708
+ check_spends ! ( node_txn[ 1 ] , node_txn[ 0 ] . clone( ) ) ;
6709
+ check_spends ! ( node_txn[ 2 ] , node_txn[ 0 ] . clone( ) ) ;
6710
+ assert_eq ! ( node_txn[ 1 ] . input. len( ) , 1 ) ;
6711
+ assert_eq ! ( node_txn[ 2 ] . input. len( ) , 1 ) ;
6712
+ node_txn[ 1 ] . clone ( )
6713
+ } ;
6714
+ nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
6715
+
6716
+ // Broadcast partial claim on node A, should regenerate a claiming tx with HTLC dropped
6717
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : header. bitcoin_hash ( ) , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
6718
+ nodes[ 0 ] . block_notifier . block_connected ( & Block { header, txdata : vec ! [ partial_claim_tx. clone( ) ] } , 102 ) ;
6719
+ {
6720
+ let mut node_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
6721
+ assert_eq ! ( node_txn. len( ) , 1 ) ;
6722
+ check_spends ! ( node_txn[ 0 ] , remote_txn[ 0 ] . clone( ) ) ;
6723
+ assert_eq ! ( node_txn[ 0 ] . input. len( ) , 1 ) ; //dropped HTLC
6724
+ node_txn. clear ( ) ;
6725
+ }
6726
+ nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
6727
+
6728
+ // Disconnect last block on node A, should regenerate a claiming tx with HTLC dropped
6729
+ nodes[ 0 ] . block_notifier . block_disconnected ( & header, 102 ) ;
6730
+ {
6731
+ let mut node_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
6732
+ assert_eq ! ( node_txn. len( ) , 1 ) ;
6733
+ check_spends ! ( node_txn[ 0 ] , remote_txn[ 0 ] . clone( ) ) ;
6734
+ assert_eq ! ( node_txn[ 0 ] . input. len( ) , 2 ) ; //resurrected HTLC
6735
+ node_txn. clear ( ) ;
6736
+ }
6737
+
6738
+ //// Disconnect one more block and then reconnect multiple no transaction should be generated
6739
+ nodes[ 0 ] . block_notifier . block_disconnected ( & header, 101 ) ;
6740
+ connect_blocks ( & nodes[ 1 ] . block_notifier , 15 , 101 , false , prev_header_100) ;
6741
+ {
6742
+ let mut node_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
6743
+ assert_eq ! ( node_txn. len( ) , 0 ) ;
6744
+ node_txn. clear ( ) ;
6745
+ }
6746
+ }
0 commit comments