routing: pass BlindedPaymentPathSet around everywhere

Building on from the previous commit, here we pass the PathSet around
everywhere where we previously passed around the single BlindedPayment.
This commit is contained in:
Elle Mouton 2024-05-15 15:08:19 +02:00
parent 3d5f20b70f
commit 4a22ec8413
No known key found for this signature in database
GPG Key ID: D7D916376026F177
7 changed files with 94 additions and 92 deletions

View File

@ -388,10 +388,10 @@ func (r *RouterBackend) parseQueryRoutesRequest(in *lnrpc.QueryRoutesRequest) (
fromNode, toNode, amt, capacity,
)
},
DestCustomRecords: record.CustomSet(in.DestCustomRecords),
CltvLimit: cltvLimit,
DestFeatures: destinationFeatures,
BlindedPayment: blindedPathSet.GetPath(),
DestCustomRecords: record.CustomSet(in.DestCustomRecords),
CltvLimit: cltvLimit,
DestFeatures: destinationFeatures,
BlindedPaymentPathSet: blindedPathSet,
}
// Pass along an outgoing channel restriction if specified.
@ -420,7 +420,7 @@ func (r *RouterBackend) parseQueryRoutesRequest(in *lnrpc.QueryRoutesRequest) (
return routing.NewRouteRequest(
sourcePubKey, targetPubKey, amt, in.TimePref, restrictions,
customRecords, routeHintEdges, blindedPathSet.GetPath(),
customRecords, routeHintEdges, blindedPathSet,
finalCLTVDelta,
)
}
@ -1007,7 +1007,7 @@ func (r *RouterBackend) extractIntentFromSendRequest(
if err != nil {
return nil, err
}
payIntent.BlindedPayment = pathSet.GetPath()
payIntent.BlindedPathSet = pathSet
// Replace the target node with the target public key
// of the blinded path set.

View File

@ -136,9 +136,8 @@ type finalHopParams struct {
// NOTE: If a non-nil blinded path is provided it is assumed to have been
// validated by the caller.
func newRoute(sourceVertex route.Vertex,
pathEdges []*unifiedEdge, currentHeight uint32,
finalHop finalHopParams, blindedPath *sphinx.BlindedPath) (
*route.Route, error) {
pathEdges []*unifiedEdge, currentHeight uint32, finalHop finalHopParams,
blindedPathSet *BlindedPaymentPathSet) (*route.Route, error) {
var (
hops []*route.Hop
@ -153,8 +152,14 @@ func newRoute(sourceVertex route.Vertex,
// backwards below, this next hop gets closer and closer to the
// sender of the payment.
nextIncomingAmount lnwire.MilliSatoshi
blindedPath *sphinx.BlindedPath
)
if blindedPathSet != nil {
blindedPath = blindedPathSet.GetPath().BlindedPath
}
pathLength := len(pathEdges)
for i := pathLength - 1; i >= 0; i-- {
// Now we'll start to calculate the items within the per-hop
@ -437,9 +442,9 @@ type RestrictParams struct {
// the payee.
Metadata []byte
// BlindedPayment is necessary to determine the hop size of the
// BlindedPaymentPathSet is necessary to determine the hop size of the
// last/exit hop.
BlindedPayment *BlindedPayment
BlindedPaymentPathSet *BlindedPaymentPathSet
}
// PathFindingConfig defines global parameters that control the trade-off in
@ -1365,9 +1370,11 @@ func getProbabilityBasedDist(weight int64, probability float64,
func lastHopPayloadSize(r *RestrictParams, finalHtlcExpiry int32,
amount lnwire.MilliSatoshi) uint64 {
if r.BlindedPayment != nil {
blindedPath := r.BlindedPayment.BlindedPath.BlindedHops
blindedPoint := r.BlindedPayment.BlindedPath.BlindingPoint
if r.BlindedPaymentPathSet != nil {
paymentPath := r.BlindedPaymentPathSet.
LargestLastHopPayloadPath()
blindedPath := paymentPath.BlindedPath.BlindedHops
blindedPoint := paymentPath.BlindedPath.BlindingPoint
encryptedData := blindedPath[len(blindedPath)-1].CipherText
finalHop := route.Hop{

View File

@ -3277,6 +3277,11 @@ func TestBlindedRouteConstruction(t *testing.T) {
require.NoError(t, blindedPayment.Validate())
blindedPathSet, err := NewBlindedPaymentPathSet(
[]*BlindedPayment{blindedPayment},
)
require.NoError(t, err)
// Generate route hints from our blinded payment and a set of edges
// that make up the graph we'll give to route construction. The hints
// map is keyed by source node, so we can retrieve our blinded edges
@ -3382,7 +3387,7 @@ func TestBlindedRouteConstruction(t *testing.T) {
route, err := newRoute(
sourceVertex, edges, currentHeight, finalHopParams,
blindedPath,
blindedPathSet,
)
require.NoError(t, err)
require.Equal(t, expectedRoute, route)
@ -3409,31 +3414,38 @@ func TestLastHopPayloadSize(t *testing.T) {
amtToForward = lnwire.MilliSatoshi(10000)
finalHopExpiry int32 = 144
oneHopBlindedPayment = &BlindedPayment{
BlindedPath: &sphinx.BlindedPath{
BlindedHops: []*sphinx.BlindedHopInfo{
{
CipherText: encrypedData,
},
oneHopPath = &sphinx.BlindedPath{
BlindedHops: []*sphinx.BlindedHopInfo{
{
CipherText: encrypedData,
},
BlindingPoint: blindedPoint,
},
BlindingPoint: blindedPoint,
}
twoHopBlindedPayment = &BlindedPayment{
BlindedPath: &sphinx.BlindedPath{
BlindedHops: []*sphinx.BlindedHopInfo{
{
CipherText: encrypedData,
},
{
CipherText: encrypedData,
},
twoHopPath = &sphinx.BlindedPath{
BlindedHops: []*sphinx.BlindedHopInfo{
{
CipherText: encrypedData,
},
{
CipherText: encrypedData,
},
BlindingPoint: blindedPoint,
},
BlindingPoint: blindedPoint,
}
)
oneHopBlindedPayment, err := NewBlindedPaymentPathSet(
[]*BlindedPayment{{BlindedPath: oneHopPath}},
)
require.NoError(t, err)
twoHopBlindedPayment, err := NewBlindedPaymentPathSet(
[]*BlindedPayment{{BlindedPath: twoHopPath}},
)
require.NoError(t, err)
testCases := []struct {
name string
restrictions *RestrictParams
@ -3454,7 +3466,7 @@ func TestLastHopPayloadSize(t *testing.T) {
{
name: "Blinded final hop introduction point",
restrictions: &RestrictParams{
BlindedPayment: oneHopBlindedPayment,
BlindedPaymentPathSet: oneHopBlindedPayment,
},
amount: amtToForward,
finalHopExpiry: finalHopExpiry,
@ -3462,7 +3474,7 @@ func TestLastHopPayloadSize(t *testing.T) {
{
name: "Blinded final hop of a two hop payment",
restrictions: &RestrictParams{
BlindedPayment: twoHopBlindedPayment,
BlindedPaymentPathSet: twoHopBlindedPayment,
},
amount: amtToForward,
finalHopExpiry: finalHopExpiry,
@ -3490,12 +3502,11 @@ func TestLastHopPayloadSize(t *testing.T) {
}
var finalHop route.Hop
if tc.restrictions.BlindedPayment != nil {
blindedPath := tc.restrictions.BlindedPayment.
BlindedPath.BlindedHops
blindedPoint := tc.restrictions.BlindedPayment.
BlindedPath.BlindingPoint
if tc.restrictions.BlindedPaymentPathSet != nil {
path := tc.restrictions.BlindedPaymentPathSet.
LargestLastHopPayloadPath()
blindedPath := path.BlindedPath.BlindedHops
blindedPoint := path.BlindedPath.BlindingPoint
//nolint:lll
finalHop = route.Hop{

View File

@ -5,7 +5,6 @@ import (
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btclog"
sphinx "github.com/lightningnetwork/lightning-onion"
"github.com/lightningnetwork/lnd/build"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/channeldb/models"
@ -206,13 +205,13 @@ func newPaymentSession(p *LightningPayment, selfNode route.Vertex,
return nil, err
}
if p.BlindedPayment != nil {
if p.BlindedPathSet != nil {
if len(edges) != 0 {
return nil, fmt.Errorf("cannot have both route hints " +
"and blinded path")
}
edges, err = p.BlindedPayment.toRouteHints()
edges, err = p.BlindedPathSet.ToRouteHints()
if err != nil {
return nil, err
}
@ -342,7 +341,7 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi,
// can split. Split payments to blinded paths won't have
// MPP records.
if p.payment.PaymentAddr == nil &&
p.payment.BlindedPayment == nil {
p.payment.BlindedPathSet == nil {
p.log.Debugf("not splitting because payment " +
"address is unspecified")
@ -407,11 +406,6 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi,
return nil, err
}
var blindedPath *sphinx.BlindedPath
if p.payment.BlindedPayment != nil {
blindedPath = p.payment.BlindedPayment.BlindedPath
}
// With the next candidate path found, we'll attempt to turn
// this into a route by applying the time-lock and fee
// requirements.
@ -424,7 +418,7 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi,
records: p.payment.DestCustomRecords,
paymentAddr: p.payment.PaymentAddr,
metadata: p.payment.Metadata,
}, blindedPath,
}, p.payment.BlindedPathSet,
)
if err != nil {
return nil, err

View File

@ -477,10 +477,10 @@ type RouteRequest struct {
// in blinded payment.
FinalExpiry uint16
// BlindedPayment contains an optional blinded path and parameters
// used to reach a target node via a blinded path. This field is
// BlindedPathSet contains a set of optional blinded paths and
// parameters used to reach a target node blinded paths. This field is
// mutually exclusive with the Target field.
BlindedPayment *BlindedPayment
BlindedPathSet *BlindedPaymentPathSet
}
// RouteHints is an alias type for a set of route hints, with the source node
@ -494,7 +494,7 @@ type RouteHints map[route.Vertex][]AdditionalEdge
func NewRouteRequest(source route.Vertex, target *route.Vertex,
amount lnwire.MilliSatoshi, timePref float64,
restrictions *RestrictParams, customRecords record.CustomSet,
routeHints RouteHints, blindedPayment *BlindedPayment,
routeHints RouteHints, blindedPathSet *BlindedPaymentPathSet,
finalExpiry uint16) (*RouteRequest, error) {
var (
@ -504,11 +504,8 @@ func NewRouteRequest(source route.Vertex, target *route.Vertex,
err error
)
if blindedPayment != nil {
if err := blindedPayment.Validate(); err != nil {
return nil, fmt.Errorf("invalid blinded payment: %w",
err)
}
if blindedPathSet != nil {
blindedPayment := blindedPathSet.GetPath()
introVertex := route.NewVertex(
blindedPayment.BlindedPath.IntroductionPoint,
@ -539,13 +536,13 @@ func NewRouteRequest(source route.Vertex, target *route.Vertex,
requestExpiry = blindedPayment.CltvExpiryDelta
}
requestHints, err = blindedPayment.toRouteHints()
requestHints, err = blindedPathSet.ToRouteHints()
if err != nil {
return nil, err
}
}
requestTarget, err := getTargetNode(target, blindedPayment)
requestTarget, err := getTargetNode(target, blindedPathSet)
if err != nil {
return nil, err
}
@ -559,15 +556,15 @@ func NewRouteRequest(source route.Vertex, target *route.Vertex,
CustomRecords: customRecords,
RouteHints: requestHints,
FinalExpiry: requestExpiry,
BlindedPayment: blindedPayment,
BlindedPathSet: blindedPathSet,
}, nil
}
func getTargetNode(target *route.Vertex, blindedPayment *BlindedPayment) (
route.Vertex, error) {
func getTargetNode(target *route.Vertex,
blindedPathSet *BlindedPaymentPathSet) (route.Vertex, error) {
var (
blinded = blindedPayment != nil
blinded = blindedPathSet != nil
targetSet = target != nil
)
@ -576,6 +573,8 @@ func getTargetNode(target *route.Vertex, blindedPayment *BlindedPayment) (
return route.Vertex{}, ErrTargetAndBlinded
case blinded:
blindedPayment := blindedPathSet.GetPath()
// If we're dealing with an edge-case blinded path that just
// has an introduction node (first hop expected to be the intro
// hop), then we return the unblinded introduction node as our
@ -597,16 +596,6 @@ func getTargetNode(target *route.Vertex, blindedPayment *BlindedPayment) (
}
}
// blindedPath returns the request's blinded path, which is set if the payment
// is to a blinded route.
func (r *RouteRequest) blindedPath() *sphinx.BlindedPath {
if r.BlindedPayment == nil {
return nil
}
return r.BlindedPayment.BlindedPath
}
// FindRoute attempts to query the ChannelRouter for the optimum path to a
// particular target destination to which it is able to send `amt` after
// factoring in channel capacities and cumulative fees along the route.
@ -664,7 +653,7 @@ func (r *ChannelRouter) FindRoute(req *RouteRequest) (*route.Route, float64,
totalAmt: req.Amount,
cltvDelta: req.FinalExpiry,
records: req.CustomRecords,
}, req.blindedPath(),
}, req.BlindedPathSet,
)
if err != nil {
return nil, 0, err
@ -926,14 +915,10 @@ type LightningPayment struct {
// BlindedPayment field.
RouteHints [][]zpay32.HopHint
// BlindedPayment holds the information about a blinded path to the
// payment recipient. This is mutually exclusive to the RouteHints
// BlindedPathSet holds the information about a set of blinded paths to
// the payment recipient. This is mutually exclusive to the RouteHints
// field.
//
// NOTE: a recipient may provide multiple blinded payment paths in the
// same invoice. Currently, LND will only attempt to use the first one.
// A future PR will handle multiple blinded payment paths.
BlindedPayment *BlindedPayment
BlindedPathSet *BlindedPaymentPathSet
// OutgoingChannelIDs is the list of channels that are allowed for the
// first hop. If nil, any channel may be used.

View File

@ -2223,11 +2223,6 @@ func TestNewRouteRequest(t *testing.T) {
finalExpiry: unblindedCltv,
err: ErrExpiryAndBlinded,
},
{
name: "invalid blinded payment",
blindedPayment: &BlindedPayment{},
err: ErrNoBlindedPath,
},
}
for _, testCase := range testCases {
@ -2236,9 +2231,19 @@ func TestNewRouteRequest(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
t.Parallel()
var blindedPathInfo *BlindedPaymentPathSet
if testCase.blindedPayment != nil {
blindedPathInfo, err = NewBlindedPaymentPathSet(
[]*BlindedPayment{
testCase.blindedPayment,
},
)
require.NoError(t, err)
}
req, err := NewRouteRequest(
source, testCase.target, 1000, 0, nil, nil,
testCase.routeHints, testCase.blindedPayment,
testCase.routeHints, blindedPathInfo,
testCase.finalExpiry,
)
require.ErrorIs(t, err, testCase.err)

View File

@ -5105,7 +5105,7 @@ type rpcPaymentIntent struct {
paymentAddr *[32]byte
payReq []byte
metadata []byte
blindedPayment *routing.BlindedPayment
blindedPathSet *routing.BlindedPaymentPathSet
destCustomRecords record.CustomSet
@ -5248,7 +5248,7 @@ func (r *rpcServer) extractPaymentIntent(rpcPayReq *rpcPaymentRequest) (rpcPayme
if err != nil {
return payIntent, err
}
payIntent.blindedPayment = pathSet.GetPath()
payIntent.blindedPathSet = pathSet
// Replace the destination node with the target public
// key of the blinded path set.
@ -5417,7 +5417,7 @@ func (r *rpcServer) dispatchPaymentIntent(
DestFeatures: payIntent.destFeatures,
PaymentAddr: payIntent.paymentAddr,
Metadata: payIntent.metadata,
BlindedPayment: payIntent.blindedPayment,
BlindedPathSet: payIntent.blindedPathSet,
// Don't enable multi-part payments on the main rpc.
// Users need to use routerrpc for that.