diff --git a/lnrpc/routerrpc/config.go b/lnrpc/routerrpc/config.go index ec036258f..9877556db 100644 --- a/lnrpc/routerrpc/config.go +++ b/lnrpc/routerrpc/config.go @@ -42,14 +42,23 @@ type Config struct { // DefaultConfig defines the config defaults. func DefaultConfig() *Config { defaultRoutingConfig := RoutingConfig{ - AprioriHopProbability: routing.DefaultAprioriHopProbability, - AprioriWeight: routing.DefaultAprioriWeight, - MinRouteProbability: routing.DefaultMinRouteProbability, - PenaltyHalfLife: routing.DefaultPenaltyHalfLife, - AttemptCost: routing.DefaultAttemptCost.ToSatoshis(), - AttemptCostPPM: routing.DefaultAttemptCostPPM, - MaxMcHistory: routing.DefaultMaxMcHistory, - McFlushInterval: routing.DefaultMcFlushInterval, + ProbabilityEstimatorType: routing.DefaultEstimator, + MinRouteProbability: routing.DefaultMinRouteProbability, + + AttemptCost: routing.DefaultAttemptCost.ToSatoshis(), + AttemptCostPPM: routing.DefaultAttemptCostPPM, + MaxMcHistory: routing.DefaultMaxMcHistory, + McFlushInterval: routing.DefaultMcFlushInterval, + AprioriConfig: &AprioriConfig{ + HopProbability: routing.DefaultAprioriHopProbability, + Weight: routing.DefaultAprioriWeight, + PenaltyHalfLife: routing.DefaultPenaltyHalfLife, + }, + BimodalConfig: &BimodalConfig{ + Scale: int64(routing.DefaultBimodalScaleMsat), + NodeWeight: routing.DefaultBimodalNodeWeight, + DecayTime: routing.DefaultBimodalDecayTime, + }, } return &Config{ @@ -60,13 +69,21 @@ func DefaultConfig() *Config { // GetRoutingConfig returns the routing config based on this sub server config. func GetRoutingConfig(cfg *Config) *RoutingConfig { return &RoutingConfig{ - AprioriHopProbability: cfg.AprioriHopProbability, - AprioriWeight: cfg.AprioriWeight, - MinRouteProbability: cfg.MinRouteProbability, - AttemptCost: cfg.AttemptCost, - AttemptCostPPM: cfg.AttemptCostPPM, - PenaltyHalfLife: cfg.PenaltyHalfLife, - MaxMcHistory: cfg.MaxMcHistory, - McFlushInterval: cfg.McFlushInterval, + ProbabilityEstimatorType: cfg.ProbabilityEstimatorType, + MinRouteProbability: cfg.MinRouteProbability, + AttemptCost: cfg.AttemptCost, + AttemptCostPPM: cfg.AttemptCostPPM, + MaxMcHistory: cfg.MaxMcHistory, + McFlushInterval: cfg.McFlushInterval, + AprioriConfig: &AprioriConfig{ + HopProbability: cfg.AprioriConfig.HopProbability, + Weight: cfg.AprioriConfig.Weight, + PenaltyHalfLife: cfg.AprioriConfig.PenaltyHalfLife, + }, + BimodalConfig: &BimodalConfig{ + Scale: cfg.BimodalConfig.Scale, + NodeWeight: cfg.BimodalConfig.NodeWeight, + DecayTime: cfg.BimodalConfig.DecayTime, + }, } } diff --git a/lnrpc/routerrpc/routing_config.go b/lnrpc/routerrpc/routing_config.go index 2a53ba2e4..a1bbad590 100644 --- a/lnrpc/routerrpc/routing_config.go +++ b/lnrpc/routerrpc/routing_config.go @@ -7,28 +7,16 @@ import ( ) // RoutingConfig contains the configurable parameters that control routing. +// +//nolint:lll type RoutingConfig struct { + // ProbabilityEstimatorType sets the estimator to use. + ProbabilityEstimatorType string `long:"estimator" choice:"apriori" choice:"bimodal" description:"Probability estimator used for pathfinding." ` + // MinRouteProbability is the minimum required route success probability // to attempt the payment. MinRouteProbability float64 `long:"minrtprob" description:"Minimum required route success probability to attempt the payment"` - // AprioriHopProbability is the assumed success probability of a hop in - // a route when no other information is available. - AprioriHopProbability float64 `long:"apriorihopprob" description:"Assumed success probability of a hop in a route when no other information is available."` - - // AprioriWeight is a value in the range [0, 1] that defines to what - // extent historical results should be extrapolated to untried - // connections. Setting it to one will completely ignore historical - // results and always assume the configured a priori probability for - // untried connections. A value of zero will ignore the a priori - // probability completely and only base the probability on historical - // results, unless there are none available. - AprioriWeight float64 `long:"aprioriweight" description:"Weight of the a priori probability in success probability estimation. Valid values are in [0, 1]."` - - // PenaltyHalfLife defines after how much time a penalized node or - // channel is back at 50% probability. - PenaltyHalfLife time.Duration `long:"penaltyhalflife" description:"Defines the duration after which a penalized node or channel is back at 50% probability"` - // AttemptCost is the fixed virtual cost in path finding of a failed // payment attempt. It is used to trade off potentially better routes // against their probability of succeeding. @@ -47,4 +35,51 @@ type RoutingConfig struct { // McFlushInterval defines the timer interval to use to flush mission // control state to the DB. McFlushInterval time.Duration `long:"mcflushinterval" description:"the timer interval to use to flush mission control state to the DB"` + + // AprioriConfig defines parameters for the apriori probability. + AprioriConfig *AprioriConfig `group:"apriori" namespace:"apriori" description:"configuration for the apriori pathfinding probability estimator"` + + // BimodalConfig defines parameters for the bimodal probability. + BimodalConfig *BimodalConfig `group:"bimodal" namespace:"bimodal" description:"configuration for the bimodal pathfinding probability estimator"` +} + +// AprioriConfig defines parameters for the apriori probability. +// +//nolint:lll +type AprioriConfig struct { + // HopProbability is the assumed success probability of a hop in a route + // when no other information is available. + HopProbability float64 `long:"hopprob" description:"Assumed success probability of a hop in a route when no other information is available."` + + // Weight is a value in the range [0, 1] that defines to what extent + // historical results should be extrapolated to untried connections. + // Setting it to one will completely ignore historical results and + // always assume the configured a priori probability for untried + // connections. A value of zero will ignore the a priori probability + // completely and only base the probability on historical results, + // unless there are none available. + Weight float64 `long:"weight" description:"Weight of the a priori probability in success probability estimation. Valid values are in [0, 1]."` + + // PenaltyHalfLife defines after how much time a penalized node or + // channel is back at 50% probability. + PenaltyHalfLife time.Duration `long:"penaltyhalflife" description:"Defines the duration after which a penalized node or channel is back at 50% probability"` +} + +// BimodalConfig defines parameters for the bimodal probability. +// +//nolint:lll +type BimodalConfig struct { + // Scale describes the scale over which channels still have some + // liquidity left on both channel ends. A value of 0 means that we + // assume perfectly unbalanced channels, a very high value means + // randomly balanced channels. + Scale int64 `long:"scale" description:"Defines the unbalancedness assumed for the network, the amount defined in msat."` + + // NodeWeight defines how strongly non-routed channels should be taken + // into account for probability estimation. Valid values are in [0,1]. + NodeWeight float64 `long:"nodeweight" description:"Defines how strongly non-routed channels should be taken into account for probability estimation. Valid values are in [0, 1]."` + + // DecayTime is the scale for the exponential information decay over + // time for previous successes or failures. + DecayTime time.Duration `long:"decaytime" description:"Describes the information decay of knowledge about previous successes and failures in channels."` } diff --git a/routing/pathfind.go b/routing/pathfind.go index bffc46336..f204591b6 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -46,6 +46,10 @@ type pathFinder = func(g *graphParams, r *RestrictParams, []*channeldb.CachedEdgePolicy, float64, error) var ( + // DefaultEstimator is the default estimator used for computing + // probabilities in pathfinding. + DefaultEstimator = AprioriEstimatorName + // DefaultAttemptCost is the default fixed virtual cost in path finding // of a failed payment attempt. It is used to trade off potentially // better routes against their probability of succeeding. diff --git a/sample-lnd.conf b/sample-lnd.conf index 72b78c489..b8aadd874 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -1105,21 +1105,23 @@ litecoin.node=ltcd [routerrpc] +; Probability estimator used for pathfinding. (default: apriori) +; routerrpc.estimator=[apriori|bimodal] + ; Minimum required route success probability to attempt the payment (default: ; 0.01) ; routerrpc.minrtprob=1 -; Assumed success probability of a hop in a route when no other information is -; available. (default: 0.6) -; routerrpc.apriorihopprob=0.2 +; The maximum number of payment results that are held on disk by mission control +; (default: 1000) +; routerrpc.maxmchistory=900 -; Weight of the a priori probability in success probability estimation. Valid -; values are in [0, 1]. (default: 0.5) -; routerrpc.aprioriweight=0.3 +; The time interval with which the MC store state is flushed to the database +; (default: 1s) +; routerrpc.mcflushinterval=1m -; Defines the duration after which a penalized node or channel is back at 50% -; probability (default: 1h0m0s) -; routerrpc.penaltyhalflife=2h +; Path to the router macaroon +; routerrpc.routermacaroonpath=~/.lnd/data/chain/bitcoin/simnet/router.macaroon ; The (virtual) fixed cost in sats of a failed payment attempt (default: 100) ; routerrpc.attemptcost=90 @@ -1128,15 +1130,32 @@ litecoin.node=ltcd ; attempt (default: 1000) ; routerrpc.attemptcostppm=900 -; The maximum number of payment results that are held on disk by mission control -; (default: 1000) -; routerrpc.maxmchistory=900 +; Assumed success probability of a hop in a route when no other information is +; available. (default: 0.6) +; routerrpc.apriori.hopprob=0.2 -; The time interval with which the MC store state is flushed to the DB. -; routerrpc.mcflushinterval=1m +; Weight of the a priori probability in success probability estimation. Valid +; values are in [0, 1]. (default: 0.5) +; routerrpc.apriori.weight=0.3 -; Path to the router macaroon -; routerrpc.routermacaroonpath=~/.lnd/data/chain/bitcoin/simnet/router.macaroon +; Defines the duration after which a penalized node or channel is back at 50% +; probability (default: 1h0m0s) +; routerrpc.apriori.penaltyhalflife=2h + +; Describes the scale over which channels still have some liquidity left on +; both channel ends. A very low value (compared to typical channel capacities) +; means that we assume unbalanced channels, a very high value means randomly +; balanced channels. Value in msat. (default: 300000000) +; routerrpc.bimodal.scale=1000000000 + +; Defines how strongly non-routed channels of forwarders should be taken into +; account for probability estimation. A weight of zero disables this feature. +; Valid values are in [0, 1]. (default: 0.2) +; routerrpc.bimodal.nodeweight=0.3 + +; Defines the information decay of knowledge about previous successes and +; failures in channels. (default: 168h0m0s) +; routerrpc.bimodal.decaytime=72h [workers] diff --git a/server.go b/server.go index 592e061bb..d63d9644d 100644 --- a/server.go +++ b/server.go @@ -873,15 +873,42 @@ func newServer(cfg *Config, listenAddrs []net.Addr, if cfg.Estimator != nil { estimator = cfg.Estimator } else { - aCfg := routing.AprioriConfig{ - AprioriHopProbability: routingConfig. - AprioriHopProbability, - PenaltyHalfLife: routingConfig.PenaltyHalfLife, - AprioriWeight: routingConfig.AprioriWeight, - } - estimator, err = routing.NewAprioriEstimator(aCfg) - if err != nil { - return nil, err + switch routingConfig.ProbabilityEstimatorType { + case routing.AprioriEstimatorName: + aCfg := routingConfig.AprioriConfig + aprioriConfig := routing.AprioriConfig{ + AprioriHopProbability: aCfg.HopProbability, + PenaltyHalfLife: aCfg.PenaltyHalfLife, + AprioriWeight: aCfg.Weight, + } + + estimator, err = routing.NewAprioriEstimator( + aprioriConfig, + ) + if err != nil { + return nil, err + } + + case routing.BimodalEstimatorName: + bCfg := routingConfig.BimodalConfig + bimodalConfig := routing.BimodalConfig{ + BimodalNodeWeight: bCfg.NodeWeight, + BimodalScaleMsat: lnwire.MilliSatoshi( + bCfg.Scale, + ), + BimodalDecayTime: bCfg.DecayTime, + } + + estimator, err = routing.NewBimodalEstimator( + bimodalConfig, + ) + if err != nil { + return nil, err + } + + default: + return nil, fmt.Errorf("unknown estimator type %v", + routingConfig.ProbabilityEstimatorType) } }