diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 31be88a382..5678ca4bd3 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -1,511 +1,510 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers // Copyright (c) 2017-2018 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include #include #include static CBlock CreateGenesisBlock(const char *pszTimestamp, const CScript &genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const Amount genesisReward) { CMutableTransaction txNew; txNew.nVersion = 1; txNew.vin.resize(1); txNew.vout.resize(1); txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << std::vector((const uint8_t *)pszTimestamp, (const uint8_t *)pszTimestamp + strlen(pszTimestamp)); txNew.vout[0].nValue = genesisReward; txNew.vout[0].scriptPubKey = genesisOutputScript; CBlock genesis; genesis.nTime = nTime; genesis.nBits = nBits; genesis.nNonce = nNonce; genesis.nVersion = nVersion; genesis.vtx.push_back(MakeTransactionRef(std::move(txNew))); genesis.hashPrevBlock.SetNull(); genesis.hashMerkleRoot = BlockMerkleRoot(genesis); return genesis; } /** * Build the genesis block. Note that the output of its generation transaction * cannot be spent since it did not originally exist in the database. * * CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, * hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, * vtx=1) * CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0) * CTxIn(COutPoint(000000, -1), coinbase * 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73) * CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B) * vMerkleTree: 4a5e1e */ -static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, - uint32_t nBits, int32_t nVersion, - const Amount genesisReward) { +CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits, + int32_t nVersion, const Amount genesisReward) { const char *pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"; const CScript genesisOutputScript = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909" "a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112" "de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward); } /** * Main network */ /** * 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 */ class CMainParams : public CChainParams { public: CMainParams() { strNetworkID = "main"; consensus.nSubsidyHalvingInterval = 210000; consensus.BIP34Height = 227931; consensus.BIP34Hash = uint256S( "000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8"); // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0 consensus.BIP65Height = 388381; // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931 consensus.BIP66Height = 363725; // 000000000000000004a1b34462cb8aeebd5799177f7a29cf28f2d1961716b5b5 consensus.CSVHeight = 419328; consensus.powLimit = uint256S( "00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // two weeks consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; consensus.nPowTargetSpacing = 10 * 60; consensus.fPowAllowMinDifficultyBlocks = false; consensus.fPowNoRetargeting = false; // 95% of 2016 consensus.nRuleChangeActivationThreshold = 1916; // nPowTargetTimespan / nPowTargetSpacing consensus.nMinerConfirmationWindow = 2016; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; // January 1, 2008 consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // December 31, 2008 consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // The best chain should have at least this much work. consensus.nMinimumChainWork = uint256S( "000000000000000000000000000000000000000000eafdfa9271c11ceae5513a"); // By default assume that the signatures in ancestors of this block are // valid. consensus.defaultAssumeValid = uint256S( "000000000000000001b4b8e36aec7d4f9671a47872cb9a74dc16ca398c7dcc18"); // August 1, 2017 hard fork consensus.uahfHeight = 478558; // November 13, 2017 hard fork consensus.daaHeight = 504031; // November 15, 2018 hard fork consensus.magneticAnomalyHeight = 556766; // Wed, 15 May 2019 12:00:00 UTC hard fork consensus.greatWallActivationTime = 1557921600; // Nov 15, 2019 12:00:00 UTC protocol upgrade consensus.gravitonActivationTime = 1573819200; /** * The message start string is designed to be unlikely to occur in * normal data. The characters are rarely used upper ASCII, not valid as * UTF-8, and produce a large 32-bit integer with any alignment. */ diskMagic[0] = 0xf9; diskMagic[1] = 0xbe; diskMagic[2] = 0xb4; diskMagic[3] = 0xd9; netMagic[0] = 0xe3; netMagic[1] = 0xe1; netMagic[2] = 0xf3; netMagic[3] = 0xe8; nDefaultPort = 8333; nPruneAfterHeight = 100000; genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); assert(consensus.hashGenesisBlock == uint256S("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1" "b60a8ce26f")); assert(genesis.hashMerkleRoot == uint256S("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b" "7afdeda33b")); // Note that of those which support the service bits prefix, most only // support a subset of possible options. This is fine at runtime as // we'll fall back to using them as a oneshot if they don't support the // service bits we want, but we should get them updated to support all // service bits wanted by any release ASAP to avoid it where possible. // Bitcoin ABC seeder vSeeds.emplace_back("seed.bitcoinabc.org"); // bitcoinforks seeders vSeeds.emplace_back("seed-abc.bitcoinforks.org"); // BU backed seeder vSeeds.emplace_back("btccash-seeder.bitcoinunlimited.info"); // Bitprim vSeeds.emplace_back("seed.bitprim.org"); // Amaury SÉCHET vSeeds.emplace_back("seed.deadalnix.me"); // criptolayer.net vSeeds.emplace_back("seeder.criptolayer.net"); base58Prefixes[PUBKEY_ADDRESS] = std::vector(1, 0); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1, 5); base58Prefixes[SECRET_KEY] = std::vector(1, 128); base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x88, 0xB2, 0x1E}; base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x88, 0xAD, 0xE4}; cashaddrPrefix = "bitcoincash"; vFixedSeeds = std::vector( pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main)); fDefaultConsistencyChecks = false; fRequireStandard = true; fMineBlocksOnDemand = false; checkpointData = { .mapCheckpoints = { {11111, uint256S("0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee" "92559f542fdb26e7c1d")}, {33333, uint256S("000000002dd5588a74784eaa7ab0507a18ad16a236e7b" "1ce69f00d7ddfb5d0a6")}, {74000, uint256S("0000000000573993a3c9e41ce34471c079dcf5f52a0e8" "24a81e7f953b8661a20")}, {105000, uint256S("00000000000291ce28027faea320c8d2b054b2e0fe44" "a773f3eefb151d6bdc97")}, {134444, uint256S("00000000000005b12ffd4cd315cd34ffd4a594f430ac" "814c91184a0d42d2b0fe")}, {168000, uint256S("000000000000099e61ea72015e79632f216fe6cb33d7" "899acb35b75c8303b763")}, {193000, uint256S("000000000000059f452a5f7340de6682a977387c1701" "0ff6e6c3bd83ca8b1317")}, {210000, uint256S("000000000000048b95347e83192f69cf0366076336c6" "39f9b7228e9ba171342e")}, {216116, uint256S("00000000000001b4f4b433e81ee46494af945cf96014" "816a4e2370f11b23df4e")}, {225430, uint256S("00000000000001c108384350f74090433e7fcf79a606" "b8e797f065b130575932")}, {250000, uint256S("000000000000003887df1f29024b06fc2200b55f8af8" "f35453d7be294df2d214")}, {279000, uint256S("0000000000000001ae8c72a0b0c301f67e3afca10e81" "9efa9041e458e9bd7e40")}, {295000, uint256S("00000000000000004d9b4ef50f0f9d686fd69db2e03a" "f35a100370c64632a983")}, // UAHF fork block. {478558, uint256S("0000000000000000011865af4122fe3b144e2cbeea86" "142e8ff2fb4107352d43")}, // Nov, 13 DAA activation block. {504031, uint256S("0000000000000000011ebf65b60d0a3de80b8175be70" "9d653b4c1a1beeb6ab9c")}, // Monolith activation. {530359, uint256S("0000000000000000011ada8bd08f46074f44a8f15539" "6f43e38acf9501c49103")}, // Magnetic anomaly activation. {556767, uint256S("0000000000000000004626ff6e3b936941d341c5932e" "ce4357eeccac44e6d56c")}, // Great wall activation. {582680, uint256S("000000000000000001b4b8e36aec7d4f9671a47872cb" "9a74dc16ca398c7dcc18")}, }}; // Data as of block // 000000000000000001d2ce557406b017a928be25ee98906397d339c3f68eec5d // (height 523992). chainTxData = ChainTxData{ // UNIX timestamp of last known number of transactions. 1522608016, // Total number of transactions between genesis and that timestamp // (the tx=... number in the ChainStateFlushed debug.log lines) 248589038, // Estimated number of transactions per second after that timestamp. 3.2}; } }; /** * Testnet (v3) */ class CTestNetParams : public CChainParams { public: CTestNetParams() { strNetworkID = "test"; consensus.nSubsidyHalvingInterval = 210000; consensus.BIP34Height = 21111; consensus.BIP34Hash = uint256S( "0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8"); // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6 consensus.BIP65Height = 581885; // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182 consensus.BIP66Height = 330776; // 00000000025e930139bac5c6c31a403776da130831ab85be56578f3fa75369bb consensus.CSVHeight = 770112; consensus.powLimit = uint256S( "00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // two weeks consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; consensus.nPowTargetSpacing = 10 * 60; consensus.fPowAllowMinDifficultyBlocks = true; consensus.fPowNoRetargeting = false; // 75% for testchains consensus.nRuleChangeActivationThreshold = 1512; // nPowTargetTimespan / nPowTargetSpacing consensus.nMinerConfirmationWindow = 2016; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; // January 1, 2008 consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // December 31, 2008 consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // The best chain should have at least this much work. consensus.nMinimumChainWork = uint256S( "000000000000000000000000000000000000000000000043cb761ba833f844c5"); // By default assume that the signatures in ancestors of this block are // valid. consensus.defaultAssumeValid = uint256S( "00000000000002cb911c0a756a24c2fe6c1a29acaede3569ce430b95d8ff012d"); // August 1, 2017 hard fork consensus.uahfHeight = 1155875; // November 13, 2017 hard fork consensus.daaHeight = 1188697; // November 15, 2018 hard fork consensus.magneticAnomalyHeight = 1267996; // Wed, 15 May 2019 12:00:00 UTC hard fork consensus.greatWallActivationTime = 1557921600; // Nov 15, 2019 12:00:00 UTC protocol upgrade consensus.gravitonActivationTime = 1573819200; diskMagic[0] = 0x0b; diskMagic[1] = 0x11; diskMagic[2] = 0x09; diskMagic[3] = 0x07; netMagic[0] = 0xf4; netMagic[1] = 0xe5; netMagic[2] = 0xf3; netMagic[3] = 0xf4; nDefaultPort = 18333; nPruneAfterHeight = 1000; genesis = CreateGenesisBlock(1296688602, 414098458, 0x1d00ffff, 1, 50 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); assert(consensus.hashGenesisBlock == uint256S("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526" "f8d77f4943")); assert(genesis.hashMerkleRoot == uint256S("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b" "7afdeda33b")); vFixedSeeds.clear(); vSeeds.clear(); // nodes with support for servicebits filtering should be at the top // Bitcoin ABC seeder vSeeds.emplace_back("testnet-seed.bitcoinabc.org"); // bitcoinforks seeders vSeeds.emplace_back("testnet-seed-abc.bitcoinforks.org"); // Bitprim vSeeds.emplace_back("testnet-seed.bitprim.org"); // Amaury SÉCHET vSeeds.emplace_back("testnet-seed.deadalnix.me"); // criptolayer.net vSeeds.emplace_back("testnet-seeder.criptolayer.net"); base58Prefixes[PUBKEY_ADDRESS] = std::vector(1, 111); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1, 196); base58Prefixes[SECRET_KEY] = std::vector(1, 239); base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94}; cashaddrPrefix = "bchtest"; vFixedSeeds = std::vector( pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test)); fDefaultConsistencyChecks = false; fRequireStandard = false; fMineBlocksOnDemand = false; checkpointData = { .mapCheckpoints = { {546, uint256S("000000002a936ca763904c3c35fce2f3556c559c0214345" "d31b1bcebf76acb70")}, // UAHF fork block. {1155875, uint256S("00000000f17c850672894b9a75b63a1e72830bbd5f4" "c8889b5c1a80e7faef138")}, // Nov, 13. DAA activation block. {1188697, uint256S("0000000000170ed0918077bde7b4d36cc4c91be69fa" "09211f748240dabe047fb")}, }}; // Data as of block // 000000000005b07ecf85563034d13efd81c1a29e47e22b20f4fc6919d5b09cd6 // (height 1223263) chainTxData = ChainTxData{1522608381, 15052068, 0.15}; } }; /** * Regression test */ class CRegTestParams : public CChainParams { public: CRegTestParams() { strNetworkID = "regtest"; consensus.nSubsidyHalvingInterval = 150; // BIP34 has not activated on regtest (far in the future so block v1 are // not rejected in tests) consensus.BIP34Height = 100000000; consensus.BIP34Hash = uint256(); // BIP65 activated on regtest (Used in rpc activation tests) consensus.BIP65Height = 1351; // BIP66 activated on regtest (Used in rpc activation tests) consensus.BIP66Height = 1251; // CSV activated on regtest (Used in rpc activation tests) consensus.CSVHeight = 576; consensus.powLimit = uint256S( "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // two weeks consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; consensus.nPowTargetSpacing = 10 * 60; consensus.fPowAllowMinDifficultyBlocks = true; consensus.fPowNoRetargeting = true; // 75% for testchains consensus.nRuleChangeActivationThreshold = 108; // Faster than normal for regtest (144 instead of 2016) consensus.nMinerConfirmationWindow = 144; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 999999999999ULL; // The best chain should have at least this much work. consensus.nMinimumChainWork = uint256S("0x00"); // By default assume that the signatures in ancestors of this block are // valid. consensus.defaultAssumeValid = uint256S("0x00"); // UAHF is always enabled on regtest. consensus.uahfHeight = 0; // November 13, 2017 hard fork is always on on regtest. consensus.daaHeight = 0; // November 15, 2018 hard fork is always on on regtest. consensus.magneticAnomalyHeight = 0; // Wed, 15 May 2019 12:00:00 UTC hard fork consensus.greatWallActivationTime = 1557921600; // Nov 15, 2019 12:00:00 UTC protocol upgrade consensus.gravitonActivationTime = 1573819200; diskMagic[0] = 0xfa; diskMagic[1] = 0xbf; diskMagic[2] = 0xb5; diskMagic[3] = 0xda; netMagic[0] = 0xda; netMagic[1] = 0xb5; netMagic[2] = 0xbf; netMagic[3] = 0xfa; nDefaultPort = 18444; nPruneAfterHeight = 1000; genesis = CreateGenesisBlock(1296688602, 2, 0x207fffff, 1, 50 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); assert(consensus.hashGenesisBlock == uint256S("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b" "1a11466e2206")); assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab212" "7b7afdeda33b")); //!< Regtest mode doesn't have any fixed seeds. vFixedSeeds.clear(); //!< Regtest mode doesn't have any DNS seeds. vSeeds.clear(); fDefaultConsistencyChecks = true; fRequireStandard = false; fMineBlocksOnDemand = true; checkpointData = {.mapCheckpoints = { {0, uint256S("0f9188f13cb7b2c71f2a335e3a4fc328bf5" "beb436012afca590b1a11466e2206")}, }}; chainTxData = ChainTxData{0, 0, 0}; base58Prefixes[PUBKEY_ADDRESS] = std::vector(1, 111); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1, 196); base58Prefixes[SECRET_KEY] = std::vector(1, 239); base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94}; cashaddrPrefix = "bchreg"; } }; static std::unique_ptr globalChainParams; const CChainParams &Params() { assert(globalChainParams); return *globalChainParams; } std::unique_ptr CreateChainParams(const std::string &chain) { if (chain == CBaseChainParams::MAIN) { return std::unique_ptr(new CMainParams()); } if (chain == CBaseChainParams::TESTNET) { return std::unique_ptr(new CTestNetParams()); } if (chain == CBaseChainParams::REGTEST) { return std::unique_ptr(new CRegTestParams()); } throw std::runtime_error( strprintf("%s: Unknown chain %s.", __func__, chain)); } void SelectParams(const std::string &network) { SelectBaseParams(network); globalChainParams = CreateChainParams(network); } diff --git a/src/chainparams.h b/src/chainparams.h index f3f3d8d0fa..1efd46fd8d 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -1,121 +1,124 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_CHAINPARAMS_H #define BITCOIN_CHAINPARAMS_H #include #include #include #include #include #include struct SeedSpec6 { uint8_t addr[16]; uint16_t port; }; typedef std::map MapCheckpoints; struct CCheckpointData { MapCheckpoints mapCheckpoints; }; struct ChainTxData { int64_t nTime; int64_t nTxCount; double dTxRate; }; /** * CChainParams defines various tweakable parameters of a given instance of the * Bitcoin system. There are three: the main network on which people trade goods * and services, the public test network which gets reset from time to time and * a regression test mode which is intended for private networks only. It has * minimal difficulty to ensure that blocks can be found instantly. */ class CChainParams { public: enum Base58Type { PUBKEY_ADDRESS, SCRIPT_ADDRESS, SECRET_KEY, EXT_PUBLIC_KEY, EXT_SECRET_KEY, MAX_BASE58_TYPES }; const Consensus::Params &GetConsensus() const { return consensus; } const CMessageHeader::MessageMagic &DiskMagic() const { return diskMagic; } const CMessageHeader::MessageMagic &NetMagic() const { return netMagic; } int GetDefaultPort() const { return nDefaultPort; } const CBlock &GenesisBlock() const { return genesis; } /** Default value for -checkmempool and -checkblockindex argument */ bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; } /** Policy: Filter transactions that do not match well-defined patterns */ bool RequireStandard() const { return fRequireStandard; } uint64_t PruneAfterHeight() const { return nPruneAfterHeight; } /** * Make miner stop after a block is found. In RPC, don't return until * nGenProcLimit blocks are generated. */ bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; } /** Return the BIP70 network string (main, test or regtest) */ std::string NetworkIDString() const { return strNetworkID; } /** Return the list of hostnames to look up for DNS seeds */ const std::vector &DNSSeeds() const { return vSeeds; } const std::vector &Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } const std::string &CashAddrPrefix() const { return cashaddrPrefix; } const std::vector &FixedSeeds() const { return vFixedSeeds; } const CCheckpointData &Checkpoints() const { return checkpointData; } const ChainTxData &TxData() const { return chainTxData; } protected: CChainParams() {} Consensus::Params consensus; CMessageHeader::MessageMagic diskMagic; CMessageHeader::MessageMagic netMagic; int nDefaultPort; uint64_t nPruneAfterHeight; std::vector vSeeds; std::vector base58Prefixes[MAX_BASE58_TYPES]; std::string cashaddrPrefix; std::string strNetworkID; CBlock genesis; std::vector vFixedSeeds; bool fDefaultConsistencyChecks; bool fRequireStandard; bool fMineBlocksOnDemand; CCheckpointData checkpointData; ChainTxData chainTxData; }; /** * Creates and returns a std::unique_ptr of the chosen chain. * @returns a CChainParams* of the chosen chain. * @throws a std::runtime_error if the chain is not supported. */ std::unique_ptr CreateChainParams(const std::string &chain); +CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits, + int32_t nVersion, const Amount genesisReward); + /** * Return the currently selected parameters. This won't change after app * startup, except for unit tests. */ const CChainParams &Params(); /** * Sets the params returned by Params() to those for the given BIP70 chain name. * @throws std::runtime_error when the chain is not supported. */ void SelectParams(const std::string &chain); #endif // BITCOIN_CHAINPARAMS_H diff --git a/src/config.cpp b/src/config.cpp index 80069d446e..1ece0d0d15 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -1,101 +1,104 @@ // Copyright (c) 2017 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include // DEFAULT_MAX_BLOCK_SIZE #include #include // DEFAULT_BLOCK_PRIORITY_PERCENTAGE GlobalConfig::GlobalConfig() : useCashAddr(false), nMaxBlockSize(DEFAULT_MAX_BLOCK_SIZE), nBlockPriorityPercentage(DEFAULT_BLOCK_PRIORITY_PERCENTAGE) {} bool GlobalConfig::SetMaxBlockSize(uint64_t maxBlockSize) { // Do not allow maxBlockSize to be set below historic 1MB limit // It cannot be equal either because of the "must be big" UAHF rule. if (maxBlockSize <= LEGACY_MAX_BLOCK_SIZE) { return false; } nMaxBlockSize = maxBlockSize; return true; } uint64_t GlobalConfig::GetMaxBlockSize() const { return nMaxBlockSize; } bool GlobalConfig::SetBlockPriorityPercentage(int64_t blockPriorityPercentage) { // blockPriorityPercentage has to belong to [0..100] if ((blockPriorityPercentage < 0) || (blockPriorityPercentage > 100)) { return false; } nBlockPriorityPercentage = blockPriorityPercentage; return true; } uint8_t GlobalConfig::GetBlockPriorityPercentage() const { return nBlockPriorityPercentage; } const CChainParams &GlobalConfig::GetChainParams() const { return Params(); } static GlobalConfig gConfig; const Config &GetConfig() { return gConfig; } void GlobalConfig::SetCashAddrEncoding(bool c) { useCashAddr = c; } bool GlobalConfig::UseCashAddrEncoding() const { return useCashAddr; } DummyConfig::DummyConfig() : chainParams(CreateChainParams(CBaseChainParams::REGTEST)) {} DummyConfig::DummyConfig(std::string net) : chainParams(CreateChainParams(net)) {} +DummyConfig::DummyConfig(std::unique_ptr chainParamsIn) + : chainParams(std::move(chainParamsIn)) {} + void DummyConfig::SetChainParams(std::string net) { chainParams = CreateChainParams(net); } void GlobalConfig::SetExcessUTXOCharge(Amount fee) { excessUTXOCharge = fee; } Amount GlobalConfig::GetExcessUTXOCharge() const { return excessUTXOCharge; } void GlobalConfig::SetMinFeePerKB(CFeeRate fee) { feePerKB = fee; } CFeeRate GlobalConfig::GetMinFeePerKB() const { return feePerKB; } void GlobalConfig::SetRPCUserAndPassword(std::string userAndPassword) { rpcUserAndPassword = userAndPassword; } std::string GlobalConfig::GetRPCUserAndPassword() const { return rpcUserAndPassword; } void GlobalConfig::SetRPCCORSDomain(std::string corsDomain) { rpcCORSDomain = corsDomain; } std::string GlobalConfig::GetRPCCORSDomain() const { return rpcCORSDomain; } diff --git a/src/config.h b/src/config.h index 9c415b225a..3900f76c2b 100644 --- a/src/config.h +++ b/src/config.h @@ -1,120 +1,121 @@ // Copyright (c) 2017 Amaury SÉCHET // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_CONFIG_H #define BITCOIN_CONFIG_H #include #include #include #include #include #include class CChainParams; class Config : public boost::noncopyable { public: virtual bool SetMaxBlockSize(uint64_t maxBlockSize) = 0; virtual uint64_t GetMaxBlockSize() const = 0; virtual bool SetBlockPriorityPercentage(int64_t blockPriorityPercentage) = 0; virtual uint8_t GetBlockPriorityPercentage() const = 0; virtual const CChainParams &GetChainParams() const = 0; virtual void SetCashAddrEncoding(bool) = 0; virtual bool UseCashAddrEncoding() const = 0; virtual void SetExcessUTXOCharge(Amount amt) = 0; virtual Amount GetExcessUTXOCharge() const = 0; virtual void SetMinFeePerKB(CFeeRate amt) = 0; virtual CFeeRate GetMinFeePerKB() const = 0; virtual void SetRPCUserAndPassword(std::string userAndPassword) = 0; virtual std::string GetRPCUserAndPassword() const = 0; virtual void SetRPCCORSDomain(std::string corsDomain) = 0; virtual std::string GetRPCCORSDomain() const = 0; }; class GlobalConfig final : public Config { public: GlobalConfig(); bool SetMaxBlockSize(uint64_t maxBlockSize) override; uint64_t GetMaxBlockSize() const override; bool SetBlockPriorityPercentage(int64_t blockPriorityPercentage) override; uint8_t GetBlockPriorityPercentage() const override; const CChainParams &GetChainParams() const override; void SetCashAddrEncoding(bool) override; bool UseCashAddrEncoding() const override; void SetExcessUTXOCharge(Amount) override; Amount GetExcessUTXOCharge() const override; void SetMinFeePerKB(CFeeRate amt) override; CFeeRate GetMinFeePerKB() const override; void SetRPCUserAndPassword(std::string userAndPassword) override; std::string GetRPCUserAndPassword() const override; void SetRPCCORSDomain(std::string corsDomain) override; std::string GetRPCCORSDomain() const override; private: bool useCashAddr; Amount excessUTXOCharge; CFeeRate feePerKB; /** RPC authentication configs */ // Pre-base64-encoded authentication token, with user and password separated // by a colon. std::string rpcUserAndPassword; // CORS domain, the allowed Origin std::string rpcCORSDomain; /** The largest block size this node will accept. */ uint64_t nMaxBlockSize; uint64_t nBlockPriorityPercentage; }; // Dummy for subclassing in unittests class DummyConfig : public Config { public: DummyConfig(); DummyConfig(std::string net); + DummyConfig(std::unique_ptr chainParamsIn); bool SetMaxBlockSize(uint64_t maxBlockSize) override { return false; } uint64_t GetMaxBlockSize() const override { return 0; } bool SetBlockPriorityPercentage(int64_t blockPriorityPercentage) override { return false; } uint8_t GetBlockPriorityPercentage() const override { return 0; } void SetChainParams(std::string net); const CChainParams &GetChainParams() const override { return *chainParams; } void SetCashAddrEncoding(bool) override {} bool UseCashAddrEncoding() const override { return false; } void SetExcessUTXOCharge(Amount amt) override {} Amount GetExcessUTXOCharge() const override { return Amount::zero(); } void SetMinFeePerKB(CFeeRate amt) override{}; CFeeRate GetMinFeePerKB() const override { return CFeeRate(Amount::zero()); } void SetRPCUserAndPassword(std::string userAndPassword) override{}; std::string GetRPCUserAndPassword() const override { return ""; }; void SetRPCCORSDomain(std::string corsDomain) override{}; std::string GetRPCCORSDomain() const override { return ""; }; private: std::unique_ptr chainParams; }; // Temporary woraround. const Config &GetConfig(); #endif diff --git a/src/test/checkpoints_tests.cpp b/src/test/checkpoints_tests.cpp index 24dfb05f7f..d52bf60ee3 100644 --- a/src/test/checkpoints_tests.cpp +++ b/src/test/checkpoints_tests.cpp @@ -1,40 +1,229 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers // Copyright (c) 2018 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. // // Unit tests for block-chain checkpoints // #include +#include #include +#include +#include +#include #include +#include +#include #include #include -BOOST_FIXTURE_TEST_SUITE(checkpoints_tests, BasicTestingSetup) +BOOST_FIXTURE_TEST_SUITE(checkpoints_tests, TestingSetup) BOOST_AUTO_TEST_CASE(sanity) { const auto params = CreateChainParams(CBaseChainParams::MAIN); const CCheckpointData &checkpoints = params->Checkpoints(); uint256 p11111 = uint256S( "0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d"); uint256 p134444 = uint256S( "00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe"); 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_AUTO_TEST_CASE(ban_fork_at_genesis_block) { + DummyConfig config; + + // Sanity check that a checkpoint exists at the genesis block + auto &checkpoints = config.GetChainParams().Checkpoints().mapCheckpoints; + assert(checkpoints.find(0) != checkpoints.end()); + + // Another precomputed genesis block (with differing nTime) should conflict + // with the regnet genesis block checkpoint and not be accepted or stored + // in memory. + CBlockHeader header = + CreateGenesisBlock(1296688603, 2, 0x207fffff, 1, 50 * COIN); + + // Header should not be accepted + CValidationState state; + CBlockHeader invalid; + const CBlockIndex *pindex = nullptr; + BOOST_CHECK( + !ProcessNewBlockHeaders(config, {header}, state, &pindex, &invalid)); + BOOST_CHECK(state.IsInvalid()); + BOOST_CHECK(pindex == nullptr); + BOOST_CHECK(invalid.GetHash() == header.GetHash()); + + // Sanity check to ensure header was not saved in memory + { + LOCK(cs_main); + BOOST_CHECK(LookupBlockIndex(header.GetHash()) == nullptr); + } +} + +class ChainParamsWithCheckpoints : public CChainParams { +public: + ChainParamsWithCheckpoints(const CChainParams &chainParams, + CCheckpointData &checkpoints) + : CChainParams(chainParams) { + checkpointData = checkpoints; + } +}; + +class MainnetConfigWithTestCheckpoints : public DummyConfig { +public: + MainnetConfigWithTestCheckpoints() : DummyConfig(createChainParams()) {} + + static std::unique_ptr createChainParams() { + CCheckpointData checkpoints = { + .mapCheckpoints = { + {2, uint256S("000000006a625f06636b8bb6ac7b960a8d0" + "3705d1ace08b1a19da3fdcc99ddbd")}, + }}; + const auto mainParams = CreateChainParams(CBaseChainParams::MAIN); + return std::make_unique(*mainParams, + checkpoints); + } +}; + +/** + * This test has 4 precomputed blocks mined ontop of the genesis block: + * G ---> A ---> AA (checkpointed) + * \ \ + * \--> B \-> AB + * After the node has accepted only A and AA, these rejects should occur: + * * B should be rejected for forking prior to an accepted checkpoint + * * AB should be rejected for forking at an accepted checkpoint + */ +BOOST_AUTO_TEST_CASE(ban_fork_prior_to_and_at_checkpoints) { + MainnetConfigWithTestCheckpoints config; + + CValidationState state; + CBlockHeader invalid; + const CBlockIndex *pindex = nullptr; + + // Start with mainnet genesis block + CBlockHeader headerG = config.GetChainParams().GenesisBlock(); + BOOST_CHECK(headerG.GetHash() == + uint256S("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f" + "1b60a8ce26f")); + BOOST_CHECK( + ProcessNewBlockHeaders(config, {headerG}, state, &pindex, &invalid)); + pindex = nullptr; + + CBlockHeader headerA, headerB, headerAA, headerAB; + CDataStream stream = CDataStream( + ParseHex( + "010000006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000" + "000000982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e85723" + "3e0e61bc6649ffff001d01e3629901010000000100000000000000000000000000" + "00000000000000000000000000000000000000ffffffff0704ffff001d0104ffff" + "ffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390" + "813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166" + "bf621e73a82cbf2342c858eeac00000000"), + SER_NETWORK, PROTOCOL_VERSION); + stream >> headerA; + BOOST_CHECK(headerA.GetHash() == + uint256S("00000000839a8e6886ab5951d76f411475428afc90947ee320161" + "bbf18eb6048")); + BOOST_CHECK(headerA.hashPrevBlock == headerG.GetHash()); + + stream = CDataStream( + ParseHex( + "010000004860eb18bf1b1620e37e9490fc8a427514416fd75159ab86688e9a8300" + "000000d5fdcc541e25de1c7a5addedf24858b8bb665c9f36ef744ee42c316022c9" + "0f9bb0bc6649ffff001d08d2bd6101010000000100000000000000000000000000" + "00000000000000000000000000000000000000ffffffff0704ffff001d010bffff" + "ffff0100f2052a010000004341047211a824f55b505228e4c3d5194c1fcfaa15a4" + "56abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b4" + "17ab79a0fcae412ae3316b77ac00000000"), + SER_NETWORK, PROTOCOL_VERSION); + stream >> headerAA; + BOOST_CHECK(headerAA.GetHash() == + uint256S("000000006a625f06636b8bb6ac7b960a8d03705d1ace08b1a19da" + "3fdcc99ddbd")); + BOOST_CHECK(headerAA.hashPrevBlock == headerA.GetHash()); + + stream = CDataStream( + ParseHex( + "000000206fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000" + "000000bff4e0fd76ec3e9c8853811dec34dda8d5debb24d4113d94235fd4b24bb2" + "92981b70995cffff001d4e6e050001020000000100000000000000000000000000" + "00000000000000000000000000000000000000ffffffff0d51026302082f454233" + "322e302fffffffff0100f2052a01000000232103c91f2fa16c94c92d08629eeb8f" + "d681658d49f2b3016b13336d67d79f858dbc71ac000000001"), + SER_NETWORK, PROTOCOL_VERSION); + stream >> headerB; + BOOST_CHECK(headerB.hashPrevBlock == headerG.GetHash()); + + stream = CDataStream( + ParseHex( + "000000204860eb18bf1b1620e37e9490fc8a427514416fd75159ab86688e9a8300" + "0000003800b1dd09f3f1a1c9e62ce8dca6d1e6caacc9a02d178ef6ad95527b49ff" + "863f8282995cffff001d2cc70f0001020000000100000000000000000000000000" + "00000000000000000000000000000000000000ffffffff0d52024902082f454233" + "322e302fffffffff0100f2052a010000002321020a56690eb0e2454c1f362d3599" + "89198a0b23505578be4164a65521ee7751eb1dac00000000"), + SER_NETWORK, PROTOCOL_VERSION); + stream >> headerAB; + BOOST_CHECK(headerAB.hashPrevBlock == headerA.GetHash()); + + // Headers A and AA should be accepted + BOOST_CHECK( + ProcessNewBlockHeaders(config, {headerA}, state, &pindex, &invalid)); + BOOST_CHECK(state.IsValid()); + BOOST_CHECK(pindex != nullptr); + pindex = nullptr; + BOOST_CHECK(invalid.IsNull()); + + BOOST_CHECK( + ProcessNewBlockHeaders(config, {headerAA}, state, &pindex, &invalid)); + BOOST_CHECK(state.IsValid()); + BOOST_CHECK(pindex != nullptr); + pindex = nullptr; + BOOST_CHECK(invalid.IsNull()); + + // Header B should be rejected + BOOST_CHECK( + !ProcessNewBlockHeaders(config, {headerB}, state, &pindex, &invalid)); + BOOST_CHECK(state.IsInvalid()); + BOOST_CHECK(state.GetRejectCode() == REJECT_CHECKPOINT); + BOOST_CHECK(state.GetRejectReason() == "bad-fork-prior-to-checkpoint"); + BOOST_CHECK(pindex == nullptr); + BOOST_CHECK(invalid.GetHash() == headerB.GetHash()); + + // Sanity check to ensure header was not saved in memory + { + LOCK(cs_main); + BOOST_CHECK(LookupBlockIndex(headerB.GetHash()) == nullptr); + } + + // Header AB should be rejected + BOOST_CHECK( + !ProcessNewBlockHeaders(config, {headerAB}, state, &pindex, &invalid)); + BOOST_CHECK(state.IsInvalid()); + BOOST_CHECK(state.GetRejectCode() == REJECT_CHECKPOINT); + BOOST_CHECK(state.GetRejectReason() == "checkpoint mismatch"); + BOOST_CHECK(pindex == nullptr); + BOOST_CHECK(invalid.GetHash() == headerAB.GetHash()); + + // Sanity check to ensure header was not saved in memory + { + LOCK(cs_main); + BOOST_CHECK(LookupBlockIndex(headerAB.GetHash()) == nullptr); + } +} + BOOST_AUTO_TEST_SUITE_END()