Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 3,520 Lines • ▼ Show 20 Lines | bool CheckBlock(const Config &config, const CBlock &block, | ||||
if (validationOptions.shouldValidatePoW() && | if (validationOptions.shouldValidatePoW() && | ||||
validationOptions.shouldValidateMerkleRoot()) { | validationOptions.shouldValidateMerkleRoot()) { | ||||
block.fChecked = true; | block.fChecked = true; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
static bool CheckIndexAgainstCheckpoint(const CBlockIndex *pindexPrev, | /** | ||||
* Context-dependent validity checks. | |||||
* By "context", we mean only the previous block headers, but not the UTXO | |||||
* set; UTXO-related validity checks are done in ConnectBlock(). | |||||
*/ | |||||
static bool ContextualCheckBlockHeader(const Config &config, | |||||
const CBlockHeader &block, | |||||
CValidationState &state, | CValidationState &state, | ||||
const CChainParams &chainparams, | const CBlockIndex *pindexPrev, | ||||
const uint256 &hash) { | int64_t nAdjustedTime) { | ||||
if (*pindexPrev->phashBlock == | assert(pindexPrev != nullptr); | ||||
chainparams.GetConsensus().hashGenesisBlock) { | const int nHeight = pindexPrev->nHeight + 1; | ||||
return true; | |||||
// Check proof of work | |||||
const Consensus::Params &consensusParams = | |||||
config.GetChainParams().GetConsensus(); | |||||
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, config)) { | |||||
LogPrintf("bad bits after height: %d\n", pindexPrev->nHeight); | |||||
return state.DoS(100, false, REJECT_INVALID, "bad-diffbits", false, | |||||
"incorrect proof of work"); | |||||
} | } | ||||
int nHeight = pindexPrev->nHeight + 1; | // Check against checkpoints | ||||
const CCheckpointData &checkpoints = chainparams.Checkpoints(); | if (fCheckpointsEnabled) { | ||||
const CCheckpointData &checkpoints = | |||||
config.GetChainParams().Checkpoints(); | |||||
// Check that the block chain matches the known block chain up to a | // Check that the block chain matches the known block chain up to a | ||||
// checkpoint. | // checkpoint. | ||||
if (!Checkpoints::CheckBlock(checkpoints, nHeight, hash)) { | if (!Checkpoints::CheckBlock(checkpoints, nHeight, block.GetHash())) { | ||||
return state.DoS(100, | return state.DoS(100, | ||||
error("%s: rejected by checkpoint lock-in at %d", | error("%s: rejected by checkpoint lock-in at %d", | ||||
__func__, nHeight), | __func__, nHeight), | ||||
REJECT_CHECKPOINT, "checkpoint mismatch"); | REJECT_CHECKPOINT, "checkpoint mismatch"); | ||||
} | } | ||||
// Don't accept any forks from the main chain prior to last checkpoint. | // Don't accept any forks from the main chain prior to last checkpoint. | ||||
// GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in | // GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's | ||||
// our MapBlockIndex. | // in our MapBlockIndex. | ||||
CBlockIndex *pcheckpoint = Checkpoints::GetLastCheckpoint(checkpoints); | CBlockIndex *pcheckpoint = Checkpoints::GetLastCheckpoint(checkpoints); | ||||
if (pcheckpoint && nHeight < pcheckpoint->nHeight) { | if (pcheckpoint && nHeight < pcheckpoint->nHeight) { | ||||
return state.DoS( | return state.DoS( | ||||
100, | 100, | ||||
error("%s: forked chain older than last checkpoint (height %d)", | error("%s: forked chain older than last checkpoint (height %d)", | ||||
__func__, nHeight), | __func__, nHeight), | ||||
REJECT_CHECKPOINT, "bad-fork-prior-to-checkpoint"); | REJECT_CHECKPOINT, "bad-fork-prior-to-checkpoint"); | ||||
} | } | ||||
return true; | |||||
} | |||||
static bool ContextualCheckBlockHeader(const Config &config, | |||||
const CBlockHeader &block, | |||||
CValidationState &state, | |||||
const CBlockIndex *pindexPrev, | |||||
int64_t nAdjustedTime) { | |||||
const Consensus::Params &consensusParams = | |||||
config.GetChainParams().GetConsensus(); | |||||
assert(pindexPrev != nullptr); | |||||
const int nHeight = pindexPrev->nHeight + 1; | |||||
// Check proof of work | |||||
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, config)) { | |||||
LogPrintf("bad bits after height: %d\n", pindexPrev->nHeight); | |||||
return state.DoS(100, false, REJECT_INVALID, "bad-diffbits", false, | |||||
"incorrect proof of work"); | |||||
} | } | ||||
// Check timestamp against prev | // Check timestamp against prev | ||||
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast()) { | if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast()) { | ||||
return state.Invalid(false, REJECT_INVALID, "time-too-old", | return state.Invalid(false, REJECT_INVALID, "time-too-old", | ||||
"block's timestamp is too early"); | "block's timestamp is too early"); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 169 Lines • ▼ Show 20 Lines | if (hash != chainparams.GetConsensus().hashGenesisBlock) { | ||||
CBlockIndex *pindexPrev = (*mi).second; | CBlockIndex *pindexPrev = (*mi).second; | ||||
assert(pindexPrev); | assert(pindexPrev); | ||||
if (pindexPrev->nStatus.isInvalid()) { | if (pindexPrev->nStatus.isInvalid()) { | ||||
return state.DoS(100, error("%s: prev block invalid", __func__), | return state.DoS(100, error("%s: prev block invalid", __func__), | ||||
REJECT_INVALID, "bad-prevblk"); | REJECT_INVALID, "bad-prevblk"); | ||||
} | } | ||||
if (fCheckpointsEnabled && !CheckIndexAgainstCheckpoint( | |||||
pindexPrev, state, chainparams, hash)) { | |||||
return error("%s: CheckIndexAgainstCheckpoint(): %s", __func__, | |||||
state.GetRejectReason().c_str()); | |||||
} | |||||
if (!ContextualCheckBlockHeader(config, block, state, pindexPrev, | if (!ContextualCheckBlockHeader(config, block, state, pindexPrev, | ||||
GetAdjustedTime())) { | GetAdjustedTime())) { | ||||
return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", | return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", | ||||
__func__, hash.ToString(), FormatStateMessage(state)); | __func__, hash.ToString(), FormatStateMessage(state)); | ||||
} | } | ||||
} | } | ||||
if (pindex == nullptr) { | if (pindex == nullptr) { | ||||
▲ Show 20 Lines • Show All 258 Lines • ▼ Show 20 Lines | bool ProcessNewBlock(const Config &config, | ||||
return true; | return true; | ||||
} | } | ||||
bool TestBlockValidity(const Config &config, CValidationState &state, | bool TestBlockValidity(const Config &config, CValidationState &state, | ||||
const CBlock &block, CBlockIndex *pindexPrev, | const CBlock &block, CBlockIndex *pindexPrev, | ||||
BlockValidationOptions validationOptions) { | BlockValidationOptions validationOptions) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
const CChainParams &chainparams = config.GetChainParams(); | |||||
assert(pindexPrev && pindexPrev == chainActive.Tip()); | assert(pindexPrev && pindexPrev == chainActive.Tip()); | ||||
if (fCheckpointsEnabled && | |||||
!CheckIndexAgainstCheckpoint(pindexPrev, state, chainparams, | |||||
block.GetHash())) { | |||||
return error("%s: CheckIndexAgainstCheckpoint(): %s", __func__, | |||||
state.GetRejectReason().c_str()); | |||||
} | |||||
CCoinsViewCache viewNew(pcoinsTip.get()); | CCoinsViewCache viewNew(pcoinsTip.get()); | ||||
CBlockIndex indexDummy(block); | CBlockIndex indexDummy(block); | ||||
indexDummy.pprev = pindexPrev; | indexDummy.pprev = pindexPrev; | ||||
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())) { | ||||
▲ Show 20 Lines • Show All 1,523 Lines • Show Last 20 Lines |