From 0b6a19866bde6916989a4ecd35197ad499aa19f4 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 26 Oct 2018 11:41:55 -0700 Subject: [PATCH] routing/pathfind: pass ignore disable flags for local channels To decouple our own path finding from the graph state, we don't consider the disable bit when attempting to use local channels. Instead the bandwidth hints will be zero for local inactive channels. We alos modify the unit test to check that the disable flag is ignored for local edges. --- routing/pathfind.go | 17 ++++++++++--- routing/pathfind_test.go | 53 +++++++++++++++++++++++++++++++++------- 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/routing/pathfind.go b/routing/pathfind.go index fa9778ae..a1910292 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -462,7 +462,11 @@ type graphParams struct { // 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. + // 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 } @@ -585,10 +589,15 @@ func findPath(g *graphParams, r *restrictParams, 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 } diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index c535a4ee..0948e0fa 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -1451,7 +1451,9 @@ 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() @@ -1487,19 +1489,52 @@ func TestRouteFailDisabledEdge(t *testing.T) { 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( + &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,