fixed slow loading of block index, increased wallet flush period

This commit is contained in:
Brannon King 2020-01-27 17:38:38 -07:00
parent c7c0d44c13
commit b14c7bb3be
13 changed files with 75 additions and 81 deletions

View file

@ -141,25 +141,25 @@ std::string CBaseBlob<BITS>::ToString() const
template<uint32_t BITS>
uint8_t* CBaseBlob<BITS>::begin() noexcept
{
return data.begin();
return data.data();
}
template<uint32_t BITS>
const uint8_t* CBaseBlob<BITS>::begin() const noexcept
{
return data.begin();
return data.data();
}
template<uint32_t BITS>
uint8_t* CBaseBlob<BITS>::end() noexcept
{
return data.end();
return data.data() + data.size();
}
template<uint32_t BITS>
const uint8_t* CBaseBlob<BITS>::end() const noexcept
{
return data.end();
return data.data() + data.size();
}
template<uint32_t BITS>

View file

@ -1213,6 +1213,8 @@ bool AppInitLockDataDirectory()
return true;
}
extern CChainState g_chainstate;
bool AppInitMain()
{
const CChainParams& chainparams = Params();
@ -1481,7 +1483,7 @@ bool AppInitMain()
// If the loaded chain has a wrong genesis, bail out immediately
// (we're likely using a testnet datadir, or the other way around).
if (!mapBlockIndex.empty() && !LookupBlockIndex(chainparams.GetConsensus().hashGenesisBlock)) {
if (!g_chainstate.mapBlockIndex.empty() && !LookupBlockIndex(chainparams.GetConsensus().hashGenesisBlock)) {
return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
}
@ -1711,7 +1713,6 @@ bool AppInitMain()
//// debug print
{
LOCK(cs_main);
LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size());
chain_active_height = chainActive.Height();
}
LogPrintf("nBestHeight = %d\n", chain_active_height);

View file

@ -88,8 +88,7 @@ WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
WalletTxStatus MakeWalletTxStatus(const CWalletTx& wtx)
{
WalletTxStatus result;
auto mi = ::mapBlockIndex.find(wtx.hashBlock);
CBlockIndex* block = mi != ::mapBlockIndex.end() ? mi->second : nullptr;
CBlockIndex* block = LookupBlockIndex(wtx.hashBlock);
result.block_height = (block ? block->nHeight : std::numeric_limits<int>::max());
result.blocks_to_maturity = wtx.GetBlocksToMaturity();
result.depth_in_main_chain = wtx.GetDepthInMainChain();

View file

@ -1299,6 +1299,8 @@ struct CompareBlocksByHeight
}
};
extern CChainState g_chainstate;
static UniValue getchaintips(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
@ -1347,7 +1349,7 @@ static UniValue getchaintips(const JSONRPCRequest& request)
std::set<const CBlockIndex*> setOrphans;
std::set<const CBlockIndex*> setPrevs;
for (const std::pair<const uint256, CBlockIndex*>& item : mapBlockIndex)
for (const auto& item : g_chainstate.mapBlockIndex)
{
if (!chainActive.Contains(item.second)) {
setOrphans.insert(item.second);

View file

@ -33,16 +33,15 @@ void ParseClaimtrieId(const UniValue& v, std::string& claimId, const std::string
static CBlockIndex* BlockHashIndex(const uint256& blockHash)
{
AssertLockHeld(cs_main);
auto index = LookupBlockIndex(blockHash);
if (mapBlockIndex.count(blockHash) == 0)
if (index == nullptr)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
CBlockIndex* pblockIndex = mapBlockIndex[blockHash];
if (!chainActive.Contains(pblockIndex))
if (!chainActive.Contains(index))
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not in main chain");
return pblockIndex;
return index;
}
#define MAX_RPC_BLOCK_DECREMENTS 500

View file

@ -361,29 +361,33 @@ bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams,
{
auto query = db << "SELECT hash, prevHash, height, file, dataPos, undoPos, txCount, "
"version, rootTxHash, rootTrieHash, time, bits, nonce, status "
"FROM block_info"; // insertBlockIndex puts them in order
"FROM block_info ORDER BY height";
// Load mapBlockIndex
for (auto&& row: query) {
boost::this_thread::interruption_point();
// Construct block index object
uint256 hash, prevHash;
row >> hash >> prevHash;
CBlockIndex* pindexNew = insertBlockIndex(hash);
pindexNew->pprev = insertBlockIndex(prevHash);
row >> pindexNew->nHeight;
row >> pindexNew->nFile;
row >> pindexNew->nDataPos;
row >> pindexNew->nUndoPos;
row >> pindexNew->nTx;
row >> pindexNew->nVersion;
row >> pindexNew->hashMerkleRoot;
row >> pindexNew->hashClaimTrie;
row >> pindexNew->nTime;
row >> pindexNew->nBits;
row >> pindexNew->nNonce;
row >> pindexNew->nStatus;
row >> pindexNew->nHeight
>> pindexNew->nFile
>> pindexNew->nDataPos
>> pindexNew->nUndoPos
>> pindexNew->nTx
>> pindexNew->nVersion
>> pindexNew->hashMerkleRoot
>> pindexNew->hashClaimTrie
>> pindexNew->nTime
>> pindexNew->nBits
>> pindexNew->nNonce
>> pindexNew->nStatus;
if ((pindexNew->nHeight & 0x3ff) == 0x3ff) { // don't check for shutdown on every single block
boost::this_thread::interruption_point();
if (ShutdownRequested())
return false;
}
pindexNew->nChainTx = pindexNew->pprev ? pindexNew->pprev->nChainTx + pindexNew->nTx : pindexNew->nTx;

View file

@ -62,7 +62,6 @@
CChainState g_chainstate;
CCriticalSection cs_main;
BlockMap& mapBlockIndex = g_chainstate.mapBlockIndex;
CChain& chainActive = g_chainstate.chainActive;
CBlockIndex *pindexBestHeader = nullptr;
CWaitableCriticalSection g_best_block_mutex;
@ -3662,7 +3661,7 @@ void PruneOneBlockFile(const int fileNumber)
{
LOCK(cs_LastBlockFile);
for (const auto& entry : mapBlockIndex) {
for (const auto& entry : g_chainstate.mapBlockIndex) {
CBlockIndex* pindex = entry.second;
if (pindex->nFile == fileNumber) {
pindex->nStatus &= ~BLOCK_HAVE_DATA;
@ -3857,18 +3856,18 @@ CBlockIndex * CChainState::InsertBlockIndex(const uint256& hash)
{
AssertLockHeld(cs_main);
// Return existing
auto mi = mapBlockIndex.find(hash);
if (mi != mapBlockIndex.end())
return mi->second;
if (hash.IsNull())
return nullptr;
// Return existing
BlockMap::iterator mi = mapBlockIndex.find(hash);
if (mi != mapBlockIndex.end())
return (*mi).second;
// Create new
CBlockIndex* pindexNew = new CBlockIndex();
mi = mapBlockIndex.insert(std::make_pair(hash, pindexNew)).first;
pindexNew->phashBlock = &((*mi).first);
pindexNew->phashBlock = &(mi->first);
return pindexNew;
}
@ -3950,14 +3949,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 : mapBlockIndex)
for (const std::pair<const uint256, CBlockIndex*>& item : g_chainstate.mapBlockIndex)
{
CBlockIndex* pindex = item.second;
if (pindex->nStatus & BLOCK_HAVE_DATA) {
setBlkDataFiles.insert(pindex->nFile);
}
}
for (std::set<int>::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++)
for (auto it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); ++it)
{
CDiskBlockPos pos(*it, 0);
if (CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION).IsNull()) {
@ -3984,7 +3983,7 @@ bool LoadChainTip(const CChainParams& chainparams)
if (chainActive.Tip() && chainActive.Tip()->GetBlockHash() == pcoinsTip->GetBestBlock()) return true;
if (pcoinsTip->GetBestBlock().IsNull() && mapBlockIndex.size() == 1) {
if (pcoinsTip->GetBestBlock().IsNull() && g_chainstate.mapBlockIndex.size() == 1) {
// In case we just added the genesis block, connect it now, so
// that we always have a chainActive.Tip() when we return.
LogPrintf("%s: Connecting genesis block...\n", __func__);
@ -4344,10 +4343,10 @@ void UnloadBlockIndex()
warningcache[b].clear();
}
for (BlockMap::value_type& entry : mapBlockIndex) {
for (BlockMap::value_type& entry : g_chainstate.mapBlockIndex) {
delete entry.second;
}
mapBlockIndex.clear();
g_chainstate.mapBlockIndex.clear();
fHavePruned = false;
g_chainstate.UnloadBlockIndex();
@ -4360,7 +4359,7 @@ bool LoadBlockIndex(const CChainParams& chainparams)
if (!fReindex) {
bool ret = LoadBlockIndexDB(chainparams);
if (!ret) return false;
needs_init = mapBlockIndex.empty();
needs_init = g_chainstate.mapBlockIndex.empty();
if (needs_init) {
auto blockDir = GetDataDir() / "blocks";
@ -4899,15 +4898,21 @@ double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex *pin
return pindex->nChainTx / fTxTotal;
}
CBlockIndex *LookupBlockIndex(const uint256 &hash) {
AssertLockHeld(cs_main);
auto it = g_chainstate.mapBlockIndex.find(hash);
return it == g_chainstate.mapBlockIndex.end() ? nullptr : it->second;
}
class CMainCleanup
{
public:
CMainCleanup() {}
~CMainCleanup() {
// block headers
BlockMap::iterator it1 = mapBlockIndex.begin();
for (; it1 != mapBlockIndex.end(); it1++)
auto it1 = g_chainstate.mapBlockIndex.begin();
for (; it1 != g_chainstate.mapBlockIndex.end(); ++it1)
delete (*it1).second;
mapBlockIndex.clear();
g_chainstate.mapBlockIndex.clear();
}
} instance_of_cmaincleanup;

View file

@ -139,18 +139,12 @@ static const bool DEFAULT_PEERBLOOMFILTERS = true;
/** Default for -stopatheight */
static const int DEFAULT_STOPATHEIGHT = 0;
struct BlockHasher
{
size_t operator()(const uint256& hash) const { return GetCheapHash(hash); }
};
extern CScript COINBASE_FLAGS;
extern CCriticalSection cs_main;
extern CBlockPolicyEstimator feeEstimator;
extern CTxMemPool mempool;
extern std::atomic_bool g_is_mempool_loaded;
typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
extern BlockMap& mapBlockIndex;
typedef std::map<uint256, CBlockIndex*> BlockMap;
extern uint64_t nLastBlockTx;
extern uint64_t nLastBlockWeight;
extern const std::string strMessageMagic;
@ -465,7 +459,7 @@ public:
/**
* 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 mapBlockIndex.
*/
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@ -597,12 +591,7 @@ public:
/** Replay blocks that aren't fully applied to the database. */
bool ReplayBlocks(const CChainParams& params, CCoinsView* view);
inline CBlockIndex* LookupBlockIndex(const uint256& hash)
{
AssertLockHeld(cs_main);
BlockMap::const_iterator it = mapBlockIndex.find(hash);
return it == mapBlockIndex.end() ? nullptr : it->second;
}
CBlockIndex* LookupBlockIndex(const uint256& hash);
/** Find the last common block between the parameter chain and a locator. */
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator);

View file

@ -245,7 +245,7 @@ void WalletInit::Start(CScheduler& scheduler) const
}
// Run a thread to flush wallet periodically
scheduler.scheduleEvery(MaybeCompactWalletDB, 500);
scheduler.scheduleEvery(MaybeCompactWalletDB, 1000);
}
void WalletInit::Flush() const

View file

@ -765,23 +765,19 @@ void ListNameClaims(const CWalletTx& wtx, CWallet* const pwallet, const std::str
CClaimTrieCache trieCache(pclaimTrie);
auto it = mapBlockIndex.find(wtx.hashBlock);
if (it != mapBlockIndex.end())
auto pindex = LookupBlockIndex(wtx.hashBlock);
if (pindex)
{
CBlockIndex* pindex = it->second;
if (pindex)
entry.pushKV("height", pindex->nHeight);
entry.pushKV("expiration height", pindex->nHeight + trieCache.expirationTime());
if (pindex->nHeight + trieCache.expirationTime() > chainActive.Height())
{
entry.pushKV("height", pindex->nHeight);
entry.pushKV("expiration height", pindex->nHeight + trieCache.expirationTime());
if (pindex->nHeight + trieCache.expirationTime() > chainActive.Height())
{
entry.pushKV("expired", false);
entry.pushKV("blocks to expiration", pindex->nHeight + trieCache.expirationTime() - chainActive.Height());
}
else
{
entry.pushKV("expired", true);
}
entry.pushKV("expired", false);
entry.pushKV("blocks to expiration", pindex->nHeight + trieCache.expirationTime() - chainActive.Height());
}
else
{
entry.pushKV("expired", true);
}
}
entry.pushKV("confirmations", wtx.GetDepthInMainChain());

View file

@ -5,6 +5,7 @@
#ifndef BITCOIN_WALLET_RPCWALLET_H
#define BITCOIN_WALLET_RPCWALLET_H
#include <memory>
#include <string>
class CRPCTable;

View file

@ -1,5 +1,3 @@
#include <memory>
#include <set>
#include <utility>
#include <vector>
@ -13,7 +11,6 @@
#include <test/test_bitcoin.h>
#include <validation.h>
#include <wallet/coincontrol.h>
#include <wallet/test/wallet_test_fixture.h>
#include <policy/policy.h>
#include <boost/test/unit_test.hpp>
@ -125,7 +122,7 @@ void rollbackBlock(const std::vector<uint256>& ids) {
}
// totally weird that invalidateblock is async
while (GetMainSignals().CallbacksPending())
usleep(5000);
MilliSleep(5);
}
uint256 AbandonAClaim(const uint256& txid, bool isSupport = false) {

View file

@ -24,6 +24,7 @@
extern UniValue importmulti(const JSONRPCRequest& request);
extern UniValue dumpwallet(const JSONRPCRequest& request);
extern UniValue importwallet(const JSONRPCRequest& request);
extern CChainState g_chainstate;
BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup)
@ -206,7 +207,7 @@ static int64_t AddTx(CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64
CBlockIndex* block = nullptr;
if (blockTime > 0) {
LOCK(cs_main);
auto inserted = mapBlockIndex.emplace(GetRandHash(), new CBlockIndex);
auto inserted = g_chainstate.mapBlockIndex.emplace(GetRandHash(), new CBlockIndex);
assert(inserted.second);
const uint256& hash = inserted.first->first;
block = inserted.first->second;