Skip to content

Commit dce8360

Browse files
committed
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.
1 parent 2325413 commit dce8360

File tree

6 files changed

+15
-38
lines changed

6 files changed

+15
-38
lines changed

src/chain.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,10 @@ CBlockIndex* CBlockIndex::GetAncestor(int height)
8282
while (heightWalk > height) {
8383
int heightSkip = GetSkipHeight(heightWalk);
8484
int heightSkipPrev = GetSkipHeight(heightWalk - 1);
85-
if (heightSkip == height ||
86-
(heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
87-
heightSkipPrev >= height))) {
85+
if (pindexWalk->pskip != NULL &&
86+
(heightSkip == height ||
87+
(heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
88+
heightSkipPrev >= height)))) {
8889
// Only follow pskip if pprev->pskip isn't better than pskip->pprev.
8990
pindexWalk = pindexWalk->pskip;
9091
heightWalk = heightSkip;

src/checkpoints.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,6 @@ namespace Checkpoints {
2424
*/
2525
static const double SIGCHECK_VERIFICATION_FACTOR = 5.0;
2626

27-
bool CheckBlock(const CCheckpointData& data, int nHeight, const uint256& hash)
28-
{
29-
const MapCheckpoints& checkpoints = data.mapCheckpoints;
30-
31-
MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
32-
if (i == checkpoints.end()) return true;
33-
return hash == i->second;
34-
}
35-
3627
//! Guess how far we are in the verification process at the given block index
3728
double GuessVerificationProgress(const CCheckpointData& data, CBlockIndex *pindex, bool fSigchecks) {
3829
if (pindex==NULL)

src/checkpoints.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ struct CCheckpointData {
2626
double fTransactionsPerDay;
2727
};
2828

29-
//! Returns true if block passes checkpoint checks
30-
bool CheckBlock(const CCheckpointData& data, int nHeight, const uint256& hash);
31-
3229
//! Return conservative estimate of total number of blocks, 0 if unknown
3330
int GetTotalBlocksEstimate(const CCheckpointData& data);
3431

src/init.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ std::string HelpMessage(HelpMessageMode mode)
347347
strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
348348
if (GetBoolArg("-help-debug", false))
349349
{
350-
strUsage += HelpMessageOpt("-checkpoints", strprintf(_("Only accept block chain matching built-in checkpoints (default: %u)"), 1));
350+
strUsage += HelpMessageOpt("-checkpoints", strprintf(_("Disable expensive verification for known chain history (default: %u)"), 1));
351351
strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf(_("Flush database activity from memory pool to disk log every <n> megabytes (default: %u)"), 100));
352352
strUsage += HelpMessageOpt("-disablesafemode", strprintf(_("Disable safemode, override a real safe mode event (default: %u)"), 0));
353353
strUsage += HelpMessageOpt("-testsafemode", strprintf(_("Force safe mode (default: %u)"), 0));

src/main.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,7 +1714,14 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
17141714
return true;
17151715
}
17161716

1717-
bool fScriptChecks = (!fCheckpointsEnabled || pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints()));
1717+
bool fScriptChecks = true;
1718+
if (fCheckpointsEnabled) {
1719+
CBlockIndex *pindexLastCheckpoint = Checkpoints::GetLastCheckpoint(chainparams.Checkpoints());
1720+
if (pindexLastCheckpoint && pindexLastCheckpoint->GetAncestor(pindex->nHeight) == pindex) {
1721+
// This block is an ancestor of a checkpoint: disable script checks
1722+
fScriptChecks = false;
1723+
}
1724+
}
17181725

17191726
// Do not allow blocks that contain transactions which 'overwrite' older transactions,
17201727
// unless those are already completely spent.
@@ -2630,13 +2637,8 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
26302637
return state.Invalid(error("%s: block's timestamp is too early", __func__),
26312638
REJECT_INVALID, "time-too-old");
26322639

2633-
if(fCheckpointsEnabled)
2640+
if (fCheckpointsEnabled)
26342641
{
2635-
// Check that the block chain matches the known block chain up to a checkpoint
2636-
if (!Checkpoints::CheckBlock(chainParams.Checkpoints(), nHeight, hash))
2637-
return state.DoS(100, error("%s: rejected by checkpoint lock-in at %d", __func__, nHeight),
2638-
REJECT_CHECKPOINT, "checkpoint mismatch");
2639-
26402642
// Don't accept any forks from the main chain prior to last checkpoint
26412643
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainParams.Checkpoints());
26422644
if (pcheckpoint && nHeight < pcheckpoint->nHeight)

src/test/Checkpoints_tests.cpp

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,7 @@ BOOST_FIXTURE_TEST_SUITE(Checkpoints_tests, BasicTestingSetup)
2121
BOOST_AUTO_TEST_CASE(sanity)
2222
{
2323
const Checkpoints::CCheckpointData& checkpoints = Params(CBaseChainParams::MAIN).Checkpoints();
24-
uint256 p11111 = uint256S("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d");
25-
uint256 p134444 = uint256S("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe");
26-
BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 11111, p11111));
27-
BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 134444, p134444));
28-
29-
30-
// Wrong hashes at checkpoints should fail:
31-
BOOST_CHECK(!Checkpoints::CheckBlock(checkpoints, 11111, p134444));
32-
BOOST_CHECK(!Checkpoints::CheckBlock(checkpoints, 134444, p11111));
33-
34-
// ... but any hash not at a checkpoint should succeed:
35-
BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 11111+1, p134444));
36-
BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 134444+1, p11111));
37-
3824
BOOST_CHECK(Checkpoints::GetTotalBlocksEstimate(checkpoints) >= 134444);
39-
}
25+
}
4026

4127
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)