From d17506b89973a1f9e184fb4da56661ea0b00e752 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 14 Jul 2023 09:58:43 +0930 Subject: [PATCH] wallet: use standard-style iterators for invoices. Same as we use for offers, etc. Signed-off-by: Rusty Russell --- lightningd/invoice.c | 12 ++--- lightningd/test/run-invoice-select-inchan.c | 18 ++++---- wallet/invoices.c | 50 ++++++--------------- wallet/invoices.h | 41 +++++++---------- wallet/wallet.h | 7 --- 5 files changed, 45 insertions(+), 83 deletions(-) diff --git a/lightningd/invoice.c b/lightningd/invoice.c index e6a946fc5..e73f40b78 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -1223,7 +1223,6 @@ static void json_add_invoices(struct json_stream *response, const struct sha256 *payment_hash, const struct sha256 *local_offer_id) { - struct invoice_iterator it; const struct invoice_details *details; u64 inv_dbid; @@ -1242,10 +1241,13 @@ static void json_add_invoices(struct json_stream *response, json_add_invoice(response, NULL, details); } } else { - memset(&it, 0, sizeof(it)); - while (invoices_iterate(wallet->invoices, &it)) { - details = invoices_iterator_deref(response, - wallet->invoices, &it); + struct db_stmt *stmt; + + for (stmt = invoices_first(wallet->invoices, &inv_dbid); + stmt; + stmt = invoices_next(wallet->invoices, stmt, &inv_dbid)) { + details = invoices_get_details(tmpctx, + wallet->invoices, inv_dbid); /* FIXME: db can filter this better! */ if (local_offer_id) { if (!details->local_offer_id diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index cf8d41a68..49e138ce3 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -393,20 +393,20 @@ bool invoices_find_unpaid(struct invoices *invoices UNNEEDED, u64 *inv_dbid UNNEEDED, const struct sha256 *rhash UNNEEDED) { fprintf(stderr, "invoices_find_unpaid called!\n"); abort(); } +/* Generated stub for invoices_first */ +struct db_stmt *invoices_first(struct invoices *invoices UNNEEDED, + u64 *inv_dbid UNNEEDED) +{ fprintf(stderr, "invoices_first called!\n"); abort(); } /* Generated stub for invoices_get_details */ struct invoice_details *invoices_get_details(const tal_t *ctx UNNEEDED, struct invoices *invoices UNNEEDED, u64 inv_dbid UNNEEDED) { fprintf(stderr, "invoices_get_details called!\n"); abort(); } -/* Generated stub for invoices_iterate */ -bool invoices_iterate(struct invoices *invoices UNNEEDED, - struct invoice_iterator *it UNNEEDED) -{ fprintf(stderr, "invoices_iterate called!\n"); abort(); } -/* Generated stub for invoices_iterator_deref */ -const struct invoice_details *invoices_iterator_deref( - const tal_t *ctx UNNEEDED, struct invoices *invoices UNNEEDED, - const struct invoice_iterator *it UNNEEDED) -{ fprintf(stderr, "invoices_iterator_deref called!\n"); abort(); } +/* Generated stub for invoices_next */ +struct db_stmt *invoices_next(struct invoices *invoices UNNEEDED, + struct db_stmt *stmt UNNEEDED, + u64 *inv_dbid UNNEEDED) +{ fprintf(stderr, "invoices_next called!\n"); abort(); } /* Generated stub for invoices_resolve */ bool invoices_resolve(struct invoices *invoices UNNEEDED, u64 inv_dbid UNNEEDED, diff --git a/wallet/invoices.c b/wallet/invoices.c index 46078c74b..17c74fbb1 100644 --- a/wallet/invoices.c +++ b/wallet/invoices.c @@ -442,50 +442,26 @@ void invoices_delete_expired(struct invoices *invoices, db_exec_prepared_v2(take(stmt)); } -bool invoices_iterate(struct invoices *invoices, - struct invoice_iterator *it) +struct db_stmt *invoices_first(struct invoices *invoices, + u64 *inv_dbid) { struct db_stmt *stmt; - if (!it->p) { - stmt = db_prepare_v2(invoices->wallet->db, SQL("SELECT" - " state" - ", payment_key" - ", payment_hash" - ", label" - ", msatoshi" - ", expiry_time" - ", pay_index" - ", msatoshi_received" - ", paid_timestamp" - ", bolt11" - ", description" - ", features" - ", local_offer_id" - " FROM invoices" - " ORDER BY id;")); - db_query_prepared(stmt); - it->p = stmt; - } else - stmt = it->p; + stmt = db_prepare_v2(invoices->wallet->db, SQL("SELECT id FROM invoices ORDER by id;")); + db_query_prepared(stmt); - - if (db_step(stmt)) - /* stmt doesn't need to be freed since we expect to be called - * again, and stmt will be freed on the last iteration. */ - return true; - - tal_free(stmt); - it->p = NULL; - return false; + return invoices_next(invoices, stmt, inv_dbid); } -const struct invoice_details * -invoices_iterator_deref(const tal_t *ctx, struct invoices *invoices UNUSED, - const struct invoice_iterator *it) +struct db_stmt *invoices_next(struct invoices *invoices, + struct db_stmt *stmt, + u64 *inv_dbid) { - assert(it->p); - return wallet_stmt2invoice_details(ctx, (struct db_stmt*) it->p); + if (!db_step(stmt)) + return tal_free(stmt); + + *inv_dbid = db_col_u64(stmt, "id"); + return stmt; } static s64 get_next_pay_index(struct db *db) diff --git a/wallet/invoices.h b/wallet/invoices.h index e79b323a1..2e39ebbca 100644 --- a/wallet/invoices.h +++ b/wallet/invoices.h @@ -9,7 +9,6 @@ struct db; struct json_escape; struct invoice; struct invoice_details; -struct invoice_iterator; struct invoices; struct sha256; struct timers; @@ -130,36 +129,28 @@ void invoices_delete_expired(struct invoices *invoices, u64 max_expiry_time); /** - * invoices_iterate - Iterate over all existing invoices + * Iterate through all the invoices. + * @invoices: the invoices + * @inv_dbid: the first invoice dbid (if returns non-NULL) * - * @invoices - the invoice handler. - * @iterator - the iterator object to use. - * - * Return false at end-of-sequence, true if still iterating. - * Usage: - * - * struct invoice_iterator it; - * memset(&it, 0, sizeof(it)) - * while (invoices_iterate(wallet, &it)) { - * ... - * } + * Returns pointer to hand as @stmt to invoices_next(), or NULL. + * If you choose not to call invoices_next() you must free it! */ -bool invoices_iterate(struct invoices *invoices, - struct invoice_iterator *it); +struct db_stmt *invoices_first(struct invoices *invoices, + u64 *inv_dbid); /** - * wallet_invoice_iterator_deref - Read the details of the - * invoice currently pointed to by the given iterator. - * - * @ctx - the owner of the label and msatoshi fields returned. - * @wallet - the wallet whose invoices are to be iterated over. - * @iterator - the iterator object to use. - * @return The invoice details allocated off of `ctx` + * Iterate through all the offers. + * @invoices: the invoices + * @stmt: return from invoices_first() or previous invoices_next() + * @inv_dbid: the first invoice dbid (if returns non-NULL) * + * Returns NULL once we're out of invoices. If you choose not to call + * invoices_next() again you must free return. */ -const struct invoice_details *invoices_iterator_deref( - const tal_t *ctx, struct invoices *invoices, - const struct invoice_iterator *it); +struct db_stmt *invoices_next(struct invoices *invoices, + struct db_stmt *stmt, + u64 *inv_dbid); /** * invoices_resolve - Mark an invoice as paid diff --git a/wallet/wallet.h b/wallet/wallet.h index 3640a05f3..2e6babef0 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -63,13 +63,6 @@ static inline enum output_status output_status_in_db(enum output_status s) fatal("%s: %u is invalid", __func__, s); } -/* An object that handles iteration over the set of invoices */ -struct invoice_iterator { - /* The contents of this object is subject to change - * and should not be depended upon */ - void *p; -}; - /* Enumeration of all known output types. These include all types that * could ever end up on-chain and we may need to react upon. Notice * that `to_local`, `htlc_offer`, and `htlc_recv` may need immediate