aboutsummaryrefslogtreecommitdiff
path: root/src/validation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/validation.cpp')
-rw-r--r--src/validation.cpp95
1 files changed, 54 insertions, 41 deletions
diff --git a/src/validation.cpp b/src/validation.cpp
index 7312be3abc..fceb135854 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -17,7 +17,6 @@
#include <cuckoocache.h>
#include <hash.h>
#include <index/txindex.h>
-#include <init.h>
#include <policy/fees.h>
#include <policy/policy.h>
#include <policy/rbf.h>
@@ -29,6 +28,7 @@
#include <script/script.h>
#include <script/sigcache.h>
#include <script/standard.h>
+#include <shutdown.h>
#include <timedata.h>
#include <tinyformat.h>
#include <txdb.h>
@@ -45,7 +45,6 @@
#include <sstream>
#include <boost/algorithm/string/replace.hpp>
-#include <boost/algorithm/string/join.hpp>
#include <boost/thread.hpp>
#if defined(NDEBUG)
@@ -157,7 +156,7 @@ public:
std::multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked;
CBlockIndex *pindexBestInvalid = nullptr;
- bool LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree);
+ bool LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock);
@@ -165,8 +164,8 @@ 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.
*/
- bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex);
- bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock);
+ 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);
// Block (dis)connection on a given view:
DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view);
@@ -177,9 +176,9 @@ public:
bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions *disconnectpool);
// Manual block validity manipulation:
- bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex);
- bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex);
- bool ResetBlockFailureFlags(CBlockIndex *pindex);
+ bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
+ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool ReplayBlocks(const CChainParams& params, CCoinsView* view);
bool RewindBlockIndex(const CChainParams& params);
@@ -193,9 +192,9 @@ private:
bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace);
bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool);
- CBlockIndex* AddToBlockIndex(const CBlockHeader& block);
+ CBlockIndex* AddToBlockIndex(const CBlockHeader& block) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Create a new block index entry for a given block hash */
- CBlockIndex * InsertBlockIndex(const uint256& hash);
+ CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Make various assertions about the state of the block index.
*
@@ -204,11 +203,11 @@ private:
void CheckBlockIndex(const Consensus::Params& consensusParams);
void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state);
- CBlockIndex* FindMostWorkChain();
- void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams);
+ CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params);
+ bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
} g_chainstate;
@@ -651,7 +650,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
view.SetBackend(viewMemPool);
// do all inputs exist?
- for (const CTxIn txin : tx.vin) {
+ for (const CTxIn& txin : tx.vin) {
if (!pcoinsTip->HaveCoinInCache(txin.prevout)) {
coins_to_uncache.push_back(txin.prevout);
}
@@ -806,13 +805,11 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// be increased is also an easy-to-reason about way to prevent
// DoS attacks via replacements.
//
- // The mining code doesn't (currently) take children into
- // account (CPFP) so we only consider the feerates of
- // transactions being directly replaced, not their indirect
- // descendants. While that does mean high feerate children are
- // ignored when deciding whether or not to replace, we do
- // require the replacement to pay more overall fees too,
- // mitigating most cases.
+ // We only consider the feerates of transactions being directly
+ // replaced, not their indirect descendants. While that does
+ // mean high feerate children are ignored when deciding whether
+ // or not to replace, we do require the replacement to pay more
+ // overall fees too, mitigating most cases.
CFeeRate oldFeeRate(mi->GetModifiedFee(), mi->GetTxSize());
if (newFeeRate <= oldFeeRate)
{
@@ -942,7 +939,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
}
// Remove conflicting transactions from the mempool
- for (const CTxMemPool::txiter it : allConflicting)
+ for (CTxMemPool::txiter it : allConflicting)
{
LogPrint(BCLog::MEMPOOL, "replacing tx %s with %s for %s BTC additional fees, %d delta bytes\n",
it->GetTx().GetHash().ToString(),
@@ -2229,6 +2226,13 @@ static void DoWarning(const std::string& strWarning)
}
}
+/** Private helper function that concatenates warning messages. */
+static void AppendWarning(std::string& res, const std::string& warn)
+{
+ if (!res.empty()) res += ", ";
+ res += warn;
+}
+
/** Check warning conditions and do some notifications on new chain tip set. */
void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainParams) {
// New best block
@@ -2240,7 +2244,7 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
g_best_block_cv.notify_all();
}
- std::vector<std::string> warningMessages;
+ std::string warningMessages;
if (!IsInitialBlockDownload())
{
int nUpgraded = 0;
@@ -2253,7 +2257,7 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
if (state == ThresholdState::ACTIVE) {
DoWarning(strWarning);
} else {
- warningMessages.push_back(strWarning);
+ AppendWarning(warningMessages, strWarning);
}
}
}
@@ -2266,7 +2270,7 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
pindex = pindex->pprev;
}
if (nUpgraded > 0)
- warningMessages.push_back(strprintf(_("%d of last 100 blocks have unexpected version"), nUpgraded));
+ AppendWarning(warningMessages, strprintf(_("%d of last 100 blocks have unexpected version"), nUpgraded));
if (nUpgraded > 100/2)
{
std::string strWarning = _("Warning: Unknown block versions being mined! It's possible unknown rules are in effect");
@@ -2280,7 +2284,7 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
FormatISO8601DateTime(pindexNew->GetBlockTime()),
GuessVerificationProgress(chainParams.TxData(), pindexNew), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
if (!warningMessages.empty())
- LogPrintf(" warning='%s'", boost::algorithm::join(warningMessages, ", ")); /* Continued */
+ LogPrintf(" warning='%s'", warningMessages); /* Continued */
LogPrintf("\n");
}
@@ -2630,7 +2634,7 @@ bool CChainState::ActivateBestChainStep(CValidationState& state, const CChainPar
return true;
}
-static void NotifyHeaderTip() {
+static void NotifyHeaderTip() LOCKS_EXCLUDED(cs_main) {
bool fNotify = false;
bool fInitialBlockDownload = false;
static CBlockIndex* pindexHeaderOld = nullptr;
@@ -2863,7 +2867,7 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C
return g_chainstate.InvalidateBlock(state, chainparams, pindex);
}
-bool CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
+void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
AssertLockHeld(cs_main);
int nHeight = pindex->nHeight;
@@ -2895,9 +2899,9 @@ bool CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
}
pindex = pindex->pprev;
}
- return true;
}
-bool ResetBlockFailureFlags(CBlockIndex *pindex) {
+
+void ResetBlockFailureFlags(CBlockIndex *pindex) {
return g_chainstate.ResetBlockFailureFlags(pindex);
}
@@ -3380,7 +3384,7 @@ bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState&
return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
// If the previous block index isn't valid, determine if it descends from any block which
- // has been found invalid (g_failed_blocks), then mark pindexPrev and any blocks
+ // has been found invalid (m_failed_blocks), then mark pindexPrev and any blocks
// between them as failed.
if (!pindexPrev->IsValid(BLOCK_VALID_SCRIPTS)) {
for (const CBlockIndex* failedit : m_failed_blocks) {
@@ -3714,6 +3718,15 @@ static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfte
int count=0;
if (nCurrentUsage + nBuffer >= nPruneTarget) {
+ // On a prune event, the chainstate DB is flushed.
+ // To avoid excessive prune events negating the benefit of high dbcache
+ // values, we should not prune too rapidly.
+ // So when pruning in IBD, increase the buffer a bit to avoid a re-prune too soon.
+ if (IsInitialBlockDownload()) {
+ // Since this is only relevant during IBD, we use a fixed 10%
+ nBuffer += nPruneTarget / 10;
+ }
+
for (int fileNumber = 0; fileNumber < nLastBlockFile; fileNumber++) {
nBytesToPrune = vinfoBlockFile[fileNumber].nSize + vinfoBlockFile[fileNumber].nUndoSize;
@@ -3811,7 +3824,7 @@ CBlockIndex * CChainState::InsertBlockIndex(const uint256& hash)
bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree)
{
- if (!blocktree.LoadBlockIndexGuts(consensus_params, [this](const uint256& hash){ return this->InsertBlockIndex(hash); }))
+ if (!blocktree.LoadBlockIndexGuts(consensus_params, [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); }))
return false;
boost::this_thread::interruption_point();
@@ -3861,7 +3874,7 @@ bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlo
return true;
}
-bool static LoadBlockIndexDB(const CChainParams& chainparams)
+bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
if (!g_chainstate.LoadBlockIndex(chainparams.GetConsensus(), *pblocktree))
return false;
@@ -3969,14 +3982,13 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
nCheckLevel = std::max(0, std::min(4, nCheckLevel));
LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
CCoinsViewCache coins(coinsview);
- CBlockIndex* pindexState = chainActive.Tip();
+ CBlockIndex* pindex;
CBlockIndex* pindexFailure = nullptr;
int nGoodTransactions = 0;
CValidationState state;
int reportDone = 0;
LogPrintf("[0%%]..."); /* Continued */
- for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev)
- {
+ for (pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) {
boost::this_thread::interruption_point();
int percentageDone = std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
if (reportDone < percentageDone/10) {
@@ -4010,13 +4022,12 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
}
}
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks
- if (nCheckLevel >= 3 && pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) {
+ if (nCheckLevel >= 3 && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) {
assert(coins.GetBestBlock() == pindex->GetBlockHash());
DisconnectResult res = g_chainstate.DisconnectBlock(block, pindex, coins);
if (res == DISCONNECT_FAILED) {
return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
}
- pindexState = pindex->pprev;
if (res == DISCONNECT_UNCLEAN) {
nGoodTransactions = 0;
pindexFailure = pindex;
@@ -4030,9 +4041,11 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
if (pindexFailure)
return error("VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainActive.Height() - pindexFailure->nHeight + 1, nGoodTransactions);
+ // store block count as we move pindex at check level >= 4
+ int block_count = chainActive.Height() - pindex->nHeight;
+
// check level 4: try reconnecting blocks
if (nCheckLevel >= 4) {
- CBlockIndex *pindex = pindexState;
while (pindex != chainActive.Tip()) {
boost::this_thread::interruption_point();
uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50))), false);
@@ -4046,7 +4059,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
}
LogPrintf("[DONE].\n");
- LogPrintf("No coin database inconsistencies in last %i blocks (%i transactions)\n", chainActive.Height() - pindexState->nHeight, nGoodTransactions);
+ LogPrintf("No coin database inconsistencies in last %i blocks (%i transactions)\n", block_count, nGoodTransactions);
return true;
}