From 1a8978100efd55a8878cf6e79a3eb40c980c9c8d Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 8 Jan 2021 15:13:50 +1030 Subject: [PATCH] invoice: add ctlv option. This is required if we want to create a "bouncer" plugin (in my copious free time!) Signed-off-by: Rusty Russell Changelog-Added: JSON-RPC: `invoice` now takes an optional `cltv` parameter. --- contrib/pyln-client/pyln/client/lightning.py | 5 +++-- doc/lightning-invoice.7 | 8 ++++++-- doc/lightning-invoice.7.md | 5 ++++- lightningd/invoice.c | 5 ++++- tests/test_invoices.py | 6 ++++++ 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/contrib/pyln-client/pyln/client/lightning.py b/contrib/pyln-client/pyln/client/lightning.py index c99122d21..09b75fa11 100644 --- a/contrib/pyln-client/pyln/client/lightning.py +++ b/contrib/pyln-client/pyln/client/lightning.py @@ -872,7 +872,7 @@ class LightningRpc(UnixDomainSocketRpc): } return self.call("help", payload) - def invoice(self, msatoshi, label, description, expiry=None, fallbacks=None, preimage=None, exposeprivatechannels=None): + def invoice(self, msatoshi, label, description, expiry=None, fallbacks=None, preimage=None, exposeprivatechannels=None, cltv=None): """ Create an invoice for {msatoshi} with {label} and {description} with optional {expiry} seconds (default 1 week). @@ -884,7 +884,8 @@ class LightningRpc(UnixDomainSocketRpc): "expiry": expiry, "fallbacks": fallbacks, "preimage": preimage, - "exposeprivatechannels": exposeprivatechannels + "exposeprivatechannels": exposeprivatechannels, + "cltv": cltv, } return self.call("invoice", payload) diff --git a/doc/lightning-invoice.7 b/doc/lightning-invoice.7 index b0d434404..16d43d0d1 100644 --- a/doc/lightning-invoice.7 +++ b/doc/lightning-invoice.7 @@ -4,7 +4,7 @@ lightning-invoice - Command for accepting payments .SH SYNOPSIS \fBinvoice\fR \fImsatoshi\fR \fIlabel\fR \fIdescription\fR [\fIexpiry\fR] -[\fIfallbacks\fR] [\fIpreimage\fR] [\fIexposeprivatechannels\fR] +[\fIfallbacks\fR] [\fIpreimage\fR] [\fIexposeprivatechannels\fR] [\fIcltv\fR] .SH DESCRIPTION @@ -71,6 +71,10 @@ other public channel)\. The selection uses some randomness to prevent probing, but favors channels that become more balanced after the payment\. + +If specified, \fIcltv\fR sets the \fImin_final_cltv_expiry\fR for the invoice\. +Otherwise, it's set to the parameter \fBcltv-final\fR\. + .SH RETURN VALUE On success, a hash is returned as \fIpayment_hash\fR to be given to the @@ -124,4 +128,4 @@ Rusty Russell \fI is mainly responsible\. Main web site: \fIhttps://github.com/ElementsProject/lightning\fR -\" SHA256STAMP:9a361884baa1bdceffb9861839ce4728cf38eaf5d08b3437ad4b3f5b9b42d8db +\" SHA256STAMP:5a7792cb739f34adf7db346f3bd615816915230fcb8343af1b742336a677dbc2 diff --git a/doc/lightning-invoice.7.md b/doc/lightning-invoice.7.md index 4914255cd..7b2b0757c 100644 --- a/doc/lightning-invoice.7.md +++ b/doc/lightning-invoice.7.md @@ -5,7 +5,7 @@ SYNOPSIS -------- **invoice** *msatoshi* *label* *description* \[*expiry*\] -\[*fallbacks*\] \[*preimage*\] \[*exposeprivatechannels*\] +\[*fallbacks*\] \[*preimage*\] \[*exposeprivatechannels*\] \[*cltv*\] DESCRIPTION ----------- @@ -65,6 +65,9 @@ other public channel). The selection uses some randomness to prevent probing, but favors channels that become more balanced after the payment. +If specified, *cltv* sets the *min_final_cltv_expiry* for the invoice. +Otherwise, it's set to the parameter **cltv-final**. + RETURN VALUE ------------ diff --git a/lightningd/invoice.c b/lightningd/invoice.c index 89dbee7b2..848a2699b 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -1006,6 +1006,7 @@ static struct command_result *json_invoice(struct command *cmd, struct sha256 rhash; struct secret payment_secret; struct preimage *preimage; + u32 *cltv; #if DEVELOPER const jsmntok_t *routes; #endif @@ -1022,6 +1023,8 @@ static struct command_result *json_invoice(struct command *cmd, p_opt("preimage", param_preimage, &preimage), p_opt("exposeprivatechannels", param_chanhints, &info->chanhints), + p_opt_def("cltv", param_number, &cltv, + cmd->ld->config.cltv_final), #if DEVELOPER p_opt("dev-routes", param_array, &routes), #endif @@ -1081,7 +1084,7 @@ static struct command_result *json_invoice(struct command *cmd, info->b11->timestamp = time_now().ts.tv_sec; info->b11->payment_hash = rhash; info->b11->receiver_id = cmd->ld->id; - info->b11->min_final_cltv_expiry = cmd->ld->config.cltv_final; + info->b11->min_final_cltv_expiry = *cltv; info->b11->expiry = *expiry; info->b11->description = tal_steal(info->b11, desc_val); info->b11->description_hash = NULL; diff --git a/tests/test_invoices.py b/tests/test_invoices.py index 881f77097..26983ac92 100644 --- a/tests/test_invoices.py +++ b/tests/test_invoices.py @@ -30,6 +30,7 @@ def test_invoice(node_factory, chainparams): assert b11['fallbacks'][0]['type'] == 'P2WPKH' assert b11['fallbacks'][1]['addr'] == addr2 assert b11['fallbacks'][1]['type'] == 'P2SH' + assert b11['min_final_cltv_expiry'] == 5 # There's no incoming channel, so no routeboost assert 'routes' not in b11 assert 'warning_capacity' in inv @@ -58,6 +59,11 @@ def test_invoice(node_factory, chainparams): l2.rpc.invoice(4294967295 + 1, 'inv3', '?') l2.rpc.invoice(4294967295, 'inv3', '?') + # Test cltv option. + inv = l1.rpc.invoice(123000, 'label3', 'description', '3700', cltv=99) + b11 = l1.rpc.decodepay(inv['bolt11']) + assert b11['min_final_cltv_expiry'] == 99 + def test_invoice_zeroval(node_factory): """A zero value invoice is unpayable, did you mean 'any'?"""