Skip to content

Commit 2b0d291

Browse files
committed
[refactor] Add deploymentstatus.h
Provides DeploymentEnabled, DeploymentActiveAt, and DeploymentActiveAfter helpers for checking the status of buried deployments. Can be overloaded so the same syntax works for non-buried deployments, allowing future soft forks to be changed from signalled to buried deployments without having to touch the implementation code. Replaces IsWitnessEnabled and IsScriptWitnessEnabled.
1 parent eccd736 commit 2b0d291

9 files changed

+101
-53
lines changed

src/Makefile.am

+1
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ BITCOIN_CORE_H = \
145145
core_memusage.h \
146146
cuckoocache.h \
147147
dbwrapper.h \
148+
deploymentstatus.h \
148149
external_signer.h \
149150
flatfile.h \
150151
fs.h \

src/consensus/params.h

+29
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@
1111

1212
namespace Consensus {
1313

14+
enum BuriedDeployment : int16_t
15+
{
16+
// buried deployments get negative values to avoid overlap with DeploymentPos
17+
DEPLOYMENT_HEIGHTINCB = std::numeric_limits<int16_t>::min(),
18+
DEPLOYMENT_CLTV,
19+
DEPLOYMENT_DERSIG,
20+
DEPLOYMENT_CSV,
21+
DEPLOYMENT_SEGWIT,
22+
};
23+
constexpr bool ValidDeployment(BuriedDeployment dep) { return DEPLOYMENT_HEIGHTINCB <= dep && dep <= DEPLOYMENT_SEGWIT; }
24+
1425
enum DeploymentPos
1526
{
1627
DEPLOYMENT_TESTDUMMY,
@@ -100,7 +111,25 @@ struct Params {
100111
*/
101112
bool signet_blocks{false};
102113
std::vector<uint8_t> signet_challenge;
114+
115+
int DeploymentHeight(BuriedDeployment dep) const
116+
{
117+
switch (dep) {
118+
case DEPLOYMENT_HEIGHTINCB:
119+
return BIP34Height;
120+
case DEPLOYMENT_CLTV:
121+
return BIP65Height;
122+
case DEPLOYMENT_DERSIG:
123+
return BIP66Height;
124+
case DEPLOYMENT_CSV:
125+
return CSVHeight;
126+
case DEPLOYMENT_SEGWIT:
127+
return SegwitHeight;
128+
} // no default case, so the compiler can warn about missing cases
129+
return std::numeric_limits<int>::max();
130+
}
103131
};
132+
104133
} // namespace Consensus
105134

106135
#endif // BITCOIN_CONSENSUS_PARAMS_H

src/deploymentstatus.h

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright (c) 2020 The Bitcoin Core 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 BITCOIN_DEPLOYMENTSTATUS_H
6+
#define BITCOIN_DEPLOYMENTSTATUS_H
7+
8+
#include <chain.h>
9+
10+
#include <limits>
11+
12+
/** Determine if a deployment is active for the next block */
13+
inline bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::BuriedDeployment dep)
14+
{
15+
assert(Consensus::ValidDeployment(dep));
16+
return (pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1) >= params.DeploymentHeight(dep);
17+
}
18+
19+
/** Determine if a deployment is active for this block */
20+
inline bool DeploymentActiveAt(const CBlockIndex& index, const Consensus::Params& params, Consensus::BuriedDeployment dep)
21+
{
22+
assert(Consensus::ValidDeployment(dep));
23+
return index.nHeight >= params.DeploymentHeight(dep);
24+
}
25+
26+
/** Determine if a deployment is enabled (can ever be active) */
27+
inline bool DeploymentEnabled(const Consensus::Params& params, Consensus::BuriedDeployment dep)
28+
{
29+
assert(Consensus::ValidDeployment(dep));
30+
return params.DeploymentHeight(dep) != std::numeric_limits<int>::max();
31+
}
32+
33+
#endif // BITCOIN_DEPLOYMENTSTATUS_H

src/init.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <chain.h>
1717
#include <chainparams.h>
1818
#include <compat/sanity.h>
19+
#include <deploymentstatus.h>
1920
#include <fs.h>
2021
#include <hash.h>
2122
#include <httprpc.h>
@@ -1587,7 +1588,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
15871588
}
15881589
}
15891590

