mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 13:25:43 +01:00
paymod: Check if destination is reachable at all directly at startup
This does two things: it checks if the destination of the payment is at all reachable without routehints, and if it is it adds a direct attempt as option to the routehints in the form of a NULL routehint. It also simplifies the selection of the routehint since the direct case is no longer special, instead we just return a NULL routehint as if it were a normal routehint.
This commit is contained in:
parent
497b18ba33
commit
b78aa3fb25
@ -1770,19 +1770,14 @@ static bool routehint_excluded(struct payment *p,
|
||||
static struct route_info *next_routehint(struct routehints_data *d,
|
||||
struct payment *p)
|
||||
{
|
||||
/* Implements a random selection of a routehint, or none in 1/numhints
|
||||
* cases, by starting the iteration of the routehints in a random
|
||||
* order, and adding a virtual NULL result at the end. */
|
||||
size_t numhints = tal_count(d->routehints);
|
||||
size_t offset = pseudorand(numhints + 1);
|
||||
size_t offset = pseudorand(numhints);
|
||||
struct route_info *curr;
|
||||
|
||||
for (size_t i=0; i<tal_count(d->routehints); i++) {
|
||||
size_t curr = (offset + i) % (numhints + 1);
|
||||
if (curr == numhints)
|
||||
return NULL;
|
||||
|
||||
if (!routehint_excluded(p, d->routehints[curr]))
|
||||
return d->routehints[i];
|
||||
curr = d->routehints[(offset + i) % numhints];
|
||||
if (curr == NULL || !routehint_excluded(p, curr))
|
||||
return curr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -1821,6 +1816,58 @@ static u32 route_cltv(u32 cltv,
|
||||
return cltv;
|
||||
}
|
||||
|
||||
static struct command_result *routehint_getroute_result(struct command *cmd,
|
||||
const char *buffer,
|
||||
const jsmntok_t *toks,
|
||||
struct payment *p)
|
||||
{
|
||||
struct payment *root = payment_root(p);
|
||||
const jsmntok_t *rtok = json_get_member(buffer, toks, "route");
|
||||
struct routehints_data *d = payment_mod_routehints_get_data(root);
|
||||
|
||||
/* If there was a route the destination is reachable without
|
||||
* routehints. */
|
||||
d->destination_reachable = (rtok != NULL);
|
||||
|
||||
if (d->destination_reachable)
|
||||
tal_arr_expand(&d->routehints, NULL);
|
||||
|
||||
d->current_routehint = next_routehint(d, p);
|
||||
|
||||
plugin_log(p->plugin, LOG_DBG,
|
||||
"The destination is%s directly reachable %s attempts "
|
||||
"without routehints",
|
||||
d->destination_reachable ? "" : " not",
|
||||
d->destination_reachable ? "including" : "excluding");
|
||||
|
||||
/* Now we can continue on our merry way. */
|
||||
payment_continue(p);
|
||||
|
||||
/* Let payment_finished_ handle this, so we mark it as pending */
|
||||
return command_still_pending(cmd);
|
||||
}
|
||||
|
||||
static void routehint_check_reachable(struct payment *p)
|
||||
{
|
||||
struct out_req *req;
|
||||
/* Start a tiny exploratory getroute request, so we
|
||||
* know whether we stand any chance of reaching the
|
||||
* destination without routehints. This will later be
|
||||
* used to mix in attempts without routehints. */
|
||||
req = jsonrpc_request_start(p->plugin, NULL, "getroute",
|
||||
routehint_getroute_result,
|
||||
routehint_getroute_result, p);
|
||||
json_add_node_id(req->js, "id", p->destination);
|
||||
json_add_amount_msat_only(req->js, "msatoshi", AMOUNT_MSAT(1000));
|
||||
json_add_num(req->js, "maxhops", 20);
|
||||
json_add_num(req->js, "riskfactor", 10);
|
||||
send_outreq(p->plugin, req);
|
||||
plugin_log(p->plugin, LOG_DBG,
|
||||
"Asking gossipd whether %s is reachable "
|
||||
"without routehints.",
|
||||
type_to_string(tmpctx, struct node_id, p->destination));
|
||||
}
|
||||
|
||||
static void routehint_step_cb(struct routehints_data *d, struct payment *p)
|
||||
{
|
||||
struct routehints_data *pd;
|
||||
@ -1837,6 +1884,14 @@ static void routehint_step_cb(struct routehints_data *d, struct payment *p)
|
||||
if (p->parent == NULL) {
|
||||
d->routehints = filter_routehints(d, p->local_id,
|
||||
p->invoice->routes);
|
||||
|
||||
plugin_log(p->plugin, LOG_DBG,
|
||||
"After filtering routehints we're left with "
|
||||
"%zu usable hints",
|
||||
tal_count(d->routehints));
|
||||
/* Do not continue normally, instead go and check if
|
||||
* we can reach the destination directly. */
|
||||
return routehint_check_reachable(p);
|
||||
} else {
|
||||
pd = payment_mod_get_data(p->parent,
|
||||
&routehints_pay_mod);
|
||||
@ -1844,6 +1899,7 @@ static void routehint_step_cb(struct routehints_data *d, struct payment *p)
|
||||
* the root has filtered them we can just shared a
|
||||
* pointer here. */
|
||||
d->routehints = pd->routehints;
|
||||
d->destination_reachable = pd->destination_reachable;
|
||||
}
|
||||
d->current_routehint = next_routehint(d, p);
|
||||
|
||||
|
@ -299,6 +299,9 @@ struct routehints_data {
|
||||
/* We modify the CLTV in the getroute call, so we need to remember
|
||||
* what the final cltv delta was so we re-apply it correctly. */
|
||||
u32 final_cltv;
|
||||
|
||||
/* Is the destination reachable without any routehints? */
|
||||
bool destination_reachable;
|
||||
};
|
||||
|
||||
struct exemptfee_data {
|
||||
|
Loading…
Reference in New Issue
Block a user