diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index e2c420ed..9b11f0b3 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -14,13 +14,25 @@ namespace Checkpoints { typedef std::map MapCheckpoints; - // + // How many times we expect transactions after the last checkpoint to + // be slower. This number is conservative. On multi-core CPUs with + // parallel signature checking enabled, this number is way too high. + // We prefer a progressbar that's faster at the end than the other + // way around, though. + static const double fSigcheckVerificationFactor = 15.0; + + struct CCheckpointData { + const MapCheckpoints *mapCheckpoints; + int64 nTimeLastCheckpoint; + int64 nTransactionsLastCheckpoint; + double fTransactionsPerDay; + }; + // What makes a good checkpoint block? // + Is surrounded by blocks with reasonable timestamps // (no blocks before with a timestamp after, none after with // timestamp before) // + Contains no strange transactions - // static MapCheckpoints mapCheckpoints = boost::assign::map_list_of ( 11111, uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")) @@ -33,30 +45,81 @@ namespace Checkpoints (210000, uint256("0x000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e")) (216116, uint256("0x00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e")) ; + static const CCheckpointData data = { + &mapCheckpoints, + 1357902690, // * UNIX timestamp of last checkpoint block + 11011160, // * total number of transactions between genesis and last checkpoint + // (the tx=... number in the SetBestChain debug.log lines) + 50000.0 // * estimated number of transactions per day after checkpoint + }; - static MapCheckpoints mapCheckpointsTestnet = + static MapCheckpoints mapCheckpointsTestnet = boost::assign::map_list_of ( 546, uint256("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")) ; + static const CCheckpointData dataTestnet = { + &mapCheckpointsTestnet, + 1338180505, + 16341, + 300 + }; + + const CCheckpointData &Checkpoints() { + if (fTestNet) + return dataTestnet; + else + return data; + } bool CheckBlock(int nHeight, const uint256& hash) { if (!GetBoolArg("-checkpoints", true)) return true; - MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints); + const MapCheckpoints& checkpoints = *Checkpoints().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(CBlockIndex *pindex) { + if (pindex==NULL) + return 0.0; + + int64 nNow = time(NULL); + + double fWorkBefore = 0.0; // Amount of work done before pindex + double fWorkAfter = 0.0; // Amount of work left after pindex (estimated) + // Work is defined as: 1.0 per transaction before the last checkoint, and + // fSigcheckVerificationFactor per transaction after. + + const CCheckpointData &data = Checkpoints(); + + if (pindex->nChainTx <= data.nTransactionsLastCheckpoint) { + double nCheapBefore = pindex->nChainTx; + double nCheapAfter = data.nTransactionsLastCheckpoint - pindex->nChainTx; + double nExpensiveAfter = (nNow - data.nTimeLastCheckpoint)/86400.0*data.fTransactionsPerDay; + fWorkBefore = nCheapBefore; + fWorkAfter = nCheapAfter + nExpensiveAfter*fSigcheckVerificationFactor; + } else { + double nCheapBefore = data.nTransactionsLastCheckpoint; + double nExpensiveBefore = pindex->nChainTx - data.nTransactionsLastCheckpoint; + double nExpensiveAfter = (nNow - pindex->nTime)/86400.0*data.fTransactionsPerDay; + fWorkBefore = nCheapBefore + nExpensiveBefore*fSigcheckVerificationFactor; + fWorkAfter = nExpensiveAfter*fSigcheckVerificationFactor; + } + + return fWorkBefore / (fWorkBefore + fWorkAfter); + } + int GetTotalBlocksEstimate() { if (!GetBoolArg("-checkpoints", true)) return 0; - MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints); + const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints; return checkpoints.rbegin()->first; } @@ -66,7 +129,7 @@ namespace Checkpoints if (!GetBoolArg("-checkpoints", true)) return NULL; - MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints); + const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints; BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, checkpoints) { diff --git a/src/checkpoints.h b/src/checkpoints.h index 70e93656..dcfb44e1 100644 --- a/src/checkpoints.h +++ b/src/checkpoints.h @@ -22,6 +22,8 @@ namespace Checkpoints // Returns last CBlockIndex* in mapBlockIndex that is a checkpoint CBlockIndex* GetLastCheckpoint(const std::map& mapBlockIndex); + + double GuessVerificationProgress(CBlockIndex *pindex); } #endif diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 635e0cb3..16bc0a47 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -572,8 +572,8 @@ void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks) progressBarLabel->setText(importText); progressBarLabel->setVisible(true); progressBar->setFormat(tr("%1 behind").arg(timeBehindText)); - progressBar->setMaximum(totalSecs); - progressBar->setValue(totalSecs - secs); + progressBar->setMaximum(1000000000); + progressBar->setValue(clientModel->getVerificationProgress() * 1000000000.0 + 0.5); progressBar->setVisible(true); tooltip = tr("Catching up...") + QString("
") + tooltip; diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 5f3368c3..858fbe24 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -6,6 +6,7 @@ #include "alert.h" #include "main.h" +#include "checkpoints.h" #include "ui_interface.h" #include @@ -54,6 +55,10 @@ QDateTime ClientModel::getLastBlockDate() const return QDateTime::fromTime_t(1231006505); // Genesis block's time } +double ClientModel::getVerificationProgress() const +{ + return Checkpoints::GuessVerificationProgress(pindexBest); +} void ClientModel::updateTimer() { diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 1afccb78..a3fe9204 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -34,6 +34,7 @@ public: int getNumBlocks() const; int getNumBlocksAtStartup(); + double getVerificationProgress() const; QDateTime getLastBlockDate() const; //! Return true if client connected to testnet