diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index f1b7ba6e5..94861b1c6 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -489,14 +489,9 @@ static void payment_getroute_add_excludes(struct payment *p, json_add_node_id(js, NULL, &nodes[i]); /* And make sure we don't route in a circle via the routehint! */ - if (p->temp_exclusion) { - struct short_channel_id_dir scidd; - scidd.scid = *p->temp_exclusion; - for (size_t dir = 0; dir < 2; dir++) { - scidd.dir = dir; - json_add_short_channel_id_dir(js, NULL, &scidd); - } - } + if (p->temp_exclusion) + for (size_t i = 0; i < tal_count(p->temp_exclusion); ++i) + json_add_string(js, NULL, p->temp_exclusion[i]); json_array_end(js); } @@ -1841,6 +1836,47 @@ static u32 route_cltv(u32 cltv, return cltv; } +/** routehint_generate_exclusion_list + * + * @brief generate a list of items to append to `excludes` + * parameter of `getroute`. + * + * @param ctx - the context to allocate off of. + * @param routehint - the actual routehint, a `tal` array. + * @param payment - the payment that we will create an + * exclusion list for. + * + * @return an array of strings that will be appended to the + * `excludes` parameter of `getroute`. + */ +static +const char **routehint_generate_exclusion_list(const tal_t *ctx, + struct route_info *routehint, + struct payment *payment) +{ + const char **exc; + size_t i; + + if (!routehint || tal_count(routehint) == 0) + /* Nothing to exclude. */ + return NULL; + + exc = tal_arr(ctx, const char *, 0); + /* Exclude every node except the first, because the first is + * the entry point to the routehint. */ + for (i = 1 /* Skip the first! */; i < tal_count(routehint); ++i) + tal_arr_expand(&exc, + type_to_string(exc, struct node_id, + &routehint[i].pubkey)); + /* Also exclude the destination, because it would be foolish to + * pass through it and *then* go to the routehint entry point. */ + tal_arr_expand(&exc, + type_to_string(exc, struct node_id, + payment->destination)); + + return exc; +} + /* Change the destination and compute the final msatoshi amount to send to the * routehint entry point. */ static void routehint_pre_getroute(struct routehints_data *d, struct payment *p) @@ -1853,6 +1889,8 @@ static void routehint_pre_getroute(struct routehints_data *d, struct payment *p) have_more = (d->offset < tal_count(d->routehints) - 1); p->failroute_retry = have_more; + p->temp_exclusion = tal_free(p->temp_exclusion); + if (d->current_routehint != NULL) { if (!route_msatoshi(&p->getroute->amount, p->amount, d->current_routehint, @@ -1873,11 +1911,9 @@ static void routehint_pre_getroute(struct routehints_data *d, struct payment *p) /* Exclude the entrypoint to the routehint, so we don't end up * going through the destination to the entrypoint. */ - p->temp_exclusion = &d->current_routehint[0].short_channel_id; - } else { + p->temp_exclusion = routehint_generate_exclusion_list(p, d->current_routehint, p); + } else plugin_log(p->plugin, LOG_DBG, "Not using a routehint"); - p->temp_exclusion = NULL; - } } static struct command_result *routehint_getroute_result(struct command *cmd, diff --git a/plugins/libplugin-pay.h b/plugins/libplugin-pay.h index b6e3a52be..a8a2ebef6 100644 --- a/plugins/libplugin-pay.h +++ b/plugins/libplugin-pay.h @@ -232,8 +232,8 @@ struct payment { struct channel_hint *channel_hints; struct node_id *excluded_nodes; - /* Optional temporarily excluded channel (i.e. this routehint) */ - struct short_channel_id *temp_exclusion; + /* Optional temporarily excluded channels/nodes (i.e. this routehint) */ + const char **temp_exclusion; struct payment_result *result;