@@ -2294,16 +2294,20 @@ fn test_anchors_aggregated_revoked_htlc_tx() {
22942294
22952295 assert ! ( nodes[ 1 ] . chain_monitor. chain_monitor. get_and_clear_pending_events( ) . is_empty( ) ) ;
22962296 let spendable_output_events = nodes[ 0 ] . chain_monitor . chain_monitor . get_and_clear_pending_events ( ) ;
2297- assert_eq ! ( spendable_output_events. len( ) , 2 ) ;
2298- for event in spendable_output_events. iter ( ) {
2297+ assert_eq ! ( spendable_output_events. len( ) , 4 ) ;
2298+ for event in spendable_output_events {
22992299 if let Event :: SpendableOutputs { outputs, channel_id } = event {
23002300 assert_eq ! ( outputs. len( ) , 1 ) ;
23012301 assert ! ( vec![ chan_b. 2 , chan_a. 2 ] . contains( & channel_id. unwrap( ) ) ) ;
23022302 let spend_tx = nodes[ 0 ] . keys_manager . backing . spend_spendable_outputs (
23032303 & [ & outputs[ 0 ] ] , Vec :: new ( ) , Script :: new_op_return ( & [ ] ) , 253 , None , & Secp256k1 :: new ( ) ,
23042304 ) . unwrap ( ) ;
23052305
2306- check_spends ! ( spend_tx, revoked_claim_transactions. get( & spend_tx. input[ 0 ] . previous_output. txid) . unwrap( ) ) ;
2306+ if let SpendableOutputDescriptor :: StaticPaymentOutput ( _) = & outputs[ 0 ] {
2307+ check_spends ! ( spend_tx, & revoked_commitment_a, & revoked_commitment_b) ;
2308+ } else {
2309+ check_spends ! ( spend_tx, revoked_claim_transactions. get( & spend_tx. input[ 0 ] . previous_output. txid) . unwrap( ) ) ;
2310+ }
23072311 } else {
23082312 panic ! ( "unexpected event" ) ;
23092313 }
@@ -2321,3 +2325,90 @@ fn test_anchors_aggregated_revoked_htlc_tx() {
23212325 // revoked commitment which Bob has the preimage for.
23222326 assert_eq ! ( nodes[ 1 ] . chain_monitor. chain_monitor. get_claimable_balances( & [ ] ) . len( ) , 6 ) ;
23232327}
2328+
2329+ fn do_test_anchors_monitor_fixes_counterparty_payment_script_on_reload ( confirm_commitment_before_reload : bool ) {
2330+ // Tests that we'll fix a ChannelMonitor's `counterparty_payment_script` for an anchor outputs
2331+ // channel upon deserialization.
2332+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
2333+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
2334+ let persister;
2335+ let chain_monitor;
2336+ let mut user_config = test_default_channel_config ( ) ;
2337+ user_config. channel_handshake_config . negotiate_anchors_zero_fee_htlc_tx = true ;
2338+ user_config. manually_accept_inbound_channels = true ;
2339+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ Some ( user_config) , Some ( user_config) ] ) ;
2340+ let node_deserialized;
2341+ let mut nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
2342+
2343+ let ( _, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 100_000 , 50_000_000 ) ;
2344+
2345+ // Set the monitor's `counterparty_payment_script` to a dummy P2WPKH script.
2346+ let secp = Secp256k1 :: new ( ) ;
2347+ let privkey = bitcoin:: PrivateKey :: from_slice ( & [ 1 ; 32 ] , bitcoin:: Network :: Testnet ) . unwrap ( ) ;
2348+ let pubkey = bitcoin:: PublicKey :: from_private_key ( & secp, & privkey) ;
2349+ let p2wpkh_script = Script :: new_v0_p2wpkh ( & pubkey. wpubkey_hash ( ) . unwrap ( ) ) ;
2350+ get_monitor ! ( nodes[ 1 ] , chan_id) . set_counterparty_payment_script ( p2wpkh_script. clone ( ) ) ;
2351+ assert_eq ! ( get_monitor!( nodes[ 1 ] , chan_id) . get_counterparty_payment_script( ) , p2wpkh_script) ;
2352+
2353+ // Confirm the counterparty's commitment and reload the monitor (either before or after) such
2354+ // that we arrive at the correct `counterparty_payment_script` after the reload.
2355+ nodes[ 0 ] . node . force_close_broadcasting_latest_txn ( & chan_id, & nodes[ 1 ] . node . get_our_node_id ( ) ) . unwrap ( ) ;
2356+ check_added_monitors ( & nodes[ 0 ] , 1 ) ;
2357+ check_closed_broadcast ( & nodes[ 0 ] , 1 , true ) ;
2358+ check_closed_event ! ( & nodes[ 0 ] , 1 , ClosureReason :: HolderForceClosed , false ,
2359+ [ nodes[ 1 ] . node. get_our_node_id( ) ] , 100000 ) ;
2360+
2361+ let commitment_tx = {
2362+ let mut txn = nodes[ 0 ] . tx_broadcaster . unique_txn_broadcast ( ) ;
2363+ assert_eq ! ( txn. len( ) , 1 ) ;
2364+ assert_eq ! ( txn[ 0 ] . output. len( ) , 4 ) ;
2365+ check_spends ! ( txn[ 0 ] , funding_tx) ;
2366+ txn. pop ( ) . unwrap ( )
2367+ } ;
2368+
2369+ mine_transaction ( & nodes[ 0 ] , & commitment_tx) ;
2370+ let commitment_tx_conf_height = if confirm_commitment_before_reload {
2371+ // We should expect our round trip serialization check to fail as we're writing the monitor
2372+ // with the incorrect P2WPKH script but reading it with the correct P2WSH script.
2373+ * nodes[ 1 ] . chain_monitor . expect_monitor_round_trip_fail . lock ( ) . unwrap ( ) = Some ( chan_id) ;
2374+ let commitment_tx_conf_height = block_from_scid ( & mine_transaction ( & nodes[ 1 ] , & commitment_tx) ) ;
2375+ let serialized_monitor = get_monitor ! ( nodes[ 1 ] , chan_id) . encode ( ) ;
2376+ reload_node ! ( nodes[ 1 ] , user_config, & nodes[ 1 ] . node. encode( ) , & [ & serialized_monitor] , persister, chain_monitor, node_deserialized) ;
2377+ commitment_tx_conf_height
2378+ } else {
2379+ let serialized_monitor = get_monitor ! ( nodes[ 1 ] , chan_id) . encode ( ) ;
2380+ reload_node ! ( nodes[ 1 ] , user_config, & nodes[ 1 ] . node. encode( ) , & [ & serialized_monitor] , persister, chain_monitor, node_deserialized) ;
2381+ let commitment_tx_conf_height = block_from_scid ( & mine_transaction ( & nodes[ 1 ] , & commitment_tx) ) ;
2382+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
2383+ check_closed_broadcast ( & nodes[ 1 ] , 1 , true ) ;
2384+ commitment_tx_conf_height
2385+ } ;
2386+ check_closed_event ! ( & nodes[ 1 ] , 1 , ClosureReason :: CommitmentTxConfirmed , false ,
2387+ [ nodes[ 0 ] . node. get_our_node_id( ) ] , 100000 ) ;
2388+ assert ! ( get_monitor!( nodes[ 1 ] , chan_id) . get_counterparty_payment_script( ) . is_v0_p2wsh( ) ) ;
2389+
2390+ connect_blocks ( & nodes[ 0 ] , ANTI_REORG_DELAY - 1 ) ;
2391+ connect_blocks ( & nodes[ 1 ] , ANTI_REORG_DELAY - 1 ) ;
2392+
2393+ if confirm_commitment_before_reload {
2394+ // If we saw the commitment before our `counterparty_payment_script` was fixed, we'll never
2395+ // get the spendable output event for the `to_remote` output, so we'll need to get it
2396+ // manually via `get_spendable_outputs`.
2397+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
2398+ let outputs = get_monitor ! ( nodes[ 1 ] , chan_id) . get_spendable_outputs ( & commitment_tx, commitment_tx_conf_height) ;
2399+ assert_eq ! ( outputs. len( ) , 1 ) ;
2400+ let spend_tx = nodes[ 1 ] . keys_manager . backing . spend_spendable_outputs (
2401+ & [ & outputs[ 0 ] ] , Vec :: new ( ) , Builder :: new ( ) . push_opcode ( opcodes:: all:: OP_RETURN ) . into_script ( ) ,
2402+ 253 , None , & secp
2403+ ) . unwrap ( ) ;
2404+ check_spends ! ( spend_tx, & commitment_tx) ;
2405+ } else {
2406+ test_spendable_output ( & nodes[ 1 ] , & commitment_tx) ;
2407+ }
2408+ }
2409+
2410+ #[ test]
2411+ fn test_anchors_monitor_fixes_counterparty_payment_script_on_reload ( ) {
2412+ do_test_anchors_monitor_fixes_counterparty_payment_script_on_reload ( false ) ;
2413+ do_test_anchors_monitor_fixes_counterparty_payment_script_on_reload ( true ) ;
2414+ }
0 commit comments