diff --git a/common/bolt12.c b/common/bolt12.c index 8768d7bcb..f284fcd6c 100644 --- a/common/bolt12.c +++ b/common/bolt12.c @@ -166,27 +166,6 @@ struct tlv_offer *offer_decode(const tal_t *ctx, const struct feature_set *our_features, const struct chainparams *must_be_chain, char **fail) -{ - struct tlv_offer *offer; - - offer = offer_decode_nosig(ctx, b12, b12len, - our_features, must_be_chain, fail); - - if (offer) { - *fail = check_signature(ctx, offer->fields, - "offer", "signature", - offer->node_id, offer->signature); - if (*fail) - offer = tal_free(offer); - } - return offer; -} - -struct tlv_offer *offer_decode_nosig(const tal_t *ctx, - const char *b12, size_t b12len, - const struct feature_set *our_features, - const struct chainparams *must_be_chain, - char **fail) { struct tlv_offer *offer = tlv_offer_new(ctx); const u8 *data; @@ -208,6 +187,19 @@ struct tlv_offer *offer_decode_nosig(const tal_t *ctx, if (*fail) return tal_free(offer); + /* BOLT-offers #12: + * - if `signature` is present, but is not a valid signature using + * `node_id` as described in [Signature Calculation](#signature-calculation): + * - MUST NOT respond to the offer. + */ + if (offer->signature) { + *fail = check_signature(ctx, offer->fields, + "offer", "signature", + offer->node_id, offer->signature); + if (*fail) + return tal_free(offer); + } + return offer; } diff --git a/common/bolt12.h b/common/bolt12.h index d4e836bf7..a136e1730 100644 --- a/common/bolt12.h +++ b/common/bolt12.h @@ -33,20 +33,13 @@ char *offer_encode(const tal_t *ctx, const struct tlv_offer *bolt12_tlv); * @must_be_chain: if non-NULL, chain to enforce. * @fail: pointer to descriptive error string, set if this returns NULL. * - * Note: checks signature! + * Note: checks signature if present. */ struct tlv_offer *offer_decode(const tal_t *ctx, const char *b12, size_t b12len, const struct feature_set *our_features, const struct chainparams *must_be_chain, char **fail); -/* Variant which does not check signature */ -struct tlv_offer *offer_decode_nosig(const tal_t *ctx, - const char *b12, size_t b12len, - const struct feature_set *our_features, - const struct chainparams *must_be_chain, - char **fail); - /** * invrequest_encode - encode this complete bolt12 invreq TLV into text. */ diff --git a/devtools/bolt12-cli.c b/devtools/bolt12-cli.c index a006943e6..8822b8546 100644 --- a/devtools/bolt12-cli.c +++ b/devtools/bolt12-cli.c @@ -481,8 +481,8 @@ int main(int argc, char *argv[]) if (streq(hrp, "lno")) { const struct tlv_offer *offer - = offer_decode_nosig(ctx, argv[2], strlen(argv[2]), - NULL, NULL, &fail); + = offer_decode(ctx, argv[2], strlen(argv[2]), + NULL, NULL, &fail); if (!offer) errx(ERROR_BAD_DECODE, "Bad offer: %s", fail); @@ -517,7 +517,7 @@ int main(int argc, char *argv[]) print_features(offer->features); if (offer->paths) print_blindedpaths(offer->paths, NULL); - if (must_have(offer, signature) && offer->node_id) + if (offer->signature && offer->node_id) well_formed &= print_signature("offer", "signature", offer->fields, offer->node_id, diff --git a/doc/lightning-decode.7 b/doc/lightning-decode.7 index 1ce806d50..f4cc5e031 100644 --- a/doc/lightning-decode.7 +++ b/doc/lightning-decode.7 @@ -35,10 +35,10 @@ If \fBtype\fR is "bolt12 offer", and \fBvalid\fR is \fItrue\fR: .IP \[bu] \fBnode_id\fR (pubkey32): x-only public key of the offering node .IP \[bu] -\fBsignature\fR (bip340sig): BIP-340 signature of the \fInode_id\fR on this offer -.IP \[bu] \fBdescription\fR (string): the description of the purpose of the offer .IP \[bu] +\fBsignature\fR (bip340sig, optional): BIP-340 signature of the \fInode_id\fR on this offer +.IP \[bu] \fBchains\fR (array of hexs, optional): which blockchains this offer is for (missing implies bitcoin mainnet only): .RS .IP \[bu] @@ -414,4 +414,4 @@ Rusty Russell \fI is mainly responsible\. Main web site: \fIhttps://github.com/ElementsProject/lightning\fR -\" SHA256STAMP:045cd00ad893483df132bdffd913049bfe43acb152a511accc9f17f87ba06a8d +\" SHA256STAMP:cd54af7c631f06b3db72848cdf90951ceb14d89b8bca981dba69244cd2ddbae5 diff --git a/doc/lightning-decode.7.md b/doc/lightning-decode.7.md index 7d1f28aa5..e0b62d39b 100644 --- a/doc/lightning-decode.7.md +++ b/doc/lightning-decode.7.md @@ -27,8 +27,8 @@ On success, an object is returned, containing: If **type** is "bolt12 offer", and **valid** is *true*: - **offer_id** (hex): the id of this offer (merkle hash of non-signature fields) (always 64 characters) - **node_id** (pubkey32): x-only public key of the offering node - - **signature** (bip340sig): BIP-340 signature of the *node_id* on this offer - **description** (string): the description of the purpose of the offer + - **signature** (bip340sig, optional): BIP-340 signature of the *node_id* on this offer - **chains** (array of hexs, optional): which blockchains this offer is for (missing implies bitcoin mainnet only): - the genesis blockhash (always 64 characters) - **currency** (string, optional): ISO 4217 code of the currency (missing implies Bitcoin) (always 3 characters) @@ -183,4 +183,4 @@ RESOURCES Main web site: -[comment]: # ( SHA256STAMP:f0adee97f3b5776059252703efee1b8e244c1141f9f3dd5fe73e3d7ed4d59ab4) +[comment]: # ( SHA256STAMP:8ca0b9178b8ea6575cd80291001263dc27f721664648086a7c1a02efcb545ee7) diff --git a/doc/lightning-disableoffer.7 b/doc/lightning-disableoffer.7 index df88f5921..99bbd0af3 100644 --- a/doc/lightning-disableoffer.7 +++ b/doc/lightning-disableoffer.7 @@ -48,6 +48,8 @@ On success, an object is returned, containing: .IP \[bu] \fBbolt12\fR (string): The bolt12 string representing this offer .IP \[bu] +\fBbolt12_unsigned\fR (string): The bolt12 string representing this offer, without signature +.IP \[bu] \fBused\fR (boolean): Whether the offer has had an invoice paid / payment made .IP \[bu] \fBlabel\fR (string, optional): The label provided when offer was created @@ -78,4 +80,4 @@ Rusty Russell \fI is mainly responsible\. Main web site: \fIhttps://github.com/ElementsProject/lightning\fR -\" SHA256STAMP:03b1a12409ad02eca1543d99bafdfbd2d7d2c869e182fba513e3f93fb48a7664 +\" SHA256STAMP:2383f44a3bcc1023d6619f5ead4c27d7b2bd9a52bd64d00142fd26658a49dd32 diff --git a/doc/lightning-disableoffer.7.md b/doc/lightning-disableoffer.7.md index 32f6fb66d..396151ba2 100644 --- a/doc/lightning-disableoffer.7.md +++ b/doc/lightning-disableoffer.7.md @@ -40,6 +40,7 @@ On success, an object is returned, containing: - **active** (boolean): Whether the offer can produce invoices/payments (always "false") - **single_use** (boolean): Whether the offer is disabled after first successful use - **bolt12** (string): The bolt12 string representing this offer +- **bolt12_unsigned** (string): The bolt12 string representing this offer, without signature - **used** (boolean): Whether the offer has had an invoice paid / payment made - **label** (string, optional): The label provided when offer was created [comment]: # (GENERATE-FROM-SCHEMA-END) @@ -72,4 +73,4 @@ RESOURCES --------- Main web site: -[comment]: # ( SHA256STAMP:abf340bf35dcefd42fba609b3ae95adb2f74bb5766c68e174a9b8f9114c80202) +[comment]: # ( SHA256STAMP:5b96eca3e35f6c556b93db1743c617b59e69058c9421ece9cc99a9c8814c176b) diff --git a/doc/lightning-listoffers.7 b/doc/lightning-listoffers.7 index 383c855cc..c06b4403d 100644 --- a/doc/lightning-listoffers.7 +++ b/doc/lightning-listoffers.7 @@ -41,6 +41,8 @@ On success, an object containing \fBoffers\fR is returned\. It is an array of o .IP \[bu] \fBbolt12\fR (string): the bolt12 encoding of the offer .IP \[bu] +\fBbolt12_unsigned\fR (string): the bolt12 encoding of the offer, without signature +.IP \[bu] \fBused\fR (boolean): True if an associated invoice has been paid .IP \[bu] \fBlabel\fR (string, optional): the (optional) user-specified label @@ -82,4 +84,4 @@ Rusty Russell \fI is mainly responsible\. Main web site: \fIhttps://github.com/ElementsProject/lightning\fR -\" SHA256STAMP:7e359219084e648a629b0d43774db17bbfbe693074b817fa5890b7c8bccd1429 +\" SHA256STAMP:bf83e52cc56aaef876eb1039a6fbbcd9d2e15703c54f33163176c7ba41523261 diff --git a/doc/lightning-listoffers.7.md b/doc/lightning-listoffers.7.md index b772fb6f4..0ae49761a 100644 --- a/doc/lightning-listoffers.7.md +++ b/doc/lightning-listoffers.7.md @@ -35,6 +35,7 @@ On success, an object containing **offers** is returned. It is an array of obje - **active** (boolean): whether this can still be used - **single_use** (boolean): whether this expires as soon as it's paid - **bolt12** (string): the bolt12 encoding of the offer +- **bolt12_unsigned** (string): the bolt12 encoding of the offer, without signature - **used** (boolean): True if an associated invoice has been paid - **label** (string, optional): the (optional) user-specified label [comment]: # (GENERATE-FROM-SCHEMA-END) @@ -78,4 +79,4 @@ RESOURCES --------- Main web site: -[comment]: # ( SHA256STAMP:58e9f5aa5808e19e3be151b1c1f1215ec23953b60ab294418aa57426c5bcbd46) +[comment]: # ( SHA256STAMP:e2b8508c98e6161c45fca91bceb273e6c2865cec0e1761dde85f8f2dd6670491) diff --git a/doc/lightning-offer.7 b/doc/lightning-offer.7 index eae6ebb78..ee94a4194 100644 --- a/doc/lightning-offer.7 +++ b/doc/lightning-offer.7 @@ -15,6 +15,11 @@ creating one or more invoices\. It automatically enables the processing of an incoming invoice_request, and issuing of invoices\. +Note that it creates two variants of the offer: a signed and an +unsigned one (which is smaller)\. Wallets should accept both: the +current specification allows either\. + + The \fIamount\fR parameter can be the string "any", which creates an offer that can be paid with any amount (e\.g\. a donation)\. Otherwise it can be a positive value in millisatoshi precision; it can be a whole @@ -112,6 +117,8 @@ On success, an object is returned, containing: .IP \[bu] \fBbolt12\fR (string): the bolt12 encoding of the offer .IP \[bu] +\fBbolt12_unsigned\fR (string): the bolt12 encoding of the offer, without a signature +.IP \[bu] \fBused\fR (boolean): True if an associated invoice has been paid (always \fIfalse\fR) .IP \[bu] \fBlabel\fR (string, optional): the (optional) user-specified label @@ -145,4 +152,4 @@ Rusty Russell \fI is mainly responsible\. Main web site: \fIhttps://github.com/ElementsProject/lightning\fR -\" SHA256STAMP:fdc65b544ee660ef7afafb13bc727b859411df072739c4b22973fbc870d785f2 +\" SHA256STAMP:f7faf86c7cb052200c3b4d6e3d6209afa54600cc7a33e1082583a2766d02a275 diff --git a/doc/lightning-offer.7.md b/doc/lightning-offer.7.md index b223c8130..d739ad02a 100644 --- a/doc/lightning-offer.7.md +++ b/doc/lightning-offer.7.md @@ -15,6 +15,10 @@ The **offer** RPC command creates an offer, which is a precursor to creating one or more invoices. It automatically enables the processing of an incoming invoice_request, and issuing of invoices. +Note that it creates two variants of the offer: a signed and an +unsigned one (which is smaller). Wallets should accept both: the +current specification allows either. + The *amount* parameter can be the string "any", which creates an offer that can be paid with any amount (e.g. a donation). Otherwise it can be a positive value in millisatoshi precision; it can be a whole @@ -95,6 +99,7 @@ On success, an object is returned, containing: - **active** (boolean): whether this can still be used (always *true*) - **single_use** (boolean): whether this expires as soon as it's paid (reflects the *single_use* parameter) - **bolt12** (string): the bolt12 encoding of the offer +- **bolt12_unsigned** (string): the bolt12 encoding of the offer, without a signature - **used** (boolean): True if an associated invoice has been paid (always *false*) - **label** (string, optional): the (optional) user-specified label [comment]: # (GENERATE-FROM-SCHEMA-END) @@ -123,4 +128,4 @@ RESOURCES Main web site: -[comment]: # ( SHA256STAMP:20c0be7bad73fcf71ccae61c2c5a112c8602216d9d2e9f647f8273fdf4e3ed8b) +[comment]: # ( SHA256STAMP:0f9cfd3cc68aaba20af0eee763c93b475016619d960e3f5bbc0b762a809f0fef) diff --git a/doc/lightning-offerout.7 b/doc/lightning-offerout.7 index 3aa770286..a0317f5da 100644 --- a/doc/lightning-offerout.7 +++ b/doc/lightning-offerout.7 @@ -17,6 +17,11 @@ offer)\. It automatically enables the accepting and payment of corresponding invoice message (we will only pay once, however!)\. +Note that it creates two variants of the offer: a signed and an +unsigned one (which is smaller)\. Wallets should accept both: the +current specification allows either\. + + The \fIamount\fR parameter can be the string "any", which creates an offer that can be paid with any amount (e\.g\. a donation)\. Otherwise it can be a positive value in millisatoshi precision; it can be a whole @@ -64,6 +69,8 @@ On success, an object is returned, containing: .IP \[bu] \fBbolt12\fR (string): the bolt12 encoding of the offer .IP \[bu] +\fBbolt12_unsigned\fR (string): the bolt12 encoding of the offer, without a signature +.IP \[bu] \fBused\fR (boolean): True if an incoming invoice has been paid (always \fIfalse\fR) .IP \[bu] \fBlabel\fR (string, optional): the (optional) user-specified label @@ -106,4 +113,4 @@ Rusty Russell \fI is mainly responsible\. Main web site: \fIhttps://github.com/ElementsProject/lightning\fR -\" SHA256STAMP:823219aff5dc06ab3b810442048b6cf733210c3eae80567327dc396e5f7987c8 +\" SHA256STAMP:3de11c6de7905322d9ef748981fc1d4f9ca91f4be46d76af6e9124572853047d diff --git a/doc/lightning-offerout.7.md b/doc/lightning-offerout.7.md index 859e9260a..5fa92266e 100644 --- a/doc/lightning-offerout.7.md +++ b/doc/lightning-offerout.7.md @@ -18,6 +18,10 @@ send an invoice for us to pay (technically, this is referred to as a offer). It automatically enables the accepting and payment of corresponding invoice message (we will only pay once, however!). +Note that it creates two variants of the offer: a signed and an +unsigned one (which is smaller). Wallets should accept both: the +current specification allows either. + The *amount* parameter can be the string "any", which creates an offer that can be paid with any amount (e.g. a donation). Otherwise it can be a positive value in millisatoshi precision; it can be a whole @@ -55,6 +59,7 @@ On success, an object is returned, containing: - **active** (boolean): whether this will pay a matching incoming invoice (always *true*) - **single_use** (boolean): whether this expires as soon as it's paid out (always *true*) - **bolt12** (string): the bolt12 encoding of the offer +- **bolt12_unsigned** (string): the bolt12 encoding of the offer, without a signature - **used** (boolean): True if an incoming invoice has been paid (always *false*) - **label** (string, optional): the (optional) user-specified label [comment]: # (GENERATE-FROM-SCHEMA-END) @@ -92,4 +97,4 @@ RESOURCES Main web site: -[comment]: # ( SHA256STAMP:6db3fdba07f376e697326b3bf1bd74c013084a459cb9f4fe76d23fce58bd58fe) +[comment]: # ( SHA256STAMP:2b7e7b543a88a10dbfbca2508e034af79f43ed0845abdb9df1fdf7e28ee33c26) diff --git a/doc/schemas/decode.schema.json b/doc/schemas/decode.schema.json index f76db5357..ad168d24e 100644 --- a/doc/schemas/decode.schema.json +++ b/doc/schemas/decode.schema.json @@ -28,7 +28,7 @@ } }, "then": { - "required": [ "offer_id", "node_id", "signature", "description" ], + "required": [ "offer_id", "node_id", "description" ], "additionalProperties": false, "properties": { "type": { }, diff --git a/doc/schemas/disableoffer.schema.json b/doc/schemas/disableoffer.schema.json index 6b745c8b7..07e177bc4 100644 --- a/doc/schemas/disableoffer.schema.json +++ b/doc/schemas/disableoffer.schema.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", - "required": [ "offer_id", "active", "single_use", "bolt12", "used" ], + "required": [ "offer_id", "active", "single_use", "bolt12", "bolt12_unsigned", "used" ], "additionalProperties": false, "properties": { "offer_id": { @@ -23,6 +23,10 @@ "type": "string", "description": "The bolt12 string representing this offer" }, + "bolt12_unsigned": { + "type": "string", + "description": "The bolt12 string representing this offer, without signature" + }, "used": { "type": "boolean", "description": "Whether the offer has had an invoice paid / payment made" diff --git a/doc/schemas/listoffers.schema.json b/doc/schemas/listoffers.schema.json index 9c6caa101..b7f21d112 100644 --- a/doc/schemas/listoffers.schema.json +++ b/doc/schemas/listoffers.schema.json @@ -9,7 +9,7 @@ "items": { "type": "object", "additionalProperties": false, - "required": [ "offer_id", "active", "single_use", "bolt12", "used" ], + "required": [ "offer_id", "active", "single_use", "bolt12", "bolt12_unsigned", "used" ], "properties": { "offer_id": { "type": "hex", @@ -29,6 +29,10 @@ "type": "string", "description": "the bolt12 encoding of the offer" }, + "bolt12_unsigned": { + "type": "string", + "description": "the bolt12 encoding of the offer, without signature" + }, "used": { "type": "boolean", "description": "True if an associated invoice has been paid" diff --git a/doc/schemas/offer.schema.json b/doc/schemas/offer.schema.json index 2c0e70001..83f7c4e5b 100644 --- a/doc/schemas/offer.schema.json +++ b/doc/schemas/offer.schema.json @@ -2,7 +2,7 @@ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "additionalProperties": false, - "required": [ "offer_id", "active", "single_use", "bolt12", "used" ], + "required": [ "offer_id", "active", "single_use", "bolt12", "bolt12_unsigned", "used" ], "properties": { "offer_id": { "type": "hex", @@ -23,6 +23,10 @@ "type": "string", "description": "the bolt12 encoding of the offer" }, + "bolt12_unsigned": { + "type": "string", + "description": "the bolt12 encoding of the offer, without a signature" + }, "used": { "type": "boolean", "enum": [ false ], diff --git a/doc/schemas/offerout.schema.json b/doc/schemas/offerout.schema.json index 6c0886772..03d98aeeb 100644 --- a/doc/schemas/offerout.schema.json +++ b/doc/schemas/offerout.schema.json @@ -2,7 +2,7 @@ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "additionalProperties": false, - "required": [ "offer_id", "active", "single_use", "bolt12", "used" ], + "required": [ "offer_id", "active", "single_use", "bolt12", "bolt12_unsigned", "used" ], "properties": { "offer_id": { "type": "hex", @@ -24,6 +24,10 @@ "type": "string", "description": "the bolt12 encoding of the offer" }, + "bolt12_unsigned": { + "type": "string", + "description": "the bolt12 encoding of the offer, without a signature" + }, "used": { "type": "boolean", "enum": [ false ], diff --git a/lightningd/offer.c b/lightningd/offer.c index 4cb993707..f63531c7b 100644 --- a/lightningd/offer.c +++ b/lightningd/offer.c @@ -14,6 +14,7 @@ static void json_populate_offer(struct json_stream *response, const struct sha256 *offer_id, const char *b12, + const char *b12_nosig, const struct json_escape *label, enum offer_status status) { @@ -21,6 +22,8 @@ static void json_populate_offer(struct json_stream *response, json_add_bool(response, "active", offer_status_active(status)); json_add_bool(response, "single_use", offer_status_single(status)); json_add_string(response, "bolt12", b12); + if (b12_nosig) + json_add_string(response, "bolt12_unsigned", b12_nosig); json_add_bool(response, "used", offer_status_used(status)); if (label) json_add_escaped_string(response, "label", label); @@ -33,9 +36,9 @@ static struct command_result *param_b12_offer(struct command *cmd, struct tlv_offer **offer) { char *fail; - *offer = offer_decode_nosig(cmd, buffer + tok->start, - tok->end - tok->start, - cmd->ld->our_features, chainparams, &fail); + *offer = offer_decode(cmd, buffer + tok->start, + tok->end - tok->start, + cmd->ld->our_features, chainparams, &fail); if (!*offer) return command_fail_badparam(cmd, name, buffer, tok, fail); if ((*offer)->signature) @@ -83,7 +86,7 @@ static struct command_result *json_createoffer(struct command *cmd, struct json_escape *label; struct tlv_offer *offer; struct sha256 merkle; - const char *b12str; + const char *b12str, *b12str_nosig; bool *single_use; enum offer_status status; struct pubkey32 key; @@ -112,9 +115,11 @@ static struct command_result *json_createoffer(struct command *cmd, OFFER_ALREADY_EXISTS, "Duplicate offer"); } + offer->signature = tal_free(offer->signature); + b12str_nosig = offer_encode(cmd, offer); response = json_stream_success(cmd); - json_populate_offer(response, &merkle, b12str, label, status); + json_populate_offer(response, &merkle, b12str, b12str_nosig, label, status); return command_success(cmd, response); } @@ -126,6 +131,25 @@ static const struct json_command createoffer_command = { }; AUTODATA(json_command, &createoffer_command); +/* We store strings in the db, so removing signatures is easiest by conversion */ +static const char *offer_str_nosig(const tal_t *ctx, + struct lightningd *ld, + const char *b12str) +{ + char *fail; + struct tlv_offer *offer = offer_decode(tmpctx, b12str, strlen(b12str), + ld->our_features, chainparams, + &fail); + + if (!offer) { + log_broken(ld->log, "Cannot reparse offerstr from db %s: %s", + b12str, fail); + return NULL; + } + offer->signature = tal_free(offer->signature); + return offer_encode(ctx, offer); +} + static struct command_result *json_listoffers(struct command *cmd, const char *buffer, const jsmntok_t *obj UNNEEDED, @@ -153,7 +177,9 @@ static struct command_result *json_listoffers(struct command *cmd, if (b12 && offer_status_active(status) >= *active_only) { json_object_start(response, NULL); json_populate_offer(response, - offer_id, b12, label, status); + offer_id, b12, + offer_str_nosig(tmpctx, cmd->ld, b12), + label, status); json_object_end(response); } } else { @@ -168,7 +194,10 @@ static struct command_result *json_listoffers(struct command *cmd, if (offer_status_active(status) >= *active_only) { json_object_start(response, NULL); json_populate_offer(response, - &id, b12, label, status); + &id, b12, + offer_str_nosig(tmpctx, + cmd->ld, b12), + label, status); json_object_end(response); } } @@ -213,7 +242,10 @@ static struct command_result *json_disableoffer(struct command *cmd, status = wallet_offer_disable(wallet, offer_id, status); response = json_stream_success(cmd); - json_populate_offer(response, offer_id, b12, label, status); + json_populate_offer(response, offer_id, b12, + offer_str_nosig(tmpctx, + cmd->ld, b12), + label, status); return command_success(cmd, response); } diff --git a/tests/test_pay.py b/tests/test_pay.py index 881fb5c7f..0211d42da 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -3823,6 +3823,7 @@ def test_offer(node_factory, bitcoind): offer = only_one(l1.rpc.call('listoffers', [ret['offer_id']])['offers']) assert offer['bolt12'] == ret['bolt12'] + assert offer['bolt12_unsigned'] == ret['bolt12_unsigned'] assert offer['offer_id'] == ret['offer_id'] output = subprocess.check_output([bolt12tool, 'decode', @@ -3831,6 +3832,12 @@ def test_offer(node_factory, bitcoind): assert 'amount' not in output else: assert 'amount' in output + output = subprocess.check_output([bolt12tool, 'decode', + offer['bolt12_unsigned']]).decode('ASCII') + if amount == 'any': + assert 'amount' not in output + else: + assert 'amount' in output # Try wrong amount precision: with pytest.raises(RpcError, match='Currency AUD requires 2 minor units'): @@ -3985,7 +3992,7 @@ def test_fetchinvoice(node_factory, bitcoind): 'description': 'simple test'}) inv1 = l1.rpc.call('fetchinvoice', {'offer': offer1['bolt12']}) - inv2 = l1.rpc.call('fetchinvoice', {'offer': offer1['bolt12']}) + inv2 = l1.rpc.call('fetchinvoice', {'offer': offer1['bolt12_unsigned']}) assert inv1 != inv2 assert 'next_period' not in inv1 assert 'next_period' not in inv2 @@ -4244,9 +4251,8 @@ def test_sendinvoice(node_factory, bitcoind): assert only_one(l1.rpc.call('listoffers', [offer['offer_id']])['offers'])['used'] is False # sendinvoice should work. - out = l2.rpc.call('sendinvoice', {'offer': offer['bolt12'], + out = l2.rpc.call('sendinvoice', {'offer': offer['bolt12_unsigned'], 'label': 'test sendinvoice 1'}) - print(out) assert out['label'] == 'test sendinvoice 1' assert out['description'] == 'simple test' assert 'bolt12' in out