mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 01:43:36 +01:00
offers: check they use the blinded path if one is specified.
Now we can specify a blinded path in an offer, we have to check they used it (or didn't use it, if we didn't have one!). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
27578d5c1d
commit
0d4b9ad6ce
@ -255,7 +255,7 @@ static struct command_result *onion_message_recv(struct command *cmd,
|
||||
if (reply_path)
|
||||
return handle_invoice_request(cmd,
|
||||
invreqbin,
|
||||
reply_path);
|
||||
reply_path, secret);
|
||||
else
|
||||
plugin_log(cmd->plugin, LOG_DBG,
|
||||
"invoice_request without reply_path");
|
||||
@ -265,7 +265,7 @@ static struct command_result *onion_message_recv(struct command *cmd,
|
||||
if (invtok) {
|
||||
const u8 *invbin = json_tok_bin_from_hex(tmpctx, buf, invtok);
|
||||
if (invbin)
|
||||
return handle_invoice(cmd, invbin, reply_path);
|
||||
return handle_invoice(cmd, invbin, reply_path, secret);
|
||||
}
|
||||
|
||||
return command_hook_success(cmd);
|
||||
|
@ -209,7 +209,8 @@ static struct command_result *listinvreqs_error(struct command *cmd,
|
||||
|
||||
struct command_result *handle_invoice(struct command *cmd,
|
||||
const u8 *invbin,
|
||||
struct blinded_path *reply_path STEALS)
|
||||
struct blinded_path *reply_path STEALS,
|
||||
const struct secret *secret)
|
||||
{
|
||||
size_t len = tal_count(invbin);
|
||||
struct inv *inv = tal(cmd, struct inv);
|
||||
@ -227,6 +228,16 @@ struct command_result *handle_invoice(struct command *cmd,
|
||||
}
|
||||
invoice_invreq_id(inv->inv, &inv->invreq_id);
|
||||
|
||||
/* We never publish invoice_requests with a reply path, so replies via
|
||||
* a path are invalid */
|
||||
if (secret) {
|
||||
if (command_dev_apis(cmd))
|
||||
return fail_inv(cmd, inv, "Unexpected blinded path");
|
||||
/* Normally, "I don't know what you're talking about!" */
|
||||
return fail_inv(cmd, inv, "Unknown invoice_request %s",
|
||||
fmt_sha256(tmpctx, &inv->invreq_id));
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
* A reader of an invoice:
|
||||
* - MUST reject the invoice if `invoice_amount` is not present.
|
||||
|
@ -6,6 +6,7 @@
|
||||
/* We got an onionmessage with an invoice! reply_path could be NULL. */
|
||||
struct command_result *handle_invoice(struct command *cmd,
|
||||
const u8 *invbin,
|
||||
struct blinded_path *reply_path STEALS);
|
||||
struct blinded_path *reply_path STEALS,
|
||||
const struct secret *secret);
|
||||
|
||||
#endif /* LIGHTNING_PLUGINS_OFFERS_INV_HOOK_H */
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <bitcoin/chainparams.h>
|
||||
#include <bitcoin/preimage.h>
|
||||
#include <ccan/cast/cast.h>
|
||||
#include <ccan/mem/mem.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/bech32_util.h>
|
||||
#include <common/blindedpath.h>
|
||||
@ -35,6 +36,9 @@ struct invreq {
|
||||
|
||||
/* The preimage for the invoice. */
|
||||
struct preimage preimage;
|
||||
|
||||
/* Optional secret. */
|
||||
const struct secret *secret;
|
||||
};
|
||||
|
||||
static struct command_result *WARN_UNUSED_RESULT
|
||||
@ -820,7 +824,50 @@ static struct command_result *listoffers_done(struct command *cmd,
|
||||
if (arr->size == 0)
|
||||
return fail_invreq(cmd, ir, "Unknown offer");
|
||||
|
||||
/* Now, since we looked up by hash, we know that the entire offer
|
||||
* is faithfully mirrored in this invreq. */
|
||||
|
||||
/* BOLT-offers #4:
|
||||
*
|
||||
* The final recipient:
|
||||
*...
|
||||
* - MUST ignore the message if the `path_id` does not match
|
||||
* the blinded route it created
|
||||
*/
|
||||
offertok = arr + 1;
|
||||
if (ir->secret) {
|
||||
struct sha256 offer_id;
|
||||
const u8 *blinding_path_secret;
|
||||
struct blinded_path **offer_paths;
|
||||
|
||||
if (!ir->invreq->offer_paths) {
|
||||
/* You should not have used a blinded path for invreq */
|
||||
if (command_dev_apis(cmd))
|
||||
return fail_invreq(cmd, ir, "Unexpected blinded path");
|
||||
return fail_invreq(cmd, ir, "Unknown offer");
|
||||
}
|
||||
/* We generated this without the paths, so temporarily remove them */
|
||||
offer_paths = ir->invreq->offer_paths;
|
||||
ir->invreq->offer_paths = NULL;
|
||||
invreq_offer_id(ir->invreq, &offer_id);
|
||||
ir->invreq->offer_paths = offer_paths;
|
||||
blinding_path_secret = invoice_path_id(tmpctx,
|
||||
&offerblinding_base, &offer_id);
|
||||
if (!memeq(ir->secret, tal_bytelen(ir->secret),
|
||||
blinding_path_secret, tal_bytelen(blinding_path_secret))) {
|
||||
/* You used the wrong blinded path for invreq */
|
||||
if (command_dev_apis(cmd))
|
||||
return fail_invreq(cmd, ir, "Wrong blinded path");
|
||||
return fail_invreq(cmd, ir, "Unknown offer");
|
||||
}
|
||||
} else {
|
||||
if (ir->invreq->offer_paths) {
|
||||
/* You should have used a blinded path for invreq */
|
||||
if (command_dev_apis(cmd))
|
||||
return fail_invreq(cmd, ir, "Expected blinded path");
|
||||
return fail_invreq(cmd, ir, "Unknown offer");
|
||||
}
|
||||
}
|
||||
|
||||
activetok = json_get_member(buf, offertok, "active");
|
||||
if (!activetok) {
|
||||
@ -833,8 +880,6 @@ static struct command_result *listoffers_done(struct command *cmd,
|
||||
if (!active)
|
||||
return fail_invreq(cmd, ir, "Offer no longer available");
|
||||
|
||||
/* Now, since we looked up by hash, we know that the entire offer
|
||||
* is faithfully mirrored in this invreq. */
|
||||
b12tok = json_get_member(buf, offertok, "bolt12");
|
||||
if (!b12tok) {
|
||||
return fail_internalerr(cmd, ir,
|
||||
@ -972,7 +1017,8 @@ static struct command_result *listoffers_done(struct command *cmd,
|
||||
|
||||
struct command_result *handle_invoice_request(struct command *cmd,
|
||||
const u8 *invreqbin,
|
||||
struct blinded_path *reply_path)
|
||||
struct blinded_path *reply_path,
|
||||
const struct secret *secret)
|
||||
{
|
||||
struct out_req *req;
|
||||
int bad_feature;
|
||||
@ -981,7 +1027,7 @@ struct command_result *handle_invoice_request(struct command *cmd,
|
||||
struct invreq *ir = tal(cmd, struct invreq);
|
||||
|
||||
ir->reply_path = tal_steal(ir, reply_path);
|
||||
|
||||
ir->secret = tal_dup_or_null(ir, struct secret, secret);
|
||||
ir->invreq = fromwire_tlv_invoice_request(cmd, &cursor, &len);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
|
@ -6,5 +6,6 @@
|
||||
/* We got an onionmessage with an invreq! */
|
||||
struct command_result *handle_invoice_request(struct command *cmd,
|
||||
const u8 *invreqbin,
|
||||
struct blinded_path *reply_path STEALS);
|
||||
struct blinded_path *reply_path STEALS,
|
||||
const struct secret *secret TAKES);
|
||||
#endif /* LIGHTNING_PLUGINS_OFFERS_INVREQ_HOOK_H */
|
||||
|
Loading…
Reference in New Issue
Block a user