@@ -9900,3 +9900,154 @@ pub fn test_multi_post_event_actions() {
99009900 do_test_multi_post_event_actions ( true ) ;
99019901 do_test_multi_post_event_actions ( false ) ;
99029902}
9903+
9904+ #[ xtest( feature = "_externalize_tests" ) ]
9905+ pub fn test_dust_exposure_holding_cell_assertion ( ) {
9906+ // Test that we properly move forward if we pop an HTLC-add from the holding cell but fail to
9907+ // add it to the channel. In 0.2 this cause a (harmless in prod) debug assertion failure. We
9908+ // try to ensure that this won't happen by checking that an HTLC will be able to be added
9909+ // before we add it to the holding cell, so getting into this state takes a bit of work.
9910+ //
9911+ // Here we accomplish this by using the dust exposure limit. This has the unique feature that
9912+ // node C can increase node B's dust exposure on the B <-> C channel without B doing anything.
9913+ // To exploit this, we get node B one HTLC away from being over-exposed to dust, give it one
9914+ // more HTLC in the holding cell, then have node C add an HTLC. By the time the holding-cell
9915+ // HTLC is released we are at max-dust-exposure and will fail it.
9916+
9917+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
9918+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
9919+
9920+ // Configure nodes with specific dust limits
9921+ let mut config = test_default_channel_config ( ) ;
9922+ // Use a fixed dust exposure limit to make the test simpler
9923+ const DUST_HTLC_VALUE_MSAT : u64 = 500_000 ;
9924+ config. channel_config . max_dust_htlc_exposure = MaxDustHTLCExposure :: FixedLimitMsat ( 5_000_000 ) ;
9925+ config. channel_handshake_config . max_inbound_htlc_value_in_flight_percent_of_channel = 100 ;
9926+
9927+ let configs = [ Some ( config. clone ( ) ) , Some ( config. clone ( ) ) , Some ( config. clone ( ) ) ] ;
9928+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & configs) ;
9929+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
9930+
9931+ let node_a_id = nodes[ 0 ] . node . get_our_node_id ( ) ;
9932+ let node_b_id = nodes[ 1 ] . node . get_our_node_id ( ) ;
9933+ let node_c_id = nodes[ 2 ] . node . get_our_node_id ( ) ;
9934+
9935+ // Create channels: A <-> B <-> C
9936+ create_announced_chan_between_nodes ( & nodes, 0 , 1 ) ;
9937+ let bc_chan_id = create_announced_chan_between_nodes ( & nodes, 1 , 2 ) . 2 ;
9938+ send_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] , & nodes[ 2 ] ] , 10_000_000 ) ;
9939+
9940+ // Send multiple dust HTLCs from B to C to approach the dust limit (including transaction fees)
9941+ for _ in 0 ..4 {
9942+ route_payment ( & nodes[ 1 ] , & [ & nodes[ 2 ] ] , DUST_HTLC_VALUE_MSAT ) ;
9943+ }
9944+
9945+ // At this point we shouldn't be over the dust limit, and should still be able to send HTLCs.
9946+ let bs_chans = nodes[ 1 ] . node . list_channels ( ) ;
9947+ let bc_chan = bs_chans. iter ( ) . find ( |chan| chan. counterparty . node_id == node_c_id) . unwrap ( ) ;
9948+ assert_eq ! (
9949+ bc_chan. next_outbound_htlc_minimum_msat,
9950+ config. channel_handshake_config. our_htlc_minimum_msat
9951+ ) ;
9952+
9953+ // Add a further HTLC from B to C, but don't deliver the send messages.
9954+ // After this we'll only have the ability to add one more HTLC, but by not delivering the send
9955+ // messages (leaving B waiting on C's RAA) the next HTLC will go into B's holding cell.
9956+ let ( route_bc, payment_hash_bc, _payment_preimage_bc, payment_secret_bc) =
9957+ get_route_and_payment_hash ! ( nodes[ 1 ] , nodes[ 2 ] , DUST_HTLC_VALUE_MSAT ) ;
9958+ let onion_bc = RecipientOnionFields :: secret_only ( payment_secret_bc) ;
9959+ let id = PaymentId ( payment_hash_bc. 0 ) ;
9960+ nodes[ 1 ] . node . send_payment_with_route ( route_bc, payment_hash_bc, onion_bc, id) . unwrap ( ) ;
9961+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
9962+ let send_bc = SendEvent :: from_node ( & nodes[ 1 ] ) ;
9963+
9964+ let bs_chans = nodes[ 1 ] . node . list_channels ( ) ;
9965+ let bc_chan = bs_chans. iter ( ) . find ( |chan| chan. counterparty . node_id == node_c_id) . unwrap ( ) ;
9966+ assert_eq ! (
9967+ bc_chan. next_outbound_htlc_minimum_msat,
9968+ config. channel_handshake_config. our_htlc_minimum_msat
9969+ ) ;
9970+
9971+ // Forward an additional HTLC from A through B to C. This will go in B's holding cell for node
9972+ // C as it is waiting on a response to the above messages.
9973+ let payment_params_ac = PaymentParameters :: from_node_id ( node_c_id, TEST_FINAL_CLTV )
9974+ . with_bolt11_features ( nodes[ 2 ] . node . bolt11_invoice_features ( ) )
9975+ . unwrap ( ) ;
9976+ let ( route_ac, payment_hash_cell, _, payment_secret_ac) =
9977+ get_route_and_payment_hash ! ( nodes[ 0 ] , nodes[ 2 ] , payment_params_ac, DUST_HTLC_VALUE_MSAT ) ;
9978+ let onion_ac = RecipientOnionFields :: secret_only ( payment_secret_ac) ;
9979+ let id = PaymentId ( payment_hash_cell. 0 ) ;
9980+ nodes[ 0 ] . node . send_payment_with_route ( route_ac, payment_hash_cell, onion_ac, id) . unwrap ( ) ;
9981+ check_added_monitors ( & nodes[ 0 ] , 1 ) ;
9982+
9983+ let send_ab = SendEvent :: from_node ( & nodes[ 0 ] ) ;
9984+ nodes[ 1 ] . node . handle_update_add_htlc ( node_a_id, & send_ab. msgs [ 0 ] ) ;
9985+ do_commitment_signed_dance ( & nodes[ 1 ] , & nodes[ 0 ] , & send_ab. commitment_msg , false , true ) ;
9986+
9987+ // At this point when we process pending forwards the HTLC will go into the holding cell and no
9988+ // further messages will be generated. Node B will also be at its maximum dust exposure and
9989+ // will refuse to send any dust HTLCs (when it includes the holding cell HTLC).
9990+ expect_and_process_pending_htlcs ( & nodes[ 1 ] , false ) ;
9991+ assert ! ( nodes[ 1 ] . node. get_and_clear_pending_msg_events( ) . is_empty( ) ) ;
9992+
9993+ let bs_chans = nodes[ 1 ] . node . list_channels ( ) ;
9994+ let bc_chan = bs_chans. iter ( ) . find ( |chan| chan. counterparty . node_id == node_c_id) . unwrap ( ) ;
9995+ assert ! ( bc_chan. next_outbound_htlc_minimum_msat > DUST_HTLC_VALUE_MSAT ) ;
9996+
9997+ // Send an additional HTLC from C to B. This will make B unable to forward the HTLC already in
9998+ // its holding cell as it would be over-exposed to dust.
9999+ let ( route_cb, payment_hash_cb, payment_preimage_cb, payment_secret_cb) =
10000+ get_route_and_payment_hash ! ( nodes[ 2 ] , nodes[ 1 ] , DUST_HTLC_VALUE_MSAT ) ;
10001+ let onion_cb = RecipientOnionFields :: secret_only ( payment_secret_cb) ;
10002+ let id = PaymentId ( payment_hash_cb. 0 ) ;
10003+ nodes[ 2 ] . node . send_payment_with_route ( route_cb, payment_hash_cb, onion_cb, id) . unwrap ( ) ;
10004+ check_added_monitors ( & nodes[ 2 ] , 1 ) ;
10005+
10006+ // Now deliver all the messages and make sure that the HTLC is failed-back.
10007+ let send_event_cb = SendEvent :: from_node ( & nodes[ 2 ] ) ;
10008+ nodes[ 1 ] . node . handle_update_add_htlc ( node_c_id, & send_event_cb. msgs [ 0 ] ) ;
10009+ nodes[ 1 ] . node . handle_commitment_signed_batch_test ( node_c_id, & send_event_cb. commitment_msg ) ;
10010+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
10011+
10012+ nodes[ 2 ] . node . handle_update_add_htlc ( node_b_id, & send_bc. msgs [ 0 ] ) ;
10013+ nodes[ 2 ] . node . handle_commitment_signed_batch_test ( node_b_id, & send_bc. commitment_msg ) ;
10014+ check_added_monitors ( & nodes[ 2 ] , 1 ) ;
10015+
10016+ let cs_raa = get_event_msg ! ( nodes[ 2 ] , MessageSendEvent :: SendRevokeAndACK , node_b_id) ;
10017+ nodes[ 1 ] . node . handle_revoke_and_ack ( node_c_id, & cs_raa) ;
10018+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
10019+ let ( bs_raa, bs_cs) = get_revoke_commit_msgs ( & nodes[ 1 ] , & node_c_id) ;
10020+
10021+ // When we delivered the RAA above, we attempted (and failed) to add the HTLC to the channel,
10022+ // causing it to be ready to fail-back, which we do here:
10023+ let next_hop =
10024+ HTLCHandlingFailureType :: Forward { node_id : Some ( node_c_id) , channel_id : bc_chan_id } ;
10025+ expect_htlc_forwarding_fails ( & nodes[ 1 ] , & [ next_hop] ) ;
10026+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
10027+ fail_payment_along_path ( & [ & nodes[ 0 ] , & nodes[ 1 ] ] ) ;
10028+ let conditions = PaymentFailedConditions :: new ( ) ;
10029+ expect_payment_failed_conditions ( & nodes[ 0 ] , payment_hash_cell, false , conditions) ;
10030+
10031+ nodes[ 2 ] . node . handle_revoke_and_ack ( node_b_id, & bs_raa) ;
10032+ check_added_monitors ( & nodes[ 2 ] , 1 ) ;
10033+ let cs_cs = get_htlc_update_msgs ( & nodes[ 2 ] , & node_b_id) ;
10034+
10035+ nodes[ 2 ] . node . handle_commitment_signed_batch_test ( node_b_id, & bs_cs) ;
10036+ check_added_monitors ( & nodes[ 2 ] , 1 ) ;
10037+ let cs_raa = get_event_msg ! ( nodes[ 2 ] , MessageSendEvent :: SendRevokeAndACK , node_b_id) ;
10038+
10039+ nodes[ 1 ] . node . handle_commitment_signed_batch_test ( node_c_id, & cs_cs. commitment_signed ) ;
10040+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
10041+ let bs_raa = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendRevokeAndACK , node_c_id) ;
10042+
10043+ nodes[ 1 ] . node . handle_revoke_and_ack ( node_c_id, & cs_raa) ;
10044+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
10045+ expect_and_process_pending_htlcs ( & nodes[ 1 ] , false ) ;
10046+ expect_payment_claimable ! ( nodes[ 1 ] , payment_hash_cb, payment_secret_cb, DUST_HTLC_VALUE_MSAT ) ;
10047+
10048+ nodes[ 2 ] . node . handle_revoke_and_ack ( node_b_id, & bs_raa) ;
10049+ check_added_monitors ( & nodes[ 2 ] , 1 ) ;
10050+
10051+ // Now that everything has settled, make sure the channels still work with a simple claim.
10052+ claim_payment ( & nodes[ 2 ] , & [ & nodes[ 1 ] ] , payment_preimage_cb) ;
10053+ }
0 commit comments