renepay: make self payments with renesendpay

Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
This commit is contained in:
Lagrang3 2025-01-23 09:04:18 +01:00 committed by Rusty Russell
parent a04010c871
commit 74effa31d2
2 changed files with 91 additions and 49 deletions

View file

@ -258,13 +258,8 @@ static struct command_result *selfpay_success(struct command *cmd,
const char *method UNUSED,
const char *buf,
const jsmntok_t *tok,
struct route *route)
struct payment *payment)
{
tal_steal(tmpctx, route); // discard this route when tmpctx clears
struct payment *payment =
payment_map_get(pay_plugin->payment_map, route->key.payment_hash);
assert(payment);
struct preimage preimage;
const char *err;
err = json_scan(tmpctx, buf, tok, "{payment_preimage:%}",
@ -282,18 +277,17 @@ static struct command_result *selfpay_failure(struct command *cmd,
const char *method UNUSED,
const char *buf,
const jsmntok_t *tok,
struct route *route)
struct payment *payment)
{
tal_steal(tmpctx, route); // discard this route when tmpctx clears
struct payment *payment =
payment_map_get(pay_plugin->payment_map, route->key.payment_hash);
assert(payment);
struct payment_result *result = tal_sendpay_result_from_json(tmpctx, buf, tok);
if (result == NULL)
plugin_err(pay_plugin->plugin,
struct payment_result *result =
tal_sendpay_result_from_json(tmpctx, buf, tok);
if (result == NULL) {
plugin_log(pay_plugin->plugin, LOG_UNUSUAL,
"Unable to parse sendpay failure: %.*s",
json_tok_full_len(tok), json_tok_full(buf, tok));
return payment_fail(payment, LIGHTNINGD,
"Self pay failed for unknown reason");
}
return payment_fail(payment, result->code, "%s", result->message);
}
@ -310,17 +304,32 @@ static struct command_result *selfpay_cb(struct payment *payment)
"Selfpay: cannot get a valid cmd.");
struct payment_info *pinfo = &payment->payment_info;
/* Self-payment routes are not part of the routetracker, we build them
* on-the-fly here and release them on success or failure. */
struct route *route =
new_route(payment, payment->groupid,
/*partid=*/0, pinfo->payment_hash,
pinfo->amount, pinfo->amount);
struct out_req *req;
req = jsonrpc_request_start(cmd, "sendpay",
selfpay_success, selfpay_failure, route);
route->hops = tal_arr(route, struct route_hop, 0);
json_add_route(req->js, route, payment);
req = jsonrpc_request_start(cmd, "renesendpay", selfpay_success,
selfpay_failure, payment);
json_add_sha256(req->js, "payment_hash", &pinfo->payment_hash);
json_add_u64(req->js, "partid", 0);
json_add_u64(req->js, "groupid", payment->groupid);
json_add_string(req->js, "invoice", pinfo->invstr);
json_add_node_id(req->js, "destination", &pinfo->destination);
json_add_amount_msat(req->js, "amount_msat", pinfo->amount);
json_add_amount_msat(req->js, "total_amount_msat", pinfo->amount);
json_add_u32(req->js, "final_cltv", pinfo->final_cltv);
if (pinfo->label)
json_add_string(req->js, "label", pinfo->label);
if (pinfo->description)
json_add_string(req->js, "description", pinfo->description);
/* An empty route means a payment to oneself, pathlen=0 */
json_array_start(req->js, "route");
json_array_end(req->js);
if (pinfo->payment_secret)
json_add_secret(req->js, "payment_secret",
pinfo->payment_secret);
else {
assert(pinfo->blinded_paths);
const struct blinded_path *bpath = pinfo->blinded_paths[0];
json_myadd_blinded_path(req->js, "blinded_path", bpath);
}
return send_outreq(req);
}

View file

