Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 1,869 Lines • ▼ Show 20 Lines | static bool ConnectBlock(const Config &config, const CBlock &block, | ||||
CValidationState &state, CBlockIndex *pindex, | CValidationState &state, CBlockIndex *pindex, | ||||
CCoinsViewCache &view, const CChainParams &chainparams, | CCoinsViewCache &view, const CChainParams &chainparams, | ||||
bool fJustCheck = false) { | bool fJustCheck = false) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
int64_t nTimeStart = GetTimeMicros(); | int64_t nTimeStart = GetTimeMicros(); | ||||
// Check it again in case a previous version let a bad block in | // Check it again in case a previous version let a bad block in | ||||
if (!CheckBlock(config, block, state, chainparams.GetConsensus(), | if (!CheckBlock(config, block, state, !fJustCheck, !fJustCheck)) { | ||||
!fJustCheck, !fJustCheck)) { | |||||
return error("%s: Consensus::CheckBlock: %s", __func__, | return error("%s: Consensus::CheckBlock: %s", __func__, | ||||
FormatStateMessage(state)); | FormatStateMessage(state)); | ||||
} | } | ||||
// Verify that the view's current state corresponds to the previous block | // Verify that the view's current state corresponds to the previous block | ||||
uint256 hashPrevBlock = | uint256 hashPrevBlock = | ||||
pindex->pprev == nullptr ? uint256() : pindex->pprev->GetBlockHash(); | pindex->pprev == nullptr ? uint256() : pindex->pprev->GetBlockHash(); | ||||
assert(hashPrevBlock == view.GetBestBlock()); | assert(hashPrevBlock == view.GetBestBlock()); | ||||
▲ Show 20 Lines • Show All 1,302 Lines • ▼ Show 20 Lines | if (nNewChunks > nOldChunks) { | ||||
} | } | ||||
} else | } else | ||||
return state.Error("out of disk space"); | return state.Error("out of disk space"); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool CheckBlockHeader(const CBlockHeader &block, CValidationState &state, | static bool CheckBlockHeader(const Config &config, const CBlockHeader &block, | ||||
const Consensus::Params &consensusParams, | CValidationState &state, bool fCheckPOW = true) { | ||||
bool fCheckPOW) { | const Consensus::Params &consensusParams = | ||||
config.GetChainParams().GetConsensus(); | |||||
// Check proof of work matches claimed amount | // Check proof of work matches claimed amount | ||||
if (fCheckPOW && | if (fCheckPOW && | ||||
!CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) | !CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) { | ||||
return state.DoS(50, false, REJECT_INVALID, "high-hash", false, | return state.DoS(50, false, REJECT_INVALID, "high-hash", false, | ||||
"proof of work failed"); | "proof of work failed"); | ||||
} | |||||
return true; | return true; | ||||
} | } | ||||
bool CheckBlock(const Config &config, const CBlock &block, | bool CheckBlock(const Config &config, const CBlock &block, | ||||
CValidationState &state, | CValidationState &state, bool fCheckPOW, | ||||
const Consensus::Params &consensusParams, bool fCheckPOW, | |||||
bool fCheckMerkleRoot) { | bool fCheckMerkleRoot) { | ||||
// These are checks that are independent of context. | // These are checks that are independent of context. | ||||
if (block.fChecked) { | if (block.fChecked) { | ||||
return true; | return true; | ||||
} | } | ||||
// Check that the header is valid (particularly PoW). This is mostly | // Check that the header is valid (particularly PoW). This is mostly | ||||
// redundant with the call in AcceptBlockHeader. | // redundant with the call in AcceptBlockHeader. | ||||
if (!CheckBlockHeader(block, state, consensusParams, fCheckPOW)) { | if (!CheckBlockHeader(config, block, state, fCheckPOW)) { | ||||
return false; | return false; | ||||
} | } | ||||
// Check the merkle root. | // Check the merkle root. | ||||
if (fCheckMerkleRoot) { | if (fCheckMerkleRoot) { | ||||
bool mutated; | bool mutated; | ||||
uint256 hashMerkleRoot2 = BlockMerkleRoot(block, &mutated); | uint256 hashMerkleRoot2 = BlockMerkleRoot(block, &mutated); | ||||
if (block.hashMerkleRoot != hashMerkleRoot2) { | if (block.hashMerkleRoot != hashMerkleRoot2) { | ||||
▲ Show 20 Lines • Show All 277 Lines • ▼ Show 20 Lines | if (hash != chainparams.GetConsensus().hashGenesisBlock) { | ||||
if (pindex->nStatus & BLOCK_FAILED_MASK) { | if (pindex->nStatus & BLOCK_FAILED_MASK) { | ||||
return state.Invalid(error("%s: block %s is marked invalid", | return state.Invalid(error("%s: block %s is marked invalid", | ||||
__func__, hash.ToString()), | __func__, hash.ToString()), | ||||
0, "duplicate"); | 0, "duplicate"); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
if (!CheckBlockHeader(block, state, chainparams.GetConsensus())) { | if (!CheckBlockHeader(config, block, state)) { | ||||
return error("%s: Consensus::CheckBlockHeader: %s, %s", __func__, | return error("%s: Consensus::CheckBlockHeader: %s, %s", __func__, | ||||
hash.ToString(), FormatStateMessage(state)); | hash.ToString(), FormatStateMessage(state)); | ||||
} | } | ||||
// Get prev block index | // Get prev block index | ||||
CBlockIndex *pindexPrev = nullptr; | CBlockIndex *pindexPrev = nullptr; | ||||
BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock); | BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock); | ||||
if (mi == mapBlockIndex.end()) { | if (mi == mapBlockIndex.end()) { | ||||
▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | if (!fRequested) { | ||||
} | } | ||||
} | } | ||||
if (fNewBlock) { | if (fNewBlock) { | ||||
*fNewBlock = true; | *fNewBlock = true; | ||||
} | } | ||||
const CChainParams &chainparams = config.GetChainParams(); | const CChainParams &chainparams = config.GetChainParams(); | ||||
if (!CheckBlock(config, block, state, chainparams.GetConsensus()) || | if (!CheckBlock(config, block, state) || | ||||
!ContextualCheckBlock(config, block, state, chainparams.GetConsensus(), | !ContextualCheckBlock(config, block, state, chainparams.GetConsensus(), | ||||
pindex->pprev)) { | pindex->pprev)) { | ||||
if (state.IsInvalid() && !state.CorruptionPossible()) { | if (state.IsInvalid() && !state.CorruptionPossible()) { | ||||
pindex->nStatus |= BLOCK_FAILED_VALID; | pindex->nStatus |= BLOCK_FAILED_VALID; | ||||
setDirtyBlockIndex.insert(pindex); | setDirtyBlockIndex.insert(pindex); | ||||
} | } | ||||
return error("%s: %s (block %s)", __func__, FormatStateMessage(state), | return error("%s: %s (block %s)", __func__, FormatStateMessage(state), | ||||
block.GetHash().ToString()); | block.GetHash().ToString()); | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | bool ProcessNewBlock(const Config &config, | ||||
CBlockIndex *pindex = nullptr; | CBlockIndex *pindex = nullptr; | ||||
if (fNewBlock) *fNewBlock = false; | if (fNewBlock) *fNewBlock = false; | ||||
const CChainParams &chainparams = config.GetChainParams(); | const CChainParams &chainparams = config.GetChainParams(); | ||||
CValidationState state; | CValidationState state; | ||||
// Ensure that CheckBlock() passes before calling AcceptBlock, as | // Ensure that CheckBlock() passes before calling AcceptBlock, as | ||||
// belt-and-suspenders. | // belt-and-suspenders. | ||||
bool ret = | bool ret = CheckBlock(config, *pblock, state); | ||||
CheckBlock(config, *pblock, state, chainparams.GetConsensus()); | |||||
LOCK(cs_main); | LOCK(cs_main); | ||||
if (ret) { | if (ret) { | ||||
// Store to disk | // Store to disk | ||||
ret = AcceptBlock(config, pblock, state, &pindex, fForceProcessing, | ret = AcceptBlock(config, pblock, state, &pindex, fForceProcessing, | ||||
nullptr, fNewBlock); | nullptr, fNewBlock); | ||||
} | } | ||||
Show All 33 Lines | bool TestBlockValidity(const Config &config, CValidationState &state, | ||||
indexDummy.nHeight = pindexPrev->nHeight + 1; | indexDummy.nHeight = pindexPrev->nHeight + 1; | ||||
// NOTE: CheckBlockHeader is called by CheckBlock | // NOTE: CheckBlockHeader is called by CheckBlock | ||||
if (!ContextualCheckBlockHeader(config, block, state, pindexPrev, | if (!ContextualCheckBlockHeader(config, block, state, pindexPrev, | ||||
GetAdjustedTime())) { | GetAdjustedTime())) { | ||||
return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, | return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, | ||||
FormatStateMessage(state)); | FormatStateMessage(state)); | ||||
} | } | ||||
if (!CheckBlock(config, block, state, chainparams.GetConsensus(), fCheckPOW, | if (!CheckBlock(config, block, state, fCheckPOW, fCheckMerkleRoot)) { | ||||
fCheckMerkleRoot)) { | |||||
return error("%s: Consensus::CheckBlock: %s", __func__, | return error("%s: Consensus::CheckBlock: %s", __func__, | ||||
FormatStateMessage(state)); | FormatStateMessage(state)); | ||||
} | } | ||||
if (!ContextualCheckBlock(config, block, state, chainparams.GetConsensus(), | if (!ContextualCheckBlock(config, block, state, chainparams.GetConsensus(), | ||||
pindexPrev)) { | pindexPrev)) { | ||||
return error("%s: Consensus::ContextualCheckBlock: %s", __func__, | return error("%s: Consensus::ContextualCheckBlock: %s", __func__, | ||||
FormatStateMessage(state)); | FormatStateMessage(state)); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 414 Lines • ▼ Show 20 Lines | for (CBlockIndex *pindex = chainActive.Tip(); pindex && pindex->pprev; | ||||
// check level 0: read from disk | // check level 0: read from disk | ||||
if (!ReadBlockFromDisk(block, pindex, config)) { | if (!ReadBlockFromDisk(block, pindex, config)) { | ||||
return error( | return error( | ||||
"VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", | "VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", | ||||
pindex->nHeight, pindex->GetBlockHash().ToString()); | pindex->nHeight, pindex->GetBlockHash().ToString()); | ||||
} | } | ||||
// check level 1: verify block validity | // check level 1: verify block validity | ||||
if (nCheckLevel >= 1 && | if (nCheckLevel >= 1 && !CheckBlock(config, block, state)) { | ||||
!CheckBlock(config, block, state, chainparams.GetConsensus())) { | |||||
return error("%s: *** found bad block at %d, hash=%s (%s)\n", | return error("%s: *** found bad block at %d, hash=%s (%s)\n", | ||||
__func__, pindex->nHeight, | __func__, pindex->nHeight, | ||||
pindex->GetBlockHash().ToString(), | pindex->GetBlockHash().ToString(), | ||||
FormatStateMessage(state)); | FormatStateMessage(state)); | ||||
} | } | ||||
// check level 2: verify undo validity | // check level 2: verify undo validity | ||||
if (nCheckLevel >= 2 && pindex) { | if (nCheckLevel >= 2 && pindex) { | ||||
▲ Show 20 Lines • Show All 857 Lines • Show Last 20 Lines |