mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 09:54:16 +01:00
pay: Add a hysteresis for channel_hint relaxation
If we have a large channel, fail to send through a small amount, and then add a `channel_hint`, then it can happen that the call to `channel_hint_set_update` is already late enough that it refills the 1msat we removed from the attempted amount, thus making the edge we just excluded eligible again, which can lead into an infinite loop. We slow down the updating of the channel_hints to once every hysteresis timeout. This allows us to set tight constraints, while not incurring in the accidental relaxation issue.
This commit is contained in:
parent
50a0321759
commit
30a2933a94
@ -14,8 +14,27 @@ void channel_hint_to_json(const char *name, const struct channel_hint *hint,
|
||||
json_object_end(dest);
|
||||
}
|
||||
|
||||
/* How long until even a channel whose estimate is down at 0msat will
|
||||
* be considered fully refilled. The refill rate is the inverse of
|
||||
* this times the channel size. The refilling is a linear
|
||||
* approximation, with a small hysteresis applied in order to prevent
|
||||
* a single payment relaxing its own constraints thus causing it to
|
||||
* prematurely retry an already attempted channel.
|
||||
*/
|
||||
#define PAY_REFILL_TIME 7200
|
||||
|
||||
/* Add an artificial delay before accepting updates. This ensures we
|
||||
* don't actually end up relaxing a tight constraint inbetween the
|
||||
* attempt that added it and the next retry. If we were to relax right
|
||||
* away, then we could end up retrying the exact same path we just
|
||||
* failed at. If the `time_between_attempts * refill > 1msat`, we'd
|
||||
* end up not actually constraining at all, because we set the
|
||||
* estimate to `attempt - 1msat`. This also results in the updates
|
||||
* being limited to once every minute, and causes a stairway
|
||||
* pattern. The hysteresis has to be >60s otherwise a single payment
|
||||
* can already end up retrying a previously excluded channel.
|
||||
*/
|
||||
#define PAY_REFILL_HYSTERESIS 60
|
||||
/**
|
||||
* Update the `channel_hint` in place, return whether it should be kept.
|
||||
*
|
||||
@ -40,6 +59,9 @@ bool channel_hint_update(const struct timeabs now, struct channel_hint *hint)
|
||||
if (!amount_sat_to_msat(&capacity, hint->capacity))
|
||||
abort();
|
||||
|
||||
if (now.ts.tv_sec < hint->timestamp + PAY_REFILL_HYSTERESIS)
|
||||
return true;
|
||||
|
||||
u64 seconds = now.ts.tv_sec - hint->timestamp;
|
||||
if (!amount_msat_mul(&refill, capacity, seconds))
|
||||
abort();
|
||||
|
Loading…
Reference in New Issue
Block a user