diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index 6f624c839..a7d5463ba 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -870,6 +870,7 @@ static void remove_tip(struct chain_topology *topo) struct block *b = topo->tip; struct bitcoin_txid *txs; size_t i, n; + const struct short_channel_id *removed_scids; log_debug(topo->log, "Removing stale block %u: %s", topo->tip->height, @@ -890,11 +891,20 @@ static void remove_tip(struct chain_topology *topo) for (i = 0; i < n; i++) txwatch_fire(topo, &txs[i], 0); + /* Grab these before we delete block from db */ + removed_scids = wallet_utxoset_get_created(tmpctx, topo->ld->wallet, + b->height); wallet_block_remove(topo->ld->wallet, b); + /* This may have unconfirmed txs: reconfirm as we add blocks. */ watch_for_utxo_reconfirmation(topo, topo->ld->wallet); block_map_del(&topo->block_map, b); tal_free(b); + + /* These no longer exist, so gossipd drops any reference to them just + * as if they were spent. */ + for (size_t i=0; ibitcoind->ld, &removed_scids[i]); } static void get_new_block(struct bitcoind *bitcoind, diff --git a/tests/test_misc.py b/tests/test_misc.py index c78d250e4..e6277716e 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -1195,8 +1195,9 @@ def test_funding_reorg_private(node_factory, bitcoind): l2.daemon.wait_for_logs([r'Removing stale block {}'.format(106), r'Got depth change .->{} for .* REORG'.format(0)]) - wait_for(lambda: chan_active(l2, '106x1x0', False)) + # New one should replace old. wait_for(lambda: chan_active(l2, '108x1x0', True)) + assert l2.rpc.listchannels('106x1x0')['channels'] == [] l1.rpc.close(l2.info['id']) bitcoind.generate_block(1, True) @@ -1241,8 +1242,8 @@ def test_funding_reorg_remote_lags(node_factory, bitcoind): # Unblinding l2 brings it back in sync, restarts channeld and sends its announce sig l2.daemon.rpcproxy.mock_rpc('getblockhash', None) - wait_for(lambda: chan_active(l2, '103x1x0', False)) wait_for(lambda: chan_active(l2, '104x1x0', True)) + assert l2.rpc.listchannels('103x1x0')['channels'] == [] wait_for(lambda: only_one(l2.rpc.listpeers()['peers'][0]['channels'])['status'] == [ 'CHANNELD_NORMAL:Reconnected, and reestablished.', diff --git a/wallet/db_postgres_sqlgen.c b/wallet/db_postgres_sqlgen.c index 539287837..2ec8c9400 100644 --- a/wallet/db_postgres_sqlgen.c +++ b/wallet/db_postgres_sqlgen.c @@ -1826,6 +1826,12 @@ struct db_query db_postgres_queries[] = { .placeholders = 1, .readonly = true, }, + { + .name = "SELECT blockheight, txindex, outnum FROM utxoset WHERE blockheight = ?", + .query = "SELECT blockheight, txindex, outnum FROM utxoset WHERE blockheight = $1", + .placeholders = 1, + .readonly = true, + }, { .name = "SELECT blockheight FROM transactions WHERE id=?", .query = "SELECT blockheight FROM transactions WHERE id=$1", @@ -2020,10 +2026,10 @@ struct db_query db_postgres_queries[] = { }, }; -#define DB_POSTGRES_QUERY_COUNT 335 +#define DB_POSTGRES_QUERY_COUNT 336 #endif /* HAVE_POSTGRES */ #endif /* LIGHTNINGD_WALLET_GEN_DB_POSTGRES */ -// SHA256STAMP:27a166e040e517422e91cf7ffbd12426b34337b8d75f82d7aa4c448beae5e821 +// SHA256STAMP:df06b800543e6bb886100ca428247ac1097f749098779dae43ba875154700f58 diff --git a/wallet/db_sqlite3_sqlgen.c b/wallet/db_sqlite3_sqlgen.c index c57cb3772..5f276fc3d 100644 --- a/wallet/db_sqlite3_sqlgen.c +++ b/wallet/db_sqlite3_sqlgen.c @@ -1826,6 +1826,12 @@ struct db_query db_sqlite3_queries[] = { .placeholders = 1, .readonly = true, }, + { + .name = "SELECT blockheight, txindex, outnum FROM utxoset WHERE blockheight = ?", + .query = "SELECT blockheight, txindex, outnum FROM utxoset WHERE blockheight = ?", + .placeholders = 1, + .readonly = true, + }, { .name = "SELECT blockheight FROM transactions WHERE id=?", .query = "SELECT blockheight FROM transactions WHERE id=?", @@ -2020,10 +2026,10 @@ struct db_query db_sqlite3_queries[] = { }, }; -#define DB_SQLITE3_QUERY_COUNT 335 +#define DB_SQLITE3_QUERY_COUNT 336 #endif /* HAVE_SQLITE3 */ #endif /* LIGHTNINGD_WALLET_GEN_DB_SQLITE3 */ -// SHA256STAMP:27a166e040e517422e91cf7ffbd12426b34337b8d75f82d7aa4c448beae5e821 +// SHA256STAMP:df06b800543e6bb886100ca428247ac1097f749098779dae43ba875154700f58 diff --git a/wallet/statements_gettextgen.po b/wallet/statements_gettextgen.po index 317b0406d..b4419e5ac 100644 --- a/wallet/statements_gettextgen.po +++ b/wallet/statements_gettextgen.po @@ -1206,119 +1206,123 @@ msgstr "" msgid "SELECT txid, spendheight, scriptpubkey, satoshis FROM utxoset WHERE blockheight = ? AND txindex = ? AND outnum = ? AND spendheight IS NULL" msgstr "" -#: wallet/wallet.c:3746 +#: wallet/wallet.c:3768 msgid "SELECT blockheight, txindex, outnum FROM utxoset WHERE spendheight = ?" msgstr "" -#: wallet/wallet.c:3777 wallet/wallet.c:3937 +#: wallet/wallet.c:3785 +msgid "SELECT blockheight, txindex, outnum FROM utxoset WHERE blockheight = ?" +msgstr "" + +#: wallet/wallet.c:3802 wallet/wallet.c:3962 msgid "SELECT blockheight FROM transactions WHERE id=?" msgstr "" -#: wallet/wallet.c:3787 +#: wallet/wallet.c:3812 msgid "INSERT INTO transactions ( id, blockheight, txindex, rawtx) VALUES (?, ?, ?, ?);" msgstr "" -#: wallet/wallet.c:3808 +#: wallet/wallet.c:3833 msgid "UPDATE transactions SET blockheight = ?, txindex = ? WHERE id = ?" msgstr "" -#: wallet/wallet.c:3825 +#: wallet/wallet.c:3850 msgid "INSERT INTO transaction_annotations (txid, idx, location, type, channel) VALUES (?, ?, ?, ?, ?) ON CONFLICT(txid,idx) DO NOTHING;" msgstr "" -#: wallet/wallet.c:3857 +#: wallet/wallet.c:3882 msgid "SELECT type, channel_id FROM transactions WHERE id=?" msgstr "" -#: wallet/wallet.c:3873 +#: wallet/wallet.c:3898 msgid "UPDATE transactions SET type = ?, channel_id = ? WHERE id = ?" msgstr "" -#: wallet/wallet.c:3892 +#: wallet/wallet.c:3917 msgid "SELECT type FROM transactions WHERE id=?" msgstr "" -#: wallet/wallet.c:3915 +#: wallet/wallet.c:3940 msgid "SELECT rawtx FROM transactions WHERE id=?" msgstr "" -#: wallet/wallet.c:3961 +#: wallet/wallet.c:3986 msgid "SELECT blockheight, txindex FROM transactions WHERE id=?" msgstr "" -#: wallet/wallet.c:3989 +#: wallet/wallet.c:4014 msgid "SELECT id FROM transactions WHERE blockheight=?" msgstr "" -#: wallet/wallet.c:4008 +#: wallet/wallet.c:4033 msgid "INSERT INTO channeltxs ( channel_id, type, transaction_id, input_num, blockheight) VALUES (?, ?, ?, ?, ?);" msgstr "" -#: wallet/wallet.c:4032 +#: wallet/wallet.c:4057 msgid "SELECT DISTINCT(channel_id) FROM channeltxs WHERE type = ?;" msgstr "" -#: wallet/wallet.c:4053 +#: wallet/wallet.c:4078 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:4098 +#: wallet/wallet.c:4123 msgid "UPDATE forwarded_payments SET in_msatoshi=?, out_msatoshi=?, state=?, resolved_time=?, failcode=? WHERE in_htlc_id=?" msgstr "" -#: wallet/wallet.c:4156 +#: wallet/wallet.c:4181 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:4215 +#: wallet/wallet.c:4240 msgid "SELECT CAST(COALESCE(SUM(in_msatoshi - out_msatoshi), 0) AS BIGINT)FROM forwarded_payments WHERE state = ?;" msgstr "" -#: wallet/wallet.c:4264 +#: wallet/wallet.c:4289 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) WHERE (1 = ? OR f.state = ?) AND (1 = ? OR f.in_channel_scid = ?) AND (1 = ? OR f.out_channel_scid = ?)" msgstr "" -#: wallet/wallet.c:4386 +#: wallet/wallet.c:4411 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:4480 +#: wallet/wallet.c:4505 msgid "INSERT INTO penalty_bases ( channel_id, commitnum, txid, outnum, amount) VALUES (?, ?, ?, ?, ?);" msgstr "" -#: wallet/wallet.c:4505 +#: wallet/wallet.c:4530 msgid "SELECT commitnum, txid, outnum, amount FROM penalty_bases WHERE channel_id = ?" msgstr "" -#: wallet/wallet.c:4529 +#: wallet/wallet.c:4554 msgid "DELETE FROM penalty_bases WHERE channel_id = ? AND commitnum = ?" msgstr "" -#: wallet/wallet.c:4547 +#: wallet/wallet.c:4572 msgid "SELECT 1 FROM offers WHERE offer_id = ?;" msgstr "" -#: wallet/wallet.c:4560 +#: wallet/wallet.c:4585 msgid "INSERT INTO offers ( offer_id, bolt12, label, status) VALUES (?, ?, ?, ?);" msgstr "" -#: wallet/wallet.c:4587 +#: wallet/wallet.c:4612 msgid "SELECT bolt12, label, status FROM offers WHERE offer_id = ?;" msgstr "" -#: wallet/wallet.c:4615 +#: wallet/wallet.c:4640 msgid "SELECT offer_id FROM offers;" msgstr "" -#: wallet/wallet.c:4641 +#: wallet/wallet.c:4666 msgid "UPDATE offers SET status=? WHERE offer_id = ?;" msgstr "" -#: wallet/wallet.c:4652 +#: wallet/wallet.c:4677 msgid "UPDATE invoices SET state=? WHERE state=? AND local_offer_id = ?;" msgstr "" -#: wallet/wallet.c:4680 +#: wallet/wallet.c:4705 msgid "SELECT status FROM offers WHERE offer_id = ?;" msgstr "" @@ -1337,4 +1341,4 @@ msgstr "" #: wallet/test/run-wallet.c:1696 msgid "INSERT INTO channels (id) VALUES (1);" msgstr "" -# SHA256STAMP:3652b5850f08383c0f0c01a7f11c1a22ec2b4ac16018152d2770a73674fb05ec +# SHA256STAMP:d0ba3b9e4e392f7327662f333f4712582f7553a819d588ebb3641b229215e90f diff --git a/wallet/wallet.c b/wallet/wallet.c index 02ba582d0..e3d5da7f7 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -3556,7 +3556,7 @@ void wallet_block_add(struct wallet *w, struct block *b) void wallet_block_remove(struct wallet *w, struct block *b) { struct db_stmt *stmt = - db_prepare_v2(w->db, SQL("DELETE FROM blocks WHERE hash = ?")); + db_prepare_v2(w->db, SQL("DELETE FROM blocks WHERE hash = ?")); db_bind_sha256d(stmt, 0, &b->blkid.shad); db_exec_prepared_v2(take(stmt)); @@ -3738,21 +3738,12 @@ 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) +/* Turns "SELECT blockheight, txindex, outnum" into scids */ +static const struct short_channel_id *db_scids(const tal_t *ctx, + struct db_stmt *stmt STEALS) { - 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); + struct short_channel_id *res = tal_arr(ctx, struct short_channel_id, 0); - res = tal_arr(ctx, struct short_channel_id, 0); while (db_step(stmt)) { struct short_channel_id scid; u64 blocknum, txnum, outnum; @@ -3769,6 +3760,40 @@ wallet_utxoset_get_spent(const tal_t *ctx, struct wallet *w, u32 blockheight) return res; } +const struct short_channel_id * +wallet_utxoset_get_spent(const tal_t *ctx, struct wallet *w, + u32 blockheight) +{ + struct db_stmt *stmt; + 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); + + return db_scids(ctx, stmt); +} + +const struct short_channel_id * +wallet_utxoset_get_created(const tal_t *ctx, struct wallet *w, + u32 blockheight) +{ + struct db_stmt *stmt; + stmt = db_prepare_v2(w->db, SQL("SELECT" + " blockheight," + " txindex," + " outnum " + "FROM utxoset " + "WHERE blockheight = ?")); + db_bind_int(stmt, 0, blockheight); + db_query_prepared(stmt); + + return db_scids(ctx, stmt); +} + 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 7985dc5a0..398fd948a 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -1198,6 +1198,12 @@ void wallet_utxoset_add(struct wallet *w, const struct bitcoin_tx *tx, const struct short_channel_id * wallet_utxoset_get_spent(const tal_t *ctx, struct wallet *w, u32 blockheight); +/** + * Retrieve all UTXO entries that were created at a given blockheight. + */ +const struct short_channel_id * +wallet_utxoset_get_created(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);