diff --git a/routing/pathfind.go b/routing/pathfind.go index f2e0b134..c3035711 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -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 diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index 383e0c2f..81278f40 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -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) + } +} diff --git a/routing/router_test.go b/routing/router_test.go index c184c3ce..ebe7d545 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -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. diff --git a/rpcserver.go b/rpcserver.go index 64e19005..62bb30fc 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -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 }