From 559d3c0910f824283f41b7d53e0b262fc05eb706 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 4 Sep 2019 16:26:18 +0200 Subject: [PATCH] routing: also fail pairs for node-level failures This commit modifies the interpretation of node-level failures. Previously only the failing node was marked. With this commit, also the incoming and outgoing connections involved in the route are marked as failed. The change prepares for the removal of node-level failures in mission control probability estimation. --- routing/missioncontrol_test.go | 8 ++++---- routing/result_interpretation.go | 24 ++++++++++++++++++++++-- routing/result_interpretation_test.go | 7 +++++++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/routing/missioncontrol_test.go b/routing/missioncontrol_test.go index fd9596d2..93b37bf5 100644 --- a/routing/missioncontrol_test.go +++ b/routing/missioncontrol_test.go @@ -165,8 +165,8 @@ func TestMissionControl(t *testing.T) { ctx.restartMc() ctx.expectP(1000, 0.4) - // A node level failure should bring probability of every channel back - // to zero. + // A node level failure should bring probability of all known channels + // back to zero. ctx.reportFailure(0, lnwire.NewExpiryTooSoon(lnwire.ChannelUpdate{})) ctx.expectP(1000, 0) @@ -177,8 +177,8 @@ func TestMissionControl(t *testing.T) { len(history.Nodes)) } - if len(history.Pairs) != 2 { - t.Fatalf("expected 2 pairs, but got %v", len(history.Pairs)) + if len(history.Pairs) != 3 { + t.Fatalf("expected 3 pairs, but got %v", len(history.Pairs)) } // Test reporting a success. diff --git a/routing/result_interpretation.go b/routing/result_interpretation.go index d89f959a..696d930c 100644 --- a/routing/result_interpretation.go +++ b/routing/result_interpretation.go @@ -378,10 +378,30 @@ func (i *interpretedResult) processPaymentOutcomeUnknown(route *route.Route) { i.failPairRange(route, 0, n-1) } -// failNode marks the node indicated by idx in the route as failed. This -// function intentionally panics when the self node is failed. +// failNode marks the node indicated by idx in the route as failed. It also +// marks the incoming and outgoing channels of the node as failed. This function +// intentionally panics when the self node is failed. func (i *interpretedResult) failNode(rt *route.Route, idx int) { + // Mark the node as failing. i.nodeFailure = &rt.Hops[idx-1].PubKeyBytes + + // Mark the incoming connection as failed for the node. We intent to + // penalize as much as we can for a node level failure, including future + // outgoing traffic for this connection. The pair as it is returned by + // getPair is directed towards the failed node. Therefore we first + // reverse the pair. We don't want to affect the score of the node + // sending towards the failing node. + incomingChannelIdx := idx - 1 + inPair, _ := getPair(rt, incomingChannelIdx) + i.pairResults[inPair.Reverse()] = failPairResult(0) + + // If not the ultimate node, mark the outgoing connection as failed for + // the node. + if idx < len(rt.Hops) { + outgoingChannelIdx := idx + outPair, _ := getPair(rt, outgoingChannelIdx) + i.pairResults[outPair] = failPairResult(0) + } } // failPairRange marks the node pairs from node fromIdx to node toIdx as failed diff --git a/routing/result_interpretation_test.go b/routing/result_interpretation_test.go index 23ea5d1e..78b6088a 100644 --- a/routing/result_interpretation_test.go +++ b/routing/result_interpretation_test.go @@ -146,6 +146,10 @@ var resultTestCases = []resultTestCase{ expectedResult: &interpretedResult{ nodeFailure: &hops[1], + pairResults: map[DirectedNodePair]pairResult{ + getTestPair(1, 0): failPairResult(0), + getTestPair(1, 2): failPairResult(0), + }, }, }, @@ -160,6 +164,9 @@ var resultTestCases = []resultTestCase{ expectedResult: &interpretedResult{ finalFailureReason: &reasonError, nodeFailure: &hops[1], + pairResults: map[DirectedNodePair]pairResult{ + getTestPair(1, 0): failPairResult(0), + }, }, }, }