Skip to content

Commit

Permalink
Merge pull request bitcoin#142 from dagurval/checkpoint
Browse files Browse the repository at this point in the history
Extend checkpointing to a safe distance in the past
  • Loading branch information
dgenr8 committed Apr 14, 2016
2 parents 43c3b8e + 23e0b01 commit 042fac7
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 27 deletions.
1 change: 1 addition & 0 deletions src/Makefile.test.include
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ BITCOIN_TESTS =\
test/miner_tests.cpp \
test/multisig_tests.cpp \
test/netbase_tests.cpp \
test/options_tests.cpp \
test/p2p_protocol_tests.cpp \
test/pmt_tests.cpp \
test/policyestimator_tests.cpp \
Expand Down
18 changes: 5 additions & 13 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,8 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
if (showDebug)
{
strUsage += HelpMessageOpt("-checkpoints", strprintf("Only accept block chain matching built-in checkpoints (default: %u)", 1));
strUsage += HelpMessageOpt("-checkpoints", strprintf("Skip validating scripts for old blocks with valid PoW (default: %u)", 1));
strUsage += HelpMessageOpt("-checkpoint-days", strprintf("Minimum age of blocks (in days) to skip validation for (default: %u)", DEFAULT_CHECKPOINT_DAYS));
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));
Expand Down Expand Up @@ -798,15 +799,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (nMempoolSizeLimit < 0 || nMempoolSizeLimit < nMempoolDescendantSizeLimit * 40)
return InitError(strprintf(_("Error: -maxmempool must be at least %d MB"), GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) / 25));

// -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency
nScriptCheckThreads = GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS);
if (nScriptCheckThreads <= 0)
nScriptCheckThreads += boost::thread::hardware_concurrency();
if (nScriptCheckThreads <= 1)
nScriptCheckThreads = 0;
else if (nScriptCheckThreads > MAX_SCRIPTCHECK_THREADS)
nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS;

fServer = GetBoolArg("-server", false);

// block pruning; get the amount of disk space (in MB) to allot for block & undo files
Expand Down Expand Up @@ -946,9 +938,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD);
std::ostringstream strErrors;

LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads);
if (nScriptCheckThreads) {
for (int i=0; i<nScriptCheckThreads-1; i++)
LogPrintf("Using %u threads for script verification\n", Opt().ScriptCheckThreads());
if (Opt().ScriptCheckThreads()) {
for (int i=0; i<Opt().ScriptCheckThreads()-1; i++)
threadGroup.create_thread(&ThreadScriptCheck);
}

Expand Down
12 changes: 8 additions & 4 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ boost::atomic<uint32_t> sizeForkTime(std::numeric_limits<uint32_t>::max());
int64_t nTimeBestReceived = 0;
CWaitableCriticalSection csBestBlock;
CConditionVariable cvBlockChange;
int nScriptCheckThreads = 0;
bool fImporting = false;
bool fReindex = false;
bool fTxIndex = false;
Expand Down Expand Up @@ -2153,7 +2152,12 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return true;
}

bool fScriptChecks = (!fCheckpointsEnabled || pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints()));
const int64_t timeBarrier = GetTime() - 24 * 3600 * Opt().CheckpointDays();
// Blocks that have varius days of POW behind them makes them secure in
// that actually online nodes checked the scripts, so during initial sync we
// don't need to check the scripts.
// All other block validity tests are still checked.
bool fScriptChecks = !fCheckpointsEnabled || block.nTime > timeBarrier;

// Do not allow blocks that contain transactions which 'overwrite' older transactions,
// unless those are already completely spent.
Expand Down Expand Up @@ -2205,7 +2209,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
// Post-fork, accurately counted sigop/sighash limits are used
ValidationCostTracker costTracker(MaxBlockSigops(block.nTime), MaxBlockSighash(block.nTime));

CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL);
CCheckQueueControl<CScriptCheck> control(fScriptChecks && Opt().ScriptCheckThreads() ? &scriptcheckqueue : NULL);

CAmount nFees = 0;
int nInputs = 0;
Expand Down Expand Up @@ -2246,7 +2250,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin

std::vector<CScriptCheck> vChecks;
if (!CheckInputs(tx, state, view, fScriptChecks, flags, false,
&costTracker, nScriptCheckThreads ? &vChecks : NULL))
&costTracker, Opt().ScriptCheckThreads() ? &vChecks : NULL))
return false;
control.Add(vChecks);
}
Expand Down
5 changes: 0 additions & 5 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,6 @@ static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
/** The pre-allocation chunk size for rev?????.dat files (since 0.8) */
static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB
/** Maximum number of script-checking threads allowed */
static const int MAX_SCRIPTCHECK_THREADS = 16;
/** -par default (number of script-checking threads, 0 = auto) */
static const int DEFAULT_SCRIPTCHECK_THREADS = 0;
/** Number of blocks that can be requested at any given time from a single peer. */
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16;
/** Timeout in seconds during which a peer must stall block download progress before being disconnected. */
Expand Down Expand Up @@ -124,7 +120,6 @@ extern CWaitableCriticalSection csBestBlock;
extern CConditionVariable cvBlockChange;
extern bool fImporting;
extern bool fReindex;
extern int nScriptCheckThreads;
extern bool fTxIndex;
extern bool fIsBareMultisigStd;
extern bool fCheckBlockIndex;
Expand Down
21 changes: 21 additions & 0 deletions src/options.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "options.h"
#include "util.h"
#include <stdexcept>
#include <boost/thread.hpp>

static std::auto_ptr<ArgGetter> Args;

Expand All @@ -14,6 +15,9 @@ struct DefaultGetter : public ArgGetter {

return mapMultiArgs[arg];
}
virtual int64_t GetArg(const std::string& strArg, int64_t nDefault) {
return ::GetArg(strArg, nDefault);
}
};

Opt::Opt() {
Expand Down Expand Up @@ -48,6 +52,23 @@ std::vector<std::string> Opt::UAComment(bool validate) {
return uacomments;
}

int Opt::ScriptCheckThreads() {
// -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency
int nScriptCheckThreads = Args->GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS);
if (nScriptCheckThreads <= 0)
nScriptCheckThreads += boost::thread::hardware_concurrency();
if (nScriptCheckThreads <= 1)
nScriptCheckThreads = 0;
else if (nScriptCheckThreads > MAX_SCRIPTCHECK_THREADS)
nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS;
return nScriptCheckThreads;
}

int64_t Opt::CheckpointDays() {
int64_t def = DEFAULT_CHECKPOINT_DAYS * std::max(1, ScriptCheckThreads());
return std::max(int64_t(1), Args->GetArg("-checkpoint-days", def));
}

std::auto_ptr<ArgReset> SetDummyArgGetter(std::auto_ptr<ArgGetter> getter) {
Args.reset(getter.release());
return std::auto_ptr<ArgReset>(new ArgReset);
Expand Down
13 changes: 12 additions & 1 deletion src/options.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#ifndef BITCOIN_OPTIONS_H
#define BITCOIN_OPTIONS_H

#include <string>
#include <memory>
#include <stdint.h>
#include <string>
#include <vector>

struct Opt {
Expand All @@ -11,15 +12,25 @@ struct Opt {
bool IsStealthMode();
bool HidePlatform();
std::vector<std::string> UAComment(bool validate = false);
int ScriptCheckThreads();
int64_t CheckpointDays();
};

/** Maximum number of script-checking threads allowed */
static const int MAX_SCRIPTCHECK_THREADS = 16;
/** -par default (number of script-checking threads, 0 = auto) */
static const int DEFAULT_SCRIPTCHECK_THREADS = 0;
// Blocks newer than n days will have their script validated during sync.
static const int DEFAULT_CHECKPOINT_DAYS = 30;

//
// For unit testing
//

struct ArgGetter {
virtual bool GetBool(const std::string& arg, bool def) = 0;
virtual std::vector<std::string> GetMultiArgs(const std::string& arg) = 0;
virtual int64_t GetArg(const std::string& strArg, int64_t nDefault) = 0;
};

struct ArgReset {
Expand Down
2 changes: 1 addition & 1 deletion src/qt/optionsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include "guiutil.h"
#include "optionsmodel.h"

#include "main.h" // for MAX_SCRIPTCHECK_THREADS
#include "options.h" // for MAX_SCRIPTCHECK_THREADS
#include "netbase.h"
#include "txdb.h" // for -dbcache defaults

Expand Down
2 changes: 1 addition & 1 deletion src/qt/optionsmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

#include "amount.h"
#include "init.h"
#include "main.h"
#include "options.h"
#include "net.h"
#include "txdb.h" // for -dbcache defaults

Expand Down
4 changes: 4 additions & 0 deletions src/test/clientversion_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ struct DummyArgGetter : public ArgGetter {
return uacomment;
return std::vector<std::string>();
}
virtual int64_t GetArg(const std::string& strArg, int64_t nDefault) {
assert(false);
}


bool stealthmode;
bool hideplatform;
Expand Down
79 changes: 79 additions & 0 deletions src/test/options_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (c) 2016 The Bitcoin XT developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/test/unit_test.hpp>

#include "options.h"
#include <limits.h>

const int NOT_SET = std::numeric_limits<int>::min();

struct DummyArgGetter : public ArgGetter {

DummyArgGetter() : ArgGetter(),
par(NOT_SET), checkpdays(NOT_SET)
{
}

virtual int64_t GetArg(const std::string& strArg, int64_t nDefault) {
if (strArg == "-par")
return par == NOT_SET ? nDefault : par;

if (strArg == "-checkpoint-days")
return checkpdays == NOT_SET ? nDefault : checkpdays;

assert(false);
}
virtual std::vector<std::string> GetMultiArgs(const std::string& arg) {
assert(false);
}
virtual bool GetBool(const std::string& arg, bool def) {
assert(false);
}
int par;
int checkpdays;
};

BOOST_AUTO_TEST_SUITE(options_tests);

BOOST_AUTO_TEST_CASE(scripthreads) {
std::auto_ptr<DummyArgGetter> arg(new DummyArgGetter);
DummyArgGetter* argPtr = arg.get();
std::auto_ptr<ArgReset> argraii
= SetDummyArgGetter(std::auto_ptr<ArgGetter>(arg.release()));

argPtr->par = 0; // auto
BOOST_CHECK(Opt().ScriptCheckThreads() > 0);

argPtr->par = 1; // not threaded
BOOST_CHECK_EQUAL(0, Opt().ScriptCheckThreads());

argPtr->par = 3; // 3 threads
BOOST_CHECK_EQUAL(3, Opt().ScriptCheckThreads());
}

BOOST_AUTO_TEST_CASE(checkpointdays) {
std::auto_ptr<DummyArgGetter> arg(new DummyArgGetter);
DummyArgGetter* argPtr = arg.get();
std::auto_ptr<ArgReset> argraii
= SetDummyArgGetter(std::auto_ptr<ArgGetter>(arg.release()));

// No multiplier
argPtr->par = 1;
BOOST_CHECK_EQUAL(DEFAULT_CHECKPOINT_DAYS, Opt().CheckpointDays());

// x3 multiplier (3 script threads)
argPtr->par = 3;
BOOST_CHECK_EQUAL(3 * DEFAULT_CHECKPOINT_DAYS, Opt().CheckpointDays());

// Explicitly set days overrides default and multipliers
argPtr->checkpdays = 1;
BOOST_CHECK_EQUAL(1, Opt().CheckpointDays());

// Can't have less than 1 day
argPtr->checkpdays = 0;
BOOST_CHECK_EQUAL(1, Opt().CheckpointDays());
}

BOOST_AUTO_TEST_SUITE_END()
5 changes: 3 additions & 2 deletions src/test/test_bitcoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "txdb.h"
#include "ui_interface.h"
#include "util.h"
#include "options.h"
#ifdef ENABLE_WALLET
#include "wallet/db.h"
#include "wallet/wallet.h"
Expand Down Expand Up @@ -60,8 +61,8 @@ TestingSetup::TestingSetup()
pwalletMain->LoadWallet(fFirstRun);
RegisterValidationInterface(pwalletMain);
#endif
nScriptCheckThreads = 3;
for (int i=0; i < nScriptCheckThreads-1; i++)
mapArgs["-par"] = "3";
for (int i=0; i < Opt().ScriptCheckThreads()-1; i++)
threadGroup.create_thread(&ThreadScriptCheck);
RegisterNodeSignals(GetNodeSignals());
}
Expand Down

0 comments on commit 042fac7

Please sign in to comment.