2016-02-15 05:13:27 +01:00
// 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.
2018-04-02 00:30:17 +02:00
# ifndef BITCOIN_VERSIONBITS_H
# define BITCOIN_VERSIONBITS_H
2016-02-15 05:13:27 +01:00
2020-03-19 23:46:56 +01:00
# include <chain.h>
2016-02-15 05:13:27 +01:00
# include <map>
/** What block version to use for new blocks (pre versionbits) */
static const int32_t VERSIONBITS_LAST_OLD_BLOCK_VERSION = 4 ;
/** What bits to set in version for versionbits blocks */
static const int32_t VERSIONBITS_TOP_BITS = 0x20000000UL ;
/** What bitmask determines whether versionbits is in use */
static const int32_t VERSIONBITS_TOP_MASK = 0xE0000000UL ;
/** Total bits available for versionbits */
static const int32_t VERSIONBITS_NUM_BITS = 29 ;
2019-08-16 04:51:16 +02:00
/** BIP 9 defines a finite-state-machine to deploy a softfork in multiple stages.
* State transitions happen during retarget period if conditions are met
* In case of reorg , transitions can go backward . Without transition , state is
* inherited between periods . All blocks of a period share the same state .
*/
2020-06-09 05:44:04 +02:00
enum class ThresholdState {
2019-08-16 04:51:16 +02:00
DEFINED , // First state that each softfork starts out as. The genesis block is by definition in this state for each deployment.
STARTED , // For blocks past the starttime.
LOCKED_IN , // For one retarget period after the first retarget period with STARTED blocks of which at least threshold have the associated bit set in nVersion.
ACTIVE , // For all blocks after the LOCKED_IN retarget period (final state)
FAILED , // For all blocks once the first retarget period after the timeout time is hit, if LOCKED_IN wasn't already reached (final state)
2016-02-15 05:13:27 +01:00
} ;
// 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
2019-08-06 05:08:33 +02:00
// will either be nullptr or a block with (height + 1) % Period() == 0.
2016-02-15 05:13:27 +01:00
typedef std : : map < const CBlockIndex * , ThresholdState > ThresholdConditionCache ;
2019-08-16 04:51:16 +02:00
/** Display status of an in-progress BIP9 softfork */
2017-05-23 19:07:29 +02:00
struct BIP9Stats {
2019-08-16 04:51:16 +02:00
/** Length of blocks of the BIP9 signalling period */
2017-05-23 19:07:29 +02:00
int period ;
2019-08-16 04:51:16 +02:00
/** Number of blocks with the version bit set required to activate the softfork */
2017-05-23 19:07:29 +02:00
int threshold ;
2019-08-16 04:51:16 +02:00
/** Number of blocks elapsed since the beginning of the current period */
2017-05-23 19:07:29 +02:00
int elapsed ;
2019-08-16 04:51:16 +02:00
/** Number of blocks with the version bit set since the beginning of the current period */
2017-05-23 19:07:29 +02:00
int count ;
2019-08-16 04:51:16 +02:00
/** False if there are not enough blocks left in this period to pass activation threshold */
2017-05-23 19:07:29 +02:00
bool possible ;
} ;
2016-02-15 05:13:27 +01:00
/**
* Abstract class that implements BIP9 - style threshold logic , and caches results .
*/
class AbstractThresholdConditionChecker {
protected :
virtual bool Condition ( const CBlockIndex * pindex , const Consensus : : Params & params ) const = 0 ;
virtual int64_t BeginTime ( const Consensus : : Params & params ) const = 0 ;
2023-11-10 15:31:12 +01:00
virtual int SignalHeight ( const CBlockIndex * pindexPrev , const Consensus : : Params & params ) const = 0 ;
2016-02-15 05:13:27 +01:00
virtual int64_t EndTime ( const Consensus : : Params & params ) const = 0 ;
virtual int Period ( const Consensus : : Params & params ) const = 0 ;
2020-09-12 16:33:12 +02:00
virtual int Threshold ( const Consensus : : Params & params , int nAttempt ) const = 0 ;
2016-02-15 05:13:27 +01:00
public :
2019-08-16 04:51:16 +02:00
/** Returns the numerical statistics of an in-progress BIP9 softfork in the current period */
2020-09-12 16:33:12 +02:00
BIP9Stats GetStateStatisticsFor ( const CBlockIndex * pindex , const Consensus : : Params & params , ThresholdConditionCache & cache ) const ;
2019-08-16 04:51:16 +02:00
/** Returns the state for pindex A based on parent pindexPrev B. Applies any state transition if conditions are present.
* Caches state from first block of period . */
2016-02-15 05:13:27 +01:00
ThresholdState GetStateFor ( const CBlockIndex * pindexPrev , const Consensus : : Params & params , ThresholdConditionCache & cache ) const ;
2019-08-16 04:51:16 +02:00
/** 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 */
2016-10-19 16:36:21 +02:00
int GetStateSinceHeightFor ( const CBlockIndex * pindexPrev , const Consensus : : Params & params , ThresholdConditionCache & cache ) const ;
2016-02-15 05:13:27 +01:00
} ;
2019-08-16 04:51:16 +02:00
/** BIP 9 allows multiple softforks to be deployed in parallel. We cache per-period state for every one of them
* keyed by the bit position used to signal support . */
2016-02-15 05:13:27 +01:00
struct VersionBitsCache
{
ThresholdConditionCache caches [ Consensus : : MAX_VERSION_BITS_DEPLOYMENTS ] ;
void Clear ( ) ;
} ;
2023-03-13 16:37:00 +01:00
/** Get the BIP9 state for a given deployment at the current tip. */
2016-02-15 05:13:27 +01:00
ThresholdState VersionBitsState ( const CBlockIndex * pindexPrev , const Consensus : : Params & params , Consensus : : DeploymentPos pos , VersionBitsCache & cache ) ;
2023-03-13 16:37:00 +01:00
/** Get the numerical statistics for the BIP9 state for a given deployment at the current tip. */
2020-09-12 16:33:12 +02:00
BIP9Stats VersionBitsStatistics ( const CBlockIndex * pindexPrev , const Consensus : : Params & params , Consensus : : DeploymentPos pos , VersionBitsCache & cache ) ;
2023-03-13 16:37:00 +01:00
/** Get the block height at which the BIP9 deployment switched into the state for the block building on the current tip. */
2016-10-19 16:36:21 +02:00
int VersionBitsStateSinceHeight ( const CBlockIndex * pindexPrev , const Consensus : : Params & params , Consensus : : DeploymentPos pos , VersionBitsCache & cache ) ;
2016-02-15 05:13:27 +01:00
uint32_t VersionBitsMask ( const Consensus : : Params & params , Consensus : : DeploymentPos pos ) ;
2023-11-10 15:31:12 +01:00
class AbstractEHFManager
{
public :
using Signals = std : : unordered_map < uint8_t , int > ;
/**
* getInstance ( ) is used in versionbit because it is non - trivial
* to get access to NodeContext from all usages of VersionBits * methods
* For simplification of interface this methods static / global variable is used
* to get access to EHF data
*/
public :
[ [ nodiscard ] ] static AbstractEHFManager * getInstance ( ) {
return globalInstance ;
} ;
/**
* ` GetSignalsStage ' prepares signals for new block .
* The results are diffent with GetFromCache results due to one more
* stage of processing : signals that would be expired in next block
* are excluded from results .
* This member function is not const because it calls non - const GetFromCache ( )
*/
virtual Signals GetSignalsStage ( const CBlockIndex * const pindexPrev ) = 0 ;
protected :
static AbstractEHFManager * globalInstance ;
} ;
2018-04-02 00:30:17 +02:00
# endif // BITCOIN_VERSIONBITS_H