mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 07:04:22 +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:
@@ -1770,19 +1770,14 @@ static bool routehint_excluded(struct payment *p,
|
|||||||
static struct route_info *next_routehint(struct routehints_data *d,
|
static struct route_info *next_routehint(struct routehints_data *d,
|
||||||
struct payment *p)
|
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 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++) {
|
for (size_t i=0; i<tal_count(d->routehints); i++) {
|
||||||
size_t curr = (offset + i) % (numhints + 1);
|
curr = d->routehints[(offset + i) % numhints];
|
||||||
if (curr == numhints)
|
if (curr == NULL || !routehint_excluded(p, curr))
|
||||||
return NULL;
|
return curr;
|
||||||
|
|
||||||
if (!routehint_excluded(p, d->routehints[curr]))
|
|
||||||
return d->routehints[i];
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1821,6 +1816,58 @@ static u32 route_cltv(u32 cltv,
|
|||||||
return 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)
|
static void routehint_step_cb(struct routehints_data *d, struct payment *p)
|
||||||
{
|
{
|
||||||
struct routehints_data *pd;
|
struct routehints_data *pd;
|
||||||
@@ -1837,6 +1884,14 @@ static void routehint_step_cb(struct routehints_data *d, struct payment *p)
|
|||||||
if (p->parent == NULL) {
|
if (p->parent == NULL) {
|
||||||
d->routehints = filter_routehints(d, p->local_id,
|
d->routehints = filter_routehints(d, p->local_id,
|
||||||
p->invoice->routes);
|
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 {
|
} else {
|
||||||
pd = payment_mod_get_data(p->parent,
|
pd = payment_mod_get_data(p->parent,
|
||||||
&routehints_pay_mod);
|
&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
|
* the root has filtered them we can just shared a
|
||||||
* pointer here. */
|
* pointer here. */
|
||||||
d->routehints = pd->routehints;
|
d->routehints = pd->routehints;
|
||||||
|
d->destination_reachable = pd->destination_reachable;
|
||||||
}
|
}
|
||||||
d->current_routehint = next_routehint(d, p);
|
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
|
/* 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. */
|
* what the final cltv delta was so we re-apply it correctly. */
|
||||||
u32 final_cltv;
|
u32 final_cltv;
|
||||||
|
|
||||||
|
/* Is the destination reachable without any routehints? */
|
||||||
|
bool destination_reachable;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct exemptfee_data {
|
struct exemptfee_data {
|
||||||
|
|||||||
Reference in New Issue
Block a user