Skip to content

Commit 71bdf0b

Browse files
committed
Merge bitcoin/bitcoin#22626: Remove txindex migration code
fa20f81 Remove txindex migration code (MarcoFalke) fae8786 doc: Fix validation typo (MarcoFalke) fab8900 Add missing includes and forward declarations, remove unused ones (MarcoFalke) Pull request description: No supported version of Bitcoin Core used the legacy txindex, so all relevant nodes can be assumed to have upgraded. Thus, there is no need to keep this code any longer. As a temporary courtesy, provide a one-time warning on how to free the disk space used by the legacy txindex. Fixes #22615 ACKs for top commit: laanwj: Code review ACK fa20f81 hebasto: ACK fa20f81, tested on Linux Mint 20.2 (x86_64). Zero-1729: crACK fa20f81 theStack: Approach ACK fa20f81 Tree-SHA512: 68aa32d064d1e3932e6e382816a4b5de417bd7e82861fea1ee50660e8c397f4efeb88ae4ed54a8ad1952c3563eb0b8449d7ccf883c353cc4d4dc7e15c53d78e8
2 parents 698b4b8 + fa20f81 commit 71bdf0b

File tree

8 files changed

+44
-175
lines changed

8 files changed

+44
-175
lines changed

src/index/base.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
#define BITCOIN_INDEX_BASE_H
77

88
#include <dbwrapper.h>
9-
#include <primitives/block.h>
10-
#include <primitives/transaction.h>
119
#include <threadinterrupt.h>
1210
#include <validationinterface.h>
1311

12+
class CBlock;
1413
class CBlockIndex;
1514
class CChainState;
1615

src/index/txindex.cpp

Lines changed: 2 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,14 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5-
#include <index/disktxpos.h>
65
#include <index/txindex.h>
6+
7+
#include <index/disktxpos.h>
78
#include <node/blockstorage.h>
8-
#include <node/ui_interface.h>
9-
#include <shutdown.h>
109
#include <util/system.h>
11-
#include <util/translation.h>
1210
#include <validation.h>
1311

14-
constexpr uint8_t DB_BEST_BLOCK{'B'};
1512
constexpr uint8_t DB_TXINDEX{'t'};
16-
constexpr uint8_t DB_TXINDEX_BLOCK{'T'};
1713

1814
std::unique_ptr<TxIndex> g_txindex;
1915

@@ -30,10 +26,6 @@ class TxIndex::DB : public BaseIndex::DB
3026

3127
/// Write a batch of transaction positions to the DB.
3228
bool WriteTxs(const std::vector<std::pair<uint256, CDiskTxPos>>& v_pos);
33-
34-
/// Migrate txindex data from the block tree DB, where it may be for older nodes that have not
35-
/// been upgraded yet to the new database.
36-
bool MigrateData(CBlockTreeDB& block_tree_db, const CBlockLocator& best_locator);
3729
};
3830

3931
TxIndex::DB::DB(size_t n_cache_size, bool f_memory, bool f_wipe) :
@@ -54,163 +46,12 @@ bool TxIndex::DB::WriteTxs(const std::vector<std::pair<uint256, CDiskTxPos>>& v_
5446
return WriteBatch(batch);
5547
}
5648

