routing: use absolute final expiry in pathfinding
This commit is contained in:
parent
e546a2c42b
commit
72a6383975
@ -24,9 +24,10 @@ type nodeWithDist struct {
|
||||
// amount that includes also the fees for subsequent hops.
|
||||
amountToReceive lnwire.MilliSatoshi
|
||||
|
||||
// incomingCltv is the expected cltv value for the incoming htlc of this
|
||||
// node. This value does not include the final cltv.
|
||||
incomingCltv uint32
|
||||
// incomingCltv is the expected absolute expiry height for the incoming
|
||||
// htlc of this node. This value should already include the final cltv
|
||||
// delta.
|
||||
incomingCltv int32
|
||||
|
||||
// probability is the probability that from this node onward the route
|
||||
// is successful.
|
||||
|
@ -47,7 +47,8 @@ const (
|
||||
// pathFinder defines the interface of a path finding algorithm.
|
||||
type pathFinder = func(g *graphParams, r *RestrictParams,
|
||||
cfg *PathFindingConfig, source, target route.Vertex,
|
||||
amt lnwire.MilliSatoshi) ([]*channeldb.ChannelEdgePolicy, error)
|
||||
amt lnwire.MilliSatoshi, finalHtlcExpiry int32) (
|
||||
[]*channeldb.ChannelEdgePolicy, error)
|
||||
|
||||
var (
|
||||
// DefaultPaymentAttemptPenalty is the virtual cost in path finding weight
|
||||
@ -411,7 +412,7 @@ func getMaxOutgoingAmt(node route.Vertex, outgoingChan *uint64,
|
||||
// that need to be paid along the path and accurately check the amount
|
||||
// to forward at every node against the available bandwidth.
|
||||
func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig,
|
||||
source, target route.Vertex, amt lnwire.MilliSatoshi) (
|
||||
source, target route.Vertex, amt lnwire.MilliSatoshi, finalHtlcExpiry int32) (
|
||||
[]*channeldb.ChannelEdgePolicy, error) {
|
||||
|
||||
// Pathfinding can be a significant portion of the total payment
|
||||
@ -542,10 +543,14 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig,
|
||||
weight: 0,
|
||||
node: target,
|
||||
amountToReceive: amt,
|
||||
incomingCltv: 0,
|
||||
incomingCltv: finalHtlcExpiry,
|
||||
probability: 1,
|
||||
}
|
||||
|
||||
// Calculate the absolute cltv limit. Use uint64 to prevent an overflow
|
||||
// if the cltv limit is MaxUint32.
|
||||
absoluteCltvLimit := uint64(r.CltvLimit) + uint64(finalHtlcExpiry)
|
||||
|
||||
// processEdge is a helper closure that will be used to make sure edges
|
||||
// satisfy our specific requirements.
|
||||
processEdge := func(fromVertex route.Vertex,
|
||||
@ -590,11 +595,10 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig,
|
||||
timeLockDelta = edge.TimeLockDelta
|
||||
}
|
||||
|
||||
incomingCltv := toNodeDist.incomingCltv +
|
||||
uint32(timeLockDelta)
|
||||
incomingCltv := toNodeDist.incomingCltv + int32(timeLockDelta)
|
||||
|
||||
// Check that we are within our CLTV limit.
|
||||
if incomingCltv > r.CltvLimit {
|
||||
if uint64(incomingCltv) > absoluteCltvLimit {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -823,6 +823,7 @@ func testBasicGraphPathFindingCase(t *testing.T, graphInstance *testGraphInstanc
|
||||
},
|
||||
testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, target, paymentAmt,
|
||||
startingHeight+finalHopCLTV,
|
||||
)
|
||||
if test.expectFailureNoPath {
|
||||
if err == nil {
|
||||
@ -1012,6 +1013,7 @@ func TestPathFindingWithAdditionalEdges(t *testing.T) {
|
||||
},
|
||||
r, testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, doge.PubKeyBytes, paymentAmt,
|
||||
0,
|
||||
)
|
||||
}
|
||||
|
||||
@ -1383,7 +1385,7 @@ func TestNewRoutePathTooLong(t *testing.T) {
|
||||
graph: graph.graph,
|
||||
},
|
||||
noRestrictions, testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, target, paymentAmt,
|
||||
sourceNode.PubKeyBytes, target, paymentAmt, 0,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("path should have been found")
|
||||
@ -1397,7 +1399,7 @@ func TestNewRoutePathTooLong(t *testing.T) {
|
||||
graph: graph.graph,
|
||||
},
|
||||
noRestrictions, testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, target, paymentAmt,
|
||||
sourceNode.PubKeyBytes, target, paymentAmt, 0,
|
||||
)
|
||||
if err == nil {
|
||||
t.Fatalf("should not have been able to find path, supposed to be "+
|
||||
@ -1437,7 +1439,7 @@ func TestPathNotAvailable(t *testing.T) {
|
||||
graph: graph.graph,
|
||||
},
|
||||
noRestrictions, testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, unknownNode, 100,
|
||||
sourceNode.PubKeyBytes, unknownNode, 100, 0,
|
||||
)
|
||||
if err != errNoPathFound {
|
||||
t.Fatalf("path shouldn't have been found: %v", err)
|
||||
@ -1495,7 +1497,7 @@ func TestDestTLVGraphFallback(t *testing.T) {
|
||||
graph: ctx.graphParams.graph,
|
||||
},
|
||||
r, testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, target, 100,
|
||||
sourceNode.PubKeyBytes, target, 100, 0,
|
||||
)
|
||||
}
|
||||
|
||||
@ -1604,7 +1606,7 @@ func TestMissingFeatureDep(t *testing.T) {
|
||||
graph: ctx.graphParams.graph,
|
||||
},
|
||||
r, testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, target, 100,
|
||||
sourceNode.PubKeyBytes, target, 100, 0,
|
||||
)
|
||||
}
|
||||
|
||||
@ -1682,7 +1684,7 @@ func TestDestPaymentAddr(t *testing.T) {
|
||||
graph: ctx.graphParams.graph,
|
||||
},
|
||||
r, testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, target, 100,
|
||||
sourceNode.PubKeyBytes, target, 100, 0,
|
||||
)
|
||||
}
|
||||
|
||||
@ -1743,7 +1745,7 @@ func TestPathInsufficientCapacity(t *testing.T) {
|
||||
graph: graph.graph,
|
||||
},
|
||||
noRestrictions, testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt, 0,
|
||||
)
|
||||
if err != errNoPathFound {
|
||||
t.Fatalf("graph shouldn't be able to support payment: %v", err)
|
||||
@ -1776,7 +1778,7 @@ func TestRouteFailMinHTLC(t *testing.T) {
|
||||
graph: graph.graph,
|
||||
},
|
||||
noRestrictions, testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt, 0,
|
||||
)
|
||||
if err != errNoPathFound {
|
||||
t.Fatalf("graph shouldn't be able to support payment: %v", err)
|
||||
@ -1875,7 +1877,7 @@ func TestRouteFailDisabledEdge(t *testing.T) {
|
||||
graph: graph.graph,
|
||||
},
|
||||
noRestrictions, testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt, 0,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find path: %v", err)
|
||||
@ -1903,7 +1905,7 @@ func TestRouteFailDisabledEdge(t *testing.T) {
|
||||
graph: graph.graph,
|
||||
},
|
||||
noRestrictions, testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt, 0,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find path: %v", err)
|
||||
@ -1928,7 +1930,7 @@ func TestRouteFailDisabledEdge(t *testing.T) {
|
||||
graph: graph.graph,
|
||||
},
|
||||
noRestrictions, testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt, 0,
|
||||
)
|
||||
if err != errNoPathFound {
|
||||
t.Fatalf("graph shouldn't be able to support payment: %v", err)
|
||||
@ -1962,7 +1964,7 @@ func TestPathSourceEdgesBandwidth(t *testing.T) {
|
||||
graph: graph.graph,
|
||||
},
|
||||
noRestrictions, testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt, 0,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find path: %v", err)
|
||||
@ -1986,7 +1988,7 @@ func TestPathSourceEdgesBandwidth(t *testing.T) {
|
||||
bandwidthHints: bandwidths,
|
||||
},
|
||||
noRestrictions, testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt, 0,
|
||||
)
|
||||
if err != errNoPathFound {
|
||||
t.Fatalf("graph shouldn't be able to support payment: %v", err)
|
||||
@ -2004,7 +2006,7 @@ func TestPathSourceEdgesBandwidth(t *testing.T) {
|
||||
bandwidthHints: bandwidths,
|
||||
},
|
||||
noRestrictions, testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt, 0,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find path: %v", err)
|
||||
@ -2035,7 +2037,7 @@ func TestPathSourceEdgesBandwidth(t *testing.T) {
|
||||
bandwidthHints: bandwidths,
|
||||
},
|
||||
noRestrictions, testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt, 0,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find path: %v", err)
|
||||
@ -2872,7 +2874,7 @@ func (c *pathFindingTestContext) findPath(target route.Vertex,
|
||||
|
||||
return findPath(
|
||||
&c.graphParams, &c.restrictParams, &c.pathFindingConfig,
|
||||
c.source, target, amt,
|
||||
c.source, target, amt, 0,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -113,6 +113,8 @@ func (p *paymentSession) RequestRoute(payment *LightningPayment,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
finalHtlcExpiry := int32(height) + int32(finalCltvDelta)
|
||||
|
||||
path, err := p.pathFinder(
|
||||
&graphParams{
|
||||
graph: ss.Graph,
|
||||
@ -121,7 +123,7 @@ func (p *paymentSession) RequestRoute(payment *LightningPayment,
|
||||
},
|
||||
restrictions, &ss.PathFindingConfig,
|
||||
ss.SelfNode.PubKeyBytes, payment.Target,
|
||||
payment.Amount,
|
||||
payment.Amount, finalHtlcExpiry,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -15,8 +15,8 @@ func TestRequestRoute(t *testing.T) {
|
||||
|
||||
findPath := func(g *graphParams, r *RestrictParams,
|
||||
cfg *PathFindingConfig, source, target route.Vertex,
|
||||
amt lnwire.MilliSatoshi) ([]*channeldb.ChannelEdgePolicy,
|
||||
error) {
|
||||
amt lnwire.MilliSatoshi, finalHtlcExpiry int32) (
|
||||
[]*channeldb.ChannelEdgePolicy, error) {
|
||||
|
||||
// We expect find path to receive a cltv limit excluding the
|
||||
// final cltv delta (including the block padding).
|
||||
|
@ -1431,27 +1431,29 @@ func (r *ChannelRouter) FindRoute(source, target route.Vertex,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We'll fetch the current block height so we can properly calculate the
|
||||
// required HTLC time locks within the route.
|
||||
_, currentHeight, err := r.cfg.Chain.GetBestBlock()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Now that we know the destination is reachable within the graph, we'll
|
||||
// execute our path finding algorithm.
|
||||
finalHtlcExpiry := currentHeight + int32(finalCLTVDelta)
|
||||
|
||||
path, err := findPath(
|
||||
&graphParams{
|
||||
graph: r.cfg.Graph,
|
||||
bandwidthHints: bandwidthHints,
|
||||
},
|
||||
restrictions, &r.cfg.PathFindingConfig,
|
||||
source, target, amt,
|
||||
source, target, amt, finalHtlcExpiry,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We'll fetch the current block height so we can properly calculate the
|
||||
// required HTLC time locks within the route.
|
||||
_, currentHeight, err := r.cfg.Chain.GetBestBlock()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create the route with absolute time lock values.
|
||||
route, err := newRoute(
|
||||
source, path, uint32(currentHeight),
|
||||
|
@ -2174,7 +2174,7 @@ func TestFindPathFeeWeighting(t *testing.T) {
|
||||
},
|
||||
noRestrictions,
|
||||
testPathFindingConfig,
|
||||
sourceNode.PubKeyBytes, target, amt,
|
||||
sourceNode.PubKeyBytes, target, amt, 0,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find path: %v", err)
|
||||
|
Loading…
Reference in New Issue
Block a user