aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/node/blockstorage.cpp46
-rw-r--r--src/node/blockstorage.h11
-rw-r--r--src/rpc/blockchain.cpp8
-rw-r--r--src/validation.cpp36
-rw-r--r--src/wallet/test/wallet_tests.cpp4
5 files changed, 58 insertions, 47 deletions
diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp
index 8a99130fd0..a13c1a9956 100644
--- a/src/node/blockstorage.cpp
+++ b/src/node/blockstorage.cpp
@@ -32,11 +32,18 @@ static FILE* OpenUndoFile(const FlatFilePos& pos, bool fReadOnly = false);
static FlatFileSeq BlockFileSeq();
static FlatFileSeq UndoFileSeq();
-CBlockIndex* BlockManager::LookupBlockIndex(const uint256& hash) const
+CBlockIndex* BlockManager::LookupBlockIndex(const uint256& hash)
+{
+ AssertLockHeld(cs_main);
+ BlockMap::iterator it = m_block_index.find(hash);
+ return it == m_block_index.end() ? nullptr : &it->second;
+}
+
+const 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;
+ return it == m_block_index.end() ? nullptr : &it->second;
}
CBlockIndex* BlockManager::AddToBlockIndex(const CBlockHeader& block)
@@ -47,20 +54,22 @@ CBlockIndex* BlockManager::AddToBlockIndex(const CBlockHeader& block)
uint256 hash = block.GetHash();
BlockMap::iterator it = m_block_index.find(hash);
if (it != m_block_index.end()) {
- return it->second;
+ return &it->second;
}
// Construct new block index object
- CBlockIndex* pindexNew = new CBlockIndex(block);
+ CBlockIndex new_index{block};
// We assign the sequence id to blocks only when the full data is available,
// 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;
+ new_index.nSequenceId = 0;
+ BlockMap::iterator mi = m_block_index.insert(std::make_pair(hash, std::move(new_index))).first;
+
+ CBlockIndex* pindexNew = &(*mi).second;
pindexNew->phashBlock = &((*mi).first);
BlockMap::iterator miPrev = m_block_index.find(block.hashPrevBlock);
if (miPrev != m_block_index.end()) {
- pindexNew->pprev = (*miPrev).second;
+ pindexNew->pprev = &(*miPrev).second;
pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
pindexNew->BuildSkip();
}
@@ -80,8 +89,8 @@ void BlockManager::PruneOneBlockFile(const int fileNumber)
AssertLockHeld(cs_main);
LOCK(cs_LastBlockFile);
- for (const auto& entry : m_block_index) {
- CBlockIndex* pindex = entry.second;
+ for (auto& entry : m_block_index) {
+ CBlockIndex* pindex = &entry.second;
if (pindex->nFile == fileNumber) {
pindex->nStatus &= ~BLOCK_HAVE_DATA;
pindex->nStatus &= ~BLOCK_HAVE_UNDO;
@@ -202,12 +211,13 @@ CBlockIndex* BlockManager::InsertBlockIndex(const uint256& hash)
// Return existing
BlockMap::iterator mi = m_block_index.find(hash);
if (mi != m_block_index.end()) {
- return (*mi).second;
+ return &(*mi).second;
}
// Create new
- CBlockIndex* pindexNew = new CBlockIndex();
- mi = m_block_index.insert(std::make_pair(hash, pindexNew)).first;
+ CBlockIndex new_index{};
+ mi = m_block_index.insert(std::make_pair(hash, std::move(new_index))).first;
+ CBlockIndex* pindexNew = &(*mi).second;
pindexNew->phashBlock = &((*mi).first);
return pindexNew;
@@ -224,8 +234,8 @@ 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 (std::pair<const uint256, CBlockIndex>& item : m_block_index) {
+ CBlockIndex* pindex = &item.second;
vSortedByHeight.push_back(std::make_pair(pindex->nHeight, pindex));
}
sort(vSortedByHeight.begin(), vSortedByHeight.end());
@@ -327,10 +337,6 @@ void BlockManager::Unload()
{
m_blocks_unlinked.clear();
- for (const BlockMap::value_type& entry : m_block_index) {
- delete entry.second;
- }
-
m_block_index.clear();
m_blockfile_info.clear();
@@ -386,8 +392,8 @@ bool BlockManager::LoadBlockIndexDB(ChainstateManager& chainman)
// 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 : m_block_index) {
- CBlockIndex* pindex = item.second;
+ for (const std::pair<const uint256, CBlockIndex>& item : m_block_index) {
+ const CBlockIndex* pindex = &item.second;
if (pindex->nStatus & BLOCK_HAVE_DATA) {
setBlkDataFiles.insert(pindex->nFile);
}
diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h
index 42e46797d2..be1ed83064 100644
--- a/src/node/blockstorage.h
+++ b/src/node/blockstorage.h
@@ -5,6 +5,7 @@
#ifndef BITCOIN_NODE_BLOCKSTORAGE_H
#define BITCOIN_NODE_BLOCKSTORAGE_H
+#include <chain.h>
#include <fs.h>
#include <protocol.h> // For CMessageHeader::MessageStartChars
#include <sync.h>
@@ -20,7 +21,6 @@ class ArgsManager;
class BlockValidationState;
class CBlock;
class CBlockFileInfo;
-class CBlockIndex;
class CBlockUndo;
class CChain;
class CChainParams;
@@ -52,7 +52,11 @@ extern bool fPruneMode;
/** Number of MiB of block files that we're trying to stay below. */
extern uint64_t nPruneTarget;
-typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
+// 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
+// container that has stable addressing (true of all std associative
+// containers), or make the key a `std::unique_ptr<CBlockIndex>`
+typedef std::unordered_map<uint256, CBlockIndex, BlockHasher> BlockMap;
struct CBlockIndexWorkComparator {
bool operator()(const CBlockIndex* pa, const CBlockIndex* pb) const;
@@ -144,7 +148,8 @@ public:
//! Mark one block file as pruned (modify associated database entries)
void PruneOneBlockFile(const int fileNumber) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- CBlockIndex* LookupBlockIndex(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ CBlockIndex* LookupBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ const CBlockIndex* LookupBlockIndex(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Get block file info entry for one block file */
CBlockFileInfo* GetBlockFileInfo(size_t n);
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 9817c80cbd..2c69fdd457 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1753,10 +1753,10 @@ static RPCHelpMan getchaintips()
std::set<const CBlockIndex*> setOrphans;
std::set<const CBlockIndex*> setPrevs;
- for (const std::pair<const uint256, CBlockIndex*>& item : chainman.BlockIndex()) {
- if (!active_chain.Contains(item.second)) {
- setOrphans.insert(item.second);
- setPrevs.insert(item.second->pprev);
+ for (const std::pair<const uint256, CBlockIndex>& item : chainman.BlockIndex()) {
+ if (!active_chain.Contains(&item.second)) {
+ setOrphans.insert(&item.second);
+ setPrevs.insert(item.second.pprev);
}
}
diff --git a/src/validation.cpp b/src/validation.cpp
index 035b5783c3..fdb1518b3c 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -1978,7 +1978,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
// effectively caching the result of part of the verification.
BlockMap::const_iterator 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->second.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.
@@ -3035,8 +3035,8 @@ bool CChainState::InvalidateBlock(BlockValidationState& state, CBlockIndex* pind
{
LOCK(cs_main);
- for (const auto& entry : m_blockman.m_block_index) {
- CBlockIndex *candidate = entry.second;
+ for (auto& entry : m_blockman.m_block_index) {
+ CBlockIndex* candidate = &entry.second;
// 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.
@@ -3135,8 +3135,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->second.IsValid(BLOCK_VALID_TRANSACTIONS) && it->second.HaveTxsDownloaded() && !setBlockIndexCandidates.value_comp()(&it->second, m_chain.Tip())) {
+ setBlockIndexCandidates.insert(&it->second);
}
it++;
}
@@ -3159,17 +3159,17 @@ 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;
- m_blockman.m_dirty_blockindex.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->second.IsValid() && it->second.GetAncestor(nHeight) == pindex) {
+ it->second.nStatus &= ~BLOCK_FAILED_MASK;
+ m_blockman.m_dirty_blockindex.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->second == m_chainman.m_best_invalid) {
+ if (&it->second == m_chainman.m_best_invalid) {
// Reset invalid block marker if it was pointing to one of those.
m_chainman.m_best_invalid = nullptr;
}
- m_chainman.m_failed_blocks.erase(it->second);
+ m_chainman.m_failed_blocks.erase(&it->second);
}
it++;
}
@@ -3500,7 +3500,7 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
if (hash != chainparams.GetConsensus().hashGenesisBlock) {
if (miSelf != m_blockman.m_block_index.end()) {
// Block header is already known.
- CBlockIndex* pindex = miSelf->second;
+ CBlockIndex* pindex = &(miSelf->second);
if (ppindex)
*ppindex = pindex;
if (pindex->nStatus & BLOCK_FAILED_MASK) {
@@ -3522,7 +3522,7 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
LogPrint(BCLog::VALIDATION, "%s: %s prev block not found\n", __func__, hash.ToString());
return state.Invalid(BlockValidationResult::BLOCK_MISSING_PREV, "prev-blk-not-found");
}
- pindexPrev = (*mi).second;
+ pindexPrev = &((*mi).second);
if (pindexPrev->nStatus & BLOCK_FAILED_MASK) {
LogPrint(BCLog::VALIDATION, "%s: %s prev block invalid\n", __func__, hash.ToString());
return state.Invalid(BlockValidationResult::BLOCK_INVALID_PREV, "bad-prevblk");
@@ -3988,13 +3988,13 @@ bool CChainState::ReplayBlocks()
if (m_blockman.m_block_index.count(hashHeads[0]) == 0) {
return error("ReplayBlocks(): reorganization to unknown block requested");
}
- pindexNew = m_blockman.m_block_index[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 (m_blockman.m_block_index.count(hashHeads[1]) == 0) {
return error("ReplayBlocks(): reorganization from unknown block requested");
}
- pindexOld = m_blockman.m_block_index[hashHeads[1]];
+ pindexOld = &(m_blockman.m_block_index[hashHeads[1]]);
pindexFork = LastCommonAncestor(pindexOld, pindexNew);
assert(pindexFork != nullptr);
}
@@ -4261,8 +4261,8 @@ void CChainState::CheckBlockIndex()
// 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 (std::pair<const uint256, CBlockIndex>& entry : m_blockman.m_block_index) {
+ forward.insert(std::make_pair(entry.second.pprev, &entry.second));
}
assert(forward.size() == m_blockman.m_block_index.size());
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 7693c9c0e8..c59f7e6f05 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -367,10 +367,10 @@ 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 inserted = chainman.BlockIndex().emplace(std::piecewise_construct, std::make_tuple(GetRandHash()), std::make_tuple());
assert(inserted.second);
const uint256& hash = inserted.first->first;
- block = inserted.first->second;
+ block = &inserted.first->second;
block->nTime = blockTime;
block->phashBlock = &hash;
state = TxStateConfirmed{hash, block->nHeight, /*position_in_block=*/0};