mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-21 22:31:48 +01:00
global: update BOLT12 quotes.
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 <rusty@rustcorp.com.au>
This commit is contained in:
parent
f2a7b19281
commit
bf549130d6
16 changed files with 657 additions and 615 deletions
|
@ -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,
|
||||
|
@ -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
|
||||
|
|
1
cln-grpc/proto/node.proto
generated
1
cln-grpc/proto/node.proto
generated
|
@ -1663,6 +1663,7 @@ message DecodeResponse {
|
|||
optional bytes offer_issuer_id = 83;
|
||||
optional string warning_missing_offer_issuer_id = 84;
|
||||
repeated DecodeInvreq_paths invreq_paths = 85;
|
||||
optional string warning_empty_blinded_path = 86;
|
||||
}
|
||||
|
||||
message DecodeOffer_paths {
|
||||
|
|
1
cln-grpc/src/convert.rs
generated
1
cln-grpc/src/convert.rs
generated
|
@ -1599,6 +1599,7 @@ impl From<responses::DecodeResponse> for pb::DecodeResponse {
|
|||
unique_id: c.unique_id, // Rule #2 for type string?
|
||||
valid: c.valid, // Rule #2 for type boolean
|
||||
version: c.version, // Rule #2 for type string?
|
||||
warning_empty_blinded_path: c.warning_empty_blinded_path, // Rule #2 for type string?
|
||||
warning_invalid_invoice_request_signature: c.warning_invalid_invoice_request_signature, // Rule #2 for type string?
|
||||
warning_invalid_invoice_signature: c.warning_invalid_invoice_signature, // Rule #2 for type string?
|
||||
warning_invalid_invreq_payer_note: c.warning_invalid_invreq_payer_note, // Rule #2 for type string?
|
||||
|
|
2
cln-rpc/src/model.rs
generated
2
cln-rpc/src/model.rs
generated
|
@ -6872,6 +6872,8 @@ pub mod responses {
|
|||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub version: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub warning_empty_blinded_path: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub warning_invalid_invoice_request_signature: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub warning_invalid_invoice_signature: Option<String>,
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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:
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
|
|
@ -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": [
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -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
|
||||
|
|
|
@ -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 },
|
||||
|
@ -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`]
|
||||
|
@ -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`]
|
||||
|
@ -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`]
|
||||
|
|
|
@ -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": [
|
||||
|
|
|
@ -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";
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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`.
|
||||
|
|
|
@ -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 */
|
||||
|
@ -317,11 +315,16 @@ 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)
|
||||
|
@ -329,14 +332,6 @@ struct command_result *handle_invoice(struct command *cmd,
|
|||
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:
|
||||
*...
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue