mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-20 15:44:21 +01:00
invoice: Modify waitanyinvoice interface to use pay_index.
This commit is contained in:
@@ -2,12 +2,12 @@
|
||||
.\" Title: lightning-waitanyinvoice
|
||||
.\" Author: [see the "AUTHOR" section]
|
||||
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
|
||||
.\" Date: 01/23/2017
|
||||
.\" Date: 12/26/2017
|
||||
.\" Manual: \ \&
|
||||
.\" Source: \ \&
|
||||
.\" Language: English
|
||||
.\"
|
||||
.TH "LIGHTNING\-WAITANYIN" "7" "01/23/2017" "\ \&" "\ \&"
|
||||
.TH "LIGHTNING\-WAITANYIN" "7" "12/26/2017" "\ \&" "\ \&"
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" * Define some portability stuff
|
||||
.\" -----------------------------------------------------------------
|
||||
@@ -31,15 +31,17 @@
|
||||
lightning-waitanyinvoice \- Protocol for waiting for payments\&.
|
||||
.SH "SYNOPSIS"
|
||||
.sp
|
||||
\fBwaitanyinvoice\fR [\fIlastlabel\fR]
|
||||
\fBwaitanyinvoice\fR [\fIlastpay_index\fR]
|
||||
.SH "DESCRIPTION"
|
||||
.sp
|
||||
The \fBwaitanyinvoice\fR RPC command waits until an invoice is paid, then returns a single entry as per \fBlistinvoice\fR\&. It will not return for any invoices paid prior to or including \fIlastlabel\fR\&.
|
||||
The \fBwaitanyinvoice\fR RPC command waits until an invoice is paid, then returns a single entry as per \fBlistinvoice\fR\&. It will not return for any invoices paid prior to or including the \fIlastpay_index\fR\&.
|
||||
.sp
|
||||
This is usually called iteratively: once with no arguments, then repeatedly with the returned \fIlabel\fR entry\&. This ensures that no paid invoice is missed\&.
|
||||
This is usually called iteratively: once with no arguments, then repeatedly with the returned \fIpay_index\fR entry\&. This ensures that no paid invoice is missed\&.
|
||||
.sp
|
||||
The \fIpay_index\fR is a monotonically\-increasing number assigned to an invoice when it gets paid\&. The first valid \fIpay_index\fR is 1; specifying \fIlastpay_index\fR of 0 equivalent to not specifying a \fIlastpay_index\fR\&. Negative \fIlastpay_index\fR is invalid\&.
|
||||
.SH "RETURN VALUE"
|
||||
.sp
|
||||
On success, the \fIrhash\fR, \fIlabel\fR, and \fImsatoshi\fR will be returned\&.
|
||||
On success, the \fIrhash\fR, \fIlabel\fR, \fIpay_index\fR, and \fImsatoshi\fR will be returned\&.
|
||||
.SH "AUTHOR"
|
||||
.sp
|
||||
Rusty Russell <rusty@rustcorp\&.com\&.au> is mainly responsible\&.
|
||||
|
||||
@@ -8,21 +8,27 @@ lightning-waitanyinvoice - Protocol for waiting for payments.
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
*waitanyinvoice* ['lastlabel']
|
||||
*waitanyinvoice* ['lastpay_index']
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
The *waitanyinvoice* RPC command waits until an invoice is paid, then
|
||||
returns a single entry as per *listinvoice*. It will not return for
|
||||
any invoices paid prior to or including 'lastlabel'.
|
||||
any invoices paid prior to or including the 'lastpay_index'.
|
||||
|
||||
This is usually called iteratively: once with no arguments, then
|
||||
repeatedly with the returned 'label' entry. This ensures that no paid
|
||||
repeatedly with the returned 'pay_index' entry. This ensures that no paid
|
||||
invoice is missed.
|
||||
|
||||
The 'pay_index' is a monotonically-increasing number assigned to an
|
||||
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.
|
||||
|
||||
|
||||
RETURN VALUE
|
||||
------------
|
||||
On success, the 'rhash', 'label', and 'msatoshi' will be returned.
|
||||
On success, the 'rhash', 'label', 'pay_index', and 'msatoshi' will be returned.
|
||||
|
||||
//FIXME:Enumerate errors
|
||||
|
||||
|
||||
@@ -83,6 +83,8 @@ static void tell_waiter(struct command *cmd, const struct invoice *paid)
|
||||
json_add_hex(response, "rhash", &paid->rhash, sizeof(paid->rhash));
|
||||
json_add_u64(response, "msatoshi", paid->msatoshi);
|
||||
json_add_bool(response, "complete", paid->state == PAID);
|
||||
if (paid->state == PAID)
|
||||
json_add_u64(response, "pay_index", paid->pay_index);
|
||||
json_object_end(response);
|
||||
command_success(cmd, response);
|
||||
}
|
||||
@@ -98,7 +100,11 @@ void resolve_invoice(struct lightningd *ld, struct invoice *invoice)
|
||||
|
||||
invoice->state = PAID;
|
||||
|
||||
/* Tell all the waitanyinvoice waiters about the new paid invoice */
|
||||
/* wallet_invoice_save updates pay_index member,
|
||||
* which tell_waiter needs. */
|
||||
wallet_invoice_save(ld->wallet, invoice);
|
||||
|
||||
/* Tell all the waiters about the new paid invoice */
|
||||
while ((w = list_pop(&invs->invoice_waiters,
|
||||
struct invoice_waiter,
|
||||
list)) != NULL)
|
||||
@@ -109,8 +115,6 @@ void resolve_invoice(struct lightningd *ld, struct invoice *invoice)
|
||||
list)) != NULL)
|
||||
tell_waiter(w->cmd, invoice);
|
||||
|
||||
wallet_invoice_save(ld->wallet, invoice);
|
||||
|
||||
/* Also mark the payment in the history table as complete */
|
||||
wallet_payment_set_status(ld->wallet, &invoice->rhash, PAYMENT_COMPLETE);
|
||||
}
|
||||
@@ -389,44 +393,43 @@ AUTODATA(json_command, &delinvoice_command);
|
||||
static void json_waitanyinvoice(struct command *cmd,
|
||||
const char *buffer, const jsmntok_t *params)
|
||||
{
|
||||
jsmntok_t *labeltok;
|
||||
const char *label = NULL;
|
||||
jsmntok_t *pay_indextok;
|
||||
u64 pay_index;
|
||||
struct invoice_waiter *w;
|
||||
struct invoices *invs = cmd->ld->invoices;
|
||||
int res;
|
||||
bool res;
|
||||
struct wallet *wallet = cmd->ld->wallet;
|
||||
char* outlabel;
|
||||
struct sha256 outrhash;
|
||||
u64 outmsatoshi;
|
||||
u64 outpay_index;
|
||||
struct json_result *response;
|
||||
|
||||
if (!json_get_params(buffer, params,
|
||||
"?label", &labeltok,
|
||||
"?lastpay_index", &pay_indextok,
|
||||
NULL)) {
|
||||
command_fail(cmd, "Invalid arguments");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!labeltok) {
|
||||
label = NULL;
|
||||
if (!pay_indextok) {
|
||||
pay_index = 0;
|
||||
} else {
|
||||
label = tal_strndup(cmd, buffer + labeltok->start,
|
||||
labeltok->end - labeltok->start);
|
||||
if (!json_tok_u64(buffer, pay_indextok, &pay_index)) {
|
||||
command_fail(cmd, "'%.*s' is not a valid number",
|
||||
pay_indextok->end - pay_indextok->start,
|
||||
buffer + pay_indextok->start);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find next paid invoice. */
|
||||
res = wallet_invoice_nextpaid(cmd, wallet, label,
|
||||
&outlabel, &outrhash, &outmsatoshi);
|
||||
label = tal_free(label);
|
||||
|
||||
/* If we failed to find label, error it. */
|
||||
if (res == -1) {
|
||||
command_fail(cmd, "Label not found");
|
||||
return;
|
||||
}
|
||||
res = wallet_invoice_nextpaid(cmd, wallet, pay_index,
|
||||
&outlabel, &outrhash,
|
||||
&outmsatoshi, &outpay_index);
|
||||
|
||||
/* If we found one, return it. */
|
||||
if (res == 1) {
|
||||
if (res) {
|
||||
response = new_json_result(cmd);
|
||||
|
||||
json_object_start(response, NULL);
|
||||
@@ -434,6 +437,7 @@ static void json_waitanyinvoice(struct command *cmd,
|
||||
json_add_hex(response, "rhash", &outrhash, sizeof(outrhash));
|
||||
json_add_u64(response, "msatoshi", outmsatoshi);
|
||||
json_add_bool(response, "complete", true);
|
||||
json_add_u64(response, "pay_index", outpay_index);
|
||||
json_object_end(response);
|
||||
|
||||
command_success(cmd, response);
|
||||
@@ -454,8 +458,8 @@ static void json_waitanyinvoice(struct command *cmd,
|
||||
static const struct json_command waitanyinvoice_command = {
|
||||
"waitanyinvoice",
|
||||
json_waitanyinvoice,
|
||||
"Wait for the next invoice to be paid, after {label} (if supplied)))",
|
||||
"Returns {label}, {rhash} and {msatoshi} on success. "
|
||||
"Wait for the next invoice to be paid, after {lastpay_index} (if supplied)))",
|
||||
"Returns {label}, {rhash}, {msatoshi}, and {pay_index} on success. "
|
||||
};
|
||||
AUTODATA(json_command, &waitanyinvoice_command);
|
||||
|
||||
|
||||
@@ -2435,20 +2435,22 @@ class LightningDTests(BaseLightningDTests):
|
||||
l1.rpc.pay(inv2['bolt11'])
|
||||
r = f.result(timeout=5)
|
||||
assert r['label'] == 'inv1'
|
||||
pay_index = r['pay_index']
|
||||
|
||||
# This one should return immediately with inv2
|
||||
r = self.executor.submit(l2.rpc.waitanyinvoice, 'inv1').result(timeout=5)
|
||||
r = self.executor.submit(l2.rpc.waitanyinvoice, pay_index).result(timeout=5)
|
||||
assert r['label'] == 'inv2'
|
||||
pay_index = r['pay_index']
|
||||
|
||||
# Now spawn the next waiter
|
||||
f = self.executor.submit(l2.rpc.waitanyinvoice, 'inv2')
|
||||
f = self.executor.submit(l2.rpc.waitanyinvoice, pay_index)
|
||||
time.sleep(1)
|
||||
assert not f.done()
|
||||
l1.rpc.pay(inv3['bolt11'])
|
||||
r = f.result(timeout=5)
|
||||
assert r['label'] == 'inv3'
|
||||
|
||||
self.assertRaises(ValueError, l2.rpc.waitanyinvoice, 'doesntexist')
|
||||
self.assertRaises(ValueError, l2.rpc.waitanyinvoice, 'non-number')
|
||||
|
||||
|
||||
def test_waitanyinvoice_reversed(self):
|
||||
@@ -2471,10 +2473,11 @@ class LightningDTests(BaseLightningDTests):
|
||||
# Wait - should not block, should return inv2
|
||||
r = self.executor.submit(l2.rpc.waitanyinvoice).result(timeout=5)
|
||||
assert r['label'] == 'inv2'
|
||||
pay_index = r['pay_index']
|
||||
# Pay inv1
|
||||
l1.rpc.pay(inv1['bolt11'])
|
||||
# Wait inv2 - should not block, should return inv1
|
||||
r = self.executor.submit(l2.rpc.waitanyinvoice, 'inv2').result(timeout=5)
|
||||
r = self.executor.submit(l2.rpc.waitanyinvoice, pay_index).result(timeout=5)
|
||||
assert r['label'] == 'inv1'
|
||||
|
||||
def test_channel_reenable(self):
|
||||
|
||||
@@ -1125,49 +1125,31 @@ bool wallet_htlcs_reconnect(struct wallet *wallet,
|
||||
return true;
|
||||
}
|
||||
|
||||
int wallet_invoice_nextpaid(const tal_t *cxt,
|
||||
bool wallet_invoice_nextpaid(const tal_t *cxt,
|
||||
const struct wallet *wallet,
|
||||
const char *labelz,
|
||||
u64 pay_index,
|
||||
char **outlabel,
|
||||
struct sha256 *outrhash,
|
||||
u64 *outmsatoshi)
|
||||
u64 *outmsatoshi,
|
||||
u64 *outpay_index)
|
||||
{
|
||||
sqlite3_stmt *stmt;
|
||||
int res;
|
||||
u64 pay_index;
|
||||
|
||||
/* Generate query. */
|
||||
if (labelz) {
|
||||
/* Find label. */
|
||||
stmt = db_prepare(wallet->db,
|
||||
"SELECT pay_index FROM invoices WHERE label=?;");
|
||||
sqlite3_bind_text(stmt, 1, labelz, strlen(labelz), SQLITE_TRANSIENT);
|
||||
res = sqlite3_step(stmt);
|
||||
if (res != SQLITE_ROW) {
|
||||
sqlite3_finalize(stmt);
|
||||
return -1;
|
||||
}
|
||||
pay_index = sqlite3_column_int64(stmt, 0);
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
stmt = db_prepare(wallet->db,
|
||||
"SELECT label, payment_hash, msatoshi FROM invoices"
|
||||
"SELECT label, payment_hash, msatoshi, pay_index"
|
||||
" FROM invoices"
|
||||
" WHERE pay_index NOT NULL"
|
||||
" AND pay_index > ?"
|
||||
" ORDER BY pay_index ASC LIMIT 1;");
|
||||
sqlite3_bind_int64(stmt, 1, pay_index);
|
||||
} else {
|
||||
stmt = db_prepare(wallet->db,
|
||||
"SELECT label, payment_hash, msatoshi FROM invoices"
|
||||
" WHERE pay_index NOT NULL"
|
||||
" ORDER BY pay_index ASC LIMIT 1;");
|
||||
}
|
||||
|
||||
res = sqlite3_step(stmt);
|
||||
if (res != SQLITE_ROW) {
|
||||
/* No paid invoice found. */
|
||||
sqlite3_finalize(stmt);
|
||||
return 0;
|
||||
return false;
|
||||
} else {
|
||||
/* Paid invoice found, return data. */
|
||||
*outlabel = tal_strndup(cxt, sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0));
|
||||
@@ -1177,11 +1159,11 @@ int wallet_invoice_nextpaid(const tal_t *cxt,
|
||||
|
||||
*outmsatoshi = sqlite3_column_int64(stmt, 2);
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
return 1;
|
||||
}
|
||||
*outpay_index = sqlite3_column_int64(stmt, 3);
|
||||
|
||||
return -1;
|
||||
sqlite3_finalize(stmt);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Acquire the next pay_index. */
|
||||
|
||||
@@ -333,28 +333,29 @@ bool wallet_htlcs_reconnect(struct wallet *wallet,
|
||||
/**
|
||||
* wallet_invoice_nextpaid -- Find a paid invoice.
|
||||
*
|
||||
* Get the details (label, rhash, msatoshi) of the next paid
|
||||
* invoice after the invoice with the given label. If label is
|
||||
* `NULL`, get the details of the first paid invoice. Return -1
|
||||
* if label is non-`NULL` and is not found, 0 if no more paid
|
||||
* invoices after specified invoice (or no paid invoices if label
|
||||
* is `NULL`), 1 if the next paid invoice was found.
|
||||
* Get the details (label, rhash, msatoshi, pay_index) of the first paid
|
||||
* invoice greater than the given pay_index. Return false if no paid
|
||||
* invoice found, return true if found. The first ever paid invoice will
|
||||
* have a pay_index of 1 or greater, so giving a pay_index of 0 will get
|
||||
* the first ever paid invoice if there is one.
|
||||
*
|
||||
* @ctx: Context to create the returned label.
|
||||
* @wallet: Wallet to query
|
||||
* @labelz: The label to be queried (zero-terminated), or
|
||||
* `NULL` if first invoice is to be queried.
|
||||
* @pay_index: The paid invoice returned will have pay_index greater
|
||||
* than this argument.
|
||||
* @outlabel: Pointer to label of found paid invoice. Caller
|
||||
* must free if this function returns 1.
|
||||
* must free if this function returns true.
|
||||
* @outrhash: Pointer to struct rhash to be filled.
|
||||
* @outmsatoshi: Pointer to number of millisatoshis value to pay.
|
||||
* @outpay_index: Pointer to pay_index of found paid invoice.
|
||||
*/
|
||||
int wallet_invoice_nextpaid(const tal_t *cxt,
|
||||
bool wallet_invoice_nextpaid(const tal_t *cxt,
|
||||
const struct wallet *wallet,
|
||||
const char *labelz,
|
||||
u64 pay_index,
|
||||
char **outlabel,
|
||||
struct sha256 *outrhash,
|
||||
u64 *outmsatoshi);
|
||||
u64 *outmsatoshi,
|
||||
u64 *outpay_index);
|
||||
|
||||
/**
|
||||
* wallet_invoice_save -- Save/update an invoice to the wallet
|
||||
|
||||
Reference in New Issue
Block a user