// Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include // for 'map_list_of()' #include #include "checkpoints.h" #include "main.h" #include "uint256.h" namespace Checkpoints { typedef std::map MapCheckpoints; // How many times we expect transactions after the last checkpoint to // be slower. This number is a compromise, as it can't be accurate for // every system. When reindexing from a fast disk with a slow CPU, it // can be up to 20, while when downloading from a slow network with a // fast multicore CPU, it won't be much higher than 1. static const double fSigcheckVerificationFactor = 5.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 ( 1500, uint256("0x841a2965955dd288cfa707a755d05a54e45f8bd476835ec9af4402a2b59a2967")) ( 4032, uint256("0x9ce90e427198fc0ef05e5905ce3503725b80e26afd35a987965fd7e3d9cf0846")) ( 8064, uint256("0xeb984353fc5190f210651f150c40b8a4bab9eeeff0b729fcb3987da694430d70")) ( 16128, uint256("0x602edf1859b7f9a6af809f1d9b0e6cb66fdc1d4d9dcd7a4bec03e12a1ccd153d")) ( 23420, uint256("0xd80fdf9ca81afd0bd2b2a90ac3a9fe547da58f2530ec874e978fce0b5101b507")) ( 50000, uint256("0x69dc37eb029b68f075a5012dcc0419c127672adb4f3a32882b2b3e71d07a20a6")) ( 80000, uint256("0x4fcb7c02f676a300503f49c764a89955a8f920b46a8cbecb4867182ecdb2e90a")) (120000, uint256("0xbd9d26924f05f6daa7f0155f32828ec89e8e29cee9e7121b026a7a3552ac6131")) (161500, uint256("0xdbe89880474f4bb4f75c227c77ba1cdc024991123b28b8418dbbf7798471ff43")) (179620, uint256("0x2ad9c65c990ac00426d18e446e0fd7be2ffa69e9a7dcb28358a50b2b78b9f709")) (240000, uint256("0x7140d1c4b4c2157ca217ee7636f24c9c73db39c4590c4e6eab2e3ea1555088aa")) (383640, uint256("0x2b6809f094a9215bafc65eb3f110a35127a34be94b7d0590a096c3f126c6f364")) (409004, uint256("0x487518d663d9f1fa08611d9395ad74d982b667fbdc0e77e9cf39b4f1355908a3")) (456000, uint256("0xbf34f71cc6366cd487930d06be22f897e34ca6a40501ac7d401be32456372004")) ; static const CCheckpointData data = { &mapCheckpoints, 1383887110, // * UNIX timestamp of last checkpoint block 2179203, // * total number of transactions between genesis and last checkpoint // (the tx=... number in the SetBestChain debug.log lines) 8000.0 // * estimated number of transactions per day after checkpoint }; static MapCheckpoints mapCheckpointsTestnet = boost::assign::map_list_of ( 546, uint256("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")) ( 35000, uint256("2af959ab4f12111ce947479bfcef16702485f04afd95210aa90fde7d1e4a64ad")) ; static const CCheckpointData dataTestnet = { &mapCheckpointsTestnet, 1369685559, 37581, 300 }; const CCheckpointData &Checkpoints() { if (fTestNet) return dataTestnet; else return data; } bool CheckBlock(int nHeight, const uint256& hash) { if (fTestNet) return true; // Testnet has no checkpoints if (!GetBoolArg("-checkpoints", true)) return true; 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 (fTestNet) return 0; // Testnet has no checkpoints if (!GetBoolArg("-checkpoints", true)) return 0; const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints; return checkpoints.rbegin()->first; } CBlockIndex* GetLastCheckpoint(const std::map& mapBlockIndex) { if (fTestNet) return NULL; // Testnet has no checkpoints if (!GetBoolArg("-checkpoints", true)) return NULL; const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints; BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, checkpoints) { const uint256& hash = i.second; std::map::const_iterator t = mapBlockIndex.find(hash); if (t != mapBlockIndex.end()) return t->second; } return NULL; } }