mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
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:
@@ -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 doesn’t 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")),
|
||||||
|
|||||||
Reference in New Issue
Block a user