From 4aa90cf474952b35098ebd6806fb93f13901fb45 Mon Sep 17 00:00:00 2001 From: bitromortac Date: Thu, 16 Mar 2023 10:03:15 +0100 Subject: [PATCH] routing: add error case for zero capacity Since no edge should have a zero capacity associated with it, passing a zero capacity to the bimodal probability calculation results now in an error. --- docs/release-notes/release-notes-0.16.0.md | 4 ++++ routing/probability_bimodal.go | 14 ++++++++++---- routing/probability_bimodal_test.go | 14 +++++++++++++- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/docs/release-notes/release-notes-0.16.0.md b/docs/release-notes/release-notes-0.16.0.md index 4b033687c..3c97d9c0d 100644 --- a/docs/release-notes/release-notes-0.16.0.md +++ b/docs/release-notes/release-notes-0.16.0.md @@ -459,6 +459,10 @@ in the lnwire package](https://github.com/lightningnetwork/lnd/pull/7303) https://github.com/lightningnetwork/lnd/pull/6815) * [The a priori capacity factor is made configurable and its effect is limited.](https://github.com/lightningnetwork/lnd/pull/7444) +* Local edges and hop hints [are extended with a + capacity](https://github.com/lightningnetwork/lnd/pull/7520) to avoid channel + white listing in probability calculations. The influence of the node + probability is reduced. ## Configuration * Note that [this pathfinding change](https://github.com/lightningnetwork/lnd/pull/6815) diff --git a/routing/probability_bimodal.go b/routing/probability_bimodal.go index c1718e977..06f2646ec 100644 --- a/routing/probability_bimodal.go +++ b/routing/probability_bimodal.go @@ -49,6 +49,10 @@ var ( // ErrInvalidDecayTime is returned when we get a decay time below zero. ErrInvalidDecayTime = errors.New("decay time must be larger than zero") + + // ErrZeroCapacity is returned when we encounter a channel with zero + // capacity in probability estimation. + ErrZeroCapacity = errors.New("capacity must be larger than zero") ) // BimodalConfig contains configuration for our probability estimator. @@ -226,7 +230,9 @@ func (p *BimodalEstimator) directProbability(now time.Time, capacity, successAmount, failAmount, amt, ) if err != nil { - log.Errorf("error computing probability: %v", err) + log.Errorf("error computing probability to node: %v "+ + "(node: %v, results: %v, amt: %v, capacity: %v)", + err, toNode, results, amt, capacity) return 0.0 } @@ -441,10 +447,10 @@ func (p *BimodalEstimator) probabilityFormula(capacityMsat, successAmountMsat, failAmount := float64(failAmountMsat) amount := float64(amountMsat) - // Capacity being zero is a sentinel value to ignore the probability - // estimation, we'll return the full probability here. + // In order for this formula to give reasonable results, we need to have + // an estimate of the capacity of a channel (or edge between nodes). if capacity == 0.0 { - return 1.0, nil + return 0, ErrZeroCapacity } // We cannot send more than the capacity. diff --git a/routing/probability_bimodal_test.go b/routing/probability_bimodal_test.go index 53f8829c4..8e8797d39 100644 --- a/routing/probability_bimodal_test.go +++ b/routing/probability_bimodal_test.go @@ -232,6 +232,16 @@ func TestSuccessProbability(t *testing.T) { require.NoError(t, err) }) } + + // We expect an error when the capacity is zero. + t.Run("zero capacity", func(t *testing.T) { + t.Parallel() + + _, err := estimator.probabilityFormula( + 0, 0, 0, 0, + ) + require.ErrorIs(t, err, ErrZeroCapacity) + }) } // TestIntegral tests certain limits of the probability distribution integral. @@ -649,7 +659,9 @@ func FuzzProbability(f *testing.F) { estimator := BimodalEstimator{ BimodalConfig: BimodalConfig{BimodalScaleMsat: scale}, } - f.Add(uint64(0), uint64(0), uint64(0), uint64(0)) + + // We don't start fuzzing at zero, because that would cause an error. + f.Add(uint64(1), uint64(0), uint64(0), uint64(0)) f.Fuzz(func(t *testing.T, capacity, successAmt, failAmt, amt uint64) { _, err := estimator.probabilityFormula(