mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-12-10 21:03:04 +01:00
routing: split BuildRoute
Create a couple of subroutines that we can unit test separately.
This commit is contained in:
@@ -2743,6 +2743,19 @@ func (r *ChannelRouter) BuildRoute(amt *lnwire.MilliSatoshi,
|
|||||||
// amount that this route can carry.
|
// amount that this route can carry.
|
||||||
useMinAmt := amt == nil
|
useMinAmt := amt == nil
|
||||||
|
|
||||||
|
var runningAmt lnwire.MilliSatoshi
|
||||||
|
if useMinAmt {
|
||||||
|
// For minimum amount routes, aim to deliver at least 1 msat to
|
||||||
|
// the destination. There are nodes in the wild that have a
|
||||||
|
// min_htlc channel policy of zero, which could lead to a zero
|
||||||
|
// amount payment being made.
|
||||||
|
runningAmt = 1
|
||||||
|
} else {
|
||||||
|
// If an amount is specified, we need to build a route that
|
||||||
|
// delivers exactly this amount to the final destination.
|
||||||
|
runningAmt = *amt
|
||||||
|
}
|
||||||
|
|
||||||
// We'll attempt to obtain a set of bandwidth hints that helps us select
|
// We'll attempt to obtain a set of bandwidth hints that helps us select
|
||||||
// the best outgoing channel to use in case no outgoing channel is set.
|
// the best outgoing channel to use in case no outgoing channel is set.
|
||||||
bandwidthHints, err := newBandwidthManager(
|
bandwidthHints, err := newBandwidthManager(
|
||||||
@@ -2759,24 +2772,46 @@ func (r *ChannelRouter) BuildRoute(amt *lnwire.MilliSatoshi,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sourceNode := r.selfNode.PubKeyBytes
|
||||||
|
unifiers, senderAmt, err := getRouteUnifiers(
|
||||||
|
sourceNode, hops, useMinAmt, runningAmt, outgoingChans,
|
||||||
|
r.cachedGraph, bandwidthHints,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pathEdges, receiverAmt, err := getPathEdges(
|
||||||
|
senderAmt, unifiers, bandwidthHints, hops,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build and return the final route.
|
||||||
|
return newRoute(
|
||||||
|
sourceNode, pathEdges, uint32(height),
|
||||||
|
finalHopParams{
|
||||||
|
amt: receiverAmt,
|
||||||
|
totalAmt: receiverAmt,
|
||||||
|
cltvDelta: uint16(finalCltvDelta),
|
||||||
|
records: nil,
|
||||||
|
paymentAddr: payAddr,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getRouteUnifiers returns a list of edge unifiers for the given route.
|
||||||
|
func getRouteUnifiers(source route.Vertex, hops []route.Vertex,
|
||||||
|
useMinAmt bool, runningAmt lnwire.MilliSatoshi,
|
||||||
|
outgoingChans map[uint64]struct{}, graph routingGraph,
|
||||||
|
bandwidthHints *bandwidthManager) ([]*edgeUnifier, lnwire.MilliSatoshi,
|
||||||
|
error) {
|
||||||
|
|
||||||
// Allocate a list that will contain the edge unifiers for this route.
|
// Allocate a list that will contain the edge unifiers for this route.
|
||||||
unifiers := make([]*edgeUnifier, len(hops))
|
unifiers := make([]*edgeUnifier, len(hops))
|
||||||
|
|
||||||
var runningAmt lnwire.MilliSatoshi
|
|
||||||
if useMinAmt {
|
|
||||||
// For minimum amount routes, aim to deliver at least 1 msat to
|
|
||||||
// the destination. There are nodes in the wild that have a
|
|
||||||
// min_htlc channel policy of zero, which could lead to a zero
|
|
||||||
// amount payment being made.
|
|
||||||
runningAmt = 1
|
|
||||||
} else {
|
|
||||||
// If an amount is specified, we need to build a route that
|
|
||||||
// delivers exactly this amount to the final destination.
|
|
||||||
runningAmt = *amt
|
|
||||||
}
|
|
||||||
|
|
||||||
// Traverse hops backwards to accumulate fees in the running amounts.
|
// Traverse hops backwards to accumulate fees in the running amounts.
|
||||||
source := r.selfNode.PubKeyBytes
|
|
||||||
for i := len(hops) - 1; i >= 0; i-- {
|
for i := len(hops) - 1; i >= 0; i-- {
|
||||||
toNode := hops[i]
|
toNode := hops[i]
|
||||||
|
|
||||||
@@ -2793,16 +2828,16 @@ func (r *ChannelRouter) BuildRoute(amt *lnwire.MilliSatoshi,
|
|||||||
// in the graph.
|
// in the graph.
|
||||||
u := newNodeEdgeUnifier(source, toNode, outgoingChans)
|
u := newNodeEdgeUnifier(source, toNode, outgoingChans)
|
||||||
|
|
||||||
err := u.addGraphPolicies(r.cachedGraph)
|
err := u.addGraphPolicies(graph)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exit if there are no channels.
|
// Exit if there are no channels.
|
||||||
edgeUnifier, ok := u.edgeUnifiers[fromNode]
|
edgeUnifier, ok := u.edgeUnifiers[fromNode]
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Errorf("Cannot find policy for node %v", fromNode)
|
log.Errorf("Cannot find policy for node %v", fromNode)
|
||||||
return nil, ErrNoChannel{
|
return nil, 0, ErrNoChannel{
|
||||||
fromNode: fromNode,
|
fromNode: fromNode,
|
||||||
position: i,
|
position: i,
|
||||||
}
|
}
|
||||||
@@ -2822,7 +2857,7 @@ func (r *ChannelRouter) BuildRoute(amt *lnwire.MilliSatoshi,
|
|||||||
log.Errorf("Cannot find policy with amt=%v for node %v",
|
log.Errorf("Cannot find policy with amt=%v for node %v",
|
||||||
runningAmt, fromNode)
|
runningAmt, fromNode)
|
||||||
|
|
||||||
return nil, ErrNoChannel{
|
return nil, 0, ErrNoChannel{
|
||||||
fromNode: fromNode,
|
fromNode: fromNode,
|
||||||
position: i,
|
position: i,
|
||||||
}
|
}
|
||||||
@@ -2839,16 +2874,25 @@ func (r *ChannelRouter) BuildRoute(amt *lnwire.MilliSatoshi,
|
|||||||
unifiers[i] = edgeUnifier
|
unifiers[i] = edgeUnifier
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return unifiers, runningAmt, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getPathEdges returns the edges that make up the path and the total amount,
|
||||||
|
// including fees, to send the payment.
|
||||||
|
func getPathEdges(receiverAmt lnwire.MilliSatoshi, unifiers []*edgeUnifier,
|
||||||
|
bandwidthHints *bandwidthManager,
|
||||||
|
hops []route.Vertex) ([]*channeldb.CachedEdgePolicy,
|
||||||
|
lnwire.MilliSatoshi, error) {
|
||||||
|
|
||||||
// Now that we arrived at the start of the route and found out the route
|
// Now that we arrived at the start of the route and found out the route
|
||||||
// total amount, we make a forward pass. Because the amount may have
|
// total amount, we make a forward pass. Because the amount may have
|
||||||
// been increased in the backward pass, fees need to be recalculated and
|
// been increased in the backward pass, fees need to be recalculated and
|
||||||
// amount ranges re-checked.
|
// amount ranges re-checked.
|
||||||
var pathEdges []*channeldb.CachedEdgePolicy
|
var pathEdges []*channeldb.CachedEdgePolicy
|
||||||
receiverAmt := runningAmt
|
|
||||||
for i, unifier := range unifiers {
|
for i, unifier := range unifiers {
|
||||||
edge := unifier.getEdge(receiverAmt, bandwidthHints)
|
edge := unifier.getEdge(receiverAmt, bandwidthHints)
|
||||||
if edge == nil {
|
if edge == nil {
|
||||||
return nil, ErrNoChannel{
|
return nil, 0, ErrNoChannel{
|
||||||
fromNode: hops[i-1],
|
fromNode: hops[i-1],
|
||||||
position: i,
|
position: i,
|
||||||
}
|
}
|
||||||
@@ -2864,15 +2908,5 @@ func (r *ChannelRouter) BuildRoute(amt *lnwire.MilliSatoshi,
|
|||||||
pathEdges = append(pathEdges, edge.policy)
|
pathEdges = append(pathEdges, edge.policy)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build and return the final route.
|
return pathEdges, receiverAmt, nil
|
||||||
return newRoute(
|
|
||||||
source, pathEdges, uint32(height),
|
|
||||||
finalHopParams{
|
|
||||||
amt: receiverAmt,
|
|
||||||
totalAmt: receiverAmt,
|
|
||||||
cltvDelta: uint16(finalCltvDelta),
|
|
||||||
records: nil,
|
|
||||||
paymentAddr: payAddr,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user