@@ -2294,16 +2294,20 @@ fn test_anchors_aggregated_revoked_htlc_tx() {
2294
2294
2295
2295
assert ! ( nodes[ 1 ] . chain_monitor. chain_monitor. get_and_clear_pending_events( ) . is_empty( ) ) ;
2296
2296
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 {
2299
2299
if let Event :: SpendableOutputs { outputs, channel_id } = event {
2300
2300
assert_eq ! ( outputs. len( ) , 1 ) ;
2301
2301
assert ! ( vec![ chan_b. 2 , chan_a. 2 ] . contains( & channel_id. unwrap( ) ) ) ;
2302
2302
let spend_tx = nodes[ 0 ] . keys_manager . backing . spend_spendable_outputs (
2303
2303
& [ & outputs[ 0 ] ] , Vec :: new ( ) , Script :: new_op_return ( & [ ] ) , 253 , None , & Secp256k1 :: new ( ) ,
2304
2304
) . unwrap ( ) ;
2305
2305
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
+ }
2307
2311
} else {
2308
2312
panic ! ( "unexpected event" ) ;
2309
2313
}
@@ -2321,3 +2325,90 @@ fn test_anchors_aggregated_revoked_htlc_tx() {
2321
2325
// revoked commitment which Bob has the preimage for.
2322
2326
assert_eq ! ( nodes[ 1 ] . chain_monitor. chain_monitor. get_claimable_balances( & [ ] ) . len( ) , 6 ) ;
2323
2327
}
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