1010//! A bunch of useful utilities for building networks of nodes and exchanging messages between
1111//! nodes for functional tests.
1212
13+ use crate :: blinded_path:: payment:: DummyTlvs ;
1314use crate :: chain:: channelmonitor:: ChannelMonitor ;
1415use crate :: chain:: transaction:: OutPoint ;
1516use crate :: chain:: { BestBlock , ChannelMonitorUpdateStatus , Confirm , Listen , Watch } ;
@@ -3435,6 +3436,7 @@ fn fail_payment_along_path<'a, 'b, 'c>(expected_path: &[&Node<'a, 'b, 'c>]) {
34353436pub struct PassAlongPathArgs < ' a , ' b , ' c , ' d > {
34363437 pub origin_node : & ' a Node < ' b , ' c , ' d > ,
34373438 pub expected_path : & ' a [ & ' a Node < ' b , ' c , ' d > ] ,
3439+ pub dummy_tlvs : Vec < DummyTlvs > ,
34383440 pub recv_value : u64 ,
34393441 pub payment_hash : PaymentHash ,
34403442 pub payment_secret : Option < PaymentSecret > ,
@@ -3456,6 +3458,7 @@ impl<'a, 'b, 'c, 'd> PassAlongPathArgs<'a, 'b, 'c, 'd> {
34563458 Self {
34573459 origin_node,
34583460 expected_path,
3461+ dummy_tlvs : vec ! [ ] ,
34593462 recv_value,
34603463 payment_hash,
34613464 payment_secret : None ,
@@ -3503,12 +3506,17 @@ impl<'a, 'b, 'c, 'd> PassAlongPathArgs<'a, 'b, 'c, 'd> {
35033506 self . expected_failure = Some ( failure) ;
35043507 self
35053508 }
3509+ pub fn with_dummy_tlvs ( mut self , dummy_tlvs : & [ DummyTlvs ] ) -> Self {
3510+ self . dummy_tlvs = dummy_tlvs. to_vec ( ) ;
3511+ self
3512+ }
35063513}
35073514
35083515pub fn do_pass_along_path < ' a , ' b , ' c > ( args : PassAlongPathArgs ) -> Option < Event > {
35093516 let PassAlongPathArgs {
35103517 origin_node,
35113518 expected_path,
3519+ dummy_tlvs,
35123520 recv_value,
35133521 payment_hash : our_payment_hash,
35143522 payment_secret : our_payment_secret,
@@ -3543,6 +3551,16 @@ pub fn do_pass_along_path<'a, 'b, 'c>(args: PassAlongPathArgs) -> Option<Event>
35433551 node. node . process_pending_htlc_forwards ( ) ;
35443552 }
35453553
3554+ if is_last_hop {
3555+ // At the final hop, the incoming packet contains N dummy-hop layers
3556+ // before the real HTLC. Each call to `process_pending_htlc_forwards`
3557+ // strips exactly one dummy layer, so we call it N times.
3558+ for _ in 0 ..dummy_tlvs. len ( ) {
3559+ assert ! ( node. node. needs_pending_htlc_processing( ) ) ;
3560+ node. node . process_pending_htlc_forwards ( ) ;
3561+ }
3562+ }
3563+
35463564 if is_last_hop && clear_recipient_events {
35473565 let events_2 = node. node . get_and_clear_pending_events ( ) ;
35483566 if payment_claimable_expected {
@@ -3755,6 +3773,29 @@ pub struct ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
37553773 pub origin_node : & ' a Node < ' b , ' c , ' d > ,
37563774 pub expected_paths : & ' a [ & ' a [ & ' a Node < ' b , ' c , ' d > ] ] ,
37573775 pub expected_extra_fees : Vec < u32 > ,
3776+ /// A one-off adjustment used only in tests to account for an existing
3777+ /// fee-handling trade-off in LDK.
3778+ ///
3779+ /// When the payer is the introduction node of a blinded path, LDK does not
3780+ /// subtract the forward fee for the `payer -> next_hop` channel
3781+ /// (see [`BlindedPaymentPath::advance_path_by_one`]). This keeps the fee
3782+ /// logic simpler at the cost of a small, intentional overpayment.
3783+ ///
3784+ /// In the simple two-hop case (payer as introduction node → payee),
3785+ /// this overpayment has historically been avoided by simply not charging
3786+ /// the payer the forward fee, since the payer knows there is only
3787+ /// a single hop after them.
3788+ ///
3789+ /// However, with the introduction of dummy hops in LDK v0.3, even a
3790+ /// two-node real path (payer as introduction node → payee) may appear as a
3791+ /// multi-hop blinded path. This makes the existing overpayment surface in
3792+ /// tests.
3793+ ///
3794+ /// Until the fee-handling trade-off is revisited, this field allows tests
3795+ /// to compensate for that expected difference.
3796+ ///
3797+ /// [`BlindedPaymentPath::advance_path_by_one`]: crate::blinded_path::payment::BlindedPaymentPath::advance_path_by_one
3798+ pub expected_extra_total_fees_msat : u64 ,
37583799 pub expected_min_htlc_overpay : Vec < u32 > ,
37593800 pub skip_last : bool ,
37603801 pub payment_preimage : PaymentPreimage ,
@@ -3778,6 +3819,7 @@ impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
37783819 origin_node,
37793820 expected_paths,
37803821 expected_extra_fees : vec ! [ 0 ; expected_paths. len( ) ] ,
3822+ expected_extra_total_fees_msat : 0 ,
37813823 expected_min_htlc_overpay : vec ! [ 0 ; expected_paths. len( ) ] ,
37823824 skip_last : false ,
37833825 payment_preimage,
@@ -3793,6 +3835,10 @@ impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
37933835 self . expected_extra_fees = extra_fees;
37943836 self
37953837 }
3838+ pub fn with_expected_extra_total_fees_msat ( mut self , extra_total_fees : u64 ) -> Self {
3839+ self . expected_extra_total_fees_msat = extra_total_fees;
3840+ self
3841+ }
37963842 pub fn with_expected_min_htlc_overpay ( mut self , extra_fees : Vec < u32 > ) -> Self {
37973843 self . expected_min_htlc_overpay = extra_fees;
37983844 self
@@ -4060,13 +4106,21 @@ pub fn pass_claimed_payment_along_route_from_ev(
40604106
40614107 expected_total_fee_msat
40624108}
4109+
40634110pub fn claim_payment_along_route (
40644111 args : ClaimAlongRouteArgs ,
40654112) -> ( Option < PaidBolt12Invoice > , Vec < Event > ) {
4066- let origin_node = args. origin_node ;
4067- let payment_preimage = args. payment_preimage ;
4068- let skip_last = args. skip_last ;
4069- let expected_total_fee_msat = do_claim_payment_along_route ( args) ;
4113+ let ClaimAlongRouteArgs {
4114+ origin_node,
4115+ payment_preimage,
4116+ skip_last,
4117+ expected_extra_total_fees_msat,
4118+ ..
4119+ } = args;
4120+
4121+ let expected_total_fee_msat =
4122+ do_claim_payment_along_route ( args) + expected_extra_total_fees_msat;
4123+
40704124 if !skip_last {
40714125 expect_payment_sent ! ( origin_node, payment_preimage, Some ( expected_total_fee_msat) )
40724126 } else {
0 commit comments