routing: create PathFindingConfig for global parameters

This commit is contained in:
Joost Jager 2019-06-20 12:03:45 +02:00
parent 377b7bf3ce
commit 34b264a3d8
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
9 changed files with 83 additions and 56 deletions

@ -153,7 +153,6 @@ func (r *RouterBackend) QueryRoutes(ctx context.Context,
return 1 return 1
}, },
PaymentAttemptPenalty: routing.DefaultPaymentAttemptPenalty,
} }
// Query the channel router for a possible path to the destination that // Query the channel router for a possible path to the destination that

@ -37,8 +37,8 @@ const (
// pathFinder defines the interface of a path finding algorithm. // pathFinder defines the interface of a path finding algorithm.
type pathFinder = func(g *graphParams, r *RestrictParams, type pathFinder = func(g *graphParams, r *RestrictParams,
source, target route.Vertex, amt lnwire.MilliSatoshi) ( cfg *PathFindingConfig, source, target route.Vertex,
[]*channeldb.ChannelEdgePolicy, error) amt lnwire.MilliSatoshi) ([]*channeldb.ChannelEdgePolicy, error)
var ( var (
// DefaultPaymentAttemptPenalty is the virtual cost in path finding weight // 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 // ctlv. After path finding is complete, the caller needs to increase
// all cltv expiry heights with the required final cltv delta. // all cltv expiry heights with the required final cltv delta.
CltvLimit *uint32 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 // PaymentAttemptPenalty is the virtual cost in path finding weight
// units of executing a payment attempt that fails. It is used to trade // units of executing a payment attempt that fails. It is used to trade
// off potentially better routes against their probability of // 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 // destination node back to source. This is to properly accumulate fees
// that need to be paid along the path and accurately check the amount // that need to be paid along the path and accurately check the amount
// to forward at every node against the available bandwidth. // to forward at every node against the available bandwidth.
func findPath(g *graphParams, r *RestrictParams, source, target route.Vertex, func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig,
amt lnwire.MilliSatoshi) ([]*channeldb.ChannelEdgePolicy, error) { source, target route.Vertex, amt lnwire.MilliSatoshi) (
[]*channeldb.ChannelEdgePolicy, error) {
var err error var err error
tx := g.tx 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 // If the probability is below the specified lower bound, we can
// abandon this direction. Adding further nodes can only lower // abandon this direction. Adding further nodes can only lower
// the probability more. // the probability more.
if probability < r.MinProbability { if probability < cfg.MinProbability {
return 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 // Add an extra factor to the weight to take into account the
// probability. // probability.
tempDist := getProbabilityBasedDist( tempDist := getProbabilityBasedDist(
tempWeight, probability, int64(r.PaymentAttemptPenalty), tempWeight, probability,
int64(cfg.PaymentAttemptPenalty),
) )
// If the current best route is better than this candidate // If the current best route is better than this candidate

@ -55,6 +55,8 @@ var (
FeeLimit: noFeeLimit, FeeLimit: noFeeLimit,
ProbabilitySource: noProbabilitySource, ProbabilitySource: noProbabilitySource,
} }
testPathFindingConfig = &PathFindingConfig{}
) )
var ( var (
@ -650,6 +652,7 @@ func TestFindLowestFeePath(t *testing.T) {
graph: testGraphInstance.graph, graph: testGraphInstance.graph,
}, },
noRestrictions, noRestrictions,
testPathFindingConfig,
sourceNode.PubKeyBytes, target, paymentAmt, sourceNode.PubKeyBytes, target, paymentAmt,
) )
if err != nil { if err != nil {
@ -791,6 +794,7 @@ func testBasicGraphPathFindingCase(t *testing.T, graphInstance *testGraphInstanc
FeeLimit: test.feeLimit, FeeLimit: test.feeLimit,
ProbabilitySource: noProbabilitySource, ProbabilitySource: noProbabilitySource,
}, },
testPathFindingConfig,
sourceNode.PubKeyBytes, target, paymentAmt, sourceNode.PubKeyBytes, target, paymentAmt,
) )
if test.expectFailureNoPath { if test.expectFailureNoPath {
@ -957,7 +961,7 @@ func TestPathFindingWithAdditionalEdges(t *testing.T) {
graph: graph.graph, graph: graph.graph,
additionalEdges: additionalEdges, additionalEdges: additionalEdges,
}, },
noRestrictions, noRestrictions, testPathFindingConfig,
sourceNode.PubKeyBytes, doge.PubKeyBytes, paymentAmt, sourceNode.PubKeyBytes, doge.PubKeyBytes, paymentAmt,
) )
if err != nil { if err != nil {
@ -1211,7 +1215,7 @@ func TestNewRoutePathTooLong(t *testing.T) {
&graphParams{ &graphParams{
graph: graph.graph, graph: graph.graph,
}, },
noRestrictions, noRestrictions, testPathFindingConfig,
sourceNode.PubKeyBytes, target, paymentAmt, sourceNode.PubKeyBytes, target, paymentAmt,
) )
if err != nil { if err != nil {
@ -1225,7 +1229,7 @@ func TestNewRoutePathTooLong(t *testing.T) {
&graphParams{ &graphParams{
graph: graph.graph, graph: graph.graph,
}, },
noRestrictions, noRestrictions, testPathFindingConfig,
sourceNode.PubKeyBytes, target, paymentAmt, sourceNode.PubKeyBytes, target, paymentAmt,
) )
if err == nil { if err == nil {
@ -1265,7 +1269,7 @@ func TestPathNotAvailable(t *testing.T) {
&graphParams{ &graphParams{
graph: graph.graph, graph: graph.graph,
}, },
noRestrictions, noRestrictions, testPathFindingConfig,
sourceNode.PubKeyBytes, unknownNode, 100, sourceNode.PubKeyBytes, unknownNode, 100,
) )
if !IsError(err, ErrNoPathFound) { if !IsError(err, ErrNoPathFound) {
@ -1302,7 +1306,7 @@ func TestPathInsufficientCapacity(t *testing.T) {
&graphParams{ &graphParams{
graph: graph.graph, graph: graph.graph,
}, },
noRestrictions, noRestrictions, testPathFindingConfig,
sourceNode.PubKeyBytes, target, payAmt, sourceNode.PubKeyBytes, target, payAmt,
) )
if !IsError(err, ErrNoPathFound) { if !IsError(err, ErrNoPathFound) {
@ -1335,7 +1339,7 @@ func TestRouteFailMinHTLC(t *testing.T) {
&graphParams{ &graphParams{
graph: graph.graph, graph: graph.graph,
}, },
noRestrictions, noRestrictions, testPathFindingConfig,
sourceNode.PubKeyBytes, target, payAmt, sourceNode.PubKeyBytes, target, payAmt,
) )
if !IsError(err, ErrNoPathFound) { if !IsError(err, ErrNoPathFound) {
@ -1393,7 +1397,7 @@ func TestRouteFailMaxHTLC(t *testing.T) {
&graphParams{ &graphParams{
graph: graph.graph, graph: graph.graph,
}, },
noRestrictions, noRestrictions, testPathFindingConfig,
sourceNode.PubKeyBytes, target, payAmt, sourceNode.PubKeyBytes, target, payAmt,
) )
if err != nil { if err != nil {
@ -1415,7 +1419,7 @@ func TestRouteFailMaxHTLC(t *testing.T) {
&graphParams{ &graphParams{
graph: graph.graph, graph: graph.graph,
}, },
noRestrictions, noRestrictions, testPathFindingConfig,
sourceNode.PubKeyBytes, target, payAmt, sourceNode.PubKeyBytes, target, payAmt,
) )
if !IsError(err, ErrNoPathFound) { if !IsError(err, ErrNoPathFound) {
@ -1450,7 +1454,7 @@ func TestRouteFailDisabledEdge(t *testing.T) {
&graphParams{ &graphParams{
graph: graph.graph, graph: graph.graph,
}, },
noRestrictions, noRestrictions, testPathFindingConfig,
sourceNode.PubKeyBytes, target, payAmt, sourceNode.PubKeyBytes, target, payAmt,
) )
if err != nil { if err != nil {
@ -1478,7 +1482,7 @@ func TestRouteFailDisabledEdge(t *testing.T) {
&graphParams{ &graphParams{
graph: graph.graph, graph: graph.graph,
}, },
noRestrictions, noRestrictions, testPathFindingConfig,
sourceNode.PubKeyBytes, target, payAmt, sourceNode.PubKeyBytes, target, payAmt,
) )
if err != nil { if err != nil {
@ -1503,7 +1507,7 @@ func TestRouteFailDisabledEdge(t *testing.T) {
&graphParams{ &graphParams{
graph: graph.graph, graph: graph.graph,
}, },
noRestrictions, noRestrictions, testPathFindingConfig,
sourceNode.PubKeyBytes, target, payAmt, sourceNode.PubKeyBytes, target, payAmt,
) )
if !IsError(err, ErrNoPathFound) { if !IsError(err, ErrNoPathFound) {
@ -1537,7 +1541,7 @@ func TestPathSourceEdgesBandwidth(t *testing.T) {
&graphParams{ &graphParams{
graph: graph.graph, graph: graph.graph,
}, },
noRestrictions, noRestrictions, testPathFindingConfig,
sourceNode.PubKeyBytes, target, payAmt, sourceNode.PubKeyBytes, target, payAmt,
) )
if err != nil { if err != nil {
@ -1561,7 +1565,7 @@ func TestPathSourceEdgesBandwidth(t *testing.T) {
graph: graph.graph, graph: graph.graph,
bandwidthHints: bandwidths, bandwidthHints: bandwidths,
}, },
noRestrictions, noRestrictions, testPathFindingConfig,
sourceNode.PubKeyBytes, target, payAmt, sourceNode.PubKeyBytes, target, payAmt,
) )
if !IsError(err, ErrNoPathFound) { if !IsError(err, ErrNoPathFound) {
@ -1579,7 +1583,7 @@ func TestPathSourceEdgesBandwidth(t *testing.T) {
graph: graph.graph, graph: graph.graph,
bandwidthHints: bandwidths, bandwidthHints: bandwidths,
}, },
noRestrictions, noRestrictions, testPathFindingConfig,
sourceNode.PubKeyBytes, target, payAmt, sourceNode.PubKeyBytes, target, payAmt,
) )
if err != nil { if err != nil {
@ -1610,7 +1614,7 @@ func TestPathSourceEdgesBandwidth(t *testing.T) {
graph: graph.graph, graph: graph.graph,
bandwidthHints: bandwidths, bandwidthHints: bandwidths,
}, },
noRestrictions, noRestrictions, testPathFindingConfig,
sourceNode.PubKeyBytes, target, payAmt, sourceNode.PubKeyBytes, target, payAmt,
) )
if err != nil { if err != nil {
@ -1903,6 +1907,7 @@ func TestRestrictOutgoingChannel(t *testing.T) {
OutgoingChannelID: &outgoingChannelID, OutgoingChannelID: &outgoingChannelID,
ProbabilitySource: noProbabilitySource, ProbabilitySource: noProbabilitySource,
}, },
testPathFindingConfig,
sourceVertex, target, paymentAmt, sourceVertex, target, paymentAmt,
) )
if err != nil { if err != nil {
@ -1998,6 +2003,7 @@ func testCltvLimit(t *testing.T, limit uint32, expectedChannel uint64) {
CltvLimit: cltvLimit, CltvLimit: cltvLimit,
ProbabilitySource: noProbabilitySource, ProbabilitySource: noProbabilitySource,
}, },
testPathFindingConfig,
sourceVertex, target, paymentAmt, sourceVertex, target, paymentAmt,
) )
if expectedChannel == 0 { if expectedChannel == 0 {
@ -2174,8 +2180,10 @@ func testProbabilityRouting(t *testing.T, p10, p11, p20, minProbability float64,
graph: testGraphInstance.graph, graph: testGraphInstance.graph,
}, },
&RestrictParams{ &RestrictParams{
FeeLimit: noFeeLimit, FeeLimit: noFeeLimit,
ProbabilitySource: probabilitySource, ProbabilitySource: probabilitySource,
},
&PathFindingConfig{
PaymentAttemptPenalty: lnwire.NewMSatFromSatoshis(10), PaymentAttemptPenalty: lnwire.NewMSatFromSatoshis(10),
MinProbability: minProbability, MinProbability: minProbability,
}, },

@ -83,12 +83,10 @@ func (p *paymentSession) RequestRoute(payment *LightningPayment,
ss := p.sessionSource ss := p.sessionSource
restrictions := &RestrictParams{ restrictions := &RestrictParams{
ProbabilitySource: ss.MissionControl.GetEdgeProbability, ProbabilitySource: ss.MissionControl.GetEdgeProbability,
FeeLimit: payment.FeeLimit, FeeLimit: payment.FeeLimit,
OutgoingChannelID: payment.OutgoingChannelID, OutgoingChannelID: payment.OutgoingChannelID,
CltvLimit: cltvLimit, CltvLimit: cltvLimit,
PaymentAttemptPenalty: ss.PaymentAttemptPenalty,
MinProbability: ss.MinRouteProbability,
} }
path, err := p.pathFinder( path, err := p.pathFinder(
@ -97,7 +95,8 @@ func (p *paymentSession) RequestRoute(payment *LightningPayment,
additionalEdges: p.additionalEdges, additionalEdges: p.additionalEdges,
bandwidthHints: p.bandwidthHints, bandwidthHints: p.bandwidthHints,
}, },
restrictions, ss.SelfNode.PubKeyBytes, payment.Target, restrictions, &ss.PathFindingConfig,
ss.SelfNode.PubKeyBytes, payment.Target,
payment.Amount, payment.Amount,
) )
if err != nil { if err != nil {

@ -38,15 +38,9 @@ type SessionSource struct {
// execution. // execution.
MissionControl MissionController MissionControl MissionController
// PaymentAttemptPenalty is the virtual cost in path finding weight // PathFindingConfig defines global parameters that control the
// units of executing a payment attempt that fails. It is used to trade // trade-off in path finding between fees and probabiity.
// off potentially better routes against their probability of PathFindingConfig PathFindingConfig
// succeeding.
PaymentAttemptPenalty lnwire.MilliSatoshi
// MinProbability defines the minimum success probability of the
// returned route.
MinRouteProbability float64
} }
// NewPaymentSession creates a new payment session backed by the latest prune // NewPaymentSession creates a new payment session backed by the latest prune

@ -14,8 +14,9 @@ func TestRequestRoute(t *testing.T) {
) )
findPath := func(g *graphParams, r *RestrictParams, findPath := func(g *graphParams, r *RestrictParams,
source, target route.Vertex, amt lnwire.MilliSatoshi) ( cfg *PathFindingConfig, source, target route.Vertex,
[]*channeldb.ChannelEdgePolicy, error) { amt lnwire.MilliSatoshi) ([]*channeldb.ChannelEdgePolicy,
error) {
// We expect find path to receive a cltv limit excluding the // We expect find path to receive a cltv limit excluding the
// final cltv delta. // final cltv delta.

@ -287,6 +287,9 @@ type Config struct {
// spentness of channel outpoints. For neutrino, this saves long rescans // spentness of channel outpoints. For neutrino, this saves long rescans
// from blocking initial usage of the daemon. // from blocking initial usage of the daemon.
AssumeChannelValid bool AssumeChannelValid bool
// PathFindingConfig defines global path finding parameters.
PathFindingConfig PathFindingConfig
} }
// routeTuple is an entry within the ChannelRouter's route cache. We cache // 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, graph: r.cfg.Graph,
bandwidthHints: bandwidthHints, bandwidthHints: bandwidthHints,
}, },
restrictions, source, target, amt, restrictions, &r.cfg.PathFindingConfig,
source, target, amt,
) )
if err != nil { if err != nil {
return nil, err return nil, err

@ -90,11 +90,18 @@ func createTestCtxFromGraphInstance(startingHeight uint32, graphInstance *testGr
return nil, nil, err return nil, nil, err
} }
pathFindingConfig := &PathFindingConfig{
MinProbability: 0.01,
PaymentAttemptPenalty: 100,
}
mcConfig := &MissionControlConfig{
PenaltyHalfLife: time.Hour,
AprioriHopProbability: 0.9,
}
mc := NewMissionControl( mc := NewMissionControl(
&MissionControlConfig{ mcConfig,
PenaltyHalfLife: time.Hour,
AprioriHopProbability: 0.9,
},
) )
sessionSource := &SessionSource{ sessionSource := &SessionSource{
@ -103,9 +110,11 @@ func createTestCtxFromGraphInstance(startingHeight uint32, graphInstance *testGr
QueryBandwidth: func(e *channeldb.ChannelEdgeInfo) lnwire.MilliSatoshi { QueryBandwidth: func(e *channeldb.ChannelEdgeInfo) lnwire.MilliSatoshi {
return lnwire.NewMSatFromSatoshis(e.Capacity) return lnwire.NewMSatFromSatoshis(e.Capacity)
}, },
MinRouteProbability: 0.01, PathFindingConfig: PathFindingConfig{
PaymentAttemptPenalty: 100, MinProbability: 0.01,
MissionControl: mc, PaymentAttemptPenalty: 100,
},
MissionControl: mc,
} }
router, err := New(Config{ router, err := New(Config{
@ -125,6 +134,7 @@ func createTestCtxFromGraphInstance(startingHeight uint32, graphInstance *testGr
next := atomic.AddUint64(&uniquePaymentID, 1) next := atomic.AddUint64(&uniquePaymentID, 1)
return next, nil return next, nil
}, },
PathFindingConfig: *pathFindingConfig,
}) })
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("unable to create router %v", err) return nil, nil, fmt.Errorf("unable to create router %v", err)
@ -2163,6 +2173,7 @@ func TestFindPathFeeWeighting(t *testing.T) {
graph: ctx.graph, graph: ctx.graph,
}, },
noRestrictions, noRestrictions,
testPathFindingConfig,
sourceNode.PubKeyBytes, target, amt, sourceNode.PubKeyBytes, target, amt,
) )
if err != nil { if err != nil {

@ -666,13 +666,17 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB,
int64(routingConfig.PaymentAttemptPenalty.ToSatoshis()), int64(routingConfig.PaymentAttemptPenalty.ToSatoshis()),
routingConfig.MinRouteProbability) routingConfig.MinRouteProbability)
paymentSessionSource := &routing.SessionSource{ pathFindingConfig := routing.PathFindingConfig{
Graph: chanGraph,
MissionControl: s.missionControl,
QueryBandwidth: queryBandwidth,
SelfNode: selfNode,
PaymentAttemptPenalty: routingConfig.PaymentAttemptPenalty, 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) paymentControl := channeldb.NewPaymentControl(chanDB)
@ -692,6 +696,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB,
QueryBandwidth: queryBandwidth, QueryBandwidth: queryBandwidth,
AssumeChannelValid: cfg.Routing.UseAssumeChannelValid(), AssumeChannelValid: cfg.Routing.UseAssumeChannelValid(),
NextPaymentID: sequencer.NextID, NextPaymentID: sequencer.NextID,
PathFindingConfig: pathFindingConfig,
}) })
if err != nil { if err != nil {
return nil, fmt.Errorf("can't create router: %v", err) return nil, fmt.Errorf("can't create router: %v", err)