Skip to content

Commit b99cbe8

Browse files
committed
Merge branch 'add-testnet4-support' of https://github.com/2seaq/lightning into add-testnet4-support
2 parents 19fcf16 + 0b2df67 commit b99cbe8

File tree

8 files changed

+76
-28
lines changed

8 files changed

+76
-28
lines changed

common/bolt12.c

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,6 @@ struct tlv_invoice *invoice_decode(const tal_t *ctx,
489489
char **fail)
490490
{
491491
struct tlv_invoice *invoice;
492-
u64 expiry, now;
493492

494493
invoice = invoice_decode_minimal(ctx, b12, b12len, our_features,
495494
must_be_chain, fail);
@@ -527,27 +526,6 @@ struct tlv_invoice *invoice_decode(const tal_t *ctx,
527526
return tal_free(invoice);
528527
}
529528

530-
/* BOLT-offers #12:
531-
* - if `invoice_relative_expiry` is present:
532-
* - MUST reject the invoice if the current time since 1970-01-01 UTC
533-
* is greater than `invoice_created_at` plus `seconds_from_creation`.
534-
* - otherwise:
535-
* - MUST reject the invoice if the current time since 1970-01-01 UTC
536-
* is greater than `invoice_created_at` plus 7200.
537-
*/
538-
if (invoice->invoice_relative_expiry)
539-
expiry = *invoice->invoice_relative_expiry;
540-
else
541-
expiry = 7200;
542-
now = time_now().ts.tv_sec;
543-
/* If it overflows, it's forever */
544-
if (!add_overflows_u64(*invoice->invoice_created_at, expiry)
545-
&& now > *invoice->invoice_created_at + expiry) {
546-
*fail = tal_fmt(ctx, "expired %"PRIu64" seconds ago",
547-
now - (*invoice->invoice_created_at + expiry));
548-
return tal_free(invoice);
549-
}
550-
551529
/* BOLT-offers #12:
552530
* - MUST reject the invoice if `invoice_paths` is not present or is
553531
* empty. */
@@ -583,6 +561,30 @@ struct tlv_invoice *invoice_decode(const tal_t *ctx,
583561
return invoice;
584562
}
585563

564+
u64 invoice_expiry(const struct tlv_invoice *invoice)
565+
{
566+
u64 expiry;
567+
568+
/* BOLT-offers #12:
569+
* - if `invoice_relative_expiry` is present:
570+
* - MUST reject the invoice if the current time since 1970-01-01 UTC
571+
* is greater than `invoice_created_at` plus `seconds_from_creation`.
572+
* - otherwise:
573+
* - MUST reject the invoice if the current time since 1970-01-01 UTC
574+
* is greater than `invoice_created_at` plus 7200.
575+
*/
576+
if (invoice->invoice_relative_expiry)
577+
expiry = *invoice->invoice_relative_expiry;
578+
else
579+
expiry = 7200;
580+
581+
/* If it overflows, it's forever */
582+
if (add_overflows_u64(*invoice->invoice_created_at, expiry))
583+
return UINT64_MAX;
584+
585+
return *invoice->invoice_created_at + expiry;
586+
}
587+
586588
static bool bolt12_has_invoice_prefix(const char *str)
587589
{
588590
return strstarts(str, "lni1") || strstarts(str, "LNI1");

common/bolt12.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,17 @@ char *invoice_encode(const tal_t *ctx, const struct tlv_invoice *bolt12_tlv);
7575
* is not expired). It also checks signature.
7676
*
7777
* Note: blinded path features need to be checked by the caller before use!
78+
* Note: expiration must be check by caller before use!
7879
*/
7980
struct tlv_invoice *invoice_decode(const tal_t *ctx,
8081
const char *b12, size_t b12len,
8182
const struct feature_set *our_features,
8283
const struct chainparams *must_be_chain,
8384
char **fail);
8485

86+
/* UINT64_MAX if no expiry. */
87+
u64 invoice_expiry(const struct tlv_invoice *invoice);
88+
8589
/* This one only checks it decides, and optionally is correct chain/features */
8690
struct tlv_invoice *invoice_decode_minimal(const tal_t *ctx,
8791
const char *b12, size_t b12len,

contrib/msggen/msggen/schema.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36330,6 +36330,7 @@
3633036330
"- -1: Catchall nonspecific error.",
3633136331
"- 203: Permanent failure from destination (e.g. it said it didn't recognize invoice)",
3633236332
"- 205: Couldn't find, or find a way to, the destination.",
36333+
"- 207: Invoice has expired.",
3633336334
"- 219: Invoice has already been paid.",
3633436335
"- 209: Other payment error."
3633536336
],

doc/contribute-to-core-lightning/release-checklist.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Here's a checklist for the release process.
3434
3. Confirm that the tag will show up for builds with `git describe`
3535
4. Push the tag to remote `git push --tags`.
3636
5. Draft a new `v<VERSION>rc1` release on Github and check `Set as a pre-release` option.
37-
6. Follow [reproducible build](https://docs.corelightning.org/docs/repro) for [Builder image setup](https://docs.corelightning.org/docs/repro#builder-image-setup). It will create builder images `cl-repro-<codename>` which are required for the next step.
37+
6. Run the script `contrib/cl-repro.sh` for [Builder image setup](https://docs.corelightning.org/docs/repro#builder-image-setup). This will create the required builder images `cl-repro-<codename>` for the next step.
3838
7. Run `tools/build-release.sh bin-Fedora-28-amd64 bin-Ubuntu sign` script to prepare required builds for the release. With `bin-Fedora-28-amd64 bin-Ubuntu sign`, it will build a zipfile, a non-reproducible Fedora, reproducible Ubuntu images. Once it is done, the script will sign the release contents and create SHA256SUMS and SHA256SUMS.asc in the release folder.
3939
8. Upload reproducible builds, SHA256SUMS and SHA256SUMS.asc from the release folder to newly drafted release.
4040
9. Announce rc1 release on core-lightning's release-chat channel on Discord & [BuildOnL2](https://community.corelightning.org/c/general-questions/).
@@ -117,7 +117,7 @@ Here's a checklist for the release process.
117117
7. Confirm that the tag is properly set up for builds by running `git describe`.
118118
8. Push the tag to the remote repository `git push --tags`.
119119
9. Create a new release draft for `v<VERSION>.<POINT_VERSION>` on GitHub, ensuring to check the `Set as a pre-release` option.
120-
10. Follow the [reproducible build](https://docs.corelightning.org/docs/repro) instructions for [Builder image setup](https://docs.corelightning.org/docs/repro#builder-image-setup) to create builder images named `cl-repro-<codename>` required for the next step.
120+
10. Execute the script contrib/cl-repro.sh for the [Builder image setup](https://docs.corelightning.org/docs/repro#builder-image-setup). This will generate the builder images `cl-repro-<codename>` needed for the next step.
121121
11. Run the following script to prepare the required builds `tools/build-release.sh bin-Fedora-28-amd64 bin-Ubuntu sign`.
122122
12. Upload the reproducible builds along with `SHA256SUMS` and `SHA256SUMS.asc` files from the release folder to the newly drafted release.
123123
13. Share the `SHA256SUMS` and `SHA256SUMS.asc` files with the team for verification and signing.

doc/getting-started/advanced-setup/repro.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ Note: Since your signature certifies the integrity of the resulting binaries, pl
2525

2626
The build environments are a set of docker images that are created directly from the installation mediums and repositories from the OS provider. The following sections describe how to create those images. Don't worry, you only have to create each image once and can then reuse the images for future builds.
2727

28+
## Script cl-repro
29+
30+
The script `contrib/cl-repro.sh` covers below `Base image creation` and `Builder image setup` steps. You can skip these steps by simply running the `contrib/cl-repro.sh` script.
31+
2832
## Base image creation
2933

3034
Depending on the distribution that we want to build for the instructions to create a base image can vary. In the following sections we discuss the specific instructions for each distribution, whereas the instructions are identical again once we have the base image.
@@ -93,10 +97,6 @@ sufficient to ensure that the resulting `cl-repro-<codename>` image is reproduci
9397

9498
The dockerfiles assume that the base image has the codename as its image name.
9599

96-
## Script cl-repro
97-
98-
The script `contrib/cl-repro.sh` covers above `Base image creation` and `Builder image setup` steps. You can skip these steps by simply running the `contrib/cl-repro.sh` script.
99-
100100
# Building using the builder image
101101

102102
Finally, after building enviornment setup we can perform the actual build. At this point we have a container image that has been prepared to build reproducibly. As you can see from the `Dockerfile` above we assume the source git repository gets mounted as `/repo` in the docker container. The container will clone the repository to an internal path, in order to keep the repository clean, build the artifacts there, and then copy them back to `/repo/release`.

doc/schemas/lightning-xpay.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
"- -1: Catchall nonspecific error.",
108108
"- 203: Permanent failure from destination (e.g. it said it didn't recognize invoice)",
109109
"- 205: Couldn't find, or find a way to, the destination.",
110+
"- 207: Invoice has expired.",
110111
"- 219: Invoice has already been paid.",
111112
"- 209: Other payment error."
112113
],

plugins/xpay/xpay.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,7 @@ static struct command_result *json_xpay(struct command *cmd,
14141414
struct payment *payment = tal(cmd, struct payment);
14151415
unsigned int *retryfor;
14161416
struct out_req *req;
1417+
u64 now, invexpiry;
14171418
char *err;
14181419

14191420
if (!param_check(cmd, buffer, params,
@@ -1448,6 +1449,7 @@ static struct command_result *json_xpay(struct command *cmd,
14481449
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
14491450
"Invalid bolt12 invoice: %s", err);
14501451

1452+
invexpiry = invoice_expiry(b12inv);
14511453
payment->full_amount = amount_msat(*b12inv->invoice_amount);
14521454
if (msat)
14531455
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
@@ -1517,8 +1519,16 @@ static struct command_result *json_xpay(struct command *cmd,
15171519
payment->full_amount = *b11->msat;
15181520
else
15191521
payment->full_amount = *msat;
1522+
1523+
invexpiry = b11->timestamp + b11->expiry;
15201524
}
15211525

1526+
now = time_now().ts.tv_sec;
1527+
if (now > invexpiry)
1528+
return command_fail(cmd, PAY_INVOICE_EXPIRED,
1529+
"Invoice expired %"PRIu64" seconds ago",
1530+
now - invexpiry);
1531+
15221532
if (partial) {
15231533
payment->amount = *partial;
15241534
if (amount_msat_greater(payment->amount, payment->full_amount))

tests/test_pay.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6768,3 +6768,33 @@ def test_pay_unannounced_routehint(node_factory, bitcoind):
67686768
dev_routes=[routel2l3])
67696769
result = l1.rpc.pay(inv['bolt11'])
67706770
assert result["status"] == "complete", f"pay result is {result}"
6771+
6772+
6773+
def test_decode_expired_bolt12(node_factory):
6774+
l1 = node_factory.get_node()
6775+
6776+
assert l1.rpc.decode('lni1qqgr7gm5fdxs3maw5tx94yx3k2hzxzqrqc0xsz3pwpkxz7t9wf0nwvpkxacku6tzxdhkuemfwdmrv6rywgmkxu35dvcrq93pqvvhnlnvurnfanndnxjtcjnmxrkj92xtsupa6lwjm7hkr8s8zflqkkppqgr5egnuvnfxvhzgemdljrkr5xhapg9zkjd73nqnmgxeesclr0j5skfud3hx7vt6vdehxwfjwakkxwt909skuamydfek67t2vau8zwfc0qukkennw9ensv3nvee8g7rww9jkwmrjwuursanpds6hydmy5zvqxxtelekwpe57eekenf9uffanpmfz4r9cwq7a0hfdltmpncr3ylstqvk0f8p94n8sk8r5pwh5um0v5sgs3atjnk54ja7yxle4putgwrv3sqgr72f645z9yjhe6f0r0ccfwhyufr0h734m2url2yputu25w7yzauxsqv4wftn76zuzrk9mkw203nfsz0kkc4ksk2d6ahd3ecslhrp5ecel7k0zy5r4s46fyjcr5x6kwcry08runv9zrsqqqqqqqqqqqqqqzgqqqqqqqqqqqqqayjedltzjqqqqqq9yq3n5ft0l4qs03nycmga9uqvexwyq2x59y8326r256clag77sq9z5m9wm9jz4ned2qvrpu69syyp3j707dnswd8kwdkv6f0z20vcw6g4gewrs8hta6t067cv7quf8uzlsgqjjt30e2udf5y3d79xpp7fhxktd4qflyexnsn3zthx2u9g5hzt2j45ky7q3mchmq75cqzxlr2x09dlhg6pj958xwgpykl0aczwepj6q') == {
6777+
'invoice_amount_msat': 401000,
6778+
'invoice_created_at': 1732554239,
6779+
'invoice_node_id': '031979fe6ce0e69ece6d99a4bc4a7b30ed22a8cb8703dd7dd2dfaf619e07127e0b',
6780+
'invoice_paths': [{'first_node_id': '031979fe6ce0e69ece6d99a4bc4a7b30ed22a8cb8703dd7dd2dfaf619e07127e0b',
6781+
'first_path_key': '032cf49c25accf0b1c740baf4e6deca41108f5729da95977c437f350f16870d918',
6782+
'path': [{'blinded_node_id': '03f293aad04524af9d25e37e30975c9c48df7f46bb5707f5103c5f15477882ef0d',
6783+
'encrypted_recipient_data': 'ae4ae7ed0b821d8bbb394f8cd3013ed6c56d0b29baeddb1ce21fb8c34ce33ff59e2250758574924b03a1b567606479c7c9b0'}],
6784+
'payinfo': {'cltv_expiry_delta': 18,
6785+
'features': '',
6786+
'fee_base_msat': 0,
6787+
'fee_proportional_millionths': 0}}],
6788+
'invoice_payment_hash': 'f8cc98da3a5e01993388051a8521e2ad0d54d63fd47bd001454d95db2c8559e5',
6789+
'invoice_relative_expiry': 7200,
6790+
'invreq_metadata': '3f23744b4d08efaea2cc5a90d1b2ae23',
6791+
'invreq_payer_id': '02074ca27c64d2665c48cedbf90ec3a1afd0a0a2b49be8cc13da0d9cc31f1be548',
6792+
'invreq_payer_note': 'lno1zcss92wmc9eyanwdjsmyjgxq98x9kfsqs823frtxnqeglrw88val5r7d',
6793+
'offer_amount_msat': 401000,
6794+
'offer_description': 'player_7067qnib3ongisv6hdr7cr4k00',
6795+
'offer_id': '0a32bd421b9c2b1d2cc1c49a5ff1aa8adb5ce02b6dde496358d874e9ca181276',
6796+
'offer_issuer_id': '031979fe6ce0e69ece6d99a4bc4a7b30ed22a8cb8703dd7dd2dfaf619e07127e0b',
6797+
'signature': '2525c5f9571a9a122df14c10f9373596da813f264d384e225dccae1514b896a9569627811de2fb07a98008df1a8cf2b7f7468322d0e672024b7dfdc09d90cb40',
6798+
'type': 'bolt12 invoice',
6799+
'valid': True,
6800+
}

0 commit comments

Comments
 (0)