@@ -2715,3 +2715,113 @@ fn test_anchors_monitor_fixes_counterparty_payment_script_on_reload() {
27152715 do_test_anchors_monitor_fixes_counterparty_payment_script_on_reload ( false ) ;
27162716 do_test_anchors_monitor_fixes_counterparty_payment_script_on_reload ( true ) ;
27172717}
2718+
2719+ #[ cfg( not( feature = "_test_vectors" ) ) ]
2720+ fn do_test_monitor_claims_with_random_signatures ( anchors : bool , confirm_counterparty_commitment : 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 ( _, _, chan_id, 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+
2752+ let ( closing_node, other_node) = if confirm_counterparty_commitment {
2753+ ( & nodes[ 1 ] , & nodes[ 0 ] )
2754+ } else {
2755+ ( & nodes[ 0 ] , & nodes[ 1 ] )
2756+ } ;
2757+
2758+ closing_node. node . force_close_broadcasting_latest_txn ( & chan_id, & other_node. node . get_our_node_id ( ) ) . unwrap ( ) ;
2759+
2760+ // The commitment transaction comes first.
2761+ let commitment_tx = {
2762+ let mut txn = closing_node. tx_broadcaster . unique_txn_broadcast ( ) ;
2763+ assert_eq ! ( txn. len( ) , 1 ) ;
2764+ check_spends ! ( txn[ 0 ] , funding_tx) ;
2765+ txn. pop ( ) . unwrap ( )
2766+ } ;
2767+
2768+ mine_transaction ( closing_node, & commitment_tx) ;
2769+ check_added_monitors ! ( closing_node, 1 ) ;
2770+ check_closed_broadcast ! ( closing_node, true ) ;
2771+ check_closed_event ! ( closing_node, 1 , ClosureReason :: HolderForceClosed , [ other_node. node. get_our_node_id( ) ] , 1_000_000 ) ;
2772+
2773+ mine_transaction ( other_node, & commitment_tx) ;
2774+ check_added_monitors ! ( other_node, 1 ) ;
2775+ check_closed_broadcast ! ( other_node, true ) ;
2776+ check_closed_event ! ( other_node, 1 , ClosureReason :: CommitmentTxConfirmed , [ closing_node. node. get_our_node_id( ) ] , 1_000_000 ) ;
2777+
2778+ // If we update the best block to the new height before providing the confirmed transactions,
2779+ // we'll see another broadcast of the commitment transaction.
2780+ if anchors && !confirm_counterparty_commitment && nodes[ 0 ] . connect_style . borrow ( ) . updates_best_block_first ( ) {
2781+ let _ = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ;
2782+ }
2783+
2784+ // Then comes the HTLC timeout transaction.
2785+ if confirm_counterparty_commitment {
2786+ connect_blocks ( & nodes[ 0 ] , 5 ) ;
2787+ test_spendable_output ( & nodes[ 0 ] , & commitment_tx, false ) ;
2788+ connect_blocks ( & nodes[ 0 ] , TEST_FINAL_CLTV - 5 ) ;
2789+ } else {
2790+ connect_blocks ( & nodes[ 0 ] , TEST_FINAL_CLTV ) ;
2791+ }
2792+ if anchors && !confirm_counterparty_commitment {
2793+ handle_bump_htlc_event ( & nodes[ 0 ] , 1 ) ;
2794+ }
2795+ let htlc_timeout_tx = {
2796+ let mut txn = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ;
2797+ assert_eq ! ( txn. len( ) , 1 ) ;
2798+ let tx = if txn[ 0 ] . input [ 0 ] . previous_output . txid == commitment_tx. txid ( ) {
2799+ txn[ 0 ] . clone ( )
2800+ } else {
2801+ txn[ 1 ] . clone ( )
2802+ } ;
2803+ check_spends ! ( tx, commitment_tx, coinbase_tx) ;
2804+ tx
2805+ } ;
2806+
2807+ // Check we rebroadcast it with a different wtxid.
2808+ nodes[ 0 ] . chain_monitor . chain_monitor . rebroadcast_pending_claims ( ) ;
2809+ if anchors && !confirm_counterparty_commitment {
2810+ handle_bump_htlc_event ( & nodes[ 0 ] , 1 ) ;
2811+ }
2812+ {
2813+ let mut txn = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ;
2814+ assert_eq ! ( txn. len( ) , 1 ) ;
2815+ assert_eq ! ( txn[ 0 ] . txid( ) , htlc_timeout_tx. txid( ) ) ;
2816+ assert_ne ! ( txn[ 0 ] . wtxid( ) , htlc_timeout_tx. wtxid( ) ) ;
2817+ }
2818+ }
2819+
2820+ #[ cfg( not( feature = "_test_vectors" ) ) ]
2821+ #[ test]
2822+ fn test_monitor_claims_with_random_signatures ( ) {
2823+ do_test_monitor_claims_with_random_signatures ( false , false ) ;
2824+ do_test_monitor_claims_with_random_signatures ( false , true ) ;
2825+ do_test_monitor_claims_with_random_signatures ( true , false ) ;
2826+ do_test_monitor_claims_with_random_signatures ( true , true ) ;
2827+ }
0 commit comments