Browse Source

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>
ppa-0.6.1
Christian Decker 7 years ago
committed by Rusty Russell
parent
commit
5a2242cde7
  1. 90
      lightningd/invoice.c
  2. 12
      lightningd/invoice.h
  3. 4
      lightningd/lightningd.c

90
lightningd/invoice.c

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

12
lightningd/invoice.h

@ -9,13 +9,21 @@
struct invoices; struct invoices;
struct lightningd; 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 { struct invoice {
u64 id;
enum invoice_status state;
struct list_node list; struct list_node list;
const char *label; const char *label;
u64 msatoshi; u64 msatoshi;
struct preimage r; struct preimage r;
struct sha256 rhash; struct sha256 rhash;
u64 paid_num;
}; };
#define INVOICE_MAX_LABEL_LEN 128 #define INVOICE_MAX_LABEL_LEN 128
@ -25,7 +33,7 @@ void invoice_add(struct invoices *i,
const struct preimage *r, const struct preimage *r,
u64 msatoshi, u64 msatoshi,
const char *label, const char *label,
u64 complete); enum invoice_status state);
void resolve_invoice(struct lightningd *ld, struct invoice *invoice); void resolve_invoice(struct lightningd *ld, struct invoice *invoice);

4
lightningd/lightningd.c

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

Loading…
Cancel
Save