@@ -2078,3 +2078,302 @@ pub fn test_update_fulfill_htlc_bolt2_missing_badonion_bit_for_malformed_htlc_me
20782078 let reason = ClosureReason :: ProcessingError { err : err_msg. data } ;
20792079 check_closed_event ! ( nodes[ 0 ] , 1 , reason, [ node_b_id] , 1000000 ) ;
20802080}
2081+
2082+ #[ xtest( feature = "_externalize_tests" ) ]
2083+ pub fn test_dust_limit_fee_accounting ( ) {
2084+ do_test_dust_limit_fee_accounting ( false ) ;
2085+ do_test_dust_limit_fee_accounting ( true ) ;
2086+ }
2087+
2088+ pub fn do_test_dust_limit_fee_accounting ( can_afford : bool ) {
2089+ // Test that when a channel funder sends HTLCs exactly on the dust limit
2090+ // of the funder, the fundee correctly accounts for the additional fee on the
2091+ // funder's commitment transaction due to those additional non-dust HTLCs when
2092+ // checking for any infrigements on the funder's reserve.
2093+
2094+ let channel_type = ChannelTypeFeatures :: anchors_zero_htlc_fee_and_dependencies ( ) ;
2095+
2096+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
2097+
2098+ let mut default_config = test_default_channel_config ( ) ;
2099+ default_config. channel_handshake_config . negotiate_anchors_zero_fee_htlc_tx = true ;
2100+ default_config. manually_accept_inbound_channels = true ;
2101+
2102+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
2103+ let node_chanmgrs =
2104+ create_node_chanmgrs ( 2 , & node_cfgs, & [ Some ( default_config. clone ( ) ) , Some ( default_config) ] ) ;
2105+
2106+ let mut nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
2107+
2108+ let node_a_id = nodes[ 0 ] . node . get_our_node_id ( ) ;
2109+ let node_b_id = nodes[ 1 ] . node . get_our_node_id ( ) ;
2110+
2111+ // Set a HTLC amount that is equal to the dust limit of the funder
2112+ const HTLC_AMT_SAT : u64 = 354 ;
2113+
2114+ const CHANNEL_VALUE_SAT : u64 = 100_000 ;
2115+
2116+ const FEERATE_PER_KW : u32 = 253 ;
2117+
2118+ let commit_tx_fee_sat =
2119+ chan_utils:: commit_tx_fee_sat ( FEERATE_PER_KW , MIN_AFFORDABLE_HTLC_COUNT , & channel_type) ;
2120+
2121+ // By default the reserve is set to 1% or 1000sat, whichever is higher
2122+ let channel_reserve_satoshis = 1_000 ;
2123+
2124+ // Set node 0's balance to pay for exactly MIN_AFFORDABLE_HTLC_COUNT non-dust HTLCs on the channel, minus some offset
2125+ let node_0_balance_sat = commit_tx_fee_sat
2126+ + channel_reserve_satoshis
2127+ + 2 * crate :: ln:: channel:: ANCHOR_OUTPUT_VALUE_SATOSHI
2128+ + MIN_AFFORDABLE_HTLC_COUNT as u64 * HTLC_AMT_SAT
2129+ - if can_afford { 0 } else { 1 } ;
2130+ let mut node_1_balance_sat = CHANNEL_VALUE_SAT - node_0_balance_sat;
2131+
2132+ let chan_id = create_chan_between_nodes_with_value (
2133+ & nodes[ 0 ] ,
2134+ & nodes[ 1 ] ,
2135+ CHANNEL_VALUE_SAT ,
2136+ node_1_balance_sat * 1000 ,
2137+ )
2138+ . 3 ;
2139+
2140+ {
2141+ // Double check the reserve that node 0 has to maintain here
2142+ let per_peer_state_lock;
2143+ let mut peer_state_lock;
2144+ let chan =
2145+ get_channel_ref ! ( nodes[ 1 ] , nodes[ 0 ] , per_peer_state_lock, peer_state_lock, chan_id) ;
2146+ assert_eq ! (
2147+ chan. funding( ) . holder_selected_channel_reserve_satoshis,
2148+ channel_reserve_satoshis
2149+ ) ;
2150+ }
2151+ {
2152+ // Double check the dust limit on node 0's commitment transactions; when node 0
2153+ // adds a HTLC, node 1 will check that the fee on node 0's commitment transaction
2154+ // does not dip under the node 1 selected reserve.
2155+ let per_peer_state_lock;
2156+ let mut peer_state_lock;
2157+ let chan =
2158+ get_channel_ref ! ( nodes[ 0 ] , nodes[ 1 ] , per_peer_state_lock, peer_state_lock, chan_id) ;
2159+ assert_eq ! ( chan. context( ) . holder_dust_limit_satoshis, HTLC_AMT_SAT ) ;
2160+ }
2161+
2162+ // Precompute the route to skip any router complaints when sending the last HTLC
2163+ let ( route_0_1, payment_hash_0_1, _, payment_secret_0_1) =
2164+ get_route_and_payment_hash ! ( nodes[ 0 ] , nodes[ 1 ] , HTLC_AMT_SAT * 1000 ) ;
2165+
2166+ let mut htlcs = Vec :: new ( ) ;
2167+ for _ in 0 ..MIN_AFFORDABLE_HTLC_COUNT - 1 {
2168+ let ( _payment_preimage, payment_hash, ..) =
2169+ route_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , HTLC_AMT_SAT * 1000 ) ;
2170+ // Grab a snapshot of these HTLCs to manually build the commitment transaction later...
2171+ let accepted_htlc = chan_utils:: HTLCOutputInCommitment {
2172+ offered : false ,
2173+ amount_msat : HTLC_AMT_SAT * 1000 ,
2174+ // Hard-coded to match the expected value
2175+ cltv_expiry : 81 ,
2176+ payment_hash,
2177+ transaction_output_index : None ,
2178+ } ;
2179+ htlcs. push ( accepted_htlc) ;
2180+ }
2181+
2182+ // Need to manually create the update_add_htlc message to go around the channel reserve check in send_htlc()
2183+ let secp_ctx = Secp256k1 :: new ( ) ;
2184+ let session_priv = SecretKey :: from_slice ( & [ 42 ; 32 ] ) . expect ( "RNG is bad!" ) ;
2185+
2186+ let cur_height = nodes[ 1 ] . node . best_block . read ( ) . unwrap ( ) . height + 1 ;
2187+
2188+ let onion_keys =
2189+ onion_utils:: construct_onion_keys ( & secp_ctx, & route_0_1. paths [ 0 ] , & session_priv) ;
2190+ let recipient_onion_fields = RecipientOnionFields :: secret_only ( payment_secret_0_1) ;
2191+ let ( onion_payloads, amount_msat, cltv_expiry) = onion_utils:: build_onion_payloads (
2192+ & route_0_1. paths [ 0 ] ,
2193+ HTLC_AMT_SAT * 1000 ,
2194+ & recipient_onion_fields,
2195+ cur_height,
2196+ & None ,
2197+ None ,
2198+ None ,
2199+ )
2200+ . unwrap ( ) ;
2201+ let onion_routing_packet =
2202+ onion_utils:: construct_onion_packet ( onion_payloads, onion_keys, [ 0 ; 32 ] , & payment_hash_0_1)
2203+ . unwrap ( ) ;
2204+ // Double check the hard-coded value
2205+ assert_eq ! ( cltv_expiry, 81 ) ;
2206+ let msg = msgs:: UpdateAddHTLC {
2207+ channel_id : chan_id,
2208+ htlc_id : MIN_AFFORDABLE_HTLC_COUNT as u64 - 1 ,
2209+ amount_msat,
2210+ payment_hash : payment_hash_0_1,
2211+ cltv_expiry,
2212+ onion_routing_packet,
2213+ skimmed_fee_msat : None ,
2214+ blinding_point : None ,
2215+ } ;
2216+
2217+ nodes[ 1 ] . node . handle_update_add_htlc ( node_a_id, & msg) ;
2218+
2219+ if !can_afford {
2220+ let err = "Remote HTLC add would put them under remote reserve value" . to_string ( ) ;
2221+ nodes[ 1 ] . logger . assert_log_contains ( "lightning::ln::channelmanager" , & err, 3 ) ;
2222+ let events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
2223+ assert_eq ! ( events. len( ) , 2 ) ;
2224+ let reason = ClosureReason :: ProcessingError { err } ;
2225+ check_closed_event ( & nodes[ 1 ] , 1 , reason, false , & [ node_a_id] , CHANNEL_VALUE_SAT ) ;
2226+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
2227+ } else {
2228+ // Now manually create the commitment_signed message corresponding to the update_add
2229+ // nodes[0] just sent. In the code for construction of this message, "local" refers
2230+ // to the sender of the message, and "remote" refers to the receiver.
2231+
2232+ const INITIAL_COMMITMENT_NUMBER : u64 = ( 1 << 48 ) - 1 ;
2233+
2234+ let ( local_secret, next_local_point) = {
2235+ let per_peer_state = nodes[ 0 ] . node . per_peer_state . read ( ) . unwrap ( ) ;
2236+ let chan_lock = per_peer_state. get ( & node_b_id) . unwrap ( ) . lock ( ) . unwrap ( ) ;
2237+ let local_chan =
2238+ chan_lock. channel_by_id . get ( & chan_id) . and_then ( Channel :: as_funded) . unwrap ( ) ;
2239+ let chan_signer = local_chan. get_signer ( ) ;
2240+ // Make the signer believe we validated another commitment, so we can release the secret
2241+ chan_signer. as_ecdsa ( ) . unwrap ( ) . get_enforcement_state ( ) . last_holder_commitment -= 1 ;
2242+
2243+ (
2244+ chan_signer
2245+ . as_ref ( )
2246+ . release_commitment_secret (
2247+ INITIAL_COMMITMENT_NUMBER - MIN_AFFORDABLE_HTLC_COUNT as u64 + 1 ,
2248+ )
2249+ . unwrap ( ) ,
2250+ chan_signer
2251+ . as_ref ( )
2252+ . get_per_commitment_point (
2253+ INITIAL_COMMITMENT_NUMBER - MIN_AFFORDABLE_HTLC_COUNT as u64 ,
2254+ & secp_ctx,
2255+ )
2256+ . unwrap ( ) ,
2257+ )
2258+ } ;
2259+ let remote_point = {
2260+ let per_peer_lock;
2261+ let mut peer_state_lock;
2262+
2263+ let channel =
2264+ get_channel_ref ! ( nodes[ 1 ] , nodes[ 0 ] , per_peer_lock, peer_state_lock, chan_id) ;
2265+ let chan_signer = channel. as_funded ( ) . unwrap ( ) . get_signer ( ) ;
2266+ chan_signer
2267+ . as_ref ( )
2268+ . get_per_commitment_point (
2269+ INITIAL_COMMITMENT_NUMBER - MIN_AFFORDABLE_HTLC_COUNT as u64 ,
2270+ & secp_ctx,
2271+ )
2272+ . unwrap ( )
2273+ } ;
2274+
2275+ // Build the remote commitment transaction so we can sign it, and then later use the
2276+ // signature for the commitment_signed message.
2277+ let local_chan_balance = node_0_balance_sat
2278+ - HTLC_AMT_SAT * MIN_AFFORDABLE_HTLC_COUNT as u64
2279+ - 2 * crate :: ln:: channel:: ANCHOR_OUTPUT_VALUE_SATOSHI
2280+ - chan_utils:: commit_tx_fee_sat (
2281+ FEERATE_PER_KW ,
2282+ MIN_AFFORDABLE_HTLC_COUNT ,
2283+ & channel_type,
2284+ ) ;
2285+
2286+ let accepted_htlc_info = chan_utils:: HTLCOutputInCommitment {
2287+ offered : false ,
2288+ amount_msat : HTLC_AMT_SAT * 1000 ,
2289+ cltv_expiry,
2290+ payment_hash : payment_hash_0_1,
2291+ transaction_output_index : None ,
2292+ } ;
2293+ htlcs. push ( accepted_htlc_info) ;
2294+
2295+ let commitment_number = INITIAL_COMMITMENT_NUMBER - MIN_AFFORDABLE_HTLC_COUNT as u64 ;
2296+
2297+ let res = {
2298+ let per_peer_lock;
2299+ let mut peer_state_lock;
2300+
2301+ let channel =
2302+ get_channel_ref ! ( nodes[ 0 ] , nodes[ 1 ] , per_peer_lock, peer_state_lock, chan_id) ;
2303+ let chan_signer = channel. as_funded ( ) . unwrap ( ) . get_signer ( ) ;
2304+
2305+ let commitment_tx = CommitmentTransaction :: new (
2306+ commitment_number,
2307+ & remote_point,
2308+ node_1_balance_sat,
2309+ local_chan_balance,
2310+ FEERATE_PER_KW ,
2311+ htlcs,
2312+ & channel. funding ( ) . channel_transaction_parameters . as_counterparty_broadcastable ( ) ,
2313+ & secp_ctx,
2314+ ) ;
2315+ let params = & channel. funding ( ) . channel_transaction_parameters ;
2316+ chan_signer
2317+ . as_ecdsa ( )
2318+ . unwrap ( )
2319+ . sign_counterparty_commitment (
2320+ params,
2321+ & commitment_tx,
2322+ Vec :: new ( ) ,
2323+ Vec :: new ( ) ,
2324+ & secp_ctx,
2325+ )
2326+ . unwrap ( )
2327+ } ;
2328+
2329+ let commit_signed_msg = msgs:: CommitmentSigned {
2330+ channel_id : chan_id,
2331+ signature : res. 0 ,
2332+ htlc_signatures : res. 1 ,
2333+ funding_txid : None ,
2334+ #[ cfg( taproot) ]
2335+ partial_signature_with_nonce : None ,
2336+ } ;
2337+
2338+ // Send the commitment_signed message to the nodes[1].
2339+ nodes[ 1 ] . node . handle_commitment_signed ( node_a_id, & commit_signed_msg) ;
2340+ let _ = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
2341+
2342+ // Send the RAA to nodes[1].
2343+ let raa_msg = msgs:: RevokeAndACK {
2344+ channel_id : chan_id,
2345+ per_commitment_secret : local_secret,
2346+ next_per_commitment_point : next_local_point,
2347+ #[ cfg( taproot) ]
2348+ next_local_nonce : None ,
2349+ } ;
2350+ nodes[ 1 ] . node . handle_revoke_and_ack ( node_a_id, & raa_msg) ;
2351+
2352+ // The HTLC actually fails here in `fn validate_commitment_signed` due to a fee spike buffer
2353+ // violation. It nonetheless passed all checks in `fn validate_update_add_htlc`.
2354+
2355+ expect_pending_htlcs_forwardable ! ( nodes[ 1 ] ) ;
2356+ expect_htlc_handling_failed_destinations ! (
2357+ nodes[ 1 ] . node. get_and_clear_pending_events( ) ,
2358+ & [ HTLCHandlingFailureType :: Receive { payment_hash: payment_hash_0_1 } ]
2359+ ) ;
2360+
2361+ let events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
2362+ assert_eq ! ( events. len( ) , 1 ) ;
2363+ // Make sure the HTLC failed in the way we expect.
2364+ match events[ 0 ] {
2365+ MessageSendEvent :: UpdateHTLCs {
2366+ updates : msgs:: CommitmentUpdate { ref update_fail_htlcs, .. } ,
2367+ ..
2368+ } => {
2369+ assert_eq ! ( update_fail_htlcs. len( ) , 1 ) ;
2370+ update_fail_htlcs[ 0 ] . clone ( )
2371+ } ,
2372+ _ => panic ! ( "Unexpected event" ) ,
2373+ } ;
2374+ nodes[ 1 ] . logger . assert_log ( "lightning::ln::channel" ,
2375+ format ! ( "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required." , raa_msg. channel_id) , 1 ) ;
2376+
2377+ check_added_monitors ( & nodes[ 1 ] , 3 ) ;
2378+ }
2379+ }
0 commit comments