Pass checkpoint data in as necessarytags/v0.15.1
@@ -25,12 +25,12 @@ namespace Checkpoints { | |||
bool fEnabled = true; | |||
bool CheckBlock(int nHeight, const uint256& hash) | |||
bool CheckBlock(const CCheckpointData& data, int nHeight, const uint256& hash) | |||
{ | |||
if (!fEnabled) | |||
return true; | |||
const MapCheckpoints& checkpoints = Params().Checkpoints().mapCheckpoints; | |||
const MapCheckpoints& checkpoints = data.mapCheckpoints; | |||
MapCheckpoints::const_iterator i = checkpoints.find(nHeight); | |||
if (i == checkpoints.end()) return true; | |||
@@ -38,7 +38,7 @@ namespace Checkpoints { | |||
} | |||
//! Guess how far we are in the verification process at the given block index | |||
double GuessVerificationProgress(CBlockIndex *pindex, bool fSigchecks) { | |||
double GuessVerificationProgress(const CCheckpointData& data, CBlockIndex *pindex, bool fSigchecks) { | |||
if (pindex==NULL) | |||
return 0.0; | |||
@@ -50,8 +50,6 @@ namespace Checkpoints { | |||
// Work is defined as: 1.0 per transaction before the last checkpoint, and | |||
// fSigcheckVerificationFactor per transaction after. | |||
const CCheckpointData &data = Params().Checkpoints(); | |||
if (pindex->nChainTx <= data.nTransactionsLastCheckpoint) { | |||
double nCheapBefore = pindex->nChainTx; | |||
double nCheapAfter = data.nTransactionsLastCheckpoint - pindex->nChainTx; | |||
@@ -69,22 +67,22 @@ namespace Checkpoints { | |||
return fWorkBefore / (fWorkBefore + fWorkAfter); | |||
} | |||
int GetTotalBlocksEstimate() | |||
int GetTotalBlocksEstimate(const CCheckpointData& data) | |||
{ | |||
if (!fEnabled) | |||
return 0; | |||
const MapCheckpoints& checkpoints = Params().Checkpoints().mapCheckpoints; | |||
const MapCheckpoints& checkpoints = data.mapCheckpoints; | |||
return checkpoints.rbegin()->first; | |||
} | |||
CBlockIndex* GetLastCheckpoint() | |||
CBlockIndex* GetLastCheckpoint(const CCheckpointData& data) | |||
{ | |||
if (!fEnabled) | |||
return NULL; | |||
const MapCheckpoints& checkpoints = Params().Checkpoints().mapCheckpoints; | |||
const MapCheckpoints& checkpoints = data.mapCheckpoints; | |||
BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, checkpoints) | |||
{ |
@@ -27,15 +27,15 @@ struct CCheckpointData { | |||
}; | |||
//! Returns true if block passes checkpoint checks | |||
bool CheckBlock(int nHeight, const uint256& hash); | |||
bool CheckBlock(const CCheckpointData& data, int nHeight, const uint256& hash); | |||
//! Return conservative estimate of total number of blocks, 0 if unknown | |||
int GetTotalBlocksEstimate(); | |||
int GetTotalBlocksEstimate(const CCheckpointData& data); | |||
//! Returns last CBlockIndex* in mapBlockIndex that is a checkpoint | |||
CBlockIndex* GetLastCheckpoint(); | |||
CBlockIndex* GetLastCheckpoint(const CCheckpointData& data); | |||
double GuessVerificationProgress(CBlockIndex* pindex, bool fSigchecks = true); | |||
double GuessVerificationProgress(const CCheckpointData& data, CBlockIndex* pindex, bool fSigchecks = true); | |||
extern bool fEnabled; | |||
@@ -1204,8 +1204,9 @@ CAmount GetBlockValue(int nHeight, const CAmount& nFees) | |||
bool IsInitialBlockDownload() | |||
{ | |||
const CChainParams& chainParams = Params(); | |||
LOCK(cs_main); | |||
if (fImporting || fReindex || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate()) | |||
if (fImporting || fReindex || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate(chainParams.Checkpoints())) | |||
return true; | |||
static bool lockIBDState = false; | |||
if (lockIBDState) | |||
@@ -1709,7 +1710,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin | |||
return true; | |||
} | |||
bool fScriptChecks = pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate(); | |||
bool fScriptChecks = pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints()); | |||
// Do not allow blocks that contain transactions which 'overwrite' older transactions, | |||
// unless those are already completely spent. | |||
@@ -1954,6 +1955,7 @@ void PruneAndFlush() { | |||
/** Update chainActive and related internal data structures. */ | |||
void static UpdateTip(CBlockIndex *pindexNew) { | |||
const CChainParams& chainParams = Params(); | |||
chainActive.SetTip(pindexNew); | |||
// New best block | |||
@@ -1963,7 +1965,7 @@ void static UpdateTip(CBlockIndex *pindexNew) { | |||
LogPrintf("%s: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f cache=%u\n", __func__, | |||
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx, | |||
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), | |||
Checkpoints::GuessVerificationProgress(chainActive.Tip()), (unsigned int)pcoinsTip->GetCacheSize()); | |||
Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()), (unsigned int)pcoinsTip->GetCacheSize()); | |||
cvBlockChange.notify_all(); | |||
@@ -2247,6 +2249,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo | |||
bool ActivateBestChain(CValidationState &state, CBlock *pblock) { | |||
CBlockIndex *pindexNewTip = NULL; | |||
CBlockIndex *pindexMostWork = NULL; | |||
const CChainParams& chainParams = Params(); | |||
do { | |||
boost::this_thread::interruption_point(); | |||
@@ -2271,7 +2274,7 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) { | |||
if (!fInitialDownload) { | |||
uint256 hashNewTip = pindexNewTip->GetBlockHash(); | |||
// Relay inventory, but don't relay old inventory during initial block download. | |||
int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(); | |||
int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainParams.Checkpoints()); | |||
// Don't relay blocks if pruning -- could cause a peer to try to download, resulting | |||
// in a stalled download if the block file is pruned before the request. | |||
if (nLocalServices & NODE_NETWORK) { | |||
@@ -2601,7 +2604,8 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo | |||
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex * const pindexPrev) | |||
{ | |||
const Consensus::Params& consensusParams = Params().GetConsensus(); | |||
const CChainParams& chainParams = Params(); | |||
const Consensus::Params& consensusParams = chainParams.GetConsensus(); | |||
uint256 hash = block.GetHash(); | |||
if (hash == consensusParams.hashGenesisBlock) | |||
return true; | |||
@@ -2611,7 +2615,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta | |||
int nHeight = pindexPrev->nHeight+1; | |||
// Check proof of work | |||
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, Params().GetConsensus())) | |||
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams)) | |||
return state.DoS(100, error("%s: incorrect proof of work", __func__), | |||
REJECT_INVALID, "bad-diffbits"); | |||
@@ -2621,24 +2625,24 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta | |||
REJECT_INVALID, "time-too-old"); | |||
// Check that the block chain matches the known block chain up to a checkpoint | |||
if (!Checkpoints::CheckBlock(nHeight, hash)) | |||
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(); | |||
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainParams.Checkpoints()); | |||
if (pcheckpoint && nHeight < pcheckpoint->nHeight) | |||
return state.DoS(100, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight)); | |||
// Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded: | |||
if (block.nVersion < 2 && IsSuperMajority(2, pindexPrev, Params().RejectBlockOutdatedMajority())) | |||
if (block.nVersion < 2 && IsSuperMajority(2, pindexPrev, consensusParams.nMajorityRejectBlockOutdated)) | |||
{ | |||
return state.Invalid(error("%s: rejected nVersion=1 block", __func__), | |||
REJECT_OBSOLETE, "bad-version"); | |||
} | |||
// Reject block.nVersion=2 blocks when 95% (75% on testnet) of the network has upgraded: | |||
if (block.nVersion < 3 && IsSuperMajority(3, pindexPrev, Params().RejectBlockOutdatedMajority())) | |||
if (block.nVersion < 3 && IsSuperMajority(3, pindexPrev, consensusParams.nMajorityRejectBlockOutdated)) | |||
{ | |||
return state.Invalid(error("%s : rejected nVersion=2 block", __func__), | |||
REJECT_OBSOLETE, "bad-version"); | |||
@@ -3025,6 +3029,7 @@ CBlockIndex * InsertBlockIndex(uint256 hash) | |||
bool static LoadBlockIndexDB() | |||
{ | |||
const CChainParams& chainparams = Params(); | |||
if (!pblocktree->LoadBlockIndexGuts()) | |||
return false; | |||
@@ -3127,7 +3132,7 @@ bool static LoadBlockIndexDB() | |||
LogPrintf("%s: hashBestChain=%s height=%d date=%s progress=%f\n", __func__, | |||
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), | |||
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), | |||
Checkpoints::GuessVerificationProgress(chainActive.Tip())); | |||
Checkpoints::GuessVerificationProgress(chainparams.Checkpoints(), chainActive.Tip())); | |||
return true; | |||
} |
@@ -89,7 +89,7 @@ QDateTime ClientModel::getLastBlockDate() const | |||
double ClientModel::getVerificationProgress() const | |||
{ | |||
LOCK(cs_main); | |||
return Checkpoints::GuessVerificationProgress(chainActive.Tip()); | |||
return Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip()); | |||
} | |||
void ClientModel::updateTimer() |
@@ -490,7 +490,7 @@ Value getblockchaininfo(const Array& params, bool fHelp) | |||
obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1)); | |||
obj.push_back(Pair("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex())); | |||
obj.push_back(Pair("difficulty", (double)GetDifficulty())); | |||
obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(chainActive.Tip()))); | |||
obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip()))); | |||
obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex())); | |||
return obj; | |||
} |
@@ -10,6 +10,7 @@ | |||
#include "uint256.h" | |||
#include "test/test_bitcoin.h" | |||
#include "chainparams.h" | |||
#include <boost/test/unit_test.hpp> | |||
@@ -19,21 +20,22 @@ 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(11111, p11111)); | |||
BOOST_CHECK(Checkpoints::CheckBlock(134444, p134444)); | |||
BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 11111, p11111)); | |||
BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 134444, p134444)); | |||
// Wrong hashes at checkpoints should fail: | |||
BOOST_CHECK(!Checkpoints::CheckBlock(11111, p134444)); | |||
BOOST_CHECK(!Checkpoints::CheckBlock(134444, p11111)); | |||
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(11111+1, p134444)); | |||
BOOST_CHECK(Checkpoints::CheckBlock(134444+1, p11111)); | |||
BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 11111+1, p134444)); | |||
BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 134444+1, p11111)); | |||
BOOST_CHECK(Checkpoints::GetTotalBlocksEstimate() >= 134444); | |||
BOOST_CHECK(Checkpoints::GetTotalBlocksEstimate(checkpoints) >= 134444); | |||
} | |||
BOOST_AUTO_TEST_SUITE_END() |
@@ -1059,6 +1059,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) | |||
{ | |||
int ret = 0; | |||
int64_t nNow = GetTime(); | |||
const CChainParams& chainParams = Params(); | |||
CBlockIndex* pindex = pindexStart; | |||
{ | |||
@@ -1070,12 +1071,12 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) | |||
pindex = chainActive.Next(pindex); | |||
ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup | |||
double dProgressStart = Checkpoints::GuessVerificationProgress(pindex, false); | |||
double dProgressTip = Checkpoints::GuessVerificationProgress(chainActive.Tip(), false); | |||
double dProgressStart = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false); | |||
double dProgressTip = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip(), false); | |||
while (pindex) | |||
{ | |||
if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0) | |||
ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((Checkpoints::GuessVerificationProgress(pindex, false) - dProgressStart) / (dProgressTip - dProgressStart) * 100)))); | |||
ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false) - dProgressStart) / (dProgressTip - dProgressStart) * 100)))); | |||
CBlock block; | |||
ReadBlockFromDisk(block, pindex); | |||
@@ -1087,7 +1088,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) | |||
pindex = chainActive.Next(pindex); | |||
if (GetTime() >= nNow + 60) { | |||
nNow = GetTime(); | |||
LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, Checkpoints::GuessVerificationProgress(pindex)); | |||
LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex)); | |||
} | |||
} | |||
ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI |