Skip to content

Commit

Permalink
global: update BOLT12 quotes.
Browse files Browse the repository at this point in the history
This is a final sweep to match the current BOLT12 text:

	1563d13999d342680140c693de0b9d65aa522372 ("More bolt12 test vectors.")

Only two code changes, to change the order of checks to match the bolt,
and to give a warning on decode if a path is empty.

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Aug 1, 2024
1 parent f2a7b19 commit bf54913
Show file tree
Hide file tree
Showing 16 changed files with 657 additions and 615 deletions.
5 changes: 5 additions & 0 deletions .msggen.json
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,7 @@
"Decode.unknown_offer_tlvs[]": 19,
"Decode.valid": 2,
"Decode.version": 71,
"Decode.warning_empty_blinded_path": 86,
"Decode.warning_invalid_invoice_request_signature": 39,
"Decode.warning_invalid_invoice_signature": 58,
"Decode.warning_invalid_invreq_payer_note": 37,
Expand Down Expand Up @@ -4815,6 +4816,10 @@
"added": "pre-v0.10.1",
"deprecated": null
},
"Decode.warning_empty_blinded_path": {
"added": "v24.08",
"deprecated": null
},
"Decode.warning_invalid_invoice_request_signature": {
"added": "pre-v0.10.1",
"deprecated": null
Expand Down
1 change: 1 addition & 0 deletions cln-grpc/proto/node.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cln-grpc/src/convert.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions cln-rpc/src/model.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion common/test/run-bolt12-encode-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ int main(int argc, char *argv[])
/* BOLT-offers #12:
* - if it includes `offer_paths`:
* - SHOULD ignore any invoice_request which does not use the path.
* - MAY set `offer_issuer_id` to the node's public key to request the invoice from.
* - MAY set `offer_issuer_id`.
* - otherwise:
* - MUST set `offer_issuer_id` to the node's public key to request the invoice from.
*/
Expand Down
11 changes: 7 additions & 4 deletions common/test/run-bolt12-format-string-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,7 @@ int main(int argc, char *argv[])
offer = tlv_offer_new(tmpctx);
/* BOLT-offers #12:
* A writer of an offer:
* - MUST NOT set any tlv fields greater or equal to 80, or tlv field 0.
* - MUST set `offer_issuer_id` to the node's public key to request the invoice from.
* - MUST set `offer_description` to a complete description of the purpose
* of the payment.
* - 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:
Expand All @@ -134,9 +131,12 @@ int main(int argc, char *argv[])
* - 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).
* - MUST set `offer_description` to a complete description of the purpose
* of the payment.
* - otherwise:
* - MUST NOT set `offer_amount`
* - MUST NOT set `offer_currency`
* - MAY set `offer_description`
* - MAY set `offer_metadata` for its own use.
* - if it supports bolt12 offer features:
* - MUST set `offer_features`.`features` to the bitmap of bolt12 features.
Expand All @@ -151,6 +151,9 @@ int main(int argc, char *argv[])
* - 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.
* - if it sets `offer_issuer`:
* - SHOULD set it to identify the issuer of the invoice clearly.
* - if it includes a domain name:
Expand Down
7 changes: 7 additions & 0 deletions contrib/msggen/msggen/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -5726,6 +5726,13 @@
}
}
},
"warning_empty_blinded_path": {
"added": "v24.08",
"type": "string",
"description": [
"The blinded path has 0 hops."
]
},
"offer_node_id": {
"type": "pubkey",
"deprecated": [
Expand Down
1,176 changes: 588 additions & 588 deletions contrib/pyln-grpc-proto/pyln/grpc/node_pb2.py

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions contrib/pyln-testing/pyln/testing/grpc2py.py
Original file line number Diff line number Diff line change
Expand Up @@ -1312,6 +1312,7 @@ def decode2py(m):
"unique_id": m.unique_id, # PrimitiveField in generate_composite
"valid": m.valid, # PrimitiveField in generate_composite
"version": m.version, # PrimitiveField in generate_composite
"warning_empty_blinded_path": m.warning_empty_blinded_path, # PrimitiveField in generate_composite
"warning_invalid_invoice_request_signature": m.warning_invalid_invoice_request_signature, # PrimitiveField in generate_composite
"warning_invalid_invoice_signature": m.warning_invalid_invoice_signature, # PrimitiveField in generate_composite
"warning_invalid_invreq_payer_note": m.warning_invalid_invreq_payer_note, # PrimitiveField in generate_composite
Expand Down
9 changes: 6 additions & 3 deletions devtools/bolt12-cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ static u64 get_offer_type(const char *name)
* * [`tu64`:`max`]
* 1. type: 22 (`offer_issuer_id`)
* 2. data:
* * [`point`:`node_id`]
* * [`point`:`id`]
*/
{ "offer_chains", 2 },
{ "offer_metadata", 4 },
Expand Down Expand Up @@ -510,7 +510,7 @@ static u64 get_offer_type(const char *name)
* * [`tu64`:`max`]
* 1. type: 22 (`offer_issuer_id`)
* 2. data:
* * [`point`:`node_id`]
* * [`point`:`id`]
* 1. type: 80 (`invreq_chain`)
* 2. data:
* * [`chain_hash`:`chain`]
Expand Down Expand Up @@ -583,7 +583,7 @@ static u64 get_offer_type(const char *name)
* * [`tu64`:`max`]
* 1. type: 22 (`offer_issuer_id`)
* 2. data:
* * [`point`:`node_id`]
* * [`point`:`id`]
* 1. type: 80 (`invreq_chain`)
* 2. data:
* * [`chain_hash`:`chain`]
Expand All @@ -602,6 +602,9 @@ static u64 get_offer_type(const char *name)
* 1. type: 89 (`invreq_payer_note`)
* 2. data:
* * [`...*utf8`:`note`]
* 1. type: 90 (`invreq_paths`)
* 2. data:
* * [`...*blinded_path`:`paths`]
* 1. type: 160 (`invoice_paths`)
* 2. data:
* * [`...*blinded_path`:`paths`]
Expand Down
7 changes: 7 additions & 0 deletions doc/schemas/lightning-decode.json
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,13 @@
}
}
},
"warning_empty_blinded_path": {
"added": "v24.08",
"type": "string",
"description": [
"The blinded path has 0 hops."
]
},
"offer_node_id": {
"type": "pubkey",
"deprecated": [
Expand Down
15 changes: 9 additions & 6 deletions plugins/fetchinvoice.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,11 @@ static struct command_result *handle_invreq_response(struct command *cmd,
}

/* BOLT-offers #12:
* - if `offer_node_id` or `offer_paths` are present (invoice_request for an offer):
* - MUST reject the invoice if `invoice_node_id` is not equal to the public key it sent the `invoice_request` to.
* - 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.
*/
if (!inv->invoice_node_id || !pubkey_eq(inv->offer_issuer_id, sent->issuer_key)) {
badfield = "invoice_node_id";
Expand Down Expand Up @@ -560,7 +563,7 @@ static struct command_result *try_establish(struct command *cmd,
target = first.pubkey;
/* BOLT-offers #12:
* - if `offer_issuer_id` is present (invoice_request for an offer):
* - MUST reject the invoice if `invoice_node_id` is not equal `offer_issuer_id`
* - 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.
*/
Expand Down Expand Up @@ -1171,7 +1174,7 @@ static struct command_result *param_invreq(struct command *cmd,
* The reader:
* - MUST fail the 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 fail the 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.
Expand Down Expand Up @@ -1228,7 +1231,7 @@ static struct command_result *param_invreq(struct command *cmd,
}

/* BOLT-offers #12:
* - otherwise (no `offer_node_id` or `offer_paths`, not a response to our offer):
* - 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:
* - `offer_chains`, `offer_features` or `offer_quantity_max`.
* - MUST fail the request if `invreq_amount` is not present.
Expand Down Expand Up @@ -1338,7 +1341,7 @@ struct command_result *json_sendinvoice(struct command *cmd,

/* BOLT-offers #12:
* - if `offer_issuer_id` is present:
* - MUST set `invoice_node_id` to `offer_issuer_id`.
* - 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:
Expand Down
14 changes: 14 additions & 0 deletions plugins/offers.c
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,19 @@ static bool json_add_blinded_paths(struct json_stream *js,
return false;
}

/* BOLT-offers #12:
* - if `num_hops` is 0 in any `blinded_path` in `offer_paths`:
* - MUST NOT respond to the offer.
*/
for (size_t i = 0; i < tal_count(paths); i++) {
if (tal_count(paths[i]->path) == 0) {
json_add_str_fmt(js, "warning_empty_blinded_path",
"blinded path %zu has 0 hops",
i);
return false;
}
}

return true;
}

Expand Down Expand Up @@ -1011,6 +1024,7 @@ static void json_add_b12_invoice(struct json_stream *js,
/* BOLT-offers #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`.
* - 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`.
Expand Down
17 changes: 6 additions & 11 deletions plugins/offers_inv_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,11 @@ static struct command_result *listinvreqs_done(struct command *cmd,
* - 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`.
* - 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`.
* - 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.
* - otherwise (invoice_request without an offer):
* - MAY reject the invoice if it cannot confirm that `invoice_node_id` is correct, out-of-band.
*
* - otherwise: (a invoice presented without being requested, eg. scanned by user):
*/

/* Since the invreq_id hashes all fields in those ranges, we know it matches */
Expand Down Expand Up @@ -317,26 +315,23 @@ struct command_result *handle_invoice(struct command *cmd,
* A reader of an invoice:
*...
* - 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`.
* - 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`.
*/
if (!inv->inv->invoice_paths)
return fail_inv(cmd, inv, "Missing invoice_paths");
for (size_t i = 0; i < tal_count(inv->inv->invoice_paths); i++) {
if (tal_count(inv->inv->invoice_paths[i]->path) == 0)
return fail_inv(cmd, inv, "Empty path in invoice_paths");
}
if (!inv->inv->invoice_blindedpay)
return fail_inv(cmd, inv, "Missing invoice_blindedpay");
if (tal_count(inv->inv->invoice_blindedpay)
!= tal_count(inv->inv->invoice_paths))
return fail_inv(cmd, inv,
"Mismatch between invoice_blindedpay and invoice_paths");

/* BOLT-offers #12:
* - MUST reject the invoice if `num_hops` is 0 in any `blinded_path` in `invoice_paths`.
*/
for (size_t i = 0; i < tal_count(inv->inv->invoice_paths); i++) {
if (tal_count(inv->inv->invoice_paths[i]->path) == 0)
return fail_inv(cmd, inv, "Empty path in invoice_paths");
}

/* BOLT-offers #12:
* A reader of an invoice:
*...
Expand Down
2 changes: 1 addition & 1 deletion plugins/offers_invreq_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -930,7 +930,7 @@ static struct command_result *listoffers_done(struct command *cmd,

/* BOLT-offers #12:
* - if `offer_issuer_id` is present:
* - MUST set `invoice_node_id` to `offer_issuer_id`.
* - 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;
Expand Down
2 changes: 1 addition & 1 deletion plugins/offers_offer.c
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,7 @@ struct command_result *json_invoicerequest(struct command *cmd,
/* BOLT-offers #12:
* - otherwise (not responding to an offer):
*...
* - MUST set `invreq_payer_id` as it would set `offer_issuer_id` for an offer.
* - MUST set `invreq_payer_id` (as it would set `offer_issuer_id` for an offer).
*/
/* FIXME: Allow invoicerequests using aliases! */
invreq->invreq_payer_id = tal_dup(invreq, struct pubkey, &id);
Expand Down

0 comments on commit bf54913

Please sign in to comment.