fetchinvoice: return the next period for recurring offers.

This is useful for the caller to know when to call again.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2020-12-16 13:48:42 +10:30 committed by Christian Decker
parent 19af1d10e6
commit 96caf9f4ab
2 changed files with 62 additions and 0 deletions

View File

@ -200,6 +200,15 @@ static struct command_result *recv_onion_message(struct command *cmd,
} else
expected_amount = NULL;
/* BOLT-offers #12:
* - if the offer contained `recurrence`:
* - MUST reject the invoice if `recurrence_basetime` is not set.
*/
if (sent->invreq->recurrence_counter && !inv->recurrence_basetime) {
badfield = "recurrence_basetime";
goto badinv;
}
/* BOLT-offers #12:
* - SHOULD confirm authorization if the `description` does not exactly
* match the `offer`
@ -252,6 +261,44 @@ static struct command_result *recv_onion_message(struct command *cmd,
amount_msat(*inv->amount));
json_object_end(out);
/* We tell them about next period at this point, if any. */
if (sent->offer->recurrence) {
u64 next_counter, next_period_idx;
u64 paywindow_start, paywindow_end;
next_counter = *sent->invreq->recurrence_counter + 1;
if (sent->invreq->recurrence_start)
next_period_idx = *sent->invreq->recurrence_start
+ next_counter;
else
next_period_idx = next_counter;
/* If this was the last, don't tell them about a next! */
if (!sent->offer->recurrence_limit
|| next_period_idx <= *sent->offer->recurrence_limit) {
json_object_start(out, "next_period");
json_add_u64(out, "counter", next_counter);
json_add_u64(out, "starttime",
offer_period_start(*inv->recurrence_basetime,
next_period_idx,
sent->offer->recurrence));
json_add_u64(out, "endtime",
offer_period_start(*inv->recurrence_basetime,
next_period_idx + 1,
sent->offer->recurrence) - 1);
offer_period_paywindow(sent->offer->recurrence,
sent->offer->recurrence_paywindow,
sent->offer->recurrence_base,
*inv->recurrence_basetime,
next_period_idx,
&paywindow_start, &paywindow_end);
json_add_u64(out, "paywindow_start", paywindow_start);
json_add_u64(out, "paywindow_end", paywindow_end);
json_object_end(out);
}
}
discard_result(command_finished(sent->cmd, out));
return command_hook_success(cmd);

View File

@ -3856,6 +3856,8 @@ def test_fetchinvoice(node_factory, bitcoind):
inv1 = l1.rpc.call('fetchinvoice', {'offer': offer})
inv2 = l1.rpc.call('fetchinvoice', {'offer': offer})
assert inv1 != inv2
assert 'next_period' not in inv1
assert 'next_period' not in inv2
l1.rpc.pay(inv1['invoice'])
l1.rpc.pay(inv2['invoice'])
@ -3868,6 +3870,8 @@ def test_fetchinvoice(node_factory, bitcoind):
inv1 = l1.rpc.call('fetchinvoice', {'offer': offer})
inv2 = l1.rpc.call('fetchinvoice', {'offer': offer})
assert inv1 != inv2
assert 'next_period' not in inv1
assert 'next_period' not in inv2
l1.rpc.pay(inv1['invoice'])
@ -3890,6 +3894,11 @@ def test_fetchinvoice(node_factory, bitcoind):
'recurrence_counter': 0,
'recurrence_label': 'test recurrence'})
print(ret)
period1 = ret['next_period']
assert period1['counter'] == 1
assert period1['endtime'] == period1['starttime'] + 59
assert period1['paywindow_start'] == period1['starttime'] - 60
assert period1['paywindow_end'] == period1['endtime']
l1.rpc.pay(ret['invoice'], label='test recurrence')
@ -3897,5 +3906,11 @@ def test_fetchinvoice(node_factory, bitcoind):
'recurrence_counter': 1,
'recurrence_label': 'test recurrence'})
print(ret)
period2 = ret['next_period']
assert period2['counter'] == 2
assert period2['starttime'] == period1['endtime'] + 1
assert period2['endtime'] == period2['starttime'] + 59
assert period2['paywindow_start'] == period2['starttime'] - 60
assert period2['paywindow_end'] == period2['endtime']
l1.rpc.pay(ret['invoice'], label='test recurrence')