Skip to content

Commit

Permalink
lightningd/invoice.c: Add timeout parameter to waitanyinvoice.
Browse files Browse the repository at this point in the history
Fixes: #3192

Changelog-Added: `waitanyinvoice` now supports a `timeout` parameter, which when set will cause the command to fail when the timeout is reached; can set this to 0 to fail immediately if no new invoice has been paid yet.
  • Loading branch information
ZmnSCPxj authored and cdecker committed Jan 28, 2020
1 parent e379528 commit 67590fc
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 5 deletions.
1 change: 1 addition & 0 deletions common/jsonrpc_errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,6 @@
#define INVOICE_LABEL_ALREADY_EXISTS 900
#define INVOICE_PREIMAGE_ALREADY_EXISTS 901
#define INVOICE_HINTS_GAVE_NO_ROUTES 902
#define INVOICE_WAIT_TIMED_OUT 904

#endif /* LIGHTNING_COMMON_JSONRPC_ERRORS_H */
8 changes: 6 additions & 2 deletions contrib/pyln-client/pyln/client/lightning.py
Original file line number Diff line number Diff line change
Expand Up @@ -988,14 +988,18 @@ def stop(self):
"""
return self.call("stop")

def waitanyinvoice(self, lastpay_index=None):
def waitanyinvoice(self, lastpay_index=None, timeout=None, **kwargs):
"""
Wait for the next invoice to be paid, after {lastpay_index}
(if supplied)
Fail after {timeout} seconds has passed without an invoice
being paid.
"""
payload = {
"lastpay_index": lastpay_index
"lastpay_index": lastpay_index,
"timeout": timeout
}
payload.update({k: v for k, v in kwargs.items()})
return self.call("waitanyinvoice", payload)

def waitblockheight(self, blockheight, timeout=None):
Expand Down
20 changes: 19 additions & 1 deletion doc/lightning-waitanyinvoice.7

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

15 changes: 14 additions & 1 deletion doc/lightning-waitanyinvoice.7.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ lightning-waitanyinvoice -- Command for waiting for payments
SYNOPSIS
--------

**waitanyinvoice** \[*lastpay\_index*\]
**waitanyinvoice** \[*lastpay\_index*\] \[*timeout*\]

DESCRIPTION
-----------
Expand All @@ -22,12 +22,25 @@ invoice when it gets paid. The first valid *pay\_index* is 1; specifying
*lastpay\_index* of 0 equivalent to not specifying a *lastpay\_index*.
Negative *lastpay\_index* is invalid.

If *timeout* is specified, wait at most that number of seconds, which
must be an integer.
If the specified *timeout* is reached, this command will return with an
error.
You can specify this to 0 so that **waitanyinvoice** will return
immediately with an error if no pending invoice is available yet.
If unspecified, this command will wait indefinitely.

RETURN VALUE
------------

On success, an invoice description will be returned as per
lightning-listinvoice(7): *complete* will always be *true*.

Possible errors are:

* 904.
The *timeout* was reached without an invoice being paid.

AUTHOR
------

Expand Down
22 changes: 21 additions & 1 deletion lightningd/invoice.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <common/overflows.h>
#include <common/param.h>
#include <common/pseudorand.h>
#include <common/timeout.h>
#include <common/utils.h>
#include <errno.h>
#include <gossipd/gen_gossip_wire.h>
Expand Down Expand Up @@ -102,6 +103,12 @@ static void wait_on_invoice(const struct invoice *invoice, void *cmd)
else
tell_waiter_deleted((struct command *) cmd);
}
static void wait_timed_out(struct command *cmd)
{
was_pending(command_fail(cmd, INVOICE_WAIT_TIMED_OUT,
"Timed out while waiting "
"for invoice to be paid"));
}

/* We derive invoice secret using 1-way function from payment_preimage
* (just a different one from the payment_hash!) */
Expand Down Expand Up @@ -1129,13 +1136,25 @@ static struct command_result *json_waitanyinvoice(struct command *cmd,
const jsmntok_t *params)
{
u64 *pay_index;
u64 *timeout;
struct wallet *wallet = cmd->ld->wallet;

if (!param(cmd, buffer, params,
p_opt_def("lastpay_index", param_u64, &pay_index, 0),
p_opt("timeout", &param_u64, &timeout),
NULL))
return command_param_failed();

/*~ We allocate the timeout and the wallet-waitanyinvoice
* in the cmd context, so whichever one manages to complete
* the command first (and destroy the cmd context)
* auto-cancels the other, is not tal amazing?
*/
if (timeout)
(void) new_reltimer(cmd->ld->timers, cmd,
time_from_sec(*timeout),
&wait_timed_out, cmd);

/* Set command as pending. We do not know if
* wallet_invoice_waitany will return immediately
* or not, so indicating pending is safest. */
Expand All @@ -1155,7 +1174,8 @@ static const struct json_command waitanyinvoice_command = {
"waitanyinvoice",
"payment",
json_waitanyinvoice,
"Wait for the next invoice to be paid, after {lastpay_index} (if supplied)"
"Wait for the next invoice to be paid, after {lastpay_index} (if supplied). "
"If {timeout} seconds is reached while waiting, fail with an error."
};
AUTODATA(json_command, &waitanyinvoice_command);

Expand Down

0 comments on commit 67590fc

Please sign in to comment.