@@ -11765,3 +11765,142 @@ pub fn test_funding_signed_event() {
1176511765 nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
1176611766 nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
1176711767}
11768+
11769+ #[ xtest( feature = "_externalize_tests" ) ]
11770+ pub fn test_claimed_htlcs_not_in_pending_claim_requests ( ) {
11771+ use crate :: events:: bump_transaction:: sync:: WalletSourceSync ;
11772+
11773+ // ====== TEST SETUP ======
11774+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
11775+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
11776+
11777+ let mut user_cfg = test_default_channel_config ( ) ;
11778+
11779+ // Anchor channels are required so that multiple HTLC-Successes can be aggregated into a single
11780+ // transaction.
11781+ user_cfg. channel_handshake_config . negotiate_anchors_zero_fee_htlc_tx = true ;
11782+ user_cfg. manually_accept_inbound_channels = true ;
11783+
11784+ let configs = [ Some ( user_cfg. clone ( ) ) , Some ( user_cfg. clone ( ) ) ] ;
11785+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & configs) ;
11786+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
11787+
11788+ let node_a_id = nodes[ 0 ] . node . get_our_node_id ( ) ;
11789+ let node_b_id = nodes[ 1 ] . node . get_our_node_id ( ) ;
11790+
11791+ // Since we're using anchor channels, make sure each node has a UTXO for paying fees.
11792+ let coinbase_tx = Transaction {
11793+ version : Version :: TWO ,
11794+ lock_time : LockTime :: ZERO ,
11795+ input : vec ! [ TxIn { ..Default :: default ( ) } ] ,
11796+ output : vec ! [
11797+ TxOut {
11798+ value: Amount :: ONE_BTC ,
11799+ script_pubkey: nodes[ 0 ] . wallet_source. get_change_script( ) . unwrap( ) ,
11800+ } ,
11801+ TxOut {
11802+ value: Amount :: ONE_BTC ,
11803+ script_pubkey: nodes[ 1 ] . wallet_source. get_change_script( ) . unwrap( ) ,
11804+ } ,
11805+ ] ,
11806+ } ;
11807+ nodes[ 0 ] . wallet_source . add_utxo (
11808+ bitcoin:: OutPoint { txid : coinbase_tx. compute_txid ( ) , vout : 0 } ,
11809+ coinbase_tx. output [ 0 ] . value ,
11810+ ) ;
11811+ nodes[ 1 ] . wallet_source . add_utxo (
11812+ bitcoin:: OutPoint { txid : coinbase_tx. compute_txid ( ) , vout : 1 } ,
11813+ coinbase_tx. output [ 1 ] . value ,
11814+ ) ;
11815+
11816+ const CHAN_CAPACITY : u64 = 10_000_000 ;
11817+ let ( _, _, cid, funding_tx) =
11818+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , CHAN_CAPACITY , 0 ) ;
11819+
11820+ // Ensure all nodes are at the same initial height.
11821+ let node_max_height = nodes. iter ( ) . map ( |node| node. best_block_info ( ) . 1 ) . max ( ) . unwrap ( ) ;
11822+ for node in & nodes {
11823+ let blocks_to_mine = node_max_height - node. best_block_info ( ) . 1 ;
11824+ if blocks_to_mine > 0 {
11825+ connect_blocks ( node, blocks_to_mine) ;
11826+ }
11827+ }
11828+
11829+ // ====== TEST PROCESS ======
11830+
11831+ // Route HTLC 1 and 2 from A to B.
11832+ let ( preimage_1, payment_hash_1, ..) = route_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , 1_000_000 ) ;
11833+ let ( _preimage_2, _payment_hash_2, ..) = route_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , 1_000_000 ) ;
11834+
11835+ // Node A claims HTLC 1.
11836+ nodes[ 1 ] . node . claim_funds ( preimage_1) ;
11837+ expect_payment_claimed ! ( nodes[ 1 ] , payment_hash_1, 1_000_000 ) ;
11838+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
11839+ let _ = get_htlc_update_msgs ( & nodes[ 1 ] , & node_a_id) ;
11840+
11841+ // Force close the channel by broadcasting node B's commitment tx.
11842+ let node_b_commit_tx = get_local_commitment_txn ! ( nodes[ 1 ] , cid) ;
11843+ assert_eq ! ( node_b_commit_tx. len( ) , 1 ) ;
11844+ let node_b_commit_tx = & node_b_commit_tx[ 0 ] ;
11845+ check_spends ! ( node_b_commit_tx, funding_tx) ;
11846+
11847+ mine_transaction ( & nodes[ 0 ] , node_b_commit_tx) ;
11848+ check_closed_event (
11849+ & nodes[ 0 ] ,
11850+ 1 ,
11851+ ClosureReason :: CommitmentTxConfirmed ,
11852+ false ,
11853+ & [ node_b_id] ,
11854+ CHAN_CAPACITY ,
11855+ ) ;
11856+ check_closed_broadcast ! ( nodes[ 0 ] , true ) ;
11857+ check_added_monitors ( & nodes[ 0 ] , 1 ) ;
11858+
11859+ mine_transaction ( & nodes[ 1 ] , node_b_commit_tx) ;
11860+ check_closed_event (
11861+ & nodes[ 1 ] ,
11862+ 1 ,
11863+ ClosureReason :: CommitmentTxConfirmed ,
11864+ false ,
11865+ & [ node_a_id] ,
11866+ CHAN_CAPACITY ,
11867+ ) ;
11868+ check_closed_broadcast ! ( nodes[ 1 ] , true ) ;
11869+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
11870+
11871+ // Confirm HTLC 1 claiming tx on node A.
11872+ let process_bump_event = |node : & Node | {
11873+ let events = node. chain_monitor . chain_monitor . get_and_clear_pending_events ( ) ;
11874+ assert_eq ! ( events. len( ) , 1 ) ;
11875+ let bump_event = match & events[ 0 ] {
11876+ Event :: BumpTransaction ( bump_event) => bump_event,
11877+ e => panic ! ( "Unexepected event: {:#?}" , e) ,
11878+ } ;
11879+ node. bump_tx_handler . handle_event ( bump_event) ;
11880+
11881+ let mut tx = node. tx_broadcaster . txn_broadcast ( ) ;
11882+ assert_eq ! ( tx. len( ) , 1 ) ;
11883+ tx. pop ( ) . unwrap ( )
11884+ } ;
11885+ let htlc_1_claiming_tx = process_bump_event ( & nodes[ 1 ] ) ;
11886+
11887+ mine_transaction ( & nodes[ 0 ] , & htlc_1_claiming_tx) ;
11888+ // Node A reaches the HTLC timeout height.
11889+ connect_blocks ( & nodes[ 0 ] , TEST_FINAL_CLTV - 1 ) ;
11890+
11891+ // Check that node A times out only HTLC 2, and does not attempt to timeout the already
11892+ // claimed HTLC 1.
11893+ let timeout_tx = {
11894+ let mut txs = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ;
11895+ assert_eq ! ( txs. len( ) , 1 ) ;
11896+ txs. pop ( ) . unwrap ( )
11897+ } ;
11898+ let htlc_already_claimed = htlc_1_claiming_tx. input . iter ( ) . any ( |htlc|{
11899+ htlc. previous_output == timeout_tx. input [ 0 ] . previous_output
11900+ } ) ;
11901+ assert ! ( !htlc_already_claimed, "HTLC already claimed by counterparty's HTLC-Success transaction" ) ;
11902+ assert_eq ! ( timeout_tx. input. len( ) , 1 ) ;
11903+
11904+ let events = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
11905+ assert_eq ! ( events. len( ) , 2 ) ;
11906+ }
0 commit comments