routing: account for case where final destination send TemporaryChannelFailure

In this commit, we fix an existing bug that could cause lnd to crash if
we sent a payment, and the *destination* sent a temp channel failure
error message. When handling such a message, we’ll look in the nextHop
map to see which channel was *after* the node that sent the payment.
However, if the destination sends this error, then there’ll be no entry
in this map.

To address this case, we now add a prevHop map. If we attempt to lookup
a node in the nextHop map, and they don’t have an entry, then we’ll
consult the prevHop map.

We also update the set of tests to ensure that we’re properly setting
both the prevHop map and the nextHop map.
This commit is contained in:
Olaoluwa Osuntokun
2018-01-10 15:15:49 -08:00
parent beeb75cb5f
commit d70e4bb0a0
4 changed files with 78 additions and 5 deletions

View File

@ -411,6 +411,41 @@ func TestBasicGraphPathFinding(t *testing.T) {
paymentAmt+firstHopFee, route.Hops[1].AmtToForward)
}
// Finally, the next and prev hop maps should be properly set.
//
// The previous hop from goku should be the channel from roasbeef, and
// the next hop should be the channel to sophon.
gokuPrevChan, ok := route.prevHopChannel(aliases["songoku"])
if !ok {
t.Fatalf("goku didn't have next chan but should have")
}
if gokuPrevChan.ChannelID != route.Hops[0].Channel.ChannelID {
t.Fatalf("incorrect prev chan: expected %v, got %v",
gokuPrevChan.ChannelID, route.Hops[0].Channel.ChannelID)
}
gokuNextChan, ok := route.nextHopChannel(aliases["songoku"])
if !ok {
t.Fatalf("goku didn't have prev chan but should have")
}
if gokuNextChan.ChannelID != route.Hops[1].Channel.ChannelID {
t.Fatalf("incorrect prev chan: expected %v, got %v",
gokuNextChan.ChannelID, route.Hops[1].Channel.ChannelID)
}
// Sophon shouldn't have a next chan, but she should have a prev chan.
if _, ok := route.nextHopChannel(aliases["sophon"]); ok {
t.Fatalf("incorrect next hop map, no vertexes should " +
"be after sophon")
}
sophonPrevEdge, ok := route.prevHopChannel(aliases["sophon"])
if !ok {
t.Fatalf("sophon didn't have prev chan but should have")
}
if sophonPrevEdge.ChannelID != route.Hops[1].Channel.ChannelID {
t.Fatalf("incorrect prev chan: expected %v, got %v",
sophonPrevEdge.ChannelID, route.Hops[1].Channel.ChannelID)
}
// Next, attempt to query for a path to Luo Ji for 100 satoshis, there
// exist two possible paths in the graph, but the shorter (1 hop) path
// should be selected.