From 978e5c67d807f102ae316bb8ef753a4321ccb5f2 Mon Sep 17 00:00:00 2001 From: ZmnSCPxj Date: Fri, 23 Feb 2018 01:04:47 +0000 Subject: [PATCH] invoices: Remove persistent in-memory invoice structures. --- lightningd/invoice.c | 36 ++--- lightningd/peer_htlcs.c | 5 +- wallet/invoices.c | 302 +++++++++++++++++---------------------- wallet/invoices.h | 39 +++-- wallet/test/run-wallet.c | 27 ++-- wallet/wallet.c | 33 +++-- wallet/wallet.h | 53 +++---- 7 files changed, 240 insertions(+), 255 deletions(-) diff --git a/lightningd/invoice.c b/lightningd/invoice.c index 1e8f9e9b1..e516802e7 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -62,7 +62,7 @@ static void tell_waiter(struct command *cmd, const struct invoice *inv) struct json_result *response = new_json_result(cmd); struct invoice_details details; - wallet_invoice_details(cmd, cmd->ld->wallet, inv, &details); + wallet_invoice_details(cmd, cmd->ld->wallet, *inv, &details); json_add_invoice(response, &details, true); if (details.state == PAID) command_success(cmd, response); @@ -104,7 +104,7 @@ static bool hsm_sign_b11(const u5 *u5bytes, static void json_invoice(struct command *cmd, const char *buffer, const jsmntok_t *params) { - const struct invoice *invoice; + struct invoice invoice; struct invoice_details details; jsmntok_t *msatoshi, *label, *desc, *exp, *fallback; u64 *msatoshi_val; @@ -117,6 +117,7 @@ static void json_invoice(struct command *cmd, char *b11enc; const u8 *fallback_script; u64 expiry = 3600; + bool result; if (!json_get_params(cmd, buffer, params, "msatoshi", &msatoshi, @@ -146,7 +147,7 @@ static void json_invoice(struct command *cmd, /* label */ label_val = tal_strndup(cmd, buffer + label->start, label->end - label->start); - if (wallet_invoice_find_by_label(wallet, label_val)) { + if (wallet_invoice_find_by_label(wallet, &invoice, label_val)) { command_fail(cmd, "Duplicate label '%s'", label_val); return; } @@ -193,11 +194,12 @@ static void json_invoice(struct command *cmd, } - invoice = wallet_invoice_create(cmd->ld->wallet, - take(msatoshi_val), - take(label_val), - expiry); - if (!invoice) { + result = wallet_invoice_create(cmd->ld->wallet, + &invoice, + take(msatoshi_val), + take(label_val), + expiry); + if (!result) { command_fail(cmd, "Failed to create invoice on database"); return; } @@ -318,7 +320,7 @@ AUTODATA(json_command, &listinvoices_command); static void json_delinvoice(struct command *cmd, const char *buffer, const jsmntok_t *params) { - const struct invoice *i; + struct invoice i; struct invoice_details details; jsmntok_t *labeltok, *statustok; struct json_result *response = new_json_result(cmd); @@ -334,8 +336,7 @@ static void json_delinvoice(struct command *cmd, label = tal_strndup(cmd, buffer + labeltok->start, labeltok->end - labeltok->start); - i = wallet_invoice_find_by_label(wallet, label); - if (!i) { + if (!wallet_invoice_find_by_label(wallet, &i, label)) { command_fail(cmd, "Unknown invoice"); return; } @@ -359,7 +360,7 @@ static void json_delinvoice(struct command *cmd, if (!wallet_invoice_delete(wallet, i)) { log_broken(cmd->ld->log, "Error attempting to remove invoice %"PRIu64, - i->id); + i.id); command_fail(cmd, "Database error"); return; } @@ -424,7 +425,7 @@ AUTODATA(json_command, &waitanyinvoice_command); static void json_waitinvoice(struct command *cmd, const char *buffer, const jsmntok_t *params) { - const struct invoice *i; + struct invoice i; struct invoice_details details; struct wallet *wallet = cmd->ld->wallet; jsmntok_t *labeltok; @@ -434,18 +435,17 @@ static void json_waitinvoice(struct command *cmd, return; } - /* Search in paid invoices, if found return immediately */ + /* Search for invoice */ label = tal_strndup(cmd, buffer + labeltok->start, labeltok->end - labeltok->start); - i = wallet_invoice_find_by_label(wallet, label); - - if (!i) { + if (!wallet_invoice_find_by_label(wallet, &i, label)) { command_fail(cmd, "Label not found"); return; } wallet_invoice_details(cmd, cmd->ld->wallet, i, &details); + /* If paid or expired return immediately */ if (details.state == PAID || details.state == EXPIRED) { - tell_waiter(cmd, i); + tell_waiter(cmd, &i); return; } else { /* There is an unpaid one matching, let's wait... */ diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index a617421d4..1592f98e5 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -229,7 +229,7 @@ static void handle_localpay(struct htlc_in *hin, u32 outgoing_cltv_value) { enum onion_type failcode; - const struct invoice *invoice; + struct invoice invoice; struct invoice_details details; struct lightningd *ld = hin->key.channel->peer->ld; const tal_t *tmpctx = tal_tmpctx(ld); @@ -262,8 +262,7 @@ static void handle_localpay(struct htlc_in *hin, goto fail; } - invoice = wallet_invoice_find_unpaid(ld->wallet, payment_hash); - if (!invoice) { + if (!wallet_invoice_find_unpaid(ld->wallet, &invoice, payment_hash)) { failcode = WIRE_UNKNOWN_PAYMENT_HASH; goto fail; } diff --git a/wallet/invoices.c b/wallet/invoices.c index 39058f30e..c0fa5427a 100644 --- a/wallet/invoices.c +++ b/wallet/invoices.c @@ -37,8 +37,6 @@ struct invoices { struct log *log; /* The timers object to use for expirations. */ struct timers *timers; - /* The invoice list. */ - struct list_head invlist; /* Waiters waiting for invoices to be paid, expired, or deleted. */ struct list_head waiters; /* Earliest time for some invoice to expire */ @@ -92,37 +90,36 @@ trigger_invoice_waiter_expire_or_delete(struct invoices *invoices, tal_free(tmpctx); } -static bool wallet_stmt2invoice_details(sqlite3_stmt *stmt, - struct invoice *invoice, +static void wallet_stmt2invoice_details(const tal_t *ctx, + sqlite3_stmt *stmt, struct invoice_details *dtl) { - invoice->id = sqlite3_column_int64(stmt, 0); - dtl->state = sqlite3_column_int(stmt, 1); + dtl->state = sqlite3_column_int(stmt, 0); - assert(sqlite3_column_bytes(stmt, 2) == sizeof(struct preimage)); - memcpy(&dtl->r, sqlite3_column_blob(stmt, 2), sqlite3_column_bytes(stmt, 2)); + assert(sqlite3_column_bytes(stmt, 1) == sizeof(struct preimage)); + memcpy(&dtl->r, sqlite3_column_blob(stmt, 1), sqlite3_column_bytes(stmt, 1)); - assert(sqlite3_column_bytes(stmt, 3) == sizeof(struct sha256)); - memcpy(&dtl->rhash, sqlite3_column_blob(stmt, 3), sqlite3_column_bytes(stmt, 3)); + assert(sqlite3_column_bytes(stmt, 2) == sizeof(struct sha256)); + memcpy(&dtl->rhash, sqlite3_column_blob(stmt, 2), sqlite3_column_bytes(stmt, 2)); - dtl->label = tal_strndup(dtl, sqlite3_column_blob(stmt, 4), sqlite3_column_bytes(stmt, 4)); + dtl->label = tal_strndup(ctx, sqlite3_column_blob(stmt, 3), sqlite3_column_bytes(stmt, 3)); - if (sqlite3_column_type(stmt, 5) != SQLITE_NULL) { - dtl->msatoshi = tal(dtl, u64); - *dtl->msatoshi = sqlite3_column_int64(stmt, 5); + if (sqlite3_column_type(stmt, 4) != SQLITE_NULL) { + dtl->msatoshi = tal(ctx, u64); + *dtl->msatoshi = sqlite3_column_int64(stmt, 4); } else { dtl->msatoshi = NULL; } - dtl->expiry_time = sqlite3_column_int64(stmt, 6); + dtl->expiry_time = sqlite3_column_int64(stmt, 5); if (dtl->state == PAID) { - dtl->pay_index = sqlite3_column_int64(stmt, 7); - dtl->msatoshi_received = sqlite3_column_int64(stmt, 8); - dtl->paid_timestamp = sqlite3_column_int64(stmt, 9); + dtl->pay_index = sqlite3_column_int64(stmt, 6); + dtl->msatoshi_received = sqlite3_column_int64(stmt, 7); + dtl->paid_timestamp = sqlite3_column_int64(stmt, 8); } - return true; + return; } struct invoices *invoices_new(const tal_t *ctx, @@ -136,7 +133,6 @@ struct invoices *invoices_new(const tal_t *ctx, invs->log = log; invs->timers = timers; - list_head_init(&invs->invlist); list_head_init(&invs->waiters); invs->expiration_timer = NULL; @@ -159,19 +155,6 @@ static void update_db_expirations(struct invoices *invoices, u64 now) db_exec_prepared(invoices->db, stmt); } -static struct invoice *invoices_find_by_id(struct invoices *invoices, - u64 id) -{ - struct invoice *i; - - /* FIXME: Use something better than a linear scan. */ - list_for_each(&invoices->invlist, i, list) { - if (i->id == id) - return i; - } - return NULL; -} - struct invoice_id_node { struct list_node list; u64 id; @@ -185,7 +168,7 @@ static void trigger_expiration(struct invoices *invoices) struct invoice_id_node *idn; u64 now = time_now().ts.tv_sec; sqlite3_stmt *stmt; - struct invoice *i; + struct invoice i; /* Free current expiration timer */ invoices->expiration_timer = tal_free(invoices->expiration_timer); @@ -211,13 +194,11 @@ static void trigger_expiration(struct invoices *invoices) /* Trigger expirations */ list_for_each(&idlist, idn, list) { - /* Update in-memory structure */ - i = invoices_find_by_id(invoices, idn->id); - i->details->state = EXPIRED; /* Trigger expiration */ + i.id = idn->id; trigger_invoice_waiter_expire_or_delete(invoices, idn->id, - i); + &i); } install_expiration_timer(invoices); @@ -271,63 +252,34 @@ static void install_expiration_timer(struct invoices *invoices) bool invoices_load(struct invoices *invoices) { - int count = 0; u64 now = time_now().ts.tv_sec; - struct invoice *i; - sqlite3_stmt *stmt; update_db_expirations(invoices, now); - /* Load invoices from db. */ - stmt = db_query(__func__, invoices->db, - "SELECT id, state, payment_key, payment_hash" - " , label, msatoshi, expiry_time, pay_index" - " , msatoshi_received, paid_timestamp" - " FROM invoices;"); - if (!stmt) { - log_broken(invoices->log, "Could not load invoices"); - return false; - } - - while (sqlite3_step(stmt) == SQLITE_ROW) { - i = tal(invoices, struct invoice); - i->owner = invoices; - i->details = tal(i, struct invoice_details); - if (!wallet_stmt2invoice_details(stmt, i, i->details)) { - log_broken(invoices->log, "Error deserializing invoice"); - sqlite3_finalize(stmt); - return false; - } - list_add_tail(&invoices->invlist, &i->list); - count++; - } - log_debug(invoices->log, "Loaded %d invoices from DB", count); - - sqlite3_finalize(stmt); - install_expiration_timer(invoices); return true; } -const struct invoice *invoices_create(struct invoices *invoices, - u64 *msatoshi TAKES, - const char *label TAKES, - u64 expiry) +bool invoices_create(struct invoices *invoices, + struct invoice *pinvoice, + u64 *msatoshi TAKES, + const char *label TAKES, + u64 expiry) { sqlite3_stmt *stmt; - struct invoice *invoice; + struct invoice dummy; struct preimage r; struct sha256 rhash; u64 expiry_time; u64 now = time_now().ts.tv_sec; - if (invoices_find_by_label(invoices, label)) { + if (invoices_find_by_label(invoices, &dummy, label)) { if (taken(msatoshi)) tal_free(msatoshi); if (taken(label)) tal_free(label); - return NULL; + return false; } /* Compute expiration. */ @@ -363,21 +315,7 @@ const struct invoice *invoices_create(struct invoices *invoices, db_exec_prepared(invoices->db, stmt); - /* Create and load in-memory structure. */ - invoice = tal(invoices, struct invoice); - invoice->owner = invoices; - - invoice->id = sqlite3_last_insert_rowid(invoices->db->sql); - invoice->details = tal(invoice, struct invoice_details); - invoice->details->state = UNPAID; - invoice->details->label = tal_strdup(invoice->details, label); - invoice->details->msatoshi = tal_dup(invoice->details, u64, msatoshi); /* Works even if msatoshi == NULL. */ - memcpy(&invoice->details->r, &r, sizeof(invoice->details->r)); - memcpy(&invoice->details->rhash, &rhash, sizeof(invoice->details->rhash)); - invoice->details->expiry_time = expiry_time; - - /* Add to invoices object. */ - list_add_tail(&invoices->invlist, &invoice->list); + pinvoice->id = sqlite3_last_insert_rowid(invoices->db->sql); /* Install expiration trigger. */ if (!invoices->expiration_timer || @@ -387,80 +325,109 @@ const struct invoice *invoices_create(struct invoices *invoices, install_expiration_timer(invoices); } - return invoice; + if (taken(msatoshi)) + tal_free(msatoshi); + if (taken(label)) + tal_free(label); + return true; } -const struct invoice *invoices_find_by_label(struct invoices *invoices, - const char *label) +bool invoices_find_by_label(struct invoices *invoices, + struct invoice *pinvoice, + const char *label) { - struct invoice *i; + sqlite3_stmt *stmt; - /* FIXME: Use something better than a linear scan. */ - list_for_each(&invoices->invlist, i, list) { - if (streq(i->details->label, label)) - return i; + stmt = db_prepare(invoices->db, + "SELECT id" + " FROM invoices" + " WHERE label = ?;"); + sqlite3_bind_text(stmt, 1, label, strlen(label), SQLITE_TRANSIENT); + if (sqlite3_step(stmt) == SQLITE_ROW) { + pinvoice->id = sqlite3_column_int64(stmt, 0); + sqlite3_finalize(stmt); + return true; + } else { + sqlite3_finalize(stmt); + return false; } - return NULL; } -const struct invoice *invoices_find_unpaid(struct invoices *invoices, - const struct sha256 *rhash) +bool invoices_find_unpaid(struct invoices *invoices, + struct invoice *pinvoice, + const struct sha256 *rhash) { - struct invoice *i; + sqlite3_stmt *stmt; - list_for_each(&invoices->invlist, i, list) { - if (structeq(rhash, &i->details->rhash) && - i->details->state == UNPAID) { - if (time_now().ts.tv_sec > i->details->expiry_time) - break; - return i; - } + stmt = db_prepare(invoices->db, + "SELECT id" + " FROM invoices" + " WHERE payment_hash = ?" + " AND state = ?;"); + sqlite3_bind_blob(stmt, 1, rhash, sizeof(*rhash), SQLITE_TRANSIENT); + sqlite3_bind_int(stmt, 2, UNPAID); + if (sqlite3_step(stmt) == SQLITE_ROW) { + pinvoice->id = sqlite3_column_int64(stmt, 0); + sqlite3_finalize(stmt); + return true; + } else { + sqlite3_finalize(stmt); + return false; } - return NULL; } bool invoices_delete(struct invoices *invoices, - const struct invoice *cinvoice) + struct invoice invoice) { sqlite3_stmt *stmt; - struct invoice *invoice = (struct invoice *) cinvoice; /* Delete from database. */ stmt = db_prepare(invoices->db, "DELETE FROM invoices WHERE id=?;"); - sqlite3_bind_int64(stmt, 1, invoice->id); + sqlite3_bind_int64(stmt, 1, invoice.id); db_exec_prepared(invoices->db, stmt); if (sqlite3_changes(invoices->db->sql) != 1) return false; - /* Delete from invoices object. */ - list_del_from(&invoices->invlist, &invoice->list); - /* Tell all the waiters about the fact that it was deleted. */ trigger_invoice_waiter_expire_or_delete(invoices, - invoice->id, NULL); - - /* Free all watchers and the invoice. */ - tal_free(invoice); + invoice.id, NULL); return true; } bool invoices_iterate(struct invoices *invoices, struct invoice_iterator *it) { - if (it->curr) - it->curr = list_next(&invoices->invlist, it->curr, list); - else - it->curr = list_top(&invoices->invlist, struct invoice, list); - return it->curr != NULL; + sqlite3_stmt *stmt; + int res; + if (!it->p) { + stmt = db_prepare(invoices->db, + "SELECT state, payment_key, payment_hash" + " , label, msatoshi, expiry_time, pay_index" + " , msatoshi_received, paid_timestamp" + " FROM invoices;"); + it->p = stmt; + } else + stmt = it->p; + + res = sqlite3_step(stmt); + if (res == SQLITE_DONE) { + sqlite3_finalize(stmt); + it->p = NULL; + return false; + } else { + assert(res == SQLITE_ROW); + return true; + } } void invoices_iterator_deref(const tal_t *ctx, struct invoices *invoices, const struct invoice_iterator *it, struct invoice_details *details) { - invoices_get_details(ctx, invoices, it->curr, details); + assert(it->p); + wallet_stmt2invoice_details(ctx, (sqlite3_stmt*) it->p, details); } static s64 get_next_pay_index(struct db *db) @@ -476,11 +443,10 @@ static s64 get_next_pay_index(struct db *db) void invoices_resolve(struct invoices *invoices, - const struct invoice *cinvoice, + struct invoice invoice, u64 msatoshi_received) { sqlite3_stmt *stmt; - struct invoice *invoice = (struct invoice *)cinvoice; s64 pay_index; u64 paid_timestamp; const tal_t *tmpctx = tal_tmpctx(NULL); @@ -501,17 +467,11 @@ void invoices_resolve(struct invoices *invoices, sqlite3_bind_int64(stmt, 2, pay_index); sqlite3_bind_int64(stmt, 3, msatoshi_received); sqlite3_bind_int64(stmt, 4, paid_timestamp); - sqlite3_bind_int64(stmt, 5, invoice->id); + sqlite3_bind_int64(stmt, 5, invoice.id); db_exec_prepared(invoices->db, stmt); - /* Update in-memory structure. */ - invoice->details->state = PAID; - invoice->details->pay_index = pay_index; - invoice->details->msatoshi_received = msatoshi_received; - invoice->details->paid_timestamp = paid_timestamp; - /* Tell all the waiters about the paid invoice. */ - trigger_invoice_waiter_resolve(invoices, invoice->id, invoice); + trigger_invoice_waiter_resolve(invoices, invoice.id, &invoice); /* Free all watchers. */ tal_free(tmpctx); @@ -552,13 +512,12 @@ void invoices_waitany(const tal_t *ctx, void *cbarg) { sqlite3_stmt *stmt; - const struct invoice *invoice; + struct invoice invoice; int res; - char const* label; /* Look for an already-paid invoice. */ stmt = db_prepare(invoices->db, - "SELECT label" + "SELECT id" " FROM invoices" " WHERE pay_index NOT NULL" " AND pay_index > ?" @@ -567,16 +526,10 @@ void invoices_waitany(const tal_t *ctx, res = sqlite3_step(stmt); if (res == SQLITE_ROW) { - /* Invoice found. Look up the invoice object. */ - label = tal_strndup(ctx, sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0)); + invoice.id = sqlite3_column_int64(stmt, 0); sqlite3_finalize(stmt); - /* The invoice should definitely exist in-memory. */ - invoice = invoices_find_by_label(invoices, label); - assert(invoice); - tal_free(label); - - cb(invoice, cbarg); + cb(&invoice, cbarg); return; } @@ -590,38 +543,53 @@ void invoices_waitany(const tal_t *ctx, void invoices_waitone(const tal_t *ctx, struct invoices *invoices UNUSED, - struct invoice const *cinvoice, + struct invoice invoice, void (*cb)(const struct invoice *, void*), void *cbarg) { - struct invoice *invoice = (struct invoice*) cinvoice; - if (invoice->details->state == PAID || invoice->details->state == EXPIRED) { - cb(invoice, cbarg); + sqlite3_stmt *stmt; + int res; + enum invoice_status state; + + stmt = db_prepare(invoices->db, + "SELECT state" + " FROM invoices" + " WHERE id = ?;"); + sqlite3_bind_int64(stmt, 1, invoice.id); + res = sqlite3_step(stmt); + assert(res == SQLITE_ROW); + state = sqlite3_column_int(stmt, 0); + sqlite3_finalize(stmt); + + if (state == PAID || state == EXPIRED) { + cb(&invoice, cbarg); return; } /* Not yet paid. */ add_invoice_waiter(ctx, &invoices->waiters, - false, invoice->id, cb, cbarg); + false, invoice.id, cb, cbarg); } void invoices_get_details(const tal_t *ctx, struct invoices *invoices, - const struct invoice *invoice, + struct invoice invoice, struct invoice_details *dtl) { - dtl->state = invoice->details->state; - dtl->r = invoice->details->r; - dtl->rhash = invoice->details->rhash; - dtl->label = tal_strdup(ctx, invoice->details->label); - dtl->msatoshi = - invoice->details->msatoshi ? - tal_dup(ctx, u64, invoice->details->msatoshi) : - /*otherwise*/ NULL ; - dtl->expiry_time = invoice->details->expiry_time; - if (dtl->state == PAID) { - dtl->pay_index = invoice->details->pay_index; - dtl->msatoshi_received = invoice->details->msatoshi_received; - dtl->paid_timestamp = invoice->details->paid_timestamp; - } + sqlite3_stmt *stmt; + int result; + + stmt = db_prepare(invoices->db, + "SELECT state, payment_key, payment_hash" + " , label, msatoshi, expiry_time, pay_index" + " , msatoshi_received, paid_timestamp" + " FROM invoices" + " WHERE id = ?;"); + sqlite3_bind_int64(stmt, 1, invoice.id); + result = sqlite3_step(stmt); + assert(result == SQLITE_ROW); + + wallet_stmt2invoice_details(ctx, stmt, dtl); + + sqlite3_finalize(stmt); } diff --git a/wallet/invoices.h b/wallet/invoices.h index 83ebcc7c4..fce9d0fe8 100644 --- a/wallet/invoices.h +++ b/wallet/invoices.h @@ -39,6 +39,7 @@ bool invoices_load(struct invoices *invoices); * invoices_create - Create a new invoice. * * @invoices - the invoice handler. + * @pinvoice - pointer to location to load new invoice in. * @msatoshi - the amount the invoice should have, or * NULL for any-amount invoices. * @label - the unique label for this invoice. Must be @@ -46,36 +47,44 @@ bool invoices_load(struct invoices *invoices); * @expiry - the number of seconds before the invoice * expires * - * Returns NULL if label already exists or expiry is 0. + * Returns false if label already exists or expiry is 0. + * Returns true if created invoice. * FIXME: Fallback addresses */ -const struct invoice *invoices_create(struct invoices *invoices, - u64 *msatoshi TAKES, - const char *label TAKES, - u64 expiry); +bool invoices_create(struct invoices *invoices, + struct invoice *pinvoice, + u64 *msatoshi TAKES, + const char *label TAKES, + u64 expiry); /** * invoices_find_by_label - Search for an invoice by label * * @invoices - the invoice handler. + * @pinvoice - pointer to location to load found invoice in. * @label - the label to search for. Must be null-terminated. * - * Returns NULL if no invoice with that label exists. + * Returns false if no invoice with that label exists. + * Returns true if found. */ -const struct invoice *invoices_find_by_label(struct invoices *invoices, - const char *label); +bool invoices_find_by_label(struct invoices *invoices, + struct invoice *pinvoice, + const char *label); /** * invoices_find_unpaid - Search for an unpaid, unexpired invoice by * payment_hash * * @invoices - the invoice handler. + * @pinvoice - pointer to location to load found invoice in. * @rhash - the payment_hash to search for. * - * Returns NULL if no invoice with that payment hash exists. + * Returns false if no unpaid invoice with that rhash exists. + * Returns true if found. */ -const struct invoice *invoices_find_unpaid(struct invoices *invoices, - const struct sha256 *rhash); +bool invoices_find_unpaid(struct invoices *invoices, + struct invoice *pinvoice, + const struct sha256 *rhash); /** * invoices_delete - Delete an invoice @@ -86,7 +95,7 @@ const struct invoice *invoices_find_unpaid(struct invoices *invoices, * Return false on failure. */ bool invoices_delete(struct invoices *invoices, - const struct invoice *invoice); + struct invoice invoice); /** * invoices_iterate - Iterate over all existing invoices @@ -132,7 +141,7 @@ void invoices_iterator_deref(const tal_t *ctx, * does not check). */ void invoices_resolve(struct invoices *invoices, - const struct invoice *invoice, + struct invoice invoice, u64 msatoshi_received); /** @@ -173,7 +182,7 @@ void invoices_waitany(const tal_t *ctx, */ void invoices_waitone(const tal_t *ctx, struct invoices *invoices, - struct invoice const *invoice, + struct invoice invoice, void (*cb)(const struct invoice *, void*), void *cbarg); @@ -187,7 +196,7 @@ void invoices_waitone(const tal_t *ctx, */ void invoices_get_details(const tal_t *ctx, struct invoices *invoices, - const struct invoice *invoice, + struct invoice invoice, struct invoice_details *details); #endif /* LIGHTNING_WALLET_INVOICES_H */ diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 48ad1a10a..d1cc1d65a 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -95,27 +95,30 @@ u8 *get_supported_global_features(const tal_t *ctx UNNEEDED) u8 *get_supported_local_features(const tal_t *ctx UNNEEDED) { fprintf(stderr, "get_supported_local_features called!\n"); abort(); } /* Generated stub for invoices_create */ -const struct invoice *invoices_create(struct invoices *invoices UNNEEDED, - u64 *msatoshi TAKES UNNEEDED, - const char *label TAKES UNNEEDED, - u64 expiry UNNEEDED) +bool invoices_create(struct invoices *invoices UNNEEDED, + struct invoice *pinvoice UNNEEDED, + u64 *msatoshi TAKES UNNEEDED, + const char *label TAKES UNNEEDED, + u64 expiry UNNEEDED) { fprintf(stderr, "invoices_create called!\n"); abort(); } /* Generated stub for invoices_delete */ bool invoices_delete(struct invoices *invoices UNNEEDED, - const struct invoice *invoice UNNEEDED) + struct invoice invoice UNNEEDED) { fprintf(stderr, "invoices_delete called!\n"); abort(); } /* Generated stub for invoices_find_by_label */ -const struct invoice *invoices_find_by_label(struct invoices *invoices UNNEEDED, - const char *label UNNEEDED) +bool invoices_find_by_label(struct invoices *invoices UNNEEDED, + struct invoice *pinvoice UNNEEDED, + const char *label UNNEEDED) { fprintf(stderr, "invoices_find_by_label called!\n"); abort(); } /* Generated stub for invoices_find_unpaid */ -const struct invoice *invoices_find_unpaid(struct invoices *invoices UNNEEDED, - const struct sha256 *rhash UNNEEDED) +bool invoices_find_unpaid(struct invoices *invoices UNNEEDED, + struct invoice *pinvoice UNNEEDED, + const struct sha256 *rhash UNNEEDED) { fprintf(stderr, "invoices_find_unpaid called!\n"); abort(); } /* Generated stub for invoices_get_details */ void invoices_get_details(const tal_t *ctx UNNEEDED, struct invoices *invoices UNNEEDED, - const struct invoice *invoice UNNEEDED, + struct invoice invoice UNNEEDED, struct invoice_details *details UNNEEDED) { fprintf(stderr, "invoices_get_details called!\n"); abort(); } /* Generated stub for invoices_iterate */ @@ -139,7 +142,7 @@ struct invoices *invoices_new(const tal_t *ctx UNNEEDED, { fprintf(stderr, "invoices_new called!\n"); abort(); } /* Generated stub for invoices_resolve */ void invoices_resolve(struct invoices *invoices UNNEEDED, - const struct invoice *invoice UNNEEDED, + struct invoice invoice UNNEEDED, u64 msatoshi_received UNNEEDED) { fprintf(stderr, "invoices_resolve called!\n"); abort(); } /* Generated stub for invoices_waitany */ @@ -152,7 +155,7 @@ void invoices_waitany(const tal_t *ctx UNNEEDED, /* Generated stub for invoices_waitone */ void invoices_waitone(const tal_t *ctx UNNEEDED, struct invoices *invoices UNNEEDED, - struct invoice const *invoice UNNEEDED, + struct invoice invoice UNNEEDED, void (*cb)(const struct invoice * UNNEEDED, void*) UNNEEDED, void *cbarg UNNEEDED) { fprintf(stderr, "invoices_waitone called!\n"); abort(); } diff --git a/wallet/wallet.c b/wallet/wallet.c index 0e5564444..e350d3e2a 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1266,24 +1266,27 @@ bool wallet_invoice_load(struct wallet *wallet) { return invoices_load(wallet->invoices); } -const struct invoice *wallet_invoice_create(struct wallet *wallet, - u64 *msatoshi TAKES, - const char *label TAKES, - u64 expiry) { - return invoices_create(wallet->invoices, msatoshi, label, expiry); +bool wallet_invoice_create(struct wallet *wallet, + struct invoice *pinvoice, + u64 *msatoshi TAKES, + const char *label TAKES, + u64 expiry) { + return invoices_create(wallet->invoices, pinvoice, msatoshi, label, expiry); } -const struct invoice *wallet_invoice_find_by_label(struct wallet *wallet, - const char *label) +bool wallet_invoice_find_by_label(struct wallet *wallet, + struct invoice *pinvoice, + const char *label) { - return invoices_find_by_label(wallet->invoices, label); + return invoices_find_by_label(wallet->invoices, pinvoice, label); } -const struct invoice *wallet_invoice_find_unpaid(struct wallet *wallet, - const struct sha256 *rhash) +bool wallet_invoice_find_unpaid(struct wallet *wallet, + struct invoice *pinvoice, + const struct sha256 *rhash) { - return invoices_find_unpaid(wallet->invoices, rhash); + return invoices_find_unpaid(wallet->invoices, pinvoice, rhash); } bool wallet_invoice_delete(struct wallet *wallet, - const struct invoice *invoice) + struct invoice invoice) { return invoices_delete(wallet->invoices, invoice); } @@ -1300,7 +1303,7 @@ void wallet_invoice_iterator_deref(const tal_t *ctx, return invoices_iterator_deref(ctx, wallet->invoices, it, details); } void wallet_invoice_resolve(struct wallet *wallet, - const struct invoice *invoice, + struct invoice invoice, u64 msatoshi_received) { invoices_resolve(wallet->invoices, invoice, msatoshi_received); @@ -1315,7 +1318,7 @@ void wallet_invoice_waitany(const tal_t *ctx, } void wallet_invoice_waitone(const tal_t *ctx, struct wallet *wallet, - struct invoice const *invoice, + struct invoice invoice, void (*cb)(const struct invoice *, void*), void *cbarg) { @@ -1323,7 +1326,7 @@ void wallet_invoice_waitone(const tal_t *ctx, } void wallet_invoice_details(const tal_t *ctx, struct wallet *wallet, - const struct invoice *invoice, + struct invoice invoice, struct invoice_details *details) { invoices_get_details(ctx, wallet->invoices, invoice, details); diff --git a/wallet/wallet.h b/wallet/wallet.h index dde8bdcb7..3f316c9cc 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -394,20 +394,13 @@ struct invoice_details { struct invoice_iterator { /* The contents of this object is subject to change * and should not be depended upon */ - const struct invoice *curr; + void *p; }; struct invoice { /* Internal, rest of lightningd should not use */ - /* List off ld->wallet->invoices. Must be first or else - * dev-memleak is driven insane. */ - struct list_node list; /* Database ID */ u64 id; - /* The owning invoices object. */ - struct invoices *owner; - /* Loaded details. */ - struct invoice_details *details; }; #define INVOICE_MAX_LABEL_LEN 128 @@ -430,6 +423,7 @@ bool wallet_invoice_load(struct wallet *wallet); * wallet_invoice_create - Create a new invoice. * * @wallet - the wallet to create the invoice in. + * @pinvoice - pointer to location to load new invoice in. * @msatoshi - the amount the invoice should have, or * NULL for any-amount invoices. * @label - the unique label for this invoice. Must be @@ -437,36 +431,44 @@ bool wallet_invoice_load(struct wallet *wallet); * @expiry - the number of seconds before the invoice * expires * - * Returns NULL if label already exists or expiry is 0. + * Returns false if label already exists or expiry is 0. + * Returns true if created invoice. * FIXME: Fallback addresses */ -const struct invoice *wallet_invoice_create(struct wallet *wallet, - u64 *msatoshi TAKES, - const char *label TAKES, - u64 expiry); +bool wallet_invoice_create(struct wallet *wallet, + struct invoice *pinvoice, + u64 *msatoshi TAKES, + const char *label TAKES, + u64 expiry); /** * wallet_invoice_find_by_label - Search for an invoice by label * * @wallet - the wallet to search. + * @pinvoice - pointer to location to load found invoice in. * @label - the label to search for. Must be null-terminated. * - * Returns NULL if no invoice with that label exists. + * Returns false if no invoice with that label exists. + * Returns true if found. */ -const struct invoice *wallet_invoice_find_by_label(struct wallet *wallet, - const char *label); +bool wallet_invoice_find_by_label(struct wallet *wallet, + struct invoice *pinvoice, + const char *label); /** * wallet_invoice_find_unpaid - Search for an unpaid, unexpired invoice by * payment_hash * * @wallet - the wallet to search. + * @pinvoice - pointer to location to load found invoice in. * @rhash - the payment_hash to search for. * - * Returns NULL if no invoice with that payment hash exists. + * Returns false if no unpaid invoice with that rhash exists. + * Returns true if found. */ -const struct invoice *wallet_invoice_find_unpaid(struct wallet *wallet, - const struct sha256 *rhash); +bool wallet_invoice_find_unpaid(struct wallet *wallet, + struct invoice *pinvoice, + const struct sha256 *rhash); /** * wallet_invoice_delete - Delete an invoice @@ -477,7 +479,7 @@ const struct invoice *wallet_invoice_find_unpaid(struct wallet *wallet, * Return false on failure. */ bool wallet_invoice_delete(struct wallet *wallet, - const struct invoice *invoice); + struct invoice invoice); /** * wallet_invoice_iterate - Iterate over all existing invoices @@ -520,10 +522,10 @@ void wallet_invoice_iterator_deref(const tal_t *ctx, * @msatoshi_received - the actual amount received. * * Precondition: the invoice must not yet be expired (wallet - * does not check). + * does not check!). */ void wallet_invoice_resolve(struct wallet *wallet, - const struct invoice *invoice, + struct invoice invoice, u64 msatoshi_received); /** @@ -537,7 +539,8 @@ void wallet_invoice_resolve(struct wallet *wallet, * @cb - the callback to invoke. If an invoice is already * paid with pay_index greater than lastpay_index, this * is called immediately, otherwise it is called during - * an invoices_resolve call. + * an invoices_resolve call. Will never be given a NULL + * pointer-to-invoice. * @cbarg - the callback data. */ void wallet_invoice_waitany(const tal_t *ctx, @@ -564,7 +567,7 @@ void wallet_invoice_waitany(const tal_t *ctx, */ void wallet_invoice_waitone(const tal_t *ctx, struct wallet *wallet, - struct invoice const *invoice, + struct invoice invoice, void (*cb)(const struct invoice *, void*), void *cbarg); @@ -578,7 +581,7 @@ void wallet_invoice_waitone(const tal_t *ctx, */ void wallet_invoice_details(const tal_t *ctx, struct wallet *wallet, - const struct invoice *invoice, + struct invoice invoice, struct invoice_details *details); /**