Page MenuHomePhabricator

No OneTemporary

diff --git a/src/index/base.cpp b/src/index/base.cpp
index 08a3656e6..aae693e5a 100644
--- a/src/index/base.cpp
+++ b/src/index/base.cpp
@@ -24,6 +24,8 @@
#include <string>
#include <utility>
+using node::g_indexes_ready_to_sync;
+
constexpr uint8_t DB_BEST_BLOCK{'B'};
constexpr int64_t SYNC_LOG_INTERVAL = 30; // secon
@@ -83,7 +85,17 @@ bool BaseIndex::Init() {
if (locator.IsNull()) {
SetBestBlockIndex(nullptr);
} else {
- SetBestBlockIndex(m_chainstate->FindForkInGlobalIndex(locator));
+ // Setting the best block to the locator's top block. If it is not part
+ // of the best chain, we will rewind to the fork point during index sync
+ const CBlockIndex *locator_index{
+ m_chainstate->m_blockman.LookupBlockIndex(locator.vHave.at(0))};
+ if (!locator_index) {
+ return InitError(
+ strprintf(Untranslated("%s: best block of the index not found. "
+ "Please rebuild the index."),
+ GetName()));
+ }
+ SetBestBlockIndex(locator_index);
}
// Note: this will latch to true immediately if the user starts up with an
@@ -91,7 +103,10 @@ bool BaseIndex::Init() {
// happen solely via `BlockConnected` signals until, possibly, the next
// restart.
m_synced = m_best_block_index.load() == active_chain.Tip();
- if (!m_synced) {
+
+ // Skip pruning check if indexes are not ready to sync (because
+ // reindex-chainstate has wiped the chain).
+ if (!m_synced && g_indexes_ready_to_sync) {
bool prune_violation = false;
if (!m_best_block_index) {
// index is not built yet
@@ -154,6 +169,14 @@ static const CBlockIndex *NextSyncBlock(const CBlockIndex *pindex_prev,
}
void BaseIndex::ThreadSync() {
+ // Wait for a possible reindex-chainstate to finish until continuing
+ // with the index sync
+ while (!g_indexes_ready_to_sync) {
+ if (!m_interrupt.sleep_for(std::chrono::milliseconds(500))) {
+ return;
+ }
+ }
+
const CBlockIndex *pindex = m_best_block_index.load();
if (!m_synced) {
int64_t last_log_time = 0;
diff --git a/src/init.cpp b/src/init.cpp
index eb85ff13c..9427841f1 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -124,6 +124,7 @@ using node::CacheSizes;
using node::CalculateCacheSizes;
using node::DEFAULT_PERSIST_MEMPOOL;
using node::fReindex;
+using node::g_indexes_ready_to_sync;
using node::KernelNotifications;
using node::LoadChainstate;
using node::MempoolPath;
@@ -629,7 +630,8 @@ void SetupServerArgs(NodeContext &node) {
ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg(
"-reindex",
- "Rebuild chain state and block index from the blk*.dat files on disk",
+ "Rebuild chain state and block index from the blk*.dat files on disk."
+ " This will also rebuild active optional indexes.",
ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg(
"-settings=<file>",
@@ -2633,6 +2635,12 @@ bool AppInitMain(Config &config, RPCServer &rpcServer,
config.SetCashAddrEncoding(args.GetBoolArg("-usecashaddr", true));
// Step 8: load indexers
+
+ // If reindex-chainstate was specified, delay syncing indexes until
+ // ThreadImport has reindexed the chain
+ if (!fReindexChainState) {
+ g_indexes_ready_to_sync = true;
+ }
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
auto result{
WITH_LOCK(cs_main, return CheckLegacyTxindex(*Assert(
diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp
index b694a945b..803d590e9 100644
--- a/src/node/blockstorage.cpp
+++ b/src/node/blockstorage.cpp
@@ -29,6 +29,7 @@
namespace node {
std::atomic_bool fReindex(false);
+std::atomic_bool g_indexes_ready_to_sync{false};
std::vector<CBlockIndex *> BlockManager::GetAllBlockIndices() {
AssertLockHeld(cs_main);
@@ -1030,5 +1031,6 @@ void ThreadImport(ChainstateManager &chainman,
}
} // End scope of ImportingNow
chainman.ActiveChainstate().LoadMempool(mempool_path);
+ g_indexes_ready_to_sync = true;
}
} // namespace node
diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h
index e0d75b5e5..883473bcd 100644
--- a/src/node/blockstorage.h
+++ b/src/node/blockstorage.h
@@ -51,6 +51,7 @@ static constexpr size_t BLOCK_SERIALIZATION_HEADER_SIZE =
CMessageHeader::MESSAGE_START_SIZE + sizeof(unsigned int);
extern std::atomic_bool fReindex;
+extern std::atomic_bool g_indexes_ready_to_sync;
// Because validation code takes pointers to the map's CBlockIndex objects, if
// we ever switch to another associative container, we need to either use a
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index 1edc351f3..1ba3dcfb5 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -151,6 +151,7 @@ BasicTestingSetup::BasicTestingSetup(
noui_connect();
noui_connected = true;
}
+ node::g_indexes_ready_to_sync = true;
}
BasicTestingSetup::~BasicTestingSetup() {
diff --git a/test/functional/feature_coinstatsindex.py b/test/functional/feature_coinstatsindex.py
index 0ceb51ee9..bdb9d2cf6 100644
--- a/test/functional/feature_coinstatsindex.py
+++ b/test/functional/feature_coinstatsindex.py
@@ -25,7 +25,7 @@ class CoinStatsIndexTest(BitcoinTestFramework):
self.supports_cli = False
self.extra_args = [
[
- "-automaticunparking=1",
+ "-noparkdeepreorg",
],
[
"-coinstatsindex",
@@ -38,6 +38,7 @@ class CoinStatsIndexTest(BitcoinTestFramework):
self._test_use_index_option()
self._test_reorg_index()
self._test_index_rejects_hash_serialized()
+ self._test_init_index_after_reorg()
def block_sanity_check(self, block_info):
block_subsidy = 50_000_000
@@ -48,6 +49,11 @@ class CoinStatsIndexTest(BitcoinTestFramework):
+ block_info["unspendable"],
)
+ def sync_index_node(self):
+ self.wait_until(
+ lambda: self.nodes[1].getindexinfo()["coinstatsindex"]["synced"] is True
+ )
+
def _test_coin_stats_index(self):
node = self.nodes[0]
index_node = self.nodes[1]
@@ -239,6 +245,20 @@ class CoinStatsIndexTest(BitcoinTestFramework):
res10 = index_node.gettxoutsetinfo("muhash")
assert res8["txouts"] < res10["txouts"]
+ self.log.info("Test that the index works with -reindex")
+
+ self.restart_node(1, extra_args=["-coinstatsindex", "-reindex"])
+ self.sync_index_node()
+ res11 = index_node.gettxoutsetinfo("muhash")
+ assert_equal(res11, res10)
+
+ self.log.info("Test that the index works with -reindex-chainstate")
+
+ self.restart_node(1, extra_args=["-coinstatsindex", "-reindex-chainstate"])
+ self.sync_index_node()
+ res12 = index_node.gettxoutsetinfo("muhash")
+ assert_equal(res12, res10)
+
def _test_use_index_option(self):
self.log.info("Test use_index option for nodes running the index")
@@ -259,6 +279,7 @@ class CoinStatsIndexTest(BitcoinTestFramework):
index_node = self.nodes[1]
reorg_blocks = self.generatetoaddress(index_node, 2, getnewdestination()[2])
reorg_block = reorg_blocks[1]
+ self.sync_index_node()
res_invalid = index_node.gettxoutsetinfo("muhash")
index_node.invalidateblock(reorg_blocks[0])
assert_equal(index_node.gettxoutsetinfo("muhash")["height"], 110)
@@ -319,6 +340,30 @@ class CoinStatsIndexTest(BitcoinTestFramework):
use_index=use_index,
)
+ def _test_init_index_after_reorg(self):
+ self.log.info("Test a reorg while the index is deactivated")
+ index_node = self.nodes[1]
+ block = self.nodes[0].getbestblockhash()
+ self.generate(index_node, 2, sync_fun=self.no_op)
+ self.sync_index_node()
+
+ # Restart without index
+ self.restart_node(1, extra_args=[])
+ self.connect_nodes(0, 1)
+ index_node.invalidateblock(block)
+ self.generatetoaddress(index_node, 5, getnewdestination()[2])
+ res = index_node.gettxoutsetinfo(
+ hash_type="muhash", hash_or_height=None, use_index=False
+ )
+
+ # Restart with index that still has its best block on the old chain
+ self.restart_node(1, extra_args=self.extra_args[1])
+ self.sync_index_node()
+ res1 = index_node.gettxoutsetinfo(
+ hash_type="muhash", hash_or_height=None, use_index=True
+ )
+ assert_equal(res["muhash"], res1["muhash"])
+
if __name__ == "__main__":
CoinStatsIndexTest().main()

File Metadata

Mime Type
text/x-diff
Expires
Sun, Mar 2, 12:10 (1 d, 3 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5187793
Default Alt Text
(8 KB)

Event Timeline