Skip to content

Commit fa20f81

Browse files
author
MarcoFalke
committed
Remove txindex migration code
1 parent fae8786 commit fa20f81

File tree

5 files changed

+33
-168
lines changed

5 files changed

+33
-168
lines changed

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
@@ -1566,6 +1566,10 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
15661566

15671567
// ********************************************************* Step 8: start indexers
15681568
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
1569+
if (const auto error{CheckLegacyTxindex(*Assert(chainman.m_blockman.m_block_tree_db))}) {
1570+
return InitError(*error);
1571+
}
1572+
15691573
g_txindex = std::make_unique<TxIndex>(nTxIndexCache, false, fReindex);
15701574
if (!g_txindex->Start(chainman.ActiveChainstate())) {
15711575
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: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@
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>
@@ -22,6 +21,7 @@ class uint256;
2221
namespace Consensus {
2322
struct Params;
2423
};
24+
struct bilingual_str;
2525

2626
//! -dbcache default (MiB)
2727
static const int64_t nDefaultDbCache = 450;
@@ -89,4 +89,6 @@ class CBlockTreeDB : public CDBWrapper
8989
bool LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex);
9090
};
9191

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

0 commit comments

Comments
 (0)