routing: check for empty hops list

This commit fixes a crash that could be triggered by sending an empty
hop list to the SendToRoute rpc.
This commit is contained in:
Joost Jager 2018-12-10 09:41:03 +01:00
parent 4d647b6e5d
commit b2cb760c65
No known key found for this signature in database
GPG Key ID: AE6B0D042C8E38D9
4 changed files with 30 additions and 5 deletions

@ -326,9 +326,12 @@ func newRoute(amtToSend, feeLimit lnwire.MilliSatoshi, sourceVertex Vertex,
}
// With the base routing data expressed as hops, build the full route
newRoute := NewRouteFromHops(
newRoute, err := NewRouteFromHops(
nextIncomingAmount, totalTimeLock, sourceVertex, hops,
)
if err != nil {
return nil, err
}
// Invalidate this route if its total fees exceed our fee limit.
if newRoute.TotalFees > feeLimit {
@ -344,7 +347,11 @@ func newRoute(amtToSend, feeLimit lnwire.MilliSatoshi, sourceVertex Vertex,
// information to perform the payment. It infers fee amounts and populates the
// node, chan and prev/next hop maps.
func NewRouteFromHops(amtToSend lnwire.MilliSatoshi, timeLock uint32,
sourceVertex Vertex, hops []*Hop) *Route {
sourceVertex Vertex, hops []*Hop) (*Route, error) {
if len(hops) == 0 {
return nil, ErrNoRouteHopsProvided
}
// First, we'll create a route struct and populate it with the fields
// for which the values are provided as arguments of this function.
@ -369,7 +376,7 @@ func NewRouteFromHops(amtToSend lnwire.MilliSatoshi, timeLock uint32,
route.chanIndex[hop.ChannelID] = struct{}{}
}
return route
return route, nil
}
// Vertex is a simple alias for the serialization of a compressed Bitcoin

@ -1903,3 +1903,15 @@ func assertExpectedPath(t *testing.T, path []*channeldb.ChannelEdgePolicy,
}
}
}
// TestNewRouteFromEmptyHops tests that the NewRouteFromHops function returns an
// error when the hop list is empty.
func TestNewRouteFromEmptyHops(t *testing.T) {
t.Parallel()
var source Vertex
_, err := NewRouteFromHops(0, 0, source, []*Hop{})
if err != ErrNoRouteHopsProvided {
t.Fatalf("expected empty hops error: instead got: %v", err)
}
}

@ -421,10 +421,13 @@ func TestChannelUpdateValidation(t *testing.T) {
},
}
route := NewRouteFromHops(
route, err := NewRouteFromHops(
lnwire.MilliSatoshi(10000), 100,
NewVertex(ctx.aliases["a"]), hops,
)
if err != nil {
t.Fatalf("unable to create route: %v", err)
}
// Set up a channel update message with an invalid signature to be
// returned to the sender.

@ -3848,12 +3848,15 @@ func (r *rpcServer) unmarshallRoute(rpcroute *lnrpc.Route,
prevNodePubKey = routeHop.PubKeyBytes
}
route := routing.NewRouteFromHops(
route, err := routing.NewRouteFromHops(
lnwire.MilliSatoshi(rpcroute.TotalAmtMsat),
rpcroute.TotalTimeLock,
sourceNode.PubKeyBytes,
hops,
)
if err != nil {
return nil, err
}
return route, nil
}