fetchinvoice: include send in path, use pubkeys.

We had sent->path be a list of node_ids, but it makes more sense as
pubkeys so we can avoid conversion.  Also, I find it easier to think
about (especially creating backwards paths) if we include *ourselves*
as the first element in the path.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2021-09-21 14:53:45 +09:30
parent 37ddf2e829
commit 2112f4fd8e

View File

@@ -20,7 +20,7 @@
#include <sodium.h> #include <sodium.h>
static struct gossmap *global_gossmap; static struct gossmap *global_gossmap;
static struct node_id local_id; static struct pubkey local_id;
static bool disable_connect = false; static bool disable_connect = false;
static LIST_HEAD(sent_list); static LIST_HEAD(sent_list);
@@ -33,8 +33,8 @@ struct sent {
struct command *cmd; struct command *cmd;
/* The offer we are trying to get an invoice/payment for. */ /* The offer we are trying to get an invoice/payment for. */
struct tlv_offer *offer; struct tlv_offer *offer;
/* Path to use. */ /* Path to use (including self) */
struct node_id *path; struct pubkey *path;
/* The invreq we sent, OR the invoice we sent */ /* The invreq we sent, OR the invoice we sent */
struct tlv_invoice_request *invreq; struct tlv_invoice_request *invreq;
@@ -567,10 +567,11 @@ static void node_id_from_pubkey32(struct node_id *nid,
&node32_id->pubkey); &node32_id->pubkey);
} }
/* Create path to node which can carry onion messages; if it can't find /* Create path to node which can carry onion messages (including
* one, returns NULL. Fills in nodeid_parity for 33rd nodeid byte. */ * self); if it can't find one, returns NULL. Fills in nodeid_parity
static struct node_id *path_to_node(const tal_t *ctx, * for 33rd nodeid byte. */
struct gossmap *gossmap, static struct pubkey *path_to_node(const tal_t *ctx,
struct plugin *plugin,
const struct pubkey32 *node32_id, const struct pubkey32 *node32_id,
enum nodeid_parity *parity) enum nodeid_parity *parity)
{ {
@@ -578,7 +579,9 @@ static struct node_id *path_to_node(const tal_t *ctx,
const struct dijkstra *dij; const struct dijkstra *dij;
const struct gossmap_node *src; const struct gossmap_node *src;
const struct gossmap_node *dst; const struct gossmap_node *dst;
struct node_id *nodes, dstid; struct node_id dstid, local_nodeid;
struct pubkey *nodes;
struct gossmap *gossmap = get_gossmap(plugin);
/* We try both parities. */ /* We try both parities. */
*parity = nodeid_parity_even; *parity = nodeid_parity_even;
@@ -597,7 +600,8 @@ static struct node_id *path_to_node(const tal_t *ctx,
*parity = node_parity(gossmap, dst); *parity = node_parity(gossmap, dst);
/* If we don't exist in gossip, routing can't happen. */ /* If we don't exist in gossip, routing can't happen. */
src = gossmap_find_node(gossmap, &local_id); node_id_from_pubkey(&local_nodeid, &local_id);
src = gossmap_find_node(gossmap, &local_nodeid);
if (!src) if (!src)
return NULL; return NULL;
@@ -608,9 +612,15 @@ static struct node_id *path_to_node(const tal_t *ctx,
if (!r) if (!r)
return NULL; return NULL;
nodes = tal_arr(ctx, struct node_id, tal_count(r)); nodes = tal_arr(ctx, struct pubkey, tal_count(r) + 1);
for (size_t i = 0; i < tal_count(r); i++) nodes[0] = local_id;
nodes[i] = r[i].node_id; for (size_t i = 0; i < tal_count(r); i++) {
if (!pubkey_from_node_id(&nodes[i+1], &r[i].node_id)) {
plugin_err(plugin, "Could not convert nodeid %s",
type_to_string(tmpctx, struct node_id,
&r[i].node_id));
}
}
return nodes; return nodes;
} }
@@ -631,19 +641,14 @@ static struct command_result *send_message(struct command *cmd,
struct out_req *req; struct out_req *req;
/* FIXME: Maybe we should allow this? */ /* FIXME: Maybe we should allow this? */
if (tal_bytelen(sent->path) == 0) if (tal_count(sent->path) == 1)
return command_fail(cmd, PAY_ROUTE_NOT_FOUND, return command_fail(cmd, PAY_ROUTE_NOT_FOUND,
"Refusing to talk to ourselves"); "Refusing to talk to ourselves");
/* Reverse path is offset by one: we are the final node. */ /* Reverse path is offset by one. */
backwards = tal_arr(tmpctx, struct pubkey, tal_count(sent->path)); backwards = tal_arr(tmpctx, struct pubkey, tal_count(sent->path) - 1);
for (size_t i = 0; i < tal_count(sent->path) - 1; i++) { for (size_t i = 0; i < tal_count(backwards); i++)
if (!pubkey_from_node_id(&backwards[tal_count(sent->path)-2-i], backwards[tal_count(backwards)-1-i] = sent->path[i];
&sent->path[i]))
abort();
}
if (!pubkey_from_node_id(&backwards[tal_count(sent->path)-1], &local_id))
abort();
/* Ok, now make reply for onion_message */ /* Ok, now make reply for onion_message */
path = make_blindedpath(tmpctx, backwards, &blinding, path = make_blindedpath(tmpctx, backwards, &blinding,
@@ -654,9 +659,9 @@ static struct command_result *send_message(struct command *cmd,
forward_error, forward_error,
sent); sent);
json_array_start(req->js, "hops"); json_array_start(req->js, "hops");
for (size_t i = 0; i < tal_count(sent->path); i++) { for (size_t i = 1; i < tal_count(sent->path); i++) {
json_object_start(req->js, NULL); json_object_start(req->js, NULL);
json_add_node_id(req->js, "id", &sent->path[i]); json_add_pubkey(req->js, "id", &sent->path[i]);
if (i == tal_count(sent->path) - 1) if (i == tal_count(sent->path) - 1)
json_add_hex_talarr(req->js, msgfield, msgval); json_add_hex_talarr(req->js, msgfield, msgval);
json_object_end(req->js); json_object_end(req->js);
@@ -757,7 +762,17 @@ static struct command_result *try_other_parity(struct command *cmd,
/* Flip parity */ /* Flip parity */
ca->node_id.k[0] = SECP256K1_TAG_PUBKEY_ODD; ca->node_id.k[0] = SECP256K1_TAG_PUBKEY_ODD;
ca->sent->path[0] = ca->node_id; /* Path is us -> them, so they're second entry */
if (!pubkey_from_node_id(&ca->sent->path[1], &ca->node_id)) {
/* Should not happen!
* Pieter Wuille points out:
* y^2 = x^3 + 7 mod p
* negating y doesnt change the left hand side
*/
return command_done_err(cmd, LIGHTNINGD,
"Failed: could not convert inverted pubkey?",
NULL);
}
req = jsonrpc_request_start(cmd->plugin, cmd, "connect", connected, req = jsonrpc_request_start(cmd->plugin, cmd, "connect", connected,
connect_failed, ca); connect_failed, ca);
json_add_node_id(req->js, "id", &ca->node_id); json_add_node_id(req->js, "id", &ca->node_id);
@@ -797,8 +812,14 @@ connect_direct(struct command *cmd,
} }
/* Make a direct path -> dst. */ /* Make a direct path -> dst. */
sent->path = tal_arr(sent, struct node_id, 1); sent->path = tal_arr(sent, struct pubkey, 2);
sent->path[0] = ca->node_id; sent->path[0] = local_id;
if (!pubkey_from_node_id(&sent->path[1], &ca->node_id)) {
/* Should not happen! */
return command_done_err(cmd, LIGHTNINGD,
"Failed: could not convert to pubkey?",
NULL);
}
if (disable_connect) { if (disable_connect) {
/* FIXME: This means we will fail if parity is wrong! */ /* FIXME: This means we will fail if parity is wrong! */
@@ -918,7 +939,7 @@ static struct command_result *invreq_done(struct command *cmd,
} }
} }
sent->path = path_to_node(sent, get_gossmap(cmd->plugin), sent->path = path_to_node(sent, cmd->plugin,
sent->offer->node_id, sent->offer->node_id,
&parity); &parity);
if (!sent->path) if (!sent->path)
@@ -978,7 +999,7 @@ force_payer_secret(struct command *cmd,
"Failed to sign with payer_secret"); "Failed to sign with payer_secret");
} }
sent->path = path_to_node(sent, get_gossmap(cmd->plugin), sent->path = path_to_node(sent, cmd->plugin,
sent->offer->node_id, sent->offer->node_id,
&parity); &parity);
if (!sent->path) if (!sent->path)
@@ -1273,7 +1294,7 @@ static struct command_result *createinvoice_done(struct command *cmd,
"Bad createinvoice response %s", fail); "Bad createinvoice response %s", fail);
} }
sent->path = path_to_node(sent, get_gossmap(cmd->plugin), sent->path = path_to_node(sent, cmd->plugin,
sent->offer->node_id, sent->offer->node_id,
&parity); &parity);
if (!sent->path) if (!sent->path)
@@ -1455,9 +1476,13 @@ static struct command_result *json_sendinvoice(struct command *cmd,
* - MUST set `description` the same as the offer. * - MUST set `description` the same as the offer.
*/ */
sent->inv->node_id = tal(sent->inv, struct pubkey32); sent->inv->node_id = tal(sent->inv, struct pubkey32);
if (!pubkey32_from_node_id(sent->inv->node_id, &local_id))
plugin_err(cmd->plugin, "Invalid local_id %s?", /* This only fails if pubkey is invalid. */
type_to_string(tmpctx, struct node_id, &local_id)); if (!secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx,
&sent->inv->node_id->pubkey,
NULL,
&local_id.pubkey))
abort();
sent->inv->description sent->inv->description
= tal_dup_talarr(sent->inv, char, sent->offer->description); = tal_dup_talarr(sent->inv, char, sent->offer->description);
@@ -1633,7 +1658,7 @@ static struct command_result *json_rawrequest(struct command *cmd,
sent->cmd = cmd; sent->cmd = cmd;
sent->offer = NULL; sent->offer = NULL;
sent->path = path_to_node(sent, get_gossmap(cmd->plugin), sent->path = path_to_node(sent, cmd->plugin,
&node_id32, &node_id32,
&parity); &parity);
if (!sent->path) { if (!sent->path) {
@@ -1680,7 +1705,7 @@ static const char *init(struct plugin *p, const char *buf UNUSED,
rpc_scan(p, "getinfo", rpc_scan(p, "getinfo",
take(json_out_obj(NULL, NULL, NULL)), take(json_out_obj(NULL, NULL, NULL)),
"{id:%}", JSON_SCAN(json_to_node_id, &local_id)); "{id:%}", JSON_SCAN(json_to_pubkey, &local_id));
rpc_scan(p, "listconfigs", rpc_scan(p, "listconfigs",
take(json_out_obj(NULL, "config", "experimental-offers")), take(json_out_obj(NULL, "config", "experimental-offers")),