diff --git a/lightningd/invoice.c b/lightningd/invoice.c index bdf229e1c..d043a82f8 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -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 = { diff --git a/lightningd/invoice.h b/lightningd/invoice.h index 989dd1ff0..732095c85 100644 --- a/lightningd/invoice.h +++ b/lightningd/invoice.h @@ -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); diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index eb2e46f9a..baab26a33 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -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 */ }