aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2015-03-19 05:34:06 -0700
committerPieter Wuille <pieter.wuille@gmail.com>2015-05-13 12:52:57 -0700
commitdce8360e44d5330cc9f9d09c9b09ac9237237204 (patch)
treeadeb8c21937470d6bd326f6a8cf2d9ae5f8904b9
parent23254131a3fdaeae9c50dafca6d0addbbf235820 (diff)
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.
-rw-r--r--src/chain.cpp7
-rw-r--r--src/checkpoints.cpp9
-rw-r--r--src/checkpoints.h3
-rw-r--r--src/init.cpp2
-rw-r--r--src/main.cpp16
-rw-r--r--src/test/Checkpoints_tests.cpp16
6 files changed, 15 insertions, 38 deletions
diff --git a/src/chain.cpp b/src/chain.cpp
index 719256106e..5b8ce076c4 100644
--- a/src/chain.cpp
+++ b/src/chain.cpp
@@ -82,9 +82,10 @@ CBlockIndex* CBlockIndex::GetAncestor(int height)
while (heightWalk > height) {
int heightSkip = GetSkipHeight(heightWalk);
int heightSkipPrev = GetSkipHeight(heightWalk - 1);
- if (heightSkip == height ||
- (heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
- heightSkipPrev >= height))) {
+ if (pindexWalk->pskip != NULL &&
+ (heightSkip == height ||
+ (heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
+ heightSkipPrev >= height)))) {
// Only follow pskip if pprev->pskip isn't better than pskip->pprev.
pindexWalk = pindexWalk->pskip;
heightWalk = heightSkip;
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
index 2024486139..87f4ad7f2e 100644
--- a/src/checkpoints.cpp
+++ b/src/checkpoints.cpp
@@ -24,15 +24,6 @@ namespace Checkpoints {
*/
static const double SIGCHECK_VERIFICATION_FACTOR = 5.0;
- bool CheckBlock(const CCheckpointData& data, int nHeight, const uint256& hash)
- {
- const MapCheckpoints& checkpoints = data.mapCheckpoints;
-
- MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
- if (i == checkpoints.end()) return true;
- return hash == i->second;
- }
-
//! Guess how far we are in the verification process at the given block index
double GuessVerificationProgress(const CCheckpointData& data, CBlockIndex *pindex, bool fSigchecks) {
if (pindex==NULL)
diff --git a/src/checkpoints.h b/src/checkpoints.h
index a720f096c0..001e3cc801 100644
--- a/src/checkpoints.h
+++ b/src/checkpoints.h
@@ -26,9 +26,6 @@ struct CCheckpointData {
double fTransactionsPerDay;
};
-//! Returns true if block passes checkpoint checks
-bool CheckBlock(const CCheckpointData& data, int nHeight, const uint256& hash);
-
//! Return conservative estimate of total number of blocks, 0 if unknown
int GetTotalBlocksEstimate(const CCheckpointData& data);
diff --git a/src/init.cpp b/src/init.cpp
index 47cbda32f5..1905bbf8b8 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -347,7 +347,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
if (GetBoolArg("-help-debug", false))
{
- strUsage += HelpMessageOpt("-checkpoints", strprintf(_("Only accept block chain matching built-in checkpoints (default: %u)"), 1));
+ strUsage += HelpMessageOpt("-checkpoints", strprintf(_("Disable expensive verification for known chain history (default: %u)"), 1));
strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf(_("Flush database activity from memory pool to disk log every <n> megabytes (default: %u)"), 100));
strUsage += HelpMessageOpt("-disablesafemode", strprintf(_("Disable safemode, override a real safe mode event (default: %u)"), 0));
strUsage += HelpMessageOpt("-testsafemode", strprintf(_("Force safe mode (default: %u)"), 0));
diff --git a/src/main.cpp b/src/main.cpp
index 4f4926eb40..39da3406a8 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -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)
diff --git a/src/test/Checkpoints_tests.cpp b/src/test/Checkpoints_tests.cpp
index 642ce13bcd..703cf307d1 100644
--- a/src/test/Checkpoints_tests.cpp
+++ b/src/test/Checkpoints_tests.cpp
@@ -21,21 +21,7 @@ BOOST_FIXTURE_TEST_SUITE(Checkpoints_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(sanity)
{
const Checkpoints::CCheckpointData& checkpoints = Params(CBaseChainParams::MAIN).Checkpoints();
- uint256 p11111 = uint256S("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d");
- uint256 p134444 = uint256S("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe");
- BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 11111, p11111));
- BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 134444, p134444));
-
-
- // Wrong hashes at checkpoints should fail:
- BOOST_CHECK(!Checkpoints::CheckBlock(checkpoints, 11111, p134444));
- BOOST_CHECK(!Checkpoints::CheckBlock(checkpoints, 134444, p11111));
-
- // ... but any hash not at a checkpoint should succeed:
- BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 11111+1, p134444));
- BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 134444+1, p11111));
-
BOOST_CHECK(Checkpoints::GetTotalBlocksEstimate(checkpoints) >= 134444);
-}
+}
BOOST_AUTO_TEST_SUITE_END()