Skip to content

Commit 3bd32c2

Browse files
committed
versionbits: Move WarningBits logic from validation to versionbits
1 parent 5da119e commit 3bd32c2

File tree

4 files changed

+80
-55
lines changed

4 files changed

+80
-55
lines changed

src/validation.cpp

Lines changed: 7 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2364,44 +2364,6 @@ DisconnectResult Chainstate::DisconnectBlock(const CBlock& block, const CBlockIn
23642364
return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN;
23652365
}
23662366

2367-
/**
2368-
* Threshold condition checker that triggers when unknown versionbits are seen on the network.
2369-
*/
2370-
class WarningBitsConditionChecker : public AbstractThresholdConditionChecker
2371-
{
2372-
private:
2373-
const ChainstateManager& m_chainman;
2374-
int m_bit;
2375-
2376-
public:
2377-
explicit WarningBitsConditionChecker(const ChainstateManager& chainman, int bit) : m_chainman{chainman}, m_bit(bit) {}
2378-
2379-
int64_t BeginTime() const override { return 0; }
2380-
int64_t EndTime() const override { return std::numeric_limits<int64_t>::max(); }
2381-
int Period() const override {
2382-
if (m_chainman.GetParams().IsTestChain()) {
2383-
return m_chainman.GetConsensus().DifficultyAdjustmentInterval();
2384-
} else {
2385-
return 2016;
2386-
}
2387-
}
2388-
int Threshold() const override {
2389-
if (m_chainman.GetParams().IsTestChain()) {
2390-
return m_chainman.GetConsensus().DifficultyAdjustmentInterval() * 3 / 4; // 75% for test nets per BIP9 suggestion
2391-
} else {
2392-
return 1815; // 90% threshold used in BIP 341
2393-
}
2394-
}
2395-
2396-
bool Condition(const CBlockIndex* pindex) const override
2397-
{
2398-
return pindex->nHeight >= m_chainman.GetConsensus().MinBIP9WarningHeight &&
2399-
((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) &&
2400-
((pindex->nVersion >> m_bit) & 1) != 0 &&
2401-
((m_chainman.m_versionbitscache.ComputeBlockVersion(pindex->pprev, m_chainman.GetConsensus()) >> m_bit) & 1) == 0;
2402-
}
2403-
};
2404-
24052367
static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman)
24062368
{
24072369
const Consensus::Params& consensusparams = chainman.GetConsensus();
@@ -3038,17 +3000,13 @@ void Chainstate::UpdateTip(const CBlockIndex* pindexNew)
30383000

30393001
std::vector<bilingual_str> warning_messages;
30403002
if (!m_chainman.IsInitialBlockDownload()) {
3041-
const CBlockIndex* pindex = pindexNew;
3042-
for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) {
3043-
WarningBitsConditionChecker checker(m_chainman, bit);
3044-
ThresholdState state = checker.GetStateFor(pindex, m_chainman.m_warningcache.at(bit));
3045-
if (state == ThresholdState::ACTIVE || state == ThresholdState::LOCKED_IN) {
3046-
const bilingual_str warning = strprintf(_("Unknown new rules activated (versionbit %i)"), bit);
3047-
if (state == ThresholdState::ACTIVE) {
3048-
m_chainman.GetNotifications().warningSet(kernel::Warning::UNKNOWN_NEW_RULES_ACTIVATED, warning);
3049-
} else {
3050-
warning_messages.push_back(warning);
3051-
}
3003+
auto bits = m_chainman.m_versionbitscache.CheckUnknownActivations(pindexNew, m_chainman.GetParams());
3004+
for (auto [bit, active] : bits) {
3005+
const bilingual_str warning = strprintf(_("Unknown new rules activated (versionbit %i)"), bit);
3006+
if (active) {
3007+
m_chainman.GetNotifications().warningSet(kernel::Warning::UNKNOWN_NEW_RULES_ACTIVATED, warning);
3008+
} else {
3009+
warning_messages.push_back(warning);
30523010
}
30533011
}
30543012
}

src/validation.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -935,8 +935,6 @@ class ChainstateManager
935935
/** Most recent headers presync progress update, for rate-limiting. */
936936
std::chrono::time_point<std::chrono::steady_clock> m_last_presync_update GUARDED_BY(::cs_main) {};
937937

938-
std::array<ThresholdConditionCache, VERSIONBITS_NUM_BITS> m_warningcache GUARDED_BY(::cs_main);
939-
940938
//! Return true if a chainstate is considered usable.
941939
//!
942940
//! This is false when a background validation chainstate has completed its

src/versionbits.cpp

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
#include <consensus/params.h>
6+
#include <kernel/chainparams.h>
67
#include <util/check.h>
78
#include <versionbits.h>
89

10+
using enum ThresholdState;
11+
912
ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, ThresholdConditionCache& cache) const
1013
{
1114
int nPeriod = Period();
@@ -224,26 +227,84 @@ uint32_t VersionBitsCache::Mask(const Consensus::Params& params, Consensus::Depl
224227
return VersionBitsConditionChecker(params, pos).Mask();
225228
}
226229

227-
int32_t VersionBitsCache::ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params)
230+
static int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params, std::array<ThresholdConditionCache, Consensus::MAX_VERSION_BITS_DEPLOYMENTS>& caches)
228231
{
229-
LOCK(m_mutex);
230232
int32_t nVersion = VERSIONBITS_TOP_BITS;
231233

232234
for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
233235
Consensus::DeploymentPos pos = static_cast<Consensus::DeploymentPos>(i);
234-
ThresholdState state = VersionBitsConditionChecker(params, pos).GetStateFor(pindexPrev, m_caches[pos]);
236+
VersionBitsConditionChecker checker(params, pos);
237+
ThresholdState state = checker.GetStateFor(pindexPrev, caches[pos]);
235238
if (state == ThresholdState::LOCKED_IN || state == ThresholdState::STARTED) {
236-
nVersion |= Mask(params, pos);
239+
nVersion |= checker.Mask();
237240
}
238241
}
239242