1590-
if (chainparams.GetConsensus().SegwitHeight != std::numeric_limits<int>::max()) {
1591+
if (DeploymentEnabled(chainparams.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) {
15911592
// Advertise witness capabilities.
15921593
// The option to not set NODE_WITNESS is only used in the tests and should be removed.
15931594
nLocalServices = ServiceFlags(nLocalServices | NODE_WITNESS);

src/miner.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <consensus/merkle.h>
1414
#include <consensus/tx_verify.h>
1515
#include <consensus/validation.h>
16+
#include <deploymentstatus.h>
1617
#include <policy/feerate.h>
1718
#include <policy/policy.h>
1819
#include <pow.h>
@@ -137,12 +138,12 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
137138
// This is only needed in case the witness softfork activation is reverted
138139
// (which would require a very deep reorganization).
139140
// Note that the mempool would accept transactions with witness data before
140-
// IsWitnessEnabled, but we would only ever mine blocks after IsWitnessEnabled
141+
// the deployment is active, but we would only ever mine blocks after activation
141142
// unless there is a massive block reorganization with the witness softfork
142143
// not activated.
143144
// TODO: replace this with a call to main to assess validity of a mempool
144145
// transaction (which in most cases can be a no-op).
145-
fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus());
146+
fIncludeWitness = DeploymentActiveAfter(pindexPrev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT);
146147

147148
int nPackagesSelected = 0;
148149
int nDescendantsUpdated = 0;

src/net_processing.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <blockfilter.h>
1212
#include <chainparams.h>
1313
#include <consensus/validation.h>
14+
#include <deploymentstatus.h>
1415
#include <hash.h>
1516
#include <index/blockfilterindex.h>
1617
#include <merkleblock.h>
@@ -997,7 +998,7 @@ void PeerManagerImpl::FindNextBlocksToDownload(NodeId nodeid, unsigned int count
997998
// We consider the chain that this peer is on invalid.
998999
return;
9991000
}
1000-
if (!State(nodeid)->fHaveWitness && IsWitnessEnabled(pindex->pprev, consensusParams)) {
1001+
if (!State(nodeid)->fHaveWitness && DeploymentActiveAt(*pindex, consensusParams, Consensus::DEPLOYMENT_SEGWIT)) {
10011002
// We wouldn't download this block or its descendants from this peer.
10021003
return;
10031004
}
@@ -1467,7 +1468,7 @@ void PeerManagerImpl::NewPoWValidBlock(const CBlockIndex *pindex, const std::sha
14671468
return;
14681469
nHighestFastAnnounce = pindex->nHeight;
14691470

1470-
bool fWitnessEnabled = IsWitnessEnabled(pindex->pprev, m_chainparams.GetConsensus());
1471+
bool fWitnessEnabled = DeploymentActiveAt(*pindex, m_chainparams.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT);
14711472
uint256 hashBlock(pblock->GetHash());
14721473

14731474
{
@@ -2082,7 +2083,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
20822083
while (pindexWalk && !m_chainman.ActiveChain().Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
20832084
if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) &&
20842085
!IsBlockRequested(pindexWalk->GetBlockHash()) &&
2085-
(!IsWitnessEnabled(pindexWalk->pprev, m_chainparams.GetConsensus()) || State(pfrom.GetId())->fHaveWitness)) {
2086+
(!DeploymentActiveAt(*pindexWalk, m_chainparams.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT) || State(pfrom.GetId())->fHaveWitness)) {
20862087
// We don't have this block, and it's not yet in flight.
20872088
vToFetch.push_back(pindexWalk);
20882089
}
@@ -3397,7 +3398,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
33973398
return;
33983399
}
33993400

3400-
if (IsWitnessEnabled(pindex->pprev, m_chainparams.GetConsensus()) && !nodestate->fSupportsDesiredCmpctVersion) {
3401+
if (DeploymentActiveAt(*pindex, m_chainparams.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT) && !nodestate->fSupportsDesiredCmpctVersion) {
34013402
// Don't bother trying to process compact blocks from v1 peers
34023403
// after segwit activates.
34033404
return;

src/rpc/mining.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <consensus/params.h>
1111
#include <consensus/validation.h>
1212
#include <core_io.h>
13+
#include <deploymentstatus.h>
1314
#include <key_io.h>
1415
#include <miner.h>
1516
#include <net.h>
@@ -774,7 +775,7 @@ static RPCHelpMan getblocktemplate()
774775
pblock->nNonce = 0;
775776

776777
// NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration
777-
const bool fPreSegWit = (pindexPrev->nHeight + 1 < consensusParams.SegwitHeight);
778+
const bool fPreSegWit = !DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT);
778779

779780
UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
780781

src/validation.cpp

+26-41
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <consensus/tx_verify.h>
1616
#include <consensus/validation.h>
1717
#include <cuckoocache.h>
18+
#include <deploymentstatus.h>
1819
#include <flatfile.h>
1920
#include <hash.h>
2021
#include <index/blockfilterindex.h>
@@ -1649,15 +1650,6 @@ class WarningBitsConditionChecker : public AbstractThresholdConditionChecker
16491650

16501651
static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS] GUARDED_BY(cs_main);
16511652

1652-
// 0.13.0 was shipped with a segwit deployment defined for testnet, but not for
1653-
// mainnet. We no longer need to support disabling the segwit deployment
1654-
// except for testing purposes, due to limitations of the functional test
1655-
// environment. See test/functional/p2p-segwit.py.
1656-
static bool IsScriptWitnessEnabled(const Consensus::Params& params)
1657-
{
1658-
return params.SegwitHeight != std::numeric_limits<int>::max();
1659-
}
1660-
16611653
static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& consensusparams)
16621654
{
16631655
unsigned int flags = SCRIPT_VERIFY_NONE;
@@ -1676,22 +1668,22 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consens
16761668

16771669
// Enforce WITNESS rules whenever P2SH is in effect (and the segwit
16781670
// deployment is defined).
1679-
if (flags & SCRIPT_VERIFY_P2SH && IsScriptWitnessEnabled(consensusparams)) {
1671+
if (flags & SCRIPT_VERIFY_P2SH && DeploymentEnabled(consensusparams, Consensus::DEPLOYMENT_SEGWIT)) {
16801672
flags |= SCRIPT_VERIFY_WITNESS;
16811673
}
16821674

1683-
// Start enforcing the DERSIG (BIP66) rule
1684-
if (pindex->nHeight >= consensusparams.BIP66Height) {
1675+
// Enforce the DERSIG (BIP66) rule
1676+
if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_DERSIG)) {
16851677
flags |= SCRIPT_VERIFY_DERSIG;
16861678
}
16871679

1688-
// Start enforcing CHECKLOCKTIMEVERIFY (BIP65) rule
1689-
if (pindex->nHeight >= consensusparams.BIP65Height) {
1680+
// Enforce CHECKLOCKTIMEVERIFY (BIP65)
1681+
if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_CLTV)) {
16901682
flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
16911683
}
16921684

1693-
// Start enforcing BIP112 (CHECKSEQUENCEVERIFY)
1694-
if (pindex->nHeight >= consensusparams.CSVHeight) {
1685+
// Enforce CHECKSEQUENCEVERIFY (BIP112)
1686+
if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_CSV)) {
16951687
flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
16961688
}
16971689

@@ -1700,8 +1692,8 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consens
17001692
flags |= SCRIPT_VERIFY_TAPROOT;
17011693
}
17021694

