Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ BITCOIN_CORE_H = \
i2p.h \
index/base.h \
index/blockfilterindex.h \
index/coinstatsindex.h \
index/disktxpos.h \
index/txindex.h \
indirectmap.h \
Expand Down Expand Up @@ -408,6 +409,7 @@ libbitcoin_server_a_SOURCES = \
i2p.cpp \
index/base.cpp \
index/blockfilterindex.cpp \
index/coinstatsindex.cpp \
index/txindex.cpp \
init.cpp \
governance/governance.cpp \
Expand Down
1 change: 1 addition & 0 deletions src/Makefile.test.include
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ BITCOIN_TESTS =\
test/cachemap_tests.cpp \
test/cachemultimap_tests.cpp \
test/coins_tests.cpp \
test/coinstatsindex_tests.cpp \
test/compilerbug_tests.cpp \
test/compress_tests.cpp \
test/crypto_tests.cpp \
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile.test_util.include
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ EXTRA_LIBRARIES += \

TEST_UTIL_H = \
test/util/blockfilter.h \
test/util/index.h \
test/util/logging.h \
test/util/mining.h \
test/util/net.h \
Expand All @@ -21,6 +22,7 @@ libtest_util_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAG
libtest_util_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libtest_util_a_SOURCES = \
test/util/blockfilter.cpp \
test/util/index.cpp \
test/util/logging.cpp \
test/util/mining.cpp \
test/util/net.cpp \
Expand Down
2 changes: 1 addition & 1 deletion src/bench/block_assemble.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ static void AssembleBlock(benchmark::Bench& bench)

for (const auto& txr : txs) {
TxValidationState state;
bool ret{::AcceptToMemoryPool(::ChainstateActive(), *test_setup.m_node.mempool, state, txr, false /* bypass_limits */, /* nAbsurdFee */ 0)};
bool ret{::AcceptToMemoryPool(test_setup.m_node.chainman->ActiveChainstate(), *test_setup.m_node.mempool, state, txr, false /* bypass_limits */, /* nAbsurdFee */ 0)};
assert(ret);
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/bench/duplicate_inputs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ static void DuplicateInputs(benchmark::Bench& bench)
CMutableTransaction coinbaseTx{};
CMutableTransaction naughtyTx{};

CBlockIndex* pindexPrev = ::ChainActive().Tip();
assert(std::addressof(::ChainActive()) == std::addressof(test_setup.m_node.chainman->ActiveChain()));
CBlockIndex* pindexPrev = test_setup.m_node.chainman->ActiveChain().Tip();
assert(pindexPrev != nullptr);
block.nBits = GetNextWorkRequired(pindexPrev, &block, chainparams.GetConsensus());
block.nNonce = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/muhash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,6 @@ MuHash3072& MuHash3072::Insert(Span<const unsigned char> in) noexcept {
}

MuHash3072& MuHash3072::Remove(Span<const unsigned char> in) noexcept {
m_numerator.Divide(ToNum3072(in));
m_denominator.Multiply(ToNum3072(in));
return *this;
}
48 changes: 27 additions & 21 deletions src/index/base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,33 +59,34 @@ bool BaseIndex::Init()
}

LOCK(cs_main);
CChain& active_chain = m_chainstate->m_chain;
if (locator.IsNull()) {
m_best_block_index = nullptr;
} else {
m_best_block_index = g_chainman.m_blockman.FindForkInGlobalIndex(::ChainActive(), locator);
m_best_block_index = m_chainstate->m_blockman.FindForkInGlobalIndex(active_chain, locator);
}
m_synced = m_best_block_index.load() == ::ChainActive().Tip();
m_synced = m_best_block_index.load() == active_chain.Tip();
if (!m_synced) {
bool prune_violation = false;
if (!m_best_block_index) {
// index is not built yet
// make sure we have all block data back to the genesis
const CBlockIndex* block = ::ChainActive().Tip();
const CBlockIndex* block = active_chain.Tip();
while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) {
block = block->pprev;
}
prune_violation = block != ::ChainActive().Genesis();
prune_violation = block != active_chain.Genesis();
}
// in case the index has a best block set and is not fully synced
// check if we have the required blocks to continue building the index
else {
const CBlockIndex* block_to_test = m_best_block_index.load();
if (!ChainActive().Contains(block_to_test)) {
if (!active_chain.Contains(block_to_test)) {
// if the bestblock is not part of the mainchain, find the fork
// and make sure we have all data down to the fork
block_to_test = ::ChainActive().FindFork(block_to_test);
block_to_test = active_chain.FindFork(block_to_test);
}
const CBlockIndex* block = ::ChainActive().Tip();
const CBlockIndex* block = active_chain.Tip();
prune_violation = true;
// check backwards from the tip if we have all block data until we reach the indexes bestblock
while (block_to_test && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) {
Expand All @@ -97,28 +98,26 @@ bool BaseIndex::Init()
}
}
if (prune_violation) {
// throw error and graceful shutdown if we can't build the index
FatalError("%s: %s best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)", __func__, GetName());
return false;
return InitError(strprintf(Untranslated("%s best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)"), GetName()));
}
}
return true;
}

