0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-08 10:31:50 -05:00

[refactor] versionbits: make VersionBitsCache a full class

Moves the VersionBits* functions to be methods of the cache class,
and makes the cache and its lock private to the class.
This commit is contained in:
Anthony Towns 2020-12-29 11:19:06 +10:00
parent 8ee3e0bed5
commit 0cfd6c6a8f
7 changed files with 39 additions and 34 deletions

View file

@ -23,7 +23,7 @@ inline bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const Consensus
inline bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos dep) inline bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos dep)
{ {
assert(Consensus::ValidDeployment(dep)); assert(Consensus::ValidDeployment(dep));
return ThresholdState::ACTIVE == VersionBitsState(pindexPrev, params, dep, g_versionbitscache); return ThresholdState::ACTIVE == g_versionbitscache.State(pindexPrev, params, dep);
} }
/** Determine if a deployment is active for this block */ /** Determine if a deployment is active for this block */

View file

@ -1372,7 +1372,7 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue&
if (consensusParams.vDeployments[id].nStartTime == Consensus::BIP9Deployment::NEVER_ACTIVE) return; if (consensusParams.vDeployments[id].nStartTime == Consensus::BIP9Deployment::NEVER_ACTIVE) return;
UniValue bip9(UniValue::VOBJ); UniValue bip9(UniValue::VOBJ);
const ThresholdState thresholdState = VersionBitsState(active_chain_tip, consensusParams, id, g_versionbitscache); const ThresholdState thresholdState = g_versionbitscache.State(active_chain_tip, consensusParams, id);
switch (thresholdState) { switch (thresholdState) {
case ThresholdState::DEFINED: bip9.pushKV("status", "defined"); break; case ThresholdState::DEFINED: bip9.pushKV("status", "defined"); break;
case ThresholdState::STARTED: bip9.pushKV("status", "started"); break; case ThresholdState::STARTED: bip9.pushKV("status", "started"); break;
@ -1386,12 +1386,12 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue&
} }
bip9.pushKV("start_time", consensusParams.vDeployments[id].nStartTime); bip9.pushKV("start_time", consensusParams.vDeployments[id].nStartTime);
bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout); bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
int64_t since_height = VersionBitsStateSinceHeight(active_chain_tip, consensusParams, id, g_versionbitscache); int64_t since_height = g_versionbitscache.StateSinceHeight(active_chain_tip, consensusParams, id);
bip9.pushKV("since", since_height); bip9.pushKV("since", since_height);
if (ThresholdState::STARTED == thresholdState) if (ThresholdState::STARTED == thresholdState)
{ {
UniValue statsUV(UniValue::VOBJ); UniValue statsUV(UniValue::VOBJ);
BIP9Stats statsStruct = VersionBitsStatistics(active_chain_tip, consensusParams, id); BIP9Stats statsStruct = g_versionbitscache.Statistics(active_chain_tip, consensusParams, id);
statsUV.pushKV("period", statsStruct.period); statsUV.pushKV("period", statsStruct.period);
statsUV.pushKV("threshold", statsStruct.threshold); statsUV.pushKV("threshold", statsStruct.threshold);
statsUV.pushKV("elapsed", statsStruct.elapsed); statsUV.pushKV("elapsed", statsStruct.elapsed);

View file

@ -841,7 +841,7 @@ static RPCHelpMan getblocktemplate()
UniValue vbavailable(UniValue::VOBJ); UniValue vbavailable(UniValue::VOBJ);
for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) { for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
Consensus::DeploymentPos pos = Consensus::DeploymentPos(j); Consensus::DeploymentPos pos = Consensus::DeploymentPos(j);
ThresholdState state = VersionBitsState(pindexPrev, consensusParams, pos, g_versionbitscache); ThresholdState state = g_versionbitscache.State(pindexPrev, consensusParams, pos);
switch (state) { switch (state) {
case ThresholdState::DEFINED: case ThresholdState::DEFINED:
case ThresholdState::FAILED: case ThresholdState::FAILED:
@ -849,7 +849,7 @@ static RPCHelpMan getblocktemplate()
break; break;
case ThresholdState::LOCKED_IN: case ThresholdState::LOCKED_IN:
// Ensure bit is set in block version // Ensure bit is set in block version
pblock->nVersion |= VersionBitsMask(consensusParams, pos); pblock->nVersion |= g_versionbitscache.Mask(consensusParams, pos);
// FALL THROUGH to get vbavailable set... // FALL THROUGH to get vbavailable set...
case ThresholdState::STARTED: case ThresholdState::STARTED:
{ {
@ -858,7 +858,7 @@ static RPCHelpMan getblocktemplate()
if (setClientRules.find(vbinfo.name) == setClientRules.end()) { if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
if (!vbinfo.gbt_force) { if (!vbinfo.gbt_force) {
// If the client doesn't support this, don't indicate it in the [default] version // If the client doesn't support this, don't indicate it in the [default] version
pblock->nVersion &= ~VersionBitsMask(consensusParams, pos); pblock->nVersion &= ~g_versionbitscache.Mask(consensusParams, pos);
} }
} }
break; break;

View file

@ -288,7 +288,7 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
// Check min_activation_height is on a retarget boundary // Check min_activation_height is on a retarget boundary
BOOST_REQUIRE_EQUAL(min_activation_height % params.nMinerConfirmationWindow, 0U); BOOST_REQUIRE_EQUAL(min_activation_height % params.nMinerConfirmationWindow, 0U);
const uint32_t bitmask{VersionBitsMask(params, dep)}; const uint32_t bitmask{g_versionbitscache.Mask(params, dep)};
BOOST_CHECK_EQUAL(bitmask, uint32_t{1} << bit); BOOST_CHECK_EQUAL(bitmask, uint32_t{1} << bit);
// In the first chain, test that the bit is set by CBV until it has failed. // In the first chain, test that the bit is set by CBV until it has failed.
@ -426,7 +426,7 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
// not take precedence over STARTED/LOCKED_IN. So all softforks on // not take precedence over STARTED/LOCKED_IN. So all softforks on
// the same bit might overlap, even when non-overlapping start-end // the same bit might overlap, even when non-overlapping start-end
// times are picked. // times are picked.
const uint32_t dep_mask{VersionBitsMask(chainParams->GetConsensus(), dep)}; const uint32_t dep_mask{g_versionbitscache.Mask(chainParams->GetConsensus(), dep)};
BOOST_CHECK(!(chain_all_vbits & dep_mask)); BOOST_CHECK(!(chain_all_vbits & dep_mask));
chain_all_vbits |= dep_mask; chain_all_vbits |= dep_mask;
check_computeblockversion(chainParams->GetConsensus(), dep); check_computeblockversion(chainParams->GetConsensus(), dep);

View file

@ -1611,9 +1611,9 @@ int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Para
int32_t nVersion = VERSIONBITS_TOP_BITS; int32_t nVersion = VERSIONBITS_TOP_BITS;
for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) { for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
ThresholdState state = VersionBitsState(pindexPrev, params, static_cast<Consensus::DeploymentPos>(i), g_versionbitscache); ThresholdState state = g_versionbitscache.State(pindexPrev, params, static_cast<Consensus::DeploymentPos>(i));
if (state == ThresholdState::LOCKED_IN || state == ThresholdState::STARTED) { if (state == ThresholdState::LOCKED_IN || state == ThresholdState::STARTED) {
nVersion |= VersionBitsMask(params, static_cast<Consensus::DeploymentPos>(i)); nVersion |= g_versionbitscache.Mask(params, static_cast<Consensus::DeploymentPos>(i));
} }
} }

View file

@ -190,32 +190,32 @@ public:
} // namespace } // namespace
ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache) ThresholdState VersionBitsCache::State(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
{ {
LOCK(cache.mutex); LOCK(m_mutex);
return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]); return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, m_caches[pos]);
} }
BIP9Stats VersionBitsStatistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos) BIP9Stats VersionBitsCache::Statistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
{ {
return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindexPrev, params); return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindexPrev, params);
} }
int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache) int VersionBitsCache::StateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
{ {
LOCK(cache.mutex); LOCK(m_mutex);
return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, cache.caches[pos]); return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, m_caches[pos]);
} }
uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos) uint32_t VersionBitsCache::Mask(const Consensus::Params& params, Consensus::DeploymentPos pos)
{ {
return VersionBitsConditionChecker(pos).Mask(params); return VersionBitsConditionChecker(pos).Mask(params);
} }
void VersionBitsCache::Clear() void VersionBitsCache::Clear()
{ {
LOCK(mutex); LOCK(m_mutex);
for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) { for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
caches[d].clear(); m_caches[d].clear();
} }
} }

