DIP0001 implementation (#1594)

* DIP0001 implementation

* add option in ComputeBlockVersion to assume that masternode is upgraded (and skip rank calculation)

* fix mainnet DIP0001 nTimeout

* schedule DIP0001 testnet activation start for Sep 18th, 2017 (bump timeout too)
This commit is contained in:
UdjinM6 2017-09-11 17:13:30 +03:00 committed by GitHub
parent 91d99fcd3f
commit cd262bf641
14 changed files with 124 additions and 30 deletions

View File

@ -107,6 +107,13 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1486252800; // Feb 5th, 2017
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1517788800; // Feb 5th, 2018
// Deployment of DIP0001
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].bit = 1;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nStartTime = 1508025600; // Oct 15th, 2017
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nTimeout = 1539561600; // Oct 15th, 2018
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nWindowSize = 4032;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nThreshold = 3226; // 80% of 4032
// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000006acd76c0e55d52910"); // 721000
@ -238,6 +245,13 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1456790400; // March 1st, 2016
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017
// Deployment of DIP0001
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].bit = 1;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nStartTime = 1505692800; // Sep 18th, 2017
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nTimeout = 1537228800; // Sep 18th, 2018
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nWindowSize = 100;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nThreshold = 50; // 50% of 100
// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000000000003c26a58a13731"); //251000
@ -349,6 +363,9 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 999999999999ULL;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].bit = 1;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nStartTime = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nTimeout = 999999999999ULL;
// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x00");

View File

@ -7,9 +7,18 @@
#define BITCOIN_CONSENSUS_CONSENSUS_H
/** The maximum allowed size for a serialized block, in bytes (network rule) */
static const unsigned int MAX_BLOCK_SIZE = 1000000;
// static const unsigned int MAX_BLOCK_SIZE = 1000000;
static const unsigned int MAX_LEGACY_BLOCK_SIZE = (1 * 1000 * 1000);
inline unsigned int MaxBlockSize(bool fDIP0001Active /*= false */)
{
return fDIP0001Active ? MAX_LEGACY_BLOCK_SIZE * 2 : MAX_LEGACY_BLOCK_SIZE;
}
/** The maximum allowed number of signature check operations in a block (network rule) */
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
// static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
inline unsigned int MaxBlockSigOps(bool fDIP0001Active /*= false */)
{
return MaxBlockSize(fDIP0001Active) / 50;
}
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
static const int COINBASE_MATURITY = 100;

View File

@ -16,6 +16,7 @@ enum DeploymentPos
{
DEPLOYMENT_TESTDUMMY,
DEPLOYMENT_CSV, // Deployment of BIP68, BIP112, and BIP113.
DEPLOYMENT_DIP0001, // Deployment of DIP0001 and lower transaction fees.
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in versionbits.cpp
MAX_VERSION_BITS_DEPLOYMENTS
};
@ -30,6 +31,10 @@ struct BIP9Deployment {
int64_t nStartTime;
/** Timeout/expiry MedianTime for the deployment attempt. */
int64_t nTimeout;
/** The number of past blocks (including the block under consideration) to be taken into account for locking in a fork. */
int64_t nWindowSize;
/** A number of blocks, in the range of 1..nWindowSize, which must signal for a fork in order to lock it in. */
int64_t nThreshold;
};
/**
@ -59,11 +64,13 @@ struct Params {
int BIP34Height;
uint256 BIP34Hash;
/**
* Minimum blocks including miner confirmation of the total of 2016 blocks in a retargetting period,
* Minimum blocks including miner confirmation of the total of nMinerConfirmationWindow blocks in a retargetting period,
* (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments.
* Default BIP9Deployment::nThreshold value for deployments where it's not specified and for unknown deployments.
* Examples: 1916 for 95%, 1512 for testchains.
*/
uint32_t nRuleChangeActivationThreshold;
// Default BIP9Deployment::nWindowSize value for deployments where it's not specified and for unknown deployments.
uint32_t nMinerConfirmationWindow;
BIP9Deployment vDeployments[MAX_VERSION_BITS_DEPLOYMENTS];
/** Proof of work parameters */

View File

@ -200,7 +200,7 @@ static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput)
uint256 txid(uint256S(strTxid));
static const unsigned int minTxOutSz = 9;
static const unsigned int maxVout = MAX_BLOCK_SIZE / minTxOutSz;
static const unsigned int maxVout = MaxBlockSize(true) / minTxOutSz;
// extract and validate vout
string strVout = strInput.substr(pos + 1, string::npos);

View File

