routing: track amt ranges in mc

This commit is contained in:
Joost Jager
2019-09-26 17:04:02 +02:00
parent 62f8cca75b
commit cdf1aa5bc1
8 changed files with 320 additions and 229 deletions

View File

@@ -125,26 +125,22 @@ type MissionControlConfig struct {
// TimedPairResult describes a timestamped pair result.
type TimedPairResult struct {
// timestamp is the time when this result was obtained.
Timestamp time.Time
// FailTime is the time of the last failure.
FailTime time.Time
// Amt is the amount that was forwarded in the last payment attempt.
Amt lnwire.MilliSatoshi
// FailAmt is the amount of the last failure. This amount may be pushed
// up if a later success is higher than the last failed amount.
FailAmt lnwire.MilliSatoshi
// Success indicates whether the payment attempt was successful through
// this pair.
Success bool
}
// SuccessTime is the time of the last success.
SuccessTime time.Time
// newTimedPairResult wraps a pair result with a timestamp.
func newTimedPairResult(timestamp time.Time,
result pairResult) TimedPairResult {
return TimedPairResult{
Timestamp: timestamp,
Amt: result.amt,
Success: result.success,
}
// SuccessAmt is the highest amount that successfully forwarded. This
// isn't necessarily the last success amount. The value of this field
// may also be pushed down if a later failure is lower than the highest
// success amount. Because of this, SuccessAmt may not match
// SuccessTime.
SuccessAmt lnwire.MilliSatoshi
}
// MissionControlSnapshot contains a snapshot of the current state of mission
@@ -272,8 +268,8 @@ func (m *MissionControl) GetProbability(fromNode, toNode route.Vertex,
}
// setLastPairResult stores a result for a node pair.
func (m *MissionControl) setLastPairResult(fromNode,
toNode route.Vertex, result TimedPairResult) {
func (m *MissionControl) setLastPairResult(fromNode, toNode route.Vertex,
timestamp time.Time, result *pairResult) {
nodePairs, ok := m.lastPairResult[fromNode]
if !ok {
@@ -281,7 +277,60 @@ func (m *MissionControl) setLastPairResult(fromNode,
m.lastPairResult[fromNode] = nodePairs
}
nodePairs[toNode] = result
current := nodePairs[toNode]
// Apply the new result to the existing data for this pair. If there is
// no existing data, apply it to the default values for TimedPairResult.
if result.success {
successAmt := result.amt
current.SuccessTime = timestamp
// Only update the success amount if this amount is higher. This
// prevents the success range from shrinking when there is no
// reason to do so. For example: small amount probes shouldn't
// affect a previous success for a much larger amount.
if successAmt > current.SuccessAmt {
current.SuccessAmt = successAmt
}
// If the success amount goes into the failure range, move the
// failure range up. Future attempts up to the success amount
// are likely to succeed. We don't want to clear the failure
// completely, because we haven't learnt much for amounts above
// the current success amount.
if !current.FailTime.IsZero() && successAmt >= current.FailAmt {
current.FailAmt = successAmt + 1
}
} else {
// For failures we always want to update both the amount and the
// time. Those need to relate to the same result, because the
// time is used to gradually diminish the penality for that
// specific result. Updating the timestamp but not the amount
// could cause a failure for a lower amount (a more severe
// condition) to be revived as if it just happened.
failAmt := result.amt
current.FailTime = timestamp
current.FailAmt = failAmt
switch {
// The failure amount is set to zero when the failure is
// amount-independent, meaning that the attempt would have
// failed regardless of the amount. This should also reset the
// success amount to zero.
case failAmt == 0:
current.SuccessAmt = 0
// If the failure range goes into the success range, move the
// success range down.
case failAmt <= current.SuccessAmt:
current.SuccessAmt = failAmt - 1
}
}
log.Debugf("Setting %v->%v range to [%v-%v]",
fromNode, toNode, current.SuccessAmt, current.FailAmt)
nodePairs[toNode] = current
}
// setAllFail stores a fail result for all known connection of the given node.
@@ -294,9 +343,9 @@ func (m *MissionControl) setAllFail(fromNode route.Vertex,
}
for connection := range nodePairs {
nodePairs[connection] = newTimedPairResult(
timestamp, failPairResult(0),
)
nodePairs[connection] = TimedPairResult{
FailTime: timestamp,
}
}
}
@@ -491,6 +540,8 @@ func (m *MissionControl) applyPaymentResult(
}
for pair, pairResult := range i.pairResults {
pairResult := pairResult
if pairResult.success {
log.Debugf("Reporting pair success to Mission "+
"Control: pair=%v", pair)
@@ -501,11 +552,7 @@ func (m *MissionControl) applyPaymentResult(
}
m.setLastPairResult(
pair.From, pair.To,
newTimedPairResult(
result.timeReply,
pairResult,
),
pair.From, pair.To, result.timeReply, &pairResult,
)
}