57-
/*
58-
* Safely persist a transfer of data from the old txindex database to the new one, and compact the
59-
* range of keys updated. This is used internally by MigrateData.
60-
*/
61-
static void WriteTxIndexMigrationBatches(CDBWrapper& newdb, CDBWrapper& olddb,
62-
CDBBatch& batch_newdb, CDBBatch& batch_olddb,
63-
const std::pair<uint8_t, uint256>& begin_key,
64-
const std::pair<uint8_t, uint256>& end_key)
65-
{
66-
// Sync new DB changes to disk before deleting from old DB.
67-
newdb.WriteBatch(batch_newdb, /*fSync=*/ true);
68-
olddb.WriteBatch(batch_olddb);
69-
olddb.CompactRange(begin_key, end_key);
70-
71-
batch_newdb.Clear();
72-
batch_olddb.Clear();
73-
}
74-
75-
bool TxIndex::DB::MigrateData(CBlockTreeDB& block_tree_db, const CBlockLocator& best_locator)
76-
{
77-
// The prior implementation of txindex was always in sync with block index
78-
// and presence was indicated with a boolean DB flag. If the flag is set,
79-
// this means the txindex from a previous version is valid and in sync with
80-
// the chain tip. The first step of the migration is to unset the flag and
81-
// write the chain hash to a separate key, DB_TXINDEX_BLOCK. After that, the
82-
// index entries are copied over in batches to the new database. Finally,
83-
// DB_TXINDEX_BLOCK is erased from the old database and the block hash is
84-
// written to the new database.
85-
//
86-
// Unsetting the boolean flag ensures that if the node is downgraded to a
87-
// previous version, it will not see a corrupted, partially migrated index
88-
// -- it will see that the txindex is disabled. When the node is upgraded
89-
// again, the migration will pick up where it left off and sync to the block
90-
// with hash DB_TXINDEX_BLOCK.
91-
bool f_legacy_flag = false;
92-
block_tree_db.ReadFlag("txindex", f_legacy_flag);
93-
if (f_legacy_flag) {
94-
if (!block_tree_db.Write(DB_TXINDEX_BLOCK, best_locator)) {
95-
return error("%s: cannot write block indicator", __func__);
96-
}
97-
if (!block_tree_db.WriteFlag("txindex", false)) {
98-
return error("%s: cannot write block index db flag", __func__);
99-
}
100-
}
101-
102-
CBlockLocator locator;
103-
if (!block_tree_db.Read(DB_TXINDEX_BLOCK, locator)) {
104-
return true;
105-
}
106-
107-
int64_t count = 0;
108-
LogPrintf("Upgrading txindex database... [0%%]\n");
109-
uiInterface.ShowProgress(_("Upgrading txindex database").translated, 0, true);
110-
int report_done = 0;
111-
const size_t batch_size = 1 << 24; // 16 MiB
112-
113-
CDBBatch batch_newdb(*this);
114-
CDBBatch batch_olddb(block_tree_db);
115-
116-
std::pair<uint8_t, uint256> key;
117-
std::pair<uint8_t, uint256> begin_key{DB_TXINDEX, uint256()};
118-
std::pair<uint8_t, uint256> prev_key = begin_key;
119-
120-
bool interrupted = false;
121-
std::unique_ptr<CDBIterator> cursor(block_tree_db.NewIterator());
122-
for (cursor->Seek(begin_key); cursor->Valid(); cursor->Next()) {
123-
if (ShutdownRequested()) {
124-
interrupted = true;
125-
break;
126-
}
127-
128-
if (!cursor->GetKey(key)) {
129-
return error("%s: cannot get key from valid cursor", __func__);
130-
}
131-
if (key.first != DB_TXINDEX) {
132-
break;
133-
}
134-
135-
// Log progress every 10%.
136-
if (++count % 256 == 0) {
137-
// Since txids are uniformly random and traversed in increasing order, the high 16 bits
138-
// of the hash can be used to estimate the current progress.
139-
const uint256& txid = key.second;
140-
uint32_t high_nibble =
141-
(static_cast<uint32_t>(*(txid.begin() + 0)) << 8) +
142-
(static_cast<uint32_t>(*(txid.begin() + 1)) << 0);
143-
int percentage_done = (int)(high_nibble * 100.0 / 65536.0 + 0.5);
144-
145-
uiInterface.ShowProgress(_("Upgrading txindex database").translated, percentage_done, true);
146-
if (report_done < percentage_done/10) {
147-
LogPrintf("Upgrading txindex database... [%d%%]\n", percentage_done);
148-
report_done = percentage_done/10;
149-
}
150-
}
151-
152-
CDiskTxPos value;
153-
if (!cursor->GetValue(value)) {
154-
return error("%s: cannot parse txindex record", __func__);
155-
}
156-
batch_newdb.Write(key, value);
157-
batch_olddb.Erase(key);
158-
159-
if (batch_newdb.SizeEstimate() > batch_size || batch_olddb.SizeEstimate() > batch_size) {
160-
// NOTE: it's OK to delete the key pointed at by the current DB cursor while iterating
161-
// because LevelDB iterators are guaranteed to provide a consistent view of the
162-
// underlying data, like a lightweight snapshot.
163-
WriteTxIndexMigrationBatches(*this, block_tree_db,
164-
batch_newdb, batch_olddb,
165-
prev_key, key);
166-
prev_key = key;
167-
}
168-
}
169-
170-
// If these final DB batches complete the migration, write the best block
171-
// hash marker to the new database and delete from the old one. This signals
172-
// that the former is fully caught up to that point in the blockchain and
173-
// that all txindex entries have been removed from the latter.
174-
if (!interrupted) {
175-
batch_olddb.Erase(DB_TXINDEX_BLOCK);
176-
batch_newdb.Write(DB_BEST_BLOCK, locator);
177-
}
178-
179-
WriteTxIndexMigrationBatches(*this, block_tree_db,
180-
batch_newdb, batch_olddb,
181-
begin_key, key);
182-
183-
if (interrupted) {
184-
LogPrintf("[CANCELLED].\n");
185-
return false;
186-
}
187-
188-
uiInterface.ShowProgress("", 100, false);
189-
190-
LogPrintf("[DONE].\n");
191-
return true;
192-
}
193-
19449
TxIndex::TxIndex(size_t n_cache_size, bool f_memory, bool f_wipe)
19550
: m_db(std::make_unique<TxIndex::DB>(n_cache_size, f_memory, f_wipe))
19651
{}
19752

