diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 8d8614817..31be88a38 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -1,511 +1,511 @@ // 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) { 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 SetBestChain debug.log lines) + // (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/index/txindex.cpp b/src/index/txindex.cpp index 7bd1c6d08..356de099e 100644 --- a/src/index/txindex.cpp +++ b/src/index/txindex.cpp @@ -1,281 +1,281 @@ // Copyright (c) 2017-2018 The Bitcoin Core 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 #include constexpr int64_t SYNC_LOG_INTERVAL = 30; // seconds constexpr int64_t SYNC_LOCATOR_WRITE_INTERVAL = 30; // seconds template static void FatalError(const char *fmt, const Args &... args) { std::string strMessage = tfm::format(fmt, args...); SetMiscWarning(strMessage); LogPrintf("*** %s\n", strMessage); uiInterface.ThreadSafeMessageBox( "Error: A fatal internal error occurred, see debug.log for details", "", CClientUIInterface::MSG_ERROR); StartShutdown(); } TxIndex::TxIndex(std::unique_ptr db) : m_db(std::move(db)), m_synced(false), m_best_block_index(nullptr) {} TxIndex::~TxIndex() { Interrupt(); Stop(); } bool TxIndex::Init() { LOCK(cs_main); // Attempt to migrate txindex from the old database to the new one. Even if // chain_tip is null, the node could be reindexing and we still want to // delete txindex records in the old database. if (!m_db->MigrateData(*pblocktree, chainActive.GetLocator())) { return false; } CBlockLocator locator; if (!m_db->ReadBestBlock(locator)) { locator.SetNull(); } m_best_block_index = FindForkInGlobalIndex(chainActive, locator); m_synced = m_best_block_index.load() == chainActive.Tip(); return true; } static const CBlockIndex *NextSyncBlock(const CBlockIndex *pindex_prev) { AssertLockHeld(cs_main); if (!pindex_prev) { return chainActive.Genesis(); } const CBlockIndex *pindex = chainActive.Next(pindex_prev); if (pindex) { return pindex; } return chainActive.Next(chainActive.FindFork(pindex_prev)); } void TxIndex::ThreadSync() { const CBlockIndex *pindex = m_best_block_index.load(); if (!m_synced) { auto &config = GetConfig(); int64_t last_log_time = 0; int64_t last_locator_write_time = 0; while (true) { if (m_interrupt) { WriteBestBlock(pindex); return; } { LOCK(cs_main); const CBlockIndex *pindex_next = NextSyncBlock(pindex); if (!pindex_next) { WriteBestBlock(pindex); m_best_block_index = pindex; m_synced = true; break; } pindex = pindex_next; } int64_t current_time = GetTime(); if (last_log_time + SYNC_LOG_INTERVAL < current_time) { LogPrintf("Syncing txindex with block chain from height %d\n", pindex->nHeight); last_log_time = current_time; } if (last_locator_write_time + SYNC_LOCATOR_WRITE_INTERVAL < current_time) { WriteBestBlock(pindex); last_locator_write_time = current_time; } CBlock block; if (!ReadBlockFromDisk(block, pindex, config)) { FatalError("%s: Failed to read block %s from disk", __func__, pindex->GetBlockHash().ToString()); return; } if (!WriteBlock(block, pindex)) { FatalError("%s: Failed to write block %s to tx index database", __func__, pindex->GetBlockHash().ToString()); return; } } } if (pindex) { LogPrintf("txindex is enabled at height %d\n", pindex->nHeight); } else { LogPrintf("txindex is enabled\n"); } } bool TxIndex::WriteBlock(const CBlock &block, const CBlockIndex *pindex) { CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); std::vector> vPos; vPos.reserve(block.vtx.size()); for (const auto &tx : block.vtx) { vPos.emplace_back(tx->GetHash(), pos); pos.nTxOffset += ::GetSerializeSize(*tx, SER_DISK, CLIENT_VERSION); } return m_db->WriteTxs(vPos); } bool TxIndex::WriteBestBlock(const CBlockIndex *block_index) { LOCK(cs_main); if (!m_db->WriteBestBlock(chainActive.GetLocator(block_index))) { return error("%s: Failed to write locator to disk", __func__); } return true; } void TxIndex::BlockConnected( const std::shared_ptr &block, const CBlockIndex *pindex, const std::vector &txn_conflicted) { if (!m_synced) { return; } const CBlockIndex *best_block_index = m_best_block_index.load(); if (!best_block_index) { if (pindex->nHeight != 0) { FatalError("%s: First block connected is not the genesis block " "(height=%d)", __func__, pindex->nHeight); return; } } else { // Ensure block connects to an ancestor of the current best block. This // should be the case most of the time, but may not be immediately after // the the sync thread catches up and sets m_synced. Consider the case // where there is a reorg and the blocks on the stale branch are in the // ValidationInterface queue backlog even after the sync thread has // caught up to the new chain tip. In this unlikely event, log a warning // and let the queue clear. if (best_block_index->GetAncestor(pindex->nHeight - 1) != pindex->pprev) { LogPrintf("%s: WARNING: Block %s does not connect to an ancestor " "of known best chain (tip=%s); not updating txindex\n", __func__, pindex->GetBlockHash().ToString(), best_block_index->GetBlockHash().ToString()); return; } } if (WriteBlock(*block, pindex)) { m_best_block_index = pindex; } else { FatalError("%s: Failed to write block %s to txindex", __func__, pindex->GetBlockHash().ToString()); return; } } -void TxIndex::SetBestChain(const CBlockLocator &locator) { +void TxIndex::ChainStateFlushed(const CBlockLocator &locator) { if (!m_synced) { return; } const uint256 &locator_tip_hash = locator.vHave.front(); const CBlockIndex *locator_tip_index; { LOCK(cs_main); locator_tip_index = LookupBlockIndex(locator_tip_hash); } if (!locator_tip_index) { FatalError("%s: First block (hash=%s) in locator was not found", __func__, locator_tip_hash.ToString()); return; } - // This checks that SetBestChain callbacks are received after + // This checks that ChainStateFlushed callbacks are received after // BlockConnected. The check may fail immediately after the the sync thread // catches up and sets m_synced. Consider the case where there is a reorg // and the blocks on the stale branch are in the ValidationInterface queue // backlog even after the sync thread has caught up to the new chain tip. In // this unlikely event, log a warning and let the queue clear. const CBlockIndex *best_block_index = m_best_block_index.load(); if (best_block_index->GetAncestor(locator_tip_index->nHeight) != locator_tip_index) { LogPrintf("%s: WARNING: Locator contains block (hash=%s) not on known " "best chain (tip=%s); not writing txindex locator\n", __func__, locator_tip_hash.ToString(), best_block_index->GetBlockHash().ToString()); return; } if (!m_db->WriteBestBlock(locator)) { error("%s: Failed to write locator to disk", __func__); } } bool TxIndex::BlockUntilSyncedToCurrentChain() { AssertLockNotHeld(cs_main); if (!m_synced) { return false; } { // Skip the queue-draining stuff if we know we're caught up with // chainActive.Tip(). LOCK(cs_main); const CBlockIndex *chain_tip = chainActive.Tip(); const CBlockIndex *best_block_index = m_best_block_index.load(); if (best_block_index->GetAncestor(chain_tip->nHeight) == chain_tip) { return true; } } LogPrintf("%s: txindex is catching up on block notifications\n", __func__); SyncWithValidationInterfaceQueue(); return true; } bool TxIndex::FindTx(const uint256 &txid, CDiskTxPos &pos) const { return m_db->ReadTxPos(txid, pos); } void TxIndex::Interrupt() { m_interrupt(); } void TxIndex::Start() { // Need to register this ValidationInterface before running Init(), so that // callbacks are not missed if Init sets m_synced to true. RegisterValidationInterface(this); if (!Init()) { FatalError("%s: txindex failed to initialize", __func__); return; } m_thread_sync = std::thread(&TraceThread>, "txindex", std::bind(&TxIndex::ThreadSync, this)); } void TxIndex::Stop() { UnregisterValidationInterface(this); if (m_thread_sync.joinable()) { m_thread_sync.join(); } } diff --git a/src/index/txindex.h b/src/index/txindex.h index 6c1902210..43db34e5c 100644 --- a/src/index/txindex.h +++ b/src/index/txindex.h @@ -1,87 +1,87 @@ // Copyright (c) 2017-2018 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_INDEX_TXINDEX_H #define BITCOIN_INDEX_TXINDEX_H #include #include #include #include #include class CBlockIndex; /** * TxIndex is used to look up transactions included in the blockchain by hash. * The index is written to a LevelDB database and records the filesystem * location of each transaction by transaction hash. */ class TxIndex final : public CValidationInterface { private: const std::unique_ptr m_db; /// Whether the index is in sync with the main chain. The flag is flipped /// from false to true once, after which point this starts processing /// ValidationInterface notifications to stay in sync. std::atomic m_synced; /// The last block in the chain that the TxIndex is in sync with. std::atomic m_best_block_index; std::thread m_thread_sync; CThreadInterrupt m_interrupt; /// Initialize internal state from the database and block index. bool Init(); /// Sync the tx index with the block index starting from the current best /// block. Intended to be run in its own thread, m_thread_sync, and can be /// interrupted with m_interrupt. Once the txindex gets in sync, the /// m_synced flag is set and the BlockConnected ValidationInterface callback /// takes over and the sync thread exits. void ThreadSync(); /// Write update index entries for a newly connected block. bool WriteBlock(const CBlock &block, const CBlockIndex *pindex); /// Write the current chain block locator to the DB. bool WriteBestBlock(const CBlockIndex *block_index); protected: void BlockConnected(const std::shared_ptr &block, const CBlockIndex *pindex, const std::vector &txn_conflicted) override; - void SetBestChain(const CBlockLocator &locator) override; + void ChainStateFlushed(const CBlockLocator &locator) override; public: /// Constructs the TxIndex, which becomes available to be queried. explicit TxIndex(std::unique_ptr db); /// Destructor interrupts sync thread if running and blocks until it exits. ~TxIndex(); /// Blocks the current thread until the transaction index is caught up to /// the current state of the block chain. This only blocks if the index has /// gotten in sync once and only needs to process blocks in the /// ValidationInterface queue. If the index is catching up from far behind, /// this method does not block and immediately returns false. bool BlockUntilSyncedToCurrentChain(); /// Look up the on-disk location of a transaction by hash. bool FindTx(const uint256 &txid, CDiskTxPos &pos) const; void Interrupt(); /// Start initializes the sync state and registers the instance as a /// ValidationInterface so that it stays in sync with blockchain updates. void Start(); /// Stops the instance from staying in sync with blockchain updates. void Stop(); }; #endif // BITCOIN_INDEX_TXINDEX_H diff --git a/src/init.cpp b/src/init.cpp index dfbc88954..c60a50d9b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1,2449 +1,2449 @@ // 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. #if defined(HAVE_CONFIG_H) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include