diff --git a/common/bolt12.c b/common/bolt12.c index e0beb67be..f3bcbcdc1 100644 --- a/common/bolt12.c +++ b/common/bolt12.c @@ -407,7 +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), or 2 (months). + * 1. A `time_unit` defining 0 (seconds), 1 (days), 2 (months). */ switch (recur->time_unit) { case 0: @@ -429,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; @@ -454,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; @@ -465,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, diff --git a/devtools/bolt12-cli.c b/devtools/bolt12-cli.c index 222c2b4fb..830d2744a 100644 --- a/devtools/bolt12-cli.c +++ b/devtools/bolt12-cli.c @@ -186,19 +186,22 @@ static bool print_recurrence(const char *fieldname, /* BOLT-recurrence #12: * Thus, each offer containing a recurring payment has: - * 1. A `time_unit` defining 0 (seconds), 1 (days), or 2 (months). + * 1. A `time_unit` defining 0 (seconds), 1 (days), 2 (months). * 2. A `period`, defining how often (in `time_unit`) it has to be paid. - * 3. An optional `recurrence_limit` of total payments to be paid. - * 4. An optional `recurrence_base`: + * 3. An optional `offer_recurrence_limit` of total payments to be paid. + * 4. An optional `offer_recurrence_base`: * * `basetime`, defining when the first period starts * in seconds since 1970-01-01 UTC. - * 5. An optional `recurrence_paywindow`: + * * The payer uses `invreq_recurrence_start` to indicate what period + * they are starting at. If you don't want them to start at arbitrary + * periods, use `offer_absolute_expiry`. + * * A `proportional_amount` flag: if set indicating that a payment made + * during the period itself will be charged proportionally to the + * remaining time in the period (e.g. 150 seconds into a 1500 second + * period gives a 10% discount). + * 5. An optional `offer_recurrence_paywindow`: * * `seconds_before`, defining how many seconds prior to the start of * the period a payment will be accepted. - * * `proportional_amount`, if set indicating that a payment made - * during the period itself will be charged proportionally to the - * remaining time in the period (e.g. 150 seconds into a 1500 - * second period gives a 10% discount). * * `seconds_after`, defining how many seconds after the start of the * period a payment will be accepted. * If this field is missing, payment will be accepted during the prior diff --git a/plugins/fetchinvoice.c b/plugins/fetchinvoice.c index 1635eac93..b70c9f4a8 100644 --- a/plugins/fetchinvoice.c +++ b/plugins/fetchinvoice.c @@ -291,12 +291,14 @@ static struct command_result *handle_invreq_response(struct command *cmd, } else expected_amount = NULL; + recurrence = invoice_recurrence(inv); + /* BOLT-recurrence #12: - * - if the offer contained `recurrence`: - * - MUST reject the invoice if `recurrence_basetime` is not set. + * - if `offer_recurrence_optional` or `offer_recurrence_compulsory` are present: + * - MUST reject the invoice if `invoice_recurrence_basetime` is not present. */ - if (inv->invreq_recurrence_counter && !inv->invoice_recurrence_basetime) { - badfield = "recurrence_basetime"; + if (recurrence && !inv->invoice_recurrence_basetime) { + badfield = "invoice_recurrence_basetime"; goto badinv; } @@ -316,7 +318,6 @@ static struct command_result *handle_invreq_response(struct command *cmd, json_object_end(out); /* We tell them about next period at this point, if any. */ - recurrence = invoice_recurrence(inv); if (recurrence) { u64 next_counter, next_period_idx; u64 paywindow_start, paywindow_end; @@ -704,9 +705,9 @@ static struct command_result *invreq_done(struct command *cmd, period_idx += *sent->invreq->invreq_recurrence_start; /* BOLT-recurrence #12: - * - if the offer contained `recurrence_limit`: - * - MUST NOT send an `invoice_request` for a period greater - * than `max_period` + * - if `offer_recurrence_limit` is present: + * - MUST NOT send an `invoice_request` for a period greater than + * `max_period` */ if (sent->invreq->offer_recurrence_limit && period_idx > *sent->invreq->offer_recurrence_limit) @@ -926,7 +927,7 @@ struct command_result *json_fetchinvoice(struct command *cmd, } /* BOLT-recurrence #12: - * - if the offer contained `recurrence`: + * - if `offer_recurrence_optional` or `offer_recurrence_compulsory` are present: */ if (invreq_recurrence(invreq)) { struct sha256 offer_id, tweak; @@ -935,12 +936,12 @@ struct command_result *json_fetchinvoice(struct command *cmd, /* BOLT-recurrence #12: * - for the initial request: *... - * - MUST set `recurrence_counter` `counter` to 0. + * - MUST set `invreq_recurrence_counter` `counter` to 0. */ /* BOLT-recurrence #12: * - for any successive requests: *... - * - MUST set `recurrence_counter` `counter` to one greater + * - MUST set `invreq_recurrence_counter` `counter` to one greater * than the highest-paid invoice. */ if (!invreq->invreq_recurrence_counter) @@ -998,15 +999,19 @@ struct command_result *json_fetchinvoice(struct command *cmd, } else { /* BOLT-recurrence #12: * - otherwise: - * - MUST NOT set `recurrence_counter`. - * - MUST NOT set `recurrence_start` + * - MUST NOT set `invreq_recurrence_counter`. + * - MUST NOT set `invreq_recurrence_start` + * - MUST NOT set `invreq_recurrence_cancel` */ if (invreq->invreq_recurrence_counter) return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "unnecessary recurrence_counter"); + "unnecessary invreq_recurrence_counter"); if (invreq->invreq_recurrence_start) return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "unnecessary recurrence_start"); + "unnecessary invreq_recurrence_start"); + if (invreq->invreq_recurrence_cancel) + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "unnecessary invreq_recurrence_cancel"); /* if the payer force to use the payer_metadata */ if (payer_metadata) { diff --git a/plugins/offers.c b/plugins/offers.c index 132f85c24..6076b5857 100644 --- a/plugins/offers.c +++ b/plugins/offers.c @@ -668,7 +668,7 @@ static bool json_add_blinded_paths(struct command *cmd, static const char *recurrence_time_unit_name(u8 time_unit) { /* BOLT-recurrence #12: - * `time_unit` defining 0 (seconds), 1 (days), or 2 (months). + * `time_unit` defining 0 (seconds), 1 (days), 2 (months). */ switch (time_unit) { case 0: @@ -1242,9 +1242,8 @@ static void json_add_b12_invoice(struct command *cmd, } /* BOLT-recurrence #12: - * - if the offer contained `recurrence`: - * - MUST reject the invoice if `recurrence_basetime` is not - * set. + * - if `offer_recurrence_optional` or `offer_recurrence_compulsory` are present: + * - MUST reject the invoice if `invoice_recurrence_basetime` is not present. */ if (invoice_recurrence(invoice)) { if (invoice->invoice_recurrence_basetime) diff --git a/plugins/offers_invreq_hook.c b/plugins/offers_invreq_hook.c index d19b1e1dd..0c0b8ee42 100644 --- a/plugins/offers_invreq_hook.c +++ b/plugins/offers_invreq_hook.c @@ -122,12 +122,12 @@ test_field(struct command *cmd, } /* BOLT-recurrence #12: - * - if the invoice corresponds to an offer with `recurrence`: - * ... - * - if it sets `relative_expiry`: - * - MUST NOT set `relative_expiry` `seconds_from_creation` more than the - * number of seconds after `created_at` that payment for this period will - * be accepted. + * - if `offer_recurrence_optional` or `offer_recurrence_compulsory` are present: + *... + * - if it sets `invoice_relative_expiry`: + * - MUST NOT set `invoice_relative_expiry`.`seconds_from_creation` more than the + * number of seconds after `invoice_created_at` that payment for this period + * will be accepted. */ static void set_recurring_inv_expiry(struct tlv_invoice *inv, u64 last_pay) { @@ -385,9 +385,11 @@ static struct command_result *check_period(struct command *cmd, basetime = ir->invreq->offer_recurrence_base->basetime; /* BOLT-recurrence #12: - * - if the invoice corresponds to an offer with `recurrence`: - * - MUST set `recurrence_basetime` to the start of period #0 as - * calculated by [Period Calculation](#offer-period-calculation). + * - if `offer_recurrence_optional` or `offer_recurrence_compulsory` + * are present: + * - MUST set `invoice_recurrence_basetime`.`basetime` to the + * start of period #0 as calculated by + * [Period Calculation](#offer-period-calculation). */ ir->inv->invoice_recurrence_basetime = tal_dup(ir->inv, u64, &basetime); @@ -395,7 +397,7 @@ static struct command_result *check_period(struct command *cmd, /* BOLT-recurrence #12: * - if `offer_recurrence_base` is present: - * - MUST fail the request if there is no `invreq_recurrence_start` + * - MUST reject the invoice request if there is no `invreq_recurrence_start` * field. * - MUST consider the period index for this request to be the * `invreq_recurrence_start` field plus the `invreq_recurrence_counter` @@ -423,8 +425,8 @@ static struct command_result *check_period(struct command *cmd, } /* BOLT-recurrence #12: - * - if the offer has a `recurrence_limit`: - * - MUST fail the request if the period index is greater than + * - if `offer_recurrence_limit` is present: + * - MUST reject the invoice request if the period index is greater than * `max_period`. */ if (ir->invreq->offer_recurrence_limit @@ -901,7 +903,7 @@ static struct command_result *listoffers_done(struct command *cmd, /* BOLT-recurrence #12: * * - if `offer_recurrence_optional` or `offer_recurrence_compulsory` are present: - * - MUST reject the invoice request if there is no `recurrence_counter` + * - MUST reject the invoice request if there is no `invreq_recurrence_counter` * field. */ err = invreq_must_have(cmd, ir, invreq_recurrence_counter); @@ -909,10 +911,10 @@ static struct command_result *listoffers_done(struct command *cmd, return err; } else { /* BOLT-recurrence #12: - * - otherwise (the offer had no `recurrence`): - * - MUST reject the invoice request if there is a `recurrence_counter` + * - otherwise (no recurrence): + * - MUST reject the invoice request if there is a `invreq_recurrence_counter` * field. - * - MUST reject the invoice request if there is a `recurrence_start` + * - MUST reject the invoice request if there is a `invreq_recurrence_start` * field. */ err = invreq_must_not_have(cmd, ir, invreq_recurrence_counter);