-
Notifications
You must be signed in to change notification settings - Fork 920
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
plugin: Split out the
struct channel_hint
handling
We're getting serious about how we manage the channel_hints, so let's give them a proper home.
- Loading branch information
Showing
6 changed files
with
170 additions
and
121 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
#include "config.h" | ||
#include <plugins/channel_hint.h> | ||
|
||
void channel_hint_to_json(const char *name, const struct channel_hint *hint, | ||
struct json_stream *dest) | ||
{ | ||
json_object_start(dest, name); | ||
json_add_u32(dest, "timestamp", hint->timestamp); | ||
json_add_short_channel_id_dir(dest, "scid", hint->scid); | ||
json_add_amount_msat(dest, "estimated_capacity_msat", | ||
hint->estimated_capacity); | ||
json_add_amount_msat(dest, "overall_capacity_msat", | ||
hint->overall_capacity); | ||
json_add_bool(dest, "enabled", hint->enabled); | ||
json_object_end(dest); | ||
} | ||
|
||
#define PAY_REFILL_TIME 7200 | ||
|
||
/** | ||
* Update the `channel_hint` in place, return whether it should be kept. | ||
* | ||
* This computes the refill-rate based on the overall capacity, and | ||
* the time elapsed since the last update and relaxes the upper bound | ||
* on the capacity, and resets the enabled flag if appropriate. If the | ||
* hint is no longer useful, i.e., it does not provide any additional | ||
* information on top of the structural information we've learned from | ||
* the gossip, then we return `false` to signal that the | ||
* `channel_hint` may be removed. | ||
*/ | ||
bool channel_hint_update(const struct timeabs now, struct channel_hint *hint) | ||
{ | ||
/* Precision is not required here, so integer division is good | ||
* enough. But keep the order such that we do not round down | ||
* too much. We do so by first multiplying, before | ||
* dividing. The formula is `current = last + delta_t * | ||
* overall / refill_rate`. | ||
*/ | ||
struct amount_msat refill; | ||
u64 seconds = now.ts.tv_sec - hint->timestamp; | ||
if (!amount_msat_mul(&refill, hint->overall_capacity, seconds)) | ||
abort(); | ||
|
||
refill = amount_msat_div(refill, PAY_REFILL_TIME); | ||
if (!amount_msat_add(&hint->estimated_capacity, | ||
hint->estimated_capacity, refill)) | ||
abort(); | ||
|
||
/* Clamp the value to the `overall_capacity` */ | ||
if (amount_msat_greater(hint->estimated_capacity, | ||
hint->overall_capacity)) | ||
hint->estimated_capacity = hint->overall_capacity; | ||
|
||
/* TODO This is rather coarse. We could map the disabled flag | ||
to having 0msat capacity, and then relax from there. But it'd | ||
likely be too slow of a relaxation.*/ | ||
if (seconds > 60) | ||
hint->enabled = true; | ||
|
||
/* Since we update in-place we should make sure that we can | ||
* just call update again and the result is stable, if no time | ||
* has passed. */ | ||
hint->timestamp = now.ts.tv_sec; | ||
|
||
/* We report this hint as useless, if the hint does not | ||
* restrict the channel, i.e., if it is enabled and the | ||
* estimate is the same as the overall capacity. */ | ||
return !hint->enabled || amount_msat_greater(hint->overall_capacity, | ||
hint->estimated_capacity); | ||
} | ||
|
||
/** | ||
* Load a channel_hint from its JSON representation. | ||
* | ||
* @return The initialized `channel_hint` or `NULL` if we encountered a parsing | ||
* error. | ||
*/ | ||
/* | ||
struct channel_hint *channel_hint_from_json(const tal_t *ctx, | ||
const char *buffer, | ||
const jsmntok_t *toks) | ||
{ | ||
const char *ret; | ||
struct channel_hint *hint = tal(ctx, struct channel_hint); | ||
ret = json_scan(ctx, buffer, toks, | ||
"{timestamp:%,scid:%,estimated_capacity_msat:%,overall_capacity_msat:%,enabled:%}", | ||
JSON_SCAN(json_to_u32, &hint->timestamp), | ||
JSON_SCAN(json_to_short_channel_id_dir, &hint->scid), | ||
JSON_SCAN(json_to_msat, &hint->estimated_capacity), | ||
JSON_SCAN(json_to_bool, &hint->enabled)); | ||
if (ret != NULL) | ||
hint = tal_free(hint); | ||
return hint; | ||
} | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
#ifndef LIGHTNING_PLUGINS_CHANNEL_HINT_H | ||
#define LIGHTNING_PLUGINS_CHANNEL_HINT_H | ||
|
||
#include "config.h" | ||
#include <bitcoin/short_channel_id.h> | ||
#include <ccan/short_types/short_types.h> | ||
#include <ccan/time/time.h> | ||
#include <common/amount.h> | ||
#include <common/json_stream.h> | ||
#include <plugins/libplugin-pay.h> | ||
#include <plugins/libplugin.h> | ||
|
||
/* Information about channels we inferred from a) looking at our channels, and | ||
* b) from failures encountered during attempts to perform a payment. These | ||
* are attached to the root payment, since that information is | ||
* global. Attempts update the estimated channel capacities when starting, and | ||
* get remove on failure. Success keeps the capacities, since the capacities | ||
* changed due to the successful HTLCs. */ | ||
struct channel_hint { | ||
/* The timestamp this observation was made. Used to let the | ||
* constraint expressed by this hint decay over time, until it | ||
* is fully relaxed, at which point we can forget about it | ||
* (the structural information is the best we can do in that | ||
* case). | ||
*/ | ||
u32 timestamp; | ||
/* The short_channel_id we're going to use when referring to | ||
* this channel. This can either be the real scid, or the | ||
* local alias. The `pay` algorithm doesn't really care which | ||
* one it is, but we'll prefer the scid as that's likely more | ||
* readable than the alias. */ | ||
struct short_channel_id_dir scid; | ||
|
||
/* Upper bound on remove channels inferred from payment failures. */ | ||
struct amount_msat estimated_capacity; | ||
|
||
/* Is the channel enabled? */ | ||
bool enabled; | ||
|
||
/* Non-null if we are one endpoint of this channel */ | ||
struct local_hint *local; | ||
|
||
/* The total `amount_msat` that were used to fund the | ||
* channel. This is always smaller gte the | ||
* estimated_capacity */ | ||
struct amount_msat overall_capacity; | ||
}; | ||
|
||
/* A collection of channel_hint instances, allowing us to handle and | ||
* update them more easily. */ | ||
struct channel_hint_set { | ||
/* tal_arr of channel_hints. */ | ||
struct channel_hint *hints; | ||
}; | ||
|
||
bool channel_hint_update(const struct timeabs now, | ||
struct channel_hint *hint); | ||
|
||
void channel_hint_to_json(const char *name, const struct channel_hint *hint, struct json_stream *dest); | ||
|
||
#endif /* LIGHTNING_PLUGINS_CHANNEL_HINT_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters