aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Towns <aj@erisian.com.au>2020-06-16 18:58:56 +1000
committerAnthony Towns <aj@erisian.com.au>2021-06-29 17:11:12 +1000
commit2b0d291da8f479739ff394dd92801da8c40b9f8e (patch)
tree50968fbedda38d56cfd6fa5b1a7c2a3ee037ddab
parenteccd736f3dc231ac0306ca763c3b72cf8247230a (diff)
[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.
-rw-r--r--src/Makefile.am1
-rw-r--r--src/consensus/params.h29
-rw-r--r--src/deploymentstatus.h33
-rw-r--r--src/init.cpp3
-rw-r--r--src/miner.cpp5
-rw-r--r--src/net_processing.cpp9
-rw-r--r--src/rpc/mining.cpp3
-rw-r--r--src/validation.cpp67
-rw-r--r--src/validation.h4
9 files changed, 101 insertions, 53 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index e2ed70556d..a3248f3eab 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -145,6 +145,7 @@ BITCOIN_CORE_H = \
core_memusage.h \
cuckoocache.h \
dbwrapper.h \
+ deploymentstatus.h \
external_signer.h \
flatfile.h \
fs.h \
diff --git a/src/consensus/params.h b/src/consensus/params.h
index 28c95e0884..9b4139d76c 100644
--- a/src/consensus/params.h
+++ b/src/consensus/params.h
@@ -11,6 +11,17 @@
namespace Consensus {
+enum BuriedDeployment : int16_t
+{
+ // buried deployments get negative values to avoid overlap with DeploymentPos
+ DEPLOYMENT_HEIGHTINCB = std::numeric_limits<int16_t>::min(),
+ DEPLOYMENT_CLTV,
+ DEPLOYMENT_DERSIG,
+ DEPLOYMENT_CSV,
+ DEPLOYMENT_SEGWIT,
+};
+constexpr bool ValidDeployment(BuriedDeployment dep) { return DEPLOYMENT_HEIGHTINCB <= dep && dep <= DEPLOYMENT_SEGWIT; }
+
enum DeploymentPos
{
DEPLOYMENT_TESTDUMMY,
@@ -100,7 +111,25 @@ struct Params {
*/
bool signet_blocks{false};
std::vector<uint8_t> signet_challenge;
+
+ int DeploymentHeight(BuriedDeployment dep) const
+ {
+ switch (dep) {
+ case DEPLOYMENT_HEIGHTINCB:
+ return BIP34Height;
+ case DEPLOYMENT_CLTV:
+ return BIP65Height;
+ case DEPLOYMENT_DERSIG:
+ return BIP66Height;
+ case DEPLOYMENT_CSV:
+ return CSVHeight;
+ case DEPLOYMENT_SEGWIT:
+ return SegwitHeight;
+ } // no default case, so the compiler can warn about missing cases
+ return std::numeric_limits<int>::max();
+ }
};
+
} // namespace Consensus
#endif // BITCOIN_CONSENSUS_PARAMS_H
diff --git a/src/deploymentstatus.h b/src/deploymentstatus.h
new file mode 100644
index 0000000000..32190e369d
--- /dev/null
+++ b/src/deploymentstatus.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2020 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_DEPLOYMENTSTATUS_H
+#define BITCOIN_DEPLOYMENTSTATUS_H
+
+#include <chain.h>
+
+#include <limits>
+
+/** Determine if a deployment is active for the next block */
+inline bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::BuriedDeployment dep)
+{
+ assert(Consensus::ValidDeployment(dep));
+ return (pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1) >= params.DeploymentHeight(dep);
+}
+
+/** Determine if a deployment is active for this block */
+inline bool DeploymentActiveAt(const CBlockIndex& index, const Consensus::Params& params, Consensus::BuriedDeployment dep)
+{
+ assert(Consensus::ValidDeployment(dep));
+ return index.nHeight >= params.DeploymentHeight(dep);
+}
+
+/** Determine if a deployment is enabled (can ever be active) */
+inline bool DeploymentEnabled(const Consensus::Params& params, Consensus::BuriedDeployment dep)
+{
+ assert(Consensus::ValidDeployment(dep));
+ return params.DeploymentHeight(dep) != std::numeric_limits<int>::max();
+}
+
+#endif // BITCOIN_DEPLOYMENTSTATUS_H
diff --git a/src/init.cpp b/src/init.cpp
index a88adbaa21..ae96f510bc 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -16,6 +16,7 @@
#include <chain.h>
#include <chainparams.h>
#include <compat/sanity.h>
+#include <deploymentstatus.h>
#include <fs.h>
#include <hash.h>
#include <httprpc.h>
@@ -1587,7 +1588,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
}
}
- if (chainparams.GetConsensus().SegwitHeight != std::numeric_limits<int>::max()) {
+ if (DeploymentEnabled(chainparams.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) {
// Advertise witness capabilities.
// The option to not set NODE_WITNESS is only used in the tests and should be removed.
nLocalServices = ServiceFlags(nLocalServices | NODE_WITNESS);
diff --git a/src/miner.cpp b/src/miner.cpp
index 0cf303eb3c..c1a992b9e9 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -13,6 +13,7 @@
#include <consensus/merkle.h>
#include <consensus/tx_verify.h>
#include <consensus/validation.h>
+#include <deploymentstatus.h>
#include <policy/feerate.h>
#include <policy/policy.h>
#include <pow.h>
@@ -137,12 +138,12 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
// This is only needed in case the witness softfork activation is reverted
// (which would require a very deep reorganization).
// Note that the mempool would accept transactions with witness data before
- // IsWitnessEnabled, but we would only ever mine blocks after IsWitnessEnabled
+ // the deployment is active, but we would only ever mine blocks after activation
// unless there is a massive block reorganization with the witness softfork
// not activated.
// TODO: replace this with a call to main to assess validity of a mempool
// transaction (which in most cases can be a no-op).
- fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus());
+ fIncludeWitness = DeploymentActiveAfter(pindexPrev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT);
int nPackagesSelected = 0;
int nDescendantsUpdated = 0;
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index ab9c41ca2b..315d2ac5cd 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -11,6 +11,7 @@
#include <blockfilter.h>
#include <chainparams.h>
#include <consensus/validation.h>
+#include <deploymentstatus.h>
#include <hash.h>
#include <index/blockfilterindex.h>
#include <merkleblock.h>
@@ -997,7 +998,7 @@ void PeerManagerImpl::FindNextBlocksToDownload(NodeId nodeid, unsigned int count
// We consider the chain that this peer is on invalid.
return;
}
- if (!State(nodeid)->fHaveWitness && IsWitnessEnabled(pindex->pprev, consensusParams)) {
+ if (!State(nodeid)->fHaveWitness && DeploymentActiveAt(*pindex, consensusParams, Consensus::DEPLOYMENT_SEGWIT)) {
// We wouldn't download this block or its descendants from this peer.
return;
}
@@ -1467,7 +1468,7 @@ void PeerManagerImpl::NewPoWValidBlock(const CBlockIndex *pindex, const std::sha
return;
nHighestFastAnnounce = pindex->nHeight;
- bool fWitnessEnabled = IsWitnessEnabled(pindex->pprev, m_chainparams.GetConsensus());
+ bool fWitnessEnabled = DeploymentActiveAt(*pindex, m_chainparams.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT);
uint256 hashBlock(pblock->GetHash());
{
@@ -2082,7 +2083,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
while (pindexWalk && !m_chainman.ActiveChain().Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) &&
!IsBlockRequested(pindexWalk->GetBlockHash()) &&
- (!IsWitnessEnabled(pindexWalk->pprev, m_chainparams.GetConsensus()) || State(pfrom.GetId())->fHaveWitness)) {
+ (!DeploymentActiveAt(*pindexWalk, m_chainparams.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT) || State(pfrom.GetId())->fHaveWitness)) {
// We don't have this block, and it's not yet in flight.
vToFetch.push_back(pindexWalk);
}
@@ -3397,7 +3398,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
return;
}
- if (IsWitnessEnabled(pindex->pprev, m_chainparams.GetConsensus()) && !nodestate->fSupportsDesiredCmpctVersion) {
+ if (DeploymentActiveAt(*pindex, m_chainparams.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT) && !nodestate->fSupportsDesiredCmpctVersion) {
// Don't bother trying to process compact blocks from v1 peers
// after segwit activates.
return;
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 327f961196..f054c8b145 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -10,6 +10,7 @@
#include <consensus/params.h>
#include <consensus/validation.h>
#include <core_io.h>
+#include <deploymentstatus.h>
#include <key_io.h>
#include <miner.h>
#include <net.h>
@@ -774,7 +775,7 @@ static RPCHelpMan getblocktemplate()
pblock->nNonce = 0;
// NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration
- const bool fPreSegWit = (pindexPrev->nHeight + 1 < consensusParams.SegwitHeight);
+ const bool fPreSegWit = !DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT);
UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
diff --git a/src/validation.cpp b/src/validation.cpp
index 1b0f881d14..b69faa54eb 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -15,6 +15,7 @@
#include <consensus/tx_verify.h>
#include <consensus/validation.h>
#include <cuckoocache.h>
+#include <deploymentstatus.h>
#include <flatfile.h>
#include <hash.h>
#include <index/blockfilterindex.h>
@@ -1649,15 +1650,6 @@ public:
static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS] GUARDED_BY(cs_main);
-// 0.13.0 was shipped with a segwit deployment defined for testnet, but not for
-// mainnet. We no longer need to support disabling the segwit deployment
-// except for testing purposes, due to limitations of the functional test
-// environment. See test/functional/p2p-segwit.py.
-static bool IsScriptWitnessEnabled(const Consensus::Params& params)
-{
- return params.SegwitHeight != std::numeric_limits<int>::max();
-}
-
static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& consensusparams)
{
unsigned int flags = SCRIPT_VERIFY_NONE;
@@ -1676,22 +1668,22 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consens
// Enforce WITNESS rules whenever P2SH is in effect (and the segwit
// deployment is defined).
- if (flags & SCRIPT_VERIFY_P2SH && IsScriptWitnessEnabled(consensusparams)) {
+ if (flags & SCRIPT_VERIFY_P2SH && DeploymentEnabled(consensusparams, Consensus::DEPLOYMENT_SEGWIT)) {
flags |= SCRIPT_VERIFY_WITNESS;
}
- // Start enforcing the DERSIG (BIP66) rule
- if (pindex->nHeight >= consensusparams.BIP66Height) {
+ // Enforce the DERSIG (BIP66) rule
+ if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_DERSIG)) {
flags |= SCRIPT_VERIFY_DERSIG;
}
- // Start enforcing CHECKLOCKTIMEVERIFY (BIP65) rule
- if (pindex->nHeight >= consensusparams.BIP65Height) {
+ // Enforce CHECKLOCKTIMEVERIFY (BIP65)
+ if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_CLTV)) {
flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
}
- // Start enforcing BIP112 (CHECKSEQUENCEVERIFY)
- if (pindex->nHeight >= consensusparams.CSVHeight) {
+ // Enforce CHECKSEQUENCEVERIFY (BIP112)
+ if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_CSV)) {
flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
}
@@ -1700,8 +1692,8 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consens
flags |= SCRIPT_VERIFY_TAPROOT;
}
- // Start enforcing BIP147 NULLDUMMY (activated simultaneously with segwit)
- if (IsWitnessEnabled(pindex->pprev, consensusparams)) {
+ // Enforce BIP147 NULLDUMMY (activated simultaneously with segwit)
+ if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_SEGWIT)) {
flags |= SCRIPT_VERIFY_NULLDUMMY;
}
@@ -1891,9 +1883,9 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
}
}
- // Start enforcing BIP68 (sequence locks)
+ // Enforce BIP68 (sequence locks)
int nLockTimeFlags = 0;
- if (pindex->nHeight >= m_params.GetConsensus().CSVHeight) {
+ if (DeploymentActiveAt(*pindex, m_params.GetConsensus(), Consensus::DEPLOYMENT_CSV)) {
nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE;
}
@@ -2986,7 +2978,7 @@ void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pi
pindexNew->nDataPos = pos.nPos;
pindexNew->nUndoPos = 0;
pindexNew->nStatus |= BLOCK_HAVE_DATA;
- if (IsWitnessEnabled(pindexNew->pprev, m_params.GetConsensus())) {
+ if (DeploymentActiveAt(*pindexNew, m_params.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) {
pindexNew->nStatus |= BLOCK_OPT_WITNESS;
}
pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS);
@@ -3107,17 +3099,11 @@ bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensu
return true;
}
-bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params)
-{
- int height = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1;
- return (height >= params.SegwitHeight);
-}
-
void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams)
{
int commitpos = GetWitnessCommitmentIndex(block);
static const std::vector<unsigned char> nonce(32, 0x00);
- if (commitpos != NO_WITNESS_COMMITMENT && IsWitnessEnabled(pindexPrev, consensusParams) && !block.vtx[0]->HasWitness()) {
+ if (commitpos != NO_WITNESS_COMMITMENT && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT) && !block.vtx[0]->HasWitness()) {
CMutableTransaction tx(*block.vtx[0]);
tx.vin[0].scriptWitness.stack.resize(1);
tx.vin[0].scriptWitness.stack[0] = nonce;
@@ -3130,7 +3116,7 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
std::vector<unsigned char> commitment;
int commitpos = GetWitnessCommitmentIndex(block);
std::vector<unsigned char> ret(32, 0x00);
- if (consensusParams.SegwitHeight != std::numeric_limits<int>::max()) {
+ if (DeploymentEnabled(consensusParams, Consensus::DEPLOYMENT_SEGWIT)) {
if (commitpos == NO_WITNESS_COMMITMENT) {
uint256 witnessroot = BlockWitnessMerkleRoot(block, nullptr);
CHash256().Write(witnessroot).Write(ret).Finalize(witnessroot);
@@ -3208,13 +3194,13 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio
if (block.GetBlockTime() > nAdjustedTime + MAX_FUTURE_BLOCK_TIME)
return state.Invalid(BlockValidationResult::BLOCK_TIME_FUTURE, "time-too-new", "block timestamp too far in the future");
- // Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded:
- // check for version 2, 3 and 4 upgrades
- if((block.nVersion < 2 && nHeight >= consensusParams.BIP34Height) ||
- (block.nVersion < 3 && nHeight >= consensusParams.BIP66Height) ||
- (block.nVersion < 4 && nHeight >= consensusParams.BIP65Height))
+ // Reject blocks with outdated version
+ if ((block.nVersion < 2 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB)) ||
+ (block.nVersion < 3 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_DERSIG)) ||
+ (block.nVersion < 4 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CLTV))) {
return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, strprintf("bad-version(0x%08x)", block.nVersion),
strprintf("rejected nVersion=0x%08x block", block.nVersion));
+ }
return true;
}
@@ -3229,9 +3215,9 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
{
const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1;
- // Start enforcing BIP113 (Median Time Past).
+ // Enforce BIP113 (Median Time Past).
int nLockTimeFlags = 0;
- if (nHeight >= consensusParams.CSVHeight) {
+ if (DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CSV)) {
assert(pindexPrev != nullptr);
nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST;
}
@@ -3248,7 +3234,7 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
}
// Enforce rule that the coinbase starts with serialized block height
- if (nHeight >= consensusParams.BIP34Height)
+ if (DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB))
{
CScript expect = CScript() << nHeight;
if (block.vtx[0]->vin[0].scriptSig.size() < expect.size() ||
@@ -3266,7 +3252,7 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
// {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness reserved value). In case there are
// multiple, the last one is used.
bool fHaveWitness = false;
- if (nHeight >= consensusParams.SegwitHeight) {
+ if (DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT)) {
int commitpos = GetWitnessCommitmentIndex(block);
if (commitpos != NO_WITNESS_COMMITMENT) {
bool malleated = false;
@@ -4096,9 +4082,8 @@ bool CChainState::NeedsRedownload() const
// At and above m_params.SegwitHeight, segwit consensus rules must be validated
CBlockIndex* block{m_chain.Tip()};
- const int segwit_height{m_params.GetConsensus().SegwitHeight};
- while (block != nullptr && block->nHeight >= segwit_height) {
+ while (block != nullptr && DeploymentActiveAt(*block, m_params.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) {
if (!(block->nStatus & BLOCK_OPT_WITNESS)) {
// block is insufficiently validated for a segwit client
return true;
@@ -5000,7 +4985,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
// Fake BLOCK_OPT_WITNESS so that CChainState::NeedsRedownload()
// won't ask to rewind the entire assumed-valid chain on startup.
- if (index->pprev && ::IsWitnessEnabled(index->pprev, ::Params().GetConsensus())) {
+ if (index->pprev && DeploymentActiveAt(*index, ::Params().GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) {
index->nStatus |= BLOCK_OPT_WITNESS;
}
}
diff --git a/src/validation.h b/src/validation.h
index fc702b7183..50a8d7e575 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -345,10 +345,6 @@ bool TestBlockValidity(BlockValidationState& state,
bool fCheckPOW = true,
bool fCheckMerkleRoot = true) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-/** Check whether witness commitments are required for a block, and whether to enforce NULLDUMMY (BIP 147) rules.
- * Note that transaction witness validation rules are always enforced when P2SH is enforced. */
-bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params);
-
/** Update uncommitted block structures (currently: only the witness reserved value). This is safe for submitted blocks. */
void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams);