diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -283,7 +283,6 @@ ui_interface.cpp validation.cpp validationinterface.cpp - versionbits.cpp ) # This require libevent diff --git a/src/Makefile.am b/src/Makefile.am --- a/src/Makefile.am +++ b/src/Makefile.am @@ -275,7 +275,6 @@ ui_interface.cpp \ validation.cpp \ validationinterface.cpp \ - versionbits.cpp \ $(BITCOIN_CORE_H) if ENABLE_ZMQ diff --git a/src/Makefile.test.include b/src/Makefile.test.include --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -114,7 +114,6 @@ test/timedata_tests.cpp \ test/transaction_tests.cpp \ test/txvalidationcache_tests.cpp \ - test/versionbits_tests.cpp \ test/uint256_tests.cpp \ test/undo_tests.cpp \ test/univalue_tests.cpp \ diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -127,7 +127,6 @@ timedata_tests.cpp transaction_tests.cpp txvalidationcache_tests.cpp - versionbits_tests.cpp uint256_tests.cpp undo_tests.cpp univalue_tests.cpp diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp deleted file mode 100644 --- a/src/test/versionbits_tests.cpp +++ /dev/null @@ -1,392 +0,0 @@ -// Copyright (c) 2014-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. - -#include "chain.h" -#include "chainparams.h" -#include "consensus/params.h" -#include "test/test_bitcoin.h" -#include "validation.h" -#include "versionbits.h" - -#include - -/* Define a virtual block time, one block per 10 minutes after Nov 14 2014, - * 0:55:36am */ -int32_t TestTime(int nHeight) { - return 1415926536 + 600 * nHeight; -} - -static const Consensus::Params paramsDummy = Consensus::Params(); - -class TestConditionChecker : public AbstractThresholdConditionChecker { -private: - mutable ThresholdConditionCache cache; - -public: - int64_t BeginTime(const Consensus::Params ¶ms) const override { - return TestTime(10000); - } - int64_t EndTime(const Consensus::Params ¶ms) const override { - return TestTime(20000); - } - int Period(const Consensus::Params ¶ms) const override { return 1000; } - int Threshold(const Consensus::Params ¶ms) const override { - return 900; - } - bool Condition(const CBlockIndex *pindex, - const Consensus::Params ¶ms) const override { - return (pindex->nVersion & 0x100); - } - - ThresholdState GetStateFor(const CBlockIndex *pindexPrev) const { - return AbstractThresholdConditionChecker::GetStateFor( - pindexPrev, paramsDummy, cache); - } - int GetStateSinceHeightFor(const CBlockIndex *pindexPrev) const { - return AbstractThresholdConditionChecker::GetStateSinceHeightFor( - pindexPrev, paramsDummy, cache); - } -}; - -#define CHECKERS 6 - -class VersionBitsTester { - // A fake blockchain - std::vector vpblock; - - // 6 independent checkers for the same bit. - // The first one performs all checks, the second only 50%, the third only - // 25%, etc... - // This is to test whether lack of cached information leads to the same - // results. - TestConditionChecker checker[CHECKERS]; - - // Test counter (to identify failures) - int num; - -public: - VersionBitsTester() : num(0) {} - - VersionBitsTester &Reset() { - for (unsigned int i = 0; i < vpblock.size(); i++) { - delete vpblock[i]; - } - for (unsigned int i = 0; i < CHECKERS; i++) { - checker[i] = TestConditionChecker(); - } - vpblock.clear(); - return *this; - } - - ~VersionBitsTester() { Reset(); } - - VersionBitsTester &Mine(unsigned int height, int32_t nTime, - int32_t nVersion) { - while (vpblock.size() < height) { - CBlockIndex *pindex = new CBlockIndex(); - pindex->nHeight = vpblock.size(); - pindex->pprev = vpblock.size() > 0 ? vpblock.back() : nullptr; - pindex->nTime = nTime; - pindex->nVersion = nVersion; - pindex->BuildSkip(); - vpblock.push_back(pindex); - } - return *this; - } - - VersionBitsTester &TestStateSinceHeight(int height) { - for (int i = 0; i < CHECKERS; i++) { - if (InsecureRandBits(i) == 0) { - BOOST_CHECK_MESSAGE( - checker[i].GetStateSinceHeightFor( - vpblock.empty() ? nullptr : vpblock.back()) == height, - strprintf("Test %i for StateSinceHeight", num)); - } - } - num++; - return *this; - } - - VersionBitsTester &TestDefined() { - for (int i = 0; i < CHECKERS; i++) { - if (InsecureRandBits(i) == 0) { - BOOST_CHECK_MESSAGE( - checker[i].GetStateFor(vpblock.empty() ? nullptr - : vpblock.back()) == - ThresholdState::DEFINED, - strprintf("Test %i for DEFINED", num)); - } - } - num++; - return *this; - } - - VersionBitsTester &TestStarted() { - for (int i = 0; i < CHECKERS; i++) { - if (InsecureRandBits(i) == 0) { - BOOST_CHECK_MESSAGE( - checker[i].GetStateFor(vpblock.empty() ? nullptr - : vpblock.back()) == - ThresholdState::STARTED, - strprintf("Test %i for STARTED", num)); - } - } - num++; - return *this; - } - - VersionBitsTester &TestLockedIn() { - for (int i = 0; i < CHECKERS; i++) { - if (InsecureRandBits(i) == 0) { - BOOST_CHECK_MESSAGE( - checker[i].GetStateFor(vpblock.empty() ? nullptr - : vpblock.back()) == - ThresholdState::LOCKED_IN, - strprintf("Test %i for LOCKED_IN", num)); - } - } - num++; - return *this; - } - - VersionBitsTester &TestActive() { - for (int i = 0; i < CHECKERS; i++) { - if (InsecureRandBits(i) == 0) { - BOOST_CHECK_MESSAGE( - checker[i].GetStateFor(vpblock.empty() ? nullptr - : vpblock.back()) == - ThresholdState::ACTIVE, - strprintf("Test %i for ACTIVE", num)); - } - } - num++; - return *this; - } - - VersionBitsTester &TestFailed() { - for (int i = 0; i < CHECKERS; i++) { - if (InsecureRandBits(i) == 0) { - BOOST_CHECK_MESSAGE( - checker[i].GetStateFor(vpblock.empty() ? nullptr - : vpblock.back()) == - ThresholdState::FAILED, - strprintf("Test %i for FAILED", num)); - } - } - num++; - return *this; - } - - CBlockIndex *Tip() { return vpblock.size() ? vpblock.back() : nullptr; } -}; - -BOOST_FIXTURE_TEST_SUITE(versionbits_tests, TestingSetup) - -BOOST_AUTO_TEST_CASE(versionbits_test) { - for (int i = 0; i < 64; i++) { - // DEFINED -> FAILED - VersionBitsTester() - .TestDefined() - .TestStateSinceHeight(0) - .Mine(1, TestTime(1), 0x100) - .TestDefined() - .TestStateSinceHeight(0) - .Mine(11, TestTime(11), 0x100) - .TestDefined() - .TestStateSinceHeight(0) - .Mine(989, TestTime(989), 0x100) - .TestDefined() - .TestStateSinceHeight(0) - .Mine(999, TestTime(20000), 0x100) - .TestDefined() - .TestStateSinceHeight(0) - .Mine(1000, TestTime(20000), 0x100) - .TestFailed() - .TestStateSinceHeight(1000) - .Mine(1999, TestTime(30001), 0x100) - .TestFailed() - .TestStateSinceHeight(1000) - .Mine(2000, TestTime(30002), 0x100) - .TestFailed() - .TestStateSinceHeight(1000) - .Mine(2001, TestTime(30003), 0x100) - .TestFailed() - .TestStateSinceHeight(1000) - .Mine(2999, TestTime(30004), 0x100) - .TestFailed() - .TestStateSinceHeight(1000) - .Mine(3000, TestTime(30005), 0x100) - .TestFailed() - .TestStateSinceHeight(1000) - - // DEFINED -> STARTED -> FAILED - .Reset() - .TestDefined() - .TestStateSinceHeight(0) - .Mine(1, TestTime(1), 0) - .TestDefined() - .TestStateSinceHeight(0) - .Mine(1000, TestTime(10000) - 1, 0x100) - .TestDefined() - // One second more and it would be defined - .TestStateSinceHeight(0) - .Mine(2000, TestTime(10000), 0x100) - .TestStarted() - // So that's what happens the next period - .TestStateSinceHeight(2000) - .Mine(2051, TestTime(10010), 0) - .TestStarted() - // 51 old blocks - .TestStateSinceHeight(2000) - .Mine(2950, TestTime(10020), 0x100) - .TestStarted() - // 899 new blocks - .TestStateSinceHeight(2000) - .Mine(3000, TestTime(20000), 0) - .TestFailed() - // 50 old blocks (so 899 out of the past 1000) - .TestStateSinceHeight(3000) - .Mine(4000, TestTime(20010), 0x100) - .TestFailed() - .TestStateSinceHeight(3000) - - // DEFINED -> STARTED -> FAILED while threshold reached - .Reset() - .TestDefined() - .TestStateSinceHeight(0) - .Mine(1, TestTime(1), 0) - .TestDefined() - .TestStateSinceHeight(0) - .Mine(1000, TestTime(10000) - 1, 0x101) - .TestDefined() - // One second more and it would be defined - .TestStateSinceHeight(0) - .Mine(2000, TestTime(10000), 0x101) - .TestStarted() - // So that's what happens the next period - .TestStateSinceHeight(2000) - .Mine(2999, TestTime(30000), 0x100) - .TestStarted() - // 999 new blocks - .TestStateSinceHeight(2000) - .Mine(3000, TestTime(30000), 0x100) - .TestFailed() - // 1 new block (so 1000 out of the past 1000 are new) - .TestStateSinceHeight(3000) - .Mine(3999, TestTime(30001), 0) - .TestFailed() - .TestStateSinceHeight(3000) - .Mine(4000, TestTime(30002), 0) - .TestFailed() - .TestStateSinceHeight(3000) - .Mine(14333, TestTime(30003), 0) - .TestFailed() - .TestStateSinceHeight(3000) - .Mine(24000, TestTime(40000), 0) - .TestFailed() - .TestStateSinceHeight(3000) - - // DEFINED -> STARTED -> LOCKEDIN at the last minute -> ACTIVE - .Reset() - .TestDefined() - .Mine(1, TestTime(1), 0) - .TestDefined() - .TestStateSinceHeight(0) - .Mine(1000, TestTime(10000) - 1, 0x101) - .TestDefined() - // One second more and it would be defined - .TestStateSinceHeight(0) - .Mine(2000, TestTime(10000), 0x101) - .TestStarted() - // So that's what happens the next period - .TestStateSinceHeight(2000) - .Mine(2050, TestTime(10010), 0x200) - .TestStarted() - // 50 old blocks - .TestStateSinceHeight(2000) - .Mine(2950, TestTime(10020), 0x100) - .TestStarted() - // 900 new blocks - .TestStateSinceHeight(2000) - .Mine(2999, TestTime(19999), 0x200) - .TestStarted() - // 49 old blocks - .TestStateSinceHeight(2000) - .Mine(3000, TestTime(29999), 0x200) - .TestLockedIn() - // 1 old block (so 900 out of the past 1000) - .TestStateSinceHeight(3000) - .Mine(3999, TestTime(30001), 0) - .TestLockedIn() - .TestStateSinceHeight(3000) - .Mine(4000, TestTime(30002), 0) - .TestActive() - .TestStateSinceHeight(4000) - .Mine(14333, TestTime(30003), 0) - .TestActive() - .TestStateSinceHeight(4000) - .Mine(24000, TestTime(40000), 0) - .TestActive() - .TestStateSinceHeight(4000) - - // DEFINED multiple periods -> STARTED multiple periods -> FAILED - .Reset() - .TestDefined() - .TestStateSinceHeight(0) - .Mine(999, TestTime(999), 0) - .TestDefined() - .TestStateSinceHeight(0) - .Mine(1000, TestTime(1000), 0) - .TestDefined() - .TestStateSinceHeight(0) - .Mine(2000, TestTime(2000), 0) - .TestDefined() - .TestStateSinceHeight(0) - .Mine(3000, TestTime(10000), 0) - .TestStarted() - .TestStateSinceHeight(3000) - .Mine(4000, TestTime(10000), 0) - .TestStarted() - .TestStateSinceHeight(3000) - .Mine(5000, TestTime(10000), 0) - .TestStarted() - .TestStateSinceHeight(3000) - .Mine(6000, TestTime(20000), 0) - .TestFailed() - .TestStateSinceHeight(6000) - .Mine(7000, TestTime(20000), 0x100) - .TestFailed() - .TestStateSinceHeight(6000); - } - - // Sanity checks of version bit deployments - const auto chainParams = CreateChainParams(CBaseChainParams::MAIN); - const Consensus::Params &mainnetParams = chainParams->GetConsensus(); - for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) { - uint32_t bitmask = VersionBitsMask( - mainnetParams, static_cast(i)); - // Make sure that no deployment tries to set an invalid bit. - BOOST_CHECK_EQUAL(bitmask & ~(uint32_t)VERSIONBITS_TOP_MASK, bitmask); - - // Verify that the deployment windows of different deployment using the - // same bit are disjoint. This test may need modification at such time - // as a new deployment is proposed that reuses the bit of an activated - // soft fork, before the end time of that soft fork. (Alternatively, - // the end time of that activated soft fork could be later changed to be - // earlier to avoid overlap.) - for (int j = i + 1; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; - j++) { - if (VersionBitsMask(mainnetParams, - static_cast(j)) == - bitmask) { - BOOST_CHECK(mainnetParams.vDeployments[j].nStartTime > - mainnetParams.vDeployments[i].nTimeout || - mainnetParams.vDeployments[i].nStartTime > - mainnetParams.vDeployments[j].nTimeout); - } - } - } -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/src/validation.h b/src/validation.h --- a/src/validation.h +++ b/src/validation.h @@ -13,6 +13,7 @@ #include "amount.h" #include "blockfileinfo.h" +#include "chain.h" #include "coins.h" #include "consensus/consensus.h" #include "diskblockpos.h" @@ -691,8 +692,6 @@ */ int GetSpendHeight(const CCoinsViewCache &inputs); -extern VersionBitsCache versionbitscache; - /** * Determine what nVersion a new block should use. */ diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1543,9 +1543,6 @@ scriptcheckqueue.Thread(); } -// Protected by cs_main -VersionBitsCache versionbitscache; - int32_t ComputeBlockVersion(const CBlockIndex *pindexPrev, const Consensus::Params ¶ms) { int32_t nVersion = VERSIONBITS_TOP_BITS; @@ -4859,7 +4856,6 @@ nBlockSequenceId = 1; setDirtyBlockIndex.clear(); setDirtyFileInfo.clear(); - versionbitscache.Clear(); for (BlockMap::value_type &entry : mapBlockIndex) { delete entry.second; diff --git a/src/versionbits.h b/src/versionbits.h --- a/src/versionbits.h +++ b/src/versionbits.h @@ -5,8 +5,7 @@ #ifndef BITCOIN_CONSENSUS_VERSIONBITS #define BITCOIN_CONSENSUS_VERSIONBITS -#include "chain.h" -#include +#include /** What block version to use for new blocks (pre versionbits) */ static const int32_t VERSIONBITS_LAST_OLD_BLOCK_VERSION = 4; @@ -17,67 +16,4 @@ /** Total bits available for versionbits */ static const int32_t VERSIONBITS_NUM_BITS = 29; -enum class ThresholdState { - DEFINED, - STARTED, - LOCKED_IN, - ACTIVE, - FAILED, -}; - -// A map that gives the state for blocks whose height is a multiple of Period(). -// The map is indexed by the block's parent, however, so all keys in the map -// will either be nullptr or a block with (height + 1) % Period() == 0. -typedef std::map ThresholdConditionCache; - -struct BIP9DeploymentInfo { - /** Deployment name */ - const char *name; - /** Whether GBT clients can safely ignore this rule in simplified usage */ - bool gbt_force; -}; - -extern const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[]; - -/** - * Abstract class that implements BIP9-style threshold logic, and caches - * results. - */ -class AbstractThresholdConditionChecker { -protected: - virtual bool Condition(const CBlockIndex *pindex, - const Consensus::Params ¶ms) const = 0; - virtual int64_t BeginTime(const Consensus::Params ¶ms) const = 0; - virtual int64_t EndTime(const Consensus::Params ¶ms) const = 0; - virtual int Period(const Consensus::Params ¶ms) const = 0; - virtual int Threshold(const Consensus::Params ¶ms) const = 0; - -public: - // Note that the functions below take a pindexPrev as input: they compute - // information for block B based on its parent. - ThresholdState GetStateFor(const CBlockIndex *pindexPrev, - const Consensus::Params ¶ms, - ThresholdConditionCache &cache) const; - int GetStateSinceHeightFor(const CBlockIndex *pindexPrev, - const Consensus::Params ¶ms, - ThresholdConditionCache &cache) const; -}; - -struct VersionBitsCache { - ThresholdConditionCache caches[Consensus::MAX_VERSION_BITS_DEPLOYMENTS]; - - void Clear(); -}; - -ThresholdState VersionBitsState(const CBlockIndex *pindexPrev, - const Consensus::Params ¶ms, - Consensus::DeploymentPos pos, - VersionBitsCache &cache); -int VersionBitsStateSinceHeight(const CBlockIndex *pindexPrev, - const Consensus::Params ¶ms, - Consensus::DeploymentPos pos, - VersionBitsCache &cache); -uint32_t VersionBitsMask(const Consensus::Params ¶ms, - Consensus::DeploymentPos pos); - #endif diff --git a/src/versionbits.cpp b/src/versionbits.cpp deleted file mode 100644 --- a/src/versionbits.cpp +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright (c) 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. - -#include "versionbits.h" - -#include "consensus/params.h" - -const struct BIP9DeploymentInfo - VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = { - { - /*.name =*/"testdummy", - /*.gbt_force =*/true, - }, -}; - -ThresholdState AbstractThresholdConditionChecker::GetStateFor( - const CBlockIndex *pindexPrev, const Consensus::Params ¶ms, - ThresholdConditionCache &cache) const { - int nPeriod = Period(params); - int nThreshold = Threshold(params); - int64_t nTimeStart = BeginTime(params); - int64_t nTimeTimeout = EndTime(params); - - // A block's state is always the same as that of the first of its period, so - // it is computed based on a pindexPrev whose height equals a multiple of - // nPeriod - 1. - if (pindexPrev != nullptr) { - pindexPrev = pindexPrev->GetAncestor( - pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod)); - } - - // Walk backwards in steps of nPeriod to find a pindexPrev whose information - // is known - std::vector vToCompute; - while (cache.count(pindexPrev) == 0) { - if (pindexPrev == nullptr) { - // The genesis block is by definition defined. - cache[pindexPrev] = ThresholdState::DEFINED; - break; - } - if (pindexPrev->GetMedianTimePast() < nTimeStart) { - // Optimization: don't recompute down further, as we know every - // earlier block will be before the start time - cache[pindexPrev] = ThresholdState::DEFINED; - break; - } - vToCompute.push_back(pindexPrev); - pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod); - } - - // At this point, cache[pindexPrev] is known - assert(cache.count(pindexPrev)); - ThresholdState state = cache[pindexPrev]; - - // Now walk forward and compute the state of descendants of pindexPrev - while (!vToCompute.empty()) { - ThresholdState stateNext = state; - pindexPrev = vToCompute.back(); - vToCompute.pop_back(); - - switch (state) { - case ThresholdState::DEFINED: { - if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) { - stateNext = ThresholdState::FAILED; - } else if (pindexPrev->GetMedianTimePast() >= nTimeStart) { - stateNext = ThresholdState::STARTED; - } - break; - } - case ThresholdState::STARTED: { - if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) { - stateNext = ThresholdState::FAILED; - break; - } - // We need to count - const CBlockIndex *pindexCount = pindexPrev; - int count = 0; - for (int i = 0; i < nPeriod; i++) { - if (Condition(pindexCount, params)) { - count++; - } - pindexCount = pindexCount->pprev; - } - if (count >= nThreshold) { - stateNext = ThresholdState::LOCKED_IN; - } - break; - } - case ThresholdState::LOCKED_IN: { - // Always progresses into ACTIVE. - stateNext = ThresholdState::ACTIVE; - break; - } - case ThresholdState::FAILED: - case ThresholdState::ACTIVE: { - // Nothing happens, these are terminal states. - break; - } - } - cache[pindexPrev] = state = stateNext; - } - - return state; -} - -int AbstractThresholdConditionChecker::GetStateSinceHeightFor( - const CBlockIndex *pindexPrev, const Consensus::Params ¶ms, - ThresholdConditionCache &cache) const { - const ThresholdState initialState = GetStateFor(pindexPrev, params, cache); - - // BIP 9 about state DEFINED: "The genesis block is by definition in this - // state for each deployment." - if (initialState == ThresholdState::DEFINED) { - return 0; - } - - const int nPeriod = Period(params); - - // A block's state is always the same as that of the first of its period, so - // it is computed based on a pindexPrev whose height equals a multiple of - // nPeriod - 1. To ease understanding of the following height calculation, - // it helps to remember that right now pindexPrev points to the block prior - // to the block that we are computing for, thus: if we are computing for the - // last block of a period, then pindexPrev points to the second to last - // block of the period, and if we are computing for the first block of a - // period, then pindexPrev points to the last block of the previous period. - // The parent of the genesis block is represented by nullptr. - pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - - ((pindexPrev->nHeight + 1) % nPeriod)); - - const CBlockIndex *previousPeriodParent = - pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod); - - while (previousPeriodParent != nullptr && - GetStateFor(previousPeriodParent, params, cache) == initialState) { - pindexPrev = previousPeriodParent; - previousPeriodParent = - pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod); - } - - // Adjust the result because right now we point to the parent block. - return pindexPrev->nHeight + 1; -} - -namespace { -/** - * Class to implement versionbits logic. - */ -class VersionBitsConditionChecker : public AbstractThresholdConditionChecker { -private: - const Consensus::DeploymentPos id; - -protected: - int64_t BeginTime(const Consensus::Params ¶ms) const override { - return params.vDeployments[id].nStartTime; - } - int64_t EndTime(const Consensus::Params ¶ms) const override { - return params.vDeployments[id].nTimeout; - } - int Period(const Consensus::Params ¶ms) const override { - return params.nMinerConfirmationWindow; - } - int Threshold(const Consensus::Params ¶ms) const override { - return params.nRuleChangeActivationThreshold; - } - - bool Condition(const CBlockIndex *pindex, - const Consensus::Params ¶ms) const override { - return (((pindex->nVersion & VERSIONBITS_TOP_MASK) == - VERSIONBITS_TOP_BITS) && - (pindex->nVersion & Mask(params)) != 0); - } - -public: - explicit VersionBitsConditionChecker(Consensus::DeploymentPos id_) - : id(id_) {} - uint32_t Mask(const Consensus::Params ¶ms) const { - return ((uint32_t)1) << params.vDeployments[id].bit; - } -}; -} // namespace - -ThresholdState VersionBitsState(const CBlockIndex *pindexPrev, - const Consensus::Params ¶ms, - Consensus::DeploymentPos pos, - VersionBitsCache &cache) { - return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, - cache.caches[pos]); -} - -int VersionBitsStateSinceHeight(const CBlockIndex *pindexPrev, - const Consensus::Params ¶ms, - Consensus::DeploymentPos pos, - VersionBitsCache &cache) { - return VersionBitsConditionChecker(pos).GetStateSinceHeightFor( - pindexPrev, params, cache.caches[pos]); -} - -uint32_t VersionBitsMask(const Consensus::Params ¶ms, - Consensus::DeploymentPos pos) { - return VersionBitsConditionChecker(pos).Mask(params); -} - -void VersionBitsCache::Clear() { - for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) { - caches[d].clear(); - } -}