|
| 1 | +#include "config.h" |
| 2 | +#include <plugins/channel_hint.h> |
| 3 | + |
| 4 | +void channel_hint_to_json(const char *name, const struct channel_hint *hint, |
| 5 | + struct json_stream *dest) |
| 6 | +{ |
| 7 | + json_object_start(dest, name); |
| 8 | + json_add_u32(dest, "timestamp", hint->timestamp); |
| 9 | + json_add_short_channel_id_dir(dest, "scid", hint->scid); |
| 10 | + json_add_amount_msat(dest, "estimated_capacity_msat", |
| 11 | + hint->estimated_capacity); |
| 12 | + json_add_amount_msat(dest, "overall_capacity_msat", |
| 13 | + hint->overall_capacity); |
| 14 | + json_add_bool(dest, "enabled", hint->enabled); |
| 15 | + json_object_end(dest); |
| 16 | +} |
| 17 | + |
| 18 | +#define PAY_REFILL_TIME 7200 |
| 19 | + |
| 20 | +/** |
| 21 | + * Update the `channel_hint` in place, return whether it should be kept. |
| 22 | + * |
| 23 | + * This computes the refill-rate based on the overall capacity, and |
| 24 | + * the time elapsed since the last update and relaxes the upper bound |
| 25 | + * on the capacity, and resets the enabled flag if appropriate. If the |
| 26 | + * hint is no longer useful, i.e., it does not provide any additional |
| 27 | + * information on top of the structural information we've learned from |
| 28 | + * the gossip, then we return `false` to signal that the |
| 29 | + * `channel_hint` may be removed. |
| 30 | + */ |
| 31 | +bool channel_hint_update(const struct timeabs now, struct channel_hint *hint) |
| 32 | +{ |
| 33 | + /* Precision is not required here, so integer division is good |
| 34 | + * enough. But keep the order such that we do not round down |
| 35 | + * too much. We do so by first multiplying, before |
| 36 | + * dividing. The formula is `current = last + delta_t * |
| 37 | + * overall / refill_rate`. |
| 38 | + */ |
| 39 | + struct amount_msat refill; |
| 40 | + u64 seconds = now.ts.tv_sec - hint->timestamp; |
| 41 | + if (!amount_msat_mul(&refill, hint->overall_capacity, seconds)) |
| 42 | + abort(); |
| 43 | + |
| 44 | + refill = amount_msat_div(refill, PAY_REFILL_TIME); |
| 45 | + if (!amount_msat_add(&hint->estimated_capacity, |
| 46 | + hint->estimated_capacity, refill)) |
| 47 | + abort(); |
| 48 | + |
| 49 | + /* Clamp the value to the `overall_capacity` */ |
| 50 | + if (amount_msat_greater(hint->estimated_capacity, |
| 51 | + hint->overall_capacity)) |
| 52 | + hint->estimated_capacity = hint->overall_capacity; |
| 53 | + |
| 54 | + /* TODO This is rather coarse. We could map the disabled flag |
| 55 | + to having 0msat capacity, and then relax from there. But it'd |
| 56 | + likely be too slow of a relaxation.*/ |
| 57 | + if (seconds > 60) |
| 58 | + hint->enabled = true; |
| 59 | + |
| 60 | + /* Since we update in-place we should make sure that we can |
| 61 | + * just call update again and the result is stable, if no time |
| 62 | + * has passed. */ |
| 63 | + hint->timestamp = now.ts.tv_sec; |
| 64 | + |
| 65 | + /* We report this hint as useless, if the hint does not |
| 66 | + * restrict the channel, i.e., if it is enabled and the |
| 67 | + * estimate is the same as the overall capacity. */ |
| 68 | + return !hint->enabled || amount_msat_greater(hint->overall_capacity, |
| 69 | + hint->estimated_capacity); |
| 70 | +} |
| 71 | + |
| 72 | +/** |
| 73 | + * Load a channel_hint from its JSON representation. |
| 74 | + * |
| 75 | + * @return The initialized `channel_hint` or `NULL` if we encountered a parsing |
| 76 | + * error. |
| 77 | + */ |
| 78 | +/* |
| 79 | +struct channel_hint *channel_hint_from_json(const tal_t *ctx, |
| 80 | + const char *buffer, |
| 81 | + const jsmntok_t *toks) |
| 82 | +{ |
| 83 | + const char *ret; |
| 84 | + struct channel_hint *hint = tal(ctx, struct channel_hint); |
| 85 | + ret = json_scan(ctx, buffer, toks, |
| 86 | + "{timestamp:%,scid:%,estimated_capacity_msat:%,overall_capacity_msat:%,enabled:%}", |
| 87 | + JSON_SCAN(json_to_u32, &hint->timestamp), |
| 88 | + JSON_SCAN(json_to_short_channel_id_dir, &hint->scid), |
| 89 | + JSON_SCAN(json_to_msat, &hint->estimated_capacity), |
| 90 | + JSON_SCAN(json_to_bool, &hint->enabled)); |
| 91 | +
|
| 92 | + if (ret != NULL) |
| 93 | + hint = tal_free(hint); |
| 94 | + return hint; |
| 95 | +} |
| 96 | +*/ |
0 commit comments