|
3 | 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
4 | 4 |
|
5 | 5 | #include <consensus/params.h>
|
| 6 | +#include <kernel/chainparams.h> |
6 | 7 | #include <util/check.h>
|
7 | 8 | #include <versionbits.h>
|
8 | 9 |
|
| 10 | +using enum ThresholdState; |
| 11 | + |
9 | 12 | ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, ThresholdConditionCache& cache) const
|
10 | 13 | {
|
11 | 14 | int nPeriod = Period();
|
@@ -224,26 +227,84 @@ uint32_t VersionBitsCache::Mask(const Consensus::Params& params, Consensus::Depl
|
224 | 227 | return VersionBitsConditionChecker(params, pos).Mask();
|
225 | 228 | }
|
226 | 229 |
|
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) |
228 | 231 | {
|
229 |
| - LOCK(m_mutex); |
230 | 232 | int32_t nVersion = VERSIONBITS_TOP_BITS;
|
231 | 233 |
|
232 | 234 | for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
|
233 | 235 | 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]); |
235 | 238 | if (state == ThresholdState::LOCKED_IN || state == ThresholdState::STARTED) {
|
236 |
| - nVersion |= Mask(params, pos); |
| 239 | + nVersion |= checker.Mask(); |
237 | 240 | }
|
238 | 241 | }
|
239 | 242 |
|
240 | 243 | return nVersion;
|
241 | 244 | }
|
242 | 245 |
|
| 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 | + |
243 | 252 | void VersionBitsCache::Clear()
|
244 | 253 | {
|
245 | 254 | LOCK(m_mutex);
|
246 | 255 | for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
|
247 | 256 | m_caches[d].clear();
|
248 | 257 | }
|
249 | 258 | }
|
| 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 | +} |
0 commit comments