@@ -2715,3 +2715,102 @@ fn test_anchors_monitor_fixes_counterparty_payment_script_on_reload() {
2715
2715
do_test_anchors_monitor_fixes_counterparty_payment_script_on_reload ( false ) ;
2716
2716
do_test_anchors_monitor_fixes_counterparty_payment_script_on_reload ( true ) ;
2717
2717
}
2718
+
2719
+ #[ cfg( not( feature = "_test_vectors" ) ) ]
2720
+ fn do_test_monitor_claims_with_random_signatures ( anchors : bool ) {
2721
+ // Tests that our monitor claims will always use fresh random signatures (ensuring a unique
2722
+ // wtxid) to prevent certain classes of transaction replacement at the bitcoin P2P layer.
2723
+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
2724
+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
2725
+ let mut user_config = test_default_channel_config ( ) ;
2726
+ if anchors {
2727
+ user_config. channel_handshake_config . negotiate_anchors_zero_fee_htlc_tx = true ;
2728
+ user_config. manually_accept_inbound_channels = true ;
2729
+ }
2730
+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ Some ( user_config) , Some ( user_config) ] ) ;
2731
+ let mut nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
2732
+
2733
+ let coinbase_tx = Transaction {
2734
+ version : 2 ,
2735
+ lock_time : PackedLockTime :: ZERO ,
2736
+ input : vec ! [ TxIn { ..Default :: default ( ) } ] ,
2737
+ output : vec ! [
2738
+ TxOut {
2739
+ value: Amount :: ONE_BTC . to_sat( ) ,
2740
+ script_pubkey: nodes[ 0 ] . wallet_source. get_change_script( ) . unwrap( ) ,
2741
+ } ,
2742
+ ] ,
2743
+ } ;
2744
+ if anchors {
2745
+ nodes[ 0 ] . wallet_source . add_utxo ( bitcoin:: OutPoint { txid : coinbase_tx. txid ( ) , vout : 0 } , coinbase_tx. output [ 0 ] . value ) ;
2746
+ }
2747
+
2748
+ // Open a channel and route a payment. We'll let it timeout to claim it.
2749
+ let ( _, _, _, funding_tx) = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 0 ) ;
2750
+ route_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , 1_000_000 ) ;
2751
+ connect_blocks ( & nodes[ 0 ] , TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1 ) ;
2752
+
2753
+ // The commitment transaction comes first.
2754
+ let commitment_tx = {
2755
+ let mut txn = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ;
2756
+ assert_eq ! ( txn. len( ) , if anchors { 1 } else { 2 } ) ;
2757
+ check_spends ! ( txn[ 0 ] , funding_tx) ;
2758
+ txn. remove ( 0 )
2759
+ } ;
2760
+
2761
+ // Check we rebroadcast it with a different wtxid.
2762
+ nodes[ 0 ] . chain_monitor . chain_monitor . rebroadcast_pending_claims ( ) ;
2763
+ {
2764
+ let mut txn = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ;
2765
+ assert_eq ! ( txn. len( ) , if anchors { 1 } else { 2 } ) ;
2766
+ let new_commitment_tx = if txn[ 0 ] . input [ 0 ] . previous_output . txid == funding_tx. txid ( ) {
2767
+ & txn[ 0 ]
2768
+ } else {
2769
+ & txn[ 1 ]
2770
+ } ;
2771
+ assert_eq ! ( new_commitment_tx. txid( ) , commitment_tx. txid( ) ) ;
2772
+ assert_ne ! ( new_commitment_tx. wtxid( ) , commitment_tx. wtxid( ) ) ;
2773
+ } ;
2774
+
2775
+ mine_transaction ( & nodes[ 0 ] , & commitment_tx) ;
2776
+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2777
+ check_closed_broadcast ! ( nodes[ 0 ] , true ) ;
2778
+ check_closed_event ! ( nodes[ 0 ] , 1 , ClosureReason :: CommitmentTxConfirmed , [ nodes[ 1 ] . node. get_our_node_id( ) ] , 1_000_000 ) ;
2779
+
2780
+ // Then comes the HTLC timeout transaction.
2781
+ if anchors {
2782
+ handle_bump_htlc_event ( & nodes[ 0 ] , 1 ) ;
2783
+ }
2784
+ let htlc_timeout_tx = {
2785
+ let mut txn = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ;
2786
+ // If we update the best block to the new height before providing the confirmed
2787
+ // transactions, we'll see another broadcast of the commitment transaction.
2788
+ assert_eq ! ( txn. len( ) , if nodes[ 0 ] . connect_style. borrow( ) . updates_best_block_first( ) { 2 } else { 1 } ) ;
2789
+ let tx = if txn[ 0 ] . input [ 0 ] . previous_output . txid == commitment_tx. txid ( ) {
2790
+ txn[ 0 ] . clone ( )
2791
+ } else {
2792
+ txn[ 1 ] . clone ( )
2793
+ } ;
2794
+ check_spends ! ( tx, commitment_tx, coinbase_tx) ;
2795
+ tx
2796
+ } ;
2797
+
2798
+ // Check we rebroadcast it with a different wtxid.
2799
+ nodes[ 0 ] . chain_monitor . chain_monitor . rebroadcast_pending_claims ( ) ;
2800
+ if anchors {
2801
+ handle_bump_htlc_event ( & nodes[ 0 ] , 1 ) ;
2802
+ }
2803
+ {
2804
+ let mut txn = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ;
2805
+ assert_eq ! ( txn. len( ) , 1 ) ;
2806
+ assert_eq ! ( txn[ 0 ] . txid( ) , htlc_timeout_tx. txid( ) ) ;
2807
+ assert_ne ! ( txn[ 0 ] . wtxid( ) , htlc_timeout_tx. wtxid( ) ) ;
2808
+ }
2809
+ }
2810
+
2811
+ #[ cfg( not( feature = "_test_vectors" ) ) ]
2812
+ #[ test]
2813
+ fn test_monitor_claims_with_random_signatures ( ) {
2814
+ do_test_monitor_claims_with_random_signatures ( false ) ;
2815
+ do_test_monitor_claims_with_random_signatures ( true ) ;
2816
+ }
0 commit comments