Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .msggen.json
Original file line number Diff line number Diff line change
Expand Up @@ -3146,6 +3146,8 @@
"Offer.description": 2,
"Offer.issuer": 3,
"Offer.label": 4,
"Offer.optional_recurrence": 14,
"Offer.proportional_amount": 13,
"Offer.quantity_max": 5,
"Offer.recurrence": 7,
"Offer.recurrence_base": 8,
Expand Down Expand Up @@ -11338,6 +11340,14 @@
"added": "pre-v0.10.1",
"deprecated": null
},
"Offer.optional_recurrence": {
"added": "v25.09",
"deprecated": null
},
"Offer.proportional_amount": {
"added": "v25.09",
"deprecated": null
},
"Offer.quantity_max": {
"added": "pre-v0.10.1",
"deprecated": null
Expand Down
3 changes: 2 additions & 1 deletion cln-grpc/proto/node.proto

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

6 changes: 4 additions & 2 deletions cln-grpc/src/convert.rs

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

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

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

47 changes: 30 additions & 17 deletions common/bolt12.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,11 +377,6 @@ static void add_months(struct tm *tm, u32 number)
tm->tm_mon += number;
}

static void add_years(struct tm *tm, u32 number)
{
tm->tm_year += number;
}

static u64 time_change(u64 prevstart, u32 number,
void (*add_time)(struct tm *tm, u32 number),
bool day_const)
Expand Down Expand Up @@ -412,8 +407,7 @@ u64 offer_period_start(u64 basetime, size_t n,
const struct recurrence *recur)
{
/* BOLT-recurrence #12:
* 1. A `time_unit` defining 0 (seconds), 1 (days), 2 (months),
* 3 (years).
* 1. A `time_unit` defining 0 (seconds), 1 (days), 2 (months).
*/
switch (recur->time_unit) {
case 0:
Expand All @@ -422,8 +416,6 @@ u64 offer_period_start(u64 basetime, size_t n,
return time_change(basetime, recur->period * n, add_days, false);
case 2:
return time_change(basetime, recur->period * n, add_months, true);
case 3:
return time_change(basetime, recur->period * n, add_years, true);
default:
/* This is our offer, how did we get here? */
return 0;
Expand All @@ -437,17 +429,17 @@ void offer_period_paywindow(const struct recurrence *recurrence,
u64 *start, u64 *end)
{
/* BOLT-recurrence #12:
* - if the offer contains `recurrence_paywindow`:
* - if `offer_recurrence_paywindow` is present:
*/
if (recurrence_paywindow) {
u64 pstart = offer_period_start(basetime, period_idx,
recurrence);
/* BOLT-recurrence #12:
* - if the offer has a `recurrence_basetime` or the
* - if `recurrence_basetime` is present or
* `recurrence_counter` is non-zero:
* - SHOULD NOT send an `invreq` for a period prior to
* - SHOULD NOT send an `invoice_request` for a period prior to
* `seconds_before` seconds before that period start.
* - SHOULD NOT send an `invreq` for a period later
* - SHOULD NOT send an `invoice_request` for a period later
* than `seconds_after` seconds past that period start.
*/
*start = pstart - recurrence_paywindow->seconds_before;
Expand All @@ -462,9 +454,9 @@ void offer_period_paywindow(const struct recurrence *recurrence,
} else {
/* BOLT-recurrence #12:
* - otherwise:
* - SHOULD NOT send an `invreq` with
* `recurrence_counter` is non-zero for a period whose
* immediate predecessor has not yet begun.
* - SHOULD NOT send an `invoice_request` with
* non-zero `recurrence_counter` for a period
* whose immediate predecessor has not yet begun.
*/
if (period_idx == 0)
*start = 0;
Expand All @@ -473,7 +465,7 @@ void offer_period_paywindow(const struct recurrence *recurrence,
recurrence);

/* BOLT-recurrence #12:
* - SHOULD NOT send an `invreq` for a period which
* - SHOULD NOT send an `invoice_request` for a period which
* has already passed.
*/
*end = offer_period_start(basetime, period_idx+1,
Expand Down Expand Up @@ -815,3 +807,24 @@ bool bolt12_bip353_valid_string(const u8 *str, size_t len)
}
return true;
}

const struct recurrence *offer_recurrence(const struct tlv_offer *offer)
{
if (offer->offer_recurrence_compulsory)
return offer->offer_recurrence_compulsory;
return offer->offer_recurrence_optional;
}

const struct recurrence *invreq_recurrence(const struct tlv_invoice_request *invreq)
{
if (invreq->offer_recurrence_compulsory)
return invreq->offer_recurrence_compulsory;
return invreq->offer_recurrence_optional;
}

const struct recurrence *invoice_recurrence(const struct tlv_invoice *inv)
{
if (inv->offer_recurrence_compulsory)
return inv->offer_recurrence_compulsory;
return inv->offer_recurrence_optional;
}
5 changes: 5 additions & 0 deletions common/bolt12.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,4 +183,9 @@ const struct tlv_field *any_field_outside_range(const struct tlv_field *fields,
* `A`-`Z`, `-`, `_` or `.`.
*/
bool bolt12_bip353_valid_string(const u8 *str, size_t strlen);

/* Extract either offer_recurrence_compulsory or offer_recurrence_optional */
const struct recurrence *offer_recurrence(const struct tlv_offer *offer);
const struct recurrence *invreq_recurrence(const struct tlv_invoice_request *invreq);
const struct recurrence *invoice_recurrence(const struct tlv_invoice *inv);
#endif /* LIGHTNING_COMMON_BOLT12_H */
4 changes: 2 additions & 2 deletions common/json_param.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ bool param(struct command *cmd, const char *buffer,

/*
* Version which *doesn't* fail if command_check_only(cmd) is true:
* allows you can do extra checks after, but MUST still fail with
* command_param_failed(); if command_check_only(cmd) is true! */
* allows you can do extra checks after, but MUST terminate
* with command_check_done() if command_check_only(cmd) is true! */
bool param_check(struct command *cmd,
const char *buffer,
const jsmntok_t tokens[], ...) LAST_ARG_NULL;
Expand Down
121 changes: 95 additions & 26 deletions contrib/msggen/msggen/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4828,6 +4828,87 @@
}
]
},
"cancelrecurringinvoice.json": {
"$schema": "../rpc-schema-draft.json",
"type": "object",
"added": "v25.09",
"rpc": "cancelrecurringinvoice",
"title": "Command for sending a cancel message for a recurring offer",
"description": [
"NOTE: Recurring offers are experimental, and may be changed in backwards-incompable ways.",
"",
"The **cancelrecurringinvoice** RPC command sends a cancellation message in place of an invoice_request. The BOLT 12 specification suggests sending this as a courtesy in place of the next invoice_request (as would be sent by fetchinvoice)."
],
"request": {
"required": [
"offer",
"recurrence_counter",
"recurrence_label"
],
"additionalProperties": false,
"properties": {
"offer": {
"type": "string",
"description": [
"Offer string (must be recurring) which we have been paying."
]
},
"recurrence_counter": {
"type": "u64",
"description": [
"One later than the last-specified recurrence_counter for the last invoice."
]
},
"recurrence_label": {
"type": "string",
"description": [
"This must be the same as prior fetchinvoice calls for the same recurrence, as it is used to link them together."
]
},
"recurrence_start": {
"type": "number",
"description": [
"Indicates what period number to start at (usually 0). This will be the same as previous fetchinvoice calls."
]
},
"payer_note": {
"type": "string",
"description": [
"To tell the issuer the reason for the cancellation."
]
},
"bip353": {
"type": "string",
"description": [
"BIP353 string (optionally with \u20bf) indicating where we fetched the offer from"
]
}
}
},
"response": {
"required": [
"bolt12"
],
"additionalProperties": false,
"properties": {
"bolt12": {
"type": "string",
"description": [
"The invoice_request we sent to the issuer."
]
}
}
},
"author": [
"Rusty Russell <<[email protected]>> is mainly responsible."
],
"see_also": [
"lightning-fetchinvoice(7)"
],
"resources": [
"Main web site: <https://github.com/ElementsProject/lightning>"
]
},
"check.json": {
"$schema": "../rpc-schema-draft.json",
"type": "object",
Expand Down Expand Up @@ -7242,12 +7323,6 @@
"Period starts at this UNIX timestamp."
]
},
"start_any_period": {
"type": "u64",
"description": [
"You can start at any period (only if `basetime` present)."
]
},
"limit": {
"type": "u32",
"description": [
Expand Down Expand Up @@ -7666,12 +7741,6 @@
"Period starts at this UNIX timestamp."
]
},
"start_any_period": {
"type": "u64",
"description": [
"You can start at any period (only if `basetime` present)."
]
},
"limit": {
"type": "u32",
"description": [
Expand Down Expand Up @@ -8304,12 +8373,6 @@
"Period starts at this UNIX timestamp."
]
},
"start_any_period": {
"type": "u64",
"description": [
"You can start at any period (only if `basetime` present)."
]
},
"limit": {
"type": "u32",
"description": [
Expand Down Expand Up @@ -12411,7 +12474,7 @@
"recurrence_start": {
"type": "number",
"description": [
"Required if the offer specifies recurrence_base with start_any_period set, otherwise it is not allowed. It indicates what period number to start at."
"Indicates what period number to start at (usually 0)."
]
},
"recurrence_label": {
Expand Down Expand Up @@ -26690,7 +26753,7 @@
"recurrence": {
"type": "string",
"description": [
"An invoice is expected at regular intervals. The argument is a positive number followed by one of `seconds`, `minutes`, `hours`, `days`, `weeks`, `months` or `years` (variants without the trailing `s` are also permitted). This is encoded in the offer. The semantics of recurrence is fairly predictable, but fully documented in BOLT 12. e.g. `4weeks`."
"An invoice is expected at regular intervals. The argument is a positive number followed by one of `seconds`, `minutes`, `hours`, `days`, `weeks`, or `months` (variants without the trailing `s` are also permitted). This is encoded in the offer. The semantics of recurrence is fairly predictable, but fully documented in BOLT 12. e.g. `4weeks`."
]
},
"recurrence_base": {
Expand All @@ -26702,7 +26765,7 @@
"recurrence_paywindow": {
"type": "string",
"description": [
"Argument of form `-time+time[%]`. The first time is the number of seconds before the start of a period in which an invoice and payment is valid, the second time is the number of seconds after the start of the period. For example *-604800+86400* means you can fetch an pay the invoice 4 weeks before the given period starts, and up to 1 day afterwards. The optional *%* indicates that the amount of the invoice will be scaled by the time remaining in the period. This is encoded in the offer."
"Argument of form `-time+time`. The first time is the number of seconds before the start of a period in which an invoice and payment is valid, the second time is the number of seconds after the start of the period. For example *-604800+86400* means you can fetch an pay the invoice 4 weeks before the given period starts, and up to 1 day afterwards. The optional *%* indicates that the amount of the invoice will be scaled by the time remaining in the period. This is encoded in the offer."
],
"default": "that payment is allowed during the current and previous periods"
},
Expand All @@ -26719,13 +26782,19 @@
],
"default": "False"
},
"recurrence_start_any_period": {
"added": "v24.02",
"proportional_amount": {
"added": "v25.09",
"type": "boolean",
"description": [
"This means that the invoice may start by paying during any period; otherwise it must start by paying at the first period. Setting this to false only makes sense if *recurrence_base* was provided. This is encoded in the offer."
],
"default": "True"
"Payment will be charged for the initial period proportional to the amount remaining (only makes sense if recurrence_base is specified)"
]
},
"optional_recurrence": {
"added": "v25.09",
"type": "boolean",
"description": [
"Make recurrence optional, for backwards compatibility (older payers will only pay once)."
]
},
"dev_paths": {
"hidden": true
Expand Down
Loading
Loading