Skip to content

Commit 2112f4f

Browse files
committed
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>
1 parent 37ddf2e commit 2112f4f

File tree

1 file changed

+62
-37
lines changed

1 file changed

+62
-37
lines changed

plugins/fetchinvoice.c

Lines changed: 62 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include <sodium.h>
2121

2222
static struct gossmap *global_gossmap;
23-
static struct node_id local_id;
23+
static struct pubkey local_id;
2424
static bool disable_connect = false;
2525
static LIST_HEAD(sent_list);
2626

@@ -33,8 +33,8 @@ struct sent {
3333
struct command *cmd;
3434
/* The offer we are trying to get an invoice/payment for. */
3535
struct tlv_offer *offer;
36-
/* Path to use. */
37-
struct node_id *path;
36+
/* Path to use (including self) */
37+
struct pubkey *path;
3838

3939
/* The invreq we sent, OR the invoice we sent */
4040
struct tlv_invoice_request *invreq;
@@ -567,18 +567,21 @@ static void node_id_from_pubkey32(struct node_id *nid,
567567
&node32_id->pubkey);
568568
}
569569

570-
/* Create path to node which can carry onion messages; if it can't find
571-
* one, returns NULL. Fills in nodeid_parity for 33rd nodeid byte. */
572-
static struct node_id *path_to_node(const tal_t *ctx,
573-
struct gossmap *gossmap,
574-
const struct pubkey32 *node32_id,
575-
enum nodeid_parity *parity)
570+
/* Create path to node which can carry onion messages (including
571+
* self); if it can't find one, returns NULL. Fills in nodeid_parity
572+
* for 33rd nodeid byte. */
573+
static struct pubkey *path_to_node(const tal_t *ctx,
574+
struct plugin *plugin,
575+
const struct pubkey32 *node32_id,
576+
enum nodeid_parity *parity)
576577
{
577578
struct route_hop *r;
578579
const struct dijkstra *dij;
579580
const struct gossmap_node *src;
580581
const struct gossmap_node *dst;
581-
struct node_id *nodes, dstid;
582+
struct node_id dstid, local_nodeid;
583+
struct pubkey *nodes;
584+
struct gossmap *gossmap = get_gossmap(plugin);
582585

583586
/* We try both parities. */
584587
*parity = nodeid_parity_even;
@@ -597,7 +600,8 @@ static struct node_id *path_to_node(const tal_t *ctx,
597600
*parity = node_parity(gossmap, dst);
598601

599602
/* If we don't exist in gossip, routing can't happen. */
600-
src = gossmap_find_node(gossmap, &local_id);
603+
node_id_from_pubkey(&local_nodeid, &local_id);
604+
src = gossmap_find_node(gossmap, &local_nodeid);
601605
if (!src)
602606
return NULL;
603607

@@ -608,9 +612,15 @@ static struct node_id *path_to_node(const tal_t *ctx,
608612
if (!r)
609613
return NULL;
610614

611-
nodes = tal_arr(ctx, struct node_id, tal_count(r));
612-
for (size_t i = 0; i < tal_count(r); i++)
613-
nodes[i] = r[i].node_id;
615+
nodes = tal_arr(ctx, struct pubkey, tal_count(r) + 1);
616+
nodes[0] = local_id;
617+
for (size_t i = 0; i < tal_count(r); i++) {
618+
if (!pubkey_from_node_id(&nodes[i+1], &r[i].node_id)) {
619+
plugin_err(plugin, "Could not convert nodeid %s",
620+
type_to_string(tmpctx, struct node_id,
621+
&r[i].node_id));
622+
}
623+
}
614624
return nodes;
615625
}
616626

@@ -631,19 +641,14 @@ static struct command_result *send_message(struct command *cmd,
631641
struct out_req *req;
632642

633643
/* FIXME: Maybe we should allow this? */
634-
if (tal_bytelen(sent->path) == 0)
644+
if (tal_count(sent->path) == 1)
635645
return command_fail(cmd, PAY_ROUTE_NOT_FOUND,
636646
"Refusing to talk to ourselves");
637647

638-
/* Reverse path is offset by one: we are the final node. */
639-
backwards = tal_arr(tmpctx, struct pubkey, tal_count(sent->path));
640-
for (size_t i = 0; i < tal_count(sent->path) - 1; i++) {
641-
if (!pubkey_from_node_id(&backwards[tal_count(sent->path)-2-i],
642-
&sent->path[i]))
643-
abort();
644-
}
645-
if (!pubkey_from_node_id(&backwards[tal_count(sent->path)-1], &local_id))
646-
abort();
648+
/* Reverse path is offset by one. */
649+
backwards = tal_arr(tmpctx, struct pubkey, tal_count(sent->path) - 1);
650+
for (size_t i = 0; i < tal_count(backwards); i++)
651+
backwards[tal_count(backwards)-1-i] = sent->path[i];
647652

648653
/* Ok, now make reply for onion_message */
649654
path = make_blindedpath(tmpctx, backwards, &blinding,
@@ -654,9 +659,9 @@ static struct command_result *send_message(struct command *cmd,
654659
forward_error,
655660
sent);
656661
json_array_start(req->js, "hops");
657-
for (size_t i = 0; i < tal_count(sent->path); i++) {
662+
for (size_t i = 1; i < tal_count(sent->path); i++) {
658663
json_object_start(req->js, NULL);
659-
json_add_node_id(req->js, "id", &sent->path[i]);
664+
json_add_pubkey(req->js, "id", &sent->path[i]);
660665
if (i == tal_count(sent->path) - 1)
661666
json_add_hex_talarr(req->js, msgfield, msgval);
662667
json_object_end(req->js);
@@ -757,7 +762,17 @@ static struct command_result *try_other_parity(struct command *cmd,
757762

758763
/* Flip parity */
759764
ca->node_id.k[0] = SECP256K1_TAG_PUBKEY_ODD;
760-
ca->sent->path[0] = ca->node_id;
765+
/* Path is us -> them, so they're second entry */
766+
if (!pubkey_from_node_id(&ca->sent->path[1], &ca->node_id)) {
767+
/* Should not happen!
768+
* Pieter Wuille points out:
769+
* y^2 = x^3 + 7 mod p
770+
* negating y doesn’t change the left hand side
771+
*/
772+
return command_done_err(cmd, LIGHTNINGD,
773+
"Failed: could not convert inverted pubkey?",
774+
NULL);
775+
}
761776
req = jsonrpc_request_start(cmd->plugin, cmd, "connect", connected,
762777
connect_failed, ca);
763778
json_add_node_id(req->js, "id", &ca->node_id);
@@ -797,8 +812,14 @@ connect_direct(struct command *cmd,
797812
}
798813

799814
/* Make a direct path -> dst. */
800-
sent->path = tal_arr(sent, struct node_id, 1);
801-
sent->path[0] = ca->node_id;
815+
sent->path = tal_arr(sent, struct pubkey, 2);
816+
sent->path[0] = local_id;
817+
if (!pubkey_from_node_id(&sent->path[1], &ca->node_id)) {
818+
/* Should not happen! */
819+
return command_done_err(cmd, LIGHTNINGD,
820+
"Failed: could not convert to pubkey?",
821+
NULL);
822+
}
802823

803824
if (disable_connect) {
804825
/* FIXME: This means we will fail if parity is wrong! */
@@ -918,7 +939,7 @@ static struct command_result *invreq_done(struct command *cmd,
918939
}
919940
}
920941

921-
sent->path = path_to_node(sent, get_gossmap(cmd->plugin),
942+
sent->path = path_to_node(sent, cmd->plugin,
922943
sent->offer->node_id,
923944
&parity);
924945
if (!sent->path)
@@ -978,7 +999,7 @@ force_payer_secret(struct command *cmd,
978999
"Failed to sign with payer_secret");
9791000
}
9801001

981-
sent->path = path_to_node(sent, get_gossmap(cmd->plugin),
1002+
sent->path = path_to_node(sent, cmd->plugin,
9821003
sent->offer->node_id,
9831004
&parity);
9841005
if (!sent->path)
@@ -1273,7 +1294,7 @@ static struct command_result *createinvoice_done(struct command *cmd,
12731294
"Bad createinvoice response %s", fail);
12741295
}
12751296

1276-
sent->path = path_to_node(sent, get_gossmap(cmd->plugin),
1297+
sent->path = path_to_node(sent, cmd->plugin,
12771298
sent->offer->node_id,
12781299
&parity);
12791300
if (!sent->path)
@@ -1455,9 +1476,13 @@ static struct command_result *json_sendinvoice(struct command *cmd,
14551476
* - MUST set `description` the same as the offer.
14561477
*/
14571478
sent->inv->node_id = tal(sent->inv, struct pubkey32);
1458-
if (!pubkey32_from_node_id(sent->inv->node_id, &local_id))
1459-
plugin_err(cmd->plugin, "Invalid local_id %s?",
1460-
type_to_string(tmpctx, struct node_id, &local_id));
1479+
1480+
/* This only fails if pubkey is invalid. */
1481+
if (!secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx,
1482+
&sent->inv->node_id->pubkey,
1483+
NULL,
1484+
&local_id.pubkey))
1485+
abort();
14611486

14621487
sent->inv->description
14631488
= tal_dup_talarr(sent->inv, char, sent->offer->description);
@@ -1633,7 +1658,7 @@ static struct command_result *json_rawrequest(struct command *cmd,
16331658
sent->cmd = cmd;
16341659
sent->offer = NULL;
16351660

1636-
sent->path = path_to_node(sent, get_gossmap(cmd->plugin),
1661+
sent->path = path_to_node(sent, cmd->plugin,
16371662
&node_id32,
16381663
&parity);
16391664
if (!sent->path) {
@@ -1680,7 +1705,7 @@ static const char *init(struct plugin *p, const char *buf UNUSED,
16801705

16811706
rpc_scan(p, "getinfo",
16821707
take(json_out_obj(NULL, NULL, NULL)),
1683-
"{id:%}", JSON_SCAN(json_to_node_id, &local_id));
1708+
"{id:%}", JSON_SCAN(json_to_pubkey, &local_id));
16841709

16851710
rpc_scan(p, "listconfigs",
16861711
take(json_out_obj(NULL, "config", "experimental-offers")),

0 commit comments

Comments
 (0)