diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index a9222597c..45e0b3a27 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -57,7 +57,7 @@ type RouterBackend struct { restrictions *routing.RestrictParams, destCustomRecords record.CustomSet, routeHints map[route.Vertex][]*channeldb.CachedEdgePolicy, - finalExpiry uint16) (*route.Route, error) + finalExpiry uint16) (*route.Route, float64, error) MissionControl MissionControl @@ -325,7 +325,7 @@ func (r *RouterBackend) QueryRoutes(ctx context.Context, // Query the channel router for a possible path to the destination that // can carry `in.Amt` satoshis _including_ the total fee required on // the route. - route, err := r.FindRoute( + route, _, err := r.FindRoute( sourcePubKey, targetPubKey, amt, in.TimePref, restrictions, customRecords, routeHintEdges, finalCLTVDelta, ) diff --git a/lnrpc/routerrpc/router_backend_test.go b/lnrpc/routerrpc/router_backend_test.go index 89c7f8fff..bdbcfb8b8 100644 --- a/lnrpc/routerrpc/router_backend_test.go +++ b/lnrpc/routerrpc/router_backend_test.go @@ -126,7 +126,7 @@ func testQueryRoutes(t *testing.T, useMissionControl bool, useMsat bool, amt lnwire.MilliSatoshi, _ float64, restrictions *routing.RestrictParams, _ record.CustomSet, routeHints map[route.Vertex][]*channeldb.CachedEdgePolicy, - finalExpiry uint16) (*route.Route, error) { + finalExpiry uint16) (*route.Route, float64, error) { if int64(amt) != amtSat*1000 { t.Fatal("unexpected amount") @@ -187,7 +187,9 @@ func testQueryRoutes(t *testing.T, useMissionControl bool, useMsat bool, } hops := []*route.Hop{{}} - return route.NewRouteFromHops(amt, 144, source, hops) + route, err := route.NewRouteFromHops(amt, 144, source, hops) + + return route, expectedProb, err } backend := &RouterBackend{ diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index 29847e8da..502132db3 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -366,7 +366,7 @@ func (s *Server) EstimateRouteFee(ctx context.Context, // restriction for the default CLTV limit, otherwise we can find a route // that exceeds it and is useless to us. mc := s.cfg.RouterBackend.MissionControl - route, err := s.cfg.Router.FindRoute( + route, _, err := s.cfg.Router.FindRoute( s.cfg.RouterBackend.SelfNode, destNode, amtMsat, 0, &routing.RestrictParams{ FeeLimit: feeLimit, diff --git a/routing/pathfind.go b/routing/pathfind.go index a3a3955f7..bffc46336 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -43,7 +43,7 @@ const ( type pathFinder = func(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, source, target route.Vertex, amt lnwire.MilliSatoshi, timePref float64, finalHtlcExpiry int32) ( - []*channeldb.CachedEdgePolicy, error) + []*channeldb.CachedEdgePolicy, float64, error) var ( // DefaultAttemptCost is the default fixed virtual cost in path finding @@ -427,7 +427,7 @@ func getOutgoingBalance(node route.Vertex, outgoingChans map[uint64]struct{}, // available bandwidth. func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, source, target route.Vertex, amt lnwire.MilliSatoshi, timePref float64, - finalHtlcExpiry int32) ([]*channeldb.CachedEdgePolicy, error) { + finalHtlcExpiry int32) ([]*channeldb.CachedEdgePolicy, float64, error) { // Pathfinding can be a significant portion of the total payment // latency, especially on low-powered devices. Log several metrics to @@ -448,7 +448,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, var err error features, err = g.graph.fetchNodeFeatures(target) if err != nil { - return nil, err + return nil, 0, err } } @@ -457,14 +457,14 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, err := feature.ValidateRequired(features) if err != nil { log.Warnf("Pathfinding destination node features: %v", err) - return nil, errUnknownRequiredFeature + return nil, 0, errUnknownRequiredFeature } // Ensure that all transitive dependencies are set. err = feature.ValidateDeps(features) if err != nil { log.Warnf("Pathfinding destination node features: %v", err) - return nil, errMissingDependentFeature + return nil, 0, errMissingDependentFeature } // Now that we know the feature vector is well formed, we'll proceed in @@ -476,7 +476,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, if len(r.DestCustomRecords) > 0 && !features.HasFeature(lnwire.TLVOnionPayloadOptional) { - return nil, errNoTlvPayload + return nil, 0, errNoTlvPayload } // If the caller has a payment address to attach, check that our @@ -484,7 +484,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, if r.PaymentAddr != nil && !features.HasFeature(lnwire.PaymentAddrOptional) { - return nil, errNoPaymentAddr + return nil, 0, errNoPaymentAddr } // If the caller needs to send custom records, check that our @@ -492,7 +492,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, if r.Metadata != nil && !features.HasFeature(lnwire.TLVOnionPayloadOptional) { - return nil, errNoTlvPayload + return nil, 0, errNoTlvPayload } // Set up outgoing channel map for quicker access. @@ -513,19 +513,19 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, self, outgoingChanMap, g.bandwidthHints, g.graph, ) if err != nil { - return nil, err + return nil, 0, err } // If the total outgoing balance isn't sufficient, it will be // impossible to complete the payment. if total < amt { - return nil, errInsufficientBalance + return nil, 0, errInsufficientBalance } // If there is only not enough capacity on a single route, it // may still be possible to complete the payment by splitting. if max < amt { - return nil, errNoPathFound + return nil, 0, errNoPathFound } } @@ -611,8 +611,8 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, // Validate time preference value. if math.Abs(timePref) > 1 { - return nil, fmt.Errorf("time preference %v out of range [-1, 1]", - timePref) + return nil, 0, fmt.Errorf("time preference %v out of range "+ + "[-1, 1]", timePref) } // Scale to avoid the extremes -1 and 1 which run into infinity issues. @@ -856,7 +856,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, err := u.addGraphPolicies(g.graph) if err != nil { - return nil, err + return nil, 0, err } for _, reverseEdge := range additionalEdgesWithSrc[pivot] { @@ -895,7 +895,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, // Get feature vector for fromNode. fromFeatures, err := getGraphFeatures(fromNode) if err != nil { - return nil, err + return nil, 0, err } // If there are no valid features, skip this node. @@ -934,7 +934,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, if !ok { // If the node doesn't have a next hop it means we // didn't find a path. - return nil, errNoPathFound + return nil, 0, errNoPathFound } // Add the next hop to the list of path edges. @@ -968,7 +968,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, distance[source].probability, len(pathEdges), distance[source].amountToReceive-amt) - return pathEdges, nil + return pathEdges, distance[source].probability, nil } // getProbabilityBasedDist converts a weight into a distance that takes into diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index 20dcf1470..998d3a6cd 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -2291,7 +2291,7 @@ func TestPathFindSpecExample(t *testing.T) { // Query for a route of 4,999,999 mSAT to carol. carol := ctx.aliases["C"] const amt lnwire.MilliSatoshi = 4999999 - route, err := ctx.router.FindRoute( + route, _, err := ctx.router.FindRoute( bobNode.PubKeyBytes, carol, amt, 0, noRestrictions, nil, nil, MinCLTVDelta, ) @@ -2341,7 +2341,7 @@ func TestPathFindSpecExample(t *testing.T) { } // We'll now request a route from A -> B -> C. - route, err = ctx.router.FindRoute( + route, _, err = ctx.router.FindRoute( source.PubKeyBytes, carol, amt, 0, noRestrictions, nil, nil, MinCLTVDelta, ) @@ -3117,7 +3117,7 @@ func dbFindPath(graph *channeldb.ChannelGraph, } }() - return findPath( + route, _, err := findPath( &graphParams{ additionalEdges: additionalEdges, bandwidthHints: bandwidthHints, @@ -3125,4 +3125,6 @@ func dbFindPath(graph *channeldb.ChannelGraph, }, r, cfg, source, target, amt, timePref, finalHtlcExpiry, ) + + return route, err } diff --git a/routing/payment_session.go b/routing/payment_session.go index f3092ee7b..8b181a04d 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -297,7 +297,7 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, sourceVertex := routingGraph.sourceNode() // Find a route for the current amount. - path, err := p.pathFinder( + path, _, err := p.pathFinder( &graphParams{ additionalEdges: p.additionalEdges, bandwidthHints: bandwidthHints, diff --git a/routing/payment_session_test.go b/routing/payment_session_test.go index 4eaa5af66..18858f1f9 100644 --- a/routing/payment_session_test.go +++ b/routing/payment_session_test.go @@ -209,11 +209,10 @@ func TestRequestRoute(t *testing.T) { } // Override pathfinder with a mock. - session.pathFinder = func( - g *graphParams, r *RestrictParams, cfg *PathFindingConfig, - source, target route.Vertex, amt lnwire.MilliSatoshi, - timePref float64, - finalHtlcExpiry int32) ([]*channeldb.CachedEdgePolicy, error) { + session.pathFinder = func(_ *graphParams, r *RestrictParams, + _ *PathFindingConfig, _, _ route.Vertex, _ lnwire.MilliSatoshi, + _ float64, _ int32) ([]*channeldb.CachedEdgePolicy, float64, + error) { // We expect find path to receive a cltv limit excluding the // final cltv delta (including the block padding). @@ -232,7 +231,7 @@ func TestRequestRoute(t *testing.T) { }, } - return path, nil + return path, 1.0, nil } route, err := session.RequestRoute( diff --git a/routing/router.go b/routing/router.go index 949a4d8f1..378f45187 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1752,11 +1752,10 @@ type routingMsg struct { // particular target destination to which it is able to send `amt` after // factoring in channel capacities and cumulative fees along the route. func (r *ChannelRouter) FindRoute(source, target route.Vertex, - amt lnwire.MilliSatoshi, timePref float64, - restrictions *RestrictParams, + amt lnwire.MilliSatoshi, timePref float64, restrictions *RestrictParams, destCustomRecords record.CustomSet, routeHints map[route.Vertex][]*channeldb.CachedEdgePolicy, - finalExpiry uint16) (*route.Route, error) { + finalExpiry uint16) (*route.Route, float64, error) { log.Debugf("Searching for path to %v, sending %v", target, amt) @@ -1766,14 +1765,14 @@ func (r *ChannelRouter) FindRoute(source, target route.Vertex, r.cachedGraph, r.selfNode.PubKeyBytes, r.cfg.GetLink, ) if err != nil { - return nil, err + return nil, 0, err } // We'll fetch the current block height so we can properly calculate the // required HTLC time locks within the route. _, currentHeight, err := r.cfg.Chain.GetBestBlock() if err != nil { - return nil, err + return nil, 0, err } // Now that we know the destination is reachable within the graph, we'll @@ -1782,10 +1781,10 @@ func (r *ChannelRouter) FindRoute(source, target route.Vertex, // Validate time preference. if timePref < -1 || timePref > 1 { - return nil, errors.New("time preference out of range") + return nil, 0, errors.New("time preference out of range") } - path, err := findPath( + path, probability, err := findPath( &graphParams{ additionalEdges: routeHints, bandwidthHints: bandwidthHints, @@ -1796,7 +1795,7 @@ func (r *ChannelRouter) FindRoute(source, target route.Vertex, source, target, amt, timePref, finalHtlcExpiry, ) if err != nil { - return nil, err + return nil, 0, err } // Create the route with absolute time lock values. @@ -1810,7 +1809,7 @@ func (r *ChannelRouter) FindRoute(source, target route.Vertex, }, ) if err != nil { - return nil, err + return nil, 0, err } go log.Tracef("Obtained path to send %v to %x: %v", @@ -1819,7 +1818,7 @@ func (r *ChannelRouter) FindRoute(source, target route.Vertex, }), ) - return route, nil + return route, probability, nil } // generateNewSessionKey generates a new ephemeral private key to be used for a diff --git a/routing/router_test.go b/routing/router_test.go index ea76140a2..0346721e3 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -268,7 +268,7 @@ func TestFindRoutesWithFeeLimit(t *testing.T) { CltvLimit: math.MaxUint32, } - route, err := ctx.router.FindRoute( + route, _, err := ctx.router.FindRoute( ctx.router.selfNode.PubKeyBytes, target, paymentAmt, 0, restrictions, nil, nil, MinCLTVDelta, @@ -1554,7 +1554,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { targetNode := priv2.PubKey() var targetPubKeyBytes route.Vertex copy(targetPubKeyBytes[:], targetNode.SerializeCompressed()) - _, err = ctx.router.FindRoute( + _, _, err = ctx.router.FindRoute( ctx.router.selfNode.PubKeyBytes, targetPubKeyBytes, paymentAmt, 0, noRestrictions, nil, nil, MinCLTVDelta, @@ -1595,7 +1595,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { // Should still be able to find the route, and the info should be // updated. - _, err = ctx.router.FindRoute( + _, _, err = ctx.router.FindRoute( ctx.router.selfNode.PubKeyBytes, targetPubKeyBytes, paymentAmt, 0, noRestrictions, nil, nil, MinCLTVDelta,