@ -153,7 +153,7 @@ uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch) {
if (nTransactions == 0)
return uint256();
// check for excessively high numbers of transactions
if (nTransactions > MAX_BLOCK_SIZE / 60) // 60 is the lower bound for the size of a serialized CTransaction
if (nTransactions > MaxBlockSize(true) / 60) // 60 is the lower bound for the size of a serialized CTransaction
return uint256();
// there can never be more hashes provided than one for every txid
if (vHash.size() > nTransactions)

View File

@ -92,7 +92,7 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s
// Largest block you're willing to create:
unsigned int nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
// Limit to between 1K and MAX_BLOCK_SIZE-1K for sanity:
nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MaxBlockSize(fDIP0001ActiveAtTip)-1000), nBlockMaxSize));
// How much of the block should be dedicated to high-priority transactions,
// included regardless of the fees they pay
@ -231,8 +231,9 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s
continue;
unsigned int nTxSigOps = iter->GetSigOpCount();
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) {
if (nBlockSigOps > MAX_BLOCK_SIGOPS - 2) {
unsigned int nMaxBlockSigOps = MaxBlockSigOps(fDIP0001ActiveAtTip);
if (nBlockSigOps + nTxSigOps >= nMaxBlockSigOps) {
if (nBlockSigOps > nMaxBlockSigOps - 2) {
break;
}
continue;

View File

@ -2557,7 +2557,7 @@ void CConnman::RecordBytesSent(uint64_t bytes)
void CConnman::SetMaxOutboundTarget(uint64_t limit)
{
LOCK(cs_totalBytesSent);
uint64_t recommendedMinimum = (nMaxOutboundTimeframe / 600) * MAX_BLOCK_SIZE;
uint64_t recommendedMinimum = (nMaxOutboundTimeframe / 600) * MaxBlockSize(fDIP0001ActiveAtTip);
nMaxOutboundLimit = limit;
if (limit > 0 && limit < recommendedMinimum)
@ -2612,7 +2612,7 @@ bool CConnman::OutboundTargetReached(bool historicalBlockServingLimit)
{
// keep a large enough buffer to at least relay each block once
uint64_t timeLeftInCycle = GetMaxOutboundTimeLeftInCycle();
uint64_t buffer = timeLeftInCycle / 600 * MAX_BLOCK_SIZE;
uint64_t buffer = timeLeftInCycle / 600 * MaxBlockSize(fDIP0001ActiveAtTip);
if (buffer >= nMaxOutboundLimit || nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer)
return true;
}

View File

@ -24,7 +24,7 @@ static const unsigned int MAX_STANDARD_TX_SIZE = 100000;
/** Maximum number of signature check operations in an IsStandard() P2SH script */
static const unsigned int MAX_P2SH_SIGOPS = 15;
/** The maximum number of sigops we're willing to relay/mine in a single tx */
static const unsigned int MAX_STANDARD_TX_SIGOPS = MAX_BLOCK_SIGOPS/5;
static const unsigned int MAX_STANDARD_TX_SIGOPS = 4000;
/** Default for -maxmempool, maximum megabytes of mempool memory usage */
static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300;
/**

View File

@ -804,6 +804,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
bip9_softforks.push_back(BIP9SoftForkDesc("csv", consensusParams, Consensus::DEPLOYMENT_CSV));
bip9_softforks.push_back(BIP9SoftForkDesc("dip0001", consensusParams, Consensus::DEPLOYMENT_DIP0001));
obj.push_back(Pair("softforks", softforks));
obj.push_back(Pair("bip9_softforks", bip9_softforks));

View File

@ -695,8 +695,8 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
result.push_back(Pair("mutable", aMutable));
result.push_back(Pair("noncerange", "00000000ffffffff"));
result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS));
result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE));
result.push_back(Pair("sigoplimit", (int64_t)MaxBlockSigOps(fDIP0001ActiveAtTip)));
result.push_back(Pair("sizelimit", (int64_t)MaxBlockSize(fDIP0001ActiveAtTip)));
result.push_back(Pair("curtime", pblock->GetBlockTime()));
result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));

View File

@ -37,6 +37,7 @@
#include "versionbits.h"
#include "instantx.h"
#include "masternodeman.h"
#include "masternode-payments.h"
#include <sstream>
@ -471,7 +472,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
if (tx.vout.empty())
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty");
// Size limits
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_LEGACY_BLOCK_SIZE)
return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize");
// Check for negative or overflow output values
@ -511,6 +512,17 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
return true;
}
bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state, CBlockIndex * const pindexPrev)
{
bool fDIP0001Active_context = (VersionBitsState(pindexPrev, Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0001, versionbitscache) == THRESHOLD_ACTIVE);
// Size limits
if (fDIP0001Active_context && ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_STANDARD_TX_SIZE)
return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize");
return true;
}
void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) {
int expired = pool.Expire(GetTime() - age);
if (expired != 0)
@ -539,7 +551,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
if (pfMissingInputs)
*pfMissingInputs = false;
if (!CheckTransaction(tx, state))
if (!CheckTransaction(tx, state) || !ContextualCheckTransaction(tx, state, chainActive.Tip()))
return false;
// Coinbase is only valid in a block, not as a loose transaction
@ -1860,13 +1872,23 @@ void ThreadScriptCheck() {
// Protected by cs_main
VersionBitsCache versionbitscache;
int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params)
int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params, bool fAssumeMasternodeIsUpgraded)
{
LOCK(cs_main);
int32_t nVersion = VERSIONBITS_TOP_BITS;
for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
ThresholdState state = VersionBitsState(pindexPrev, params, (Consensus::DeploymentPos)i, versionbitscache);
Consensus::DeploymentPos pos = Consensus::DeploymentPos(i);
ThresholdState state = VersionBitsState(pindexPrev, params, pos, versionbitscache);
const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
if (vbinfo.check_mn_protocol && state == THRESHOLD_STARTED && !fAssumeMasternodeIsUpgraded) {
masternode_info_t mnInfo;
bool fFound = mnodeman.GetMasternodeByRank(1, pindexPrev->nHeight, 0, false, mnInfo);
if (!fFound || mnInfo.nProtocolVersion < PROTOCOL_VERSION) {
// no masternodes(?) or masternode is not upgraded yet
continue;
}
}
if (state == THRESHOLD_LOCKED_IN || state == THRESHOLD_STARTED) {
nVersion |= VersionBitsMask(params, (Consensus::DeploymentPos)i);
}
@ -2051,6 +2073,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > addressUnspentIndex;
std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> > spentIndex;
bool fDIP0001Active_context = (VersionBitsState(pindex->pprev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_DIP0001, versionbitscache) == THRESHOLD_ACTIVE);
for (unsigned int i = 0; i < block.vtx.size(); i++)
{
const CTransaction &tx = block.vtx[i];
@ -2058,7 +2082,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
nInputs += tx.vin.size();
nSigOps += GetLegacySigOpCount(tx);
if (nSigOps > MAX_BLOCK_SIGOPS)
if (nSigOps > MaxBlockSigOps(fDIP0001Active_context))
return state.DoS(100, error("ConnectBlock(): too many sigops"),
REJECT_INVALID, "bad-blk-sigops");
@ -2124,7 +2148,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
// this is to prevent a "rogue miner" from creating
// an incredibly-expensive-to-validate block.
nSigOps += GetP2SHSigOpCount(tx, view);
if (nSigOps > MAX_BLOCK_SIGOPS)
if (nSigOps > MaxBlockSigOps(fDIP0001Active_context))
return state.DoS(100, error("ConnectBlock(): too many sigops"),
REJECT_INVALID, "bad-blk-sigops");
}
@ -2419,7 +2443,7 @@ void static UpdateTip(CBlockIndex *pindexNew) {
}
for (int i = 0; i < 100 && pindex != NULL; i++)
{
int32_t nExpectedVersion = ComputeBlockVersion(pindex->pprev, chainParams.GetConsensus());
int32_t nExpectedVersion = ComputeBlockVersion(pindex->pprev, chainParams.GetConsensus(), true);
if (pindex->nVersion > VERSIONBITS_LAST_OLD_BLOCK_VERSION && (pindex->nVersion & ~nExpectedVersion) != 0)
++nUpgraded;
pindex = pindex->pprev;
@ -2436,6 +2460,9 @@ void static UpdateTip(CBlockIndex *pindexNew) {
}
}
}
// Update global flag
fDIP0001ActiveAtTip = (VersionBitsTipState(chainParams.GetConsensus(), Consensus::DEPLOYMENT_DIP0001) == THRESHOLD_ACTIVE);
}
/** Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and manually re-limit mempool size after this, with cs_main held. */
@ -3113,9 +3140,9 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
// transaction validation, as otherwise we may mark the header as invalid
// because we receive the wrong transactions for it.
// Size limits
if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
return state.DoS(100, error("CheckBlock(): size limits failed"),
// Size limits (relaxed)
if (block.vtx.empty() || block.vtx.size() > MaxBlockSize(true) || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MaxBlockSize(true))
return state.DoS(100, error("%s: size limits failed", __func__),
REJECT_INVALID, "bad-blk-length");
// First transaction must be coinbase, the rest must not be
@ -3172,7 +3199,8 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
{
nSigOps += GetLegacySigOpCount(tx);
}
if (nSigOps > MAX_BLOCK_SIGOPS)
// sigops limits (relaxed)
if (nSigOps > MaxBlockSigOps(true))
return state.DoS(100, error("CheckBlock(): out-of-bounds SigOpCount"),
REJECT_INVALID, "bad-blk-sigops");
@ -3254,13 +3282,32 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
? pindexPrev->GetMedianTimePast()
: block.GetBlockTime();
// Check that all transactions are finalized
bool fDIP0001Active_context = (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_DIP0001, versionbitscache) == THRESHOLD_ACTIVE);
// Size limits
unsigned int nMaxBlockSize = MaxBlockSize(fDIP0001Active_context);
if (block.vtx.empty() || block.vtx.size() > nMaxBlockSize || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > nMaxBlockSize)
return state.DoS(100, error("%s: size limits failed", __func__),
REJECT_INVALID, "bad-blk-length");
// Check that all transactions are finalized and not over-sized
// Also count sigops
unsigned int nSigOps = 0;
BOOST_FOREACH(const CTransaction& tx, block.vtx) {
if (!IsFinalTx(tx, nHeight, nLockTimeCutoff)) {
return state.DoS(10, error("%s: contains a non-final transaction", __func__), REJECT_INVALID, "bad-txns-nonfinal");
}
if (fDIP0001Active_context && ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_STANDARD_TX_SIZE) {
return state.DoS(100, error("%s: contains an over-sized transaction", __func__), REJECT_INVALID, "bad-txns-oversized");
}
nSigOps += GetLegacySigOpCount(tx);
}
// Check sigops
if (nSigOps > MaxBlockSigOps(fDIP0001Active_context))
return state.DoS(100, error("%s: out-of-bounds SigOpCount", __func__),
REJECT_INVALID, "bad-blk-sigops");
// Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
// if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet):
if (block.nVersion >= 2 && IsSuperMajority(2, pindexPrev, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams))
@ -3961,8 +4008,9 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB
int nLoaded = 0;
try {
unsigned int nMaxBlockSize = MaxBlockSize(true);
// This takes over fileIn and calls fclose() on it in the CBufferedFile destructor
CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION);
CBufferedFile blkdat(fileIn, 2*nMaxBlockSize, nMaxBlockSize+8, SER_DISK, CLIENT_VERSION);
uint64_t nRewind = blkdat.GetPos();
while (!blkdat.eof()) {
boost::this_thread::interruption_point();
@ -3981,7 +4029,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB
continue;
// read size
blkdat >> nSize;
if (nSize < 80 || nSize > MAX_BLOCK_SIZE)
if (nSize < 80 || nSize > nMaxBlockSize)
continue;
} catch (const std::exception&) {
// no valid block header found; don't complain

View File

@ -47,6 +47,8 @@ class CValidationState;
struct LockPoints;
static std::atomic<bool> fDIP0001ActiveAtTip{false};
/** Default for accepting alerts from the P2P network. */
static const bool DEFAULT_ALERTS = true;
/** Default for DEFAULT_WHITELISTRELAY. */
@ -839,7 +841,7 @@ extern VersionBitsCache versionbitscache;
/**
* Determine what nVersion a new block should use.
*/
int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params);
int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params, bool fAssumeMasternodeIsUpgraded = false);
/**
* Return true if hash can be found in chainActive at nBlockHeight height.

View File

@ -10,10 +10,17 @@ const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION
{
/*.name =*/ "testdummy",
/*.gbt_force =*/ true,
/*.check_mn_protocol =*/ false,
},
{
/*.name =*/ "csv",
/*.gbt_force =*/ true,
/*.check_mn_protocol =*/ false,
},
{
/*.name =*/ "dip0001",
/*.gbt_force =*/ true,
/*.check_mn_protocol =*/ true,
}
};
@ -113,8 +120,8 @@ private:
protected:
int64_t BeginTime(const Consensus::Params& params) const { return params.vDeployments[id].nStartTime; }
int64_t EndTime(const Consensus::Params& params) const { return params.vDeployments[id].nTimeout; }
int Period(const Consensus::Params& params) const { return params.nMinerConfirmationWindow; }
int Threshold(const Consensus::Params& params) const { return params.nRuleChangeActivationThreshold; }
int Period(const Consensus::Params& params) const { return params.vDeployments[id].nWindowSize ? params.vDeployments[id].nWindowSize : params.nMinerConfirmationWindow; }
int Threshold(const Consensus::Params& params) const { return params.vDeployments[id].nThreshold ? params.vDeployments[id].nThreshold : params.nRuleChangeActivationThreshold; }
bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const
{

View File

@ -35,6 +35,8 @@ struct BIP9DeploymentInfo {
const char *name;
/** Whether GBT clients can safely ignore this rule in simplified usage */
bool gbt_force;
/** Whether to check current MN protocol or not */
bool check_mn_protocol;
};
extern const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[];