View file

@ -73,22 +73,27 @@ public:
int GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const; int GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const;
}; };
/** BIP 9 allows multiple softforks to be deployed in parallel. We cache per-period state for every one of them /** BIP 9 allows multiple softforks to be deployed in parallel. We cache
* keyed by the bit position used to signal support. */ * per-period state for every one of them. */
struct VersionBitsCache class VersionBitsCache
{ {
Mutex mutex; private:
ThresholdConditionCache caches[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] GUARDED_BY(mutex); Mutex m_mutex;
ThresholdConditionCache m_caches[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] GUARDED_BY(m_mutex);
public:
/** Get the numerical statistics for a given deployment for the signalling period that includes the block after pindexPrev. */
static BIP9Stats Statistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos);
static uint32_t Mask(const Consensus::Params& params, Consensus::DeploymentPos pos);
/** Get the BIP9 state for a given deployment for the block after pindexPrev. */
ThresholdState State(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos);
/** Get the block height at which the BIP9 deployment switched into the state for the block after pindexPrev. */
int StateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos);
void Clear(); void Clear();
}; };
/** Get the BIP9 state for a given deployment for the block after pindexPrev. */
ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache);
/** Get the numerical statistics for a given deployment for the signalling period that includes the block after pindexPrev. */
BIP9Stats VersionBitsStatistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos);
/** Get the block height at which the BIP9 deployment switched into the state for the block after pindexPrev. */
int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache);
uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos);
#endif // BITCOIN_VERSIONBITS_H #endif // BITCOIN_VERSIONBITS_H