diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index e3d7e30de..f5b72f56c 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -387,6 +387,29 @@ void payment_start(struct payment *p) payment_start_at_blockheight(p, INVALID_BLOCKHEIGHT); } +/** + * Notify subscribers of the `channel_hint` topic about a changed hint + * + * We share the channel_hints across payments, and across plugins, in order to + * maximize the context they have when performing payments. + */ + /** + * Notify subscribers of the `channel_hint` topic about a changed hint + * + * We share the channel_hints across payments, and across plugins, in order + * to maximize the context they have when performing payments. + */ +static void channel_hint_notify(struct plugin *plugin, + const struct channel_hint *hint) +{ + struct json_stream *js = + plugin_notification_start(plugin, "channel_hint_update"); + + /* The timestamp used to decay the observation over time. */ + json_add_u32(js, "timestamp", hint->timestamp); + plugin_notification_end(plugin, js); +} + static void channel_hints_update(struct payment *p, const struct short_channel_id scid, int direction, bool enabled, bool local, @@ -395,6 +418,7 @@ static void channel_hints_update(struct payment *p, { struct payment *root = payment_root(p); struct channel_hint newhint; + u32 timestamp = time_now().ts.tv_sec; /* If the channel is marked as enabled it must have an estimate. */ assert(!enabled || estimated_capacity != NULL); @@ -424,7 +448,8 @@ static void channel_hints_update(struct payment *p, modified = true; } - if (modified) + if (modified) { + hint->timestamp = timestamp; paymod_log(p, LOG_DBG, "Updated a channel hint for %s: " "enabled %s, " @@ -434,12 +459,15 @@ static void channel_hints_update(struct payment *p, hint->enabled ? "true" : "false", fmt_amount_msat(tmpctx, hint->estimated_capacity)); + channel_hint_notify(p->plugin, hint); + } return; } } /* No hint found, create one. */ newhint.enabled = enabled; + newhint.timestamp = timestamp; newhint.scid.scid = scid; newhint.scid.dir = direction; if (local) { @@ -459,6 +487,7 @@ static void channel_hints_update(struct payment *p, fmt_short_channel_id_dir(tmpctx, &newhint.scid), newhint.enabled ? "true" : "false", fmt_amount_msat(tmpctx, newhint.estimated_capacity)); + channel_hint_notify(p->plugin, &newhint); } static void payment_exclude_most_expensive(struct payment *p) diff --git a/plugins/libplugin-pay.h b/plugins/libplugin-pay.h index 1bc2093ef..283c312fa 100644 --- a/plugins/libplugin-pay.h +++ b/plugins/libplugin-pay.h @@ -68,6 +68,13 @@ struct local_hint { * 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 diff --git a/plugins/pay.c b/plugins/pay.c index 2e15ea92a..c859b5d13 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -1524,6 +1524,7 @@ static const struct plugin_command commands[] = { static const char *notification_topics[] = { "pay_success", "pay_failure", + "channel_hint_update", }; int main(int argc, char *argv[])