routing: consolidate final hop params for newRoute
This commit creates a wrapper struct, grouping all parameters that influence the final hop during route construction. This is a preliminary step for passing in the receiver's invoice feature bits, which will be used to select an appropriate payment or payload type.
This commit is contained in:
parent
71e05e05bf
commit
495ae8ca42
@ -96,17 +96,29 @@ type edgePolicyWithSource struct {
|
|||||||
edge *channeldb.ChannelEdgePolicy
|
edge *channeldb.ChannelEdgePolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
// newRoute returns a fully valid route between the source and target that's
|
// finalHopParams encapsulates various parameters for route construction that
|
||||||
// capable of supporting a payment of `amtToSend` after fees are fully
|
// apply to the final hop in a route. These features include basic payment data
|
||||||
// computed. If the route is too long, or the selected path cannot support the
|
// such as amounts and cltvs, as well as more complex features like destination
|
||||||
// fully payment including fees, then a non-nil error is returned.
|
// custom records.
|
||||||
|
type finalHopParams struct {
|
||||||
|
amt lnwire.MilliSatoshi
|
||||||
|
cltvDelta uint16
|
||||||
|
records record.CustomSet
|
||||||
|
}
|
||||||
|
|
||||||
|
// newRoute constructs a route using the provided path and final hop constraints.
|
||||||
|
// Any destination specific fields from the final hop params will be attached
|
||||||
|
// assuming the destination's feature vector signals support, otherwise this
|
||||||
|
// method will fail. If the route is too long, or the selected path cannot
|
||||||
|
// support the fully payment including fees, then a non-nil error is returned.
|
||||||
//
|
//
|
||||||
// NOTE: The passed slice of ChannelHops MUST be sorted in forward order: from
|
// NOTE: The passed slice of ChannelHops MUST be sorted in forward order: from
|
||||||
// the source to the target node of the path finding attempt.
|
// the source to the target node of the path finding attempt. It is assumed that
|
||||||
func newRoute(amtToSend lnwire.MilliSatoshi, sourceVertex route.Vertex,
|
// any feature vectors on all hops have been validated for transitive
|
||||||
|
// dependencies.
|
||||||
|
func newRoute(sourceVertex route.Vertex,
|
||||||
pathEdges []*channeldb.ChannelEdgePolicy, currentHeight uint32,
|
pathEdges []*channeldb.ChannelEdgePolicy, currentHeight uint32,
|
||||||
finalCLTVDelta uint16,
|
finalHop finalHopParams) (*route.Route, error) {
|
||||||
destCustomRecords record.CustomSet) (*route.Route, error) {
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
hops []*route.Hop
|
hops []*route.Hop
|
||||||
@ -132,7 +144,7 @@ func newRoute(amtToSend lnwire.MilliSatoshi, sourceVertex route.Vertex,
|
|||||||
// If this is the last hop, then the hop payload will contain
|
// If this is the last hop, then the hop payload will contain
|
||||||
// the exact amount. In BOLT #4: Onion Routing
|
// the exact amount. In BOLT #4: Onion Routing
|
||||||
// Protocol / "Payload for the Last Node", this is detailed.
|
// Protocol / "Payload for the Last Node", this is detailed.
|
||||||
amtToForward := amtToSend
|
amtToForward := finalHop.amt
|
||||||
|
|
||||||
// Fee is not part of the hop payload, but only used for
|
// Fee is not part of the hop payload, but only used for
|
||||||
// reporting through RPC. Set to zero for the final hop.
|
// reporting through RPC. Set to zero for the final hop.
|
||||||
@ -161,9 +173,9 @@ func newRoute(amtToSend lnwire.MilliSatoshi, sourceVertex route.Vertex,
|
|||||||
// As this is the last hop, we'll use the specified
|
// As this is the last hop, we'll use the specified
|
||||||
// final CLTV delta value instead of the value from the
|
// final CLTV delta value instead of the value from the
|
||||||
// last link in the route.
|
// last link in the route.
|
||||||
totalTimeLock += uint32(finalCLTVDelta)
|
totalTimeLock += uint32(finalHop.cltvDelta)
|
||||||
|
|
||||||
outgoingTimeLock = currentHeight + uint32(finalCLTVDelta)
|
outgoingTimeLock = currentHeight + uint32(finalHop.cltvDelta)
|
||||||
} else {
|
} else {
|
||||||
// Next, increment the total timelock of the entire
|
// Next, increment the total timelock of the entire
|
||||||
// route such that each hops time lock increases as we
|
// route such that each hops time lock increases as we
|
||||||
@ -204,8 +216,8 @@ func newRoute(amtToSend lnwire.MilliSatoshi, sourceVertex route.Vertex,
|
|||||||
|
|
||||||
// If this is the last hop, then we'll populate any TLV records
|
// If this is the last hop, then we'll populate any TLV records
|
||||||
// destined for it.
|
// destined for it.
|
||||||
if i == len(pathEdges)-1 && len(destCustomRecords) != 0 {
|
if i == len(pathEdges)-1 && len(finalHop.records) != 0 {
|
||||||
currentHop.CustomRecords = destCustomRecords
|
currentHop.CustomRecords = finalHop.records
|
||||||
}
|
}
|
||||||
|
|
||||||
hops = append([]*route.Hop{currentHop}, hops...)
|
hops = append([]*route.Hop{currentHop}, hops...)
|
||||||
|
@ -680,8 +680,12 @@ func TestFindLowestFeePath(t *testing.T) {
|
|||||||
t.Fatalf("unable to find path: %v", err)
|
t.Fatalf("unable to find path: %v", err)
|
||||||
}
|
}
|
||||||
route, err := newRoute(
|
route, err := newRoute(
|
||||||
paymentAmt, ctx.source, path, startingHeight,
|
ctx.source, path, startingHeight,
|
||||||
finalHopCLTV, nil,
|
finalHopParams{
|
||||||
|
amt: paymentAmt,
|
||||||
|
cltvDelta: finalHopCLTV,
|
||||||
|
records: nil,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create path: %v", err)
|
t.Fatalf("unable to create path: %v", err)
|
||||||
@ -830,8 +834,12 @@ func testBasicGraphPathFindingCase(t *testing.T, graphInstance *testGraphInstanc
|
|||||||
}
|
}
|
||||||
|
|
||||||
route, err := newRoute(
|
route, err := newRoute(
|
||||||
paymentAmt, sourceVertex, path, startingHeight,
|
sourceVertex, path, startingHeight,
|
||||||
finalHopCLTV, nil,
|
finalHopParams{
|
||||||
|
amt: paymentAmt,
|
||||||
|
cltvDelta: finalHopCLTV,
|
||||||
|
records: nil,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create path: %v", err)
|
t.Fatalf("unable to create path: %v", err)
|
||||||
@ -1244,9 +1252,12 @@ func TestNewRoute(t *testing.T) {
|
|||||||
|
|
||||||
t.Run(testCase.name, func(t *testing.T) {
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
route, err := newRoute(
|
route, err := newRoute(
|
||||||
testCase.paymentAmount, sourceVertex,
|
sourceVertex, testCase.hops, startingHeight,
|
||||||
testCase.hops, startingHeight, finalHopCLTV,
|
finalHopParams{
|
||||||
nil,
|
amt: testCase.paymentAmount,
|
||||||
|
cltvDelta: finalHopCLTV,
|
||||||
|
records: nil,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
if testCase.expectError {
|
if testCase.expectError {
|
||||||
@ -2210,8 +2221,12 @@ func TestRestrictOutgoingChannel(t *testing.T) {
|
|||||||
t.Fatalf("unable to find path: %v", err)
|
t.Fatalf("unable to find path: %v", err)
|
||||||
}
|
}
|
||||||
route, err := newRoute(
|
route, err := newRoute(
|
||||||
paymentAmt, ctx.source, path, startingHeight,
|
ctx.source, path, startingHeight,
|
||||||
finalHopCLTV, nil,
|
finalHopParams{
|
||||||
|
amt: paymentAmt,
|
||||||
|
cltvDelta: finalHopCLTV,
|
||||||
|
records: nil,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create path: %v", err)
|
t.Fatalf("unable to create path: %v", err)
|
||||||
@ -2336,8 +2351,12 @@ func testCltvLimit(t *testing.T, limit uint32, expectedChannel uint64) {
|
|||||||
finalHopCLTV = 1
|
finalHopCLTV = 1
|
||||||
)
|
)
|
||||||
route, err := newRoute(
|
route, err := newRoute(
|
||||||
paymentAmt, ctx.source, path, startingHeight, finalHopCLTV,
|
ctx.source, path, startingHeight,
|
||||||
nil,
|
finalHopParams{
|
||||||
|
amt: paymentAmt,
|
||||||
|
cltvDelta: finalHopCLTV,
|
||||||
|
records: nil,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create path: %v", err)
|
t.Fatalf("unable to create path: %v", err)
|
||||||
@ -2623,8 +2642,12 @@ func TestNoCycle(t *testing.T) {
|
|||||||
t.Fatalf("unable to find path: %v", err)
|
t.Fatalf("unable to find path: %v", err)
|
||||||
}
|
}
|
||||||
route, err := newRoute(
|
route, err := newRoute(
|
||||||
paymentAmt, ctx.source, path, startingHeight,
|
ctx.source, path, startingHeight,
|
||||||
finalHopCLTV, nil,
|
finalHopParams{
|
||||||
|
amt: paymentAmt,
|
||||||
|
cltvDelta: finalHopCLTV,
|
||||||
|
records: nil,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create path: %v", err)
|
t.Fatalf("unable to create path: %v", err)
|
||||||
|
@ -129,8 +129,12 @@ func (p *paymentSession) RequestRoute(payment *LightningPayment,
|
|||||||
// a route by applying the time-lock and fee requirements.
|
// a route by applying the time-lock and fee requirements.
|
||||||
sourceVertex := route.Vertex(ss.SelfNode.PubKeyBytes)
|
sourceVertex := route.Vertex(ss.SelfNode.PubKeyBytes)
|
||||||
route, err := newRoute(
|
route, err := newRoute(
|
||||||
payment.Amount, sourceVertex, path, height, finalCltvDelta,
|
sourceVertex, path, height,
|
||||||
payment.DestCustomRecords,
|
finalHopParams{
|
||||||
|
amt: payment.Amount,
|
||||||
|
cltvDelta: finalCltvDelta,
|
||||||
|
records: payment.DestCustomRecords,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO(roasbeef): return which edge/vertex didn't work
|
// TODO(roasbeef): return which edge/vertex didn't work
|
||||||
|
@ -1454,8 +1454,12 @@ func (r *ChannelRouter) FindRoute(source, target route.Vertex,
|
|||||||
|
|
||||||
// Create the route with absolute time lock values.
|
// Create the route with absolute time lock values.
|
||||||
route, err := newRoute(
|
route, err := newRoute(
|
||||||
amt, source, path, uint32(currentHeight), finalCLTVDelta,
|
source, path, uint32(currentHeight),
|
||||||
destCustomRecords,
|
finalHopParams{
|
||||||
|
amt: amt,
|
||||||
|
cltvDelta: finalCLTVDelta,
|
||||||
|
records: destCustomRecords,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -2403,7 +2407,11 @@ func (r *ChannelRouter) BuildRoute(amt *lnwire.MilliSatoshi,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return newRoute(
|
return newRoute(
|
||||||
receiverAmt, source, pathEdges, uint32(height),
|
source, pathEdges, uint32(height),
|
||||||
uint16(finalCltvDelta), nil,
|
finalHopParams{
|
||||||
|
amt: receiverAmt,
|
||||||
|
cltvDelta: uint16(finalCltvDelta),
|
||||||
|
records: nil,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user