common/onion_decode: put the path_id into onion_payload->payment_secret.

And check it in invoice.c, insead of a hack where we compare against invhash.
Restore checking, too.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2022-11-09 13:01:52 +10:30
committed by Christian Decker
parent 595fbd2a19
commit c6f50220e1
3 changed files with 21 additions and 30 deletions

View File

@@ -285,9 +285,14 @@ struct onion_payload *onion_decode(const tal_t *ctx,
goto field_bad; goto field_bad;
} }
/* Blinded paths have no payment secret or metadata: /* We stash path_id (if present and valid!) in payment_secret */
* we use the path_id for that. */ if (tal_bytelen(enc->path_id) == sizeof(*p->payment_secret)) {
p->payment_secret = tal_steal(p,
(struct secret *)enc->path_id);
} else
p->payment_secret = NULL; p->payment_secret = NULL;
/* FIXME: if we supported metadata, it would also be in path_id */
p->payment_metadata = NULL; p->payment_metadata = NULL;
return p; return p;
} }

View File

@@ -116,12 +116,9 @@ void htlc_set_add(struct lightningd *ld,
return; return;
} }
/* FIXME! */
bool ignore_secret = details->invstring && strstarts(details->invstring, "lni1");
/* If we insist on a payment secret, it must always have it */ /* If we insist on a payment secret, it must always have it */
if (feature_is_set(details->features, COMPULSORY_FEATURE(OPT_PAYMENT_SECRET)) if (feature_is_set(details->features, COMPULSORY_FEATURE(OPT_PAYMENT_SECRET))
&& !payment_secret && !ignore_secret) { && !payment_secret) {
log_debug(ld->log, "Missing payment_secret, but required for %s", log_debug(ld->log, "Missing payment_secret, but required for %s",
type_to_string(tmpctx, struct sha256, type_to_string(tmpctx, struct sha256,
&hin->payment_hash)); &hin->payment_hash));

View File

@@ -142,27 +142,18 @@ static void invoice_secret(const struct preimage *payment_preimage,
memcpy(payment_secret->data, secret.u.u8, sizeof(secret.u.u8)); memcpy(payment_secret->data, secret.u.u8, sizeof(secret.u.u8));
} }
/* FIXME: This is a hack. The real secret should be a signature of some /* FIXME: The spec should require a *real* secret: a signature of the
* onion key, using the payer_id */ * payment_hash using the payer_id key. This just means they've
* *seen* the invoice! */
static void invoice_secret_bolt12(struct lightningd *ld, static void invoice_secret_bolt12(struct lightningd *ld,
const char *invstring, const struct sha256 *payment_hash,
struct secret *payment_secret) struct secret *payment_secret)
{ {
char *fail; const void *path_id = invoice_path_id(tmpctx,
struct tlv_invoice *inv; &ld->invoicesecret_base,
struct sha256 merkle; payment_hash);
assert(tal_bytelen(path_id) == sizeof(*payment_secret));
inv = invoice_decode(tmpctx, invstring, strlen(invstring), memcpy(payment_secret, path_id, sizeof(*payment_secret));
NULL, NULL, &fail);
if (!inv) {
log_broken(ld->log, "Unable to decode our invoice %s",
invstring);
return;
}
merkle_tlv(inv->fields, &merkle);
BUILD_ASSERT(sizeof(*payment_secret) == sizeof(merkle));
memcpy(payment_secret, &merkle, sizeof(merkle));
} }
struct invoice_payment_hook_payload { struct invoice_payment_hook_payload {
@@ -398,8 +389,6 @@ invoice_check_payment(const tal_t *ctx,
} }
details = wallet_invoice_details(ctx, ld->wallet, invoice); details = wallet_invoice_details(ctx, ld->wallet, invoice);
/* FIXME! */
bool ignore_secret = details->invstring && strstarts(details->invstring, "lni1");
/* BOLT #4: /* BOLT #4:
* - if the `payment_secret` doesn't match the expected value for that * - if the `payment_secret` doesn't match the expected value for that
@@ -408,17 +397,17 @@ invoice_check_payment(const tal_t *ctx,
* - MUST fail the HTLC. * - MUST fail the HTLC.
*/ */
if (feature_is_set(details->features, COMPULSORY_FEATURE(OPT_VAR_ONION)) if (feature_is_set(details->features, COMPULSORY_FEATURE(OPT_VAR_ONION))
&& !payment_secret && !ignore_secret) { && !payment_secret) {
log_debug(ld->log, "Attept to pay %s without secret", log_debug(ld->log, "Attept to pay %s without secret",
type_to_string(tmpctx, struct sha256, &details->rhash)); type_to_string(tmpctx, struct sha256, &details->rhash));
return tal_free(details); return tal_free(details);
} }
if (payment_secret && !ignore_secret) { if (payment_secret) {
struct secret expected; struct secret expected;
if (details->invstring && strstarts(details->invstring, "lni1")) if (details->invstring && strstarts(details->invstring, "lni1"))
invoice_secret_bolt12(ld, details->invstring, &expected); invoice_secret_bolt12(ld, payment_hash, &expected);
else else
invoice_secret(&details->r, &expected); invoice_secret(&details->r, &expected);
if (!secret_eq_consttime(payment_secret, &expected)) { if (!secret_eq_consttime(payment_secret, &expected)) {