From 34b264a3d889a45b26feff623fa8ceebe8d8cf05 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 20 Jun 2019 12:03:45 +0200 Subject: [PATCH] routing: create PathFindingConfig for global parameters --- lnrpc/routerrpc/router_backend.go | 1 - routing/pathfind.go | 18 ++++++++----- routing/pathfind_test.go | 42 ++++++++++++++++++------------- routing/payment_session.go | 13 +++++----- routing/payment_session_source.go | 12 +++------ routing/payment_session_test.go | 5 ++-- routing/router.go | 6 ++++- routing/router_test.go | 25 ++++++++++++------ server.go | 17 ++++++++----- 9 files changed, 83 insertions(+), 56 deletions(-) diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 9916ff151..0d9499092 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -153,7 +153,6 @@ func (r *RouterBackend) QueryRoutes(ctx context.Context, return 1 }, - PaymentAttemptPenalty: routing.DefaultPaymentAttemptPenalty, } // Query the channel router for a possible path to the destination that diff --git a/routing/pathfind.go b/routing/pathfind.go index 7e9515326..91b40371f 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -37,8 +37,8 @@ const ( // pathFinder defines the interface of a path finding algorithm. type pathFinder = func(g *graphParams, r *RestrictParams, - source, target route.Vertex, amt lnwire.MilliSatoshi) ( - []*channeldb.ChannelEdgePolicy, error) + cfg *PathFindingConfig, source, target route.Vertex, + amt lnwire.MilliSatoshi) ([]*channeldb.ChannelEdgePolicy, error) var ( // DefaultPaymentAttemptPenalty is the virtual cost in path finding weight @@ -261,7 +261,11 @@ type RestrictParams struct { // ctlv. After path finding is complete, the caller needs to increase // all cltv expiry heights with the required final cltv delta. CltvLimit *uint32 +} +// PathFindingConfig defines global parameters that control the trade-off in +// path finding between fees and probabiity. +type PathFindingConfig struct { // PaymentAttemptPenalty is the virtual cost in path finding weight // units of executing a payment attempt that fails. It is used to trade // off potentially better routes against their probability of @@ -284,8 +288,9 @@ type RestrictParams struct { // destination node back to source. This is to properly accumulate fees // that need to be paid along the path and accurately check the amount // to forward at every node against the available bandwidth. -func findPath(g *graphParams, r *RestrictParams, source, target route.Vertex, - amt lnwire.MilliSatoshi) ([]*channeldb.ChannelEdgePolicy, error) { +func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, + source, target route.Vertex, amt lnwire.MilliSatoshi) ( + []*channeldb.ChannelEdgePolicy, error) { var err error tx := g.tx @@ -476,7 +481,7 @@ func findPath(g *graphParams, r *RestrictParams, source, target route.Vertex, // If the probability is below the specified lower bound, we can // abandon this direction. Adding further nodes can only lower // the probability more. - if probability < r.MinProbability { + if probability < cfg.MinProbability { return } @@ -494,7 +499,8 @@ func findPath(g *graphParams, r *RestrictParams, source, target route.Vertex, // Add an extra factor to the weight to take into account the // probability. tempDist := getProbabilityBasedDist( - tempWeight, probability, int64(r.PaymentAttemptPenalty), + tempWeight, probability, + int64(cfg.PaymentAttemptPenalty), ) // If the current best route is better than this candidate diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index 88adade42..3e8f521d4 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -55,6 +55,8 @@ var ( FeeLimit: noFeeLimit, ProbabilitySource: noProbabilitySource, } + + testPathFindingConfig = &PathFindingConfig{} ) var ( @@ -650,6 +652,7 @@ func TestFindLowestFeePath(t *testing.T) { graph: testGraphInstance.graph, }, noRestrictions, + testPathFindingConfig, sourceNode.PubKeyBytes, target, paymentAmt, ) if err != nil { @@ -791,6 +794,7 @@ func testBasicGraphPathFindingCase(t *testing.T, graphInstance *testGraphInstanc FeeLimit: test.feeLimit, ProbabilitySource: noProbabilitySource, }, + testPathFindingConfig, sourceNode.PubKeyBytes, target, paymentAmt, ) if test.expectFailureNoPath { @@ -957,7 +961,7 @@ func TestPathFindingWithAdditionalEdges(t *testing.T) { graph: graph.graph, additionalEdges: additionalEdges, }, - noRestrictions, + noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, doge.PubKeyBytes, paymentAmt, ) if err != nil { @@ -1211,7 +1215,7 @@ func TestNewRoutePathTooLong(t *testing.T) { &graphParams{ graph: graph.graph, }, - noRestrictions, + noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, paymentAmt, ) if err != nil { @@ -1225,7 +1229,7 @@ func TestNewRoutePathTooLong(t *testing.T) { &graphParams{ graph: graph.graph, }, - noRestrictions, + noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, paymentAmt, ) if err == nil { @@ -1265,7 +1269,7 @@ func TestPathNotAvailable(t *testing.T) { &graphParams{ graph: graph.graph, }, - noRestrictions, + noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, unknownNode, 100, ) if !IsError(err, ErrNoPathFound) { @@ -1302,7 +1306,7 @@ func TestPathInsufficientCapacity(t *testing.T) { &graphParams{ graph: graph.graph, }, - noRestrictions, + noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, ) if !IsError(err, ErrNoPathFound) { @@ -1335,7 +1339,7 @@ func TestRouteFailMinHTLC(t *testing.T) { &graphParams{ graph: graph.graph, }, - noRestrictions, + noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, ) if !IsError(err, ErrNoPathFound) { @@ -1393,7 +1397,7 @@ func TestRouteFailMaxHTLC(t *testing.T) { &graphParams{ graph: graph.graph, }, - noRestrictions, + noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, ) if err != nil { @@ -1415,7 +1419,7 @@ func TestRouteFailMaxHTLC(t *testing.T) { &graphParams{ graph: graph.graph, }, - noRestrictions, + noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, ) if !IsError(err, ErrNoPathFound) { @@ -1450,7 +1454,7 @@ func TestRouteFailDisabledEdge(t *testing.T) { &graphParams{ graph: graph.graph, }, - noRestrictions, + noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, ) if err != nil { @@ -1478,7 +1482,7 @@ func TestRouteFailDisabledEdge(t *testing.T) { &graphParams{ graph: graph.graph, }, - noRestrictions, + noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, ) if err != nil { @@ -1503,7 +1507,7 @@ func TestRouteFailDisabledEdge(t *testing.T) { &graphParams{ graph: graph.graph, }, - noRestrictions, + noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, ) if !IsError(err, ErrNoPathFound) { @@ -1537,7 +1541,7 @@ func TestPathSourceEdgesBandwidth(t *testing.T) { &graphParams{ graph: graph.graph, }, - noRestrictions, + noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, ) if err != nil { @@ -1561,7 +1565,7 @@ func TestPathSourceEdgesBandwidth(t *testing.T) { graph: graph.graph, bandwidthHints: bandwidths, }, - noRestrictions, + noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, ) if !IsError(err, ErrNoPathFound) { @@ -1579,7 +1583,7 @@ func TestPathSourceEdgesBandwidth(t *testing.T) { graph: graph.graph, bandwidthHints: bandwidths, }, - noRestrictions, + noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, ) if err != nil { @@ -1610,7 +1614,7 @@ func TestPathSourceEdgesBandwidth(t *testing.T) { graph: graph.graph, bandwidthHints: bandwidths, }, - noRestrictions, + noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, ) if err != nil { @@ -1903,6 +1907,7 @@ func TestRestrictOutgoingChannel(t *testing.T) { OutgoingChannelID: &outgoingChannelID, ProbabilitySource: noProbabilitySource, }, + testPathFindingConfig, sourceVertex, target, paymentAmt, ) if err != nil { @@ -1998,6 +2003,7 @@ func testCltvLimit(t *testing.T, limit uint32, expectedChannel uint64) { CltvLimit: cltvLimit, ProbabilitySource: noProbabilitySource, }, + testPathFindingConfig, sourceVertex, target, paymentAmt, ) if expectedChannel == 0 { @@ -2174,8 +2180,10 @@ func testProbabilityRouting(t *testing.T, p10, p11, p20, minProbability float64, graph: testGraphInstance.graph, }, &RestrictParams{ - FeeLimit: noFeeLimit, - ProbabilitySource: probabilitySource, + FeeLimit: noFeeLimit, + ProbabilitySource: probabilitySource, + }, + &PathFindingConfig{ PaymentAttemptPenalty: lnwire.NewMSatFromSatoshis(10), MinProbability: minProbability, }, diff --git a/routing/payment_session.go b/routing/payment_session.go index 44abeae9f..117523e91 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -83,12 +83,10 @@ func (p *paymentSession) RequestRoute(payment *LightningPayment, ss := p.sessionSource restrictions := &RestrictParams{ - ProbabilitySource: ss.MissionControl.GetEdgeProbability, - FeeLimit: payment.FeeLimit, - OutgoingChannelID: payment.OutgoingChannelID, - CltvLimit: cltvLimit, - PaymentAttemptPenalty: ss.PaymentAttemptPenalty, - MinProbability: ss.MinRouteProbability, + ProbabilitySource: ss.MissionControl.GetEdgeProbability, + FeeLimit: payment.FeeLimit, + OutgoingChannelID: payment.OutgoingChannelID, + CltvLimit: cltvLimit, } path, err := p.pathFinder( @@ -97,7 +95,8 @@ func (p *paymentSession) RequestRoute(payment *LightningPayment, additionalEdges: p.additionalEdges, bandwidthHints: p.bandwidthHints, }, - restrictions, ss.SelfNode.PubKeyBytes, payment.Target, + restrictions, &ss.PathFindingConfig, + ss.SelfNode.PubKeyBytes, payment.Target, payment.Amount, ) if err != nil { diff --git a/routing/payment_session_source.go b/routing/payment_session_source.go index 77dad51e8..1b8fea5fa 100644 --- a/routing/payment_session_source.go +++ b/routing/payment_session_source.go @@ -38,15 +38,9 @@ type SessionSource struct { // execution. MissionControl MissionController - // PaymentAttemptPenalty is the virtual cost in path finding weight - // units of executing a payment attempt that fails. It is used to trade - // off potentially better routes against their probability of - // succeeding. - PaymentAttemptPenalty lnwire.MilliSatoshi - - // MinProbability defines the minimum success probability of the - // returned route. - MinRouteProbability float64 + // PathFindingConfig defines global parameters that control the + // trade-off in path finding between fees and probabiity. + PathFindingConfig PathFindingConfig } // NewPaymentSession creates a new payment session backed by the latest prune diff --git a/routing/payment_session_test.go b/routing/payment_session_test.go index 33070fbde..200f98ab5 100644 --- a/routing/payment_session_test.go +++ b/routing/payment_session_test.go @@ -14,8 +14,9 @@ func TestRequestRoute(t *testing.T) { ) findPath := func(g *graphParams, r *RestrictParams, - source, target route.Vertex, amt lnwire.MilliSatoshi) ( - []*channeldb.ChannelEdgePolicy, error) { + cfg *PathFindingConfig, source, target route.Vertex, + amt lnwire.MilliSatoshi) ([]*channeldb.ChannelEdgePolicy, + error) { // We expect find path to receive a cltv limit excluding the // final cltv delta. diff --git a/routing/router.go b/routing/router.go index 4df236d55..237216b36 100644 --- a/routing/router.go +++ b/routing/router.go @@ -287,6 +287,9 @@ type Config struct { // spentness of channel outpoints. For neutrino, this saves long rescans // from blocking initial usage of the daemon. AssumeChannelValid bool + + // PathFindingConfig defines global path finding parameters. + PathFindingConfig PathFindingConfig } // routeTuple is an entry within the ChannelRouter's route cache. We cache @@ -1455,7 +1458,8 @@ func (r *ChannelRouter) FindRoute(source, target route.Vertex, graph: r.cfg.Graph, bandwidthHints: bandwidthHints, }, - restrictions, source, target, amt, + restrictions, &r.cfg.PathFindingConfig, + source, target, amt, ) if err != nil { return nil, err diff --git a/routing/router_test.go b/routing/router_test.go index bc71cfc94..b3df7fafd 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -90,11 +90,18 @@ func createTestCtxFromGraphInstance(startingHeight uint32, graphInstance *testGr return nil, nil, err } + pathFindingConfig := &PathFindingConfig{ + MinProbability: 0.01, + PaymentAttemptPenalty: 100, + } + + mcConfig := &MissionControlConfig{ + PenaltyHalfLife: time.Hour, + AprioriHopProbability: 0.9, + } + mc := NewMissionControl( - &MissionControlConfig{ - PenaltyHalfLife: time.Hour, - AprioriHopProbability: 0.9, - }, + mcConfig, ) sessionSource := &SessionSource{ @@ -103,9 +110,11 @@ func createTestCtxFromGraphInstance(startingHeight uint32, graphInstance *testGr QueryBandwidth: func(e *channeldb.ChannelEdgeInfo) lnwire.MilliSatoshi { return lnwire.NewMSatFromSatoshis(e.Capacity) }, - MinRouteProbability: 0.01, - PaymentAttemptPenalty: 100, - MissionControl: mc, + PathFindingConfig: PathFindingConfig{ + MinProbability: 0.01, + PaymentAttemptPenalty: 100, + }, + MissionControl: mc, } router, err := New(Config{ @@ -125,6 +134,7 @@ func createTestCtxFromGraphInstance(startingHeight uint32, graphInstance *testGr next := atomic.AddUint64(&uniquePaymentID, 1) return next, nil }, + PathFindingConfig: *pathFindingConfig, }) if err != nil { return nil, nil, fmt.Errorf("unable to create router %v", err) @@ -2163,6 +2173,7 @@ func TestFindPathFeeWeighting(t *testing.T) { graph: ctx.graph, }, noRestrictions, + testPathFindingConfig, sourceNode.PubKeyBytes, target, amt, ) if err != nil { diff --git a/server.go b/server.go index 64b376663..f2572ab97 100644 --- a/server.go +++ b/server.go @@ -666,13 +666,17 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, int64(routingConfig.PaymentAttemptPenalty.ToSatoshis()), routingConfig.MinRouteProbability) - paymentSessionSource := &routing.SessionSource{ - Graph: chanGraph, - MissionControl: s.missionControl, - QueryBandwidth: queryBandwidth, - SelfNode: selfNode, + pathFindingConfig := routing.PathFindingConfig{ PaymentAttemptPenalty: routingConfig.PaymentAttemptPenalty, - MinRouteProbability: routingConfig.MinRouteProbability, + MinProbability: routingConfig.MinRouteProbability, + } + + paymentSessionSource := &routing.SessionSource{ + Graph: chanGraph, + MissionControl: s.missionControl, + QueryBandwidth: queryBandwidth, + SelfNode: selfNode, + PathFindingConfig: pathFindingConfig, } paymentControl := channeldb.NewPaymentControl(chanDB) @@ -692,6 +696,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, QueryBandwidth: queryBandwidth, AssumeChannelValid: cfg.Routing.UseAssumeChannelValid(), NextPaymentID: sequencer.NextID, + PathFindingConfig: pathFindingConfig, }) if err != nil { return nil, fmt.Errorf("can't create router: %v", err)