1703-
// Start enforcing BIP147 NULLDUMMY (activated simultaneously with segwit)
1704-
if (IsWitnessEnabled(pindex->pprev, consensusparams)) {
1695+
// Enforce BIP147 NULLDUMMY (activated simultaneously with segwit)
1696+
if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_SEGWIT)) {
17051697
flags |= SCRIPT_VERIFY_NULLDUMMY;
17061698
}
17071699

@@ -1891,9 +1883,9 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
18911883
}
18921884
}
18931885

1894-
// Start enforcing BIP68 (sequence locks)
1886+
// Enforce BIP68 (sequence locks)
18951887
int nLockTimeFlags = 0;
1896-
if (pindex->nHeight >= m_params.GetConsensus().CSVHeight) {
1888+
if (DeploymentActiveAt(*pindex, m_params.GetConsensus(), Consensus::DEPLOYMENT_CSV)) {
18971889
nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE;
18981890
}
18991891

@@ -2986,7 +2978,7 @@ void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pi
29862978
pindexNew->nDataPos = pos.nPos;
29872979
pindexNew->nUndoPos = 0;
29882980
pindexNew->nStatus |= BLOCK_HAVE_DATA;
2989-
if (IsWitnessEnabled(pindexNew->pprev, m_params.GetConsensus())) {
2981+
if (DeploymentActiveAt(*pindexNew, m_params.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) {
29902982
pindexNew->nStatus |= BLOCK_OPT_WITNESS;
29912983
}
29922984
pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS);
@@ -3107,17 +3099,11 @@ bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensu
31073099
return true;
31083100
}
31093101

3110-
bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params)
3111-
{
3112-
int height = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1;
3113-
return (height >= params.SegwitHeight);
3114-
}
3115-
31163102
void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams)
31173103
{
31183104
int commitpos = GetWitnessCommitmentIndex(block);
31193105
static const std::vector<unsigned char> nonce(32, 0x00);
3120-
if (commitpos != NO_WITNESS_COMMITMENT && IsWitnessEnabled(pindexPrev, consensusParams) && !block.vtx[0]->HasWitness()) {
3106+
if (commitpos != NO_WITNESS_COMMITMENT && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT) && !block.vtx[0]->HasWitness()) {
31213107
CMutableTransaction tx(*block.vtx[0]);
31223108
tx.vin[0].scriptWitness.stack.resize(1);
31233109
tx.vin[0].scriptWitness.stack[0] = nonce;
@@ -3130,7 +3116,7 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
31303116
std::vector<unsigned char> commitment;
31313117
int commitpos = GetWitnessCommitmentIndex(block);
31323118
std::vector<unsigned char> ret(32, 0x00);
3133-
if (consensusParams.SegwitHeight != std::numeric_limits<int>::max()) {
3119+
if (DeploymentEnabled(consensusParams, Consensus::DEPLOYMENT_SEGWIT)) {
31343120
if (commitpos == NO_WITNESS_COMMITMENT) {
31353121
uint256 witnessroot = BlockWitnessMerkleRoot(block, nullptr);
31363122
CHash256().Write(witnessroot).Write(ret).Finalize(witnessroot);
@@ -3208,13 +3194,13 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio
32083194
if (block.GetBlockTime() > nAdjustedTime + MAX_FUTURE_BLOCK_TIME)
32093195
return state.Invalid(BlockValidationResult::BLOCK_TIME_FUTURE, "time-too-new", "block timestamp too far in the future");
32103196

3211-
// Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded:
3212-
// check for version 2, 3 and 4 upgrades
3213-
if((block.nVersion < 2 && nHeight >= consensusParams.BIP34Height) ||
3214-
(block.nVersion < 3 && nHeight >= consensusParams.BIP66Height) ||
3215-
(block.nVersion < 4 && nHeight >= consensusParams.BIP65Height))
3197+
// Reject blocks with outdated version
3198+
if ((block.nVersion < 2 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB)) ||
3199+
(block.nVersion < 3 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_DERSIG)) ||
3200+
(block.nVersion < 4 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CLTV))) {
32163201
return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, strprintf("bad-version(0x%08x)", block.nVersion),
32173202
strprintf("rejected nVersion=0x%08x block", block.nVersion));
3203+
}
32183204

32193205
return true;
32203206
}
@@ -3229,9 +3215,9 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
32293215
{
32303216
const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1;
32313217

3232-
// Start enforcing BIP113 (Median Time Past).
3218+
// Enforce BIP113 (Median Time Past).
32333219
int nLockTimeFlags = 0;
3234-
if (nHeight >= consensusParams.CSVHeight) {
3220+
if (DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CSV)) {
32353221
assert(pindexPrev != nullptr);
32363222
nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST;
32373223
}
@@ -3248,7 +3234,7 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
32483234
}
32493235

