Merge pull request #6815 from bitromortac/2205-bimodal

pathfinding: probability for bimodal distribution
This commit is contained in:
Oliver Gugger authored and GitHub committed 2023-02-15 14:19:32 +01:00
commit 38dc67e1ef
25 files changed
+3237 -963

No files matched your search

+33 -16
View File
@@ -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,
},
}
}
File diff suppressed because it is too large. Load diff
+89 -13
View File
@@ -467,6 +467,93 @@ message SetMissionControlConfigResponse {
}
message MissionControlConfig {
/*
Deprecated, use AprioriParameters. The amount of time mission control will
take to restore a penalized node or channel back to 50% success probability,
expressed in seconds. Setting this value to a higher value will penalize
failures for longer, making mission control less likely to route through
nodes and channels that we have previously recorded failures for.
*/
uint64 half_life_seconds = 1 [deprecated = true];
/*
Deprecated, use AprioriParameters. The probability of success mission
control should assign to hop in a route where it has no other information
available. Higher values will make mission control more willing to try hops
that we have no information about, lower values will discourage trying these
hops.
*/
float hop_probability = 2 [deprecated = true];
/*
Deprecated, use AprioriParameters. The importance that mission control
should place on historical results, expressed as a value in [0;1]. Setting
this value to 1 will ignore all historical payments and just use the hop
probability to assess the probability of success for each hop. A zero value
ignores hop probability completely and relies entirely on historical
results, unless none are available.
*/
float weight = 3 [deprecated = true];
/*
The maximum number of payment results that mission control will store.
*/
uint32 maximum_payment_results = 4;
/*
The minimum time that must have passed since the previously recorded failure
before we raise the failure amount.
*/
uint64 minimum_failure_relax_interval = 5;
enum ProbabilityModel {
APRIORI = 0;
BIMODAL = 1;
}
/*
ProbabilityModel defines which probability estimator should be used in
pathfinding.
*/
ProbabilityModel Model = 6;
/*
EstimatorConfig is populated dependent on the estimator type.
*/
oneof EstimatorConfig {
AprioriParameters apriori = 7;
BimodalParameters bimodal = 8;
}
}
message BimodalParameters {
/*
NodeWeight defines how strongly other previous forwardings on channels of a
router should be taken into account when computing a channel's probability
to route. The allowed values are in the range [0, 1], where a value of 0
means that only direct information about a channel is taken into account.
*/
double node_weight = 1;
/*
ScaleMsat describes the scale over which channels statistically have some
liquidity left. The value determines how quickly the bimodal distribution
drops off from the edges of a channel. A larger value (compared to typical
channel capacities) means that the drop off is slow and that channel
balances are distributed more uniformly. A small value leads to the
assumption of very unbalanced channels.
*/
uint64 scale_msat = 2;
/*
DecayTime describes the information decay of knowledge about previous
successes and failures in channels. The smaller the decay time, the quicker
we forget about past forwardings.
*/
uint64 decay_time = 3;
}
message AprioriParameters {
/*
The amount of time mission control will take to restore a penalized node
or channel back to 50% success probability, expressed in seconds. Setting
@@ -482,7 +569,7 @@ message MissionControlConfig {
control more willing to try hops that we have no information about, lower
values will discourage trying these hops.
*/
float hop_probability = 2;
double hop_probability = 2;
/*
The importance that mission control should place on historical results,
@@ -492,18 +579,7 @@ message MissionControlConfig {
completely and relies entirely on historical results, unless none are
available.
*/
float weight = 3;
/*
The maximum number of payment results that mission control will store.
*/
uint32 maximum_payment_results = 4;
/*
The minimum time that must have passed since the previously recorded failure
before we raise the failure amount.
*/
uint64 minimum_failure_relax_interval = 5;
double weight = 3;
}
message QueryProbabilityRequest {
+61 -3
View File
@@ -593,6 +593,14 @@
],
"default": "IN_FLIGHT"
},
"MissionControlConfigProbabilityModel": {
"type": "string",
"enum": [
"APRIORI",
"BIMODAL"
],
"default": "APRIORI"
},
"lnrpcAMPRecord": {
"type": "object",
"properties": {
@@ -1073,6 +1081,46 @@
}
}
},
"routerrpcAprioriParameters": {
"type": "object",
"properties": {
"half_life_seconds": {
"type": "string",
"format": "uint64",
"description": "The amount of time mission control will take to restore a penalized node\nor channel back to 50% success probability, expressed in seconds. Setting\nthis value to a higher value will penalize failures for longer, making\nmission control less likely to route through nodes and channels that we\nhave previously recorded failures for."
},
"hop_probability": {
"type": "number",
"format": "double",
"description": "The probability of success mission control should assign to hop in a route\nwhere it has no other information available. Higher values will make mission\ncontrol more willing to try hops that we have no information about, lower\nvalues will discourage trying these hops."
},
"weight": {
"type": "number",
"format": "double",
"description": "The importance that mission control should place on historical results,\nexpressed as a value in [0;1]. Setting this value to 1 will ignore all\nhistorical payments and just use the hop probability to assess the\nprobability of success for each hop. A zero value ignores hop probability\ncompletely and relies entirely on historical results, unless none are\navailable."
}
}
},
"routerrpcBimodalParameters": {
"type": "object",
"properties": {
"node_weight": {
"type": "number",
"format": "double",
"description": "NodeWeight defines how strongly other previous forwardings on channels of a\nrouter should be taken into account when computing a channel's probability\nto route. The allowed values are in the range [0, 1], where a value of 0\nmeans that only direct information about a channel is taken into account."
},
"scale_msat": {
"type": "string",
"format": "uint64",
"description": "ScaleMsat describes the scale over which channels statistically have some\nliquidity left. The value determines how quickly the bimodal distribution\ndrops off from the edges of a channel. A larger value (compared to typical\nchannel capacities) means that the drop off is slow and that channel\nbalances are distributed more uniformly. A small value leads to the\nassumption of very unbalanced channels."
},
"decay_time": {
"type": "string",
"format": "uint64",
"description": "DecayTime describes the information decay of knowledge about previous\nsuccesses and failures in channels. The smaller the decay time, the quicker\nwe forget about past forwardings."
}
}
},
"routerrpcBuildRouteRequest": {
"type": "object",
"properties": {
@@ -1400,17 +1448,17 @@
"half_life_seconds": {
"type": "string",
"format": "uint64",
"description": "The amount of time mission control will take to restore a penalized node\nor channel back to 50% success probability, expressed in seconds. Setting\nthis value to a higher value will penalize failures for longer, making\nmission control less likely to route through nodes and channels that we\nhave previously recorded failures for."
"description": "Deprecated, use AprioriParameters. The amount of time mission control will\ntake to restore a penalized node or channel back to 50% success probability,\nexpressed in seconds. Setting this value to a higher value will penalize\nfailures for longer, making mission control less likely to route through\nnodes and channels that we have previously recorded failures for."
},
"hop_probability": {
"type": "number",
"format": "float",
"description": "The probability of success mission control should assign to hop in a route\nwhere it has no other information available. Higher values will make mission\ncontrol more willing to try hops that we have no information about, lower\nvalues will discourage trying these hops."
"description": "Deprecated, use AprioriParameters. The probability of success mission\ncontrol should assign to hop in a route where it has no other information\navailable. Higher values will make mission control more willing to try hops\nthat we have no information about, lower values will discourage trying these\nhops."
},
"weight": {
"type": "number",
"format": "float",
"description": "The importance that mission control should place on historical results,\nexpressed as a value in [0;1]. Setting this value to 1 will ignore all\nhistorical payments and just use the hop probability to assess the\nprobability of success for each hop. A zero value ignores hop probability\ncompletely and relies entirely on historical results, unless none are\navailable."
"description": "Deprecated, use AprioriParameters. The importance that mission control\nshould place on historical results, expressed as a value in [0;1]. Setting\nthis value to 1 will ignore all historical payments and just use the hop\nprobability to assess the probability of success for each hop. A zero value\nignores hop probability completely and relies entirely on historical\nresults, unless none are available."
},
"maximum_payment_results": {
"type": "integer",
@@ -1421,6 +1469,16 @@
"type": "string",
"format": "uint64",
"description": "The minimum time that must have passed since the previously recorded failure\nbefore we raise the failure amount."
},
"Model": {
"$ref": "#/definitions/MissionControlConfigProbabilityModel",
"description": "ProbabilityModel defines which probability estimator should be used in\npathfinding."
},
"apriori": {
"$ref": "#/definitions/routerrpcAprioriParameters"
},
"bimodal": {
"$ref": "#/definitions/routerrpcBimodalParameters"
}
}
},
+115 -17
View File
@@ -454,39 +454,137 @@ func (s *Server) GetMissionControlConfig(ctx context.Context,
req *GetMissionControlConfigRequest) (*GetMissionControlConfigResponse,
error) {
// Query the current mission control config.
cfg := s.cfg.RouterBackend.MissionControl.GetConfig()
return &GetMissionControlConfigResponse{
resp := &GetMissionControlConfigResponse{
Config: &MissionControlConfig{
HalfLifeSeconds: uint64(cfg.PenaltyHalfLife.Seconds()),
HopProbability: float32(cfg.AprioriHopProbability),
Weight: float32(cfg.AprioriWeight),
MaximumPaymentResults: uint32(cfg.MaxMcHistory),
MinimumFailureRelaxInterval: uint64(cfg.MinFailureRelaxInterval.Seconds()),
MaximumPaymentResults: uint32(cfg.MaxMcHistory),
MinimumFailureRelaxInterval: uint64(
cfg.MinFailureRelaxInterval.Seconds(),
),
},
}, nil
}
// We only populate fields based on the current estimator.
switch v := cfg.Estimator.Config().(type) {
case routing.AprioriConfig:
resp.Config.Model = MissionControlConfig_APRIORI
aCfg := AprioriParameters{
HalfLifeSeconds: uint64(v.PenaltyHalfLife.Seconds()),
HopProbability: v.AprioriHopProbability,
Weight: v.AprioriWeight,
}
// Populate deprecated fields.
resp.Config.HalfLifeSeconds = uint64(
v.PenaltyHalfLife.Seconds(),
)
resp.Config.HopProbability = float32(v.AprioriHopProbability)
resp.Config.Weight = float32(v.AprioriWeight)
resp.Config.EstimatorConfig = &MissionControlConfig_Apriori{
Apriori: &aCfg,
}
case routing.BimodalConfig:
resp.Config.Model = MissionControlConfig_BIMODAL
bCfg := BimodalParameters{
NodeWeight: v.BimodalNodeWeight,
ScaleMsat: uint64(v.BimodalScaleMsat),
DecayTime: uint64(v.BimodalDecayTime.Seconds()),
}
resp.Config.EstimatorConfig = &MissionControlConfig_Bimodal{
Bimodal: &bCfg,
}
default:
return nil, fmt.Errorf("unknown estimator config type %T", v)
}
return resp, nil
}
// SetMissionControlConfig returns our current mission control config.
// SetMissionControlConfig sets parameters in the mission control config.
func (s *Server) SetMissionControlConfig(ctx context.Context,
req *SetMissionControlConfigRequest) (*SetMissionControlConfigResponse,
error) {
cfg := &routing.MissionControlConfig{
ProbabilityEstimatorCfg: routing.ProbabilityEstimatorCfg{
PenaltyHalfLife: time.Duration(
req.Config.HalfLifeSeconds,
) * time.Second,
AprioriHopProbability: float64(req.Config.HopProbability),
AprioriWeight: float64(req.Config.Weight),
},
mcCfg := &routing.MissionControlConfig{
MaxMcHistory: int(req.Config.MaximumPaymentResults),
MinFailureRelaxInterval: time.Duration(
req.Config.MinimumFailureRelaxInterval,
) * time.Second,
}
switch req.Config.Model {
case MissionControlConfig_APRIORI:
var aprioriConfig routing.AprioriConfig
// Determine the apriori config with backward compatibility
// should the api use deprecated fields.
switch v := req.Config.EstimatorConfig.(type) {
case *MissionControlConfig_Bimodal:
return nil, fmt.Errorf("bimodal config " +
"provided, but apriori model requested")
case *MissionControlConfig_Apriori:
aprioriConfig = routing.AprioriConfig{
PenaltyHalfLife: time.Duration(
v.Apriori.HalfLifeSeconds,
) * time.Second,
AprioriHopProbability: v.Apriori.HopProbability,
AprioriWeight: v.Apriori.Weight,
}
default:
aprioriConfig = routing.AprioriConfig{
PenaltyHalfLife: time.Duration(
int64(req.Config.HalfLifeSeconds),
) * time.Second,
AprioriHopProbability: float64(
req.Config.HopProbability,
),
AprioriWeight: float64(req.Config.Weight),
}
}
estimator, err := routing.NewAprioriEstimator(aprioriConfig)
if err != nil {
return nil, err
}
mcCfg.Estimator = estimator
case MissionControlConfig_BIMODAL:
cfg, ok := req.Config.
EstimatorConfig.(*MissionControlConfig_Bimodal)
if !ok {
return nil, fmt.Errorf("bimodal estimator requested " +
"but corresponding config not set")
}
bCfg := cfg.Bimodal
bimodalConfig := routing.BimodalConfig{
BimodalDecayTime: time.Duration(
bCfg.DecayTime,
) * time.Second,
BimodalScaleMsat: lnwire.MilliSatoshi(bCfg.ScaleMsat),
BimodalNodeWeight: bCfg.NodeWeight,
}
estimator, err := routing.NewBimodalEstimator(bimodalConfig)
if err != nil {
return nil, err
}
mcCfg.Estimator = estimator
default:
return nil, fmt.Errorf("unknown estimator type %v",
req.Config.Model)
}
return &SetMissionControlConfigResponse{},
s.cfg.RouterBackend.MissionControl.SetConfig(cfg)
s.cfg.RouterBackend.MissionControl.SetConfig(mcCfg)
}
// QueryMissionControl exposes the internal mission control state to callers. It
+52 -17
View File
@@ -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."`
}