1 // Copyright (c) 2016-2022 The Limenka developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 5 #ifndef LIMENKA_VERSIONBITS_H
6 #define LIMENKA_VERSIONBITS_H
7 8 #include <chain.h>
9 #include <sync.h>
10 11 #include <map>
12 13 /** What block version to use for new blocks (pre versionbits) */
14 static const int32_t VERSIONBITS_LAST_OLD_BLOCK_VERSION = 4;
15 /** What bits to set in version for versionbits blocks */
16 static const int32_t VERSIONBITS_TOP_BITS = 0x20000000UL;
17 /** What bitmask determines whether versionbits is in use */
18 static const int32_t VERSIONBITS_TOP_MASK = 0xE0000000UL;
19 /** Total bits available for versionbits */
20 static const int32_t VERSIONBITS_NUM_BITS = 29;
21 22 /** BIP 9 defines a finite-state-machine to deploy a softfork in multiple stages.
23 * State transitions happen during retarget period if conditions are met
24 * In case of reorg, transitions can go backward. Without transition, state is
25 * inherited between periods. All blocks of a period share the same state.
26 */
27 enum class ThresholdState {
28 DEFINED, // First state that each softfork starts out as. The genesis block is by definition in this state for each deployment.
29 STARTED, // For blocks past the starttime.
30 LOCKED_IN, // For at least one retarget period after the first retarget period with STARTED blocks of which at least threshold have the associated bit set in nVersion, until min_activation_height is reached.
31 ACTIVE, // For all blocks after the LOCKED_IN retarget period (final state for permanent deployments)
32 FAILED, // For all blocks once the first retarget period after the timeout time is hit, if LOCKED_IN wasn't already reached (final state)
33 EXPIRED, // For temporary deployments: all blocks after active_duration periods past activation (final state)
34 };
35 36 // A map that gives the state for blocks whose height is a multiple of Period().
37 // The map is indexed by the block's parent, however, so all keys in the map
38 // will either be nullptr or a block with (height + 1) % Period() == 0.
39 typedef std::map<const CBlockIndex*, ThresholdState> ThresholdConditionCache;
40 41 /** Display status of an in-progress BIP9 softfork */
42 struct BIP9Stats {
43 /** Length of blocks of the BIP9 signalling period */
44 int period;
45 /** Number of blocks with the version bit set required to activate the softfork */
46 int threshold;
47 /** Number of blocks elapsed since the beginning of the current period */
48 int elapsed;
49 /** Number of blocks with the version bit set since the beginning of the current period */
50 int count;
51 /** False if there are not enough blocks left in this period to pass activation threshold */
52 bool possible;
53 };
54 55 /**
56 * Abstract class that implements BIP9-style threshold logic, and caches results.
57 */
58 class AbstractThresholdConditionChecker {
59 protected:
60 virtual bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const =0;
61 virtual int64_t BeginTime(const Consensus::Params& params) const =0;
62 virtual int64_t EndTime(const Consensus::Params& params) const =0;
63 virtual int MinActivationHeight(const Consensus::Params& params) const { return 0; }
64 virtual int MaxActivationHeight(const Consensus::Params& params) const { return std::numeric_limits<int>::max(); }
65 virtual int ActiveDuration(const Consensus::Params& params) const { return std::numeric_limits<int>::max(); }
66 virtual int Period(const Consensus::Params& params) const =0;
67 virtual int Threshold(const Consensus::Params& params) const =0;
68 69 public:
70 /** Returns the numerical statistics of an in-progress BIP9 softfork in the period including pindex
71 * If provided, signalling_blocks is set to true/false based on whether each block in the period signalled
72 */
73 BIP9Stats GetStateStatisticsFor(const CBlockIndex* pindex, const Consensus::Params& params, std::vector<bool>* signalling_blocks = nullptr) const;
74 /** Returns the state for pindex A based on parent pindexPrev B. Applies any state transition if conditions are present.
75 * Caches state from first block of period. */
76 ThresholdState GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const;
77 /** Returns the height since when the ThresholdState has started for pindex A based on parent pindexPrev B, all blocks of a period share the same */
78 int GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const;
79 };
80 81 /** BIP 9 allows multiple softforks to be deployed in parallel. We cache
82 * per-period state for every one of them. */
83 class VersionBitsCache
84 {
85 private:
86 Mutex m_mutex;
87 ThresholdConditionCache m_caches[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] GUARDED_BY(m_mutex);
88 89 public:
90 /** Get the numerical statistics for a given deployment for the signalling period that includes pindex.
91 * If provided, signalling_blocks is set to true/false based on whether each block in the period signalled
92 */
93 static BIP9Stats Statistics(const CBlockIndex* pindex, const Consensus::Params& params, Consensus::DeploymentPos pos, std::vector<bool>* signalling_blocks = nullptr);
94 95 static uint32_t Mask(const Consensus::Params& params, Consensus::DeploymentPos pos);
96 97 /** Get the BIP9 state for a given deployment for the block after pindexPrev. */
98 ThresholdState State(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
99 100 /** Get the block height at which the BIP9 deployment switched into the state for the block after pindexPrev. */
101 int StateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
102 103 /** Determine what nVersion a new block should use
104 */
105 int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
106 107 void Clear() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
108 };
109 110 #endif // LIMENKA_VERSIONBITS_H
111