Skip to content

Commit

Permalink
bolt12: update comments to match latest spec.
Browse files Browse the repository at this point in the history
No code changes.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
rustyrussell authored and cdecker committed Nov 9, 2022
1 parent 89d462f commit 643d1b4
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 75 deletions.
20 changes: 12 additions & 8 deletions common/bolt12.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,19 @@ bool bolt12_chains_match(const struct bitcoin_blkid *chains,
{
/* BOLT-offers #12:
* - if the chain for the invoice is not solely bitcoin:
* - MUST specify `chains` the offer is valid for.
* - MUST specify `offer_chains` the offer is valid for.
* - otherwise:
* - the bitcoin chain is implied as the first and only entry.
* - MAY omit `offer_chains`, implying that bitcoin is only chain.
*/
/* BOLT-offers #12:
* The reader of an invoice_request:
* A reader of an offer:
*...
* - if `chain` is not present:
* - MUST fail the request if bitcoin is not a supported chain.
* - otherwise:
* - MUST fail the request if `chain` is not a supported chain.
* - if `offer_chains` is not set:
* - if the node does not accept bitcoin invoices:
* - MUST NOT respond to the offer
* - otherwise: (`offer_chains` is set):
* - if the node does not accept invoices for any of the `chains`:
* - MUST NOT respond to the offer
*/
if (!chains) {
max_num_chains = 1;
Expand Down Expand Up @@ -556,7 +558,9 @@ struct tlv_invoice *invoice_for_invreq(const tal_t *ctx,

/* BOLT-offers #12:
* A writer of an invoice:
* - MUST copy all non-signature fields from the invreq (including
*...
* - if the invoice is in response to an `invoice_request`:
* - MUST copy all non-signature fields from the `invoice_request` (including
* unknown fields).
*/
len = tlv_span(wire, 0, 159, &start);
Expand Down
6 changes: 3 additions & 3 deletions common/bolt12.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
struct feature_set;

/* BOLT-offers #12:
* - if `relative_expiry` is present:
* - if `invoice_relative_expiry` is present:
* - MUST reject the invoice if the current time since 1970-01-01 UTC
* is greater than `created_at` plus `seconds_from_creation`.
* is greater than `invoice_created_at` plus `seconds_from_creation`.
* - otherwise:
* - MUST reject the invoice if the current time since 1970-01-01 UTC
* is greater than `created_at` plus 7200.
* is greater than `invoice_created_at` plus 7200.
*/
#define BOLT12_DEFAULT_REL_EXPIRY 7200

Expand Down
18 changes: 9 additions & 9 deletions common/bolt12_merkle.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
#endif

/* BOLT-offers #12:
* TLV types 240 through 1000 are considered signature elements.
* Each form is signed using one or more *signature TLV elements*: TLV
* types 240 through 1000 (inclusive).
*/
static bool is_signature_field(const struct tlv_field *field)
{
Expand Down Expand Up @@ -193,18 +194,17 @@ void merkle_tlv(const struct tlv_field *fields, struct sha256 *merkle)

/* BOLT-offers #12:
* All signatures are created as per
* [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki),
* [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki)
* and tagged as recommended there. Thus we define H(`tag`,`msg`) as
* SHA256(SHA256(`tag`) || SHA256(`tag`) || `msg`), and SIG(`tag`,`msg`,`key`)
* as the signature of H(`tag`,`msg`) using `key`.
*
* Each form is signed using one or more TLV signature elements; TLV
* types 240 through 1000 are considered signature elements. For these
* the tag is "lightning" || `messagename` || `fieldname`, and `msg` is the
* Merkle-root; "lightning" is the literal 9-byte ASCII string,
* `messagename` is the name of the TLV stream being signed (i.e. "offer",
* "invoice_request" or "invoice") and the `fieldname` is the TLV field
* containing the signature (e.g. "signature" or "refund_signature").
* Each form is signed using one or more *signature TLV elements*: TLV types
* 240 through 1000 (inclusive). For these, the tag is "lightning" ||
* `messagename` || `fieldname`, and `msg` is the Merkle-root; "lightning" is
* the literal 9-byte ASCII string, `messagename` is the name of the TLV
* stream being signed (i.e. "invoice_request" or "invoice") and the
* `fieldname` is the TLV field containing the signature (e.g. "signature").
*/
void sighash_from_merkle(const char *messagename,
const char *fieldname,
Expand Down
4 changes: 2 additions & 2 deletions common/iso4217.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

/* BOLT-offers #12:
*
* - MUST specify `iso4217` as an ISO 4712 three-letter code.
* - MUST specify `amount` in the currency unit adjusted by the ISO 4712
* - 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
* exponent (e.g. USD cents).
*/
struct iso4217_name_and_divisor {
Expand Down
6 changes: 3 additions & 3 deletions devtools/bolt12-cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,12 +362,12 @@ static void print_relative_expiry(u64 *created_at, u32 *relative)
return;

/* BOLT-offers #12:
* - if `relative_expiry` is present:
* - if `invoice_relative_expiry` is present:
* - MUST reject the invoice if the current time since 1970-01-01 UTC
* is greater than `created_at` plus `seconds_from_creation`.
* is greater than `invoice_created_at` plus `seconds_from_creation`.
* - otherwise:
* - MUST reject the invoice if the current time since 1970-01-01 UTC
* is greater than `created_at` plus 7200.
* is greater than `invoice_created_at` plus 7200.
*/
if (!relative)
printf("invoice_relative_expiry: %u (%s) (default)\n",
Expand Down
4 changes: 2 additions & 2 deletions lightningd/offer.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,8 +463,8 @@ static struct command_result *json_createinvoicerequest(struct command *cmd,
}

/* BOLT-offers #12:
* - MUST set `signature` `sig` as detailed in
* [Signature Calculation](#signature-calculation) using the `payer_key`.
* - MUST set `signature`.`sig` as detailed in
* [Signature Calculation](#signature-calculation) using the `invreq_payer_id`.
*/
/* This populates the ->fields from our entries */
invreq->fields = tlv_make_fields(invreq, tlv_invoice_request);
Expand Down
30 changes: 18 additions & 12 deletions plugins/fetchinvoice.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,8 @@ static struct command_result *handle_invreq_response(struct command *cmd,
json_add_string(out, "invoice", invoice_encode(tmpctx, inv));
json_object_start(out, "changes");
/* BOLT-offers #12:
* - SHOULD confirm authorization if `msat` is not within the amount
* range authorized.
* - SHOULD confirm authorization if `invoice_amount`.`msat` is not within
* the amount range authorized.
*/
/* We always tell them this unless it's trivial to calc and
* exactly as expected. */
Expand Down Expand Up @@ -436,17 +436,13 @@ static struct command_result *param_offer(struct command *cmd,
fail));
/* BOLT-offers #12:
* A reader of an offer:
* - if the offer contains any unknown TLV fields greater or equal to 80:
* - if the offer contains any TLV fields greater or equal to 80:
* - MUST NOT respond to the offer.
* - if `offer_features` contains unknown _odd_ bits that are non-zero:
* - MUST ignore the bit.
* - 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.
* - if `offer_description` is not set:
* - MUST NOT respond to the offer.
* - if `offer_node_id` is not set:
* - MUST NOT respond to the offer.
*/
for (size_t i = 0; i < tal_count((*offer)->fields); i++) {
if ((*offer)->fields[i].numtype > 80) {
Expand All @@ -467,6 +463,13 @@ static struct command_result *param_offer(struct command *cmd,
"unknown feature %i",
badf));
}

/* BOLT-offers #12:
* - if `offer_description` is not set:
* - MUST NOT respond to the offer.
* - if `offer_node_id` is not set:
* - MUST NOT respond to the offer.
*/
if (!(*offer)->offer_description)
return command_fail_badparam(cmd, name, buffer, tok,
"Offer does not contain a description");
Expand Down Expand Up @@ -1012,7 +1015,7 @@ static struct command_result *json_fetchinvoice(struct command *cmd,

/* BOLT-offers #12:
* - SHOULD not respond to an offer if the current time is after
* `absolute_expiry`.
* `offer_absolute_expiry`.
*/
if (sent->offer->offer_absolute_expiry
&& time_now().ts.tv_sec > *sent->offer->offer_absolute_expiry)
Expand Down Expand Up @@ -1053,7 +1056,7 @@ static struct command_result *json_fetchinvoice(struct command *cmd,

/* BOLT-offers #12:
* - if `offer_quantity_max` is present:
* - MUST set `invreq_quantity`
* - MUST set `invreq_quantity` to greater than zero.
* - if `offer_quantity_max` is non-zero:
* - MUST set `invreq_quantity` less than or equal to
* `offer_quantity_max`.
Expand All @@ -1062,6 +1065,9 @@ static struct command_result *json_fetchinvoice(struct command *cmd,
if (!invreq->invreq_quantity)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"quantity parameter required");
if (*invreq->invreq_quantity == 0)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"quantity parameter must be non-zero");
if (*invreq->offer_quantity_max
&& *invreq->invreq_quantity > *invreq->offer_quantity_max)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
Expand Down Expand Up @@ -1448,9 +1454,9 @@ static struct command_result *json_sendinvoice(struct command *cmd,
return command_param_failed();

/* BOLT-offers #12:
* The writer:
* - MUST copy all non-signature fields from the invreq (including
* unknown fields).
* - if the invoice is in response to an `invoice_request`:
* - MUST copy all non-signature fields from the `invoice_request`
* (including unknown fields).
*/
sent->inv = invoice_for_invreq(sent, sent->invreq);

Expand Down
15 changes: 3 additions & 12 deletions plugins/offers.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,8 @@ static bool json_add_blinded_paths(struct json_stream *js,
json_array_end(js);

/* BOLT-offers #12:
* - MUST reject the invoice if `blinded_payinfo` does not contain
* exactly as many `payinfo` as total `onionmsg_path` in
* `blinded_path`.
* - MUST reject the invoice if `invoice_blindedpay` does not contain
* exactly one `blinded_payinfo` per `invoice_paths`.`blinded_path`.
*/
if (blindedpay && n != tal_count(blindedpay)) {
json_add_string(js, "warning_invalid_invoice_blindedpay",
Expand Down Expand Up @@ -594,7 +593,7 @@ static bool json_add_fallbacks(struct json_stream *js,
json_add_hex_talarr(js, "hex", fallbacks[i]->address);

/* BOLT-offers #12:
* - for the bitcoin chain, if the invoice specifies `fallbacks`:
* - for the bitcoin chain, if the invoice specifies `invoice_fallbacks`:
* - MUST ignore any `fallback_address` for which `version` is
* greater than 16.
* - MUST ignore any `fallback_address` for which `address` is
Expand Down Expand Up @@ -749,14 +748,6 @@ static void json_add_b12_invoice(struct json_stream *js,
* exactly one `blinded_payinfo` per `invoice_paths`.`blinded_path`.
*/
if (invoice->invoice_paths) {
/* BOLT-offers #12:
* - if `blinded_path` is present:
* - MUST reject the invoice if `blinded_payinfo` is not
* present.
* - MUST reject the invoice if `blinded_payinfo` does not
* contain exactly as many `payinfo` as total `onionmsg_path`
* in `blinded_path`.
*/
if (!invoice->invoice_blindedpay) {
json_add_string(js, "warning_missing_invoice_blindedpay",
"invoices with paths without blindedpay are invalid");
Expand Down
49 changes: 27 additions & 22 deletions plugins/offers_invreq_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,13 @@ static struct command_result *check_previous_invoice(struct command *cmd,
}

/* BOLT-offers #12:
* - MUST fail the request if `signature` is not correct.
* - MUST fail the request if `signature` is not correct as detailed in
* [Signature Calculation](#signature-calculation) using the
* `invreq_payer_id`.
*...
* - MUST reject the invoice if `signature` is not a valid signature using
* `invoice_node_id` as described in [Signature Calculation](#signature-calculation).
*/
static bool check_payer_sig(struct command *cmd,
const struct tlv_invoice_request *invreq,
Expand All @@ -645,12 +651,12 @@ static struct command_result *invreq_amount_by_quantity(struct command *cmd,
assert(ir->invreq->offer_amount);

/* BOLT-offers #12:
* - MUST calculate the *base invoice amount* using the offer `amount`:
* - MUST calculate the *expected amount* using the `offer_amount`:
*/
*raw_amt = *ir->invreq->offer_amount;

/* BOLT-offers #12:
* - if request contains `quantity`, multiply by `quantity`.
* - if `invreq_quantity` is present, multiply by `invreq_quantity`.`quantity`.
*/
if (ir->invreq->invreq_quantity) {
if (mul_overflows_u64(*ir->invreq->invreq_quantity, *raw_amt)) {
Expand Down Expand Up @@ -703,11 +709,9 @@ static struct command_result *handle_amount_and_recurrence(struct command *cmd,
struct amount_msat base_inv_amount)
{
/* BOLT-offers #12:
* - if the offer included `amount`:
*...
* - if the request contains `amount`:
* - MUST fail the request if its `amount` is less than the
* *base invoice amount*.
* - if `invreq_amount` is present:
* - MUST fail the request if `invreq_amount`.`msat` is less than the
* *expected amount*.
*/
if (ir->invreq->offer_amount && ir->invreq->invreq_amount) {
if (amount_msat_less(amount_msat(*ir->invreq->invreq_amount), base_inv_amount)) {
Expand All @@ -716,8 +720,8 @@ static struct command_result *handle_amount_and_recurrence(struct command *cmd,
&base_inv_amount));
}
/* BOLT-offers #12:
* - MAY fail the request if its `amount` is much greater than
* the *base invoice amount*.
* - MAY fail the request if `invreq_amount`.`msat` greatly exceeds
* the *expected amount*.
*/
/* Much == 5? Easier to divide and compare, than multiply. */
if (amount_msat_greater(amount_msat_div(amount_msat(*ir->invreq->invreq_amount), 5),
Expand All @@ -726,13 +730,15 @@ static struct command_result *handle_amount_and_recurrence(struct command *cmd,
type_to_string(tmpctx, struct amount_msat,
&base_inv_amount));
}
/* BOLT-offers #12:
* - MUST use the request's `amount` as the *base invoice
* amount*.
*/
base_inv_amount = amount_msat(*ir->invreq->invreq_amount);
}

/* BOLT-offers #12:
* - if `invreq_amount` is present:
* - MUST set `invoice_amount` to `invreq_amount`
* - otherwise:
* - MUST set `invoice_amount` to the *expected amount*.
*/
/* This may be adjusted by recurrence if proportional_amount set */
ir->inv->invoice_amount = tal_dup(ir->inv, u64,
&base_inv_amount.millisatoshis); /* Raw: wire protocol */
Expand Down Expand Up @@ -794,10 +800,9 @@ static struct command_result *convert_currency(struct command *cmd,
return err;

/* BOLT-offers #12:
* - MUST calculate the *base invoice amount* using the offer
* `amount`:
* - if offer `currency` is not the invoice currency, convert
* to the invoice currency.
* - MUST calculate the *expected amount* using the `offer_amount`:
* - if `offer_currency` is not the `invreq_chain` currency, convert to the
* `invreq_chain` currency.
*/
iso4217 = find_iso4217(ir->invreq->offer_currency,
tal_bytelen(ir->invreq->offer_currency));
Expand Down Expand Up @@ -900,7 +905,7 @@ static struct command_result *listoffers_done(struct command *cmd,
}

/* BOLT-offers #12:
* - MUST fail the request if `invreq_signature` is not correct as
* - MUST fail the request if `signature` is not correct as
* detailed in [Signature Calculation](#signature-calculation) using
* the `invreq_payer_id`.
*/
Expand Down Expand Up @@ -940,10 +945,10 @@ static struct command_result *listoffers_done(struct command *cmd,
}

/* BOLT-offers #12:
* The writer of an invoice:
* A writer of an invoice:
*...
* - if the invoice is in response to an `invoice_request`:
* - MUST copy all non-signature fields from the invreq (including
* - MUST copy all non-signature fields from the `invoice_request` (including
* unknown fields).
*/
ir->inv = invoice_for_invreq(cmd, ir->invreq);
Expand Down Expand Up @@ -1035,7 +1040,7 @@ struct command_result *handle_invoice_request(struct command *cmd,

/* BOLT-offers #12:
*
* The reader of an invreq:
* The reader:
*...
* - if `invreq_features` contains unknown _even_ bits that are non-zero:
* - MUST fail the request.
Expand Down
4 changes: 2 additions & 2 deletions plugins/offers_offer.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ static struct command_result *param_amount(struct command *cmd,

/* BOLT-offers #12:
*
* - MUST specify `iso4217` as an ISO 4712 three-letter code.
* - MUST specify `amount` in the currency unit adjusted by the ISO 4712
* - 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
* exponent (e.g. USD cents).
*/
if (tok->end - tok->start < ISO4217_NAMELEN)
Expand Down

0 comments on commit 643d1b4

Please sign in to comment.