@@ -732,8 +732,9 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
732
732
test_spendable_output ( & nodes[ 0 ] , & remote_txn[ 0 ] , false ) ;
733
733
assert ! ( nodes[ 1 ] . chain_monitor. chain_monitor. get_and_clear_pending_events( ) . is_empty( ) ) ;
734
734
735
- // After broadcasting the HTLC claim transaction, node A will still consider the HTLC
736
- // possibly-claimable up to ANTI_REORG_DELAY, at which point it will drop it.
735
+ // After confirming the HTLC claim transaction, node A will no longer attempt to claim said
736
+ // HTLC, unless the transaction is reorged. However, we'll still report a
737
+ // `MaybeTimeoutClaimableHTLC` balance for it until we reach `ANTI_REORG_DELAY` confirmations.
737
738
mine_transaction ( & nodes[ 0 ] , & b_broadcast_txn[ 0 ] ) ;
738
739
if prev_commitment_tx {
739
740
expect_payment_path_successful ! ( nodes[ 0 ] ) ;
@@ -749,18 +750,10 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
749
750
// When the HTLC timeout output is spendable in the next block, A should broadcast it
750
751
connect_blocks ( & nodes[ 0 ] , htlc_cltv_timeout - nodes[ 0 ] . best_block_info ( ) . 1 ) ;
751
752
let a_broadcast_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . split_off ( 0 ) ;
752
- // Aggregated claim transaction.
753
753
assert_eq ! ( a_broadcast_txn. len( ) , 1 ) ;
754
754
check_spends ! ( a_broadcast_txn[ 0 ] , remote_txn[ 0 ] ) ;
755
- assert_eq ! ( a_broadcast_txn[ 0 ] . input. len( ) , 2 ) ;
756
- assert_ne ! ( a_broadcast_txn[ 0 ] . input[ 0 ] . previous_output. vout, a_broadcast_txn[ 0 ] . input[ 1 ] . previous_output. vout) ;
757
- // a_broadcast_txn [0] and [1] should spend the HTLC outputs of the commitment tx
758
- assert ! ( a_broadcast_txn[ 0 ] . input. iter( ) . any( |input| remote_txn[ 0 ] . output[ input. previous_output. vout as usize ] . value. to_sat( ) == 3_000 ) ) ;
755
+ assert_eq ! ( a_broadcast_txn[ 0 ] . input. len( ) , 1 ) ;
759
756
assert ! ( a_broadcast_txn[ 0 ] . input. iter( ) . any( |input| remote_txn[ 0 ] . output[ input. previous_output. vout as usize ] . value. to_sat( ) == 4_000 ) ) ;
760
-
761
- // Confirm node B's claim for node A to remove that claim from the aggregated claim transaction.
762
- mine_transaction ( & nodes[ 0 ] , & b_broadcast_txn[ 0 ] ) ;
763
- let a_broadcast_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . split_off ( 0 ) ;
764
757
let a_htlc_timeout_tx = a_broadcast_txn. into_iter ( ) . next_back ( ) . unwrap ( ) ;
765
758
766
759
// Once the HTLC-Timeout transaction confirms, A will no longer consider the HTLC
@@ -3328,3 +3321,162 @@ fn test_update_replay_panics() {
3328
3321
monitor. update_monitor ( & updates[ 2 ] , & nodes[ 1 ] . tx_broadcaster , & nodes[ 1 ] . fee_estimator , & nodes[ 1 ] . logger ) . unwrap ( ) ;
3329
3322
monitor. update_monitor ( & updates[ 3 ] , & nodes[ 1 ] . tx_broadcaster , & nodes[ 1 ] . fee_estimator , & nodes[ 1 ] . logger ) . unwrap ( ) ;
3330
3323
}
3324
+
3325
+ #[ test]
3326
+ pub fn test_pruned_locktimed_packages_recovery_after_block_disconnected ( ) {
3327
+ use crate :: events:: bump_transaction:: sync:: WalletSourceSync ;
3328
+
3329
+ // ====== TEST SETUP ======
3330
+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
3331
+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
3332
+
3333
+ let mut user_cfg = test_default_channel_config ( ) ;
3334
+ user_cfg. channel_handshake_config . negotiate_anchors_zero_fee_htlc_tx = true ;
3335
+ user_cfg. manually_accept_inbound_channels = true ;
3336
+
3337
+ let configs = [ Some ( user_cfg. clone ( ) ) , Some ( user_cfg. clone ( ) ) ] ;
3338
+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & configs) ;
3339
+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
3340
+
3341
+ let node_a_id = nodes[ 0 ] . node . get_our_node_id ( ) ;
3342
+ let node_b_id = nodes[ 1 ] . node . get_our_node_id ( ) ;
3343
+
3344
+ // Since we're using anchor channels, make sure each node has a UTXO for paying fees.
3345
+ let coinbase_tx = Transaction {
3346
+ version : Version :: TWO ,
3347
+ lock_time : LockTime :: ZERO ,
3348
+ input : vec ! [ TxIn { ..Default :: default ( ) } ] ,
3349
+ output : vec ! [
3350
+ TxOut {
3351
+ value: Amount :: ONE_BTC ,
3352
+ script_pubkey: nodes[ 0 ] . wallet_source. get_change_script( ) . unwrap( ) ,
3353
+ } ,
3354
+ TxOut {
3355
+ value: Amount :: ONE_BTC ,
3356
+ script_pubkey: nodes[ 1 ] . wallet_source. get_change_script( ) . unwrap( ) ,
3357
+ } ,
3358
+ ] ,
3359
+ } ;
3360
+ nodes[ 0 ] . wallet_source . add_utxo (
3361
+ bitcoin:: OutPoint { txid : coinbase_tx. compute_txid ( ) , vout : 0 } ,
3362
+ coinbase_tx. output [ 0 ] . value ,
3363
+ ) ;
3364
+ nodes[ 1 ] . wallet_source . add_utxo (
3365
+ bitcoin:: OutPoint { txid : coinbase_tx. compute_txid ( ) , vout : 1 } ,
3366
+ coinbase_tx. output [ 1 ] . value ,
3367
+ ) ;
3368
+
3369
+ const CHAN_CAPACITY : u64 = 10_000_000 ;
3370
+ let ( _, _, channel_id, funding_tx) =
3371
+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , CHAN_CAPACITY , 0 ) ;
3372
+
3373
+ // Ensure all nodes are at the same initial height.
3374
+ let node_max_height = nodes. iter ( ) . map ( |node| node. best_block_info ( ) . 1 ) . max ( ) . unwrap ( ) ;
3375
+ for node in & nodes {
3376
+ let blocks_to_mine = node_max_height - node. best_block_info ( ) . 1 ;
3377
+ if blocks_to_mine > 0 {
3378
+ connect_blocks ( node, blocks_to_mine) ;
3379
+ }
3380
+ }
3381
+
3382
+ // ====== TEST PROCESS ======
3383
+
3384
+ // Route HTLC 1 from A to B.
3385
+ let ( preimage_1, payment_hash_1, ..) = route_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , 1_000_000 ) ;
3386
+
3387
+ // Node B claims HTLC 1.
3388
+ nodes[ 1 ] . node . claim_funds ( preimage_1) ;
3389
+ expect_payment_claimed ! ( nodes[ 1 ] , payment_hash_1, 1_000_000 ) ;
3390
+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
3391
+ let _ = get_htlc_update_msgs ( & nodes[ 1 ] , & node_a_id) ;
3392
+
3393
+ // Force close the channel by broadcasting node B's commitment tx.
3394
+ let node_b_commit_tx = get_local_commitment_txn ! ( nodes[ 1 ] , channel_id) ;
3395
+ assert_eq ! ( node_b_commit_tx. len( ) , 1 ) ;
3396
+ let node_b_commit_tx = & node_b_commit_tx[ 0 ] ;
3397
+ check_spends ! ( node_b_commit_tx, funding_tx) ;
3398
+
3399
+ let htlc_1_locktime = nodes[ 0 ] . best_block_info ( ) . 1 + 1 + TEST_FINAL_CLTV ;
3400
+ mine_transaction ( & nodes[ 0 ] , node_b_commit_tx) ;
3401
+ check_closed_event (
3402
+ & nodes[ 0 ] ,
3403
+ 1 ,
3404
+ ClosureReason :: CommitmentTxConfirmed ,
3405
+ false ,
3406
+ & [ node_b_id] ,
3407
+ CHAN_CAPACITY ,
3408
+ ) ;
3409
+ check_closed_broadcast ! ( nodes[ 0 ] , true ) ;
3410
+ check_added_monitors ( & nodes[ 0 ] , 1 ) ;
3411
+
3412
+ mine_transaction ( & nodes[ 1 ] , node_b_commit_tx) ;
3413
+ check_closed_event (
3414
+ & nodes[ 1 ] ,
3415
+ 1 ,
3416
+ ClosureReason :: CommitmentTxConfirmed ,
3417
+ false ,
3418
+ & [ node_a_id] ,
3419
+ CHAN_CAPACITY ,
3420
+ ) ;
3421
+ check_closed_broadcast ! ( nodes[ 1 ] , true ) ;
3422
+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
3423
+
3424
+ // Node B generate HTLC 1 claim tx.
3425
+ let process_bump_event = |node : & Node | {
3426
+ let events = node. chain_monitor . chain_monitor . get_and_clear_pending_events ( ) ;
3427
+ assert_eq ! ( events. len( ) , 1 ) ;
3428
+ let bump_event = match & events[ 0 ] {
3429
+ Event :: BumpTransaction ( bump_event) => bump_event,
3430
+ e => panic ! ( "Unexepected event: {:#?}" , e) ,
3431
+ } ;
3432
+ node. bump_tx_handler . handle_event ( bump_event) ;
3433
+
3434
+ let mut tx = node. tx_broadcaster . txn_broadcast ( ) ;
3435
+ assert_eq ! ( tx. len( ) , 1 ) ;
3436
+ tx. pop ( ) . unwrap ( )
3437
+ } ;
3438
+ let bs_htlc_1_claim_tx = process_bump_event ( & nodes[ 1 ] ) ;
3439
+
3440
+ let get_locktimed_packages = || {
3441
+ let monitor = nodes[ 0 ] . chain_monitor . chain_monitor . get_monitor ( channel_id) . unwrap ( ) ;
3442
+ let onchain_tx_handler = & monitor. inner . lock ( ) . unwrap ( ) . onchain_tx_handler ;
3443
+ onchain_tx_handler. locktimed_packages . clone ( )
3444
+ } ;
3445
+
3446
+ let locktimed_packages = get_locktimed_packages ( ) ;
3447
+ let htlc_1_locktimed_package = {
3448
+ let packages = locktimed_packages. get ( & htlc_1_locktime)
3449
+ . expect ( "HTLC 1 locktimed package should exist" ) ;
3450
+ assert_eq ! ( packages. len( ) , 1 , "HTLC 1 locktimed package should have only one package" ) ;
3451
+ packages. first ( ) . unwrap ( ) . clone ( )
3452
+ } ;
3453
+
3454
+ // HTLC 1 claim tx confirmed - Node A should prune its claim request from locktimed HTLC packages.
3455
+ mine_transaction ( & nodes[ 0 ] , & bs_htlc_1_claim_tx) ;
3456
+ let locktimed_packages = get_locktimed_packages ( ) ;
3457
+ assert ! ( locktimed_packages. is_empty( ) , "locktimed packages should be pruned" ) ;
3458
+
3459
+ // Disconnect the block containing HTLC 1 claim tx to simulate a reorg. Node A should recover
3460
+ // the pruned locktimed package.
3461
+ disconnect_blocks ( & nodes[ 0 ] , 1 ) ;
3462
+ let locktimed_packages = get_locktimed_packages ( ) ;
3463
+ let recovered_htlc_1_locktimed_package = {
3464
+ let packages = locktimed_packages. get ( & htlc_1_locktime)
3465
+ . expect ( "HTLC 1 locktimed package should be recovered" ) ;
3466
+ assert_eq ! ( packages. len( ) , 1 , "HTLC 1 locktimed package should have only one package" ) ;
3467
+ packages. first ( ) . unwrap ( ) . clone ( )
3468
+ } ;
3469
+ assert ! ( recovered_htlc_1_locktimed_package == htlc_1_locktimed_package,
3470
+ "Recovered HTLC 1 locktimed package should match the original one" ) ;
3471
+
3472
+ // HTLC 1 locktime expires.
3473
+ connect_blocks ( & nodes[ 0 ] , TEST_FINAL_CLTV ) ;
3474
+ // HTLC 1 timeout tx should be broadcasted.
3475
+ let mut txs = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ;
3476
+ assert_eq ! ( txs. len( ) , 1 ) ;
3477
+ check_spends ! ( txs[ 0 ] , node_b_commit_tx) ;
3478
+
3479
+ // PaymentSent and PaymentPathSuccessful events.
3480
+ let events = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
3481
+ assert_eq ! ( events. len( ) , 2 ) ;
3482
+ }
0 commit comments