19853
TxIndex::~TxIndex() {}
19954

200-
bool TxIndex::Init()
201-
{
202-
LOCK(cs_main);
203-
204-
// Attempt to migrate txindex from the old database to the new one. Even if
205-
// chain_tip is null, the node could be reindexing and we still want to
206-
// delete txindex records in the old database.
207-
if (!m_db->MigrateData(*m_chainstate->m_blockman.m_block_tree_db, m_chainstate->m_chain.GetLocator())) {
208-
return false;
209-
}
210-
211-
return BaseIndex::Init();
212-
}
213-
21455
bool TxIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
21556
{
21657
// Exclude genesis block transaction because outputs are not spendable.

src/index/txindex.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
#ifndef BITCOIN_INDEX_TXINDEX_H
66
#define BITCOIN_INDEX_TXINDEX_H
77

8-
#include <chain.h>
98
#include <index/base.h>
10-
#include <txdb.h>
119

1210
/**
1311
* TxIndex is used to look up transactions included in the blockchain by hash.
@@ -23,9 +21,6 @@ class TxIndex final : public BaseIndex
2321
const std::unique_ptr<DB> m_db;
2422

2523
protected:
26-
/// Override base class init to migrate from old database.
27-
bool Init() override;
28-
2924
bool WriteBlock(const CBlock& block, const CBlockIndex* pindex) override;
3025

3126
BaseIndex::DB& GetDB() const override;

src/init.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,6 +1567,10 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
15671567

15681568
// ********************************************************* Step 8: start indexers
15691569
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
1570+
if (const auto error{CheckLegacyTxindex(*Assert(chainman.m_blockman.m_block_tree_db))}) {
1571+
return InitError(*error);
1572+
}
1573+
15701574
g_txindex = std::make_unique<TxIndex>(nTxIndexCache, false, fReindex);
15711575
if (!g_txindex->Start(chainman.ActiveChainstate())) {
15721576
return false;

src/txdb.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <txdb.h>
77

8+
#include <chain.h>
89
#include <node/ui_interface.h>
910
#include <pow.h>
1011
#include <random.h>
@@ -27,6 +28,28 @@ static constexpr uint8_t DB_FLAG{'F'};
2728
static constexpr uint8_t DB_REINDEX_FLAG{'R'};
2829
static constexpr uint8_t DB_LAST_BLOCK{'l'};
2930

31+
// Keys used in previous version that might still be found in the DB:
32+
static constexpr uint8_t DB_TXINDEX_BLOCK{'T'};
33+
// uint8_t DB_TXINDEX{'t'}
34+
35+
std::optional<bilingual_str> CheckLegacyTxindex(CBlockTreeDB& block_tree_db)
36+
{
37+
CBlockLocator ignored{};
38+
if (block_tree_db.Read(DB_TXINDEX_BLOCK, ignored)) {
39+
return _("The -txindex upgrade started by a previous version can not be completed. Restart with the previous version or run a full -reindex.");
40+
}
41+
bool txindex_legacy_flag{false};
42+
block_tree_db.ReadFlag("txindex", txindex_legacy_flag);
43+
if (txindex_legacy_flag) {
44+
// Disable legacy txindex and warn once about occupied disk space
45+
if (!block_tree_db.WriteFlag("txindex", false)) {
46+
return Untranslated("Failed to write block index db flag 'txindex'='0'");
47+
}
48+
return _("The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.");
49+
}
50+
return std::nullopt;
51+
}
52+
3053
namespace {
3154

3255
struct CoinEntry {

src/txdb.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,20 @@
88

99
#include <coins.h>
1010
#include <dbwrapper.h>
11-
#include <chain.h>
12-
#include <primitives/block.h>
1311

1412
#include <memory>
13+
#include <optional>
1514
#include <string>
1615
#include <utility>
1716
#include <vector>
1817

18+
class CBlockFileInfo;
1919
class CBlockIndex;
20-
class CCoinsViewDBCursor;
2120
class uint256;
21+
namespace Consensus {
22+
struct Params;
23+
};
24+
struct bilingual_str;
2225

2326
//! -dbcache default (MiB)
2427
static const int64_t nDefaultDbCache = 450;
@@ -86,4 +89,6 @@ class CBlockTreeDB : public CDBWrapper
8689
bool LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex);
8790
};
8891

92+
std::optional<bilingual_str> CheckLegacyTxindex(CBlockTreeDB& block_tree_db);
93+
8994
#endif // BITCOIN_TXDB_H

src/validation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ bool CheckFinalTx(const CBlockIndex* active_chain_tip, const CTransaction &tx, i
192192

193193
// CheckFinalTx() uses active_chain_tip.Height()+1 to evaluate
194194
// nLockTime because when IsFinalTx() is called within
195-
// CBlock::AcceptBlock(), the height of the block *being*
195+
// AcceptBlock(), the height of the block *being*
196196
// evaluated is what is used. Thus if we want to know if a
197197
// transaction can be part of the *next* block, we need to call
198198
// IsFinalTx() with one more than active_chain_tip.Height().

src/validation.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
#endif
1212

1313
#include <amount.h>
14+
#include <arith_uint256.h>
1415
#include <attributes.h>
16+
#include <chain.h>
1517
#include <coins.h>
1618
#include <consensus/validation.h>
1719
#include <crypto/common.h> // for ReadLE64
@@ -21,10 +23,11 @@
2123
#include <policy/packages.h>
2224
#include <protocol.h> // For CMessageHeader::MessageStartChars
2325
#include <script/script_error.h>
26+
#include <serialize.h>
2427
#include <sync.h>
25-
#include <txmempool.h> // For CTxMemPool::cs
2628
#include <txdb.h>
27-
#include <serialize.h>
29+
#include <txmempool.h> // For CTxMemPool::cs
30+
#include <uint256.h>
2831
#include <util/check.h>
2932
#include <util/hasher.h>
3033
#include <util/translation.h>
@@ -42,7 +45,6 @@
4245

4346
class CChainState;
4447
class BlockValidationState;
45-
class CBlockIndex;
4648
class CBlockTreeDB;
4749
class CBlockUndo;
4850
class CChainParams;

0 commit comments

Comments
 (0)