@ -145,7 +145,7 @@ static struct command_result *sendpay_rpc_failure(struct command *cmd,
json_to_u32(buffer, codetok, &errcode);
else
errcode = LIGHTNINGD;
// FIXME: make this response more useful, maybe similar to waitsendpay
return command_fail(
cmd, errcode, "renesendpay failed to error in RPC: %.*s",
json_tok_full_len(toks), json_tok_full(buffer, toks));
@ -297,6 +297,11 @@ static struct command_result *sendonion_done(struct command *cmd,
renesendpay->total_amount);
json_add_string(response, "invoice", renesendpay->invoice);
const jsmntok_t *preimagetok =
json_get_member(buffer, toks, "payment_preimage");
if (preimagetok)
json_add_tok(response, "payment_preimage", preimagetok, buffer);
if (renesendpay->label)
json_add_string(response, "label", renesendpay->label);
if (renesendpay->description)
@ -338,31 +343,55 @@ static struct command_result *waitblockheight_done(struct command *cmd,
const u8 *onion;
struct out_req *req;
onion =
create_onion(tmpctx, renesendpay, renesendpay->route[0].node_id, 1);
req = jsonrpc_request_start(cmd, "sendonion", sendonion_done,
sendpay_rpc_failure, renesendpay);
json_add_hex_talarr(req->js, "onion", onion);
if (tal_count(renesendpay->route) > 0) {
onion = create_onion(tmpctx, renesendpay,
renesendpay->route[0].node_id, 1);
req = jsonrpc_request_start(cmd, "sendonion", sendonion_done,
sendpay_rpc_failure, renesendpay);
json_add_hex_talarr(req->js, "onion", onion);
json_add_amount_msat(req->js, "amount_msat",
renesendpay->deliver_amount);
const struct route_hop *hop = &renesendpay->route[0];
json_object_start(req->js, "first_hop");
json_add_amount_msat(req->js, "amount_msat", hop->amount);
json_add_num(req->js, "delay",
hop->delay + renesendpay->blockheight);
json_add_node_id(req->js, "id", &hop->node_id);
json_add_short_channel_id(req->js, "channel", hop->scid);
json_object_end(req->js);
json_array_start(req->js, "shared_secrets");
for (size_t i = 0; i < tal_count(renesendpay->shared_secrets);
i++) {
json_add_secret(req->js, NULL,
&renesendpay->shared_secrets[i]);
}
json_array_end(req->js);
json_add_node_id(req->js, "destination",
&renesendpay->destination);
} else {
/* self payment */
onion = NULL;
req = jsonrpc_request_start(cmd, "sendpay", sendonion_done,
sendpay_rpc_failure, renesendpay);
json_array_start(req->js, "route");
json_array_end(req->js);
json_add_amount_msat(req->js, "amount_msat",
renesendpay->total_amount);
if(renesendpay->payment_secret)
json_add_secret(req->js, "payment_secret", renesendpay->payment_secret);
else{
// FIXME: get payment_secret from blinded path
}
}
json_add_sha256(req->js, "payment_hash", &renesendpay->payment_hash);
json_add_u64(req->js, "partid", renesendpay->partid);
json_add_u64(req->js, "groupid", renesendpay->groupid);
json_add_node_id(req->js, "destination", &renesendpay->destination);
json_add_amount_msat(req->js, "amount_msat", renesendpay->deliver_amount);
const struct route_hop *hop = &renesendpay->route[0];
json_object_start(req->js, "first_hop");
json_add_amount_msat(req->js, "amount_msat", hop->amount);
json_add_num(req->js, "delay", hop->delay + renesendpay->blockheight);
json_add_node_id(req->js, "id", &hop->node_id);
json_add_short_channel_id(req->js, "channel", hop->scid);
json_object_end(req->js);
json_array_start(req->js, "shared_secrets");
for (size_t i = 0; i < tal_count(renesendpay->shared_secrets); i++) {
json_add_secret(req->js, NULL, &renesendpay->shared_secrets[i]);
}
json_array_end(req->js);
if (renesendpay->label)
json_add_string(req->js, "label", renesendpay->label);
if (renesendpay->description)
@ -431,7 +460,11 @@ struct command_result *json_renesendpay(struct command *cmd,
renesendpay->partid = *partid;
renesendpay->groupid = *groupid;
renesendpay->sent_amount = renesendpay->route[0].amount;
if (tal_count(renesendpay->route) > 0)
renesendpay->sent_amount = renesendpay->route[0].amount;
else /* this might be a self pay */
renesendpay->sent_amount = *amount;
renesendpay->total_amount = *total_amount;
renesendpay->deliver_amount = *amount;
renesendpay->final_cltv = *final_cltv;