static const CBlockIndex* NextSyncBlock(const CBlockIndex* pindex_prev) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
static const CBlockIndex* NextSyncBlock(const CBlockIndex* pindex_prev, CChain& chain) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
AssertLockHeld(cs_main);

if (!pindex_prev) {
return ::ChainActive().Genesis();
return chain.Genesis();
}

const CBlockIndex* pindex = ::ChainActive().Next(pindex_prev);
const CBlockIndex* pindex = chain.Next(pindex_prev);
if (pindex) {
return pindex;
}

return ::ChainActive().Next(::ChainActive().FindFork(pindex_prev));
return chain.Next(chain.FindFork(pindex_prev));
}

void BaseIndex::ThreadSync()
Expand All @@ -141,7 +140,7 @@ void BaseIndex::ThreadSync()

{
LOCK(cs_main);
const CBlockIndex* pindex_next = NextSyncBlock(pindex);
const CBlockIndex* pindex_next = NextSyncBlock(pindex, m_chainstate->m_chain);
if (!pindex_next) {
m_best_block_index = pindex;
m_synced = true;
Expand Down Expand Up @@ -204,7 +203,12 @@ bool BaseIndex::Commit()
bool BaseIndex::CommitInternal(CDBBatch& batch)
{
LOCK(cs_main);
GetDB().WriteBestBlock(batch, ::ChainActive().GetLocator(m_best_block_index));
// Don't commit anything if we haven't indexed any block yet
// (this could happen if init is interrupted).
if (m_best_block_index == nullptr) {
return false;
}
GetDB().WriteBestBlock(batch, m_chainstate->m_chain.GetLocator(m_best_block_index));
return true;
}

Expand Down Expand Up @@ -280,7 +284,7 @@ void BaseIndex::ChainStateFlushed(const CBlockLocator& locator)
const CBlockIndex* locator_tip_index;
{
LOCK(cs_main);
locator_tip_index = g_chainman.m_blockman.LookupBlockIndex(locator_tip_hash);
locator_tip_index = m_chainstate->m_blockman.LookupBlockIndex(locator_tip_hash);
}

if (!locator_tip_index) {
Expand Down Expand Up @@ -321,7 +325,7 @@ bool BaseIndex::BlockUntilSyncedToCurrentChain() const
// Skip the queue-draining stuff if we know we're caught up with
// ::ChainActive().Tip().
LOCK(cs_main);
const CBlockIndex* chain_tip = ::ChainActive().Tip();
const CBlockIndex* chain_tip = m_chainstate->m_chain.Tip();
const CBlockIndex* best_block_index = m_best_block_index.load();
if (best_block_index->GetAncestor(chain_tip->nHeight) == chain_tip) {
return true;
Expand All @@ -338,18 +342,20 @@ void BaseIndex::Interrupt()
m_interrupt();
}

void BaseIndex::Start()
bool BaseIndex::Start(CChainState& active_chainstate)
{
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
m_chainstate = &active_chainstate;
// Need to register this ValidationInterface before running Init(), so that
// callbacks are not missed if Init sets m_synced to true.
RegisterValidationInterface(this);
if (!Init()) {
FatalError("%s: %s failed to initialize", __func__, GetName());
return;
return false;
}

m_thread_sync = std::thread(&TraceThread<std::function<void()>>, GetName(),
std::bind(&BaseIndex::ThreadSync, this));
return true;
}

void BaseIndex::Stop()
Expand Down
14 changes: 9 additions & 5 deletions src/index/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <validationinterface.h>

class CBlockIndex;
class CChainState;

struct IndexSummary {
std::string name;
Expand Down Expand Up @@ -40,10 +41,10 @@ class BaseIndex : public CValidationInterface
DB(const fs::path& path, size_t n_cache_size,
bool f_memory = false, bool f_wipe = false, bool f_obfuscate = false);

/// Read block locator of the chain that the txindex is in sync with.
/// Read block locator of the chain that the index is in sync with.
bool ReadBestBlock(CBlockLocator& locator) const;

/// Write block locator of the chain that the txindex is in sync with.
/// Write block locator of the chain that the index is in sync with.
void WriteBestBlock(CDBBatch& batch, const CBlockLocator& locator);
};

Expand Down Expand Up @@ -75,14 +76,17 @@ class BaseIndex : public CValidationInterface
/// to a chain reorganization), the index must halt until Commit succeeds or else it could end up
/// getting corrupted.
bool Commit();

protected:
CChainState* m_chainstate{nullptr};

void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) override;

void ChainStateFlushed(const CBlockLocator& locator) override;

const CBlockIndex* CurrentIndex() { return m_best_block_index.load(); };

/// Initialize internal state from the database and block index.
virtual bool Init();
[[nodiscard]] virtual bool Init();

/// Write update index entries for a newly connected block.
virtual bool WriteBlock(const CBlock& block, const CBlockIndex* pindex) { return true; }
Expand Down Expand Up @@ -115,7 +119,7 @@ class BaseIndex : public CValidationInterface

/// Start initializes the sync state and registers the instance as a
/// ValidationInterface so that it stays in sync with blockchain updates.
void Start();
[[nodiscard]] bool Start(CChainState& active_chainstate);

/// Stops the instance from staying in sync with blockchain updates.
void Stop();
Expand Down
Loading