Reduce checkpoints' effect on consensus.

Instead of only checking height to decide whether to disable script checks,
actually check whether a block is an ancestor of a checkpoint, up to which
headers have been validated. This means that we don't have to prevent
accepting a side branch anymore - it will be safe, just less fast to
do.

We still need to prevent being fed a multitude of low-difficulty headers
filling up our memory. The mechanism for that is unchanged for now: once
a checkpoint is reached with headers, no headers chain branching off before
that point are allowed anymore.
This commit is contained in:
Pieter Wuille
2015-03-19 05:34:06 -07:00
parent 23254131a3
commit dce8360e44
6 changed files with 15 additions and 38 deletions

View File

@@ -1714,7 +1714,14 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return true;
}
bool fScriptChecks = (!fCheckpointsEnabled || pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints()));
bool fScriptChecks = 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
fScriptChecks = false;
}
}
// Do not allow blocks that contain transactions which 'overwrite' older transactions,
// unless those are already completely spent.
@@ -2630,13 +2637,8 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
return state.Invalid(error("%s: block's timestamp is too early", __func__),
REJECT_INVALID, "time-too-old");
if(fCheckpointsEnabled)
if (fCheckpointsEnabled)
{
// Check that the block chain matches the known block chain up to a checkpoint
if (!Checkpoints::CheckBlock(chainParams.Checkpoints(), nHeight, hash))
return state.DoS(100, error("%s: rejected by checkpoint lock-in at %d", __func__, nHeight),
REJECT_CHECKPOINT, "checkpoint mismatch");
// Don't accept any forks from the main chain prior to last checkpoint
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainParams.Checkpoints());
if (pcheckpoint && nHeight < pcheckpoint->nHeight)