Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 21 additions & 11 deletions plugins/fetchinvoice.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@ static struct command_result *establish_path_fail(struct command *cmd,
static struct command_result *try_establish(struct command *cmd,
struct establishing_paths *epaths)
{
const struct offers_data *od = get_offers_data(cmd->plugin);
struct pubkey target;

if (epaths->sent->direct_dest) {
Expand All @@ -614,8 +615,8 @@ static struct command_result *try_establish(struct command *cmd,
epaths->sent->issuer_key = &bpath->path[tal_count(bpath->path)-1]->blinded_node_id;
}

return establish_onion_path(cmd, get_gossmap(cmd->plugin), &id, &target,
disable_connect,
return establish_onion_path(cmd, get_gossmap(cmd->plugin), &od->id, &target,
od->disable_connect,
establish_path_done,
establish_path_fail,
epaths);
Expand Down Expand Up @@ -824,15 +825,16 @@ static struct command_result *param_dev_reply_path(struct command *cmd, const ch
return NULL;
}

static bool payer_key(const u8 *public_tweak, size_t public_tweak_len,
static bool payer_key(const struct offers_data *od,
const u8 *public_tweak, size_t public_tweak_len,
struct pubkey *key)
{
struct sha256 tweakhash;

bolt12_alias_tweak(&nodealias_base, public_tweak, public_tweak_len,
bolt12_alias_tweak(&od->nodealias_base, public_tweak, public_tweak_len,
&tweakhash);

*key = id;
*key = od->id;
return secp256k1_ec_pubkey_tweak_add(secp256k1_ctx,
&key->pubkey,
tweakhash.u.u8) == 1;
Expand All @@ -845,6 +847,7 @@ static bool payer_key(const u8 *public_tweak, size_t public_tweak_len,
* as payer_id must be same for all recurring payments. */
static u8 *recurrence_invreq_metadata(const tal_t *ctx,
const struct tlv_invoice_request *invreq,
const struct secret *nodealias_base,
const char *rec_label)
{
struct sha256 offer_id, tweak;
Expand All @@ -859,7 +862,7 @@ static u8 *recurrence_invreq_metadata(const tal_t *ctx,
rec_label,
strlen(rec_label));

bolt12_alias_tweak(&nodealias_base,
bolt12_alias_tweak(nodealias_base,
tweak_input,
tal_bytelen(tweak_input),
&tweak);
Expand Down Expand Up @@ -906,6 +909,7 @@ struct command_result *json_fetchinvoice(struct command *cmd,
const char *buffer,
const jsmntok_t *params)
{
const struct offers_data *od = get_offers_data(cmd->plugin);
struct amount_msat *msat;
const char *rec_label, *payer_note;
u8 *payer_metadata;
Expand Down Expand Up @@ -1063,7 +1067,9 @@ struct command_result *json_fetchinvoice(struct command *cmd,
"needs recurrence_label");

invreq->invreq_metadata
= recurrence_invreq_metadata(invreq, invreq, rec_label);
= recurrence_invreq_metadata(invreq, invreq,
&od->nodealias_base,
rec_label);
} else {
/* BOLT-recurrence #12:
* - otherwise:
Expand Down Expand Up @@ -1097,7 +1103,7 @@ struct command_result *json_fetchinvoice(struct command *cmd,

/* We derive transient payer_id from invreq_metadata */
invreq->invreq_payer_id = tal(invreq, struct pubkey);
if (!payer_key(invreq->invreq_metadata,
if (!payer_key(od, invreq->invreq_metadata,
tal_bytelen(invreq->invreq_metadata),
invreq->invreq_payer_id)) {
/* Doesn't happen! */
Expand Down Expand Up @@ -1155,6 +1161,7 @@ struct command_result *json_cancelrecurringinvoice(struct command *cmd,
const char *buffer,
const jsmntok_t *params)
{
const struct offers_data *od = get_offers_data(cmd->plugin);
const char *rec_label, *payer_note;
struct out_req *req;
struct tlv_invoice_request *invreq;
Expand Down Expand Up @@ -1229,11 +1236,13 @@ struct command_result *json_cancelrecurringinvoice(struct command *cmd,
}

invreq->invreq_metadata
= recurrence_invreq_metadata(invreq, invreq, rec_label);
= recurrence_invreq_metadata(invreq, invreq,
&od->nodealias_base,
rec_label);

/* We derive transient payer_id from invreq_metadata */
invreq->invreq_payer_id = tal(invreq, struct pubkey);
if (!payer_key(invreq->invreq_metadata,
if (!payer_key(od, invreq->invreq_metadata,
tal_bytelen(invreq->invreq_metadata),
invreq->invreq_payer_id)) {
/* Doesn't happen! */
Expand Down Expand Up @@ -1539,6 +1548,7 @@ struct command_result *json_sendinvoice(struct command *cmd,
const char *buffer,
const jsmntok_t *params)
{
const struct offers_data *od = get_offers_data(cmd->plugin);
struct amount_msat *msat;
u32 *timeout;
struct sent *sent = tal(cmd, struct sent);
Expand Down Expand Up @@ -1611,7 +1621,7 @@ struct command_result *json_sendinvoice(struct command *cmd,
* - MUST set `invoice_node_id` to the final `blinded_node_id` on the path it received the invoice request
*/
sent->inv->invoice_node_id = tal(sent->inv, struct pubkey);
sent->inv->invoice_node_id->pubkey = id.pubkey;
sent->inv->invoice_node_id->pubkey = od->id.pubkey;

/* BOLT #12:
* - if the expiry for accepting payment is not 7200 seconds
Expand Down
77 changes: 41 additions & 36 deletions plugins/offers.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,36 +30,31 @@
#define HEADER_LEN crypto_secretstream_xchacha20poly1305_HEADERBYTES
#define ABYTES crypto_secretstream_xchacha20poly1305_ABYTES

struct pubkey id;
u32 blockheight;
u16 cltv_final;
bool disable_connect;
bool dev_invoice_bpath_scid;
struct short_channel_id *dev_invoice_internal_scid;
struct secret invoicesecret_base;
struct secret offerblinding_base;
struct secret nodealias_base;
static struct gossmap *global_gossmap;

static void init_gossmap(struct plugin *plugin)
struct offers_data *get_offers_data(struct plugin *plugin)
{
global_gossmap
= notleak_with_children(gossmap_load(plugin,
GOSSIP_STORE_FILENAME,
plugin_gossmap_logcb,
plugin));
if (!global_gossmap)
return plugin_get_data(plugin, struct offers_data);
}

static void init_gossmap(struct plugin *plugin,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this still needs to be initialized on startup.
==936832== Conditional jump or move depends on uninitialised value(s)
==936832== at 0x11424D: get_gossmap (offers.c:53)
==936832== by 0x11B316: try_establish (fetchinvoice.c:605)
==936832== by 0x11B414: send_message (fetchinvoice.c:644)
==936832== by 0x11B644: invreq_done (fetchinvoice.c:784)
==936832== by 0x121C94: handle_rpc_reply (libplugin.c:1136)
==936832== by 0x121E97: rpc_read_response_one (libplugin.c:1441)
==936832== by 0x121F48: rpc_conn_read_response (libplugin.c:1465)
==936832== by 0x1CEDCF: next_plan (io.c:60)
==936832== by 0x1CF2A0: do_plan (io.c:422)
==936832== by 0x1CF35D: io_ready (io.c:439)
==936832== by 0x1D0CEC: io_loop (poll.c:455)
==936832== by 0x1235A5: plugin_main (libplugin.c:2578)

struct offers_data *od)
{
od->global_gossmap_ = gossmap_load(plugin,
GOSSIP_STORE_FILENAME,
plugin_gossmap_logcb,
plugin);
if (!od->global_gossmap_)
plugin_err(plugin, "Could not load gossmap %s: %s",
GOSSIP_STORE_FILENAME, strerror(errno));
}

struct gossmap *get_gossmap(struct plugin *plugin)
{
if (!global_gossmap)
init_gossmap(plugin);
struct offers_data *od = get_offers_data(plugin);
if (!od->global_gossmap_)
init_gossmap(plugin, od);
else
gossmap_refresh(global_gossmap);
return global_gossmap;
gossmap_refresh(od->global_gossmap_);
return od->global_gossmap_;
}

/* BOLT #12:
Expand All @@ -69,6 +64,7 @@ struct gossmap *get_gossmap(struct plugin *plugin)
*/
bool we_want_blinded_path(struct plugin *plugin, bool for_payment)
{
const struct offers_data *od = get_offers_data(plugin);
struct node_id local_nodeid;
const struct gossmap_node *node;
const u8 *nannounce;
Expand All @@ -80,7 +76,7 @@ bool we_want_blinded_path(struct plugin *plugin, bool for_payment)
u8 rgb_color[3], alias[32];
struct tlv_node_ann_tlvs *na_tlvs;

node_id_from_pubkey(&local_nodeid, &id);
node_id_from_pubkey(&local_nodeid, &od->id);

node = gossmap_find_node(gossmap, &local_nodeid);
if (!node)
Expand Down Expand Up @@ -235,6 +231,7 @@ send_onion_reply(struct command *cmd,
struct blinded_path *reply_path,
struct tlv_onionmsg_tlv *payload)
{
const struct offers_data *od = get_offers_data(cmd->plugin);
struct onion_reply *onion_reply;

onion_reply = tal(cmd, struct onion_reply);
Expand All @@ -251,8 +248,8 @@ send_onion_reply(struct command *cmd,
}

return establish_onion_path(cmd, get_gossmap(cmd->plugin),
&id, &onion_reply->reply_path->first_node_id.pubkey,
disable_connect,
&od->id, &onion_reply->reply_path->first_node_id.pubkey,
od->disable_connect,
send_onion_reply_after_established,
send_onion_reply_not_established,
onion_reply);
Expand Down Expand Up @@ -421,8 +418,9 @@ static struct command_result *block_added_notify(struct command *cmd,
const char *buf,
const jsmntok_t *params)
{
struct offers_data *od = get_offers_data(cmd->plugin);
const char *err = json_scan(cmd, buf, params, "{block_added:{height:%}}",
JSON_SCAN(json_to_u32, &blockheight));
JSON_SCAN(json_to_u32, &od->blockheight));
if (err)
plugin_err(cmd->plugin, "Failed to parse block_added (%.*s): %s",
json_tok_full_len(params),
Expand Down Expand Up @@ -1517,34 +1515,36 @@ static const char *init(struct command *init_cmd,
const char *buf UNUSED,
const jsmntok_t *config UNUSED)
{
struct offers_data *od = get_offers_data(init_cmd->plugin);

rpc_scan(init_cmd, "getinfo",
take(json_out_obj(NULL, NULL, NULL)),
"{id:%}", JSON_SCAN(json_to_pubkey, &id));
"{id:%}", JSON_SCAN(json_to_pubkey, &od->id));

rpc_scan(init_cmd, "getchaininfo",
take(json_out_obj(NULL, "last_height", NULL)),
"{headercount:%}", JSON_SCAN(json_to_u32, &blockheight));
"{headercount:%}", JSON_SCAN(json_to_u32, &od->blockheight));

rpc_scan(init_cmd, "listconfigs",
take(json_out_obj(NULL, NULL, NULL)),
"{configs:"
"{cltv-final:{value_int:%}}}",
JSON_SCAN(json_to_u16, &cltv_final));
JSON_SCAN(json_to_u16, &od->cltv_final));

rpc_scan(init_cmd, "makesecret",
take(json_out_obj(NULL, "string", BOLT12_ID_BASE_STRING)),
"{secret:%}",
JSON_SCAN(json_to_secret, &invoicesecret_base));
JSON_SCAN(json_to_secret, &od->invoicesecret_base));

rpc_scan(init_cmd, "makesecret",
take(json_out_obj(NULL, "string", "offer-blinded-path")),
"{secret:%}",
JSON_SCAN(json_to_secret, &offerblinding_base));
JSON_SCAN(json_to_secret, &od->offerblinding_base));

rpc_scan(init_cmd, "makesecret",
take(json_out_obj(NULL, "string", NODE_ALIAS_BASE_STRING)),
"{secret:%}",
JSON_SCAN(json_to_secret, &nodealias_base));
JSON_SCAN(json_to_secret, &od->nodealias_base));

return NULL;
}
Expand Down Expand Up @@ -1605,22 +1605,27 @@ static bool scid_jsonfmt(struct plugin *plugin, struct json_stream *js, const ch
int main(int argc, char *argv[])
{
setup_locale();
struct offers_data *od = tal(NULL, struct offers_data);

od->disable_connect = false;
od->dev_invoice_bpath_scid = false;
od->dev_invoice_internal_scid = NULL;

/* We deal in UTC; mktime() uses local time */
setenv("TZ", "", 1);
plugin_main(argv, init, NULL, PLUGIN_RESTARTABLE, true, NULL,
plugin_main(argv, init, take(od), PLUGIN_RESTARTABLE, true, NULL,
commands, ARRAY_SIZE(commands),
notifications, ARRAY_SIZE(notifications),
hooks, ARRAY_SIZE(hooks),
NULL, 0,
plugin_option("fetchinvoice-noconnect", "flag",
"Don't try to connect directly to fetch/pay an invoice.",
flag_option, flag_jsonfmt, &disable_connect),
flag_option, flag_jsonfmt, &od->disable_connect),
plugin_option_dev("dev-invoice-bpath-scid", "flag",
"Use short_channel_id instead of pubkey when creating a blinded payment path",
flag_option, flag_jsonfmt, &dev_invoice_bpath_scid),
flag_option, flag_jsonfmt, &od->dev_invoice_bpath_scid),
plugin_option_dev("dev-invoice-internal-scid", "string",
"Use short_channel_id instead of pubkey when creating a blinded payment path",
scid_option, scid_jsonfmt, &dev_invoice_internal_scid),
scid_option, scid_jsonfmt, &od->dev_invoice_internal_scid),
NULL);
}
45 changes: 25 additions & 20 deletions plugins/offers.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,31 @@ struct command;
struct onion_message;
struct plugin;

/* This is me. */
extern struct pubkey id;
/* --fetchinvoice-noconnect */
extern bool disable_connect;
/* --cltv-final */
extern u16 cltv_final;
/* Current header_count */
extern u32 blockheight;
/* Basis for invoice path_secrets */
extern struct secret invoicesecret_base;
/* Base for offers path_secrets */
extern struct secret offerblinding_base;
/* Base for node aliases for invoice requests */
extern struct secret nodealias_base;
/* --dev-invoice-bpath-scid */
extern bool dev_invoice_bpath_scid;
/* --dev-invoice-internal-scid */
extern struct short_channel_id *dev_invoice_internal_scid;
/* This is me. */
extern struct pubkey id;
/* plugin_data for this plugin */
struct offers_data {
/* This is me. */
struct pubkey id;
/* --fetchinvoice-noconnect */
bool disable_connect;
/* --cltv-final */
u16 cltv_final;
/* Current header_count */
u32 blockheight;
/* Basis for invoice path_secrets */
struct secret invoicesecret_base;
/* Base for offers path_secrets */
struct secret offerblinding_base;
/* Base for node aliases for invoice requests */
struct secret nodealias_base;
/* --dev-invoice-bpath-scid */
bool dev_invoice_bpath_scid;
/* --dev-invoice-internal-scid */
struct short_channel_id *dev_invoice_internal_scid;
/* Use get_gossmap() to access this! */
struct gossmap *global_gossmap_;
};

struct offers_data *get_offers_data(struct plugin *plugin);

/* Helper to send a reply (connecting if required), and discard result */
struct command_result *WARN_UNUSED_RESULT
Expand Down
3 changes: 2 additions & 1 deletion plugins/offers_inv_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ struct command_result *handle_invoice(struct command *cmd,
struct blinded_path *reply_path STEALS,
const struct secret *secret)
{
const struct offers_data *od = get_offers_data(cmd->plugin);
size_t len = tal_count(invbin);
struct inv *inv = tal(cmd, struct inv);
struct out_req *req;
Expand All @@ -242,7 +243,7 @@ struct command_result *handle_invoice(struct command *cmd,
invoice_invreq_id(inv->inv, &invreq_id_nopath);
inv->inv->invreq_paths = invreq_paths;

path_secret = bolt12_path_id(tmpctx, &offerblinding_base, &invreq_id_nopath);
path_secret = bolt12_path_id(tmpctx, &od->offerblinding_base, &invreq_id_nopath);
if (!memeq(path_secret, tal_count(path_secret),
secret, sizeof(*secret))) {
if (command_dev_apis(cmd))
Expand Down
Loading