From a0dbe433bdb3f22be639fbb675c371277fba6d80 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 4 Sep 2014 02:01:10 +0200 Subject: [PATCH 1/4] checkpoints.cpp depends on main, it can use mapBlockIndex directly --- src/checkpoints.cpp | 2 +- src/checkpoints.h | 2 +- src/main.cpp | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 717f0b90f..343d5251f 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -146,7 +146,7 @@ namespace Checkpoints { return checkpoints.rbegin()->first; } - CBlockIndex* GetLastCheckpoint(const std::map& mapBlockIndex) + CBlockIndex* GetLastCheckpoint() { if (!fEnabled) return NULL; diff --git a/src/checkpoints.h b/src/checkpoints.h index 52cdc3555..6d3f2d493 100644 --- a/src/checkpoints.h +++ b/src/checkpoints.h @@ -22,7 +22,7 @@ namespace Checkpoints { int GetTotalBlocksEstimate(); // Returns last CBlockIndex* in mapBlockIndex that is a checkpoint - CBlockIndex* GetLastCheckpoint(const std::map& mapBlockIndex); + CBlockIndex* GetLastCheckpoint(); double GuessVerificationProgress(CBlockIndex *pindex, bool fSigchecks = true); diff --git a/src/main.cpp b/src/main.cpp index 4aebdadd3..a024461e2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2302,7 +2302,7 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex return state.Invalid(error("AcceptBlock() : block is marked invalid"), 0, "duplicate"); } - CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex); + CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(); if (pcheckpoint && block.hashPrevBlock != (chainActive.Tip() ? chainActive.Tip()->GetBlockHash() : uint256(0))) { // Extra checks to prevent "fill up memory by spamming with bogus blocks" @@ -2345,7 +2345,7 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex REJECT_CHECKPOINT, "checkpoint mismatch"); // Don't accept any forks from the main chain prior to last checkpoint - CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex); + CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(); if (pcheckpoint && nHeight < pcheckpoint->nHeight) return state.DoS(100, error("AcceptBlock() : forked chain older than last checkpoint (height %d)", nHeight)); @@ -3286,7 +3286,7 @@ void static ProcessGetData(CNode* pfrom) // If the requested block is at a height below our last // checkpoint, only serve it if it's in the checkpointed chain int nHeight = mi->second->nHeight; - CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex); + CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(); if (pcheckpoint && nHeight < pcheckpoint->nHeight) { if (!chainActive.Contains(mi->second)) { From 145d5be896db4e8fda17039bed26100e38fae2f0 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 4 Sep 2014 02:02:44 +0200 Subject: [PATCH 2/4] Introduce BlockMap type for mapBlockIndex --- src/checkpoints.cpp | 2 +- src/init.cpp | 2 +- src/main.cpp | 32 ++++++++++++++++---------------- src/main.h | 3 ++- src/qt/transactionrecord.cpp | 2 +- src/rpcblockchain.cpp | 2 +- src/rpcrawtransaction.cpp | 2 +- src/rpcwallet.cpp | 2 +- src/wallet.cpp | 6 +++--- 9 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 343d5251f..c41deea7c 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -156,7 +156,7 @@ namespace Checkpoints { BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, checkpoints) { const uint256& hash = i.second; - std::map::const_iterator t = mapBlockIndex.find(hash); + BlockMap::const_iterator t = mapBlockIndex.find(hash); if (t != mapBlockIndex.end()) return t->second; } diff --git a/src/init.cpp b/src/init.cpp index b8988f8b7..31f64878f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1031,7 +1031,7 @@ bool AppInit2(boost::thread_group& threadGroup) { string strMatch = mapArgs["-printblock"]; int nFound = 0; - for (map::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) + for (BlockMap::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) { uint256 hash = (*mi).first; if (boost::algorithm::starts_with(hash.ToString(), strMatch)) diff --git a/src/main.cpp b/src/main.cpp index a024461e2..2479beabd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,7 +38,7 @@ using namespace boost; CCriticalSection cs_main; -map mapBlockIndex; +BlockMap mapBlockIndex; CChain chainActive; int64_t nTimeBestReceived = 0; CWaitableCriticalSection csBestBlock; @@ -328,7 +328,7 @@ void ProcessBlockAvailability(NodeId nodeid) { assert(state != NULL); if (state->hashLastUnknownBlock != 0) { - map::iterator itOld = mapBlockIndex.find(state->hashLastUnknownBlock); + BlockMap::iterator itOld = mapBlockIndex.find(state->hashLastUnknownBlock); if (itOld != mapBlockIndex.end() && itOld->second->nChainWork > 0) { if (state->pindexBestKnownBlock == NULL || itOld->second->nChainWork >= state->pindexBestKnownBlock->nChainWork) state->pindexBestKnownBlock = itOld->second; @@ -344,7 +344,7 @@ void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) { ProcessBlockAvailability(nodeid); - map::iterator it = mapBlockIndex.find(hash); + BlockMap::iterator it = mapBlockIndex.find(hash); if (it != mapBlockIndex.end() && it->second->nChainWork > 0) { // An actually better block was announced. if (state->pindexBestKnownBlock == NULL || it->second->nChainWork >= state->pindexBestKnownBlock->nChainWork) @@ -434,7 +434,7 @@ CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const { CBlockIndex *CChain::FindFork(const CBlockLocator &locator) const { // Find the first block the caller has in the main chain BOOST_FOREACH(const uint256& hash, locator.vHave) { - std::map::iterator mi = mapBlockIndex.find(hash); + BlockMap::iterator mi = mapBlockIndex.find(hash); if (mi != mapBlockIndex.end()) { CBlockIndex* pindex = (*mi).second; @@ -2068,7 +2068,7 @@ CBlockIndex* AddToBlockIndex(CBlockHeader& block) { // Check for duplicate uint256 hash = block.GetHash(); - std::map::iterator it = mapBlockIndex.find(hash); + BlockMap::iterator it = mapBlockIndex.find(hash); if (it != mapBlockIndex.end()) return it->second; @@ -2079,9 +2079,9 @@ CBlockIndex* AddToBlockIndex(CBlockHeader& block) LOCK(cs_nBlockSequenceId); pindexNew->nSequenceId = nBlockSequenceId++; } - map::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; + BlockMap::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; pindexNew->phashBlock = &((*mi).first); - map::iterator miPrev = mapBlockIndex.find(block.hashPrevBlock); + BlockMap::iterator miPrev = mapBlockIndex.find(block.hashPrevBlock); if (miPrev != mapBlockIndex.end()) { pindexNew->pprev = (*miPrev).second; @@ -2294,7 +2294,7 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex AssertLockHeld(cs_main); // Check for duplicate uint256 hash = block.GetHash(); - std::map::iterator miSelf = mapBlockIndex.find(hash); + BlockMap::iterator miSelf = mapBlockIndex.find(hash); CBlockIndex *pindex = NULL; if (miSelf != mapBlockIndex.end()) { pindex = miSelf->second; @@ -2323,7 +2323,7 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex CBlockIndex* pindexPrev = NULL; int nHeight = 0; if (hash != Params().HashGenesisBlock()) { - map::iterator mi = mapBlockIndex.find(block.hashPrevBlock); + BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock); if (mi == mapBlockIndex.end()) return state.DoS(10, error("AcceptBlock() : prev block not found"), 0, "bad-prevblk"); pindexPrev = (*mi).second; @@ -2517,7 +2517,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl return error("ProcessBlock() : CheckBlock FAILED"); // If we don't already have its previous block (with full data), shunt it off to holding area until we get it - std::map::iterator it = mapBlockIndex.find(pblock->hashPrevBlock); + BlockMap::iterator it = mapBlockIndex.find(pblock->hashPrevBlock); if (pblock->hashPrevBlock != 0 && (it == mapBlockIndex.end() || !(it->second->nStatus & BLOCK_HAVE_DATA))) { LogPrintf("ProcessBlock: ORPHAN BLOCK %lu, prev=%s\n", (unsigned long)mapOrphanBlocks.size(), pblock->hashPrevBlock.ToString()); @@ -2799,7 +2799,7 @@ CBlockIndex * InsertBlockIndex(uint256 hash) return NULL; // Return existing - map::iterator mi = mapBlockIndex.find(hash); + BlockMap::iterator mi = mapBlockIndex.find(hash); if (mi != mapBlockIndex.end()) return (*mi).second; @@ -2876,7 +2876,7 @@ bool static LoadBlockIndexDB() LogPrintf("LoadBlockIndexDB(): transaction index %s\n", fTxIndex ? "enabled" : "disabled"); // Load pointer to end of best chain - std::map::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); + BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); if (it == mapBlockIndex.end()) return true; chainActive.SetTip(it->second); @@ -3034,7 +3034,7 @@ void PrintBlockTree() AssertLockHeld(cs_main); // pre-compute tree structure map > mapNext; - for (map::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) + for (BlockMap::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) { CBlockIndex* pindex = (*mi).second; mapNext[pindex->pprev].push_back(pindex); @@ -3280,7 +3280,7 @@ void static ProcessGetData(CNode* pfrom) if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK) { bool send = false; - map::iterator mi = mapBlockIndex.find(inv.hash); + BlockMap::iterator mi = mapBlockIndex.find(inv.hash); if (mi != mapBlockIndex.end()) { // If the requested block is at a height below our last @@ -3711,7 +3711,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (locator.IsNull()) { // If locator is null, return the hashStop block - map::iterator mi = mapBlockIndex.find(hashStop); + BlockMap::iterator mi = mapBlockIndex.find(hashStop); if (mi == mapBlockIndex.end()) return true; pindex = (*mi).second; @@ -4513,7 +4513,7 @@ public: CMainCleanup() {} ~CMainCleanup() { // block headers - std::map::iterator it1 = mapBlockIndex.begin(); + BlockMap::iterator it1 = mapBlockIndex.begin(); for (; it1 != mapBlockIndex.end(); it1++) delete (*it1).second; mapBlockIndex.clear(); diff --git a/src/main.h b/src/main.h index d38d033d2..da2b5cac8 100644 --- a/src/main.h +++ b/src/main.h @@ -85,7 +85,8 @@ static const unsigned char REJECT_CHECKPOINT = 0x43; extern CScript COINBASE_FLAGS; extern CCriticalSection cs_main; extern CTxMemPool mempool; -extern std::map mapBlockIndex; +typedef std::map BlockMap; +extern BlockMap mapBlockIndex; extern uint64_t nLastBlockTx; extern uint64_t nLastBlockSize; extern const std::string strMessageMagic; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index d7bd25e08..20c1449c9 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -170,7 +170,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) // Find the block the tx is in CBlockIndex* pindex = NULL; - std::map::iterator mi = mapBlockIndex.find(wtx.hashBlock); + BlockMap::iterator mi = mapBlockIndex.find(wtx.hashBlock); if (mi != mapBlockIndex.end()) pindex = (*mi).second; diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 83fe62935..4b3beae20 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -392,7 +392,7 @@ Value gettxout(const Array& params, bool fHelp) if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull()) return Value::null; - std::map::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); + BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); CBlockIndex *pindex = it->second; ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex())); if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT) diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 7cd704193..a73641834 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -88,7 +88,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry) if (hashBlock != 0) { entry.push_back(Pair("blockhash", hashBlock.GetHex())); - map::iterator mi = mapBlockIndex.find(hashBlock); + BlockMap::iterator mi = mapBlockIndex.find(hashBlock); if (mi != mapBlockIndex.end() && (*mi).second) { CBlockIndex* pindex = (*mi).second; if (chainActive.Contains(pindex)) { diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 215da2ea1..100d6c2bd 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -1447,7 +1447,7 @@ Value listsinceblock(const Array& params, bool fHelp) uint256 blockId = 0; blockId.SetHex(params[0].get_str()); - std::map::iterator it = mapBlockIndex.find(blockId); + BlockMap::iterator it = mapBlockIndex.find(blockId); if (it != mapBlockIndex.end()) pindex = it->second; } diff --git a/src/wallet.cpp b/src/wallet.cpp index 18a5b3971..d3ad4869b 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -2113,7 +2113,7 @@ void CWallet::GetKeyBirthTimes(std::map &mapKeyBirth) const { for (std::map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) { // iterate over all wallet transactions... const CWalletTx &wtx = (*it).second; - std::map::const_iterator blit = mapBlockIndex.find(wtx.hashBlock); + BlockMap::const_iterator blit = mapBlockIndex.find(wtx.hashBlock); if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) { // ... which are already in a block int nHeight = blit->second->nHeight; @@ -2233,7 +2233,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock) } // Is the tx in a block that's in the main chain - map::iterator mi = mapBlockIndex.find(hashBlock); + BlockMap::iterator mi = mapBlockIndex.find(hashBlock); if (mi == mapBlockIndex.end()) return 0; CBlockIndex* pindex = (*mi).second; @@ -2250,7 +2250,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const AssertLockHeld(cs_main); // Find the block it claims to be in - map::iterator mi = mapBlockIndex.find(hashBlock); + BlockMap::iterator mi = mapBlockIndex.find(hashBlock); if (mi == mapBlockIndex.end()) return 0; CBlockIndex* pindex = (*mi).second; From 8a41e1edd4d31d08b7360d7e5964c1c40a7aa1b6 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 4 Sep 2014 02:03:17 +0200 Subject: [PATCH 3/4] Use boost::unordered_map for mapBlockIndex --- src/main.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main.h b/src/main.h index da2b5cac8..8c0a743e2 100644 --- a/src/main.h +++ b/src/main.h @@ -29,6 +29,8 @@ #include #include +#include + class CBlockIndex; class CBloomFilter; class CInv; @@ -81,11 +83,15 @@ static const unsigned char REJECT_DUST = 0x41; static const unsigned char REJECT_INSUFFICIENTFEE = 0x42; static const unsigned char REJECT_CHECKPOINT = 0x43; +struct BlockHasher +{ + size_t operator()(const uint256& hash) const { return hash.GetLow64(); } +}; extern CScript COINBASE_FLAGS; extern CCriticalSection cs_main; extern CTxMemPool mempool; -typedef std::map BlockMap; +typedef boost::unordered_map BlockMap; extern BlockMap mapBlockIndex; extern uint64_t nLastBlockTx; extern uint64_t nLastBlockSize; From 1e4f87f5a13e34a457b537e9d13a212e6c5b754f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 4 Sep 2014 02:03:39 +0200 Subject: [PATCH 4/4] Use memcmp for uint256 equality/inequality --- src/uint256.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/uint256.h b/src/uint256.h index d1a822af0..6bb9a5940 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -10,6 +10,7 @@ #include #include #include +#include #include class uint_error : public std::runtime_error { @@ -215,8 +216,8 @@ public: friend inline const base_uint operator>>(const base_uint& a, int shift) { return base_uint(a) >>= shift; } friend inline const base_uint operator<<(const base_uint& a, int shift) { return base_uint(a) <<= shift; } friend inline const base_uint operator*(const base_uint& a, uint32_t b) { return base_uint(a) *= b; } - friend inline bool operator==(const base_uint& a, const base_uint& b) { return a.CompareTo(b) == 0; } - friend inline bool operator!=(const base_uint& a, const base_uint& b) { return a.CompareTo(b) != 0; } + friend inline bool operator==(const base_uint& a, const base_uint& b) { return memcmp(a.pn, b.pn, sizeof(a.pn)) == 0; } + friend inline bool operator!=(const base_uint& a, const base_uint& b) { return memcmp(a.pn, b.pn, sizeof(a.pn)) != 0; } friend inline bool operator>(const base_uint& a, const base_uint& b) { return a.CompareTo(b) > 0; } friend inline bool operator<(const base_uint& a, const base_uint& b) { return a.CompareTo(b) < 0; } friend inline bool operator>=(const base_uint& a, const base_uint& b) { return a.CompareTo(b) >= 0; }