Skip to content

Commit

Permalink
renepay: enable routing through blinded paths
Browse files Browse the repository at this point in the history
Enable routing through blinded paths using fake channels in local
gossmods.

Changelog-None

Signed-off-by: Lagrang3 <[email protected]>
  • Loading branch information
Lagrang3 committed Jan 13, 2025
1 parent 7ef7c77 commit f75a73d
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 23 deletions.
13 changes: 13 additions & 0 deletions plugins/renepay/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ static struct command_result *json_pay(struct command *cmd, const char *buf,

pinfo->blinded_paths = NULL;
pinfo->blinded_payinfos = NULL;
payment->routing_destination = &pinfo->destination;
} else {
pinfo->payment_secret = NULL;
pinfo->routehints = NULL;
Expand All @@ -368,6 +369,18 @@ static struct command_result *json_pay(struct command *cmd, const char *buf,
max_final_cltv = final_cltv;
}
pinfo->final_cltv = max_final_cltv;

/* When dealing with BOLT12 blinded paths we compute the
* routing targeting a fake node to enable
* multi-destination minimum-cost-flow. Every blinded
* path entry node will be linked to this fake node
* using fake channels as well. */
payment->routing_destination =
tal(payment, struct node_id);
if (!node_id_from_hexstr(
"02""0000000000000000000000000000000000000000000000000000000000000001",
66, payment->routing_destination))
abort();
}

