mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-20 15:44:21 +01:00
paymod: Add a local_channel_hints modifier to collect local channels
We can have quite detailed information about our local channels, so call `listpeers` before the `getroute` call on the root payment, to seed that information in the channel_hints.
This commit is contained in:
@@ -54,6 +54,7 @@ struct payment *payment_new(tal_t *ctx, struct command *cmd,
|
|||||||
p->partid = 0;
|
p->partid = 0;
|
||||||
p->next_partid = 1;
|
p->next_partid = 1;
|
||||||
p->plugin = cmd->plugin;
|
p->plugin = cmd->plugin;
|
||||||
|
p->channel_hints = tal_arr(p, struct channel_hint, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize all modifier data so we can point to the fields when
|
/* Initialize all modifier data so we can point to the fields when
|
||||||
@@ -793,3 +794,61 @@ static inline void retry_step_cb(struct retry_mod_data *rd,
|
|||||||
|
|
||||||
payment_continue(p);
|
payment_continue(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct command_result *
|
||||||
|
local_channel_hints_listpeers(struct command *cmd, const char *buffer,
|
||||||
|
const jsmntok_t *toks, struct payment *p)
|
||||||
|
{
|
||||||
|
const jsmntok_t *peers, *peer, *channels, *channel, *spendsats, *scid, *dir, *connected;
|
||||||
|
size_t i, j;
|
||||||
|
peers = json_get_member(buffer, toks, "peers");
|
||||||
|
|
||||||
|
if (peers == NULL)
|
||||||
|
goto done;
|
||||||
|
/* cppcheck-suppress uninitvar - cppcheck can't undestand these macros. */
|
||||||
|
json_for_each_arr(i, peer, peers) {
|
||||||
|
channels = json_get_member(buffer, peer, "channels");
|
||||||
|
if (channels == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
connected = json_get_member(buffer, peer, "connected");
|
||||||
|
|
||||||
|
json_for_each_arr(j, channel, channels) {
|
||||||
|
struct channel_hint h;
|
||||||
|
spendsats = json_get_member(buffer, channel, "spendable_msat");
|
||||||
|
scid = json_get_member(buffer, channel, "short_channel_id");
|
||||||
|
dir = json_get_member(buffer, channel, "direction");
|
||||||
|
assert(spendsats != NULL && scid != NULL && dir != NULL);
|
||||||
|
|
||||||
|
json_to_bool(buffer, connected, &h.enabled);
|
||||||
|
json_to_short_channel_id(buffer, scid, &h.scid.scid);
|
||||||
|
json_to_int(buffer, dir, &h.scid.dir);
|
||||||
|
|
||||||
|
json_to_msat(buffer, spendsats, &h.estimated_capacity);
|
||||||
|
tal_arr_expand(&p->channel_hints, h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
payment_continue(p);
|
||||||
|
return command_still_pending(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void local_channel_hints_cb(void *d UNUSED, struct payment *p)
|
||||||
|
{
|
||||||
|
struct out_req *req;
|
||||||
|
/* If we are not the root we don't look up the channel balances since
|
||||||
|
* it is unlikely that the capacities have changed much since the root
|
||||||
|
* payment looked at them. We also only call `listpeers` when the
|
||||||
|
* payment is in state PAYMENT_STEP_INITIALIZED, right before calling
|
||||||
|
* `getroute`. */
|
||||||
|
if (p->parent != NULL || p->step != PAYMENT_STEP_INITIALIZED)
|
||||||
|
return payment_continue(p);
|
||||||
|
|
||||||
|
req = jsonrpc_request_start(p->plugin, NULL, "listpeers",
|
||||||
|
local_channel_hints_listpeers,
|
||||||
|
local_channel_hints_listpeers, p);
|
||||||
|
send_outreq(p->plugin, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_PAYMENT_MODIFIER(local_channel_hints, void *, NULL, local_channel_hints_cb);
|
||||||
|
|||||||
@@ -66,8 +66,20 @@ struct payment_result {
|
|||||||
struct preimage *payment_preimage;
|
struct preimage *payment_preimage;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Relevant information about a local channel so we can exclude them early. */
|
/* Information about channels we inferred from a) looking at our channels, and
|
||||||
struct channel_status {
|
* 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 {
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Each payment goes through a number of steps that are always processed in
|
/* Each payment goes through a number of steps that are always processed in
|
||||||
@@ -168,6 +180,10 @@ struct payment {
|
|||||||
|
|
||||||
struct bolt11 *invoice;
|
struct bolt11 *invoice;
|
||||||
|
|
||||||
|
/* tal_arr of channel_hints we incrementally learn while performing
|
||||||
|
* payment attempts. */
|
||||||
|
struct channel_hint *channel_hints;
|
||||||
|
|
||||||
struct payment_result *result;
|
struct payment_result *result;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -210,6 +226,12 @@ struct retry_mod_data {
|
|||||||
extern struct payment_modifier dummy_pay_mod;
|
extern struct payment_modifier dummy_pay_mod;
|
||||||
REGISTER_PAYMENT_MODIFIER_HEADER(retry, struct retry_mod_data);
|
REGISTER_PAYMENT_MODIFIER_HEADER(retry, struct retry_mod_data);
|
||||||
|
|
||||||
|
/* For the root payment we can seed the channel_hints with the result from
|
||||||
|
* `listpeers`, hence avoid channels that we know have insufficient capacity
|
||||||
|
* or are disabled. We do this only for the root payment, to minimize the
|
||||||
|
* overhead. */
|
||||||
|
REGISTER_PAYMENT_MODIFIER_HEADER(local_channel_hints, void);
|
||||||
|
|
||||||
struct payment *payment_new(tal_t *ctx, struct command *cmd,
|
struct payment *payment_new(tal_t *ctx, struct command *cmd,
|
||||||
struct payment *parent,
|
struct payment *parent,
|
||||||
struct payment_modifier **mods);
|
struct payment_modifier **mods);
|
||||||
|
|||||||
@@ -1708,8 +1708,9 @@ static void init(struct plugin *p,
|
|||||||
maxdelay_default = atoi(field);
|
maxdelay_default = atoi(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct payment_modifier *paymod_mods[3] = {
|
struct payment_modifier *paymod_mods[4] = {
|
||||||
&dummy_pay_mod,
|
&dummy_pay_mod,
|
||||||
|
&local_channel_hints_pay_mod,
|
||||||
&retry_pay_mod,
|
&retry_pay_mod,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user