diff --git a/src/bench/rpc_blockchain.cpp b/src/bench/rpc_blockchain.cpp index c8886a4c237a..f49520abe191 100644 --- a/src/bench/rpc_blockchain.cpp +++ b/src/bench/rpc_blockchain.cpp @@ -28,8 +28,8 @@ struct TestBlockAndIndex { stream >> block; - blockHash = block.GetHash(); - blockindex.phashBlock = &blockHash; + CBlockIndex blockindex; + blockindex.m_hash_block = block.GetHash(); blockindex.nBits = 403014710; } }; diff --git a/src/chain.h b/src/chain.h index 84a3a4e1e75d..741065b9e211 100644 --- a/src/chain.h +++ b/src/chain.h @@ -137,8 +137,8 @@ enum BlockStatus: uint32_t { class CBlockIndex { public: - //! pointer to the hash of the block, if any. Memory is owned by this CBlockIndex - const uint256* phashBlock{nullptr}; + //! hash of the block. m_hash_block.IsNull() if there is not yet a hash + uint256 m_hash_block; //! pointer to the index of the predecessor of this block CBlockIndex* pprev{nullptr}; @@ -243,9 +243,9 @@ class CBlockIndex return block; } - uint256 GetBlockHash() const + const uint256& GetBlockHash() const { - return *phashBlock; + return m_hash_block; } /** diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index f8a4d4ccab05..b6ff4dfb63cc 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1578,10 +1578,10 @@ static RPCHelpMan getchaintips() std::set setOrphans; std::set setPrevs; - for (const std::pair& item : chainman.BlockIndex()) { - if (!active_chain.Contains(item.second)) { - setOrphans.insert(item.second); - setPrevs.insert(item.second->pprev); + for (CBlockIndex* pindex : chainman.BlockIndex()) { + if (!chainman.ActiveChain().Contains(pindex)) { + setOrphans.insert(pindex); + setPrevs.insert(pindex->pprev); } } @@ -1599,7 +1599,7 @@ static RPCHelpMan getchaintips() for (const CBlockIndex* block : setTips) { UniValue obj(UniValue::VOBJ); obj.pushKV("height", block->nHeight); - obj.pushKV("hash", block->phashBlock->GetHex()); + obj.pushKV("hash", block->m_hash_block.GetHex()); const int branchLen = block->nHeight - active_chain.FindFork(block)->nHeight; obj.pushKV("branchlen", branchLen); diff --git a/src/test/fuzz/banman.cpp b/src/test/fuzz/banman.cpp index 85a2ac990caf..1986b5e4c875 100644 --- a/src/test/fuzz/banman.cpp +++ b/src/test/fuzz/banman.cpp @@ -109,8 +109,9 @@ FUZZ_TARGET_INIT(banman, initialize_banman) BanMan ban_man_read{banlist_file, /* client_interface */ nullptr, /* default_ban_time */ 0}; banmap_t banmap_read; ban_man_read.GetBanned(banmap_read); - // Temporarily disabled to allow the remainder of the fuzz test to run while a fix is being worked on: - // assert(banmap == banmap_read); + // Assert temporarily disabled to allow the remainder of the fuzz test to run while a + // fix is being worked on. See https://github.com/bitcoin/bitcoin/pull/22517 + (void)(banmap == banmap_read); } } fs::remove(banlist_file.string() + ".dat"); diff --git a/src/test/fuzz/chain.cpp b/src/test/fuzz/chain.cpp index 9f7074b42369..9442ac9a8e68 100644 --- a/src/test/fuzz/chain.cpp +++ b/src/test/fuzz/chain.cpp @@ -19,8 +19,6 @@ FUZZ_TARGET(chain) return; } - const uint256 zero{}; - disk_block_index->phashBlock = &zero; (void)disk_block_index->GetBlockHash(); (void)disk_block_index->GetBlockPos(); (void)disk_block_index->GetBlockTime(); @@ -59,7 +57,6 @@ FUZZ_TARGET(chain) } CBlockIndex block_index{block_header}; - block_index.phashBlock = &zero; (void)block_index.GetBlockHash(); (void)block_index.ToString(); } diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index e20c5e4e8f14..c42e9a2042c1 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -369,7 +369,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) while (m_node.chainman->ActiveChain().Tip()->nHeight < 209999) { CBlockIndex* prev = m_node.chainman->ActiveChain().Tip(); CBlockIndex* next = new CBlockIndex(); - next->phashBlock = new uint256(InsecureRand256()); + next->m_hash_block = uint256(InsecureRand256()); m_node.chainman->ActiveChainstate().CoinsTip().SetBestBlock(next->GetBlockHash()); next->pprev = prev; next->nHeight = prev->nHeight + 1; @@ -381,7 +381,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) while (m_node.chainman->ActiveChain().Tip()->nHeight < 210000) { CBlockIndex* prev = m_node.chainman->ActiveChain().Tip(); CBlockIndex* next = new CBlockIndex(); - next->phashBlock = new uint256(InsecureRand256()); + next->m_hash_block = uint256(InsecureRand256()); m_node.chainman->ActiveChainstate().CoinsTip().SetBestBlock(next->GetBlockHash()); next->pprev = prev; next->nHeight = prev->nHeight + 1; @@ -409,11 +409,11 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) m_node.mempool->clear(); // Delete the dummy blocks again. + while (m_node.chainman->ActiveChain().Tip()->nHeight > nHeight) { CBlockIndex* del = m_node.chainman->ActiveChain().Tip(); m_node.chainman->ActiveChain().SetTip(del->pprev); m_node.chainman->ActiveChainstate().CoinsTip().SetBestBlock(del->pprev->GetBlockHash()); - delete del->phashBlock; delete del; } diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index 7ede79279f09..ad86c288e209 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(getlocator_test) vHashMain[i] = ArithToUint256(i); // Set the hash equal to the height, so we can quickly check the distances. vBlocksMain[i].nHeight = i; vBlocksMain[i].pprev = i ? &vBlocksMain[i - 1] : nullptr; - vBlocksMain[i].phashBlock = &vHashMain[i]; + vBlocksMain[i].m_hash_block = vHashMain[i]; vBlocksMain[i].BuildSkip(); BOOST_CHECK_EQUAL((int)UintToArith256(vBlocksMain[i].GetBlockHash()).GetLow64(), vBlocksMain[i].nHeight); BOOST_CHECK(vBlocksMain[i].pprev == nullptr || vBlocksMain[i].nHeight == vBlocksMain[i].pprev->nHeight + 1); @@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(getlocator_test) vHashSide[i] = ArithToUint256(i + 50000 + (arith_uint256(1) << 128)); // Add 1<<128 to the hashes, so GetLow64() still returns the height. vBlocksSide[i].nHeight = i + 50000; vBlocksSide[i].pprev = i ? &vBlocksSide[i - 1] : (vBlocksMain.data()+49999); - vBlocksSide[i].phashBlock = &vHashSide[i]; + vBlocksSide[i].m_hash_block = vHashSide[i]; vBlocksSide[i].BuildSkip(); BOOST_CHECK_EQUAL((int)UintToArith256(vBlocksSide[i].GetBlockHash()).GetLow64(), vBlocksSide[i].nHeight); BOOST_CHECK(vBlocksSide[i].pprev == nullptr || vBlocksSide[i].nHeight == vBlocksSide[i].pprev->nHeight + 1); @@ -106,7 +106,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test) vHashMain[i] = ArithToUint256(i); // Set the hash equal to the height vBlocksMain[i].nHeight = i; vBlocksMain[i].pprev = i ? &vBlocksMain[i - 1] : nullptr; - vBlocksMain[i].phashBlock = &vHashMain[i]; + vBlocksMain[i].m_hash_block = vHashMain[i]; vBlocksMain[i].BuildSkip(); if (i < 10) { vBlocksMain[i].nTime = i; diff --git a/src/util/hasher.h b/src/util/hasher.h index fa2fea30d82f..3f1293d5e3aa 100644 --- a/src/util/hasher.h +++ b/src/util/hasher.h @@ -75,13 +75,21 @@ class SignatureCacheHasher return u; } }; - +template struct BlockHasher { // this used to call `GetCheapHash()` in uint256, which was later moved; the // cheap hash function simply calls ReadLE64() however, so the end result is // identical - size_t operator()(const uint256& hash) const { return ReadLE64(hash.begin()); } + mutable T mock; + BlockHasher() : mock() {}; + size_t operator()(T* const& ptr) const { return ReadLE64(ptr->GetBlockHash().begin()); } + // Helper for querying by hash + // e.g., map.find(map.hash_function()(h)) + T* operator()(const uint256& hash) { + mock.m_hash_block = hash; + return &mock; + } }; class SaltedSipHasher diff --git a/src/validation.cpp b/src/validation.cpp index 20d641bf4008..aef4413c1f03 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -148,14 +148,15 @@ void FlushBlockFile(bool fFinalize = false, bool finalize_undo = false); CBlockIndex* BlockManager::LookupBlockIndex(const uint256& hash) const { AssertLockHeld(cs_main); - BlockMap::const_iterator it = m_block_index.find(hash); - return it == m_block_index.end() ? nullptr : it->second; + BlockMap::const_iterator it = m_block_index.find( m_block_index.hash_function()(hash)); + return it == m_block_index.end() ? nullptr : *it; + } CBlockIndex* BlockManager::FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator) { AssertLockHeld(cs_main); - + // Find the latest block common to locator and chain - we expect that // locator.vHave is sorted descending by height. for (const uint256& hash : locator.vHave) { @@ -1648,8 +1649,8 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consens // mainnet and testnet), so for simplicity, always leave P2SH // on except for the one violating block. if (consensusparams.BIP16Exception.IsNull() || // no bip16 exception on this chain - pindex->phashBlock == nullptr || // this is a new candidate block, eg from TestBlockValidity() - *pindex->phashBlock != consensusparams.BIP16Exception) // this block isn't the historical exception + pindex->m_hash_block.IsNull() || // this is a new candidate block, eg from TestBlockValidity() + pindex->m_hash_block != consensusparams.BIP16Exception) // this block isn't the historical exception { // Enforce WITNESS rules whenever P2SH is in effect flags |= SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS; @@ -1702,7 +1703,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, { AssertLockHeld(cs_main); assert(pindex); - assert(*pindex->phashBlock == block.GetHash()); + assert(pindex->m_hash_block == block.GetHash()); int64_t nTimeStart = GetTimeMicros(); // Check it again in case a previous version let a bad block in @@ -1749,9 +1750,10 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, // relative to a piece of software is an objective fact these defaults can be easily reviewed. // This setting doesn't force the selection of any particular chain but makes validating some faster by // effectively caching the result of part of the verification. - BlockMap::const_iterator it = m_blockman.m_block_index.find(hashAssumeValid); + // + BlockMap::const_iterator it = m_blockman.m_block_index.find(m_blockman.m_block_index.hash_function()(hashAssumeValid)); if (it != m_blockman.m_block_index.end()) { - if (it->second->GetAncestor(pindex->nHeight) == pindex && + if ((*it)->GetAncestor(pindex->nHeight) == pindex && pindexBestHeader->GetAncestor(pindex->nHeight) == pindex && pindexBestHeader->nChainWork >= nMinimumChainWork) { // This block is a member of the assumed verified chain and an ancestor of the best header. @@ -1988,7 +1990,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, setDirtyBlockIndex.insert(pindex); } - assert(pindex->phashBlock); + assert(!pindex->m_hash_block.IsNull()); // add this block to the view's block chain view.SetBestBlock(pindex->GetBlockHash()); @@ -2779,8 +2781,7 @@ bool CChainState::InvalidateBlock(BlockValidationState& state, CBlockIndex* pind { LOCK(cs_main); - for (const auto& entry : m_blockman.m_block_index) { - CBlockIndex *candidate = entry.second; + for (CBlockIndex* candidate : m_blockman.m_block_index) { // We don't need to put anything in our active chain into the // multimap, because those candidates will be found and considered // as we disconnect. @@ -2879,8 +2880,8 @@ bool CChainState::InvalidateBlock(BlockValidationState& state, CBlockIndex* pind // to setBlockIndexCandidates. BlockMap::iterator it = m_blockman.m_block_index.begin(); while (it != m_blockman.m_block_index.end()) { - if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->HaveTxsDownloaded() && !setBlockIndexCandidates.value_comp()(it->second, m_chain.Tip())) { - setBlockIndexCandidates.insert(it->second); + if ((*it)->IsValid(BLOCK_VALID_TRANSACTIONS) && (*it)->HaveTxsDownloaded() && !setBlockIndexCandidates.value_comp()(*it, m_chain.Tip())) { + setBlockIndexCandidates.insert(*it); } it++; } @@ -2903,17 +2904,18 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) { // Remove the invalidity flag from this block and all its descendants. BlockMap::iterator it = m_blockman.m_block_index.begin(); while (it != m_blockman.m_block_index.end()) { - if (!it->second->IsValid() && it->second->GetAncestor(nHeight) == pindex) { - it->second->nStatus &= ~BLOCK_FAILED_MASK; - setDirtyBlockIndex.insert(it->second); - if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->HaveTxsDownloaded() && setBlockIndexCandidates.value_comp()(m_chain.Tip(), it->second)) { - setBlockIndexCandidates.insert(it->second); + CBlockIndex& block = **it; + if (!block.IsValid() && block.GetAncestor(nHeight) == pindex) { + block.nStatus &= ~BLOCK_FAILED_MASK; + setDirtyBlockIndex.insert(&block); + if (block.IsValid(BLOCK_VALID_TRANSACTIONS) && block.HaveTxsDownloaded() && setBlockIndexCandidates.value_comp()(m_chain.Tip(), &block)) { + setBlockIndexCandidates.insert(&block); } - if (it->second == pindexBestInvalid) { + if (&block == pindexBestInvalid) { // Reset invalid block marker if it was pointing to one of those. pindexBestInvalid = nullptr; } - m_blockman.m_failed_blocks.erase(it->second); + m_blockman.m_failed_blocks.erase(&block); } it++; } @@ -2935,9 +2937,9 @@ CBlockIndex* BlockManager::AddToBlockIndex(const CBlockHeader& block) // Check for duplicate uint256 hash = block.GetHash(); - BlockMap::iterator it = m_block_index.find(hash); + BlockMap::iterator it = m_block_index.find(m_block_index.hash_function()(hash)); if (it != m_block_index.end()) - return it->second; + return *it; // Construct new block index object CBlockIndex* pindexNew = new CBlockIndex(block); @@ -2945,12 +2947,12 @@ CBlockIndex* BlockManager::AddToBlockIndex(const CBlockHeader& block) // to avoid miners withholding blocks but broadcasting headers, to get a // competitive advantage. pindexNew->nSequenceId = 0; - BlockMap::iterator mi = m_block_index.insert(std::make_pair(hash, pindexNew)).first; - pindexNew->phashBlock = &((*mi).first); - BlockMap::iterator miPrev = m_block_index.find(block.hashPrevBlock); + pindexNew->m_hash_block = hash; + m_block_index.insert(pindexNew); + BlockMap::iterator miPrev = m_block_index.find(m_block_index.hash_function()(block.hashPrevBlock)); if (miPrev != m_block_index.end()) { - pindexNew->pprev = (*miPrev).second; + pindexNew->pprev = *miPrev; pindexNew->nHeight = pindexNew->pprev->nHeight + 1; pindexNew->BuildSkip(); } @@ -3292,11 +3294,12 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationS AssertLockHeld(cs_main); // Check for duplicate uint256 hash = block.GetHash(); - BlockMap::iterator miSelf = m_block_index.find(hash); + BlockMap::iterator miSelf = m_block_index.find(m_block_index.hash_function()(hash)); + CBlockIndex *pindex = nullptr; if (hash != chainparams.GetConsensus().hashGenesisBlock) { if (miSelf != m_block_index.end()) { // Block header is already known. - CBlockIndex* pindex = miSelf->second; + pindex = *miSelf; if (ppindex) *ppindex = pindex; if (pindex->nStatus & BLOCK_FAILED_MASK) { @@ -3313,12 +3316,12 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationS // Get prev block index CBlockIndex* pindexPrev = nullptr; - BlockMap::iterator mi = m_block_index.find(block.hashPrevBlock); + BlockMap::iterator mi = m_block_index.find(m_block_index.hash_function()(block.hashPrevBlock)); if (mi == m_block_index.end()) { LogPrintf("ERROR: %s: prev block not found\n", __func__); return state.Invalid(BlockValidationResult::BLOCK_MISSING_PREV, "prev-blk-not-found"); } - pindexPrev = (*mi).second; + pindexPrev = *mi; if (pindexPrev->nStatus & BLOCK_FAILED_MASK) { LogPrintf("ERROR: %s: prev block invalid\n", __func__); return state.Invalid(BlockValidationResult::BLOCK_INVALID_PREV, "bad-prevblk"); @@ -3365,7 +3368,7 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationS } } } - CBlockIndex* pindex = AddToBlockIndex(block); + pindex = AddToBlockIndex(block); if (ppindex) *ppindex = pindex; @@ -3538,7 +3541,7 @@ bool TestBlockValidity(BlockValidationState& state, CBlockIndex indexDummy(block); indexDummy.pprev = pindexPrev; indexDummy.nHeight = pindexPrev->nHeight + 1; - indexDummy.phashBlock = &block_hash; + indexDummy.m_hash_block = block_hash; // NOTE: CheckBlockHeader is called by CheckBlock if (!ContextualCheckBlockHeader(block, state, chainstate.m_blockman, chainparams, pindexPrev, GetAdjustedTime())) @@ -3564,8 +3567,9 @@ void BlockManager::PruneOneBlockFile(const int fileNumber) AssertLockHeld(cs_main); LOCK(cs_LastBlockFile); - for (const auto& entry : m_block_index) { - CBlockIndex* pindex = entry.second; + + + for (CBlockIndex* pindex : m_block_index) { if (pindex->nFile == fileNumber) { pindex->nStatus &= ~BLOCK_HAVE_DATA; pindex->nStatus &= ~BLOCK_HAVE_UNDO; @@ -3693,32 +3697,48 @@ CBlockIndex * BlockManager::InsertBlockIndex(const uint256& hash) return nullptr; // Return existing - BlockMap::iterator mi = m_block_index.find(hash); + BlockMap::iterator mi = m_block_index.find(m_block_index.hash_function()(hash)); if (mi != m_block_index.end()) - return (*mi).second; + return *mi; // Create new CBlockIndex* pindexNew = new CBlockIndex(); - mi = m_block_index.insert(std::make_pair(hash, pindexNew)).first; - pindexNew->phashBlock = &((*mi).first); + pindexNew->m_hash_block = hash; + mi = m_block_index.insert(pindexNew).first; return pindexNew; } +/* +struct unordered_node : private CBlockIndex +{ +private: + void* ptr; +}; */ +CBlockIndex* x; +static inline size_t DynamicUsage(const std::unordered_set , BlockEqual>& s) +{ + return memusage::MallocUsage(sizeof(x)) * s.size() + memusage::MallocUsage(sizeof(void*) * s.bucket_count()); +} bool BlockManager::LoadBlockIndex( const Consensus::Params& consensus_params, std::set& block_index_candidates) { + auto start = std::chrono::high_resolution_clock::now(); if (!m_block_tree_db->LoadBlockIndexGuts(consensus_params, [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); })) { return false; } + auto stop = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(stop - start); + LogPrintf("shoryak was here"); + LogPrintf(" %s Duration for loading blocks is %s and memory usage by m_block_index is %0.1fMiB " , __func__ std::to_string(duration.count()) ,DynamicUsage(m_block_index) * (1.0 / (1<<20))); + // Calculate nChainWork std::vector > vSortedByHeight; vSortedByHeight.reserve(m_block_index.size()); - for (const std::pair& item : m_block_index) + for (CBlockIndex* pindex : m_block_index) { - CBlockIndex* pindex = item.second; vSortedByHeight.push_back(std::make_pair(pindex->nHeight, pindex)); } sort(vSortedByHeight.begin(), vSortedByHeight.end()); @@ -3764,8 +3784,8 @@ void BlockManager::Unload() { m_failed_blocks.clear(); m_blocks_unlinked.clear(); - for (const BlockMap::value_type& entry : m_block_index) { - delete entry.second; + for (CBlockIndex* pindex : m_block_index) { + delete pindex; } m_block_index.clear(); @@ -3773,12 +3793,19 @@ void BlockManager::Unload() { bool BlockManager::LoadBlockIndexDB(std::set& setBlockIndexCandidates) { + auto start = std::chrono::high_resolution_clock::now(); if (!LoadBlockIndex( ::Params().GetConsensus(), setBlockIndexCandidates)) { return false; } + auto stop = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(stop - start); + LogPrintf("shoryak was here"); + LogPrintf(" %s Duration for loading blocks is %s and memory usage by m_block_index is %0.1fMiB " , __func__ std::to_string(duration.count()) ,DynamicUsage(m_block_index) * (1.0 / (1<<20))); + + // Load block file info m_block_tree_db->ReadLastBlockFile(nLastBlockFile); vinfoBlockFile.resize(nLastBlockFile + 1); @@ -3799,8 +3826,8 @@ bool BlockManager::LoadBlockIndexDB(std::set setBlkDataFiles; - for (const std::pair& item : m_block_index) { - CBlockIndex* pindex = item.second; + for (CBlockIndex* pindex : m_block_index) { + if (pindex->nStatus & BLOCK_HAVE_DATA) { setBlkDataFiles.insert(pindex->nFile); } @@ -4022,16 +4049,18 @@ bool CChainState::ReplayBlocks() const CBlockIndex* pindexNew; // New tip during the interrupted flush. const CBlockIndex* pindexFork = nullptr; // Latest block common to both the old and the new tip. - if (m_blockman.m_block_index.count(hashHeads[0]) == 0) { + auto mi = m_blockman.m_block_index.find(m_blockman.m_block_index.hash_function()(hashHeads[0])); + if (mi == m_blockman.m_block_index.end()) { return error("ReplayBlocks(): reorganization to unknown block requested"); } - pindexNew = m_blockman.m_block_index[hashHeads[0]]; + pindexNew = *mi; if (!hashHeads[1].IsNull()) { // The old tip is allowed to be 0, indicating it's the first flush. - if (m_blockman.m_block_index.count(hashHeads[1]) == 0) { + auto mi2 = m_blockman.m_block_index.find(m_blockman.m_block_index.hash_function()(hashHeads[1])); + if (mi2 == m_blockman.m_block_index.end()) { return error("ReplayBlocks(): reorganization from unknown block requested"); } - pindexOld = m_blockman.m_block_index[hashHeads[1]]; + pindexOld = *mi2; pindexFork = LastCommonAncestor(pindexOld, pindexNew); assert(pindexFork != nullptr); } @@ -4075,6 +4104,7 @@ bool CChainState::NeedsRedownload() const { AssertLockHeld(cs_main); + // At and above m_params.SegwitHeight, segwit consensus rules must be validated CBlockIndex* block{m_chain.Tip()}; @@ -4146,7 +4176,10 @@ bool CChainState::LoadGenesisBlock() // m_blockman.m_block_index. Note that we can't use m_chain here, since it is // set based on the coins db, not the block index db, which is the only // thing loaded at this point. - if (m_blockman.m_block_index.count(m_params.GenesisBlock().GetHash())) + + + if (m_blockman.m_block_index.count(m_blockman.m_block_index.hash_function()(m_params.GenesisBlock().GetHash()))) + return true; try { @@ -4299,8 +4332,8 @@ void CChainState::CheckBlockIndex() // Build forward-pointing map of the entire block tree. std::multimap forward; - for (const std::pair& entry : m_blockman.m_block_index) { - forward.insert(std::make_pair(entry.second->pprev, entry.second)); + for (CBlockIndex* pindex : m_blockman.m_block_index) { + forward.insert(std::make_pair(pindex->pprev, pindex)); } assert(forward.size() == m_blockman.m_block_index.size()); @@ -4674,7 +4707,7 @@ std::optional ChainstateManager::SnapshotBlockhash() const { LOCK(::cs_main); if (m_active_chainstate && m_active_chainstate->m_from_snapshot_blockhash) { - // If a snapshot chainstate exists, it will always be our active. + return m_active_chainstate->m_from_snapshot_blockhash; } return std::nullopt; diff --git a/src/validation.h b/src/validation.h index d3e4f3b98322..ce686164e694 100644 --- a/src/validation.h +++ b/src/validation.h @@ -98,6 +98,11 @@ static const unsigned int DEFAULT_CHECKLEVEL = 3; // Setting the target to >= 550 MiB will make it likely we can respect the target. static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024; +struct BlockEqual +{ + bool operator()(CBlockIndex* const& ptr, CBlockIndex* const& ptr2) const { return ptr->GetBlockHash() == ptr2->GetBlockHash(); } +}; + /** Current sync state passed to tip changed callbacks. */ enum class SynchronizationState { INIT_REINDEX, @@ -106,7 +111,10 @@ enum class SynchronizationState { }; extern RecursiveMutex cs_main; -typedef std::unordered_map BlockMap; + +extern CBlockPolicyEstimator feeEstimator; +extern CTxMemPool mempool; +typedef std::unordered_set, BlockEqual> BlockMap; extern Mutex g_best_block_mutex; extern std::condition_variable g_best_block_cv; extern uint256 g_best_block; diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 75a08b6f74ca..3eb31e03baca 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -339,13 +339,13 @@ static int64_t AddTx(ChainstateManager& chainman, CWallet& wallet, uint32_t lock CBlockIndex* block = nullptr; if (blockTime > 0) { LOCK(cs_main); - auto inserted = chainman.BlockIndex().emplace(GetRandHash(), new CBlockIndex); + auto pblock = new CBlockIndex; + pblock->m_hash_block = GetRandHash(); + auto inserted = chainman.BlockIndex().emplace(pblock); assert(inserted.second); - const uint256& hash = inserted.first->first; - block = inserted.first->second; + block = *inserted.first; block->nTime = blockTime; - block->phashBlock = &hash; - confirm = {CWalletTx::Status::CONFIRMED, block->nHeight, hash, 0}; + confirm = {CWalletTx::Status::CONFIRMED, block->nHeight, block->GetBlockHash(), 0}; } // If transaction is already in map, to avoid inconsistencies, unconfirmation