refactoring: remove mapBlockIndex global

in lieu of ::BlockIndex().
This commit is contained in:
James O'Beirne 2019-04-10 14:34:46 -04:00
parent 55d525ab90
commit 682a1d0f20
6 changed files with 48 additions and 39 deletions

View file

@ -492,7 +492,7 @@ void SetupServerArgs()
"and level 4 tries to reconnect the blocks, " "and level 4 tries to reconnect the blocks, "
"each level includes the checks of the previous levels " "each level includes the checks of the previous levels "
"(0-4, default: %u)", DEFAULT_CHECKLEVEL), true, OptionsCategory::DEBUG_TEST); "(0-4, default: %u)", DEFAULT_CHECKLEVEL), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, ::ChainActive() and mapBlocksUnlinked occasionally. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-checkblockindex", strprintf("Do a full consistency check for the block tree, setBlockIndexCandidates, ::ChainActive() and mapBlocksUnlinked occasionally. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", DEFAULT_CHECKPOINTS_ENABLED), true, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", DEFAULT_CHECKPOINTS_ENABLED), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-deprecatedrpc=<method>", "Allows deprecated RPC method(s) to be used", true, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-deprecatedrpc=<method>", "Allows deprecated RPC method(s) to be used", true, OptionsCategory::DEBUG_TEST);
@ -1517,7 +1517,8 @@ bool AppInitMain(InitInterfaces& interfaces)
// If the loaded chain has a wrong genesis, bail out immediately // If the loaded chain has a wrong genesis, bail out immediately
// (we're likely using a testnet datadir, or the other way around). // (we're likely using a testnet datadir, or the other way around).
if (!mapBlockIndex.empty() && !LookupBlockIndex(chainparams.GetConsensus().hashGenesisBlock)) { if (!::BlockIndex().empty() &&
!LookupBlockIndex(chainparams.GetConsensus().hashGenesisBlock)) {
return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?")); return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
} }
@ -1538,7 +1539,7 @@ bool AppInitMain(InitInterfaces& interfaces)
} }
// At this point we're either in reindex or we've loaded a useful // At this point we're either in reindex or we've loaded a useful
// block tree into mapBlockIndex! // block tree into BlockIndex()!
pcoinsdbview.reset(new CCoinsViewDB(nCoinDBCache, false, fReset || fReindexChainState)); pcoinsdbview.reset(new CCoinsViewDB(nCoinDBCache, false, fReset || fReindexChainState));
pcoinscatcher.reset(new CCoinsViewErrorCatcher(pcoinsdbview.get())); pcoinscatcher.reset(new CCoinsViewErrorCatcher(pcoinsdbview.get()));
@ -1577,7 +1578,7 @@ bool AppInitMain(InitInterfaces& interfaces)
if (!fReset) { if (!fReset) {
// Note that RewindBlockIndex MUST run even if we're about to -reindex-chainstate. // Note that RewindBlockIndex MUST run even if we're about to -reindex-chainstate.
// It both disconnects blocks based on ::ChainActive(), and drops block data in // It both disconnects blocks based on ::ChainActive(), and drops block data in
// mapBlockIndex based on lack of available witness data. // BlockIndex() based on lack of available witness data.
uiInterface.InitMessage(_("Rewinding blocks...")); uiInterface.InitMessage(_("Rewinding blocks..."));
if (!RewindBlockIndex(chainparams)) { if (!RewindBlockIndex(chainparams)) {
strLoadError = _("Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain"); strLoadError = _("Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain");
@ -1749,7 +1750,7 @@ bool AppInitMain(InitInterfaces& interfaces)
//// debug print //// debug print
{ {
LOCK(cs_main); LOCK(cs_main);
LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size()); LogPrintf("block tree size = %u\n", ::BlockIndex().size());
chain_active_height = ::ChainActive().Height(); chain_active_height = ::ChainActive().Height();
} }
LogPrintf("nBestHeight = %d\n", chain_active_height); LogPrintf("nBestHeight = %d\n", chain_active_height);

View file

@ -1456,7 +1456,7 @@ static UniValue getchaintips(const JSONRPCRequest& request)
/* /*
* Idea: the set of chain tips is ::ChainActive().tip, plus orphan blocks which do not have another orphan building off of them. * Idea: the set of chain tips is ::ChainActive().tip, plus orphan blocks which do not have another orphan building off of them.
* Algorithm: * Algorithm:
* - Make one pass through mapBlockIndex, picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers. * - Make one pass through g_blockman.m_block_index, picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers.
* - Iterate through the orphan blocks. If the block isn't pointed to by another orphan, it is a chain tip. * - Iterate through the orphan blocks. If the block isn't pointed to by another orphan, it is a chain tip.
* - add ::ChainActive().Tip() * - add ::ChainActive().Tip()
*/ */
@ -1464,7 +1464,7 @@ static UniValue getchaintips(const JSONRPCRequest& request)
std::set<const CBlockIndex*> setOrphans; std::set<const CBlockIndex*> setOrphans;
std::set<const CBlockIndex*> setPrevs; std::set<const CBlockIndex*> setPrevs;
for (const std::pair<const uint256, CBlockIndex*>& item : mapBlockIndex) for (const std::pair<const uint256, CBlockIndex*>& item : ::BlockIndex())
{ {
if (!::ChainActive().Contains(item.second)) { if (!::ChainActive().Contains(item.second)) {
setOrphans.insert(item.second); setOrphans.insert(item.second);

View file

@ -250,7 +250,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams,
pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, uint256())); pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, uint256()));
// Load mapBlockIndex // Load m_block_index
while (pcursor->Valid()) { while (pcursor->Valid()) {
boost::this_thread::interruption_point(); boost::this_thread::interruption_point();
if (ShutdownRequested()) return false; if (ShutdownRequested()) return false;

View file

@ -99,7 +99,6 @@ CChain& ChainActive() { return g_chainstate.m_chain; }
*/ */
RecursiveMutex cs_main; RecursiveMutex cs_main;
BlockMap& mapBlockIndex = g_blockman.m_block_index;
CBlockIndex *pindexBestHeader = nullptr; CBlockIndex *pindexBestHeader = nullptr;
Mutex g_best_block_mutex; Mutex g_best_block_mutex;
std::condition_variable g_best_block_cv; std::condition_variable g_best_block_cv;
@ -147,6 +146,13 @@ namespace {
std::set<int> setDirtyFileInfo; std::set<int> setDirtyFileInfo;
} // anon namespace } // anon 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;
}
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator) CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator)
{ {
AssertLockHeld(cs_main); AssertLockHeld(cs_main);
@ -1046,6 +1052,11 @@ bool CChainState::IsInitialBlockDownload() const
static CBlockIndex *pindexBestForkTip = nullptr, *pindexBestForkBase = nullptr; static CBlockIndex *pindexBestForkTip = nullptr, *pindexBestForkBase = nullptr;
BlockMap& BlockIndex()
{
return g_blockman.m_block_index;
}
static void AlertNotify(const std::string& strMessage) static void AlertNotify(const std::string& strMessage)
{ {
uiInterface.NotifyAlertChanged(); uiInterface.NotifyAlertChanged();
@ -3117,7 +3128,7 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationSta
if (fCheckpointsEnabled) { if (fCheckpointsEnabled) {
// Don't accept any forks from the main chain prior to last checkpoint. // Don't accept any forks from the main chain prior to last checkpoint.
// GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our // GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our
// MapBlockIndex. // g_blockman.m_block_index.
CBlockIndex* pcheckpoint = GetLastCheckpoint(params.Checkpoints()); CBlockIndex* pcheckpoint = GetLastCheckpoint(params.Checkpoints());
if (pcheckpoint && nHeight < pcheckpoint->nHeight) if (pcheckpoint && nHeight < pcheckpoint->nHeight)
return state.Invalid(ValidationInvalidReason::BLOCK_CHECKPOINT, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight), REJECT_CHECKPOINT, "bad-fork-prior-to-checkpoint"); return state.Invalid(ValidationInvalidReason::BLOCK_CHECKPOINT, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight), REJECT_CHECKPOINT, "bad-fork-prior-to-checkpoint");
@ -3715,8 +3726,8 @@ bool BlockManager::LoadBlockIndex(
// Calculate nChainWork // Calculate nChainWork
std::vector<std::pair<int, CBlockIndex*> > vSortedByHeight; std::vector<std::pair<int, CBlockIndex*> > vSortedByHeight;
vSortedByHeight.reserve(mapBlockIndex.size()); vSortedByHeight.reserve(m_block_index.size());
for (const std::pair<const uint256, CBlockIndex*>& item : mapBlockIndex) for (const std::pair<const uint256, CBlockIndex*>& item : m_block_index)
{ {
CBlockIndex* pindex = item.second; CBlockIndex* pindex = item.second;
vSortedByHeight.push_back(std::make_pair(pindex->nHeight, pindex)); vSortedByHeight.push_back(std::make_pair(pindex->nHeight, pindex));
@ -3797,7 +3808,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_RE
// Check presence of blk files // Check presence of blk files
LogPrintf("Checking all blk files are present...\n"); LogPrintf("Checking all blk files are present...\n");
std::set<int> setBlkDataFiles; std::set<int> setBlkDataFiles;
for (const std::pair<const uint256, CBlockIndex*>& item : mapBlockIndex) for (const std::pair<const uint256, CBlockIndex*>& item : g_blockman.m_block_index)
{ {
CBlockIndex* pindex = item.second; CBlockIndex* pindex = item.second;
if (pindex->nStatus & BLOCK_HAVE_DATA) { if (pindex->nStatus & BLOCK_HAVE_DATA) {
@ -3996,16 +4007,16 @@ bool CChainState::ReplayBlocks(const CChainParams& params, CCoinsView* view)
const CBlockIndex* pindexNew; // New tip during the interrupted flush. const CBlockIndex* pindexNew; // New tip during the interrupted flush.
const CBlockIndex* pindexFork = nullptr; // Latest block common to both the old and the new tip. const CBlockIndex* pindexFork = nullptr; // Latest block common to both the old and the new tip.
if (mapBlockIndex.count(hashHeads[0]) == 0) { if (m_blockman.m_block_index.count(hashHeads[0]) == 0) {
return error("ReplayBlocks(): reorganization to unknown block requested"); return error("ReplayBlocks(): reorganization to unknown block requested");
} }
pindexNew = mapBlockIndex[hashHeads[0]]; pindexNew = m_blockman.m_block_index[hashHeads[0]];
if (!hashHeads[1].IsNull()) { // The old tip is allowed to be 0, indicating it's the first flush. if (!hashHeads[1].IsNull()) { // The old tip is allowed to be 0, indicating it's the first flush.
if (mapBlockIndex.count(hashHeads[1]) == 0) { if (m_blockman.m_block_index.count(hashHeads[1]) == 0) {
return error("ReplayBlocks(): reorganization from unknown block requested"); return error("ReplayBlocks(): reorganization from unknown block requested");
} }
pindexOld = mapBlockIndex[hashHeads[1]]; pindexOld = m_blockman.m_block_index[hashHeads[1]];
pindexFork = LastCommonAncestor(pindexOld, pindexNew); pindexFork = LastCommonAncestor(pindexOld, pindexNew);
assert(pindexFork != nullptr); assert(pindexFork != nullptr);
} }
@ -4094,7 +4105,7 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
// blocks will be dealt with below (releasing cs_main in between). // blocks will be dealt with below (releasing cs_main in between).
{ {
LOCK(cs_main); LOCK(cs_main);
for (const auto& entry : mapBlockIndex) { 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)) { if (IsWitnessEnabled(entry.second->pprev, params.GetConsensus()) && !(entry.second->nStatus & BLOCK_OPT_WITNESS) && !m_chain.Contains(entry.second)) {
EraseBlockData(entry.second); EraseBlockData(entry.second);
} }
@ -4234,7 +4245,7 @@ bool LoadBlockIndex(const CChainParams& chainparams)
if (!fReindex) { if (!fReindex) {
bool ret = LoadBlockIndexDB(chainparams); bool ret = LoadBlockIndexDB(chainparams);
if (!ret) return false; if (!ret) return false;
needs_init = mapBlockIndex.empty(); needs_init = g_blockman.m_block_index.empty();
} }
if (needs_init) { if (needs_init) {
@ -4254,10 +4265,10 @@ bool CChainState::LoadGenesisBlock(const CChainParams& chainparams)
LOCK(cs_main); LOCK(cs_main);
// Check whether we're already initialized by checking for genesis in // Check whether we're already initialized by checking for genesis in
// mapBlockIndex. Note that we can't use m_chain here, since it is // 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 // set based on the coins db, not the block index db, which is the only
// thing loaded at this point. // thing loaded at this point.
if (mapBlockIndex.count(chainparams.GenesisBlock().GetHash())) if (m_blockman.m_block_index.count(chainparams.GenesisBlock().GetHash()))
return true; return true;
try { try {
@ -4410,20 +4421,20 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
LOCK(cs_main); LOCK(cs_main);
// During a reindex, we read the genesis block and call CheckBlockIndex before ActivateBestChain, // During a reindex, we read the genesis block and call CheckBlockIndex before ActivateBestChain,
// so we have the genesis block in mapBlockIndex but no active chain. (A few of the tests when // so we have the genesis block in m_blockman.m_block_index but no active chain. (A few of the
// iterating the block tree require that m_chain has been initialized.) // tests when iterating the block tree require that m_chain has been initialized.)
if (m_chain.Height() < 0) { if (m_chain.Height() < 0) {
assert(mapBlockIndex.size() <= 1); assert(m_blockman.m_block_index.size() <= 1);
return; return;
} }
// Build forward-pointing map of the entire block tree. // Build forward-pointing map of the entire block tree.
std::multimap<CBlockIndex*,CBlockIndex*> forward; std::multimap<CBlockIndex*,CBlockIndex*> forward;
for (const std::pair<const uint256, CBlockIndex*>& entry : mapBlockIndex) { for (const std::pair<const uint256, CBlockIndex*>& entry : m_blockman.m_block_index) {
forward.insert(std::make_pair(entry.second->pprev, entry.second)); forward.insert(std::make_pair(entry.second->pprev, entry.second));
} }
assert(forward.size() == mapBlockIndex.size()); assert(forward.size() == m_blockman.m_block_index.size());
std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeGenesis = forward.equal_range(nullptr); std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeGenesis = forward.equal_range(nullptr);
CBlockIndex *pindex = rangeGenesis.first->second; CBlockIndex *pindex = rangeGenesis.first->second;
@ -4477,7 +4488,7 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
assert(pindex->nHeight == nHeight); // nHeight must be consistent. assert(pindex->nHeight == nHeight); // nHeight must be consistent.
assert(pindex->pprev == nullptr || pindex->nChainWork >= pindex->pprev->nChainWork); // For every block except the genesis block, the chainwork must be larger than the parent's. assert(pindex->pprev == nullptr || pindex->nChainWork >= pindex->pprev->nChainWork); // For every block except the genesis block, the chainwork must be larger than the parent's.
assert(nHeight < 2 || (pindex->pskip && (pindex->pskip->nHeight < nHeight))); // The pskip pointer must point back for all but the first 2 blocks. assert(nHeight < 2 || (pindex->pskip && (pindex->pskip->nHeight < nHeight))); // The pskip pointer must point back for all but the first 2 blocks.
assert(pindexFirstNotTreeValid == nullptr); // All mapBlockIndex entries must at least be TREE valid assert(pindexFirstNotTreeValid == nullptr); // All m_blockman.m_block_index entries must at least be TREE valid
if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TREE) assert(pindexFirstNotTreeValid == nullptr); // TREE valid implies all parents are TREE valid if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TREE) assert(pindexFirstNotTreeValid == nullptr); // TREE valid implies all parents are TREE valid
if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_CHAIN) assert(pindexFirstNotChainValid == nullptr); // CHAIN valid implies all parents are CHAIN valid if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_CHAIN) assert(pindexFirstNotChainValid == nullptr); // CHAIN valid implies all parents are CHAIN valid
if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_SCRIPTS) assert(pindexFirstNotScriptsValid == nullptr); // SCRIPTS valid implies all parents are SCRIPTS valid if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_SCRIPTS) assert(pindexFirstNotScriptsValid == nullptr); // SCRIPTS valid implies all parents are SCRIPTS valid
@ -4772,10 +4783,10 @@ public:
CMainCleanup() {} CMainCleanup() {}
~CMainCleanup() { ~CMainCleanup() {
// block headers // block headers
BlockMap::iterator it1 = mapBlockIndex.begin(); BlockMap::iterator it1 = g_blockman.m_block_index.begin();
for (; it1 != mapBlockIndex.end(); it1++) for (; it1 != g_blockman.m_block_index.end(); it1++)
delete (*it1).second; delete (*it1).second;
mapBlockIndex.clear(); g_blockman.m_block_index.clear();
} }
}; };
static CMainCleanup instance_of_cmaincleanup; static CMainCleanup instance_of_cmaincleanup;

View file

@ -144,7 +144,6 @@ extern CCriticalSection cs_main;
extern CBlockPolicyEstimator feeEstimator; extern CBlockPolicyEstimator feeEstimator;
extern CTxMemPool mempool; extern CTxMemPool mempool;
typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap; typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
extern BlockMap& mapBlockIndex GUARDED_BY(cs_main);
extern Mutex g_best_block_mutex; extern Mutex g_best_block_mutex;
extern std::condition_variable g_best_block_cv; extern std::condition_variable g_best_block_cv;
extern uint256 g_best_block; extern uint256 g_best_block;
@ -406,12 +405,7 @@ public:
/** Replay blocks that aren't fully applied to the database. */ /** Replay blocks that aren't fully applied to the database. */
bool ReplayBlocks(const CChainParams& params, CCoinsView* view); bool ReplayBlocks(const CChainParams& params, CCoinsView* view);
inline CBlockIndex* LookupBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) CBlockIndex* LookupBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
{
AssertLockHeld(cs_main);
BlockMap::const_iterator it = mapBlockIndex.find(hash);
return it == mapBlockIndex.end() ? nullptr : it->second;
}
/** Find the last common block between the parameter chain and a locator. */ /** Find the last common block between the parameter chain and a locator. */
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator) EXCLUSIVE_LOCKS_REQUIRED(cs_main); CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@ -498,7 +492,7 @@ public:
/** /**
* If a block header hasn't already been seen, call CheckBlockHeader on it, ensure * If a block header hasn't already been seen, call CheckBlockHeader on it, ensure
* that it doesn't descend from an invalid block, and then add it to mapBlockIndex. * that it doesn't descend from an invalid block, and then add it to m_block_index.
*/ */
bool AcceptBlockHeader( bool AcceptBlockHeader(
const CBlockHeader& block, const CBlockHeader& block,
@ -658,6 +652,9 @@ CChainState& ChainstateActive();
/** @returns the most-work chain. */ /** @returns the most-work chain. */
CChain& ChainActive(); CChain& ChainActive();
/** @returns the global block index map. */
BlockMap& BlockIndex();
/** Global variable that points to the coins database (protected by cs_main) */ /** Global variable that points to the coins database (protected by cs_main) */
extern std::unique_ptr<CCoinsViewDB> pcoinsdbview; extern std::unique_ptr<CCoinsViewDB> pcoinsdbview;

View file

@ -272,7 +272,7 @@ static int64_t AddTx(CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64
if (blockTime > 0) { if (blockTime > 0) {
auto locked_chain = wallet.chain().lock(); auto locked_chain = wallet.chain().lock();
LockAssertion lock(::cs_main); LockAssertion lock(::cs_main);
auto inserted = mapBlockIndex.emplace(GetRandHash(), new CBlockIndex); auto inserted = ::BlockIndex().emplace(GetRandHash(), new CBlockIndex);
assert(inserted.second); assert(inserted.second);
const uint256& hash = inserted.first->first; const uint256& hash = inserted.first->first;
block = inserted.first->second; block = inserted.first->second;