Merge pull request #2115 from halseth/disable-bit-decoupling

path finding: Disable bit decoupling
This commit is contained in:
Olaoluwa Osuntokun 2018-12-04 17:31:08 -08:00 committed by GitHub
commit 810afa937a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 375 additions and 68 deletions

@ -406,9 +406,17 @@ func (p *paymentSession) RequestRoute(payment *LightningPayment,
// to our destination, respecting the recommendations from
// missionControl.
path, err := findPath(
nil, p.mc.graph, p.additionalEdges, p.mc.selfNode,
payment.Target, pruneView.vertexes, pruneView.edges,
payment.Amount, payment.FeeLimit, p.bandwidthHints,
&graphParams{
graph: p.mc.graph,
additionalEdges: p.additionalEdges,
bandwidthHints: p.bandwidthHints,
},
&restrictParams{
ignoredNodes: pruneView.vertexes,
ignoredEdges: pruneView.edges,
feeLimit: payment.FeeLimit,
},
p.mc.selfNode, payment.Target, payment.Amount,
)
if err != nil {
return nil, err

@ -446,6 +446,46 @@ func edgeWeight(lockedAmt lnwire.MilliSatoshi, fee lnwire.MilliSatoshi,
return int64(fee) + timeLockPenalty
}
// graphParams wraps the set of graph parameters passed to findPath.
type graphParams struct {
// tx can be set to an existing db transaction. If not set, a new
// transaction will be started.
tx *bbolt.Tx
// graph is the ChannelGraph to be used during path finding.
graph *channeldb.ChannelGraph
// additionalEdges is an optional set of edges that should be
// considered during path finding, that is not already found in the
// channel graph.
additionalEdges map[Vertex][]*channeldb.ChannelEdgePolicy
// bandwidthHints is an optional map from channels to bandwidths that
// can be populated if the caller has a better estimate of the current
// channel bandwidth than what is found in the graph. If set, it will
// override the capacities and disabled flags found in the graph for
// local channels when doing path finding. In particular, it should be
// set to the current available sending bandwidth for active local
// channels, and 0 for inactive channels.
bandwidthHints map[uint64]lnwire.MilliSatoshi
}
// restrictParams wraps the set of restrictions passed to findPath that the
// found path must adhere to.
type restrictParams struct {
// ignoredNodes is an optional set of nodes that should be ignored if
// encountered during path finding.
ignoredNodes map[Vertex]struct{}
// ignoredEdges is an optional set of edges that should be ignored if
// encountered during path finding.
ignoredEdges map[uint64]struct{}
// feeLimit is a maximum fee amount allowed to be used on the path from
// the source to the target.
feeLimit lnwire.MilliSatoshi
}
// findPath attempts to find a path from the source node within the
// ChannelGraph to the target node that's capable of supporting a payment of
// `amt` value. The current approach implemented is modified version of
@ -457,16 +497,14 @@ func edgeWeight(lockedAmt lnwire.MilliSatoshi, fee lnwire.MilliSatoshi,
// destination node back to source. This is to properly accumulate fees
// that need to be paid along the path and accurately check the amount
// to forward at every node against the available bandwidth.
func findPath(tx *bbolt.Tx, graph *channeldb.ChannelGraph,
additionalEdges map[Vertex][]*channeldb.ChannelEdgePolicy,
func findPath(g *graphParams, r *restrictParams,
sourceNode *channeldb.LightningNode, target *btcec.PublicKey,
ignoredNodes map[Vertex]struct{}, ignoredEdges map[uint64]struct{},
amt lnwire.MilliSatoshi, feeLimit lnwire.MilliSatoshi,
bandwidthHints map[uint64]lnwire.MilliSatoshi) ([]*channeldb.ChannelEdgePolicy, error) {
amt lnwire.MilliSatoshi) ([]*channeldb.ChannelEdgePolicy, error) {
var err error
tx := g.tx
if tx == nil {
tx, err = graph.Database().Begin(false)
tx, err = g.graph.Database().Begin(false)
if err != nil {
return nil, err
}
@ -483,7 +521,8 @@ func findPath(tx *bbolt.Tx, graph *channeldb.ChannelGraph,
// also returns the source node, so there is no need to add the source
// node explicitly.
distance := make(map[Vertex]nodeWithDist)
if err := graph.ForEachNode(tx, func(_ *bbolt.Tx, node *channeldb.LightningNode) error {
if err := g.graph.ForEachNode(tx, func(_ *bbolt.Tx,
node *channeldb.LightningNode) error {
// TODO(roasbeef): with larger graph can just use disk seeks
// with a visited map
distance[Vertex(node.PubKeyBytes)] = nodeWithDist{
@ -496,7 +535,7 @@ func findPath(tx *bbolt.Tx, graph *channeldb.ChannelGraph,
}
additionalEdgesWithSrc := make(map[Vertex][]*edgePolicyWithSource)
for vertex, outgoingEdgePolicies := range additionalEdges {
for vertex, outgoingEdgePolicies := range g.additionalEdges {
// We'll also include all the nodes found within the additional
// edges that are not known to us yet in the distance map.
node := &channeldb.LightningNode{PubKeyBytes: vertex}
@ -550,19 +589,24 @@ func findPath(tx *bbolt.Tx, graph *channeldb.ChannelGraph,
fromVertex := Vertex(fromNode.PubKeyBytes)
// If the edge is currently disabled, then we'll stop here, as
// we shouldn't attempt to route through it.
// If this is not a local channel and it is disabled, we will
// skip it.
// TODO(halseth): also ignore disable flags for non-local
// channels if bandwidth hint is set?
isSourceChan := fromVertex == sourceVertex
edgeFlags := lnwire.ChanUpdateFlag(edge.Flags)
if edgeFlags&lnwire.ChanUpdateDisabled != 0 {
isDisabled := edgeFlags&lnwire.ChanUpdateDisabled != 0
if !isSourceChan && isDisabled {
return
}
// If this vertex or edge has been black listed, then we'll
// skip exploring this edge.
if _, ok := ignoredNodes[fromVertex]; ok {
if _, ok := r.ignoredNodes[fromVertex]; ok {
return
}
if _, ok := ignoredEdges[edge.ChannelID]; ok {
if _, ok := r.ignoredEdges[edge.ChannelID]; ok {
return
}
@ -609,7 +653,7 @@ func findPath(tx *bbolt.Tx, graph *channeldb.ChannelGraph,
// Check if accumulated fees would exceed fee limit when this
// node would be added to the path.
totalFee := amountToReceive - amt
if totalFee > feeLimit {
if totalFee > r.feeLimit {
return
}
@ -697,7 +741,7 @@ func findPath(tx *bbolt.Tx, graph *channeldb.ChannelGraph,
// We'll query the lower layer to see if we can obtain
// any more up to date information concerning the
// bandwidth of this edge.
edgeBandwidth, ok := bandwidthHints[edgeInfo.ChannelID]
edgeBandwidth, ok := g.bandwidthHints[edgeInfo.ChannelID]
if !ok {
// If we don't have a hint for this edge, then
// we'll just use the known Capacity as the
@ -734,7 +778,8 @@ func findPath(tx *bbolt.Tx, graph *channeldb.ChannelGraph,
// and use the payment amount as its capacity.
bandWidth := partialPath.amountToReceive
for _, reverseEdge := range additionalEdgesWithSrc[bestNode.PubKeyBytes] {
processEdge(reverseEdge.sourceNode, reverseEdge.edge, bandWidth, pivot)
processEdge(reverseEdge.sourceNode, reverseEdge.edge,
bandWidth, pivot)
}
}
@ -745,7 +790,8 @@ func findPath(tx *bbolt.Tx, graph *channeldb.ChannelGraph,
"destination")
}
// Use the nextHop map to unravel the forward path from source to target.
// Use the nextHop map to unravel the forward path from source to
// target.
pathEdges := make([]*channeldb.ChannelEdgePolicy, 0, len(next))
currentNode := sourceVertex
for currentNode != targetVertex { // TODO(roasbeef): assumes no cycles
@ -802,8 +848,17 @@ func findPaths(tx *bbolt.Tx, graph *channeldb.ChannelGraph,
// selfNode) to the target destination that's capable of carrying amt
// satoshis along the path before fees are calculated.
startingPath, err := findPath(
tx, graph, nil, source, target, ignoredVertexes, ignoredEdges,
amt, feeLimit, bandwidthHints,
&graphParams{
tx: tx,
graph: graph,
bandwidthHints: bandwidthHints,
},
&restrictParams{
ignoredNodes: ignoredVertexes,
ignoredEdges: ignoredEdges,
feeLimit: feeLimit,
},
source, target, amt,
)
if err != nil {
log.Errorf("Unable to find path: %v", err)
@ -874,9 +929,16 @@ func findPaths(tx *bbolt.Tx, graph *channeldb.ChannelGraph,
// root path removed, we'll attempt to find another
// shortest path from the spur node to the destination.
spurPath, err := findPath(
tx, graph, nil, spurNode, target,
ignoredVertexes, ignoredEdges, amt, feeLimit,
bandwidthHints,
&graphParams{
tx: tx,
graph: graph,
bandwidthHints: bandwidthHints,
},
&restrictParams{
ignoredNodes: ignoredVertexes,
ignoredEdges: ignoredEdges,
feeLimit: feeLimit,
}, spurNode, target, amt,
)
// If we weren't able to find a path, we'll continue to

@ -556,10 +556,10 @@ func TestFindLowestFeePath(t *testing.T) {
}
testGraphInstance, err := createTestGraphFromChannels(testChannels)
defer testGraphInstance.cleanUp()
if err != nil {
t.Fatalf("unable to create graph: %v", err)
}
defer testGraphInstance.cleanUp()
sourceNode, err := testGraphInstance.graph.SourceNode()
if err != nil {
@ -578,8 +578,15 @@ func TestFindLowestFeePath(t *testing.T) {
paymentAmt := lnwire.NewMSatFromSatoshis(100)
target := testGraphInstance.aliasMap["target"]
path, err := findPath(
nil, testGraphInstance.graph, nil, sourceNode, target,
ignoredVertexes, ignoredEdges, paymentAmt, noFeeLimit, nil,
&graphParams{
graph: testGraphInstance.graph,
},
&restrictParams{
ignoredNodes: ignoredVertexes,
ignoredEdges: ignoredEdges,
feeLimit: noFeeLimit,
},
sourceNode, target, paymentAmt,
)
if err != nil {
t.Fatalf("unable to find path: %v", err)
@ -676,10 +683,10 @@ func TestBasicGraphPathFinding(t *testing.T) {
t.Parallel()
testGraphInstance, err := parseTestGraph(basicGraphFilePath)
defer testGraphInstance.cleanUp()
if err != nil {
t.Fatalf("unable to create graph: %v", err)
}
defer testGraphInstance.cleanUp()
// With the test graph loaded, we'll test some basic path finding using
// the pre-generated graph. Consult the testdata/basic_graph.json file
@ -717,8 +724,15 @@ func testBasicGraphPathFindingCase(t *testing.T, graphInstance *testGraphInstanc
paymentAmt := lnwire.NewMSatFromSatoshis(test.paymentAmt)
target := graphInstance.aliasMap[test.target]
path, err := findPath(
nil, graphInstance.graph, nil, sourceNode, target,
ignoredVertexes, ignoredEdges, paymentAmt, test.feeLimit, nil,
&graphParams{
graph: graphInstance.graph,
},
&restrictParams{
ignoredNodes: ignoredVertexes,
ignoredEdges: ignoredEdges,
feeLimit: test.feeLimit,
},
sourceNode, target, paymentAmt,
)
if test.expectFailureNoPath {
if err == nil {
@ -858,10 +872,10 @@ func TestPathFindingWithAdditionalEdges(t *testing.T) {
t.Parallel()
graph, err := parseTestGraph(basicGraphFilePath)
defer graph.cleanUp()
if err != nil {
t.Fatalf("unable to create graph: %v", err)
}
defer graph.cleanUp()
sourceNode, err := graph.graph.SourceNode()
if err != nil {
@ -905,8 +919,14 @@ func TestPathFindingWithAdditionalEdges(t *testing.T) {
// We should now be able to find a path from roasbeef to doge.
path, err := findPath(
nil, graph.graph, additionalEdges, sourceNode, dogePubKey, nil, nil,
paymentAmt, noFeeLimit, nil,
&graphParams{
graph: graph.graph,
additionalEdges: additionalEdges,
},
&restrictParams{
feeLimit: noFeeLimit,
},
sourceNode, dogePubKey, paymentAmt,
)
if err != nil {
t.Fatalf("unable to find private path to doge: %v", err)
@ -921,10 +941,10 @@ func TestKShortestPathFinding(t *testing.T) {
t.Parallel()
graph, err := parseTestGraph(basicGraphFilePath)
defer graph.cleanUp()
if err != nil {
t.Fatalf("unable to create graph: %v", err)
}
defer graph.cleanUp()
sourceNode, err := graph.graph.SourceNode()
if err != nil {
@ -1246,10 +1266,10 @@ func TestNewRoutePathTooLong(t *testing.T) {
// Ensure that potential paths which are over the maximum hop-limit are
// rejected.
graph, err := parseTestGraph(excessiveHopsGraphFilePath)
defer graph.cleanUp()
if err != nil {
t.Fatalf("unable to create graph: %v", err)
}
defer graph.cleanUp()
sourceNode, err := graph.graph.SourceNode()
if err != nil {
@ -1261,12 +1281,19 @@ func TestNewRoutePathTooLong(t *testing.T) {
paymentAmt := lnwire.NewMSatFromSatoshis(100)
// We start by confirming that routing a payment 20 hops away is possible.
// Alice should be able to find a valid route to ursula.
// We start by confirming that routing a payment 20 hops away is
// possible. Alice should be able to find a valid route to ursula.
target := graph.aliasMap["ursula"]
_, err = findPath(
nil, graph.graph, nil, sourceNode, target, ignoredVertexes,
ignoredEdges, paymentAmt, noFeeLimit, nil,
&graphParams{
graph: graph.graph,
},
&restrictParams{
ignoredNodes: ignoredVertexes,
ignoredEdges: ignoredEdges,
feeLimit: noFeeLimit,
},
sourceNode, target, paymentAmt,
)
if err != nil {
t.Fatalf("path should have been found")
@ -1276,8 +1303,15 @@ func TestNewRoutePathTooLong(t *testing.T) {
// presented to Alice.
target = graph.aliasMap["vincent"]
path, err := findPath(
nil, graph.graph, nil, sourceNode, target, ignoredVertexes,
ignoredEdges, paymentAmt, noFeeLimit, nil,
&graphParams{
graph: graph.graph,
},
&restrictParams{
ignoredNodes: ignoredVertexes,
ignoredEdges: ignoredEdges,
feeLimit: noFeeLimit,
},
sourceNode, target, paymentAmt,
)
if err == nil {
t.Fatalf("should not have been able to find path, supposed to be "+
@ -1291,10 +1325,10 @@ func TestPathNotAvailable(t *testing.T) {
t.Parallel()
graph, err := parseTestGraph(basicGraphFilePath)
defer graph.cleanUp()
if err != nil {
t.Fatalf("unable to create graph: %v", err)
}
defer graph.cleanUp()
sourceNode, err := graph.graph.SourceNode()
if err != nil {
@ -1318,8 +1352,15 @@ func TestPathNotAvailable(t *testing.T) {
}
_, err = findPath(
nil, graph.graph, nil, sourceNode, unknownNode, ignoredVertexes,
ignoredEdges, 100, noFeeLimit, nil,
&graphParams{
graph: graph.graph,
},
&restrictParams{
ignoredNodes: ignoredVertexes,
ignoredEdges: ignoredEdges,
feeLimit: noFeeLimit,
},
sourceNode, unknownNode, 100,
)
if !IsError(err, ErrNoPathFound) {
t.Fatalf("path shouldn't have been found: %v", err)
@ -1330,10 +1371,10 @@ func TestPathInsufficientCapacity(t *testing.T) {
t.Parallel()
graph, err := parseTestGraph(basicGraphFilePath)
defer graph.cleanUp()
if err != nil {
t.Fatalf("unable to create graph: %v", err)
}
defer graph.cleanUp()
sourceNode, err := graph.graph.SourceNode()
if err != nil {
@ -1354,8 +1395,15 @@ func TestPathInsufficientCapacity(t *testing.T) {
payAmt := lnwire.NewMSatFromSatoshis(btcutil.SatoshiPerBitcoin)
_, err = findPath(
nil, graph.graph, nil, sourceNode, target, ignoredVertexes,
ignoredEdges, payAmt, noFeeLimit, nil,
&graphParams{
graph: graph.graph,
},
&restrictParams{
ignoredNodes: ignoredVertexes,
ignoredEdges: ignoredEdges,
feeLimit: noFeeLimit,
},
sourceNode, target, payAmt,
)
if !IsError(err, ErrNoPathFound) {
t.Fatalf("graph shouldn't be able to support payment: %v", err)
@ -1368,10 +1416,10 @@ func TestRouteFailMinHTLC(t *testing.T) {
t.Parallel()
graph, err := parseTestGraph(basicGraphFilePath)
defer graph.cleanUp()
if err != nil {
t.Fatalf("unable to create graph: %v", err)
}
defer graph.cleanUp()
sourceNode, err := graph.graph.SourceNode()
if err != nil {
@ -1386,8 +1434,15 @@ func TestRouteFailMinHTLC(t *testing.T) {
target := graph.aliasMap["songoku"]
payAmt := lnwire.MilliSatoshi(10)
_, err = findPath(
nil, graph.graph, nil, sourceNode, target, ignoredVertexes,
ignoredEdges, payAmt, noFeeLimit, nil,
&graphParams{
graph: graph.graph,
},
&restrictParams{
ignoredNodes: ignoredVertexes,
ignoredEdges: ignoredEdges,
feeLimit: noFeeLimit,
},
sourceNode, target, payAmt,
)
if !IsError(err, ErrNoPathFound) {
t.Fatalf("graph shouldn't be able to support payment: %v", err)
@ -1396,15 +1451,17 @@ func TestRouteFailMinHTLC(t *testing.T) {
// TestRouteFailDisabledEdge tests that if we attempt to route to an edge
// that's disabled, then that edge is disqualified, and the routing attempt
// will fail.
// will fail. We also test that this is true only for non-local edges, as we'll
// ignore the disable flags, with the assumption that the correct bandwidth is
// found among the bandwidth hints.
func TestRouteFailDisabledEdge(t *testing.T) {
t.Parallel()
graph, err := parseTestGraph(basicGraphFilePath)
defer graph.cleanUp()
if err != nil {
t.Fatalf("unable to create graph: %v", err)
}
defer graph.cleanUp()
sourceNode, err := graph.graph.SourceNode()
if err != nil {
@ -1418,35 +1475,208 @@ func TestRouteFailDisabledEdge(t *testing.T) {
target := graph.aliasMap["sophon"]
payAmt := lnwire.NewMSatFromSatoshis(105000)
_, err = findPath(
nil, graph.graph, nil, sourceNode, target, ignoredVertexes,
ignoredEdges, payAmt, noFeeLimit, nil,
&graphParams{
graph: graph.graph,
},
&restrictParams{
ignoredNodes: ignoredVertexes,
ignoredEdges: ignoredEdges,
feeLimit: noFeeLimit,
},
sourceNode, target, payAmt,
)
if err != nil {
t.Fatalf("unable to find path: %v", err)
}
// First, we'll modify the edge from roasbeef -> phamnuwen, to read that
// it's disabled.
_, _, phamnuwenEdge, err := graph.graph.FetchChannelEdgesByID(999991)
// Disable the edge roasbeef->phamnuwen. This should not impact the
// path finding, as we don't consider the disable flag for local
// channels (and roasbeef is the source).
roasToPham := uint64(999991)
_, e1, e2, err := graph.graph.FetchChannelEdgesByID(roasToPham)
if err != nil {
t.Fatalf("unable to fetch goku's edge: %v", err)
t.Fatalf("unable to fetch edge: %v", err)
}
phamnuwenEdge.Flags = lnwire.ChanUpdateDisabled | lnwire.ChanUpdateDirection
if err := graph.graph.UpdateEdgePolicy(phamnuwenEdge); err != nil {
e1.Flags |= lnwire.ChanUpdateDisabled
if err := graph.graph.UpdateEdgePolicy(e1); err != nil {
t.Fatalf("unable to update edge: %v", err)
}
e2.Flags |= lnwire.ChanUpdateDisabled
if err := graph.graph.UpdateEdgePolicy(e2); err != nil {
t.Fatalf("unable to update edge: %v", err)
}
// Now, if we attempt to route through that edge, we should get a
// failure as it is no longer eligible.
_, err = findPath(
nil, graph.graph, nil, sourceNode, target, ignoredVertexes,
ignoredEdges, payAmt, noFeeLimit, nil,
&graphParams{
graph: graph.graph,
},
&restrictParams{
ignoredNodes: ignoredVertexes,
ignoredEdges: ignoredEdges,
feeLimit: noFeeLimit,
},
sourceNode, target, payAmt,
)
if err != nil {
t.Fatalf("unable to find path: %v", err)
}
// Now, we'll modify the edge from phamnuwen -> sophon, to read that
// it's disabled.
phamToSophon := uint64(99999)
_, e, _, err := graph.graph.FetchChannelEdgesByID(phamToSophon)
if err != nil {
t.Fatalf("unable to fetch edge: %v", err)
}
e.Flags |= lnwire.ChanUpdateDisabled
if err := graph.graph.UpdateEdgePolicy(e); err != nil {
t.Fatalf("unable to update edge: %v", err)
}
// If we attempt to route through that edge, we should get a failure as
// it is no longer eligible.
_, err = findPath(
&graphParams{
graph: graph.graph,
},
&restrictParams{
ignoredNodes: ignoredVertexes,
ignoredEdges: ignoredEdges,
feeLimit: noFeeLimit,
},
sourceNode, target, payAmt,
)
if !IsError(err, ErrNoPathFound) {
t.Fatalf("graph shouldn't be able to support payment: %v", err)
}
}
// TestPathSourceEdgesBandwidth tests that explicitly passing in a set of
// bandwidth hints is used by the path finding algorithm to consider whether to
// use a local channel.
func TestPathSourceEdgesBandwidth(t *testing.T) {
t.Parallel()
graph, err := parseTestGraph(basicGraphFilePath)
if err != nil {
t.Fatalf("unable to create graph: %v", err)
}
defer graph.cleanUp()
sourceNode, err := graph.graph.SourceNode()
if err != nil {
t.Fatalf("unable to fetch source node: %v", err)
}
ignoredEdges := make(map[uint64]struct{})
ignoredVertexes := make(map[Vertex]struct{})
// First, we'll try to route from roasbeef -> sophon. This should
// succeed without issue, and return a path via songoku, as that's the
// cheapest path.
target := graph.aliasMap["sophon"]
payAmt := lnwire.NewMSatFromSatoshis(50000)
path, err := findPath(
&graphParams{
graph: graph.graph,
},
&restrictParams{
ignoredNodes: ignoredVertexes,
ignoredEdges: ignoredEdges,
feeLimit: noFeeLimit,
},
sourceNode, target, payAmt,
)
if err != nil {
t.Fatalf("unable to find path: %v", err)
}
assertExpectedPath(t, path, "songoku", "sophon")
// Now we'll set the bandwidth of the edge roasbeef->songoku and
// roasbeef->phamnuwen to 0.
roasToSongoku := uint64(12345)
roasToPham := uint64(999991)
bandwidths := map[uint64]lnwire.MilliSatoshi{
roasToSongoku: 0,
roasToPham: 0,
}
// Since both these edges has a bandwidth of zero, no path should be
// found.
_, err = findPath(
&graphParams{
graph: graph.graph,
bandwidthHints: bandwidths,
},
&restrictParams{
ignoredNodes: ignoredVertexes,
ignoredEdges: ignoredEdges,
feeLimit: noFeeLimit,
},
sourceNode, target, payAmt,
)
if !IsError(err, ErrNoPathFound) {
t.Fatalf("graph shouldn't be able to support payment: %v", err)
}
// Set the bandwidth of roasbeef->phamnuwen high enough to carry the
// payment.
bandwidths[roasToPham] = 2 * payAmt
// Now, if we attempt to route again, we should find the path via
// phamnuven, as the other source edge won't be considered.
path, err = findPath(
&graphParams{
graph: graph.graph,
bandwidthHints: bandwidths,
},
&restrictParams{
ignoredNodes: ignoredVertexes,
ignoredEdges: ignoredEdges,
feeLimit: noFeeLimit,
},
sourceNode, target, payAmt,
)
if err != nil {
t.Fatalf("unable to find path: %v", err)
}
assertExpectedPath(t, path, "phamnuwen", "sophon")
// Finally, set the roasbeef->songoku bandwidth, but also set its
// disable flag.
bandwidths[roasToSongoku] = 2 * payAmt
_, e1, e2, err := graph.graph.FetchChannelEdgesByID(roasToSongoku)
if err != nil {
t.Fatalf("unable to fetch edge: %v", err)
}
e1.Flags |= lnwire.ChanUpdateDisabled
if err := graph.graph.UpdateEdgePolicy(e1); err != nil {
t.Fatalf("unable to update edge: %v", err)
}
e2.Flags |= lnwire.ChanUpdateDisabled
if err := graph.graph.UpdateEdgePolicy(e2); err != nil {
t.Fatalf("unable to update edge: %v", err)
}
// Since we ignore disable flags for local channels, a path should
// still be found.
path, err = findPath(
&graphParams{
graph: graph.graph,
bandwidthHints: bandwidths,
},
&restrictParams{
ignoredNodes: ignoredVertexes,
ignoredEdges: ignoredEdges,
feeLimit: noFeeLimit,
},
sourceNode, target, payAmt,
)
if err != nil {
t.Fatalf("unable to find path: %v", err)
}
assertExpectedPath(t, path, "songoku", "sophon")
}
func TestPathInsufficientCapacityWithFee(t *testing.T) {
t.Parallel()
@ -1465,10 +1695,10 @@ func TestPathFindSpecExample(t *testing.T) {
// height.
const startingHeight = 100
ctx, cleanUp, err := createTestCtxFromFile(startingHeight, specExampleFilePath)
defer cleanUp()
if err != nil {
t.Fatalf("unable to create router: %v", err)
}
defer cleanUp()
const (
aliceFinalCLTV = 10

@ -1872,8 +1872,15 @@ func TestFindPathFeeWeighting(t *testing.T) {
// the edge weighting, we should select the direct path over the 2 hop
// path even though the direct path has a higher potential time lock.
path, err := findPath(
nil, ctx.graph, nil, sourceNode, target, ignoreVertex,
ignoreEdge, amt, noFeeLimit, nil,
&graphParams{
graph: ctx.graph,
},
&restrictParams{
ignoredNodes: ignoreVertex,
ignoredEdges: ignoreEdge,
feeLimit: noFeeLimit,
},
sourceNode, target, amt,
)
if err != nil {
t.Fatalf("unable to find path: %v", err)