From eeb6e8091bbf1360fe44fabb5a6c890d67b601e4 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Tue, 8 Sep 2020 12:34:36 +0200 Subject: [PATCH] wallet: Add function to retrieve spent UTXOs for a given height The plan is to eventually use this to tell gossipd about any outputs that were spent by the last block. --- wallet/db_postgres_sqlgen.c | 10 +++++-- wallet/db_sqlite3_sqlgen.c | 10 +++++-- wallet/statements_gettextgen.po | 48 ++++++++++++++++++--------------- wallet/wallet.c | 31 +++++++++++++++++++++ wallet/wallet.h | 15 +++++++++++ 5 files changed, 88 insertions(+), 26 deletions(-) diff --git a/wallet/db_postgres_sqlgen.c b/wallet/db_postgres_sqlgen.c index a9cc1f9e3..9960466ed 100644 --- a/wallet/db_postgres_sqlgen.c +++ b/wallet/db_postgres_sqlgen.c @@ -1490,6 +1490,12 @@ struct db_query db_postgres_queries[] = { .placeholders = 3, .readonly = true, }, + { + .name = "SELECT blockheight, txindex, outnum FROM utxoset WHERE spendheight = ?", + .query = "SELECT blockheight, txindex, outnum FROM utxoset WHERE spendheight = $1", + .placeholders = 1, + .readonly = true, + }, { .name = "SELECT blockheight FROM transactions WHERE id=?", .query = "SELECT blockheight FROM transactions WHERE id=$1", @@ -1636,10 +1642,10 @@ struct db_query db_postgres_queries[] = { }, }; -#define DB_POSTGRES_QUERY_COUNT 271 +#define DB_POSTGRES_QUERY_COUNT 272 #endif /* HAVE_POSTGRES */ #endif /* LIGHTNINGD_WALLET_GEN_DB_POSTGRES */ -// SHA256STAMP:fa885142376ef8ac5cae84c02d379d7e1bf97d3b0c69af46a6054316d2e6a1bc +// SHA256STAMP:9c0282186a89a37a232b8a4f34dceabaf5b53b7cc5c3bc24eb4e53967662cb6f diff --git a/wallet/db_sqlite3_sqlgen.c b/wallet/db_sqlite3_sqlgen.c index 413a684c9..45a597d72 100644 --- a/wallet/db_sqlite3_sqlgen.c +++ b/wallet/db_sqlite3_sqlgen.c @@ -1490,6 +1490,12 @@ struct db_query db_sqlite3_queries[] = { .placeholders = 3, .readonly = true, }, + { + .name = "SELECT blockheight, txindex, outnum FROM utxoset WHERE spendheight = ?", + .query = "SELECT blockheight, txindex, outnum FROM utxoset WHERE spendheight = ?", + .placeholders = 1, + .readonly = true, + }, { .name = "SELECT blockheight FROM transactions WHERE id=?", .query = "SELECT blockheight FROM transactions WHERE id=?", @@ -1636,10 +1642,10 @@ struct db_query db_sqlite3_queries[] = { }, }; -#define DB_SQLITE3_QUERY_COUNT 271 +#define DB_SQLITE3_QUERY_COUNT 272 #endif /* HAVE_SQLITE3 */ #endif /* LIGHTNINGD_WALLET_GEN_DB_SQLITE3 */ -// SHA256STAMP:fa885142376ef8ac5cae84c02d379d7e1bf97d3b0c69af46a6054316d2e6a1bc +// SHA256STAMP:9c0282186a89a37a232b8a4f34dceabaf5b53b7cc5c3bc24eb4e53967662cb6f diff --git a/wallet/statements_gettextgen.po b/wallet/statements_gettextgen.po index 9d1c8170f..b1cf1769d 100644 --- a/wallet/statements_gettextgen.po +++ b/wallet/statements_gettextgen.po @@ -986,87 +986,91 @@ msgstr "" msgid "SELECT txid, spendheight, scriptpubkey, satoshis FROM utxoset WHERE blockheight = ? AND txindex = ? AND outnum = ? AND spendheight IS NULL" msgstr "" -#: wallet/wallet.c:3203 wallet/wallet.c:3363 +#: wallet/wallet.c:3203 +msgid "SELECT blockheight, txindex, outnum FROM utxoset WHERE spendheight = ?" +msgstr "" + +#: wallet/wallet.c:3234 wallet/wallet.c:3394 msgid "SELECT blockheight FROM transactions WHERE id=?" msgstr "" -#: wallet/wallet.c:3213 +#: wallet/wallet.c:3244 msgid "INSERT INTO transactions ( id, blockheight, txindex, rawtx) VALUES (?, ?, ?, ?);" msgstr "" -#: wallet/wallet.c:3234 +#: wallet/wallet.c:3265 msgid "UPDATE transactions SET blockheight = ?, txindex = ? WHERE id = ?" msgstr "" -#: wallet/wallet.c:3251 +#: wallet/wallet.c:3282 msgid "INSERT INTO transaction_annotations (txid, idx, location, type, channel) VALUES (?, ?, ?, ?, ?) ON CONFLICT(txid,idx) DO NOTHING;" msgstr "" -#: wallet/wallet.c:3283 +#: wallet/wallet.c:3314 msgid "SELECT type, channel_id FROM transactions WHERE id=?" msgstr "" -#: wallet/wallet.c:3299 +#: wallet/wallet.c:3330 msgid "UPDATE transactions SET type = ?, channel_id = ? WHERE id = ?" msgstr "" -#: wallet/wallet.c:3318 +#: wallet/wallet.c:3349 msgid "SELECT type FROM transactions WHERE id=?" msgstr "" -#: wallet/wallet.c:3341 +#: wallet/wallet.c:3372 msgid "SELECT rawtx FROM transactions WHERE id=?" msgstr "" -#: wallet/wallet.c:3387 +#: wallet/wallet.c:3418 msgid "SELECT blockheight, txindex FROM transactions WHERE id=?" msgstr "" -#: wallet/wallet.c:3415 +#: wallet/wallet.c:3446 msgid "SELECT id FROM transactions WHERE blockheight=?" msgstr "" -#: wallet/wallet.c:3434 +#: wallet/wallet.c:3465 msgid "INSERT INTO channeltxs ( channel_id, type, transaction_id, input_num, blockheight) VALUES (?, ?, ?, ?, ?);" msgstr "" -#: wallet/wallet.c:3458 +#: wallet/wallet.c:3489 msgid "SELECT DISTINCT(channel_id) FROM channeltxs WHERE type = ?;" msgstr "" -#: wallet/wallet.c:3479 +#: wallet/wallet.c:3510 msgid "SELECT c.type, c.blockheight, t.rawtx, c.input_num, c.blockheight - t.blockheight + 1 AS depth, t.id as txid FROM channeltxs c JOIN transactions t ON t.id = c.transaction_id WHERE c.channel_id = ? ORDER BY c.id ASC;" msgstr "" -#: wallet/wallet.c:3524 +#: wallet/wallet.c:3555 msgid "UPDATE forwarded_payments SET in_msatoshi=?, out_msatoshi=?, state=?, resolved_time=?, failcode=? WHERE in_htlc_id=?" msgstr "" -#: wallet/wallet.c:3582 +#: wallet/wallet.c:3613 msgid "INSERT INTO forwarded_payments ( in_htlc_id, out_htlc_id, in_channel_scid, out_channel_scid, in_msatoshi, out_msatoshi, state, received_time, resolved_time, failcode) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);" msgstr "" -#: wallet/wallet.c:3641 +#: wallet/wallet.c:3672 msgid "SELECT CAST(COALESCE(SUM(in_msatoshi - out_msatoshi), 0) AS BIGINT)FROM forwarded_payments WHERE state = ?;" msgstr "" -#: wallet/wallet.c:3665 +#: wallet/wallet.c:3696 msgid "SELECT f.state, in_msatoshi, out_msatoshi, hin.payment_hash as payment_hash, in_channel_scid, out_channel_scid, f.received_time, f.resolved_time, f.failcode FROM forwarded_payments f LEFT JOIN channel_htlcs hin ON (f.in_htlc_id = hin.id)" msgstr "" -#: wallet/wallet.c:3753 +#: wallet/wallet.c:3784 msgid "SELECT t.id, t.rawtx, t.blockheight, t.txindex, t.type as txtype, c2.short_channel_id as txchan, a.location, a.idx as ann_idx, a.type as annotation_type, c.short_channel_id FROM transactions t LEFT JOIN transaction_annotations a ON (a.txid = t.id) LEFT JOIN channels c ON (a.channel = c.id) LEFT JOIN channels c2 ON (t.channel_id = c2.id) ORDER BY t.blockheight, t.txindex ASC" msgstr "" -#: wallet/wallet.c:3847 +#: wallet/wallet.c:3878 msgid "INSERT INTO penalty_bases ( channel_id, commitnum, txid, outnum, amount) VALUES (?, ?, ?, ?, ?);" msgstr "" -#: wallet/wallet.c:3872 +#: wallet/wallet.c:3903 msgid "SELECT commitnum, txid, outnum, amount FROM penalty_bases WHERE channel_id = ?" msgstr "" -#: wallet/wallet.c:3896 +#: wallet/wallet.c:3927 msgid "DELETE FROM penalty_bases WHERE channel_id = ? AND commitnum = ?" msgstr "" @@ -1081,4 +1085,4 @@ msgstr "" #: wallet/test/run-wallet.c:1345 msgid "INSERT INTO channels (id) VALUES (1);" msgstr "" -# SHA256STAMP:53a054ad896208a2c445cd4ef4bdda2d961451d816cdb2f29f2c2f7be69683d2 +# SHA256STAMP:6123671bea9e0a84e643ce453078dbdc4c8d12a3532e3c0354656eeaaff73f4b diff --git a/wallet/wallet.c b/wallet/wallet.c index 8e13bb530..297a80c0f 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -3195,6 +3195,37 @@ struct outpoint *wallet_outpoint_for_scid(struct wallet *w, tal_t *ctx, return op; } +const struct short_channel_id * +wallet_utxoset_get_spent(const tal_t *ctx, struct wallet *w, u32 blockheight) +{ + struct db_stmt *stmt; + struct short_channel_id *res; + stmt = db_prepare_v2(w->db, SQL("SELECT" + " blockheight," + " txindex," + " outnum " + "FROM utxoset " + "WHERE spendheight = ?")); + db_bind_int(stmt, 0, blockheight); + db_query_prepared(stmt); + + res = tal_arr(ctx, struct short_channel_id, 0); + while (db_step(stmt)) { + struct short_channel_id scid; + u64 blocknum, txnum, outnum; + bool ok; + blocknum = db_column_int(stmt, 0); + txnum = db_column_int(stmt, 1); + outnum = db_column_int(stmt, 2); + ok = mk_short_channel_id(&scid, blocknum, txnum, outnum); + + assert(ok); + tal_arr_expand(&res, scid); + } + tal_free(stmt); + return res; +} + void wallet_transaction_add(struct wallet *w, const struct wally_tx *tx, const u32 blockheight, const u32 txindex) { diff --git a/wallet/wallet.h b/wallet/wallet.h index 8220408a6..635b7348c 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -1110,6 +1110,21 @@ void wallet_utxoset_add(struct wallet *w, const struct bitcoin_tx *tx, const u32 txindex, const u8 *scriptpubkey, struct amount_sat sat); +/** + * Retrieve all UTXO entries that were spent by the given blockheight. + * + * This allows us to retrieve any UTXO entries that were spent by a block, + * after the block has been processed. It's main use is to be able to tell + * `gossipd` about potential channel outpoints being spent, without having to + * track all outpoints in memory. + * + * In order to return correct results `blockheight` should not be called with + * a height below the UTXO set pruning height (see `UTXO_PRUNE_DEPTH` for the + * current value). + */ +const struct short_channel_id * +wallet_utxoset_get_spent(const tal_t *ctx, struct wallet *w, u32 blockheight); + void wallet_transaction_add(struct wallet *w, const struct wally_tx *tx, const u32 blockheight, const u32 txindex);