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)
|
if (reply_path)
|
||||||
return handle_invoice_request(cmd,
|
return handle_invoice_request(cmd,
|
||||||
invreqbin,
|
invreqbin,
|
||||||
reply_path);
|
reply_path, secret);
|
||||||
else
|
else
|
||||||
plugin_log(cmd->plugin, LOG_DBG,
|
plugin_log(cmd->plugin, LOG_DBG,
|
||||||
"invoice_request without reply_path");
|
"invoice_request without reply_path");
|
||||||
@ -265,7 +265,7 @@ static struct command_result *onion_message_recv(struct command *cmd,
|
|||||||
if (invtok) {
|
if (invtok) {
|
||||||
const u8 *invbin = json_tok_bin_from_hex(tmpctx, buf, invtok);
|
const u8 *invbin = json_tok_bin_from_hex(tmpctx, buf, invtok);
|
||||||
if (invbin)
|
if (invbin)
|
||||||
return handle_invoice(cmd, invbin, reply_path);
|
return handle_invoice(cmd, invbin, reply_path, secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
return command_hook_success(cmd);
|
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,
|
struct command_result *handle_invoice(struct command *cmd,
|
||||||
const u8 *invbin,
|
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);
|
size_t len = tal_count(invbin);
|
||||||
struct inv *inv = tal(cmd, struct inv);
|
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);
|
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:
|
/* BOLT-offers #12:
|
||||||
* A reader of an invoice:
|
* A reader of an invoice:
|
||||||
* - MUST reject the invoice if `invoice_amount` is not present.
|
* - 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. */
|
/* We got an onionmessage with an invoice! reply_path could be NULL. */
|
||||||
struct command_result *handle_invoice(struct command *cmd,
|
struct command_result *handle_invoice(struct command *cmd,
|
||||||
const u8 *invbin,
|
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 */
|
#endif /* LIGHTNING_PLUGINS_OFFERS_INV_HOOK_H */
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <bitcoin/chainparams.h>
|
#include <bitcoin/chainparams.h>
|
||||||
#include <bitcoin/preimage.h>
|
#include <bitcoin/preimage.h>
|
||||||
#include <ccan/cast/cast.h>
|
#include <ccan/cast/cast.h>
|
||||||
|
#include <ccan/mem/mem.h>
|
||||||
#include <ccan/tal/str/str.h>
|
#include <ccan/tal/str/str.h>
|
||||||
#include <common/bech32_util.h>
|
#include <common/bech32_util.h>
|
||||||
#include <common/blindedpath.h>
|
#include <common/blindedpath.h>
|
||||||
@ -35,6 +36,9 @@ struct invreq {
|
|||||||
|
|
||||||
/* The preimage for the invoice. */
|
/* The preimage for the invoice. */
|
||||||
struct preimage preimage;
|
struct preimage preimage;
|
||||||
|
|
||||||
|
/* Optional secret. */
|
||||||
|
const struct secret *secret;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct command_result *WARN_UNUSED_RESULT
|
static struct command_result *WARN_UNUSED_RESULT
|
||||||
@ -820,7 +824,50 @@ static struct command_result *listoffers_done(struct command *cmd,
|
|||||||
if (arr->size == 0)
|
if (arr->size == 0)
|
||||||
return fail_invreq(cmd, ir, "Unknown offer");
|
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;
|
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");
|
activetok = json_get_member(buf, offertok, "active");
|
||||||
if (!activetok) {
|
if (!activetok) {
|
||||||
@ -833,8 +880,6 @@ static struct command_result *listoffers_done(struct command *cmd,
|
|||||||
if (!active)
|
if (!active)
|
||||||
return fail_invreq(cmd, ir, "Offer no longer available");
|
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");
|
b12tok = json_get_member(buf, offertok, "bolt12");
|
||||||
if (!b12tok) {
|
if (!b12tok) {
|
||||||
return fail_internalerr(cmd, ir,
|
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,
|
struct command_result *handle_invoice_request(struct command *cmd,
|
||||||
const u8 *invreqbin,
|
const u8 *invreqbin,
|
||||||
struct blinded_path *reply_path)
|
struct blinded_path *reply_path,
|
||||||
|
const struct secret *secret)
|
||||||
{
|
{
|
||||||
struct out_req *req;
|
struct out_req *req;
|
||||||
int bad_feature;
|
int bad_feature;
|
||||||
@ -981,7 +1027,7 @@ struct command_result *handle_invoice_request(struct command *cmd,
|
|||||||
struct invreq *ir = tal(cmd, struct invreq);
|
struct invreq *ir = tal(cmd, struct invreq);
|
||||||
|
|
||||||
ir->reply_path = tal_steal(ir, reply_path);
|
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);
|
ir->invreq = fromwire_tlv_invoice_request(cmd, &cursor, &len);
|
||||||
|
|
||||||
/* BOLT-offers #12:
|
/* BOLT-offers #12:
|
||||||
|
@ -6,5 +6,6 @@
|
|||||||
/* We got an onionmessage with an invreq! */
|
/* We got an onionmessage with an invreq! */
|
||||||
struct command_result *handle_invoice_request(struct command *cmd,
|
struct command_result *handle_invoice_request(struct command *cmd,
|
||||||
const u8 *invreqbin,
|
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 */
|
#endif /* LIGHTNING_PLUGINS_OFFERS_INVREQ_HOOK_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user