mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-21 14:24:09 +01:00
BOLT12: remove -offers from bolt12 quotes, update them.
Typo fixes and wording changes. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
c22cc11af5
commit
c3362b057c
20 changed files with 242 additions and 234 deletions
|
@ -18,13 +18,13 @@ bool bolt12_chains_match(const struct bitcoin_blkid *chains,
|
|||
size_t max_num_chains,
|
||||
const struct chainparams *must_be_chain)
|
||||
{
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if the chain for the invoice is not solely bitcoin:
|
||||
* - MUST specify `offer_chains` the offer is valid for.
|
||||
* - otherwise:
|
||||
* - MAY omit `offer_chains`, implying that bitcoin is only chain.
|
||||
* - SHOULD omit `offer_chains`, implying that bitcoin is only chain.
|
||||
*/
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A reader of an offer:
|
||||
*...
|
||||
* - if `offer_chains` is not set:
|
||||
|
@ -194,7 +194,7 @@ struct tlv_offer *offer_decode(const tal_t *ctx,
|
|||
if (*fail)
|
||||
return tal_free(offer);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A reader of an offer:
|
||||
* - if the offer contains any TLV fields outside the inclusive ranges: 1 to 79 and 1000000000 to 1999999999:
|
||||
* - MUST NOT respond to the offer.
|
||||
|
@ -214,7 +214,7 @@ struct tlv_offer *offer_decode(const tal_t *ctx,
|
|||
return tal_free(offer);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* - if `offer_amount` is set and `offer_description` is not set:
|
||||
* - MUST NOT respond to the offer.
|
||||
|
@ -224,7 +224,7 @@ struct tlv_offer *offer_decode(const tal_t *ctx,
|
|||
return tal_free(offer);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* - if neither `offer_issuer_id` nor `offer_paths` are set:
|
||||
* - MUST NOT respond to the offer.
|
||||
|
@ -234,7 +234,7 @@ struct tlv_offer *offer_decode(const tal_t *ctx,
|
|||
return tal_free(offer);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `num_hops` is 0 in any `blinded_path` in `offer_paths`:
|
||||
* - MUST NOT respond to the offer.
|
||||
*/
|
||||
|
@ -287,10 +287,10 @@ struct tlv_invoice_request *invrequest_decode(const tal_t *ctx,
|
|||
if (*fail)
|
||||
return tal_free(invrequest);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* The reader:
|
||||
*...
|
||||
* - MUST fail the request if any non-signature TLV fields are outside the inclusive ranges: 0 to 159 and 1000000000 to 2999999999
|
||||
* - MUST reject the invoice request if any non-signature TLV fields are outside the inclusive ranges: 0 to 159 and 1000000000 to 2999999999
|
||||
*/
|
||||
badf = any_field_outside_range(invrequest->fields, true,
|
||||
0, 159,
|
||||
|
@ -302,9 +302,9 @@ struct tlv_invoice_request *invrequest_decode(const tal_t *ctx,
|
|||
return tal_free(invrequest);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `num_hops` is 0 in any `blinded_path` in `invreq_paths`:
|
||||
* - MUST fail the request.
|
||||
* - MUST reject the invoice request.
|
||||
*/
|
||||
for (size_t i = 0; i < tal_count(invrequest->invreq_paths); i++) {
|
||||
if (tal_count(invrequest->invreq_paths[i]->path) == 0) {
|
||||
|
@ -346,12 +346,11 @@ struct tlv_invoice *invoice_decode_minimal(const tal_t *ctx,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `invreq_chain` is not present:
|
||||
* - MUST fail the request if bitcoin is not a supported chain.
|
||||
* - otherwise:
|
||||
* - MUST fail the request if `invreq_chain`.`chain` is not a
|
||||
* supported chain.
|
||||
* - MUST reject the invoice if bitcoin is not a supported chain.
|
||||
* - otherwise:
|
||||
* - MUST reject the invoice if `invreq_chain`.`chain` is not a supported chain.
|
||||
* - if `invoice_features` contains unknown _odd_ bits that are non-zero:
|
||||
* - MUST ignore the bit.
|
||||
* - if `invoice_features` contains unknown _even_ bits that are non-zero:
|
||||
|
@ -412,7 +411,7 @@ static u64 time_change(u64 prevstart, u32 number,
|
|||
u64 offer_period_start(u64 basetime, size_t n,
|
||||
const struct recurrence *recur)
|
||||
{
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* 1. A `time_unit` defining 0 (seconds), 1 (days), 2 (months),
|
||||
* 3 (years).
|
||||
*/
|
||||
|
@ -437,13 +436,13 @@ void offer_period_paywindow(const struct recurrence *recurrence,
|
|||
u64 basetime, u64 period_idx,
|
||||
u64 *start, u64 *end)
|
||||
{
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - if the offer contains `recurrence_paywindow`:
|
||||
*/
|
||||
if (recurrence_paywindow) {
|
||||
u64 pstart = offer_period_start(basetime, period_idx,
|
||||
recurrence);
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - if the offer has a `recurrence_basetime` or the
|
||||
* `recurrence_counter` is non-zero:
|
||||
* - SHOULD NOT send an `invreq` for a period prior to
|
||||
|
@ -461,7 +460,7 @@ void offer_period_paywindow(const struct recurrence *recurrence,
|
|||
&& recurrence_paywindow->seconds_after < 60)
|
||||
*end = pstart + 60;
|
||||
} else {
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - otherwise:
|
||||
* - SHOULD NOT send an `invreq` with
|
||||
* `recurrence_counter` is non-zero for a period whose
|
||||
|
@ -473,7 +472,7 @@ void offer_period_paywindow(const struct recurrence *recurrence,
|
|||
*start = offer_period_start(basetime, period_idx-1,
|
||||
recurrence);
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - SHOULD NOT send an `invreq` for a period which
|
||||
* has already passed.
|
||||
*/
|
||||
|
@ -502,7 +501,7 @@ struct tlv_invoice *invoice_decode(const tal_t *ctx,
|
|||
if (*fail)
|
||||
return tal_free(invoice);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A reader of an invoice:
|
||||
* - MUST reject the invoice if `invoice_amount` is not present.
|
||||
* - MUST reject the invoice if `invoice_created_at` is not present.
|
||||
|
@ -526,7 +525,7 @@ struct tlv_invoice *invoice_decode(const tal_t *ctx,
|
|||
return tal_free(invoice);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST reject the invoice if `invoice_paths` is not present or is
|
||||
* empty. */
|
||||
if (tal_count(invoice->invoice_paths) == 0) {
|
||||
|
@ -534,7 +533,7 @@ struct tlv_invoice *invoice_decode(const tal_t *ctx,
|
|||
return tal_free(invoice);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST reject the invoice if `num_hops` is 0 in any
|
||||
* `blinded_path` in `invoice_paths`.
|
||||
*/
|
||||
|
@ -546,7 +545,7 @@ struct tlv_invoice *invoice_decode(const tal_t *ctx,
|
|||
return tal_free(invoice);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST reject the invoice if `invoice_blindedpay` is not present.
|
||||
* - MUST reject the invoice if `invoice_blindedpay` does not contain exactly one `blinded_payinfo` per `invoice_paths`.`blinded_path`.
|
||||
*/
|
||||
|
@ -565,7 +564,7 @@ u64 invoice_expiry(const struct tlv_invoice *invoice)
|
|||
{
|
||||
u64 expiry;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `invoice_relative_expiry` is present:
|
||||
* - MUST reject the invoice if the current time since 1970-01-01 UTC
|
||||
* is greater than `invoice_created_at` plus `seconds_from_creation`.
|
||||
|
@ -639,7 +638,7 @@ static void calc_offer(const u8 *tlvstream, struct sha256 *id)
|
|||
size_t start1, len1, start2, len2;
|
||||
struct sha256_ctx ctx;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A writer of an offer:
|
||||
* - MUST NOT set any TLV fields outside the inclusive ranges: 1 to 79 and 1000000000 to 1999999999.
|
||||
*/
|
||||
|
@ -681,7 +680,7 @@ static void calc_invreq(const u8 *tlvstream, struct sha256 *id)
|
|||
size_t start1, len1, start2, len2;
|
||||
struct sha256_ctx ctx;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* The writer:
|
||||
*...
|
||||
* - MUST NOT set any non-signature TLV fields outside the inclusive ranges: 0 to 159 and 1000000000 to 2999999999
|
||||
|
@ -712,7 +711,7 @@ void invoice_invreq_id(const struct tlv_invoice *invoice, struct sha256 *id)
|
|||
}
|
||||
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* ## Requirements for Invoice Requests
|
||||
*
|
||||
* The writer:
|
||||
|
@ -744,11 +743,11 @@ struct tlv_invoice *invoice_for_invreq(const tal_t *ctx,
|
|||
|
||||
towire_tlv_invoice_request(&wire, invreq);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A writer of an invoice:
|
||||
*...
|
||||
* - if the invoice is in response to an `invoice_request`:
|
||||
* - MUST copy all non-signature fields from the `invoice_request` (including
|
||||
* - MUST copy all non-signature fields from the invoice request (including
|
||||
* unknown fields).
|
||||
*/
|
||||
len1 = tlv_span(wire, 0, 159, &start1);
|
||||
|
@ -765,7 +764,7 @@ struct tlv_invoice *invoice_for_invreq(const tal_t *ctx,
|
|||
|
||||
bool is_bolt12_signature_field(u64 typenum)
|
||||
{
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* Each form is signed using one or more *signature TLV elements*: TLV
|
||||
* types 240 through 1000 (inclusive). */
|
||||
return typenum >= 240 && typenum <= 1000;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
struct feature_set;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `invoice_relative_expiry` is present:
|
||||
* - MUST reject the invoice if the current time since 1970-01-01 UTC
|
||||
* is greater than `invoice_created_at` plus `seconds_from_creation`.
|
||||
|
@ -161,7 +161,7 @@ struct tlv_invoice_request *invoice_request_for_offer(const tal_t *ctx,
|
|||
struct tlv_invoice *invoice_for_invreq(const tal_t *ctx,
|
||||
const struct tlv_invoice_request *invreq);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* Each form is signed using one or more *signature TLV elements*: TLV
|
||||
* types 240 through 1000 (inclusive). */
|
||||
bool is_bolt12_signature_field(u64 typenum);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#define SUPERVERBOSE(...)
|
||||
#endif
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* Each form is signed using one or more *signature TLV elements*: TLV
|
||||
* types 240 through 1000 (inclusive).
|
||||
*/
|
||||
|
@ -39,7 +39,7 @@ static void sha256_update_tlvfield(struct sha256_ctx *ctx,
|
|||
sha256_update(ctx, field->value, field->length);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* Thus we define H(`tag`,`msg`) as SHA256(SHA256(`tag`) || SHA256(`tag`) || `msg`)*/
|
||||
/* Create a sha256_ctx which has the tag part done. */
|
||||
static void h_simpletag_ctx(struct sha256_ctx *sctx, const char *tag)
|
||||
|
@ -55,7 +55,7 @@ static void h_simpletag_ctx(struct sha256_ctx *sctx, const char *tag)
|
|||
}
|
||||
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* The Merkle tree's leaves are, in TLV-ascending order for each tlv:
|
||||
* 1. The H("LnLeaf",tlv).
|
||||
* 2. The H("LnNonce"||first-tlv,tlv-type) where first-tlv is the numerically-first TLV entry in the stream, and tlv-type is the "type" field (1-9 bytes) of the current tlv.
|
||||
|
@ -108,7 +108,7 @@ static void calc_lnleaf(const struct tlv_field *field, struct sha256 *hash)
|
|||
SUPERVERBOSE(") -> %s\n", fmt_sha256(tmpctx, hash));
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* The Merkle tree inner nodes are H("LnBranch", lesser-SHA256||greater-SHA256)
|
||||
*/
|
||||
static struct sha256 *merkle_pair(const tal_t *ctx,
|
||||
|
@ -193,7 +193,7 @@ void merkle_tlv(const struct tlv_field *fields, struct sha256 *merkle)
|
|||
tal_free(arr);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* All signatures are created as per
|
||||
* [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki)
|
||||
* and tagged as recommended there. Thus we define H(`tag`,`msg`) as
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
#include "config.h"
|
||||
#include <wire/wire.h>
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* - MUST specify `offer_currency` `iso4217` as an ISO 4712 three-letter code.
|
||||
* - MUST specify `offer_amount` in the currency unit adjusted by the ISO 4712
|
||||
* - MUST specify `offer_currency` `iso4217` as an ISO 4217 three-letter code.
|
||||
* - MUST specify `offer_amount` in the currency unit adjusted by the ISO 4217
|
||||
* exponent (e.g. USD cents).
|
||||
*/
|
||||
struct iso4217_name_and_divisor {
|
||||
|
|
|
@ -57,7 +57,7 @@ static bool decrypt_forwarding_onionmsg(const struct pubkey *path_key,
|
|||
if (encmsg->path_id)
|
||||
return false;
|
||||
|
||||
/* BOLT-offers #4:
|
||||
/* BOLT #4:
|
||||
* - if it is not the final node according to the onion encryption:
|
||||
*...
|
||||
* - if `next_node_id` is present:
|
||||
|
|
|
@ -245,9 +245,8 @@ int main(int argc, char *argv[])
|
|||
print_valid_offer(offer, "with blinded path via Bob (0x424242...), path_key 020202...",
|
||||
"path is [id=02020202..., enc=0x00*16], [id=02020202..., enc=0x11*8]", NULL);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if it includes `offer_paths`:
|
||||
* - SHOULD ignore any invoice_request which does not use the path.
|
||||
* - MAY set `offer_issuer_id`.
|
||||
* - otherwise:
|
||||
* - MUST set `offer_issuer_id` to the node's public key to request the invoice from.
|
||||
|
@ -386,7 +385,7 @@ int main(int argc, char *argv[])
|
|||
"Malformed: invalid offer_issuer_id");
|
||||
|
||||
/* Now these are simply invalid, not bad encodings */
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A reader of an offer:
|
||||
* - if the offer contains any TLV fields outside the inclusive ranges: 1 to 79 and 1000000000 to 1999999999:
|
||||
* - MUST NOT respond to the offer.
|
||||
|
@ -416,7 +415,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
offer->offer_features = tal_arr(offer, u8, 0);
|
||||
set_feature_bit(&offer->offer_features, 22);
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `offer_features` contains unknown _even_ bits that are non-zero:
|
||||
* - MUST NOT respond to the offer.
|
||||
* - SHOULD indicate the unknown bit to the user.
|
||||
|
@ -424,9 +423,11 @@ int main(int argc, char *argv[])
|
|||
print_invalid_offer(offer, "Contains unknown feature 22");
|
||||
offer->offer_features = NULL;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `offer_amount` is set and `offer_description` is not set:
|
||||
* - MUST NOT respond to the offer.
|
||||
* - if `offer_currency` is set and `offer_amount` is not set:
|
||||
* - MUST NOT respond to the offer.
|
||||
* - if neither `offer_issuer_id` nor `offer_paths` are set:
|
||||
* - MUST NOT respond to the offer.
|
||||
*/
|
||||
|
@ -434,6 +435,10 @@ int main(int argc, char *argv[])
|
|||
print_invalid_offer(offer, "Missing offer_description and offer_amount");
|
||||
offer->offer_description = tal_utf8(tmpctx, "Test vectors");
|
||||
|
||||
offer->offer_currency = tal_utf8(offer, "USD");
|
||||
print_invalid_offer(offer, "Missing offer_amount with offer_currency");
|
||||
offer->offer_currency = NULL;
|
||||
|
||||
offer->offer_issuer_id = NULL;
|
||||
print_invalid_offer(offer, "Missing offer_issuer_id and no offer_path");
|
||||
|
||||
|
|
|
@ -115,21 +115,21 @@ int main(int argc, char *argv[])
|
|||
common_setup(argv[0]);
|
||||
|
||||
offer = tlv_offer_new(tmpctx);
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A writer of an offer:
|
||||
* - MUST NOT set any TLV fields outside the inclusive ranges: 1 to 79 and 1000000000 to 1999999999.
|
||||
* - if the chain for the invoice is not solely bitcoin:
|
||||
* - MUST specify `offer_chains` the offer is valid for.
|
||||
* - otherwise:
|
||||
* - MAY omit `offer_chains`, implying that bitcoin is only chain.
|
||||
* - SHOULD omit `offer_chains`, implying that bitcoin is only chain.
|
||||
* - if a specific minimum `offer_amount` is required for successful payment:
|
||||
* - MUST set `offer_amount` to the amount expected (per item).
|
||||
* - if the currency for `offer_amount` is that of all entries in `chains`:
|
||||
* - MUST specify `amount` in multiples of the minimum lightning-payable unit
|
||||
* - MUST specify `offer_amount` in multiples of the minimum lightning-payable unit
|
||||
* (e.g. milli-satoshis for bitcoin).
|
||||
* - otherwise:
|
||||
* - MUST specify `offer_currency` `iso4217` as an ISO 4712 three-letter code.
|
||||
* - MUST specify `offer_amount` in the currency unit adjusted by the ISO 4712
|
||||
* - MUST specify `offer_currency` `iso4217` as an ISO 4217 three-letter code.
|
||||
* - MUST specify `offer_amount` in the currency unit adjusted by the ISO 4217
|
||||
* exponent (e.g. USD cents).
|
||||
* - MUST set `offer_description` to a complete description of the purpose
|
||||
* of the payment.
|
||||
|
@ -150,7 +150,6 @@ int main(int argc, char *argv[])
|
|||
* - otherwise:
|
||||
* - MAY include `offer_paths`.
|
||||
* - if it includes `offer_paths`:
|
||||
* - SHOULD ignore any invoice_request which does not use the path.
|
||||
* - MAY set `offer_issuer_id`.
|
||||
* - otherwise:
|
||||
* - MUST set `offer_issuer_id` to the node's public key to request the invoice from.
|
||||
|
|
|
@ -97,7 +97,7 @@ static u8 *tlv(u64 type, const void *contents, size_t len)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* Thus we define H(`tag`,`msg`) as SHA256(SHA256(`tag`) ||
|
||||
* SHA256(`tag`) || `msg`) */
|
||||
|
||||
|
@ -329,7 +329,7 @@ int main(int argc, char *argv[])
|
|||
tlv_update_fields(invreq, tlv_invoice_request, &invreq->fields);
|
||||
merkle_tlv(invreq->fields, &test_m);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST set `signature`.`sig` as detailed in [Signature Calculation](#signature-calculation) using the `invreq_payer_id`.
|
||||
*/
|
||||
invreq->signature = tal(invreq, struct bip340sig);
|
||||
|
|
|
@ -84,7 +84,7 @@ static const char *handle_onion(const tal_t *ctx,
|
|||
|
||||
assert(next_onion_msg);
|
||||
|
||||
/* BOLT-offers #4:
|
||||
/* BOLT #4:
|
||||
* - if it is not the final node according to the onion encryption:
|
||||
*...
|
||||
* - if `next_node_id` is present:
|
||||
|
|
|
@ -94,15 +94,15 @@ static bool print_offer_amount(const struct bitcoin_blkid *chains,
|
|||
unsigned int minor_unit;
|
||||
bool ok = true;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if a specific minimum `offer_amount` is required for successful payment:
|
||||
* - MUST set `offer_amount` to the amount expected (per item).
|
||||
* - if the currency for `offer_amount` is that of all entries in `chains`:
|
||||
* - MUST specify `amount` in multiples of the minimum lightning-payable unit
|
||||
* - MUST specify `offer_amount` in multiples of the minimum lightning-payable unit
|
||||
* (e.g. milli-satoshis for bitcoin).
|
||||
* - otherwise:
|
||||
* - MUST specify `offer_currency` `iso4217` as an ISO 4712 three-letter code.
|
||||
* - MUST specify `offer_amount` in the currency unit adjusted by the ISO 4712
|
||||
* - MUST specify `offer_currency` `iso4217` as an ISO 4217 three-letter code.
|
||||
* - MUST specify `offer_amount` in the currency unit adjusted by the ISO 4217
|
||||
* exponent (e.g. USD cents).
|
||||
* - MUST set `offer_description` to a complete description of the purpose
|
||||
* of the payment.
|
||||
|
@ -183,7 +183,7 @@ static bool print_recurrance(const struct recurrence *recurrence,
|
|||
const char *unit;
|
||||
bool ok = true;
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* Thus, each offer containing a recurring payment has:
|
||||
* 1. A `time_unit` defining 0 (seconds), 1 (days), 2 (months),
|
||||
* 3 (years).
|
||||
|
@ -363,7 +363,7 @@ static void print_relative_expiry(u64 *created_at, u32 *relative)
|
|||
if (!created_at)
|
||||
return;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `invoice_relative_expiry` is present:
|
||||
* - MUST reject the invoice if the current time since 1970-01-01 UTC
|
||||
* is greater than `invoice_created_at` plus `seconds_from_creation`.
|
||||
|
@ -453,7 +453,7 @@ static u64 get_offer_type(const char *name)
|
|||
const char *name;
|
||||
u64 val;
|
||||
} map[] = {
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* 1. `tlv_stream`: `offer`
|
||||
* 2. types:
|
||||
* 1. type: 2 (`offer_chains`)
|
||||
|
@ -501,7 +501,7 @@ static u64 get_offer_type(const char *name)
|
|||
{ "offer_issuer", 18 },
|
||||
{ "offer_quantity_max", 20 },
|
||||
{ "offer_issuer_id", 22 },
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* 1. `tlv_stream`: `invoice_request`
|
||||
* 2. types:
|
||||
* 1. type: 0 (`invreq_metadata`)
|
||||
|
@ -581,7 +581,7 @@ static u64 get_offer_type(const char *name)
|
|||
{ "invreq_paths", 90 },
|
||||
{ "invreq_bip_353_name", 91 },
|
||||
{ "signature", 240 },
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* 1. `tlv_stream`: `invoice`
|
||||
* 2. types:
|
||||
* 1. type: 0 (`invreq_metadata`)
|
||||
|
@ -833,7 +833,7 @@ int main(int argc, char *argv[])
|
|||
*offer->offer_amount);
|
||||
if (offer->offer_description)
|
||||
well_formed &= print_utf8("offer_description", offer->offer_description);
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `offer_amount` is set and `offer_description` is not set:
|
||||
* - MUST NOT respond to the offer.
|
||||
*/
|
||||
|
@ -853,7 +853,7 @@ int main(int argc, char *argv[])
|
|||
print_u64("offer_quantity_max", *offer->offer_quantity_max);
|
||||
if (offer->offer_issuer_id)
|
||||
print_node_id("offer_issuer_id", offer->offer_issuer_id);
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* - if neither `offer_issuer_id` nor `offer_paths` are set:
|
||||
* - MUST NOT respond to the offer.
|
||||
|
|
|
@ -1647,7 +1647,7 @@ static void add_stub_blindedpath(const tal_t *ctx,
|
|||
inv->invoice_paths = tal_arr(inv, struct blinded_path *, 1);
|
||||
inv->invoice_paths[0] = tal_steal(inv->invoice_paths, path);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST include `invoice_paths` containing one or more paths to the node.
|
||||
* - MUST specify `invoice_paths` in order of most-preferred to least-preferred if it has a preference.
|
||||
* - MUST include `invoice_blindedpay` with exactly one `blinded_payinfo` for each `blinded_path` in `paths`, in order.
|
||||
|
@ -1745,7 +1745,7 @@ static struct command_result *json_createinvoice(struct command *cmd,
|
|||
"Unparsable invoice '%s': %s",
|
||||
invstring, fail);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A writer of an invoice:
|
||||
*...
|
||||
* - MUST include `invoice_paths` containing one or more paths
|
||||
|
@ -1777,7 +1777,7 @@ static struct command_result *json_createinvoice(struct command *cmd,
|
|||
} else
|
||||
local_offer_id = NULL;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A writer of an invoice:
|
||||
*...
|
||||
* - MUST set `invoice_amount` to the minimum amount it will
|
||||
|
|
|
@ -314,7 +314,7 @@ static struct command_result *prev_payment(struct command *cmd,
|
|||
if (!inv->invreq_recurrence_counter)
|
||||
continue;
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - if the offer contained `recurrence_base` with
|
||||
* `start_any_period` non-zero:
|
||||
* - MUST include `recurrence_start`
|
||||
|
@ -500,7 +500,7 @@ static struct command_result *json_createinvoicerequest(struct command *cmd,
|
|||
if (command_check_only(cmd))
|
||||
return command_check_done(cmd);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST set `signature`.`sig` as detailed in
|
||||
* [Signature Calculation](#signature-calculation) using the `invreq_payer_id`.
|
||||
*/
|
||||
|
|
|
@ -139,9 +139,9 @@ static struct command_result *handle_error(struct command *cmd,
|
|||
return command_hook_success(cmd);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if the invoice is a response to an `invoice_request`:
|
||||
* - MUST reject the invoice if all fields in ranges 0 to 159 and 1000000000 to 2999999999 (inclusive) do not exactly match the `invoice_request`.
|
||||
* - MUST reject the invoice if all fields in ranges 0 to 159 and 1000000000 to 2999999999 (inclusive) do not exactly match the invoice request.
|
||||
*/
|
||||
static bool invoice_matches_request(struct command *cmd,
|
||||
const u8 *invbin,
|
||||
|
@ -210,18 +210,18 @@ static struct command_result *handle_invreq_response(struct command *cmd,
|
|||
return command_hook_success(cmd);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if the invoice is a response to an `invoice_request`:
|
||||
* - MUST reject the invoice if all fields in ranges 0 to 159 and
|
||||
* 1000000000 to 2999999999 (inclusive) do not exactly match the
|
||||
* `invoice_request`.
|
||||
* invoice request.
|
||||
*/
|
||||
if (!invoice_matches_request(cmd, invbin, sent->invreq)) {
|
||||
badfield = "invoice_request match";
|
||||
goto badinv;
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A reader of an invoice:
|
||||
* - MUST reject the invoice if `invoice_amount` is not present.
|
||||
* - MUST reject the invoice if `invoice_created_at` is not present.
|
||||
|
@ -244,12 +244,12 @@ static struct command_result *handle_invreq_response(struct command *cmd,
|
|||
badfield = "invoice_node_id";
|
||||
goto badinv;
|
||||
}
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `offer_issuer_id` is present (invoice_request for an offer):
|
||||
* - MUST reject the invoice if `invoice_node_id` is not equal to `offer_issuer_id`
|
||||
* - otherwise, if `offer_paths` is present (invoice_request for an offer without id):
|
||||
* - MUST reject the invoice if `invoice_node_id` is not equal to the final
|
||||
* `blinded_node_id` it sent the `invoice_request` to.
|
||||
* `blinded_node_id` it sent the invoice request to.
|
||||
*/
|
||||
/* Either way, we save the expected id in issuer_key */
|
||||
if (!pubkey_eq(inv->invoice_node_id, sent->issuer_key)) {
|
||||
|
@ -257,7 +257,7 @@ static struct command_result *handle_invreq_response(struct command *cmd,
|
|||
goto badinv;
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST reject the invoice if `signature` is not a valid signature
|
||||
* using `invoice_node_id` as described in [Signature Calculation]
|
||||
*/
|
||||
|
@ -290,7 +290,7 @@ static struct command_result *handle_invreq_response(struct command *cmd,
|
|||
} else
|
||||
expected_amount = NULL;
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - if the offer contained `recurrence`:
|
||||
* - MUST reject the invoice if `recurrence_basetime` is not set.
|
||||
*/
|
||||
|
@ -302,7 +302,7 @@ static struct command_result *handle_invreq_response(struct command *cmd,
|
|||
out = jsonrpc_stream_success(sent->cmd);
|
||||
json_add_string(out, "invoice", invoice_encode(tmpctx, inv));
|
||||
json_object_start(out, "changes");
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - SHOULD confirm authorization if `invoice_amount`.`msat` is not within
|
||||
* the amount range authorized.
|
||||
*/
|
||||
|
@ -586,11 +586,11 @@ static struct command_result *try_establish(struct command *cmd,
|
|||
if (!gossmap_scidd_pubkey(get_gossmap(cmd->plugin), &first))
|
||||
return establish_path_fail(cmd, "Cannot resolve scidd", epaths);
|
||||
target = first.pubkey;
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `offer_issuer_id` is present (invoice_request for an offer):
|
||||
* - MUST reject the invoice if `invoice_node_id` is not equal to `offer_issuer_id`
|
||||
* - otherwise, if `offer_paths` is present (invoice_request for an offer without id):
|
||||
* - MUST reject the invoice if `invoice_node_id` is not equal to the final `blinded_node_id` it sent the `invoice_request` to.
|
||||
* - MUST reject the invoice if `invoice_node_id` is not equal to the final `blinded_node_id` it sent the invoice request to.
|
||||
*/
|
||||
if (epaths->sent->offer && !epaths->sent->offer->offer_issuer_id)
|
||||
epaths->sent->issuer_key = &bpath->path[tal_count(bpath->path)-1]->blinded_node_id;
|
||||
|
@ -699,7 +699,7 @@ static struct command_result *invreq_done(struct command *cmd,
|
|||
if (sent->invreq->invreq_recurrence_start)
|
||||
period_idx += *sent->invreq->invreq_recurrence_start;
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - if the offer contained `recurrence_limit`:
|
||||
* - MUST NOT send an `invoice_request` for a period greater
|
||||
* than `max_period`
|
||||
|
@ -712,7 +712,7 @@ static struct command_result *invreq_done(struct command *cmd,
|
|||
period_idx,
|
||||
*sent->invreq->offer_recurrence_limit);
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - SHOULD NOT send an `invoice_request` for a period which has
|
||||
* already passed.
|
||||
*/
|
||||
|
@ -854,15 +854,15 @@ struct command_result *json_fetchinvoice(struct command *cmd,
|
|||
/* This is NULL if offer_issuer_id is missing, and set by try_establish */
|
||||
sent->issuer_key = sent->offer->offer_issuer_id;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
* - SHOULD not respond to an offer if the current time is after
|
||||
* `offer_absolute_expiry`.
|
||||
/* BOLT #12:
|
||||
* - if the current time is after `offer_absolute_expiry`:
|
||||
* - MUST NOT respond to the offer.
|
||||
*/
|
||||
if (sent->offer->offer_absolute_expiry
|
||||
&& time_now().ts.tv_sec > *sent->offer->offer_absolute_expiry)
|
||||
return command_fail(cmd, OFFER_EXPIRED, "Offer expired");
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* The writer:
|
||||
* - if it is responding to an offer:
|
||||
* - MUST copy all fields from the offer (including unknown fields).
|
||||
|
@ -872,7 +872,7 @@ struct command_result *json_fetchinvoice(struct command *cmd,
|
|||
invreq->invreq_recurrence_start = tal_steal(invreq, recurrence_start);
|
||||
invreq->invreq_quantity = tal_steal(invreq, quantity);
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - if `offer_amount` is not present:
|
||||
* - MUST specify `invreq_amount`.
|
||||
* - otherwise:
|
||||
|
@ -896,7 +896,7 @@ struct command_result *json_fetchinvoice(struct command *cmd,
|
|||
&msat->millisatoshis); /* Raw: tu64 */
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `offer_quantity_max` is present:
|
||||
* - MUST set `invreq_quantity` to greater than zero.
|
||||
* - if `offer_quantity_max` is non-zero:
|
||||
|
@ -921,19 +921,19 @@ struct command_result *json_fetchinvoice(struct command *cmd,
|
|||
"quantity parameter unnecessary");
|
||||
}
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - if the offer contained `recurrence`:
|
||||
*/
|
||||
if (invreq->offer_recurrence) {
|
||||
struct sha256 offer_id, tweak;
|
||||
u8 *tweak_input;
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - for the initial request:
|
||||
*...
|
||||
* - MUST set `recurrence_counter` `counter` to 0.
|
||||
*/
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - for any successive requests:
|
||||
*...
|
||||
* - MUST set `recurrence_counter` `counter` to one greater
|
||||
|
@ -947,7 +947,7 @@ struct command_result *json_fetchinvoice(struct command *cmd,
|
|||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"Cannot set payer_metadata for recurring offers");
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - if the offer contained `recurrence_base` with
|
||||
* `start_any_period` non-zero:
|
||||
* - MUST include `recurrence_start`
|
||||
|
@ -972,7 +972,7 @@ struct command_result *json_fetchinvoice(struct command *cmd,
|
|||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"needs recurrence_label");
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST set `invreq_metadata` to an unpredictable series of
|
||||
* bytes.
|
||||
*/
|
||||
|
@ -995,7 +995,7 @@ struct command_result *json_fetchinvoice(struct command *cmd,
|
|||
invreq->invreq_metadata
|
||||
= (u8 *)tal_dup(invreq, struct sha256, &tweak);
|
||||
} else {
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - otherwise:
|
||||
* - MUST NOT set `recurrence_counter`.
|
||||
* - MUST NOT set `recurrence_start`
|
||||
|
@ -1011,7 +1011,7 @@ struct command_result *json_fetchinvoice(struct command *cmd,
|
|||
if (payer_metadata) {
|
||||
invreq->invreq_metadata = tal_steal(invreq, payer_metadata);
|
||||
} else {
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST set `invreq_metadata` to an unpredictable series of
|
||||
* bytes.
|
||||
*/
|
||||
|
@ -1062,11 +1062,11 @@ struct command_result *json_fetchinvoice(struct command *cmd,
|
|||
"Invalid tweak for payer_id");
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* - if `offer_chains` is set:
|
||||
* - MUST set `invreq_chain` to one of `offer_chains` unless that
|
||||
* chain is bitcoin, in which case it MAY omit `invreq_chain`.
|
||||
* chain is bitcoin, in which case it SHOULD omit `invreq_chain`.
|
||||
* - otherwise:
|
||||
* - if it sets `invreq_chain` it MUST set it to bitcoin.
|
||||
*/
|
||||
|
@ -1076,7 +1076,7 @@ struct command_result *json_fetchinvoice(struct command *cmd,
|
|||
&chainparams->genesis_blockhash);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if it supports bolt12 invoice request features:
|
||||
* - MUST set `invreq_features`.`features` to the bitmap of features.
|
||||
*/
|
||||
|
@ -1183,7 +1183,7 @@ static struct command_result *createinvoice_done(struct command *cmd,
|
|||
"Bad createinvoice response %s", fail);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if it sends an invoice in response:
|
||||
* - MUST use `invreq_paths` if present, otherwise MUST use
|
||||
* `invreq_payer_id` as the node id to send to.
|
||||
|
@ -1228,11 +1228,15 @@ static struct command_result *param_invreq(struct command *cmd,
|
|||
int badf;
|
||||
struct sha256 merkle, sighash;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* FIXME: quote is garbled, see: https://github.com/lightning/bolts/pull/1222 */
|
||||
/* BOLT #12:
|
||||
* - if `invreq_chain` is not present:
|
||||
* - MUST fail the request if bitcoin is not a supported chain.
|
||||
* - MUST reject the invoice request if bitcoin is not a supported chain.
|
||||
* - if `invreq_bip_353_name` is present:
|
||||
* - MUST reject the invoice request if `name` or `domain` contain any bytes which are not
|
||||
* `0`-`9`, `a`-`z`, `A`-`Z`, `-`, `_` or `.`.
|
||||
* - otherwise:
|
||||
* - MUST fail the request if `invreq_chain`.`chain` is not a
|
||||
* - MUST reject the invoice request if `invreq_chain`.`chain` is not a
|
||||
* supported chain.
|
||||
*/
|
||||
*invreq = invrequest_decode(cmd,
|
||||
|
@ -1245,17 +1249,17 @@ static struct command_result *param_invreq(struct command *cmd,
|
|||
tal_fmt(cmd,
|
||||
"Unparsable invoice_request: %s",
|
||||
fail));
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* The reader:
|
||||
* - MUST fail the request if `invreq_payer_id` or `invreq_metadata`
|
||||
* - MUST reject the invoice request if `invreq_payer_id` or `invreq_metadata`
|
||||
* are not present.
|
||||
* - MUST fail the request if any non-signature TLV fields are outside the inclusive ranges: 0 to 159 and 1000000000 to 2999999999
|
||||
* - MUST reject the invoice request if any non-signature TLV fields are outside the inclusive ranges: 0 to 159 and 1000000000 to 2999999999
|
||||
* - if `invreq_features` contains unknown _odd_ bits that are
|
||||
* non-zero:
|
||||
* - MUST ignore the bit.
|
||||
* - if `invreq_features` contains unknown _even_ bits that are
|
||||
* non-zero:
|
||||
* - MUST fail the request.
|
||||
* - MUST reject the invoice request.
|
||||
*/
|
||||
if (!(*invreq)->invreq_payer_id)
|
||||
return command_fail_badparam(cmd, name, buffer, tok,
|
||||
|
@ -1282,8 +1286,8 @@ static struct command_result *param_invreq(struct command *cmd,
|
|||
badf));
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
* - MUST fail the request if `signature` is not correct as detailed in [Signature
|
||||
/* BOLT #12:
|
||||
* - MUST reject the invoice request if `signature` is not correct as detailed in [Signature
|
||||
* Calculation](#signature-calculation) using the `invreq_payer_id`.
|
||||
*/
|
||||
merkle_tlv((*invreq)->fields, &merkle);
|
||||
|
@ -1305,11 +1309,11 @@ static struct command_result *param_invreq(struct command *cmd,
|
|||
"This is based on an offer?");
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - otherwise (no `offer_issuer_id` or `offer_paths`, not a response to our offer):
|
||||
* - MUST fail the request if any of the following are present:
|
||||
* - MUST reject the invoice request if any of the following are present:
|
||||
* - `offer_chains`, `offer_features` or `offer_quantity_max`.
|
||||
* - MUST fail the request if `invreq_amount` is not present.
|
||||
* - MUST reject the invoice request if `invreq_amount` is not present.
|
||||
*/
|
||||
if ((*invreq)->offer_chains)
|
||||
return command_fail_badparam(cmd, name, buffer, tok,
|
||||
|
@ -1324,7 +1328,7 @@ static struct command_result *param_invreq(struct command *cmd,
|
|||
return command_fail_badparam(cmd, name, buffer, tok,
|
||||
"Missing invreq_amount");
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - otherwise (no `offer_issuer_id` or `offer_paths`, not a response to our offer):
|
||||
*...
|
||||
* - MAY use `offer_amount` (or `offer_currency`) for informational display to user.
|
||||
|
@ -1366,9 +1370,9 @@ struct command_result *json_sendinvoice(struct command *cmd,
|
|||
sent->their_paths = sent->invreq->offer_paths;
|
||||
sent->direct_dest = sent->invreq->invreq_payer_id;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if the invoice is in response to an `invoice_request`:
|
||||
* - MUST copy all non-signature fields from the `invoice_request`
|
||||
* - MUST copy all non-signature fields from the invoice request
|
||||
* (including unknown fields).
|
||||
*/
|
||||
sent->inv = invoice_for_invreq(sent, sent->invreq);
|
||||
|
@ -1376,7 +1380,7 @@ struct command_result *json_sendinvoice(struct command *cmd,
|
|||
/* This is how long we'll wait for a reply for. */
|
||||
sent->wait_timeout = *timeout;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `invreq_amount` is present:
|
||||
* - MUST set `invoice_amount` to `invreq_amount`
|
||||
* - otherwise:
|
||||
|
@ -1389,7 +1393,7 @@ struct command_result *json_sendinvoice(struct command *cmd,
|
|||
sent->inv->invoice_amount = tal_dup(sent->inv, u64,
|
||||
&msat->millisatoshis); /* Raw: tlv */
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST set `invoice_created_at` to the number of seconds since Midnight 1
|
||||
* January 1970, UTC when the invoice was created.
|
||||
* - MUST set `invoice_amount` to the minimum amount it will accept, in units of
|
||||
|
@ -1401,7 +1405,7 @@ struct command_result *json_sendinvoice(struct command *cmd,
|
|||
|
||||
/* FIXME: Support blinded paths, in which case use fake nodeid */
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST set `invoice_payment_hash` to the SHA256 hash of the
|
||||
* `payment_preimage` that will be given in return for payment.
|
||||
*/
|
||||
|
@ -1410,19 +1414,16 @@ struct command_result *json_sendinvoice(struct command *cmd,
|
|||
sha256(sent->inv->invoice_payment_hash,
|
||||
&sent->inv_preimage, sizeof(sent->inv_preimage));
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `offer_issuer_id` is present:
|
||||
* - MUST set `invoice_node_id` to the `offer_issuer_id`
|
||||
* - otherwise, if `offer_paths` is present:
|
||||
* - MUST set `invoice_node_id` to the final `blinded_node_id` on the path it received the `invoice_request`
|
||||
* - otherwise:
|
||||
* - MUST set `invoice_node_id` to a valid public key.
|
||||
* - MUST set `invoice_node_id` to the final `blinded_node_id` on the path it received the invoice request
|
||||
*/
|
||||
/* FIXME: Use transitory id! */
|
||||
sent->inv->invoice_node_id = tal(sent->inv, struct pubkey);
|
||||
sent->inv->invoice_node_id->pubkey = id.pubkey;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if the expiry for accepting payment is not 7200 seconds
|
||||
* after `invoice_created_at`:
|
||||
* - MUST set `invoice_relative_expiry`.`seconds_from_creation`
|
||||
|
|
|
@ -584,7 +584,7 @@ static bool json_add_blinded_paths(struct command *cmd,
|
|||
}
|
||||
json_array_end(js);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST reject the invoice if `invoice_blindedpay` does not contain
|
||||
* exactly one `blinded_payinfo` per `invoice_paths`.`blinded_path`.
|
||||
*/
|
||||
|
@ -595,7 +595,7 @@ static bool json_add_blinded_paths(struct command *cmd,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `num_hops` is 0 in any `blinded_path` in `offer_paths`:
|
||||
* - MUST NOT respond to the offer.
|
||||
*/
|
||||
|
@ -613,7 +613,7 @@ static bool json_add_blinded_paths(struct command *cmd,
|
|||
|
||||
static const char *recurrence_time_unit_name(u8 time_unit)
|
||||
{
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* `time_unit` defining 0 (seconds), 1 (days), 2 (months), 3 (years).
|
||||
*/
|
||||
switch (time_unit) {
|
||||
|
@ -681,7 +681,7 @@ static bool json_add_offer_fields(struct command *cmd,
|
|||
} else if (offer_amount)
|
||||
json_add_amount_msat(js, "offer_amount_msat",
|
||||
amount_msat(*offer_amount));
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* - if `offer_amount` is set and `offer_description` is not set:
|
||||
* - MUST NOT respond to the offer.
|
||||
|
@ -792,7 +792,7 @@ static void json_add_offer(struct command *cmd, struct json_stream *js, const st
|
|||
offer->offer_recurrence_paywindow,
|
||||
offer->offer_recurrence_limit,
|
||||
offer->offer_recurrence_base);
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if neither `offer_issuer_id` nor `offer_paths` are set:
|
||||
* - MUST NOT respond to the offer.
|
||||
*/
|
||||
|
@ -821,8 +821,8 @@ static bool json_add_invreq_fields(struct command *cmd,
|
|||
{
|
||||
bool valid = true;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
* - MUST fail the request if `invreq_payer_id` or `invreq_metadata` are not present.
|
||||
/* BOLT #12:
|
||||
* - MUST reject the invoice request if `invreq_payer_id` or `invreq_metadata` are not present.
|
||||
*/
|
||||
if (invreq_metadata)
|
||||
json_add_hex_talarr(js, "invreq_metadata",
|
||||
|
@ -933,7 +933,7 @@ static bool json_add_fallbacks(struct json_stream *js,
|
|||
json_add_u32(js, "version", fallbacks[i]->version);
|
||||
json_add_hex_talarr(js, "hex", fallbacks[i]->address);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - for the bitcoin chain, if the invoice specifies `invoice_fallbacks`:
|
||||
* - MUST ignore any `fallback_address` for which `version` is
|
||||
* greater than 16.
|
||||
|
@ -1007,8 +1007,8 @@ static void json_add_invoice_request(struct command *cmd,
|
|||
invreq->invreq_recurrence_counter,
|
||||
invreq->invreq_recurrence_start);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
* - MUST fail the request if `invreq_payer_id` or `invreq_metadata` are not present.
|
||||
/* BOLT #12:
|
||||
* - MUST reject the invoice request if `invreq_payer_id` or `invreq_metadata` are not present.
|
||||
*/
|
||||
if (!invreq->invreq_payer_id) {
|
||||
json_add_string(js, "warning_missing_invreq_payer_id",
|
||||
|
@ -1016,8 +1016,8 @@ static void json_add_invoice_request(struct command *cmd,
|
|||
valid = false;
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
* - MUST fail the request if `signature` is not correct as detailed
|
||||
/* BOLT #12:
|
||||
* - MUST reject the invoice request if `signature` is not correct as detailed
|
||||
* in [Signature Calculation](#signature-calculation) using the
|
||||
* `invreq_payer_id`.
|
||||
*/
|
||||
|
@ -1097,7 +1097,7 @@ static void json_add_b12_invoice(struct command *cmd,
|
|||
invoice->invreq_recurrence_counter,
|
||||
invoice->invreq_recurrence_start);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST reject the invoice if `invoice_paths` is not present
|
||||
* or is empty.
|
||||
* - MUST reject the invoice if `num_hops` is 0 in any `blinded_path` in `invoice_paths`.
|
||||
|
@ -1128,7 +1128,7 @@ static void json_add_b12_invoice(struct command *cmd,
|
|||
valid = false;
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* - if `invoice_relative_expiry` is present:
|
||||
* - MUST reject the invoice if the current time since 1970-01-01 UTC
|
||||
|
@ -1150,7 +1150,7 @@ static void json_add_b12_invoice(struct command *cmd,
|
|||
valid = false;
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST reject the invoice if `invoice_amount` is not present.
|
||||
*/
|
||||
if (invoice->invoice_amount)
|
||||
|
@ -1178,7 +1178,7 @@ static void json_add_b12_invoice(struct command *cmd,
|
|||
valid = false;
|
||||
}
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - if the offer contained `recurrence`:
|
||||
* - MUST reject the invoice if `recurrence_basetime` is not
|
||||
* set.
|
||||
|
|
|
@ -133,15 +133,15 @@ static struct command_result *listinvreqs_done(struct command *cmd,
|
|||
struct out_req *req;
|
||||
struct sha256 merkle, sighash;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A reader of an invoice:
|
||||
*...
|
||||
* - if the invoice is a response to an `invoice_request`:
|
||||
* - MUST reject the invoice if all fields in ranges 0 to 159 and 1000000000 to 2999999999 (inclusive) do not exactly match the `invoice_request`.
|
||||
* - MUST reject the invoice if all fields in ranges 0 to 159 and 1000000000 to 2999999999 (inclusive) do not exactly match the invoice request.
|
||||
* - if `offer_issuer_id` is present (invoice_request for an offer):
|
||||
* - MUST reject the invoice if `invoice_node_id` is not equal to `offer_issuer_id`
|
||||
* - otherwise, if `offer_paths` is present (invoice_request for an offer without id):
|
||||
* - MUST reject the invoice if `invoice_node_id` is not equal to the final `blinded_node_id` it sent the `invoice_request` to.
|
||||
* - MUST reject the invoice if `invoice_node_id` is not equal to the final `blinded_node_id` it sent the invoice request to.
|
||||
* - otherwise (invoice_request without an offer):
|
||||
* - MAY reject the invoice if it cannot confirm that `invoice_node_id` is correct, out-of-band.
|
||||
*/
|
||||
|
@ -165,7 +165,7 @@ static struct command_result *listinvreqs_done(struct command *cmd,
|
|||
/* We only save ones without offers to the db! */
|
||||
assert(!inv->inv->offer_issuer_id && !inv->inv->offer_paths);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST reject the invoice if `signature` is not a valid signature
|
||||
* using `invoice_node_id` as described in [Signature
|
||||
* Calculation](#signature-calculation).
|
||||
|
@ -178,7 +178,7 @@ static struct command_result *listinvreqs_done(struct command *cmd,
|
|||
if (!check_schnorr_sig(&sighash, &inv->inv->invoice_node_id->pubkey, inv->inv->signature))
|
||||
return fail_inv(cmd, inv, "invalid invoice signature");
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - SHOULD confirm authorization if `invoice_amount`.`msat` is not
|
||||
* within the amount range authorized.
|
||||
*/
|
||||
|
@ -267,7 +267,7 @@ struct command_result *handle_invoice(struct command *cmd,
|
|||
|
||||
invoice_invreq_id(inv->inv, &inv->invreq_id);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A reader of an invoice:
|
||||
* - MUST reject the invoice if `invoice_amount` is not present.
|
||||
* - MUST reject the invoice if `invoice_created_at` is not present.
|
||||
|
@ -283,7 +283,7 @@ struct command_result *handle_invoice(struct command *cmd,
|
|||
if (!inv->inv->invoice_node_id)
|
||||
return fail_inv(cmd, inv, "Missing invoice_node_id");
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A reader of an invoice:
|
||||
*...
|
||||
* - if `invoice_features` contains unknown _odd_ bits that are non-zero:
|
||||
|
@ -300,7 +300,7 @@ struct command_result *handle_invoice(struct command *cmd,
|
|||
bad_feature);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A reader of an invoice:
|
||||
*...
|
||||
* - if `invoice_relative_expiry` is present:
|
||||
|
@ -315,7 +315,7 @@ struct command_result *handle_invoice(struct command *cmd,
|
|||
if (time_now().ts.tv_sec > invexpiry)
|
||||
return fail_inv(cmd, inv, "Expired invoice");
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A reader of an invoice:
|
||||
*...
|
||||
* - MUST reject the invoice if `invoice_paths` is not present or is empty.
|
||||
|
@ -336,7 +336,7 @@ struct command_result *handle_invoice(struct command *cmd,
|
|||
return fail_inv(cmd, inv,
|
||||
"Mismatch between invoice_blindedpay and invoice_paths");
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A reader of an invoice:
|
||||
*...
|
||||
* - For each `invoice_blindedpay`.`payinfo`:
|
||||
|
|
|
@ -121,7 +121,7 @@ test_field(struct command *cmd,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - if the invoice corresponds to an offer with `recurrence`:
|
||||
* ...
|
||||
* - if it sets `relative_expiry`:
|
||||
|
@ -247,7 +247,7 @@ static struct command_result *found_best_peer(struct command *cmd,
|
|||
const struct chaninfo *best,
|
||||
struct invreq *ir)
|
||||
{
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST include `invoice_paths` containing one or more paths to the node.
|
||||
* - MUST specify `invoice_paths` in order of most-preferred to
|
||||
* least-preferred if it has a preference.
|
||||
|
@ -287,7 +287,7 @@ static struct command_result *found_best_peer(struct command *cmd,
|
|||
etlvs[0]->payment_relay->fee_base_msat = best->feebase;
|
||||
etlvs[0]->payment_relay->fee_proportional_millionths = best->feeppm;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if the expiry for accepting payment is not 7200 seconds
|
||||
* after `invoice_created_at`:
|
||||
* - MUST set `invoice_relative_expiry`
|
||||
|
@ -375,7 +375,7 @@ static struct command_result *check_period(struct command *cmd,
|
|||
if (ir->invreq->offer_recurrence_base)
|
||||
basetime = ir->invreq->offer_recurrence_base->basetime;
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - if the invoice corresponds to an offer with `recurrence`:
|
||||
* - MUST set `recurrence_basetime` to the start of period #0 as
|
||||
* calculated by [Period Calculation](#offer-period-calculation).
|
||||
|
@ -384,7 +384,7 @@ static struct command_result *check_period(struct command *cmd,
|
|||
|
||||
period_idx = *ir->invreq->invreq_recurrence_counter;
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - if the offer had `recurrence_base` and `start_any_period`
|
||||
* was 1:
|
||||
* - MUST fail the request if there is no `recurrence_start`
|
||||
|
@ -400,14 +400,14 @@ static struct command_result *check_period(struct command *cmd,
|
|||
return err;
|
||||
period_idx += *ir->invreq->invreq_recurrence_start;
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - MUST set (or not set) `recurrence_start` exactly as the
|
||||
* invreq did.
|
||||
*/
|
||||
ir->inv->invreq_recurrence_start
|
||||
= tal_dup(ir->inv, u32, ir->invreq->invreq_recurrence_start);
|
||||
} else {
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
*
|
||||
* - otherwise:
|
||||
* - MUST fail the request if there is a `recurrence_start`
|
||||
|
@ -420,7 +420,7 @@ static struct command_result *check_period(struct command *cmd,
|
|||
return err;
|
||||
}
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - if the offer has a `recurrence_limit`:
|
||||
* - MUST fail the request if the period index is greater than
|
||||
* `max_period`.
|
||||
|
@ -454,7 +454,7 @@ static struct command_result *check_period(struct command *cmd,
|
|||
|
||||
set_recurring_inv_expiry(ir->inv, paywindow_end);
|
||||
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
*
|
||||
* - if `recurrence_counter` is non-zero:
|
||||
*...
|
||||
|
@ -561,9 +561,9 @@ static struct command_result *check_previous_invoice(struct command *cmd,
|
|||
return send_outreq(req);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
|
||||
* - MUST fail the request if `signature` is not correct as detailed in
|
||||
* - MUST reject the invoice request if `signature` is not correct as detailed in
|
||||
* [Signature Calculation](#signature-calculation) using the
|
||||
* `invreq_payer_id`.
|
||||
*...
|
||||
|
@ -588,12 +588,12 @@ static struct command_result *invreq_amount_by_quantity(struct command *cmd,
|
|||
{
|
||||
assert(ir->invreq->offer_amount);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST calculate the *expected amount* using the `offer_amount`:
|
||||
*/
|
||||
*raw_amt = *ir->invreq->offer_amount;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `invreq_quantity` is present, multiply by `invreq_quantity`.`quantity`.
|
||||
*/
|
||||
if (ir->invreq->invreq_quantity) {
|
||||
|
@ -625,12 +625,12 @@ static struct command_result *invreq_base_amount_simple(struct command *cmd,
|
|||
|
||||
*amt = amount_msat(raw_amount);
|
||||
} else {
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* The reader:
|
||||
*...
|
||||
* - otherwise (no `offer_amount`):
|
||||
* - MUST fail the request if it does not contain
|
||||
* - MUST reject the invoice request if it does not contain
|
||||
* `invreq_amount`.
|
||||
*/
|
||||
err = invreq_must_have(cmd, ir, invreq_amount);
|
||||
|
@ -646,9 +646,9 @@ static struct command_result *handle_amount_and_recurrence(struct command *cmd,
|
|||
struct invreq *ir,
|
||||
struct amount_msat base_inv_amount)
|
||||
{
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `invreq_amount` is present:
|
||||
* - MUST fail the request if `invreq_amount`.`msat` is less than the
|
||||
* - MUST reject the invoice request if `invreq_amount`.`msat` is less than the
|
||||
* *expected amount*.
|
||||
*/
|
||||
if (ir->invreq->offer_amount && ir->invreq->invreq_amount) {
|
||||
|
@ -657,8 +657,8 @@ static struct command_result *handle_amount_and_recurrence(struct command *cmd,
|
|||
fmt_amount_msat(tmpctx,
|
||||
base_inv_amount));
|
||||
}
|
||||
/* BOLT-offers #12:
|
||||
* - MAY fail the request if `invreq_amount`.`msat` greatly exceeds
|
||||
/* BOLT #12:
|
||||
* - MAY reject the invoice request if `invreq_amount`.`msat` greatly exceeds
|
||||
* the *expected amount*.
|
||||
*/
|
||||
/* Much == 5? Easier to divide and compare, than multiply. */
|
||||
|
@ -671,7 +671,7 @@ static struct command_result *handle_amount_and_recurrence(struct command *cmd,
|
|||
base_inv_amount = amount_msat(*ir->invreq->invreq_amount);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `invreq_amount` is present:
|
||||
* - MUST set `invoice_amount` to `invreq_amount`
|
||||
* - otherwise:
|
||||
|
@ -738,7 +738,7 @@ static struct command_result *convert_currency(struct command *cmd,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST calculate the *expected amount* using the `offer_amount`:
|
||||
* - if `offer_currency` is not the `invreq_chain` currency, convert to the
|
||||
* `invreq_chain` currency.
|
||||
|
@ -776,9 +776,9 @@ static struct command_result *listoffers_done(struct command *cmd,
|
|||
struct command_result *err;
|
||||
struct amount_msat amt;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* - MUST fail the request if the offer fields do not exactly match a
|
||||
* - MUST reject the invoice request if the offer fields do not exactly match a
|
||||
* valid, unexpired offer.
|
||||
*/
|
||||
if (arr->size == 0)
|
||||
|
@ -787,12 +787,12 @@ static struct command_result *listoffers_done(struct command *cmd,
|
|||
/* Now, since we looked up by hash, we know that the entire offer
|
||||
* is faithfully mirrored in this invreq. */
|
||||
|
||||
/* BOLT-offers #4:
|
||||
/* BOLT #4:
|
||||
*
|
||||
* The final recipient:
|
||||
* If it is the final recipient:
|
||||
*...
|
||||
* - MUST ignore the message if the `path_id` does not match
|
||||
* the blinded route it created
|
||||
* the blinded route it created for this purpose
|
||||
*/
|
||||
offertok = arr + 1;
|
||||
if (ir->secret) {
|
||||
|
@ -853,14 +853,14 @@ static struct command_result *listoffers_done(struct command *cmd,
|
|||
return fail_invreq(cmd, ir, "Offer expired");
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `offer_quantity_max` is present:
|
||||
* - MUST fail the request if there is no `invreq_quantity` field.
|
||||
* - MUST reject the invoice request if there is no `invreq_quantity` field.
|
||||
* - if `offer_quantity_max` is non-zero:
|
||||
* - MUST fail the request if `invreq_quantity` is zero, OR greater than
|
||||
* - MUST reject the invoice request if `invreq_quantity` is zero, OR greater than
|
||||
* `offer_quantity_max`.
|
||||
* - otherwise:
|
||||
* - MUST fail the request if there is an `invreq_quantity` field.
|
||||
* - MUST reject the invoice request if there is an `invreq_quantity` field.
|
||||
*/
|
||||
if (ir->invreq->offer_quantity_max) {
|
||||
err = invreq_must_have(cmd, ir, invreq_quantity);
|
||||
|
@ -884,8 +884,8 @@ static struct command_result *listoffers_done(struct command *cmd,
|
|||
return err;
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
* - MUST fail the request if `signature` is not correct as
|
||||
/* BOLT #12:
|
||||
* - MUST reject the invoice request if `signature` is not correct as
|
||||
* detailed in [Signature Calculation](#signature-calculation) using
|
||||
* the `invreq_payer_id`.
|
||||
*/
|
||||
|
@ -899,21 +899,21 @@ static struct command_result *listoffers_done(struct command *cmd,
|
|||
}
|
||||
|
||||
if (ir->invreq->offer_recurrence) {
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
*
|
||||
* - if the offer had a `recurrence`:
|
||||
* - MUST fail the request if there is no `recurrence_counter`
|
||||
* - MUST reject the invoice request if there is no `recurrence_counter`
|
||||
* field.
|
||||
*/
|
||||
err = invreq_must_have(cmd, ir, invreq_recurrence_counter);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
/* BOLT-offers-recurrence #12:
|
||||
/* BOLT-recurrence #12:
|
||||
* - otherwise (the offer had no `recurrence`):
|
||||
* - MUST fail the request if there is a `recurrence_counter`
|
||||
* - MUST reject the invoice request if there is a `recurrence_counter`
|
||||
* field.
|
||||
* - MUST fail the request if there is a `recurrence_start`
|
||||
* - MUST reject the invoice request if there is a `recurrence_start`
|
||||
* field.
|
||||
*/
|
||||
err = invreq_must_not_have(cmd, ir, invreq_recurrence_counter);
|
||||
|
@ -924,31 +924,31 @@ static struct command_result *listoffers_done(struct command *cmd,
|
|||
return err;
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* A writer of an invoice:
|
||||
*...
|
||||
* - if the invoice is in response to an `invoice_request`:
|
||||
* - MUST copy all non-signature fields from the `invoice_request` (including
|
||||
* - MUST copy all non-signature fields from the invoice request (including
|
||||
* unknown fields).
|
||||
*/
|
||||
ir->inv = invoice_for_invreq(cmd, ir->invreq);
|
||||
assert(ir->inv->invreq_payer_id);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `offer_issuer_id` is present:
|
||||
* - MUST set `invoice_node_id` to the `offer_issuer_id`
|
||||
*/
|
||||
/* FIXME: We always provide an offer_issuer_id! */
|
||||
ir->inv->invoice_node_id = ir->inv->offer_issuer_id;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST set `invoice_created_at` to the number of seconds since
|
||||
* Midnight 1 January 1970, UTC when the invoice was created.
|
||||
*/
|
||||
ir->inv->invoice_created_at = tal(ir->inv, u64);
|
||||
*ir->inv->invoice_created_at = time_now().ts.tv_sec;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST set `invoice_payment_hash` to the SHA256 hash of the
|
||||
* `payment_preimage` that will be given in return for payment.
|
||||
*/
|
||||
|
@ -957,7 +957,7 @@ static struct command_result *listoffers_done(struct command *cmd,
|
|||
sha256(ir->inv->invoice_payment_hash,
|
||||
&ir->preimage, sizeof(ir->preimage));
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - or if it allows multiple parts to pay the invoice:
|
||||
* - MUST set `invoice_features`.`features` bit `MPP/optional`
|
||||
*/
|
||||
|
@ -993,12 +993,12 @@ struct command_result *handle_invoice_request(struct command *cmd,
|
|||
return fail_invreq(cmd, ir, "Invalid invreq");
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* The reader:
|
||||
* ...
|
||||
* - MUST fail the request if any non-signature TLV fields are outside the inclusive ranges: 0 to 159 and 1000000000 to 2999999999
|
||||
* - MUST reject the invoice request if any non-signature TLV fields are outside the inclusive ranges: 0 to 159 and 1000000000 to 2999999999
|
||||
*/
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* Each form is signed using one or more *signature TLV elements*:
|
||||
* TLV types 240 through 1000 (inclusive)
|
||||
*/
|
||||
|
@ -1008,10 +1008,10 @@ struct command_result *handle_invoice_request(struct command *cmd,
|
|||
return fail_invreq(cmd, ir, "Invalid high fields");
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* The reader:
|
||||
* - MUST fail the request if `invreq_payer_id` or `invreq_metadata`
|
||||
* - MUST reject the invoice request if `invreq_payer_id` or `invreq_metadata`
|
||||
* are not present.
|
||||
*/
|
||||
if (!ir->invreq->invreq_payer_id)
|
||||
|
@ -1019,12 +1019,12 @@ struct command_result *handle_invoice_request(struct command *cmd,
|
|||
if (!ir->invreq->invreq_metadata)
|
||||
return fail_invreq(cmd, ir, "Missing invreq_metadata");
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* The reader:
|
||||
*...
|
||||
* - if `invreq_features` contains unknown _even_ bits that are non-zero:
|
||||
* - MUST fail the request.
|
||||
* - MUST reject the invoice request.
|
||||
*/
|
||||
bad_feature = features_unsupported(plugin_feature_set(cmd->plugin),
|
||||
ir->invreq->invreq_features,
|
||||
|
@ -1050,14 +1050,18 @@ struct command_result *handle_invoice_request(struct command *cmd,
|
|||
}
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* FIXME: quote is garbled, see: https://github.com/lightning/bolts/pull/1222 */
|
||||
/* BOLT #12:
|
||||
*
|
||||
* The reader:
|
||||
*...
|
||||
* - if `invreq_chain` is not present:
|
||||
* - MUST fail the request if bitcoin is not a supported chain.
|
||||
* - MUST reject the invoice request if bitcoin is not a supported chain.
|
||||
* - if `invreq_bip_353_name` is present:
|
||||
* - MUST reject the invoice request if `name` or `domain` contain any bytes which are not
|
||||
* `0`-`9`, `a`-`z`, `A`-`Z`, `-`, `_` or `.`.
|
||||
* - otherwise:
|
||||
* - MUST fail the request if `invreq_chain`.`chain` is not a
|
||||
* - MUST reject the invoice request if `invreq_chain`.`chain` is not a
|
||||
* supported chain.
|
||||
*/
|
||||
if (!bolt12_chain_matches(ir->invreq->invreq_chain, chainparams)) {
|
||||
|
@ -1066,7 +1070,7 @@ struct command_result *handle_invoice_request(struct command *cmd,
|
|||
tal_hex(tmpctx, ir->invreq->invreq_chain));
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* - otherwise (no `offer_issuer_id` or `offer_paths`, not a response to our offer):
|
||||
*/
|
||||
|
@ -1075,10 +1079,10 @@ struct command_result *handle_invoice_request(struct command *cmd,
|
|||
return fail_invreq(cmd, ir, "Not based on an offer");
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* - if `offer_issuer_id` or `offer_paths` are present (response to an offer):
|
||||
* - MUST fail the request if the offer fields do not exactly match a
|
||||
* - MUST reject the invoice request if the offer fields do not exactly match a
|
||||
* valid, unexpired offer.
|
||||
*/
|
||||
invreq_offer_id(ir->invreq, &ir->offer_id);
|
||||
|
|
|
@ -46,15 +46,15 @@ static struct command_result *param_amount(struct command *cmd,
|
|||
|
||||
offer->offer_amount = tal(offer, u64);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* - MUST specify `offer_currency` `iso4217` as an ISO 4712 three-letter code.
|
||||
* - MUST specify `offer_amount` in the currency unit adjusted by the ISO 4712
|
||||
* - MUST specify `offer_currency` `iso4217` as an ISO 4217 three-letter code.
|
||||
* - MUST specify `offer_amount` in the currency unit adjusted by the ISO 4217
|
||||
* exponent (e.g. USD cents).
|
||||
*/
|
||||
if (tok->end - tok->start < ISO4217_NAMELEN)
|
||||
return command_fail_badparam(cmd, name, buffer, tok,
|
||||
"should be 'any', msatoshis or <amount>[.<amount>]<ISO-4712>");
|
||||
"should be 'any', msatoshis or <amount>[.<amount>]<ISO-4217>");
|
||||
|
||||
isocode = find_iso4217(buffer + tok->end - ISO4217_NAMELEN, ISO4217_NAMELEN);
|
||||
if (!isocode)
|
||||
|
@ -84,7 +84,7 @@ static struct command_result *param_amount(struct command *cmd,
|
|||
|
||||
if (!json_to_u64(buffer, &whole, offer->offer_amount))
|
||||
return command_fail_badparam(cmd, name, buffer, tok,
|
||||
"should be 'any', msatoshis or <ISO-4712><amount>[.<amount>]");
|
||||
"should be 'any', msatoshis or <ISO-4217><amount>[.<amount>]");
|
||||
|
||||
for (size_t i = 0; i < isocode->minor_unit; i++) {
|
||||
if (mul_overflows_u64(*offer->offer_amount, 10))
|
||||
|
@ -282,7 +282,7 @@ static struct command_result *found_best_peer(struct command *cmd,
|
|||
const struct chaninfo *best,
|
||||
struct offer_info *offinfo)
|
||||
{
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if it is connected only by private channels:
|
||||
* - MUST include `offer_paths` containing one or more paths to the node from
|
||||
* publicly reachable nodes.
|
||||
|
@ -323,7 +323,7 @@ static struct command_result *found_best_peer(struct command *cmd,
|
|||
static struct command_result *maybe_add_path(struct command *cmd,
|
||||
struct offer_info *offinfo)
|
||||
{
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if it is connected only by private channels:
|
||||
* - MUST include `offer_paths` containing one or more paths to the node from
|
||||
* publicly reachable nodes.
|
||||
|
@ -475,12 +475,12 @@ struct command_result *json_offer(struct command *cmd,
|
|||
return command_fail_badparam(cmd, "quantity_max",
|
||||
buffer, params,
|
||||
"must be 0 or > 1");
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* - if the chain for the invoice is not solely bitcoin:
|
||||
* - MUST specify `offer_chains` the offer is valid for.
|
||||
* - otherwise:
|
||||
* - MAY omit `offer_chains`, implying that bitcoin is only chain.
|
||||
* - SHOULD omit `offer_chains`, implying that bitcoin is only chain.
|
||||
*/
|
||||
if (!streq(chainparams->network_name, "bitcoin")) {
|
||||
offer->offer_chains = tal_arr(offer, struct bitcoin_blkid, 1);
|
||||
|
@ -506,7 +506,7 @@ struct command_result *json_offer(struct command *cmd,
|
|||
offer->offer_description
|
||||
= tal_dup_arr(offer, char, desc, strlen(desc), 0);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* - if `offer_amount` is set and `offer_description` is not set:
|
||||
* - MUST NOT respond to the offer.
|
||||
|
@ -515,7 +515,7 @@ struct command_result *json_offer(struct command *cmd,
|
|||
return command_fail_badparam(cmd, "description", buffer, params,
|
||||
"description is required for the user to know what it was they paid for");
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if it sets `offer_issuer`:
|
||||
* - SHOULD set it to identify the issuer of the invoice clearly.
|
||||
* - if it includes a domain name:
|
||||
|
@ -527,7 +527,7 @@ struct command_result *json_offer(struct command *cmd,
|
|||
= tal_dup_arr(offer, char, issuer, strlen(issuer), 0);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if it includes `offer_paths`:
|
||||
*...
|
||||
* - otherwise:
|
||||
|
@ -615,10 +615,10 @@ static struct command_result *found_best_peer_invrequest(struct command *cmd,
|
|||
struct secret blinding_path_secret;
|
||||
struct sha256 invreq_id;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST set `invreq_paths` as it would set (or not set) `offer_paths` for an offer.
|
||||
*/
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
*
|
||||
* - if it is connected only by private channels:
|
||||
* - MUST include `offer_paths` containing one or more paths to the node from
|
||||
|
@ -676,7 +676,7 @@ struct command_result *json_invoicerequest(struct command *cmd,
|
|||
NULL))
|
||||
return command_param_failed();
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - otherwise (not responding to an offer):
|
||||
* - MUST set `offer_description` to a complete description of the purpose of the payment.
|
||||
* - MUST set (or not set) `offer_absolute_expiry` and `offer_issuer` as it would for an offer.
|
||||
|
@ -702,7 +702,7 @@ struct command_result *json_invoicerequest(struct command *cmd,
|
|||
= tal_dup(invreq, struct bitcoin_blkid,
|
||||
&chainparams->genesis_blockhash);
|
||||
}
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if it sets `invreq_amount`:
|
||||
* - MUST set `msat` in multiples of the minimum lightning-payable unit
|
||||
* (e.g. milli-satoshis for bitcoin) for `invreq_chain` (or for bitcoin, if there is no `invreq_chain`).
|
||||
|
@ -710,14 +710,14 @@ struct command_result *json_invoicerequest(struct command *cmd,
|
|||
invreq->invreq_amount
|
||||
= tal_dup(invreq, u64, &msat->millisatoshis); /* Raw: wire */
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - MUST set `invreq_metadata` to an unpredictable series of bytes.
|
||||
*/
|
||||
invreq->invreq_metadata = tal_arr(invreq, u8, 16);
|
||||
randombytes_buf(invreq->invreq_metadata,
|
||||
tal_bytelen(invreq->invreq_metadata));
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - otherwise (not responding to an offer):
|
||||
*...
|
||||
* - MUST set `invreq_payer_id` (as it would set `offer_issuer_id` for an offer).
|
||||
|
@ -725,7 +725,7 @@ struct command_result *json_invoicerequest(struct command *cmd,
|
|||
/* FIXME: Allow invoicerequests using aliases! */
|
||||
invreq->invreq_payer_id = tal_dup(invreq, struct pubkey, &id);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if it supports bolt12 invoice request features:
|
||||
* - MUST set `invreq_features`.`features` to the bitmap of features.
|
||||
*/
|
||||
|
|
|
@ -1404,7 +1404,7 @@ static struct command_result *json_pay(struct command *cmd,
|
|||
node_id_from_pubkey(p->route_destination, &p->blindedpath->first_node_id.pubkey);
|
||||
p->payment_metadata = NULL;
|
||||
p->routes = NULL;
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - if `invoice_relative_expiry` is present:
|
||||
* - MUST reject the invoice if the current time since
|
||||
* 1970-01-01 UTC is greater than `invoice_created_at` plus
|
||||
|
|
|
@ -1312,7 +1312,7 @@ static char *add_blindedpath(const tal_t *ctx,
|
|||
struct short_channel_id scid;
|
||||
struct node_id src, dst;
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - SHOULD prefer to use earlier `invoice_paths` over later ones if
|
||||
* it has no other reason for preference.
|
||||
*/
|
||||
|
@ -1335,7 +1335,7 @@ static char *add_blindedpath(const tal_t *ctx,
|
|||
|
||||
assert(path->first_node_id.is_pubkey);
|
||||
|
||||
/* BOLT-offers #12:
|
||||
/* BOLT #12:
|
||||
* - For each `invoice_blindedpay`.`payinfo`:
|
||||
* - MUST NOT use the corresponding `invoice_paths`.`path`
|
||||
* if `payinfo`.`features` has any unknown even bits set.
|
||||
|
|
|
@ -5261,7 +5261,7 @@ def test_payerkey(node_factory):
|
|||
# Now we are supposed to put invreq_payer_id inside invreq, and lightningd
|
||||
# checks the derivation as a courtesy. Fortunately, invreq_payer_id is last
|
||||
for n, k in zip(nodes, expected_keys):
|
||||
# BOLT-offers #12:
|
||||
# BOLT #12:
|
||||
# 1. type: 88 (`invreq_payer_id`)
|
||||
# 2. data:
|
||||
# * [`point`:`key`]
|
||||
|
@ -5929,7 +5929,7 @@ def test_fetch_no_description_with_amount(node_factory):
|
|||
l1, l2 = node_factory.line_graph(2, opts={'allow-deprecated-apis': True})
|
||||
|
||||
# Deprecated fields make schema checker upset.
|
||||
# BOLT-offers #12:
|
||||
# BOLT #12:
|
||||
#
|
||||
# - if offer_amount is set and offer_description is not set:
|
||||
# - MUST NOT respond to the offer.
|
||||
|
|
Loading…
Add table
Reference in a new issue