diff --git a/routing/probability_bimodal.go b/routing/probability_bimodal.go index a5a8ba342..35d1f1073 100644 --- a/routing/probability_bimodal.go +++ b/routing/probability_bimodal.go @@ -500,24 +500,36 @@ func (p *BimodalEstimator) probabilityFormula(capacityMsat, successAmountMsat, failAmount = capacity } - // Mission control may have some outdated values, we correct them here. - // TODO(bitromortac): there may be better decisions to make in these - // cases, e.g., resetting failAmount=cap and successAmount=0. + // Mission control may have some outdated values with regard to the + // current channel capacity between a node pair. This can happen in case + // a large parallel channel was closed or if a channel was downscaled + // and can lead to success and/or failure amounts to be out of the range + // [0, capacity]. We assume that the liquidity situation of the channel + // is similar as before due to flow bias. - // failAmount should be capacity at max. - if failAmount > capacity { - log.Debugf("Correcting failAmount %v to capacity %v", - failAmount, capacity) + // In case we have a large success we need to correct it to be in the + // valid range. We set the success amount close to the capacity, because + // we assume to still be able to send. Any possible failure (that must + // in this case be larger than the capacity) is corrected as well. + if successAmount >= capacity { + log.Debugf("Correcting success amount %s and failure amount "+ + "%s to capacity %s", successAmountMsat, + failAmount, capacityMsat) + // We choose the success amount to be one less than the + // capacity, to both fit success and failure amounts into the + // capacity range in a consistent manner. + successAmount = capacity - 1 failAmount = capacity } - // successAmount should be capacity at max. - if successAmount > capacity { - log.Debugf("Correcting successAmount %v to capacity %v", - successAmount, capacity) + // Having no or only a small success, but a large failure only needs + // adjustment of the failure amount. + if failAmount > capacity { + log.Debugf("Correcting failure amount %s to capacity %s", + failAmountMsat, capacityMsat) - successAmount = capacity + failAmount = capacity } // We cannot send more than the fail amount. diff --git a/routing/probability_bimodal_test.go b/routing/probability_bimodal_test.go index d31332739..57590a865 100644 --- a/routing/probability_bimodal_test.go +++ b/routing/probability_bimodal_test.go @@ -212,6 +212,26 @@ func TestSuccessProbability(t *testing.T) { amount: largeAmount, expectedProbability: 0.5, }, + // Larger success and larger failure than the old capacity are + // rescaled to still give a very high success rate. + { + name: "smaller cap, large success/fail", + capacity: capacity, + failAmount: 2*capacity + 1, + successAmount: 2 * capacity, + amount: largeAmount, + expectedProbability: 1.0, + }, + // A lower success amount is not rescaled. + { + name: "smaller cap, large fail", + capacity: capacity, + successAmount: smallAmount / 2, + failAmount: 2 * capacity, + amount: smallAmount, + // See "previous success, larger amount". + expectedProbability: 0.851, + }, } estimator := BimodalEstimator{