diff --git a/routing/result_interpretation.go b/routing/result_interpretation.go index fae2835a..30d65cc0 100644 --- a/routing/result_interpretation.go +++ b/routing/result_interpretation.go @@ -191,10 +191,8 @@ func (i *interpretedResult) processPaymentOutcomeFinal( i.failPair(route, n-1) // The other hops relayed corectly, so assign those pairs a - // success result. - if n > 2 { - i.successPairRange(route, 0, n-2) - } + // success result. At this point, n >= 2. + i.successPairRange(route, 0, n-2) // We are using wrong payment hash or amount, fail the payment. case *lnwire.FailIncorrectPaymentAmount, @@ -239,7 +237,7 @@ func (i *interpretedResult) processPaymentOutcomeFinal( i.failNode(route, n) // Other channels in the route forwarded correctly. - if n > 2 { + if n >= 2 { i.successPairRange(route, 0, n-2) } diff --git a/routing/result_interpretation_test.go b/routing/result_interpretation_test.go index a5ed7989..2204139e 100644 --- a/routing/result_interpretation_test.go +++ b/routing/result_interpretation_test.go @@ -32,6 +32,16 @@ var ( }, } + routeThreeHop = route.Route{ + SourcePubKey: hops[0], + TotalAmount: 100, + Hops: []*route.Hop{ + {PubKeyBytes: hops[1], AmtToForward: 99}, + {PubKeyBytes: hops[2], AmtToForward: 97}, + {PubKeyBytes: hops[3], AmtToForward: 94}, + }, + } + routeFourHop = route.Route{ SourcePubKey: hops[0], TotalAmount: 100, @@ -203,7 +213,7 @@ var resultTestCases = []resultTestCase{ // be failed while the proceeding hops are reproed as successes. The // failure is terminal since the receiver can't process our onion. { - name: "fail invalid onion payload final hop", + name: "fail invalid onion payload final hop four", route: &routeFourHop, failureSrcIdx: 4, failure: lnwire.NewInvalidOnionPayload(0, 0), @@ -229,6 +239,30 @@ var resultTestCases = []resultTestCase{ }, }, + // Tests an invalid onion payload from a final hop on a three hop route. + { + name: "fail invalid onion payload final hop three", + route: &routeThreeHop, + failureSrcIdx: 3, + failure: lnwire.NewInvalidOnionPayload(0, 0), + + expectedResult: &interpretedResult{ + pairResults: map[DirectedNodePair]pairResult{ + getTestPair(0, 1): { + success: true, + amt: 100, + }, + getTestPair(1, 2): { + success: true, + amt: 99, + }, + getTestPair(3, 2): {}, + }, + finalFailureReason: &reasonError, + nodeFailure: &hops[3], + }, + }, + // Tests an invalid onion payload from an intermediate hop. Only the // reporting node should be failed. The failure is non-terminal since we // can still try other paths.