if (!payment_set_constraints(
Expand Down
88 changes: 73 additions & 15 deletions plugins/renepay/mods.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <plugins/renepay/routebuilder.h>
#include <plugins/renepay/routetracker.h>
#include <unistd.h>
#include <wire/bolt12_wiregen.h>

#define INVALID_ID UINT32_MAX

Expand Down Expand Up @@ -515,7 +516,9 @@ REGISTER_PAYMENT_MODIFIER(refreshgossmap, refreshgossmap_cb);
static void add_hintchan(struct payment *payment, const struct node_id *src,
const struct node_id *dst, u16 cltv_expiry_delta,
const struct short_channel_id scid, u32 fee_base_msat,
u32 fee_proportional_millionths)
u32 fee_proportional_millionths,
const struct amount_msat *chan_htlc_min,
const struct amount_msat *chan_htlc_max)
{
assert(payment);
assert(payment->local_gossmods);
Expand All @@ -528,6 +531,12 @@ static void add_hintchan(struct payment *payment, const struct node_id *src,
struct short_channel_id_dir scidd;
/* We assume any HTLC is allowed */
struct amount_msat htlc_min = AMOUNT_MSAT(0), htlc_max = MAX_CAPACITY;

if (chan_htlc_min)
htlc_min = *chan_htlc_min;
if (chan_htlc_max)
htlc_max = *chan_htlc_max;

struct amount_msat fee_base = amount_msat(fee_base_msat);
bool enabled = true;
scidd.scid = scid;
Expand Down Expand Up @@ -604,7 +613,8 @@ static struct command_result *routehints_done(struct command *cmd UNUSED,
add_hintchan(payment, &r[j].pubkey, end,
r[j].cltv_expiry_delta,
r[j].short_channel_id, r[j].fee_base_msat,
r[j].fee_proportional_millionths);
r[j].fee_proportional_millionths,
NULL, NULL);
end = &r[j].pubkey;
}
}
Expand All @@ -625,6 +635,8 @@ static struct command_result *routehints_done(struct command *cmd UNUSED,

static struct command_result *routehints_cb(struct payment *payment)
{
if (payment->payment_info.routehints == NULL)
return payment_continue(payment);
struct command *cmd = payment_command(payment);
assert(cmd);
struct out_req *req = jsonrpc_request_start(
Expand All @@ -636,6 +648,44 @@ static struct command_result *routehints_cb(struct payment *payment)

REGISTER_PAYMENT_MODIFIER(routehints, routehints_cb);


/*****************************************************************************
* blindedhints
*
* Similar to routehints but for bolt12 invoices: create fake channel that
* connect the blinded path entry point to the destination node.
*/

static struct command_result *blindedhints_cb(struct payment *payment)
{
if (payment->payment_info.blinded_paths == NULL)
return payment_continue(payment);

struct payment_info *pinfo = &payment->payment_info;
struct short_channel_id scid;
struct node_id src;

for (size_t i = 0; i < tal_count(pinfo->blinded_paths); i++) {
const struct blinded_payinfo *payinfo =
pinfo->blinded_payinfos[i];
const struct blinded_path *path = pinfo->blinded_paths[i];

scid.u64 = i; // a fake scid
node_id_from_pubkey(&src, &path->first_node_id.pubkey);

add_hintchan(payment, &src, payment->routing_destination,
payinfo->cltv_expiry_delta, scid,
payinfo->fee_base_msat,
payinfo->fee_proportional_millionths,
&payinfo->htlc_minimum_msat,
&payinfo->htlc_maximum_msat);
}
return payment_continue(payment);
}

REGISTER_PAYMENT_MODIFIER(blindedhints, blindedhints_cb);


/*****************************************************************************
* compute_routes
*
Expand Down Expand Up @@ -694,23 +744,30 @@ static struct command_result *compute_routes_cb(struct payment *payment)
* better to pass computed_routes as a reference? */
routetracker->computed_routes = tal_free(routetracker->computed_routes);

/* Send get_routes a note that it should discard the last hop because we
* are actually solving a multiple destinations problem. */
bool blinded_destination =
payment->payment_info.blinded_paths != NULL;

// TODO: add an algorithm selector here
/* We let this return an unlikely path, as it's better to try once than
* simply refuse. Plus, models are not truth! */
routetracker->computed_routes = get_routes(
routetracker,
&payment->payment_info,
&pay_plugin->my_id,
&payment->payment_info.destination,
payment->routing_destination,
pay_plugin->gossmap,
pay_plugin->uncertainty,
payment->disabledmap,
remaining,
feebudget,
&payment->next_partid,
payment->groupid,
blinded_destination,
&errcode,
&err_msg);

/* Otherwise the error message remains a child of the routetracker. */
err_msg = tal_steal(tmpctx, err_msg);

Expand Down Expand Up @@ -1230,20 +1287,21 @@ void *payment_virtual_program[] = {
/*6*/ OP_CALL, &getmychannels_pay_mod,
/*8*/ OP_CALL, &refreshgossmap_pay_mod,
/*10*/ OP_CALL, &routehints_pay_mod,
/*12*/OP_CALL, &channelfilter_pay_mod,
/*12*/ OP_CALL, &blindedhints_pay_mod,
/*14*/OP_CALL, &channelfilter_pay_mod,
// TODO shadow_additions
/* do */
/*14*/ OP_CALL, &pendingsendpays_pay_mod,
/*16*/ OP_CALL, &checktimeout_pay_mod,
/*18*/ OP_CALL, &refreshgossmap_pay_mod,
/*20*/ OP_CALL, &compute_routes_pay_mod,
/*22*/ OP_CALL, &send_routes_pay_mod,
/*16*/ OP_CALL, &pendingsendpays_pay_mod,
/*18*/ OP_CALL, &checktimeout_pay_mod,
/*20*/ OP_CALL, &refreshgossmap_pay_mod,
/*22*/ OP_CALL, &compute_routes_pay_mod,
/*24*/ OP_CALL, &send_routes_pay_mod,
/*do*/
/*24*/ OP_CALL, &sleep_pay_mod,
/*26*/ OP_CALL, &collect_results_pay_mod,
/*26*/ OP_CALL, &sleep_pay_mod,
/*28*/ OP_CALL, &collect_results_pay_mod,
/*while*/
/*28*/ OP_IF, &nothaveresults_pay_cond, (void *)24,
/*30*/ OP_IF, &nothaveresults_pay_cond, (void *)26,
/* while */
/*31*/ OP_IF, &retry_pay_cond, (void *)14,
/*34*/ OP_CALL, &end_pay_mod, /* safety net, default failure if reached */
/*36*/ NULL};
/*33*/ OP_IF, &retry_pay_cond, (void *)16,
/*36*/ OP_CALL, &end_pay_mod, /* safety net, default failure if reached */
/*38*/ NULL};
4 changes: 4 additions & 0 deletions plugins/renepay/payment.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ struct payment {
/* Localmods to apply to gossip_map for our own use. */
struct gossmap_localmods *local_gossmods;

/* Routes will be computed to reach this node, could be a fake node that
* we use to handle multiple blinded paths. */
struct node_id *routing_destination;

struct disabledmap *disabledmap;

/* Flag to indicate wether we have collected enough results to make a
Expand Down
13 changes: 11 additions & 2 deletions plugins/renepay/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct route *new_route(const tal_t *ctx, u32 groupid,

route->amount = amount;
route->amount_sent = amount_sent;
route->path_num = -1;
return route;
}

Expand All @@ -32,7 +33,8 @@ struct route *new_route(const tal_t *ctx, u32 groupid,
struct route *flow_to_route(const tal_t *ctx,
u32 groupid, u32 partid, struct sha256 payment_hash,
u32 final_cltv, struct gossmap *gossmap,
struct flow *flow)
struct flow *flow,
bool blinded_destination)
{
struct route *route =
new_route(ctx, groupid, partid, payment_hash,
Expand Down Expand Up @@ -67,6 +69,12 @@ struct route *flow_to_route(const tal_t *ctx,
route->success_prob = flow->success_prob;
route->amount = route->hops[pathlen - 1].amount;
route->amount_sent = route->hops[0].amount;

if (blinded_destination) {
route->path_num = route->hops[pathlen - 1].scid.u64;
tal_arr_remove(&route->hops, pathlen - 1);
}

return route;

function_fail:
Expand All @@ -85,7 +93,8 @@ struct route **flows_to_routes(const tal_t *ctx,
for (size_t i = 0; i < N; i++) {
routes[i] =
flow_to_route(routes, groupid, partid++,
payment_hash, final_cltv, gossmap, flows[i]);
payment_hash, final_cltv, gossmap, flows[i],
false);
if (!routes[i])
goto function_fail;
}
Expand Down
6 changes: 5 additions & 1 deletion plugins/renepay/route.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ struct route {

/* result of waitsenday */
struct payment_result *result;

/* blinded path index if any */
int path_num;
};

static inline struct routekey routekey(const struct sha256 *hash, u64 groupid,
Expand Down Expand Up @@ -117,7 +120,8 @@ struct route *new_route(const tal_t *ctx, u32 groupid,
struct route *flow_to_route(const tal_t *ctx,
u32 groupid, u32 partid, struct sha256 payment_hash,
u32 final_cltv, struct gossmap *gossmap,
struct flow *flow);
struct flow *flow,
bool blinded_destination);

struct route **flows_to_routes(const tal_t *ctx,
u32 groupid, u32 partid,
Expand Down
4 changes: 3 additions & 1 deletion plugins/renepay/routebuilder.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ struct route **get_routes(const tal_t *ctx,

u64 *next_partid,
u64 groupid,
bool blinded_destination,

enum jsonrpc_errcode *ecode,
const char **fail)
Expand Down Expand Up @@ -297,7 +298,8 @@ struct route **get_routes(const tal_t *ctx,
struct route *r = flow_to_route(
this_ctx, groupid, *next_partid,
payment_info->payment_hash,
payment_info->final_cltv, gossmap, flows[i]);
payment_info->final_cltv, gossmap, flows[i],
blinded_destination);

if (!r) {
tal_report_error(
Expand Down
1 change: 1 addition & 0 deletions plugins/renepay/routebuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ struct route **get_routes(const tal_t *ctx,

u64 *next_partid,
u64 groupid,
bool blinded_destination,

enum jsonrpc_errcode *ecode,
const char **fail);
Expand Down
1 change: 1 addition & 0 deletions plugins/renepay/test/run-bottleneck.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ int main(int argc, char *argv[])
/* feebudget */maxfee,
&next_partid,
groupid,
false,
&errcode,
&err_msg);

Expand Down
8 changes: 4 additions & 4 deletions plugins/renepay/test/run-testflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,7 @@ static void test_flow_to_route(void)
F->dirs[0]=0;
deliver = AMOUNT_MSAT(250000000);
F->amount = deliver;
route = flow_to_route(this_ctx, 1, 1, payment_hash, 0, gossmap, F);
route = flow_to_route(this_ctx, 1, 1, payment_hash, 0, gossmap, F, false);
assert(route);

assert(amount_msat_eq(route->hops[0].amount, deliver));
Expand All @@ -707,7 +707,7 @@ static void test_flow_to_route(void)
F->dirs[1]=0;
deliver = AMOUNT_MSAT(250000000);
F->amount=deliver;
route = flow_to_route(this_ctx, 1, 1, payment_hash, 0, gossmap, F);
route = flow_to_route(this_ctx, 1, 1, payment_hash, 0, gossmap, F, false);
assert(route);

assert(amount_msat_eq(route->hops[0].amount, amount_msat(250050016)));
Expand All @@ -725,7 +725,7 @@ static void test_flow_to_route(void)
F->dirs[2]=0;
deliver = AMOUNT_MSAT(250000000);
F->amount=deliver;
route = flow_to_route(this_ctx, 1, 1, payment_hash, 0, gossmap, F);
route = flow_to_route(this_ctx, 1, 1, payment_hash, 0, gossmap, F, false);
assert(route);

assert(amount_msat_eq(route->hops[0].amount, amount_msat(250087534)));
Expand All @@ -745,7 +745,7 @@ static void test_flow_to_route(void)
F->dirs[3]=0;
deliver = AMOUNT_MSAT(250000000);
F->amount=deliver;
route = flow_to_route(this_ctx, 1, 1, payment_hash, 0, gossmap, F);
route = flow_to_route(this_ctx, 1, 1, payment_hash, 0, gossmap, F, false);
assert(route);

assert(amount_msat_eq(route->hops[0].amount, amount_msat(250112544)));
Expand Down

0 comments on commit f75a73d

Please sign in to comment.