32503236
// Enforce rule that the coinbase starts with serialized block height
3251-
if (nHeight >= consensusParams.BIP34Height)
3237+
if (DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB))
32523238
{
32533239
CScript expect = CScript() << nHeight;
32543240
if (block.vtx[0]->vin[0].scriptSig.size() < expect.size() ||
@@ -3266,7 +3252,7 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
32663252
// {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness reserved value). In case there are
32673253
// multiple, the last one is used.
32683254
bool fHaveWitness = false;
3269-
if (nHeight >= consensusParams.SegwitHeight) {
3255+
if (DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT)) {
32703256
int commitpos = GetWitnessCommitmentIndex(block);
32713257
if (commitpos != NO_WITNESS_COMMITMENT) {
32723258
bool malleated = false;
@@ -4096,9 +4082,8 @@ bool CChainState::NeedsRedownload() const
40964082

40974083
// At and above m_params.SegwitHeight, segwit consensus rules must be validated
40984084
CBlockIndex* block{m_chain.Tip()};
4099-
const int segwit_height{m_params.GetConsensus().SegwitHeight};
41004085

4101-
while (block != nullptr && block->nHeight >= segwit_height) {
4086+
while (block != nullptr && DeploymentActiveAt(*block, m_params.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) {
41024087
if (!(block->nStatus & BLOCK_OPT_WITNESS)) {
41034088
// block is insufficiently validated for a segwit client
41044089
return true;
@@ -5000,7 +4985,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
50004985

50014986
// Fake BLOCK_OPT_WITNESS so that CChainState::NeedsRedownload()
50024987
// won't ask to rewind the entire assumed-valid chain on startup.
5003-
if (index->pprev && ::IsWitnessEnabled(index->pprev, ::Params().GetConsensus())) {
4988+
if (index->pprev && DeploymentActiveAt(*index, ::Params().GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) {
50044989
index->nStatus |= BLOCK_OPT_WITNESS;
50054990
}
50064991
}

src/validation.h

-4
Original file line numberDiff line numberDiff line change
@@ -345,10 +345,6 @@ bool TestBlockValidity(BlockValidationState& state,
345345
bool fCheckPOW = true,
346346
bool fCheckMerkleRoot = true) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
347347

348-
/** Check whether witness commitments are required for a block, and whether to enforce NULLDUMMY (BIP 147) rules.
349-
* Note that transaction witness validation rules are always enforced when P2SH is enforced. */
350-
bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params);
351-
352348
/** Update uncommitted block structures (currently: only the witness reserved value). This is safe for submitted blocks. */
353349
void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams);
354350

0 commit comments

Comments
 (0)