routing: add probability estimator interface
We introduce a probability `Estimator` interface which is implemented by the current apriori probability estimator. A second implementation, the bimodal probability estimator follows.
This commit is contained in:
2 files changed
+90
-1
No files matched your search
@@ -2,6 +2,7 @@ package routing
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -45,6 +46,10 @@ const (
|
|||||||
// capacityCutoffFraction, but a smooth smearing such that some residual
|
// capacityCutoffFraction, but a smooth smearing such that some residual
|
||||||
// probability is left when spending the whole amount, see above.
|
// probability is left when spending the whole amount, see above.
|
||||||
capacitySmearingFraction = 0.1
|
capacitySmearingFraction = 0.1
|
||||||
|
|
||||||
|
// AprioriEstimatorName is used to identify the apriori probability
|
||||||
|
// estimator.
|
||||||
|
AprioriEstimatorName = "apriori"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -81,6 +86,7 @@ type AprioriConfig struct {
|
|||||||
AprioriWeight float64
|
AprioriWeight float64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validate checks the configuration of the estimator for allowed values.
|
||||||
func (p AprioriConfig) validate() error {
|
func (p AprioriConfig) validate() error {
|
||||||
if p.PenaltyHalfLife < 0 {
|
if p.PenaltyHalfLife < 0 {
|
||||||
return ErrInvalidHalflife
|
return ErrInvalidHalflife
|
||||||
@@ -97,8 +103,24 @@ func (p AprioriConfig) validate() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultAprioriConfig returns the default configuration for the estimator.
|
||||||
|
func DefaultAprioriConfig() AprioriConfig {
|
||||||
|
return AprioriConfig{
|
||||||
|
PenaltyHalfLife: DefaultPenaltyHalfLife,
|
||||||
|
AprioriHopProbability: DefaultAprioriHopProbability,
|
||||||
|
AprioriWeight: DefaultAprioriWeight,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AprioriEstimator returns node and pair probabilities based on historical
|
// AprioriEstimator returns node and pair probabilities based on historical
|
||||||
// payment results.
|
// payment results. It uses a preconfigured success probability value for
|
||||||
|
// untried hops (AprioriHopProbability) and returns a high success probability
|
||||||
|
// for hops that could previously conduct a payment (prevSuccessProbability).
|
||||||
|
// Successful edges are retried until proven otherwise. Recently failed hops are
|
||||||
|
// penalized by an exponential time decay (PenaltyHalfLife), after which they
|
||||||
|
// are reconsidered for routing. If information was learned about a forwarding
|
||||||
|
// node, the information is taken into account to estimate a per node
|
||||||
|
// probability that mixes with the a priori probability (AprioriWeight).
|
||||||
type AprioriEstimator struct {
|
type AprioriEstimator struct {
|
||||||
// AprioriConfig contains configuration options for our estimator.
|
// AprioriConfig contains configuration options for our estimator.
|
||||||
AprioriConfig
|
AprioriConfig
|
||||||
@@ -108,6 +130,36 @@ type AprioriEstimator struct {
|
|||||||
prevSuccessProbability float64
|
prevSuccessProbability float64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewAprioriEstimator creates a new AprioriEstimator.
|
||||||
|
func NewAprioriEstimator(cfg AprioriConfig) (*AprioriEstimator, error) {
|
||||||
|
if err := cfg.validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &AprioriEstimator{
|
||||||
|
AprioriConfig: cfg,
|
||||||
|
prevSuccessProbability: prevSuccessProbability,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile-time checks that interfaces are implemented.
|
||||||
|
var _ Estimator = (*AprioriEstimator)(nil)
|
||||||
|
var _ estimatorConfig = (*AprioriConfig)(nil)
|
||||||
|
|
||||||
|
// Config returns the estimator's configuration.
|
||||||
|
func (p *AprioriEstimator) Config() estimatorConfig {
|
||||||
|
return p.AprioriConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the estimator's configuration as a string representation.
|
||||||
|
func (p *AprioriEstimator) String() string {
|
||||||
|
return fmt.Sprintf("estimator type: %v, penalty halflife time: %v, "+
|
||||||
|
"apriori hop probability: %v, apriori weight: %v, previous "+
|
||||||
|
"success probability: %v", AprioriEstimatorName,
|
||||||
|
p.PenaltyHalfLife, p.AprioriHopProbability, p.AprioriWeight,
|
||||||
|
p.prevSuccessProbability)
|
||||||
|
}
|
||||||
|
|
||||||
// getNodeProbability calculates the probability for connections from a node
|
// getNodeProbability calculates the probability for connections from a node
|
||||||
// that have not been tried before. The results parameter is a list of last
|
// that have not been tried before. The results parameter is a list of last
|
||||||
// payment results for that node.
|
// payment results for that node.
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package routing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
"github.com/lightningnetwork/lnd/routing/route"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Estimator estimates the probability to reach a node.
|
||||||
|
type Estimator interface {
|
||||||
|
// PairProbability estimates the probability of successfully traversing
|
||||||
|
// to toNode based on historical payment outcomes for the from node.
|
||||||
|
// Those outcomes are passed in via the results parameter.
|
||||||
|
PairProbability(now time.Time, results NodeResults,
|
||||||
|
toNode route.Vertex, amt lnwire.MilliSatoshi,
|
||||||
|
capacity btcutil.Amount) float64
|
||||||
|
|
||||||
|
// LocalPairProbability estimates the probability of successfully
|
||||||
|
// traversing our own local channels to toNode.
|
||||||
|
LocalPairProbability(now time.Time, results NodeResults,
|
||||||
|
toNode route.Vertex) float64
|
||||||
|
|
||||||
|
// Config returns the estimator's configuration.
|
||||||
|
Config() estimatorConfig
|
||||||
|
|
||||||
|
// String returns the string representation of the estimator's
|
||||||
|
// configuration.
|
||||||
|
String() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// estimatorConfig represents a configuration for a probability estimator.
|
||||||
|
type estimatorConfig interface {
|
||||||
|
// validate checks that all configuration parameters are sane.
|
||||||
|
validate() error
|
||||||
|
}
|
||||||
Reference in new issue
Block a user