Auto merge of #4770 - nuttycom:fastsync, r=nuttycom
Add -ibdskiptxverification flag to allow faster synchronization. Subsumes #4037
This commit is contained in:
commit
b076c8dfc5
|
@ -78,4 +78,12 @@ namespace Checkpoints {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool IsAncestorOfLastCheckpoint(const CCheckpointData& data, const CBlockIndex* pindex)
|
||||
{
|
||||
CBlockIndex *pindexLastCheckpoint = GetLastCheckpoint(data);
|
||||
return pindexLastCheckpoint && pindexLastCheckpoint->GetAncestor(pindex->nHeight) == pindex;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Checkpoints
|
||||
|
|
|
@ -27,6 +27,7 @@ CBlockIndex* GetLastCheckpoint(const CCheckpointData& data);
|
|||
|
||||
double GuessVerificationProgress(const CCheckpointData& data, CBlockIndex* pindex, bool fSigchecks = true);
|
||||
|
||||
bool IsAncestorOfLastCheckpoint(const CCheckpointData& data, const CBlockIndex* pindex);
|
||||
} //namespace Checkpoints
|
||||
|
||||
#endif // BITCOIN_CHECKPOINTS_H
|
||||
|
|
|
@ -32,7 +32,7 @@ TEST(CheckBlock, VersionTooLow) {
|
|||
|
||||
MockCValidationState state;
|
||||
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "version-too-low", false)).Times(1);
|
||||
EXPECT_FALSE(CheckBlock(block, state, Params(), verifier, false, false));
|
||||
EXPECT_FALSE(CheckBlock(block, state, Params(), verifier, false, false, true));
|
||||
}
|
||||
|
||||
|
||||
|
@ -65,7 +65,7 @@ TEST(CheckBlock, BlockSproutRejectsBadVersion) {
|
|||
auto verifier = ProofVerifier::Strict();
|
||||
|
||||
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-version-too-low", false)).Times(1);
|
||||
EXPECT_FALSE(CheckBlock(block, state, Params(), verifier, false, false));
|
||||
EXPECT_FALSE(CheckBlock(block, state, Params(), verifier, false, false, true));
|
||||
}
|
||||
|
||||
|
||||
|
@ -119,7 +119,7 @@ protected:
|
|||
|
||||
// We now expect this to be a valid block.
|
||||
MockCValidationState state;
|
||||
EXPECT_TRUE(ContextualCheckBlock(block, state, Params(), &indexPrev));
|
||||
EXPECT_TRUE(ContextualCheckBlock(block, state, Params(), &indexPrev, true));
|
||||
}
|
||||
|
||||
// Expects a height-1 block containing a given transaction to fail
|
||||
|
@ -137,7 +137,7 @@ protected:
|
|||
// We now expect this to be an invalid block, for the given reason.
|
||||
MockCValidationState state;
|
||||
EXPECT_CALL(state, DoS(level, false, REJECT_INVALID, reason, false)).Times(1);
|
||||
EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev));
|
||||
EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev, true));
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -154,7 +154,7 @@ TEST_F(ContextualCheckBlockTest, BadCoinbaseHeight) {
|
|||
|
||||
// Treating block as genesis should pass
|
||||
MockCValidationState state;
|
||||
EXPECT_TRUE(ContextualCheckBlock(block, state, Params(), NULL));
|
||||
EXPECT_TRUE(ContextualCheckBlock(block, state, Params(), NULL, true));
|
||||
|
||||
// Give the transaction a Founder's Reward vout
|
||||
mtx.vout.push_back(CTxOut(
|
||||
|
@ -168,20 +168,20 @@ TEST_F(ContextualCheckBlockTest, BadCoinbaseHeight) {
|
|||
CBlockIndex indexPrev {prev};
|
||||
indexPrev.nHeight = 0;
|
||||
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1);
|
||||
EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev));
|
||||
EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev, true));
|
||||
|
||||
// Setting to an incorrect height should fail
|
||||
mtx.vin[0].scriptSig = CScript() << 2 << OP_0;
|
||||
CTransaction tx3 {mtx};
|
||||
block.vtx[0] = tx3;
|
||||
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1);
|
||||
EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev));
|
||||
EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev, true));
|
||||
|
||||
// After correcting the scriptSig, should pass
|
||||
mtx.vin[0].scriptSig = CScript() << 1 << OP_0;
|
||||
CTransaction tx4 {mtx};
|
||||
block.vtx[0] = tx4;
|
||||
EXPECT_TRUE(ContextualCheckBlock(block, state, Params(), &indexPrev));
|
||||
EXPECT_TRUE(ContextualCheckBlock(block, state, Params(), &indexPrev, true));
|
||||
}
|
||||
|
||||
// TEST PLAN: first, check that each ruleset accepts its own transaction type.
|
||||
|
|
18
src/init.cpp
18
src/init.cpp
|
@ -343,6 +343,7 @@ std::string HelpMessage(HelpMessageMode mode)
|
|||
strUsage += HelpMessageOpt("-dbcache=<n>", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache));
|
||||
strUsage += HelpMessageOpt("-debuglogfile=<file>", strprintf(_("Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)"), DEFAULT_DEBUGLOGFILE));
|
||||
strUsage += HelpMessageOpt("-exportdir=<dir>", _("Specify directory to be used when exporting data"));
|
||||
strUsage += HelpMessageOpt("-ibdskiptxverification", strprintf(_("Skip transaction verification during initial block download up to the last checkpoint height. Incompatible with flags that disable checkpoints. (default = %u)"), DEFAULT_IBD_SKIP_TX_VERIFICATION));
|
||||
strUsage += HelpMessageOpt("-loadblock=<file>", _("Imports blocks from external blk000??.dat file on startup"));
|
||||
strUsage += HelpMessageOpt("-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS));
|
||||
strUsage += HelpMessageOpt("-par=<n>", strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"),
|
||||
|
@ -420,13 +421,13 @@ std::string HelpMessage(HelpMessageMode mode)
|
|||
strUsage += HelpMessageOpt("-nuparams=hexBranchId:activationHeight", "Use given activation height for specified network upgrade (regtest-only)");
|
||||
strUsage += HelpMessageOpt("-nurejectoldversions", strprintf("Reject peers that don't know about the current epoch (regtest-only) (default: %u)", DEFAULT_NU_REJECT_OLD_VERSIONS));
|
||||
strUsage += HelpMessageOpt(
|
||||
"-fundingstream=streamId:startHeight:endHeight:comma_delimited_addresses",
|
||||
"-fundingstream=streamId:startHeight:endHeight:comma_delimited_addresses",
|
||||
"Use given addresses for block subsidy share paid to the funding stream with id <streamId> (regtest-only)");
|
||||
}
|
||||
string debugCategories = "addrman, alert, bench, coindb, db, estimatefee, http, libevent, lock, mempool, net, partitioncheck, pow, proxy, prune, "
|
||||
"rand, receiveunsafe, reindex, rpc, selectcoins, tor, zmq, zrpc, zrpcunsafe (implies zrpc)"; // Don't translate these
|
||||
strUsage += HelpMessageOpt("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " +
|
||||
_("If <category> is not supplied or if <category> = 1, output all debugging information.") + " " + _("<category> can be:") + " " + debugCategories + ". " +
|
||||
_("If <category> is not supplied or if <category> = 1, output all debugging information.") + " " + _("<category> can be:") + " " + debugCategories + ". " +
|
||||
_("For multiple specific categories use -debug=<category> multiple times."));
|
||||
strUsage += HelpMessageOpt("-experimentalfeatures", _("Enable use of experimental features"));
|
||||
strUsage += HelpMessageOpt("-help-debug", _("Show all debugging options (usage: --help -help-debug)"));
|
||||
|
@ -923,6 +924,14 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||
#endif
|
||||
}
|
||||
|
||||
// ensure that the user has not disabled checkpoints when requesting to
|
||||
// skip transaction verification in initial block download.
|
||||
if (GetBoolArg("-ibdskiptxverification", DEFAULT_IBD_SKIP_TX_VERIFICATION)) {
|
||||
if (!GetBoolArg("-checkpoints", DEFAULT_CHECKPOINTS_ENABLED)) {
|
||||
return InitError(_("-ibdskiptxverification requires checkpoints to be enabled; it is incompatible with flags that disable checkpoints"));
|
||||
}
|
||||
}
|
||||
|
||||
// ********************************************************* Step 3: parameter-to-internal-flags
|
||||
|
||||
fDebug = !mapMultiArgs["-debug"].empty();
|
||||
|
@ -964,6 +973,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||
mempool.SetMempoolCostLimit(mempoolTotalCostLimit, mempoolEvictionMemorySeconds);
|
||||
|
||||
fCheckBlockIndex = GetBoolArg("-checkblockindex", chainparams.DefaultConsistencyChecks());
|
||||
fIBDSkipTxVerification = GetBoolArg("-ibdskiptxverification", DEFAULT_IBD_SKIP_TX_VERIFICATION);
|
||||
fCheckpointsEnabled = GetBoolArg("-checkpoints", DEFAULT_CHECKPOINTS_ENABLED);
|
||||
|
||||
// -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency
|
||||
|
@ -1106,8 +1116,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||
return InitError("Funding stream parameters malformed, expecting streamId:startHeight:endHeight:comma_delimited_addresses");
|
||||
}
|
||||
int nFundingStreamId;
|
||||
if (!ParseInt32(vStreamParams[0], &nFundingStreamId) ||
|
||||
nFundingStreamId < Consensus::FIRST_FUNDING_STREAM ||
|
||||
if (!ParseInt32(vStreamParams[0], &nFundingStreamId) ||
|
||||
nFundingStreamId < Consensus::FIRST_FUNDING_STREAM ||
|
||||
nFundingStreamId >= Consensus::MAX_FUNDING_STREAMS) {
|
||||
return InitError(strprintf("Invalid streamId (%s)", vStreamParams[0]));
|
||||
}
|
||||
|
|
125
src/main.cpp
125
src/main.cpp
|
@ -80,6 +80,7 @@ bool fPruneMode = false;
|
|||
bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
|
||||
bool fCheckBlockIndex = false;
|
||||
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
|
||||
bool fIBDSkipTxVerification = DEFAULT_IBD_SKIP_TX_VERIFICATION;
|
||||
bool fCoinbaseEnforcedShieldingEnabled = true;
|
||||
size_t nCoinCacheUsage = 5000 * 300;
|
||||
uint64_t nPruneTarget = 0;
|
||||
|
@ -2696,25 +2697,42 @@ static int64_t nTimeIndex = 0;
|
|||
static int64_t nTimeCallbacks = 0;
|
||||
static int64_t nTimeTotal = 0;
|
||||
|
||||
/**
|
||||
* Determine whether to do transaction checks when verifying blocks.
|
||||
* Returns `false` (allowing transaction checks to be skipped) only if all
|
||||
* of the following are true:
|
||||
* - we're currently in initial block download
|
||||
* - the `-ibdskiptxverification` flag is set
|
||||
* - the block under inspection is an ancestor of the latest checkpoint.
|
||||
*/
|
||||
static bool ShouldCheckTransactions(const CChainParams& chainparams, const CBlockIndex* pindex) {
|
||||
return !(IsInitialBlockDownload(chainparams)
|
||||
&& fIBDSkipTxVerification
|
||||
&& fCheckpointsEnabled
|
||||
&& Checkpoints::IsAncestorOfLastCheckpoint(chainparams.Checkpoints(), pindex));
|
||||
}
|
||||
|
||||
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex,
|
||||
CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
|
||||
bool fExpensiveChecks = true;
|
||||
if (fCheckpointsEnabled) {
|
||||
CBlockIndex *pindexLastCheckpoint = Checkpoints::GetLastCheckpoint(chainparams.Checkpoints());
|
||||
if (pindexLastCheckpoint && pindexLastCheckpoint->GetAncestor(pindex->nHeight) == pindex) {
|
||||
// This block is an ancestor of a checkpoint: disable script checks
|
||||
fExpensiveChecks = false;
|
||||
}
|
||||
|
||||
// If this block is an ancestor of a checkpoint, disable expensive checks
|
||||
if (fCheckpointsEnabled && Checkpoints::IsAncestorOfLastCheckpoint(chainparams.Checkpoints(), pindex)) {
|
||||
fExpensiveChecks = false;
|
||||
}
|
||||
|
||||
auto verifier = ProofVerifier::Strict();
|
||||
auto disabledVerifier = ProofVerifier::Disabled();
|
||||
// proof verification is expensive, disable if possible
|
||||
auto verifier = fExpensiveChecks ? ProofVerifier::Strict() : ProofVerifier::Disabled();
|
||||
|
||||
// If in initial block download, and this block is an ancestor of a checkpoint,
|
||||
// and -ibdskiptxverification is set, disable all transaction checks.
|
||||
bool fCheckTransactions = ShouldCheckTransactions(chainparams, pindex);
|
||||
|
||||
// Check it again to verify JoinSplit proofs, and in case a previous version let a bad block in
|
||||
if (!CheckBlock(block, state, chainparams, fExpensiveChecks ? verifier : disabledVerifier, !fJustCheck, !fJustCheck))
|
||||
if (!CheckBlock(block, state, chainparams, verifier, !fJustCheck, !fJustCheck, fCheckTransactions))
|
||||
return false;
|
||||
|
||||
// verify that the view's current state corresponds to the previous block
|
||||
|
@ -4013,10 +4031,13 @@ bool CheckBlockHeader(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CheckBlock(const CBlock& block, CValidationState& state,
|
||||
bool CheckBlock(const CBlock& block,
|
||||
CValidationState& state,
|
||||
const CChainParams& chainparams,
|
||||
ProofVerifier& verifier,
|
||||
bool fCheckPOW, bool fCheckMerkleRoot)
|
||||
bool fCheckPOW,
|
||||
bool fCheckMerkleRoot,
|
||||
bool fCheckTransactions)
|
||||
{
|
||||
// These are checks that are independent of context.
|
||||
|
||||
|
@ -4059,6 +4080,9 @@ bool CheckBlock(const CBlock& block, CValidationState& state,
|
|||
return state.DoS(100, error("CheckBlock(): more than one coinbase"),
|
||||
REJECT_INVALID, "bad-cb-multiple");
|
||||
|
||||
// skip all transaction checks if this flag is not set
|
||||
if (!fCheckTransactions) return true;
|
||||
|
||||
// Check transactions
|
||||
BOOST_FOREACH(const CTransaction& tx, block.vtx)
|
||||
if (!CheckTransaction(tx, state, verifier))
|
||||
|
@ -4144,26 +4168,29 @@ bool ContextualCheckBlockHeader(
|
|||
|
||||
bool ContextualCheckBlock(
|
||||
const CBlock& block, CValidationState& state,
|
||||
const CChainParams& chainparams, CBlockIndex * const pindexPrev)
|
||||
const CChainParams& chainparams, CBlockIndex * const pindexPrev,
|
||||
bool fCheckTransactions)
|
||||
{
|
||||
const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1;
|
||||
const Consensus::Params& consensusParams = chainparams.GetConsensus();
|
||||
|
||||
// Check that all transactions are finalized
|
||||
BOOST_FOREACH(const CTransaction& tx, block.vtx) {
|
||||
if (fCheckTransactions) {
|
||||
// Check that all transactions are finalized
|
||||
BOOST_FOREACH(const CTransaction& tx, block.vtx) {
|
||||
|
||||
// Check transaction contextually against consensus rules at block height
|
||||
if (!ContextualCheckTransaction(tx, state, chainparams, nHeight, true)) {
|
||||
return false; // Failure reason has been set in validation state object
|
||||
}
|
||||
// Check transaction contextually against consensus rules at block height
|
||||
if (!ContextualCheckTransaction(tx, state, chainparams, nHeight, true)) {
|
||||
return false; // Failure reason has been set in validation state object
|
||||
}
|
||||
|
||||
int nLockTimeFlags = 0;
|
||||
int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST)
|
||||
? pindexPrev->GetMedianTimePast()
|
||||
: block.GetBlockTime();
|
||||
if (!IsFinalTx(tx, nHeight, nLockTimeCutoff)) {
|
||||
return state.DoS(10, error("%s: contains a non-final transaction", __func__),
|
||||
REJECT_INVALID, "bad-txns-nonfinal");
|
||||
int nLockTimeFlags = 0;
|
||||
int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST)
|
||||
? pindexPrev->GetMedianTimePast()
|
||||
: block.GetBlockTime();
|
||||
if (!IsFinalTx(tx, nHeight, nLockTimeCutoff)) {
|
||||
return state.DoS(10, error("%s: contains a non-final transaction", __func__),
|
||||
REJECT_INVALID, "bad-txns-nonfinal");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4258,10 +4285,11 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state
|
|||
|
||||
/**
|
||||
* Store block on disk.
|
||||
* JoinSplit proofs are never verified, because:
|
||||
* - AcceptBlock doesn't perform script checks either.
|
||||
* - The only caller of AcceptBlock verifies JoinSplit proofs elsewhere.
|
||||
* If dbp is non-NULL, the file is known to already reside on disk
|
||||
* If dbp is non-NULL, the file is known to already reside on disk.
|
||||
*
|
||||
* JoinSplit proofs are not verified here; the only caller of AcceptBlock
|
||||
* (ProcessNewBlock) later invokes ActivateBestChain, which ultimately calls
|
||||
* ConnectBlock in a manner that can verify the proofs
|
||||
*/
|
||||
static bool AcceptBlock(const CBlock& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp)
|
||||
{
|
||||
|
@ -4293,9 +4321,11 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
|
|||
if (fTooFarAhead) return true; // Block height is too high
|
||||
}
|
||||
|
||||
// See method docstring for why this is always disabled
|
||||
// See method docstring for why this is always disabled.
|
||||
auto verifier = ProofVerifier::Disabled();
|
||||
if ((!CheckBlock(block, state, chainparams, verifier)) || !ContextualCheckBlock(block, state, chainparams, pindex->pprev)) {
|
||||
bool fCheckTransactions = ShouldCheckTransactions(chainparams, pindex);
|
||||
if ((!CheckBlock(block, state, chainparams, verifier, true, true, fCheckTransactions)) ||
|
||||
!ContextualCheckBlock(block, state, chainparams, pindex->pprev, fCheckTransactions)) {
|
||||
if (state.IsInvalid() && !state.CorruptionPossible()) {
|
||||
pindex->nStatus |= BLOCK_FAILED_VALID;
|
||||
setDirtyBlockIndex.insert(pindex);
|
||||
|
@ -4346,17 +4376,9 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, c
|
|||
auto span = TracingSpan("info", "main", "ProcessNewBlock");
|
||||
auto spanGuard = span.Enter();
|
||||
|
||||
// Preliminary checks
|
||||
auto verifier = ProofVerifier::Disabled();
|
||||
bool checked = CheckBlock(*pblock, state, chainparams, verifier);
|
||||
|
||||
{
|
||||
LOCK(cs_main);
|
||||
bool fRequested = MarkBlockAsReceived(pblock->GetHash());
|
||||
fRequested |= fForceProcessing;
|
||||
if (!checked) {
|
||||
return error("%s: CheckBlock FAILED", __func__);
|
||||
}
|
||||
bool fRequested = MarkBlockAsReceived(pblock->GetHash()) | fForceProcessing;
|
||||
|
||||
// Store to disk
|
||||
CBlockIndex *pindex = NULL;
|
||||
|
@ -4375,6 +4397,9 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, c
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is only invoked by the miner. fCheckPOW is always false.
|
||||
*/
|
||||
bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW, bool fCheckMerkleRoot)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
|
@ -4390,9 +4415,10 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
|
|||
// NOTE: CheckBlockHeader is called by CheckBlock
|
||||
if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev))
|
||||
return false;
|
||||
if (!CheckBlock(block, state, chainparams, verifier, fCheckPOW, fCheckMerkleRoot))
|
||||
// The following may be duplicative of the `CheckBlock` call within `ConnectBlock`
|
||||
if (!CheckBlock(block, state, chainparams, verifier, fCheckPOW, fCheckMerkleRoot, true))
|
||||
return false;
|
||||
if (!ContextualCheckBlock(block, state, chainparams, pindexPrev))
|
||||
if (!ContextualCheckBlock(block, state, chainparams, pindexPrev, true))
|
||||
return false;
|
||||
if (!ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true))
|
||||
return false;
|
||||
|
@ -4784,21 +4810,28 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
|
|||
CBlockIndex* pindexFailure = NULL;
|
||||
int nGoodTransactions = 0;
|
||||
CValidationState state;
|
||||
// No need to verify JoinSplits twice
|
||||
auto verifier = ProofVerifier::Disabled();
|
||||
|
||||
// Flags used to permit skipping checks for efficiency
|
||||
auto verifier = ProofVerifier::Disabled(); // No need to verify JoinSplits twice
|
||||
bool fCheckTransactions = true;
|
||||
|
||||
for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev)
|
||||
{
|
||||
boost::this_thread::interruption_point();
|
||||
uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100)))));
|
||||
if (pindex->nHeight < chainActive.Height()-nCheckDepth)
|
||||
break;
|
||||
|
||||
CBlock block;
|
||||
// check level 0: read from disk
|
||||
if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
|
||||
return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
|
||||
|
||||
// check level 1: verify block validity
|
||||
if (nCheckLevel >= 1 && !CheckBlock(block, state, chainparams, verifier))
|
||||
fCheckTransactions = ShouldCheckTransactions(chainparams, pindex);
|
||||
if (nCheckLevel >= 1 && !CheckBlock(block, state, chainparams, verifier, true, true, fCheckTransactions))
|
||||
return error("VerifyDB(): *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
|
||||
|
||||
// check level 2: verify undo validity
|
||||
if (nCheckLevel >= 2 && pindex) {
|
||||
CBlockUndo undo;
|
||||
|
@ -4808,6 +4841,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
|
|||
return error("VerifyDB(): *** found bad undo data at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
|
||||
}
|
||||
}
|
||||
|
||||
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks
|
||||
if (nCheckLevel >= 3 && pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) {
|
||||
// insightexplorer: do not update indices (false)
|
||||
|
@ -4823,6 +4857,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
|
|||
nGoodTransactions += block.vtx.size();
|
||||
}
|
||||
}
|
||||
|
||||
if (ShutdownRequested())
|
||||
return true;
|
||||
}
|
||||
|
|
30
src/main.h
30
src/main.h
|
@ -113,6 +113,7 @@ static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
|
|||
/** Default for -permitbaremultisig */
|
||||
static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
|
||||
static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
|
||||
static const bool DEFAULT_IBD_SKIP_TX_VERIFICATION = false;
|
||||
static const bool DEFAULT_TXINDEX = false;
|
||||
static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100;
|
||||
|
||||
|
@ -164,6 +165,7 @@ extern bool fTimestampIndex;
|
|||
extern bool fIsBareMultisigStd;
|
||||
extern bool fCheckBlockIndex;
|
||||
extern bool fCheckpointsEnabled;
|
||||
extern bool fIBDSkipTxVerification;
|
||||
// TODO: remove this flag by structuring our code such that
|
||||
// it is unneeded for testing
|
||||
extern bool fCoinbaseEnforcedShieldingEnabled;
|
||||
|
@ -210,11 +212,11 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals);
|
|||
/** Unregister a network node */
|
||||
void UnregisterNodeSignals(CNodeSignals& nodeSignals);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Process an incoming block. This only returns after the best known valid
|
||||
* block is made active. Note that it does not, however, guarantee that the
|
||||
* specific block passed to it has been checked for validity!
|
||||
*
|
||||
*
|
||||
* @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state if pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface (see validationinterface.h) - this will have its BlockChecked method called whenever *any* block completes validation.
|
||||
* @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid.
|
||||
* @param[in] pblock The block we want to process.
|
||||
|
@ -311,7 +313,7 @@ struct CNodeStateStats {
|
|||
|
||||
CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Count ECDSA signature operations the old-fashioned (pre-0.6) way
|
||||
* @return number of sigops this transaction's outputs will produce when spent
|
||||
* @see CTransaction::FetchInputs
|
||||
|
@ -320,7 +322,7 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx);
|
|||
|
||||
/**
|
||||
* Count ECDSA signature operations in pay-to-script-hash inputs.
|
||||
*
|
||||
*
|
||||
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
|
||||
* @return maximum number of sigops required to validate this transaction's inputs
|
||||
* @see CTransaction::FetchInputs
|
||||
|
@ -390,9 +392,9 @@ bool IsExpiringSoonTx(const CTransaction &tx, int nNextBlockHeight);
|
|||
*/
|
||||
bool CheckFinalTx(const CTransaction &tx, int flags = -1);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Closure representing one script verification
|
||||
* Note that this stores references to the spending transaction
|
||||
* Note that this stores references to the spending transaction
|
||||
*/
|
||||
class CScriptCheck
|
||||
{
|
||||
|
@ -447,13 +449,17 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus
|
|||
/** Functions for validating blocks and updating the block tree */
|
||||
|
||||
/** Context-independent validity checks */
|
||||
|
||||
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state,
|
||||
const CChainParams& chainparams,
|
||||
bool fCheckPOW = true);
|
||||
|
||||
bool CheckBlock(const CBlock& block, CValidationState& state,
|
||||
const CChainParams& chainparams,
|
||||
ProofVerifier& verifier,
|
||||
bool fCheckPOW = true, bool fCheckMerkleRoot = true);
|
||||
bool fCheckPOW,
|
||||
bool fCheckMerkleRoot,
|
||||
bool fCheckTransactions);
|
||||
|
||||
/** Context-dependent validity checks.
|
||||
* By "context", we mean only the previous block headers, but not the UTXO
|
||||
|
@ -461,7 +467,9 @@ bool CheckBlock(const CBlock& block, CValidationState& state,
|
|||
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state,
|
||||
const CChainParams& chainparams, CBlockIndex *pindexPrev);
|
||||
bool ContextualCheckBlock(const CBlock& block, CValidationState& state,
|
||||
const CChainParams& chainparams, CBlockIndex *pindexPrev);
|
||||
const CChainParams& chainparams,
|
||||
CBlockIndex *pindexPrev,
|
||||
bool fCheckTransactions);
|
||||
|
||||
/** Apply the effects of this block (with given index) on the UTXO set represented by coins.
|
||||
* Validity checks that depend on the UTXO set are also done; ConnectBlock()
|
||||
|
@ -469,9 +477,9 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state,
|
|||
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins,
|
||||
const CChainParams& chainparams, bool fJustCheck = false);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Check a block is completely valid from start to finish (only works on top
|
||||
* of our current best block, with cs_main held)
|
||||
* of our current best block, with cs_main held)
|
||||
*/
|
||||
bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
|
||||
|
||||
|
@ -521,7 +529,7 @@ int GetSpendHeight(const CCoinsViewCache& inputs);
|
|||
|
||||
uint64_t CalculateCurrentUsage();
|
||||
|
||||
/**
|
||||
/**
|
||||
* Return a CMutableTransaction with contextual default values based on set of consensus rules at nHeight. The expiryDelta will
|
||||
* either be based on the command-line argument '-txexpirydelta' or derived from consensusParams.
|
||||
*/
|
||||
|
|
|
@ -59,7 +59,7 @@ BOOST_AUTO_TEST_CASE(May15)
|
|||
// After May 15'th, big blocks are OK:
|
||||
forkingBlock.nTime = tMay15; // Invalidates PoW
|
||||
auto verifier = ProofVerifier::Strict();
|
||||
BOOST_CHECK(CheckBlock(forkingBlock, state, Params(), verifier, false, false));
|
||||
BOOST_CHECK(CheckBlock(forkingBlock, state, Params(), verifier, false, false, true));
|
||||
}
|
||||
|
||||
SetMockTime(0);
|
||||
|
|
Loading…
Reference in New Issue