Skip to content

Commit 895652e

Browse files
committed
renepay: resolve self payments with fake node
Always use a fake destination node, the self-payments are no longer a corner case for the routing problem in this way. Also it is ok for get_routes to return routes with zero length. Changelog-None. Signed-off-by: Lagrang3 <[email protected]>
1 parent 7f5ffb4 commit 895652e

File tree

7 files changed

+48
-98
lines changed

7 files changed

+48
-98
lines changed

plugins/renepay/json.c

+2
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ struct payment_result *tal_sendpay_result_from_json(const tal_t *ctx,
7676
const char *buffer,
7777
const jsmntok_t *toks)
7878
{
79+
// FIXME: we will be getting onionreply try to decode these with
80+
// shared_secrets
7981
const jsmntok_t *idtok = json_get_member(buffer, toks, "created_index");
8082
const jsmntok_t *hashtok =
8183
json_get_member(buffer, toks, "payment_hash");

plugins/renepay/main.c

+11-13
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,6 @@ static struct command_result *json_pay(struct command *cmd, const char *buf,
344344

345345
pinfo->blinded_paths = NULL;
346346
pinfo->blinded_payinfos = NULL;
347-
payment->routing_destination = &pinfo->destination;
348347
} else {
349348
pinfo->payment_secret = NULL;
350349
pinfo->routehints = NULL;
@@ -370,19 +369,18 @@ static struct command_result *json_pay(struct command *cmd, const char *buf,
370369
max_final_cltv = final_cltv;
371370
}
372371
pinfo->final_cltv = max_final_cltv;
373-
374-
/* When dealing with BOLT12 blinded paths we compute the
375-
* routing targeting a fake node to enable
376-
* multi-destination minimum-cost-flow. Every blinded
377-
* path entry node will be linked to this fake node
378-
* using fake channels as well. */
379-
payment->routing_destination =
380-
tal(payment, struct node_id);
381-
if (!node_id_from_hexstr(
382-
"02""0000000000000000000000000000000000000000000000000000000000000001",
383-
66, payment->routing_destination))
384-
abort();
385372
}
373+
/* When dealing with BOLT12 blinded paths we compute the
374+
* routing targeting a fake node to enable
375+
* multi-destination minimum-cost-flow. Every blinded
376+
* path entry node will be linked to this fake node
377+
* using fake channels as well. This is also useful for
378+
* solving self-payments. */
379+
payment->routing_destination = tal(payment, struct node_id);
380+
if (!node_id_from_hexstr("0200000000000000000000000000000000000"
381+
"00000000000000000000000000001",
382+
66, payment->routing_destination))
383+
abort();
386384

387385
if (!payment_set_constraints(
388386
payment, *msat, *maxfee, *maxdelay, *retryfor,

plugins/renepay/mods.c

+23-82
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ static struct command_result *payment_rpc_failure(struct command *cmd,
9292
json_tok_full_len(toks), json_tok_full(buffer, toks));
9393
}
9494

95+
static void add_hintchan(struct payment *payment, const struct node_id *src,
96+
const struct node_id *dst, u16 cltv_expiry_delta,
97+
const struct short_channel_id scid, u32 fee_base_msat,
98+
u32 fee_proportional_millionths,
99+
const struct amount_msat *chan_htlc_min,
100+
const struct amount_msat *chan_htlc_max);
101+
95102
/*****************************************************************************
96103
* previoussuccess
97104
*
@@ -249,88 +256,23 @@ REGISTER_PAYMENT_MODIFIER(initial_sanity_checks, initial_sanity_checks_cb);
249256

250257
/*****************************************************************************
251258
* selfpay
252-
*
253-
* Checks if the payment destination is the sender's node and perform a self
254-
* payment.
255259
*/
256260

257-
static struct command_result *selfpay_success(struct command *cmd,
258-
const char *method UNUSED,
259-
const char *buf,
260-
const jsmntok_t *tok,
261-
struct payment *payment)
262-
{
263-
struct preimage preimage;
264-
const char *err;
265-
err = json_scan(tmpctx, buf, tok, "{payment_preimage:%}",
266-
JSON_SCAN(json_to_preimage, &preimage));
267-
if (err)
268-
plugin_err(
269-
cmd->plugin, "selfpay didn't have payment_preimage: %.*s",
270-
json_tok_full_len(tok), json_tok_full(buf, tok));
271-
272-
273-
payment_note(payment, LOG_DBG, "Paid with self-pay.");
274-
return payment_success(payment, &preimage);
275-
}
276-
static struct command_result *selfpay_failure(struct command *cmd,
277-
const char *method UNUSED,
278-
const char *buf,
279-
const jsmntok_t *tok,
280-
struct payment *payment)
281-
{
282-
struct payment_result *result =
283-
tal_sendpay_result_from_json(tmpctx, buf, tok);
284-
if (result == NULL) {
285-
plugin_log(pay_plugin->plugin, LOG_UNUSUAL,
286-
"Unable to parse sendpay failure: %.*s",
287-
json_tok_full_len(tok), json_tok_full(buf, tok));
288-
return payment_fail(payment, LIGHTNINGD,
289-
"Self pay failed for unknown reason");
290-
}
291-
return payment_fail(payment, result->code, "%s", result->message);
292-
}
293-
294261
static struct command_result *selfpay_cb(struct payment *payment)
295262
{
296-
if (!node_id_eq(&pay_plugin->my_id,
297-
&payment->payment_info.destination)) {
298-
return payment_continue(payment);
299-
}
300-
301-
struct command *cmd = payment_command(payment);
302-
if (!cmd)
303-
plugin_err(pay_plugin->plugin,
304-
"Selfpay: cannot get a valid cmd.");
305-
306-
struct payment_info *pinfo = &payment->payment_info;
307-
struct out_req *req;
308-
req = jsonrpc_request_start(cmd, "renesendpay", selfpay_success,
309-
selfpay_failure, payment);
310-
json_add_sha256(req->js, "payment_hash", &pinfo->payment_hash);
311-
json_add_u64(req->js, "partid", 0);
312-
json_add_u64(req->js, "groupid", payment->groupid);
313-
json_add_string(req->js, "invoice", pinfo->invstr);
314-
json_add_node_id(req->js, "destination", &pinfo->destination);
315-
json_add_amount_msat(req->js, "amount_msat", pinfo->amount);
316-
json_add_amount_msat(req->js, "total_amount_msat", pinfo->amount);
317-
json_add_u32(req->js, "final_cltv", pinfo->final_cltv);
318-
if (pinfo->label)
319-
json_add_string(req->js, "label", pinfo->label);
320-
if (pinfo->description)
321-
json_add_string(req->js, "description", pinfo->description);
322-
/* An empty route means a payment to oneself, pathlen=0 */
323-
json_array_start(req->js, "route");
324-
json_array_end(req->js);
325-
if (pinfo->payment_secret)
326-
json_add_secret(req->js, "payment_secret",
327-
pinfo->payment_secret);
328-
else {
329-
assert(pinfo->blinded_paths);
330-
const struct blinded_path *bpath = pinfo->blinded_paths[0];
331-
json_myadd_blinded_path(req->js, "blinded_path", bpath);
263+
/* A different approach to self-pay: create a fake channel from the
264+
* bolt11 destination to the routing_destination (a fake node_id). */
265+
if (!payment->payment_info.blinded_paths) {
266+
struct amount_msat htlc_min = AMOUNT_MSAT(0);
267+
struct amount_msat htlc_max = AMOUNT_MSAT((u64)1000*100000000);
268+
struct short_channel_id scid = {.u64 = 0};
269+
add_hintchan(payment, &payment->payment_info.destination,
270+
payment->routing_destination,
271+
/* cltv delta = */ 0, scid,
272+
/* base fee = */ 0,
273+
/* ppm = */ 0, &htlc_min, &htlc_max);
332274
}
333-
return send_outreq(req);
275+
return payment_continue(payment);
334276
}
335277

336278
REGISTER_PAYMENT_MODIFIER(selfpay, selfpay_cb);
@@ -755,8 +697,7 @@ static struct command_result *compute_routes_cb(struct payment *payment)
755697

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

761702
// TODO: add an algorithm selector here
762703
/* We let this return an unlikely path, as it's better to try once than
@@ -1291,9 +1232,9 @@ REGISTER_PAYMENT_CONDITION(retry, retry_cb);
12911232
// add check pre-approved invoice
12921233
void *payment_virtual_program[] = {
12931234
/*0*/ OP_CALL, &previoussuccess_pay_mod,
1294-
/*2*/ OP_CALL, &selfpay_pay_mod,
1295-
/*4*/ OP_CALL, &knowledgerelax_pay_mod,
1296-
/*6*/ OP_CALL, &getmychannels_pay_mod,
1235+
/*2*/ OP_CALL, &knowledgerelax_pay_mod,
1236+
/*4*/ OP_CALL, &getmychannels_pay_mod,
1237+
/*6*/ OP_CALL, &selfpay_pay_mod,
12971238
/*8*/ OP_CALL, &refreshgossmap_pay_mod,
12981239
/*10*/ OP_CALL, &routehints_pay_mod,
12991240
/*12*/ OP_CALL, &blindedhints_pay_mod,

plugins/renepay/route.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ static inline u32 route_delay(const struct route *route)
170170
{
171171
assert(route);
172172
assert(route->hops);
173-
assert(tal_count(route->hops) > 0);
173+
if (tal_count(route->hops) == 0)
174+
return 0;
174175
const size_t pathlen = tal_count(route->hops);
175176
assert(route->hops[0].delay >= route->hops[pathlen - 1].delay);
176177
return route->hops[0].delay - route->hops[pathlen - 1].delay;

plugins/renepay/routebuilder.c

+2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ route_check_constraints(struct route *route, struct gossmap *gossmap,
6565
assert(route);
6666
assert(route->hops);
6767
const size_t pathlen = tal_count(route->hops);
68+
if (pathlen == 0)
69+
return RENEPAY_NOERROR;
6870
if (!amount_msat_eq(route->amount_deliver,
6971
route->hops[pathlen - 1].amount))
7072
return RENEPAY_PRECONDITION_ERROR;

plugins/renepay/sendpay.c

-2
Original file line numberDiff line numberDiff line change
@@ -435,8 +435,6 @@ static struct command_result *waitblockheight_done(struct command *cmd,
435435
renesendpay->sent_amount);
436436
json_add_amount_msat(req->js, "destination_msat",
437437
renesendpay->deliver_amount);
438-
json_add_amount_msat(req->js, "destination_msat",
439-
renesendpay->deliver_amount);
440438
json_add_u32(req->js, "cltv_expiry",
441439
initial_cltv_delta(renesendpay) +
442440
renesendpay->blockheight);

tests/test_renepay.py

+8
Original file line numberDiff line numberDiff line change
@@ -848,3 +848,11 @@ def test_offers(node_factory):
848848
invoice = l1.rpc.fetchinvoice(offer)['invoice']
849849
response = l1.rpc.call("renepay", {"invstring": invoice})
850850
assert response["status"] == "complete"
851+
852+
853+
def test_offer_selfpay(node_factory):
854+
"""We can fetch an pay our own offer"""
855+
l1 = node_factory.get_node()
856+
offer = l1.rpc.offer(amount="2msat", description="test_offer_path_self")["bolt12"]
857+
inv = l1.rpc.fetchinvoice(offer)["invoice"]
858+
l1.rpc.call("renepay", {"invstring": inv})

0 commit comments

Comments
 (0)