Use set instead of map on block index

Signed-off-by: Anthony Fieroni <bvbfan@abv.bg>
This commit is contained in:
Anthony Fieroni 2020-02-18 08:32:42 +02:00
parent 0c311d5fae
commit e738202334
8 changed files with 117 additions and 119 deletions

View file

@ -20,9 +20,7 @@ static void BlockToJsonVerbose(benchmark::State& state) {
CBlock block;
stream >> block;
CBlockIndex blockindex;
const uint256 blockHash = block.GetHash();
blockindex.phashBlock = &blockHash;
CBlockIndex blockindex(block.GetHash());
blockindex.nBits = 403014710;
while (state.KeepRunning()) {

View file

@ -140,7 +140,7 @@ class CBlockIndex
{
public:
//! pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
const uint256* phashBlock;
const uint256 hash;
//! pointer to the index of the predecessor of this block
CBlockIndex* pprev;
@ -191,7 +191,6 @@ public:
void SetNull()
{
phashBlock = nullptr;
pprev = nullptr;
pskip = nullptr;
nHeight = 0;
@ -213,12 +212,12 @@ public:
nNonce = 0;
}
CBlockIndex()
explicit CBlockIndex(const uint256& hash = {}) : hash(hash)
{
SetNull();
}
explicit CBlockIndex(const CBlockHeader& block)
explicit CBlockIndex(const CBlockHeader& block) : hash(block.GetHash())
{
SetNull();
@ -264,7 +263,7 @@ public:
uint256 GetBlockHash() const
{
return *phashBlock;
return hash;
}
uint256 GetBlockPoWHash() const

View file

@ -1351,20 +1351,16 @@ static UniValue getchaintips(const JSONRPCRequest& request)
std::set<const CBlockIndex*> setOrphans;
std::set<const CBlockIndex*> setPrevs;
for (const std::pair<const uint256, CBlockIndex*>& item : ::BlockIndex())
{
if (!::ChainActive().Contains(item.second)) {
setOrphans.insert(item.second);
setPrevs.insert(item.second->pprev);
for (auto pindex : ::BlockIndex())
if (!::ChainActive().Contains(pindex)) {
setOrphans.insert(pindex);
setPrevs.insert(pindex->pprev);
}
}
for (std::set<const CBlockIndex*>::iterator it = setOrphans.begin(); it != setOrphans.end(); ++it)
{
for (auto it = setOrphans.begin(); it != setOrphans.end(); ++it)
if (setPrevs.erase(*it) == 0) {
setTips.insert(*it);
}
}
// Always report the currently active tip.
setTips.insert(::ChainActive().Tip());
@ -1375,7 +1371,7 @@ static UniValue getchaintips(const JSONRPCRequest& request)
{
UniValue obj(UniValue::VOBJ);
obj.pushKV("height", block->nHeight);
obj.pushKV("hash", block->phashBlock->GetHex());
obj.pushKV("hash", block->hash.GetHex());
// not use ForkAt method because we need the previous one as well
const CBlockIndex *forkAt = block, *forkPrev = block;
@ -1387,8 +1383,8 @@ static UniValue getchaintips(const JSONRPCRequest& request)
const int branchLen = block->nHeight - forkAt->nHeight;
obj.pushKV("branchlen", branchLen);
if (forkAt != forkPrev) {
obj.pushKV("branchhash", forkAt->phashBlock->GetHex());
obj.pushKV("branchhashNext", forkPrev->phashBlock->GetHex());
obj.pushKV("branchhash", forkAt->hash.GetHex());
obj.pushKV("branchhashNext", forkPrev->hash.GetHex());
}
std::string status;

View file

@ -375,8 +375,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
// Create an actual 209999-long block chain (without valid blocks).
while (::ChainActive().Tip()->nHeight < 209999) {
CBlockIndex* prev = ::ChainActive().Tip();
CBlockIndex* next = new CBlockIndex();
next->phashBlock = new uint256(InsecureRand256());
CBlockIndex* next = new CBlockIndex(uint256(InsecureRand256()));
next->hashClaimTrie = pblocktemplate->block.hashClaimTrie;
::ChainstateActive().CoinsTip().SetBestBlock(next->GetBlockHash());
next->pprev = prev;
@ -388,8 +387,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
// Extend to a 210000-long block chain.
while (::ChainActive().Tip()->nHeight < 210000) {
CBlockIndex* prev = ::ChainActive().Tip();
CBlockIndex* next = new CBlockIndex();
next->phashBlock = new uint256(InsecureRand256());
CBlockIndex* next = new CBlockIndex(uint256(InsecureRand256()));
next->hashClaimTrie = pblocktemplate->block.hashClaimTrie;
::ChainstateActive().CoinsTip().SetBestBlock(next->GetBlockHash());
next->pprev = prev;
@ -422,7 +420,6 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
CBlockIndex* del = ::ChainActive().Tip();
::ChainActive().SetTip(del->pprev);
::ChainstateActive().CoinsTip().SetBestBlock(del->pprev->GetBlockHash());
delete del->phashBlock;
delete del;
}

View file

@ -47,12 +47,13 @@ BOOST_AUTO_TEST_CASE(getlocator_test)
{
// Build a main chain 100000 blocks long.
std::vector<uint256> vHashMain(100000);
std::vector<CBlockIndex> vBlocksMain(100000);
for (unsigned int i=0; i<vBlocksMain.size(); i++) {
std::vector<CBlockIndex> vBlocksMain;
vBlocksMain.reserve(100000);
for (unsigned int i=0; i<100000; i++) {
vHashMain[i] = ArithToUint256(i); // Set the hash equal to the height, so we can quickly check the distances.
vBlocksMain.emplace_back(vHashMain[i]);
vBlocksMain[i].nHeight = i;
vBlocksMain[i].pprev = i ? &vBlocksMain[i - 1] : nullptr;
vBlocksMain[i].phashBlock = &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);
@ -60,12 +61,13 @@ BOOST_AUTO_TEST_CASE(getlocator_test)
// Build a branch that splits off at block 49999, 50000 blocks long.
std::vector<uint256> vHashSide(50000);
std::vector<CBlockIndex> vBlocksSide(50000);
for (unsigned int i=0; i<vBlocksSide.size(); i++) {
std::vector<CBlockIndex> vBlocksSide;
vBlocksSide.reserve(50000);
for (unsigned int i=0; i<50000; i++) {
vHashSide[i] = ArithToUint256(i + 50000 + (arith_uint256(1) << 128)); // Add 1<<128 to the hashes, so GetLow64() still returns the height.
vBlocksSide.emplace_back(vHashSide[i]);
vBlocksSide[i].nHeight = i + 50000;
vBlocksSide[i].pprev = i ? &vBlocksSide[i - 1] : (vBlocksMain.data()+49999);
vBlocksSide[i].phashBlock = &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);
@ -102,12 +104,13 @@ BOOST_AUTO_TEST_CASE(getlocator_test)
BOOST_AUTO_TEST_CASE(findearliestatleast_test)
{
std::vector<uint256> vHashMain(100000);
std::vector<CBlockIndex> vBlocksMain(100000);
for (unsigned int i=0; i<vBlocksMain.size(); i++) {
std::vector<CBlockIndex> vBlocksMain;
vBlocksMain.reserve(100000);
for (unsigned int i=0; i<100000; i++) {
vHashMain[i] = ArithToUint256(i); // Set the hash equal to the height
vBlocksMain.emplace_back(vHashMain[i]);
vBlocksMain[i].nHeight = i;
vBlocksMain[i].pprev = i ? &vBlocksMain[i - 1] : nullptr;
vBlocksMain[i].phashBlock = &vHashMain[i];
vBlocksMain[i].BuildSkip();
if (i < 10) {
vBlocksMain[i].nTime = i;

View file

@ -83,6 +83,21 @@ bool CBlockIndexWorkComparator::operator()(const CBlockIndex *pa, const CBlockIn
return false;
}
bool CBlockIndexHashComparator::operator()(const CBlockIndex* pa, const CBlockIndex* pb) const
{
return pa->hash < pb->hash;
}
bool CBlockIndexHashComparator::operator()(const CBlockIndex* pa, const uint256& hash) const
{
return pa->hash < hash;
}
bool CBlockIndexHashComparator::operator()(const uint256& hash, const CBlockIndex* pa) const
{
return hash < pa->hash;
}
namespace {
BlockManager g_blockman;
} // anon namespace
@ -188,8 +203,8 @@ namespace {
CBlockIndex* LookupBlockIndex(const uint256& hash)
{
AssertLockHeld(cs_main);
BlockMap::const_iterator it = g_blockman.m_block_index.find(hash);
return it == g_blockman.m_block_index.end() ? nullptr : it->second;
auto it = g_blockman.m_block_index.find(hash);
return it == g_blockman.m_block_index.end() ? nullptr : *it;
}
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator)
@ -1441,14 +1456,14 @@ static void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
if (!GetfLargeWorkForkFound() && pindexBestForkBase)
{
std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") +
pindexBestForkBase->phashBlock->ToString() + std::string("'");
pindexBestForkBase->hash.ToString() + std::string("'");
AlertNotify(warning);
}
if (pindexBestForkTip && pindexBestForkBase)
{
LogPrintf("%s: Warning: Large valid fork found\n forking the chain at height %d (%s)\n lasting to height %d (%s).\nChain state database corruption likely.\n", __func__,
pindexBestForkBase->nHeight, pindexBestForkBase->phashBlock->ToString(),
pindexBestForkTip->nHeight, pindexBestForkTip->phashBlock->ToString());
pindexBestForkBase->nHeight, pindexBestForkBase->hash.ToString(),
pindexBestForkTip->nHeight, pindexBestForkTip->hash.ToString());
SetfLargeWorkForkFound(true);
}
else
@ -1983,8 +1998,7 @@ 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->hash != consensusparams.BIP16Exception) // this block isn't the historical exception
{
flags |= SCRIPT_VERIFY_P2SH;
}
@ -2037,7 +2051,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
{
AssertLockHeld(cs_main);
assert(pindex);
assert(*pindex->phashBlock == block.GetHash());
assert(pindex->hash == block.GetHash());
int64_t nTimeStart = GetTimeMicros();
// Check it again in case a previous version let a bad block in
@ -2093,9 +2107,9 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
// 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);
auto it = m_blockman.m_block_index.find(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.
@ -2384,7 +2398,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
setDirtyBlockIndex.insert(pindex);
}
assert(pindex->phashBlock);
assert(!pindex->hash.IsNull());
// add this block to the view's block chain
view.SetBestBlock(pindex->GetBlockHash());
@ -3159,8 +3173,7 @@ bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& c
{
LOCK(cs_main);
for (const auto& entry : m_blockman.m_block_index) {
CBlockIndex *candidate = entry.second;
for (auto 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.
@ -3255,11 +3268,10 @@ bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& c
// it up here, this should be an essentially unobservable error.
// Loop back over all block index entries and add any missing entries
// to setBlockIndexCandidates.
BlockMap::iterator it = m_blockman.m_block_index.begin();
auto 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++;
}
@ -3283,19 +3295,19 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
int nHeight = pindex->nHeight;
// Remove the invalidity flag from this block and all its descendants.
BlockMap::iterator it = m_blockman.m_block_index.begin();
auto 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);
if (!(*it)->IsValid() && (*it)->GetAncestor(nHeight) == pindex) {
(*it)->nStatus &= ~BLOCK_FAILED_MASK;
setDirtyBlockIndex.insert(*it);
if ((*it)->IsValid(BLOCK_VALID_TRANSACTIONS) && (*it)->HaveTxsDownloaded() && setBlockIndexCandidates.value_comp()(m_chain.Tip(), *it)) {
setBlockIndexCandidates.insert(*it);
}
if (it->second == pindexBestInvalid) {
if (*it == 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(*it);
}
it++;
}
@ -3321,9 +3333,9 @@ CBlockIndex* BlockManager::AddToBlockIndex(const CBlockHeader& block)
// Check for duplicate
uint256 hash = block.GetHash();
BlockMap::iterator it = m_block_index.find(hash);
auto it = m_block_index.find(hash);
if (it != m_block_index.end())
return it->second;
return *it;
// Construct new block index object
CBlockIndex* pindexNew = new CBlockIndex(block);
@ -3331,12 +3343,10 @@ 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);
if (miPrev != m_block_index.end())
{
pindexNew->pprev = (*miPrev).second;
auto mi = m_block_index.insert(pindexNew).first;
auto miPrev = m_block_index.find(block.hashPrevBlock);
if (miPrev != m_block_index.end()) {
pindexNew->pprev = (*miPrev);
pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
pindexNew->BuildSkip();
}
@ -3759,12 +3769,12 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, CValidationState
AssertLockHeld(cs_main);
// Check for duplicate
uint256 hash = block.GetHash();
BlockMap::iterator miSelf = m_block_index.find(hash);
auto miSelf = m_block_index.find(hash);
CBlockIndex *pindex = nullptr;
if (hash != chainparams.GetConsensus().hashGenesisBlock) {
if (miSelf != m_block_index.end()) {
// Block header is already known.
pindex = miSelf->second;
pindex = *miSelf;
if (ppindex)
*ppindex = pindex;
if (pindex->nStatus & BLOCK_FAILED_MASK)
@ -3777,10 +3787,10 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, CValidationState
// Get prev block index
CBlockIndex* pindexPrev = nullptr;
BlockMap::iterator mi = m_block_index.find(block.hashPrevBlock);
auto mi = m_block_index.find(block.hashPrevBlock);
if (mi == m_block_index.end())
return state.Invalid(ValidationInvalidReason::BLOCK_MISSING_PREV, error("%s: prev block not found", __func__), 0, "prev-blk-not-found");
pindexPrev = (*mi).second;
pindexPrev = (*mi);
if (pindexPrev->nStatus & BLOCK_FAILED_MASK)
return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_PREV, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");
if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev, GetAdjustedTime()))
@ -4009,7 +4019,6 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
CBlockIndex indexDummy(block);
indexDummy.pprev = pindexPrev;
indexDummy.nHeight = pindexPrev->nHeight + 1;
indexDummy.phashBlock = &block_hash;
// NOTE: CheckBlockHeader is called by CheckBlock
if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev, GetAdjustedTime()))
@ -4046,8 +4055,7 @@ void PruneOneBlockFile(const int fileNumber)
{
LOCK(cs_LastBlockFile);
for (const auto& entry : g_blockman.m_block_index) {
CBlockIndex* pindex = entry.second;
for (auto pindex : g_blockman.m_block_index) {
if (pindex->nFile == fileNumber) {
pindex->nStatus &= ~BLOCK_HAVE_DATA;
pindex->nStatus &= ~BLOCK_HAVE_UNDO;
@ -4214,22 +4222,21 @@ fs::path GetBlockPosFilename(const FlatFilePos &pos)
return BlockFileSeq().FileName(pos);
}
CBlockIndex * BlockManager::InsertBlockIndex(const uint256& hash)
CBlockIndex* BlockManager::InsertBlockIndex(const uint256& hash)
{
AssertLockHeld(cs_main);
// Return existing
auto mi = m_block_index.find(hash);
if (mi != m_block_index.end())
return mi->second;
return *mi;
if (hash.IsNull())
return nullptr;
// Create new
CBlockIndex* pindexNew = new CBlockIndex();
mi = m_block_index.insert(std::make_pair(hash, pindexNew)).first;
pindexNew->phashBlock = &(mi->first);
CBlockIndex* pindexNew = new CBlockIndex(hash);
m_block_index.insert(pindexNew);
return pindexNew;
}
@ -4245,14 +4252,11 @@ bool BlockManager::LoadBlockIndex(
// Calculate nChainWork
std::vector<std::pair<int, CBlockIndex*> > vSortedByHeight;
vSortedByHeight.reserve(m_block_index.size());
for (const std::pair<const uint256, CBlockIndex*>& item : m_block_index)
{
CBlockIndex* pindex = item.second;
for (auto pindex : m_block_index)
vSortedByHeight.push_back(std::make_pair(pindex->nHeight, pindex));
}
sort(vSortedByHeight.begin(), vSortedByHeight.end());
for (const std::pair<int, CBlockIndex*>& item : vSortedByHeight)
{
for (const std::pair<int, CBlockIndex*>& item : vSortedByHeight) {
if (ShutdownRequested()) return false;
CBlockIndex* pindex = item.second;
pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + GetBlockProof(*pindex);
@ -4289,13 +4293,13 @@ bool BlockManager::LoadBlockIndex(
return true;
}
void BlockManager::Unload() {
void BlockManager::Unload()
{
m_failed_blocks.clear();
m_blocks_unlinked.clear();
for (const BlockMap::value_type& entry : m_block_index) {
delete entry.second;
}
for (auto pindex : m_block_index)
delete pindex;
m_block_index.clear();
}
@ -4326,19 +4330,14 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_RE
// Check presence of blk files
LogPrintf("Checking all blk files are present...\n");
std::set<int> setBlkDataFiles;
for (const std::pair<const uint256, CBlockIndex*>& item : g_blockman.m_block_index)
{
CBlockIndex* pindex = item.second;
if (pindex->nStatus & BLOCK_HAVE_DATA) {
for (auto pindex : g_blockman.m_block_index)
if (pindex->nStatus & BLOCK_HAVE_DATA)
setBlkDataFiles.insert(pindex->nFile);
}
}
for (auto it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); ++it)
{
for (auto it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); ++it) {
FlatFilePos pos(*it, 0);
if (CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION).IsNull()) {
if (CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION).IsNull())
return false;
}
}
// Check whether we have ever pruned block & undo files
@ -4533,16 +4532,18 @@ bool CChainState::ReplayBlocks(const CChainParams& params)
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 it = m_blockman.m_block_index.find(hashHeads[0]);
if (it == m_blockman.m_block_index.end())
return error("ReplayBlocks(): reorganization to unknown block requested");
}
pindexNew = m_blockman.m_block_index[hashHeads[0]];
pindexNew = *it;
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) {
it = m_blockman.m_block_index.find(hashHeads[1]);
if (it == m_blockman.m_block_index.end())
return error("ReplayBlocks(): reorganization from unknown block requested");
}
pindexOld = m_blockman.m_block_index[hashHeads[1]];
pindexOld = *it;
pindexFork = LastCommonAncestor(pindexOld, pindexNew);
assert(pindexFork != nullptr);
}
@ -4628,11 +4629,9 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
// blocks will be dealt with below (releasing cs_main in between).
{
LOCK(cs_main);
for (const auto& entry : m_blockman.m_block_index) {
if (IsWitnessEnabled(entry.second->pprev, params.GetConsensus()) && !(entry.second->nStatus & BLOCK_OPT_WITNESS) && !m_chain.Contains(entry.second)) {
EraseBlockData(entry.second);
}
}
for (auto pindex : m_blockman.m_block_index)
if (IsWitnessEnabled(pindex->pprev, params.GetConsensus()) && !(pindex->nStatus & BLOCK_OPT_WITNESS) && !m_chain.Contains(pindex))
EraseBlockData(pindex);
}
// Find what height we need to reorganize to.
@ -4963,9 +4962,8 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
// Build forward-pointing map of the entire block tree.
std::multimap<CBlockIndex*,CBlockIndex*> forward;
for (const std::pair<const uint256, CBlockIndex*>& entry : m_blockman.m_block_index) {
forward.insert(std::make_pair(entry.second->pprev, entry.second));
}
for (auto pindex : m_blockman.m_block_index)
forward.insert(std::make_pair(pindex->pprev, pindex));
assert(forward.size() == m_blockman.m_block_index.size());
@ -5318,7 +5316,7 @@ public:
// block headers
auto it1 = g_blockman.m_block_index.begin();
for (; it1 != g_blockman.m_block_index.end(); it1++)
delete (*it1).second;
delete (*it1);
g_blockman.m_block_index.clear();
}
};

View file

@ -142,7 +142,6 @@ extern CScript COINBASE_FLAGS;
extern CCriticalSection cs_main;
extern CBlockPolicyEstimator feeEstimator;
extern CTxMemPool mempool;
typedef std::map<uint256, CBlockIndex*> BlockMap;
extern Mutex g_best_block_mutex;
extern std::condition_variable g_best_block_cv;
extern uint256 g_best_block;
@ -429,6 +428,16 @@ struct CBlockIndexWorkComparator
bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const;
};
struct CBlockIndexHashComparator
{
using is_transparent = void;
bool operator()(const CBlockIndex* pa, const CBlockIndex* pb) const;
bool operator()(const CBlockIndex* pa, const uint256& hash) const;
bool operator()(const uint256& hash, const CBlockIndex* pa) const;
};
typedef std::set<CBlockIndex*, CBlockIndexHashComparator> BlockMap;
/**
* Maintains a tree of blocks (stored in `m_block_index`) which is consulted
* to determine where the most-work tip is.

View file

@ -272,12 +272,10 @@ static int64_t AddTx(CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64
if (blockTime > 0) {
auto locked_chain = wallet.chain().lock();
LockAssertion lock(::cs_main);
auto inserted = ::BlockIndex().emplace(GetRandHash(), new CBlockIndex);
auto inserted = ::BlockIndex().emplace(new CBlockIndex(GetRandHash()));
assert(inserted.second);
const uint256& hash = inserted.first->first;
block = inserted.first->second;
block = *inserted.first;
block->nTime = blockTime;
block->phashBlock = &hash;
}
CWalletTx wtx(&wallet, MakeTransactionRef(tx));