invoice: Refactor to make the invoice status explicit

So far we were tracking the status by including it either in the paid
or the unpaid list. This refactor makes the state explicit, which
matches the planned DB schema much better.

Signed-off-by: Christian Decker <decker.christian@gmail.com>
This commit is contained in:
Christian Decker 2017-10-03 18:31:07 +02:00 committed by Rusty Russell
parent c1493ae60c
commit 5a2242cde7
3 changed files with 54 additions and 52 deletions

View File

@ -14,19 +14,19 @@ struct invoice_waiter {
struct invoices {
/* Payments for r values we know about. */
struct list_head paid, unpaid;
u64 invoices_completed;
struct list_head invlist;
/* Waiting for new invoices to be paid. */
struct list_head invoice_waiters;
};
static struct invoice *find_inv(const struct list_head *list,
const struct sha256 *rhash)
const struct sha256 *rhash,
enum invoice_status state)
{
struct invoice *i;
list_for_each(list, i, list) {
if (structeq(rhash, &i->rhash))
if (structeq(rhash, &i->rhash) && i->state == state)
return i;
}
return NULL;
@ -34,13 +34,13 @@ static struct invoice *find_inv(const struct list_head *list,
struct invoice *find_unpaid(struct invoices *invs, const struct sha256 *rhash)
{
return find_inv(&invs->unpaid, rhash);
return find_inv(&invs->invlist, rhash, UNPAID);
}
static struct invoice *find_paid(struct invoices *invs,
const struct sha256 *rhash)
{
return find_inv(&invs->paid, rhash);
return find_inv(&invs->invlist, rhash, PAID);
}
static struct invoice *find_invoice_by_label(const struct list_head *list,
@ -59,31 +59,24 @@ void invoice_add(struct invoices *invs,
const struct preimage *r,
u64 msatoshi,
const char *label,
u64 paid_num)
enum invoice_status state)
{
struct invoice *invoice = tal(invs, struct invoice);
invoice->msatoshi = msatoshi;
invoice->r = *r;
invoice->paid_num = paid_num;
invoice->state = state;
invoice->label = tal_strdup(invoice, label);
sha256(&invoice->rhash, invoice->r.r, sizeof(invoice->r.r));
if (paid_num) {
list_add(&invs->paid, &invoice->list);
if (paid_num > invs->invoices_completed)
invs->invoices_completed = paid_num;
} else
list_add(&invs->unpaid, &invoice->list);
list_add(&invs->invlist, &invoice->list);
}
struct invoices *invoices_init(const tal_t *ctx)
{
struct invoices *invs = tal(ctx, struct invoices);
list_head_init(&invs->unpaid);
list_head_init(&invs->paid);
invs->invoices_completed = 0;
list_head_init(&invs->invlist);
list_head_init(&invs->invoice_waiters);
return invs;
@ -97,13 +90,14 @@ static void tell_waiter(struct command *cmd, const struct invoice *paid)
json_add_string(response, "label", paid->label);
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);
json_object_end(response);
command_success(cmd, response);
}
/* UNIFICATION FIXME */
void db_resolve_invoice(struct lightningd *ld,
const char *label, u64 paid_num);
const char *label);
bool db_new_invoice(struct lightningd *ld,
u64 msatoshi,
const char *label,
@ -115,9 +109,7 @@ void resolve_invoice(struct lightningd *ld, struct invoice *invoice)
struct invoice_waiter *w;
struct invoices *invs = ld->invoices;
invoice->paid_num = ++invs->invoices_completed;
list_del_from(&invs->unpaid, &invoice->list);
list_add_tail(&invs->paid, &invoice->list);
invoice->state = PAID;
/* Tell all the waiters about the new paid invoice */
while ((w = list_pop(&invs->invoice_waiters,
@ -125,7 +117,7 @@ void resolve_invoice(struct lightningd *ld, struct invoice *invoice)
list)) != NULL)
tell_waiter(w->cmd, invoice);
db_resolve_invoice(ld, invoice->label, invoice->paid_num);
db_resolve_invoice(ld, invoice->label);
}
static void json_invoice(struct command *cmd,
@ -146,6 +138,7 @@ static void json_invoice(struct command *cmd,
}
invoice = tal(cmd, struct invoice);
invoice->state = UNPAID;
if (r) {
if (!hex_decode(buffer + r->start, r->end - r->start,
invoice->r.r, sizeof(invoice->r.r))) {
@ -175,8 +168,7 @@ static void json_invoice(struct command *cmd,
invoice->label = tal_strndup(invoice, buffer + label->start,
label->end - label->start);
if (find_invoice_by_label(&invs->paid, invoice->label)
|| find_invoice_by_label(&invs->unpaid, invoice->label)) {
if (find_invoice_by_label(&invs->invlist, invoice->label)) {
command_fail(cmd, "Duplicate label '%s'", invoice->label);
return;
}
@ -185,7 +177,6 @@ static void json_invoice(struct command *cmd,
INVOICE_MAX_LABEL_LEN);
return;
}
invoice->paid_num = 0;
if (!db_new_invoice(cmd->ld, invoice->msatoshi, invoice->label,
&invoice->r)) {
@ -194,7 +185,7 @@ static void json_invoice(struct command *cmd,
}
/* OK, connect it to main state, respond with hash */
tal_steal(invs, invoice);
list_add(&invs->unpaid, &invoice->list);
list_add(&invs->invlist, &invoice->list);
json_object_start(response, NULL);
json_add_hex(response, "rhash",
@ -228,7 +219,7 @@ static void json_add_invoices(struct json_result *response,
json_add_string(response, "label", i->label);
json_add_hex(response, "rhash", &i->rhash, sizeof(i->rhash));
json_add_u64(response, "msatoshi", i->msatoshi);
json_add_bool(response, "complete", i->paid_num != 0);
json_add_bool(response, "complete", i->state == PAID);
json_object_end(response);
}
}
@ -249,8 +240,7 @@ static void json_listinvoice(struct command *cmd,
json_array_start(response, NULL);
json_add_invoices(response, &invs->paid, buffer, label);
json_add_invoices(response, &invs->unpaid, buffer, label);
json_add_invoices(response, &invs->invlist, buffer, label);
json_array_end(response);
command_success(cmd, response);
}
@ -281,7 +271,7 @@ static void json_delinvoice(struct command *cmd,
label = tal_strndup(cmd, buffer + labeltok->start,
labeltok->end - labeltok->start);
i = find_invoice_by_label(&invs->unpaid, label);
i = find_invoice_by_label(&invs->invlist, label);
if (!i) {
command_fail(cmd, "Unknown invoice");
return;
@ -290,7 +280,7 @@ static void json_delinvoice(struct command *cmd,
command_fail(cmd, "Database error");
return;
}
list_del_from(&invs->unpaid, &i->list);
list_del_from(&invs->invlist, &i->list);
json_object_start(response, NULL);
json_add_string(response, "label", i->label);
@ -325,17 +315,24 @@ static void json_waitanyinvoice(struct command *cmd,
return;
}
if (!labeltok)
i = list_top(&invs->paid, struct invoice, list);
else {
if (!labeltok) {
i = list_top(&invs->invlist, struct invoice, list);
/* Advance until we find a PAID one */
while (i && i->state == UNPAID) {
i = list_next(&invs->invlist, i, list);
}
} else {
label = tal_strndup(cmd, buffer + labeltok->start,
labeltok->end - labeltok->start);
i = find_invoice_by_label(&invs->paid, label);
i = find_invoice_by_label(&invs->invlist, label);
if (!i) {
command_fail(cmd, "Label not found");
return;
}
i = list_next(&invs->paid, i, list);
while (i && i->state == UNPAID) {
i = list_next(&invs->invlist, i, list);
}
}
/* If we found one, return it. */
@ -381,23 +378,20 @@ static void json_waitinvoice(struct command *cmd,
/* Search in paid invoices, if found return immediately */
label = tal_strndup(cmd, buffer + labeltok->start, labeltok->end - labeltok->start);
i = find_invoice_by_label(&invs->paid, label);
if (i) {
tell_waiter(cmd, i);
return;
}
i = find_invoice_by_label(&invs->invlist, label);
/* No luck in paid ones? Now try the unpaid ones. */
i = find_invoice_by_label(&invs->unpaid, label);
if (!i) {
command_fail(cmd, "Label not found");
return;
} else if (i->state == PAID) {
tell_waiter(cmd, i);
return;
} else {
/* There is an unpaid one matching, let's wait... */
w = tal(cmd, struct invoice_waiter);
w->cmd = cmd;
list_add_tail(&invs->invoice_waiters, &w->list);
}
/* There is an unpaid one matching, let's wait... */
w = tal(cmd, struct invoice_waiter);
w->cmd = cmd;
list_add_tail(&invs->invoice_waiters, &w->list);
}
static const struct json_command waitinvoice_command = {

View File

@ -9,13 +9,21 @@
struct invoices;
struct lightningd;
/* /!\ This is a DB ENUM, please do not change the numbering of any
* already defined elements (adding is ok) /!\ */
enum invoice_status {
UNPAID,
PAID,
};
struct invoice {
u64 id;
enum invoice_status state;
struct list_node list;
const char *label;
u64 msatoshi;
struct preimage r;
struct sha256 rhash;
u64 paid_num;
};
#define INVOICE_MAX_LABEL_LEN 128
@ -25,7 +33,7 @@ void invoice_add(struct invoices *i,
const struct preimage *r,
u64 msatoshi,
const char *label,
u64 complete);
enum invoice_status state);
void resolve_invoice(struct lightningd *ld, struct invoice *invoice);

View File

@ -48,9 +48,9 @@ void notify_new_block(struct chain_topology *topo, u32 height)
}
void db_resolve_invoice(struct lightningd *ld,
const char *label, u64 paid_num);
const char *label);
void db_resolve_invoice(struct lightningd *ld,
const char *label, u64 paid_num)
const char *label)
{
/* FIXME */
}