240243
return nVersion;
241244
}
242245

246+
int32_t VersionBitsCache::ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params)
247+
{
248+
LOCK(m_mutex);
249+
return ::ComputeBlockVersion(pindexPrev, params, m_caches);
250+
}
251+
243252
void VersionBitsCache::Clear()
244253
{
245254
LOCK(m_mutex);
246255
for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
247256
m_caches[d].clear();
248257
}
249258
}
259+
260+
namespace {
261+
/**
262+
* Threshold condition checker that triggers when unknown versionbits are seen on the network.
263+
*/
264+
class WarningBitsConditionChecker : public AbstractThresholdConditionChecker
265+
{
266+
private:
267+
const Consensus::Params& m_params;
268+
std::array<ThresholdConditionCache, Consensus::MAX_VERSION_BITS_DEPLOYMENTS>& m_caches;
269+
int m_bit;
270+
int period{2016};
271+
int threshold{1815}; // 90% threshold used in BIP 341
272+
273+
public:
274+
explicit WarningBitsConditionChecker(const CChainParams& chainparams, std::array<ThresholdConditionCache, Consensus::MAX_VERSION_BITS_DEPLOYMENTS>& caches, int bit)
275+
: m_params{chainparams.GetConsensus()}, m_caches{caches}, m_bit(bit)
276+
{
277+
if (chainparams.IsTestChain()) {
278+
period = chainparams.GetConsensus().DifficultyAdjustmentInterval();
279+
threshold = period * 3 / 4; // 75% for test nets per BIP9 suggestion
280+
}
281+
}
282+
283+
int64_t BeginTime() const override { return 0; }
284+
int64_t EndTime() const override { return std::numeric_limits<int64_t>::max(); }
285+
int Period() const override { return period; }
286+
int Threshold() const override { return threshold; }
287+
288+
bool Condition(const CBlockIndex* pindex) const override
289+
{
290+
return pindex->nHeight >= m_params.MinBIP9WarningHeight &&
291+
((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) &&
292+
((pindex->nVersion >> m_bit) & 1) != 0 &&
293+
((::ComputeBlockVersion(pindex->pprev, m_params, m_caches) >> m_bit) & 1) == 0;
294+
}
295+
};
296+
} // anonymous namespace
297+
298+
std::vector<std::pair<int, bool>> VersionBitsCache::CheckUnknownActivations(const CBlockIndex* pindex, const CChainParams& chainparams)
299+
{
300+
LOCK(m_mutex);
301+
std::vector<std::pair<int, bool>> result;
302+
for (int bit = 0; bit < VERSIONBITS_NUM_BITS; ++bit) {
303+
WarningBitsConditionChecker checker(chainparams, m_caches, bit);
304+
ThresholdState state = checker.GetStateFor(pindex, m_warning_caches.at(bit));
305+
if (state == ACTIVE || state == LOCKED_IN) {
306+
result.emplace_back(bit, state == ACTIVE);
307+
}
308+
}
309+
return result;
310+
}

src/versionbits.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include <array>
1212
#include <map>
1313

14+
class CChainParams;
15+
1416
/** What block version to use for new blocks (pre versionbits) */
1517
static const int32_t VERSIONBITS_LAST_OLD_BLOCK_VERSION = 4;
1618
/** What bits to set in version for versionbits blocks */
@@ -82,6 +84,7 @@ class VersionBitsCache
8284
{
8385
private:
8486
Mutex m_mutex;
87+
std::array<ThresholdConditionCache,VERSIONBITS_NUM_BITS> m_warning_caches GUARDED_BY(m_mutex);
8588
std::array<ThresholdConditionCache,Consensus::MAX_VERSION_BITS_DEPLOYMENTS> m_caches GUARDED_BY(m_mutex);
8689

8790
public:
@@ -102,6 +105,11 @@ class VersionBitsCache
102105
*/
103106
int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
104107

108+
/** Check for unknown activations
109+
* Returns a vector containing the bit number used for signalling and a bool
110+
* indicating the deployment is likely to be ACTIVE, rather than merely LOCKED_IN. */
111+
std::vector<std::pair<int,bool>> CheckUnknownActivations(const CBlockIndex* pindex, const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
112+
105113
void Clear() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
106114
};
107115

0 commit comments

Comments
 (0)