@@ -82,7 +82,16 @@ type BuildBlindedPathCfg struct {
8282 MinFinalCLTVExpiryDelta uint32
8383
8484 // BlocksUntilExpiry is the number of blocks that this blinded path
85- // should remain valid for.
85+ // should remain valid for. This is a relative number of blocks. This
86+ // number in addition with a potential minimum cltv delta for the last
87+ // hop and some block padding will be the payment constraint which is
88+ // part of the blinded hop info. Every htlc using the provided blinded
89+ // hops cannot have a higher cltv delta otherwise it will get rejected
90+ // by the forwarding nodes or the final node.
91+ //
92+ // This number should at least be greater than the invoice expiry time
93+ // so that the blinded route is always valid as long as the invoice is
94+ // valid.
8695 BlocksUntilExpiry uint32
8796
8897 // MinNumHops is the minimum number of hops that each blinded path
@@ -105,13 +114,6 @@ type BuildBlindedPathCfg struct {
105114func BuildBlindedPaymentPaths (cfg * BuildBlindedPathCfg ) (
106115 []* zpay32.BlindedPaymentPath , error ) {
107116
108- if cfg .MinFinalCLTVExpiryDelta >= cfg .BlocksUntilExpiry {
109- return nil , fmt .Errorf ("blinded path CLTV expiry delta (%d) " +
110- "must be greater than the minimum final CLTV expiry " +
111- "delta (%d)" , cfg .BlocksUntilExpiry ,
112- cfg .MinFinalCLTVExpiryDelta )
113- }
114-
115117 // Find some appropriate routes for the value to be routed. This will
116118 // return a set of routes made up of real nodes.
117119 routes , err := cfg .FindRoutes (cfg .ValueMsat )
@@ -148,7 +150,7 @@ func BuildBlindedPaymentPaths(cfg *BuildBlindedPathCfg) (
148150 continue
149151 } else if err != nil {
150152 log .Errorf ("Not using route (%s) as a blinded path: %v" ,
151- err )
153+ route , err )
152154
153155 continue
154156 }
@@ -435,11 +437,27 @@ func collectRelayInfo(cfg *BuildBlindedPathCfg, path *candidatePath) (
435437 }
436438 }
437439
438- policy , err = cfg .AddPolicyBuffer (policy )
440+ if policy .MinHTLCMsat > cfg .ValueMsat {
441+ return nil , 0 , 0 , fmt .Errorf ("%w: minHTLC of hop " +
442+ "policy larger than payment amt: sentAmt(%v), " +
443+ "minHTLC(%v)" , errInvalidBlindedPath ,
444+ cfg .ValueMsat , policy .MinHTLCMsat )
445+ }
446+
447+ bufferPolicy , err := cfg .AddPolicyBuffer (policy )
439448 if err != nil {
440449 return nil , 0 , 0 , err
441450 }
442451
452+ // We only use the new buffered policy if the new minHTLC value
453+ // does not violate the sender amount.
454+ //
455+ // NOTE: We don't check this for maxHTLC, because the payment
456+ // amount can always be splitted using MPP.
457+ if bufferPolicy .MinHTLCMsat <= cfg .ValueMsat {
458+ policy = bufferPolicy
459+ }
460+
443461 // If this is the first policy we are collecting, then use this
444462 // policy to set the base values for min/max htlc.
445463 if len (hops ) == 0 {
0 commit comments