mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-06-02 23:42:33 +02:00
Merge bitcoin/bitcoin#19438: Introduce deploymentstatus
e48826ad87
tests: remove ComputeBlockVersion shortcut from versionbits tests (Anthony Towns)c5f36725e8
[refactor] Move ComputeBlockVersion into VersionBitsCache (Anthony Towns)4a69b4dbe0
[move-only] Move ComputeBlockVersion from validation to versionbits (Anthony Towns)0cfd6c6a8f
[refactor] versionbits: make VersionBitsCache a full class (Anthony Towns)8ee3e0bed5
[refactor] rpc/blockchain.cpp: SoftForkPushBack (Anthony Towns)92f48f360d
deploymentinfo: Add DeploymentName() (Anthony Towns)ea68b3a572
[move-only] Rename versionbitsinfo to deploymentinfo (Anthony Towns)c64b2c6a0f
scripted-diff: rename versionbitscache (Anthony Towns)de55304f6e
[refactor] Add versionbits deployments to deploymentstatus.h (Anthony Towns)2b0d291da8
[refactor] Add deploymentstatus.h (Anthony Towns)eccd736f3d
versionbits: Use dedicated lock instead of cs_main (Anthony Towns)36a4ba0aaa
versionbits: correct doxygen comments (Anthony Towns) Pull request description: Introduces helper functions to make it easy to bury future deployments, along the lines of the suggestion from [11398](https://github.com/bitcoin/bitcoin/pull/11398#issuecomment-335599326) "I would prefer it if a buried deployment wouldn't require all code paths that check the BIP9 status to require changing". This provides three functions: `DeploymentEnabled()` which tests if a deployment can ever be active, `DeploymentActiveAt()` which checks if a deployment should be enforced in the given block, and `DeploymentActiveAfter()` which checks if a deployment should be enforced in the block following the given block, and overloads all three to work both with buried deployments and versionbits deployments. This adds a dedicated lock for the versionbits cache, which is acquired internally by the versionbits functions, rather than relying on `cs_main`. It also moves moves versionbitscache into deploymentstatus to avoid a circular dependency with validation. ACKs for top commit: jnewbery: ACKe48826ad87
gruve-p: ACKe48826ad87
MarcoFalke: re-ACKe48826ad87
🥈 Tree-SHA512: c846ba64436d36f8180046ad551d8b0d9e20509b9bc185aa2639055fc28803dd8ec2d6771ab337e80da0b40009ad959590d5772f84a0bf6199b65190d4155bed
This commit is contained in:
commit
ddc6979b8b
@ -145,6 +145,8 @@ BITCOIN_CORE_H = \
|
|||||||
core_memusage.h \
|
core_memusage.h \
|
||||||
cuckoocache.h \
|
cuckoocache.h \
|
||||||
dbwrapper.h \
|
dbwrapper.h \
|
||||||
|
deploymentinfo.h \
|
||||||
|
deploymentstatus.h \
|
||||||
external_signer.h \
|
external_signer.h \
|
||||||
flatfile.h \
|
flatfile.h \
|
||||||
fs.h \
|
fs.h \
|
||||||
@ -272,7 +274,6 @@ BITCOIN_CORE_H = \
|
|||||||
validation.h \
|
validation.h \
|
||||||
validationinterface.h \
|
validationinterface.h \
|
||||||
versionbits.h \
|
versionbits.h \
|
||||||
versionbitsinfo.h \
|
|
||||||
wallet/bdb.h \
|
wallet/bdb.h \
|
||||||
wallet/coincontrol.h \
|
wallet/coincontrol.h \
|
||||||
wallet/coinselection.h \
|
wallet/coinselection.h \
|
||||||
@ -328,6 +329,7 @@ libbitcoin_server_a_SOURCES = \
|
|||||||
chain.cpp \
|
chain.cpp \
|
||||||
consensus/tx_verify.cpp \
|
consensus/tx_verify.cpp \
|
||||||
dbwrapper.cpp \
|
dbwrapper.cpp \
|
||||||
|
deploymentstatus.cpp \
|
||||||
flatfile.cpp \
|
flatfile.cpp \
|
||||||
httprpc.cpp \
|
httprpc.cpp \
|
||||||
httpserver.cpp \
|
httpserver.cpp \
|
||||||
@ -540,6 +542,7 @@ libbitcoin_common_a_SOURCES = \
|
|||||||
compressor.cpp \
|
compressor.cpp \
|
||||||
core_read.cpp \
|
core_read.cpp \
|
||||||
core_write.cpp \
|
core_write.cpp \
|
||||||
|
deploymentinfo.cpp \
|
||||||
external_signer.cpp \
|
external_signer.cpp \
|
||||||
init/common.cpp \
|
init/common.cpp \
|
||||||
key.cpp \
|
key.cpp \
|
||||||
@ -561,7 +564,6 @@ libbitcoin_common_a_SOURCES = \
|
|||||||
script/sign.cpp \
|
script/sign.cpp \
|
||||||
script/signingprovider.cpp \
|
script/signingprovider.cpp \
|
||||||
script/standard.cpp \
|
script/standard.cpp \
|
||||||
versionbitsinfo.cpp \
|
|
||||||
warnings.cpp \
|
warnings.cpp \
|
||||||
$(BITCOIN_CORE_H)
|
$(BITCOIN_CORE_H)
|
||||||
|
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
|
|
||||||
#include <chainparamsseeds.h>
|
#include <chainparamsseeds.h>
|
||||||
#include <consensus/merkle.h>
|
#include <consensus/merkle.h>
|
||||||
|
#include <deploymentinfo.h>
|
||||||
#include <hash.h> // for signet block challenge hash
|
#include <hash.h> // for signet block challenge hash
|
||||||
#include <util/system.h>
|
#include <util/system.h>
|
||||||
#include <versionbitsinfo.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
@ -11,13 +11,25 @@
|
|||||||
|
|
||||||
namespace Consensus {
|
namespace Consensus {
|
||||||
|
|
||||||
enum DeploymentPos
|
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 : uint16_t
|
||||||
{
|
{
|
||||||
DEPLOYMENT_TESTDUMMY,
|
DEPLOYMENT_TESTDUMMY,
|
||||||
DEPLOYMENT_TAPROOT, // Deployment of Schnorr/Taproot (BIPs 340-342)
|
DEPLOYMENT_TAPROOT, // Deployment of Schnorr/Taproot (BIPs 340-342)
|
||||||
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in versionbits.cpp
|
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in deploymentinfo.cpp
|
||||||
MAX_VERSION_BITS_DEPLOYMENTS
|
MAX_VERSION_BITS_DEPLOYMENTS
|
||||||
};
|
};
|
||||||
|
constexpr bool ValidDeployment(DeploymentPos dep) { return DEPLOYMENT_TESTDUMMY <= dep && dep <= DEPLOYMENT_TAPROOT; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Struct for each individual consensus rule change using BIP9.
|
* Struct for each individual consensus rule change using BIP9.
|
||||||
@ -100,7 +112,25 @@ struct Params {
|
|||||||
*/
|
*/
|
||||||
bool signet_blocks{false};
|
bool signet_blocks{false};
|
||||||
std::vector<uint8_t> signet_challenge;
|
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
|
} // namespace Consensus
|
||||||
|
|
||||||
#endif // BITCOIN_CONSENSUS_PARAMS_H
|
#endif // BITCOIN_CONSENSUS_PARAMS_H
|
||||||
|
36
src/deploymentinfo.cpp
Normal file
36
src/deploymentinfo.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// Copyright (c) 2016-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.
|
||||||
|
|
||||||
|
#include <deploymentinfo.h>
|
||||||
|
|
||||||
|
#include <consensus/params.h>
|
||||||
|
|
||||||
|
const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = {
|
||||||
|
{
|
||||||
|
/*.name =*/ "testdummy",
|
||||||
|
/*.gbt_force =*/ true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/*.name =*/ "taproot",
|
||||||
|
/*.gbt_force =*/ true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string DeploymentName(Consensus::BuriedDeployment dep)
|
||||||
|
{
|
||||||
|
assert(ValidDeployment(dep));
|
||||||
|
switch (dep) {
|
||||||
|
case Consensus::DEPLOYMENT_HEIGHTINCB:
|
||||||
|
return "bip34";
|
||||||
|
case Consensus::DEPLOYMENT_CLTV:
|
||||||
|
return "bip65";
|
||||||
|
case Consensus::DEPLOYMENT_DERSIG:
|
||||||
|
return "bip66";
|
||||||
|
case Consensus::DEPLOYMENT_CSV:
|
||||||
|
return "csv";
|
||||||
|
case Consensus::DEPLOYMENT_SEGWIT:
|
||||||
|
return "segwit";
|
||||||
|
} // no default case, so the compiler can warn about missing cases
|
||||||
|
return "";
|
||||||
|
}
|
29
src/deploymentinfo.h
Normal file
29
src/deploymentinfo.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Copyright (c) 2016-2018 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_DEPLOYMENTINFO_H
|
||||||
|
#define BITCOIN_DEPLOYMENTINFO_H
|
||||||
|
|
||||||
|
#include <consensus/params.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
struct VBDeploymentInfo {
|
||||||
|
/** Deployment name */
|
||||||
|
const char *name;
|
||||||
|
/** Whether GBT clients can safely ignore this rule in simplified usage */
|
||||||
|
bool gbt_force;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS];
|
||||||
|
|
||||||
|
std::string DeploymentName(Consensus::BuriedDeployment dep);
|
||||||
|
|
||||||
|
inline std::string DeploymentName(Consensus::DeploymentPos pos)
|
||||||
|
{
|
||||||
|
assert(Consensus::ValidDeployment(pos));
|
||||||
|
return VersionBitsDeploymentInfo[pos].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BITCOIN_DEPLOYMENTINFO_H
|
17
src/deploymentstatus.cpp
Normal file
17
src/deploymentstatus.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <deploymentstatus.h>
|
||||||
|
|
||||||
|
#include <consensus/params.h>
|
||||||
|
#include <versionbits.h>
|
||||||
|
|
||||||
|
VersionBitsCache g_versionbitscache;
|
||||||
|
|
||||||
|
/* Basic sanity checking for BuriedDeployment/DeploymentPos enums and
|
||||||
|
* ValidDeployment check */
|
||||||
|
|
||||||
|
static_assert(ValidDeployment(Consensus::DEPLOYMENT_TESTDUMMY), "sanity check of DeploymentPos failed (TESTDUMMY not valid)");
|
||||||
|
static_assert(!ValidDeployment(Consensus::MAX_VERSION_BITS_DEPLOYMENTS), "sanity check of DeploymentPos failed (MAX value considered valid)");
|
||||||
|
static_assert(!ValidDeployment(static_cast<Consensus::BuriedDeployment>(Consensus::DEPLOYMENT_TESTDUMMY)), "sanity check of BuriedDeployment failed (overlaps with DeploymentPos)");
|
55
src/deploymentstatus.h
Normal file
55
src/deploymentstatus.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// 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 <versionbits.h>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
/** Global cache for versionbits deployment status */
|
||||||
|
extern VersionBitsCache g_versionbitscache;
|
||||||
|
|
||||||
|
/** 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos dep)
|
||||||
|
{
|
||||||
|
assert(Consensus::ValidDeployment(dep));
|
||||||
|
return ThresholdState::ACTIVE == g_versionbitscache.State(pindexPrev, params, 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool DeploymentActiveAt(const CBlockIndex& index, const Consensus::Params& params, Consensus::DeploymentPos dep)
|
||||||
|
{
|
||||||
|
assert(Consensus::ValidDeployment(dep));
|
||||||
|
return DeploymentActiveAfter(index.pprev, params, 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool DeploymentEnabled(const Consensus::Params& params, Consensus::DeploymentPos dep)
|
||||||
|
{
|
||||||
|
assert(Consensus::ValidDeployment(dep));
|
||||||
|
return params.vDeployments[dep].nTimeout != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BITCOIN_DEPLOYMENTSTATUS_H
|
@ -16,6 +16,7 @@
|
|||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
#include <chainparams.h>
|
#include <chainparams.h>
|
||||||
#include <compat/sanity.h>
|
#include <compat/sanity.h>
|
||||||
|
#include <deploymentstatus.h>
|
||||||
#include <fs.h>
|
#include <fs.h>
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
#include <httprpc.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.
|
// Advertise witness capabilities.
|
||||||
// The option to not set NODE_WITNESS is only used in the tests and should be removed.
|
// The option to not set NODE_WITNESS is only used in the tests and should be removed.
|
||||||
nLocalServices = ServiceFlags(nLocalServices | NODE_WITNESS);
|
nLocalServices = ServiceFlags(nLocalServices | NODE_WITNESS);
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <consensus/merkle.h>
|
#include <consensus/merkle.h>
|
||||||
#include <consensus/tx_verify.h>
|
#include <consensus/tx_verify.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
|
#include <deploymentstatus.h>
|
||||||
#include <policy/feerate.h>
|
#include <policy/feerate.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
#include <pow.h>
|
#include <pow.h>
|
||||||
@ -120,7 +121,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
|||||||
assert(pindexPrev != nullptr);
|
assert(pindexPrev != nullptr);
|
||||||
nHeight = pindexPrev->nHeight + 1;
|
nHeight = pindexPrev->nHeight + 1;
|
||||||
|
|
||||||
pblock->nVersion = ComputeBlockVersion(pindexPrev, chainparams.GetConsensus());
|
pblock->nVersion = g_versionbitscache.ComputeBlockVersion(pindexPrev, chainparams.GetConsensus());
|
||||||
// -regtest only: allow overriding block.nVersion with
|
// -regtest only: allow overriding block.nVersion with
|
||||||
// -blockversion=N to test forking scenarios
|
// -blockversion=N to test forking scenarios
|
||||||
if (chainparams.MineBlocksOnDemand())
|
if (chainparams.MineBlocksOnDemand())
|
||||||
@ -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
|
// This is only needed in case the witness softfork activation is reverted
|
||||||
// (which would require a very deep reorganization).
|
// (which would require a very deep reorganization).
|
||||||
// Note that the mempool would accept transactions with witness data before
|
// 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
|
// unless there is a massive block reorganization with the witness softfork
|
||||||
// not activated.
|
// not activated.
|
||||||
// TODO: replace this with a call to main to assess validity of a mempool
|
// TODO: replace this with a call to main to assess validity of a mempool
|
||||||
// transaction (which in most cases can be a no-op).
|
// 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 nPackagesSelected = 0;
|
||||||
int nDescendantsUpdated = 0;
|
int nDescendantsUpdated = 0;
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <blockfilter.h>
|
#include <blockfilter.h>
|
||||||
#include <chainparams.h>
|
#include <chainparams.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
|
#include <deploymentstatus.h>
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
#include <index/blockfilterindex.h>
|
#include <index/blockfilterindex.h>
|
||||||
#include <merkleblock.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.
|
// We consider the chain that this peer is on invalid.
|
||||||
return;
|
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.
|
// We wouldn't download this block or its descendants from this peer.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1467,7 +1468,7 @@ void PeerManagerImpl::NewPoWValidBlock(const CBlockIndex *pindex, const std::sha
|
|||||||
return;
|
return;
|
||||||
nHighestFastAnnounce = pindex->nHeight;
|
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());
|
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) {
|
while (pindexWalk && !m_chainman.ActiveChain().Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
|
||||||
if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) &&
|
if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) &&
|
||||||
!IsBlockRequested(pindexWalk->GetBlockHash()) &&
|
!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.
|
// We don't have this block, and it's not yet in flight.
|
||||||
vToFetch.push_back(pindexWalk);
|
vToFetch.push_back(pindexWalk);
|
||||||
}
|
}
|
||||||
@ -3397,7 +3398,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||||||
return;
|
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
|
// Don't bother trying to process compact blocks from v1 peers
|
||||||
// after segwit activates.
|
// after segwit activates.
|
||||||
return;
|
return;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <banman.h>
|
#include <banman.h>
|
||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
#include <chainparams.h>
|
#include <chainparams.h>
|
||||||
|
#include <deploymentstatus.h>
|
||||||
#include <external_signer.h>
|
#include <external_signer.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
#include <interfaces/chain.h>
|
#include <interfaces/chain.h>
|
||||||
@ -692,7 +693,7 @@ public:
|
|||||||
{
|
{
|
||||||
LOCK(::cs_main);
|
LOCK(::cs_main);
|
||||||
const CBlockIndex* tip = Assert(m_node.chainman)->ActiveChain().Tip();
|
const CBlockIndex* tip = Assert(m_node.chainman)->ActiveChain().Tip();
|
||||||
return VersionBitsState(tip, Params().GetConsensus(), Consensus::DEPLOYMENT_TAPROOT, versionbitscache) == ThresholdState::ACTIVE;
|
return DeploymentActiveAfter(tip, Params().GetConsensus(), Consensus::DEPLOYMENT_TAPROOT);
|
||||||
}
|
}
|
||||||
NodeContext& m_node;
|
NodeContext& m_node;
|
||||||
};
|
};
|
||||||
|
@ -10,8 +10,11 @@
|
|||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
#include <chainparams.h>
|
#include <chainparams.h>
|
||||||
#include <coins.h>
|
#include <coins.h>
|
||||||
|
#include <consensus/params.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
#include <core_io.h>
|
#include <core_io.h>
|
||||||
|
#include <deploymentinfo.h>
|
||||||
|
#include <deploymentstatus.h>
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
#include <index/blockfilterindex.h>
|
#include <index/blockfilterindex.h>
|
||||||
#include <index/coinstatsindex.h>
|
#include <index/coinstatsindex.h>
|
||||||
@ -37,6 +40,7 @@
|
|||||||
#include <util/translation.h>
|
#include <util/translation.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <validationinterface.h>
|
#include <validationinterface.h>
|
||||||
|
#include <versionbits.h>
|
||||||
#include <warnings.h>
|
#include <warnings.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -1343,32 +1347,32 @@ static RPCHelpMan verifychain()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BuriedForkDescPushBack(UniValue& softforks, const std::string &name, int softfork_height, int tip_height) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& softforks, const Consensus::Params& params, Consensus::BuriedDeployment dep)
|
||||||
{
|
{
|
||||||
// For buried deployments.
|
// For buried deployments.
|
||||||
// A buried deployment is one where the height of the activation has been hardcoded into
|
// A buried deployment is one where the height of the activation has been hardcoded into
|
||||||
// the client implementation long after the consensus change has activated. See BIP 90.
|
// the client implementation long after the consensus change has activated. See BIP 90.
|
||||||
// Buried deployments with activation height value of
|
// Buried deployments with activation height value of
|
||||||
// std::numeric_limits<int>::max() are disabled and thus hidden.
|
// std::numeric_limits<int>::max() are disabled and thus hidden.
|
||||||
if (softfork_height == std::numeric_limits<int>::max()) return;
|
if (!DeploymentEnabled(params, dep)) return;
|
||||||
|
|
||||||
UniValue rv(UniValue::VOBJ);
|
UniValue rv(UniValue::VOBJ);
|
||||||
rv.pushKV("type", "buried");
|
rv.pushKV("type", "buried");
|
||||||
// getblockchaininfo reports the softfork as active from when the chain height is
|
// getblockchaininfo reports the softfork as active from when the chain height is
|
||||||
// one below the activation height
|
// one below the activation height
|
||||||
rv.pushKV("active", tip_height + 1 >= softfork_height);
|
rv.pushKV("active", DeploymentActiveAfter(active_chain_tip, params, dep));
|
||||||
rv.pushKV("height", softfork_height);
|
rv.pushKV("height", params.DeploymentHeight(dep));
|
||||||
softforks.pushKV(name, rv);
|
softforks.pushKV(DeploymentName(dep), rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BIP9SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& softforks, const std::string &name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
|
||||||
{
|
{
|
||||||
// For BIP9 deployments.
|
// For BIP9 deployments.
|
||||||
// Deployments that are never active are hidden.
|
// Deployments that are never active are hidden.
|
||||||
if (consensusParams.vDeployments[id].nStartTime == Consensus::BIP9Deployment::NEVER_ACTIVE) return;
|
if (consensusParams.vDeployments[id].nStartTime == Consensus::BIP9Deployment::NEVER_ACTIVE) return;
|
||||||
|
|
||||||
UniValue bip9(UniValue::VOBJ);
|
UniValue bip9(UniValue::VOBJ);
|
||||||
const ThresholdState thresholdState = VersionBitsState(active_chain_tip, consensusParams, id, versionbitscache);
|
const ThresholdState thresholdState = g_versionbitscache.State(active_chain_tip, consensusParams, id);
|
||||||
switch (thresholdState) {
|
switch (thresholdState) {
|
||||||
case ThresholdState::DEFINED: bip9.pushKV("status", "defined"); break;
|
case ThresholdState::DEFINED: bip9.pushKV("status", "defined"); break;
|
||||||
case ThresholdState::STARTED: bip9.pushKV("status", "started"); break;
|
case ThresholdState::STARTED: bip9.pushKV("status", "started"); break;
|
||||||
@ -1382,12 +1386,12 @@ static void BIP9SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniVal
|
|||||||
}
|
}
|
||||||
bip9.pushKV("start_time", consensusParams.vDeployments[id].nStartTime);
|
bip9.pushKV("start_time", consensusParams.vDeployments[id].nStartTime);
|
||||||
bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
|
bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
|
||||||
int64_t since_height = VersionBitsStateSinceHeight(active_chain_tip, consensusParams, id, versionbitscache);
|
int64_t since_height = g_versionbitscache.StateSinceHeight(active_chain_tip, consensusParams, id);
|
||||||
bip9.pushKV("since", since_height);
|
bip9.pushKV("since", since_height);
|
||||||
if (ThresholdState::STARTED == thresholdState)
|
if (ThresholdState::STARTED == thresholdState)
|
||||||
{
|
{
|
||||||
UniValue statsUV(UniValue::VOBJ);
|
UniValue statsUV(UniValue::VOBJ);
|
||||||
BIP9Stats statsStruct = VersionBitsStatistics(active_chain_tip, consensusParams, id);
|
BIP9Stats statsStruct = g_versionbitscache.Statistics(active_chain_tip, consensusParams, id);
|
||||||
statsUV.pushKV("period", statsStruct.period);
|
statsUV.pushKV("period", statsStruct.period);
|
||||||
statsUV.pushKV("threshold", statsStruct.threshold);
|
statsUV.pushKV("threshold", statsStruct.threshold);
|
||||||
statsUV.pushKV("elapsed", statsStruct.elapsed);
|
statsUV.pushKV("elapsed", statsStruct.elapsed);
|
||||||
@ -1405,7 +1409,7 @@ static void BIP9SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniVal
|
|||||||
}
|
}
|
||||||
rv.pushKV("active", ThresholdState::ACTIVE == thresholdState);
|
rv.pushKV("active", ThresholdState::ACTIVE == thresholdState);
|
||||||
|
|
||||||
softforks.pushKV(name, rv);
|
softforks.pushKV(DeploymentName(id), rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
RPCHelpMan getblockchaininfo()
|
RPCHelpMan getblockchaininfo()
|
||||||
@ -1502,14 +1506,14 @@ RPCHelpMan getblockchaininfo()
|
|||||||
|
|
||||||
const Consensus::Params& consensusParams = Params().GetConsensus();
|
const Consensus::Params& consensusParams = Params().GetConsensus();
|
||||||
UniValue softforks(UniValue::VOBJ);
|
UniValue softforks(UniValue::VOBJ);
|
||||||
BuriedForkDescPushBack(softforks, "bip34", consensusParams.BIP34Height, height);
|
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB);
|
||||||
BuriedForkDescPushBack(softforks, "bip66", consensusParams.BIP66Height, height);
|
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_DERSIG);
|
||||||
BuriedForkDescPushBack(softforks, "bip65", consensusParams.BIP65Height, height);
|
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_CLTV);
|
||||||
BuriedForkDescPushBack(softforks, "csv", consensusParams.CSVHeight, height);
|
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_CSV);
|
||||||
BuriedForkDescPushBack(softforks, "segwit", consensusParams.SegwitHeight, height);
|
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_SEGWIT);
|
||||||
BIP9SoftForkDescPushBack(tip, softforks, "testdummy", consensusParams, Consensus::DEPLOYMENT_TESTDUMMY);
|
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_TESTDUMMY);
|
||||||
BIP9SoftForkDescPushBack(tip, softforks, "taproot", consensusParams, Consensus::DEPLOYMENT_TAPROOT);
|
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_TAPROOT);
|
||||||
obj.pushKV("softforks", softforks);
|
obj.pushKV("softforks", softforks);
|
||||||
|
|
||||||
obj.pushKV("warnings", GetWarnings(false).original);
|
obj.pushKV("warnings", GetWarnings(false).original);
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#include <consensus/params.h>
|
#include <consensus/params.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
#include <core_io.h>
|
#include <core_io.h>
|
||||||
|
#include <deploymentinfo.h>
|
||||||
|
#include <deploymentstatus.h>
|
||||||
#include <key_io.h>
|
#include <key_io.h>
|
||||||
#include <miner.h>
|
#include <miner.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
@ -34,7 +36,6 @@
|
|||||||
#include <util/translation.h>
|
#include <util/translation.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <validationinterface.h>
|
#include <validationinterface.h>
|
||||||
#include <versionbitsinfo.h>
|
|
||||||
#include <warnings.h>
|
#include <warnings.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -774,7 +775,7 @@ static RPCHelpMan getblocktemplate()
|
|||||||
pblock->nNonce = 0;
|
pblock->nNonce = 0;
|
||||||
|
|
||||||
// NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration
|
// 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");
|
UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
|
||||||
|
|
||||||
@ -840,7 +841,7 @@ static RPCHelpMan getblocktemplate()
|
|||||||
UniValue vbavailable(UniValue::VOBJ);
|
UniValue vbavailable(UniValue::VOBJ);
|
||||||
for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
|
for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
|
||||||
Consensus::DeploymentPos pos = Consensus::DeploymentPos(j);
|
Consensus::DeploymentPos pos = Consensus::DeploymentPos(j);
|
||||||
ThresholdState state = VersionBitsState(pindexPrev, consensusParams, pos, versionbitscache);
|
ThresholdState state = g_versionbitscache.State(pindexPrev, consensusParams, pos);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case ThresholdState::DEFINED:
|
case ThresholdState::DEFINED:
|
||||||
case ThresholdState::FAILED:
|
case ThresholdState::FAILED:
|
||||||
@ -848,7 +849,7 @@ static RPCHelpMan getblocktemplate()
|
|||||||
break;
|
break;
|
||||||
case ThresholdState::LOCKED_IN:
|
case ThresholdState::LOCKED_IN:
|
||||||
// Ensure bit is set in block version
|
// Ensure bit is set in block version
|
||||||
pblock->nVersion |= VersionBitsMask(consensusParams, pos);
|
pblock->nVersion |= g_versionbitscache.Mask(consensusParams, pos);
|
||||||
// FALL THROUGH to get vbavailable set...
|
// FALL THROUGH to get vbavailable set...
|
||||||
case ThresholdState::STARTED:
|
case ThresholdState::STARTED:
|
||||||
{
|
{
|
||||||
@ -857,7 +858,7 @@ static RPCHelpMan getblocktemplate()
|
|||||||
if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
|
if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
|
||||||
if (!vbinfo.gbt_force) {
|
if (!vbinfo.gbt_force) {
|
||||||
// If the client doesn't support this, don't indicate it in the [default] version
|
// If the client doesn't support this, don't indicate it in the [default] version
|
||||||
pblock->nVersion &= ~VersionBitsMask(consensusParams, pos);
|
pblock->nVersion &= ~g_versionbitscache.Mask(consensusParams, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
#include <chainparams.h>
|
#include <chainparams.h>
|
||||||
#include <consensus/params.h>
|
#include <consensus/params.h>
|
||||||
|
#include <deploymentstatus.h>
|
||||||
#include <test/util/setup_common.h>
|
#include <test/util/setup_common.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <versionbits.h>
|
#include <versionbits.h>
|
||||||
@ -258,8 +259,8 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
|
|||||||
/** Check that ComputeBlockVersion will set the appropriate bit correctly */
|
/** Check that ComputeBlockVersion will set the appropriate bit correctly */
|
||||||
static void check_computeblockversion(const Consensus::Params& params, Consensus::DeploymentPos dep)
|
static void check_computeblockversion(const Consensus::Params& params, Consensus::DeploymentPos dep)
|
||||||
{
|
{
|
||||||
// This implicitly uses versionbitscache, so clear it every time
|
// This implicitly uses g_versionbitscache, so clear it every time
|
||||||
versionbitscache.Clear();
|
g_versionbitscache.Clear();
|
||||||
|
|
||||||
int64_t bit = params.vDeployments[dep].bit;
|
int64_t bit = params.vDeployments[dep].bit;
|
||||||
int64_t nStartTime = params.vDeployments[dep].nStartTime;
|
int64_t nStartTime = params.vDeployments[dep].nStartTime;
|
||||||
@ -267,7 +268,7 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
|
|||||||
int min_activation_height = params.vDeployments[dep].min_activation_height;
|
int min_activation_height = params.vDeployments[dep].min_activation_height;
|
||||||
|
|
||||||
// should not be any signalling for first block
|
// should not be any signalling for first block
|
||||||
BOOST_CHECK_EQUAL(ComputeBlockVersion(nullptr, params), VERSIONBITS_TOP_BITS);
|
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(nullptr, params), VERSIONBITS_TOP_BITS);
|
||||||
|
|
||||||
// always/never active deployments shouldn't need to be tested further
|
// always/never active deployments shouldn't need to be tested further
|
||||||
if (nStartTime == Consensus::BIP9Deployment::ALWAYS_ACTIVE ||
|
if (nStartTime == Consensus::BIP9Deployment::ALWAYS_ACTIVE ||
|
||||||
@ -287,7 +288,7 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
|
|||||||
// Check min_activation_height is on a retarget boundary
|
// Check min_activation_height is on a retarget boundary
|
||||||
BOOST_REQUIRE_EQUAL(min_activation_height % params.nMinerConfirmationWindow, 0U);
|
BOOST_REQUIRE_EQUAL(min_activation_height % params.nMinerConfirmationWindow, 0U);
|
||||||
|
|
||||||
const uint32_t bitmask{VersionBitsMask(params, dep)};
|
const uint32_t bitmask{g_versionbitscache.Mask(params, dep)};
|
||||||
BOOST_CHECK_EQUAL(bitmask, uint32_t{1} << bit);
|
BOOST_CHECK_EQUAL(bitmask, uint32_t{1} << bit);
|
||||||
|
|
||||||
// In the first chain, test that the bit is set by CBV until it has failed.
|
// In the first chain, test that the bit is set by CBV until it has failed.
|
||||||
@ -306,9 +307,9 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
|
|||||||
// earlier time, so will transition from DEFINED to STARTED at the
|
// earlier time, so will transition from DEFINED to STARTED at the
|
||||||
// end of the first period by mining blocks at nTime == 0
|
// end of the first period by mining blocks at nTime == 0
|
||||||
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||||
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
|
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||||
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||||
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
|
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||||
// then we'll keep mining at nStartTime...
|
// then we'll keep mining at nStartTime...
|
||||||
} else {
|
} else {
|
||||||
// use a time 1s earlier than start time to check we stay DEFINED
|
// use a time 1s earlier than start time to check we stay DEFINED
|
||||||
@ -316,28 +317,28 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
|
|||||||
|
|
||||||
// Start generating blocks before nStartTime
|
// Start generating blocks before nStartTime
|
||||||
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||||
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
|
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||||
|
|
||||||
// Mine more blocks (4 less than the adjustment period) at the old time, and check that CBV isn't setting the bit yet.
|
// Mine more blocks (4 less than the adjustment period) at the old time, and check that CBV isn't setting the bit yet.
|
||||||
for (uint32_t i = 1; i < params.nMinerConfirmationWindow - 4; i++) {
|
for (uint32_t i = 1; i < params.nMinerConfirmationWindow - 4; i++) {
|
||||||
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||||
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
|
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||||
}
|
}
|
||||||
// Now mine 5 more blocks at the start time -- MTP should not have passed yet, so
|
// Now mine 5 more blocks at the start time -- MTP should not have passed yet, so
|
||||||
// CBV should still not yet set the bit.
|
// CBV should still not yet set the bit.
|
||||||
nTime = nStartTime;
|
nTime = nStartTime;
|
||||||
for (uint32_t i = params.nMinerConfirmationWindow - 4; i <= params.nMinerConfirmationWindow; i++) {
|
for (uint32_t i = params.nMinerConfirmationWindow - 4; i <= params.nMinerConfirmationWindow; i++) {
|
||||||
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||||
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
|
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||||
}
|
}
|
||||||
// Next we will advance to the next period and transition to STARTED,
|
// Next we will advance to the next period and transition to STARTED,
|
||||||
}
|
}
|
||||||
|
|
||||||
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||||
// so ComputeBlockVersion should now set the bit,
|
// so ComputeBlockVersion should now set the bit,
|
||||||
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
|
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||||
// and should also be using the VERSIONBITS_TOP_BITS.
|
// and should also be using the VERSIONBITS_TOP_BITS.
|
||||||
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
|
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
|
||||||
|
|
||||||
// Check that ComputeBlockVersion will set the bit until nTimeout
|
// Check that ComputeBlockVersion will set the bit until nTimeout
|
||||||
nTime += 600;
|
nTime += 600;
|
||||||
@ -346,8 +347,8 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
|
|||||||
// These blocks are all before nTimeout is reached.
|
// These blocks are all before nTimeout is reached.
|
||||||
while (nTime < nTimeout && blocksToMine > 0) {
|
while (nTime < nTimeout && blocksToMine > 0) {
|
||||||
lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||||
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
|
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||||
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
|
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
|
||||||
blocksToMine--;
|
blocksToMine--;
|
||||||
nTime += 600;
|
nTime += 600;
|
||||||
nHeight += 1;
|
nHeight += 1;
|
||||||
@ -361,7 +362,7 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
|
|||||||
// finish the last period before we start timing out
|
// finish the last period before we start timing out
|
||||||
while (nHeight % params.nMinerConfirmationWindow != 0) {
|
while (nHeight % params.nMinerConfirmationWindow != 0) {
|
||||||
lastBlock = firstChain.Mine(nHeight+1, nTime - 1, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
lastBlock = firstChain.Mine(nHeight+1, nTime - 1, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||||
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
|
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||||
nHeight += 1;
|
nHeight += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,12 +370,12 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
|
|||||||
// the bit until the period transition.
|
// the bit until the period transition.
|
||||||
for (uint32_t i = 0; i < params.nMinerConfirmationWindow - 1; i++) {
|
for (uint32_t i = 0; i < params.nMinerConfirmationWindow - 1; i++) {
|
||||||
lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||||
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
|
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||||
nHeight += 1;
|
nHeight += 1;
|
||||||
}
|
}
|
||||||
// The next block should trigger no longer setting the bit.
|
// The next block should trigger no longer setting the bit.
|
||||||
lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||||
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
|
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// On a new chain:
|
// On a new chain:
|
||||||
@ -385,30 +386,30 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
|
|||||||
// Mine one period worth of blocks, and check that the bit will be on for the
|
// Mine one period worth of blocks, and check that the bit will be on for the
|
||||||
// next period.
|
// next period.
|
||||||
lastBlock = secondChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
lastBlock = secondChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||||
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
|
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||||
|
|
||||||
// Mine another period worth of blocks, signaling the new bit.
|
// Mine another period worth of blocks, signaling the new bit.
|
||||||
lastBlock = secondChain.Mine(params.nMinerConfirmationWindow * 2, nTime, VERSIONBITS_TOP_BITS | (1<<bit)).Tip();
|
lastBlock = secondChain.Mine(params.nMinerConfirmationWindow * 2, nTime, VERSIONBITS_TOP_BITS | (1<<bit)).Tip();
|
||||||
// After one period of setting the bit on each block, it should have locked in.
|
// After one period of setting the bit on each block, it should have locked in.
|
||||||
// We keep setting the bit for one more period though, until activation.
|
// We keep setting the bit for one more period though, until activation.
|
||||||
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
|
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||||
|
|
||||||
// Now check that we keep mining the block until the end of this period, and
|
// Now check that we keep mining the block until the end of this period, and
|
||||||
// then stop at the beginning of the next period.
|
// then stop at the beginning of the next period.
|
||||||
lastBlock = secondChain.Mine((params.nMinerConfirmationWindow * 3) - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
lastBlock = secondChain.Mine((params.nMinerConfirmationWindow * 3) - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||||
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||||
lastBlock = secondChain.Mine(params.nMinerConfirmationWindow * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
lastBlock = secondChain.Mine(params.nMinerConfirmationWindow * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||||
|
|
||||||
if (lastBlock->nHeight + 1 < min_activation_height) {
|
if (lastBlock->nHeight + 1 < min_activation_height) {
|
||||||
// check signalling continues while min_activation_height is not reached
|
// check signalling continues while min_activation_height is not reached
|
||||||
lastBlock = secondChain.Mine(min_activation_height - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
lastBlock = secondChain.Mine(min_activation_height - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||||
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||||
// then reach min_activation_height, which was already REQUIRE'd to start a new period
|
// then reach min_activation_height, which was already REQUIRE'd to start a new period
|
||||||
lastBlock = secondChain.Mine(min_activation_height, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
lastBlock = secondChain.Mine(min_activation_height, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that we don't signal after activation
|
// Check that we don't signal after activation
|
||||||
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
|
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
|
BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
|
||||||
@ -425,7 +426,7 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
|
|||||||
// not take precedence over STARTED/LOCKED_IN. So all softforks on
|
// not take precedence over STARTED/LOCKED_IN. So all softforks on
|
||||||
// the same bit might overlap, even when non-overlapping start-end
|
// the same bit might overlap, even when non-overlapping start-end
|
||||||
// times are picked.
|
// times are picked.
|
||||||
const uint32_t dep_mask{VersionBitsMask(chainParams->GetConsensus(), dep)};
|
const uint32_t dep_mask{g_versionbitscache.Mask(chainParams->GetConsensus(), dep)};
|
||||||
BOOST_CHECK(!(chain_all_vbits & dep_mask));
|
BOOST_CHECK(!(chain_all_vbits & dep_mask));
|
||||||
chain_all_vbits |= dep_mask;
|
chain_all_vbits |= dep_mask;
|
||||||
check_computeblockversion(chainParams->GetConsensus(), dep);
|
check_computeblockversion(chainParams->GetConsensus(), dep);
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <consensus/tx_verify.h>
|
#include <consensus/tx_verify.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
#include <cuckoocache.h>
|
#include <cuckoocache.h>
|
||||||
|
#include <deploymentstatus.h>
|
||||||
#include <flatfile.h>
|
#include <flatfile.h>
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
#include <index/blockfilterindex.h>
|
#include <index/blockfilterindex.h>
|
||||||
@ -683,9 +684,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for non-standard pay-to-script-hash in inputs
|
// Check for non-standard pay-to-script-hash in inputs
|
||||||
const auto& params = args.m_chainparams.GetConsensus();
|
const bool taproot_active = DeploymentActiveAfter(m_active_chainstate.m_chain.Tip(), args.m_chainparams.GetConsensus(), Consensus::DEPLOYMENT_TAPROOT);
|
||||||
auto taproot_state = VersionBitsState(m_active_chainstate.m_chain.Tip(), params, Consensus::DEPLOYMENT_TAPROOT, versionbitscache);
|
if (fRequireStandard && !AreInputsStandard(tx, m_view, taproot_active)) {
|
||||||
if (fRequireStandard && !AreInputsStandard(tx, m_view, taproot_state == ThresholdState::ACTIVE)) {
|
|
||||||
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs");
|
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1606,23 +1606,6 @@ void StopScriptCheckWorkerThreads()
|
|||||||
scriptcheckqueue.StopWorkerThreads();
|
scriptcheckqueue.StopWorkerThreads();
|
||||||
}
|
}
|
||||||
|
|
||||||
VersionBitsCache versionbitscache GUARDED_BY(cs_main);
|
|
||||||
|
|
||||||
int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params)
|
|
||||||
{
|
|
||||||
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, static_cast<Consensus::DeploymentPos>(i), versionbitscache);
|
|
||||||
if (state == ThresholdState::LOCKED_IN || state == ThresholdState::STARTED) {
|
|
||||||
nVersion |= VersionBitsMask(params, static_cast<Consensus::DeploymentPos>(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Threshold condition checker that triggers when unknown versionbits are seen on the network.
|
* Threshold condition checker that triggers when unknown versionbits are seen on the network.
|
||||||
*/
|
*/
|
||||||
@ -1644,24 +1627,14 @@ public:
|
|||||||
return pindex->nHeight >= params.MinBIP9WarningHeight &&
|
return pindex->nHeight >= params.MinBIP9WarningHeight &&
|
||||||
((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) &&
|
((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) &&
|
||||||
((pindex->nVersion >> bit) & 1) != 0 &&
|
((pindex->nVersion >> bit) & 1) != 0 &&
|
||||||
((ComputeBlockVersion(pindex->pprev, params) >> bit) & 1) == 0;
|
((g_versionbitscache.ComputeBlockVersion(pindex->pprev, params) >> bit) & 1) == 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS] GUARDED_BY(cs_main);
|
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
|
static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& consensusparams)
|
||||||
// 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) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
|
|
||||||
AssertLockHeld(cs_main);
|
|
||||||
|
|
||||||
unsigned int flags = SCRIPT_VERIFY_NONE;
|
unsigned int flags = SCRIPT_VERIFY_NONE;
|
||||||
|
|
||||||
// BIP16 didn't become active until Apr 1 2012 (on mainnet, and
|
// BIP16 didn't become active until Apr 1 2012 (on mainnet, and
|
||||||
@ -1678,32 +1651,32 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consens
|
|||||||
|
|
||||||
// Enforce WITNESS rules whenever P2SH is in effect (and the segwit
|
// Enforce WITNESS rules whenever P2SH is in effect (and the segwit
|
||||||
// deployment is defined).
|
// deployment is defined).
|
||||||
if (flags & SCRIPT_VERIFY_P2SH && IsScriptWitnessEnabled(consensusparams)) {
|
if (flags & SCRIPT_VERIFY_P2SH && DeploymentEnabled(consensusparams, Consensus::DEPLOYMENT_SEGWIT)) {
|
||||||
flags |= SCRIPT_VERIFY_WITNESS;
|
flags |= SCRIPT_VERIFY_WITNESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start enforcing the DERSIG (BIP66) rule
|
// Enforce the DERSIG (BIP66) rule
|
||||||
if (pindex->nHeight >= consensusparams.BIP66Height) {
|
if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_DERSIG)) {
|
||||||
flags |= SCRIPT_VERIFY_DERSIG;
|
flags |= SCRIPT_VERIFY_DERSIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start enforcing CHECKLOCKTIMEVERIFY (BIP65) rule
|
// Enforce CHECKLOCKTIMEVERIFY (BIP65)
|
||||||
if (pindex->nHeight >= consensusparams.BIP65Height) {
|
if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_CLTV)) {
|
||||||
flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
|
flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start enforcing BIP112 (CHECKSEQUENCEVERIFY)
|
// Enforce CHECKSEQUENCEVERIFY (BIP112)
|
||||||
if (pindex->nHeight >= consensusparams.CSVHeight) {
|
if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_CSV)) {
|
||||||
flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
|
flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start enforcing Taproot using versionbits logic.
|
// Enforce Taproot (BIP340-BIP342)
|
||||||
if (VersionBitsState(pindex->pprev, consensusparams, Consensus::DEPLOYMENT_TAPROOT, versionbitscache) == ThresholdState::ACTIVE) {
|
if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_TAPROOT)) {
|
||||||
flags |= SCRIPT_VERIFY_TAPROOT;
|
flags |= SCRIPT_VERIFY_TAPROOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start enforcing BIP147 NULLDUMMY (activated simultaneously with segwit)
|
// Enforce BIP147 NULLDUMMY (activated simultaneously with segwit)
|
||||||
if (IsWitnessEnabled(pindex->pprev, consensusparams)) {
|
if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_SEGWIT)) {
|
||||||
flags |= SCRIPT_VERIFY_NULLDUMMY;
|
flags |= SCRIPT_VERIFY_NULLDUMMY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1893,9 +1866,9 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start enforcing BIP68 (sequence locks)
|
// Enforce BIP68 (sequence locks)
|
||||||
int nLockTimeFlags = 0;
|
int nLockTimeFlags = 0;
|
||||||
if (pindex->nHeight >= m_params.GetConsensus().CSVHeight) {
|
if (DeploymentActiveAt(*pindex, m_params.GetConsensus(), Consensus::DEPLOYMENT_CSV)) {
|
||||||
nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE;
|
nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2988,7 +2961,7 @@ void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pi
|
|||||||
pindexNew->nDataPos = pos.nPos;
|
pindexNew->nDataPos = pos.nPos;
|
||||||
pindexNew->nUndoPos = 0;
|
pindexNew->nUndoPos = 0;
|
||||||
pindexNew->nStatus |= BLOCK_HAVE_DATA;
|
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->nStatus |= BLOCK_OPT_WITNESS;
|
||||||
}
|
}
|
||||||
pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS);
|
pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS);
|
||||||
@ -3109,17 +3082,11 @@ bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensu
|
|||||||
return true;
|
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)
|
void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams)
|
||||||
{
|
{
|
||||||
int commitpos = GetWitnessCommitmentIndex(block);
|
int commitpos = GetWitnessCommitmentIndex(block);
|
||||||
static const std::vector<unsigned char> nonce(32, 0x00);
|
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]);
|
CMutableTransaction tx(*block.vtx[0]);
|
||||||
tx.vin[0].scriptWitness.stack.resize(1);
|
tx.vin[0].scriptWitness.stack.resize(1);
|
||||||
tx.vin[0].scriptWitness.stack[0] = nonce;
|
tx.vin[0].scriptWitness.stack[0] = nonce;
|
||||||
@ -3132,7 +3099,7 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
|
|||||||
std::vector<unsigned char> commitment;
|
std::vector<unsigned char> commitment;
|
||||||
int commitpos = GetWitnessCommitmentIndex(block);
|
int commitpos = GetWitnessCommitmentIndex(block);
|
||||||
std::vector<unsigned char> ret(32, 0x00);
|
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) {
|
if (commitpos == NO_WITNESS_COMMITMENT) {
|
||||||
uint256 witnessroot = BlockWitnessMerkleRoot(block, nullptr);
|
uint256 witnessroot = BlockWitnessMerkleRoot(block, nullptr);
|
||||||
CHash256().Write(witnessroot).Write(ret).Finalize(witnessroot);
|
CHash256().Write(witnessroot).Write(ret).Finalize(witnessroot);
|
||||||
@ -3210,13 +3177,13 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio
|
|||||||
if (block.GetBlockTime() > nAdjustedTime + MAX_FUTURE_BLOCK_TIME)
|
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");
|
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:
|
// Reject blocks with outdated version
|
||||||
// check for version 2, 3 and 4 upgrades
|
if ((block.nVersion < 2 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB)) ||
|
||||||
if((block.nVersion < 2 && nHeight >= consensusParams.BIP34Height) ||
|
(block.nVersion < 3 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_DERSIG)) ||
|
||||||
(block.nVersion < 3 && nHeight >= consensusParams.BIP66Height) ||
|
(block.nVersion < 4 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CLTV))) {
|
||||||
(block.nVersion < 4 && nHeight >= consensusParams.BIP65Height))
|
|
||||||
return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, strprintf("bad-version(0x%08x)", block.nVersion),
|
return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, strprintf("bad-version(0x%08x)", block.nVersion),
|
||||||
strprintf("rejected nVersion=0x%08x block", block.nVersion));
|
strprintf("rejected nVersion=0x%08x block", block.nVersion));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3231,9 +3198,9 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
|
|||||||
{
|
{
|
||||||
const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1;
|
const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1;
|
||||||
|
|
||||||
// Start enforcing BIP113 (Median Time Past).
|
// Enforce BIP113 (Median Time Past).
|
||||||
int nLockTimeFlags = 0;
|
int nLockTimeFlags = 0;
|
||||||
if (nHeight >= consensusParams.CSVHeight) {
|
if (DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CSV)) {
|
||||||
assert(pindexPrev != nullptr);
|
assert(pindexPrev != nullptr);
|
||||||
nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST;
|
nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST;
|
||||||
}
|
}
|
||||||
@ -3250,7 +3217,7 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Enforce rule that the coinbase starts with serialized block height
|
// 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;
|
CScript expect = CScript() << nHeight;
|
||||||
if (block.vtx[0]->vin[0].scriptSig.size() < expect.size() ||
|
if (block.vtx[0]->vin[0].scriptSig.size() < expect.size() ||
|
||||||
@ -3268,7 +3235,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
|
// {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.
|
// multiple, the last one is used.
|
||||||
bool fHaveWitness = false;
|
bool fHaveWitness = false;
|
||||||
if (nHeight >= consensusParams.SegwitHeight) {
|
if (DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT)) {
|
||||||
int commitpos = GetWitnessCommitmentIndex(block);
|
int commitpos = GetWitnessCommitmentIndex(block);
|
||||||
if (commitpos != NO_WITNESS_COMMITMENT) {
|
if (commitpos != NO_WITNESS_COMMITMENT) {
|
||||||
bool malleated = false;
|
bool malleated = false;
|
||||||
@ -4098,9 +4065,8 @@ bool CChainState::NeedsRedownload() const
|
|||||||
|
|
||||||
// At and above m_params.SegwitHeight, segwit consensus rules must be validated
|
// At and above m_params.SegwitHeight, segwit consensus rules must be validated
|
||||||
CBlockIndex* block{m_chain.Tip()};
|
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)) {
|
if (!(block->nStatus & BLOCK_OPT_WITNESS)) {
|
||||||
// block is insufficiently validated for a segwit client
|
// block is insufficiently validated for a segwit client
|
||||||
return true;
|
return true;
|
||||||
@ -4130,7 +4096,7 @@ void UnloadBlockIndex(CTxMemPool* mempool, ChainstateManager& chainman)
|
|||||||
nLastBlockFile = 0;
|
nLastBlockFile = 0;
|
||||||
setDirtyBlockIndex.clear();
|
setDirtyBlockIndex.clear();
|
||||||
setDirtyFileInfo.clear();
|
setDirtyFileInfo.clear();
|
||||||
versionbitscache.Clear();
|
g_versionbitscache.Clear();
|
||||||
for (int b = 0; b < VERSIONBITS_NUM_BITS; b++) {
|
for (int b = 0; b < VERSIONBITS_NUM_BITS; b++) {
|
||||||
warningcache[b].clear();
|
warningcache[b].clear();
|
||||||
}
|
}
|
||||||
@ -5002,7 +4968,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
|
|||||||
|
|
||||||
// Fake BLOCK_OPT_WITNESS so that CChainState::NeedsRedownload()
|
// Fake BLOCK_OPT_WITNESS so that CChainState::NeedsRedownload()
|
||||||
// won't ask to rewind the entire assumed-valid chain on startup.
|
// 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;
|
index->nStatus |= BLOCK_OPT_WITNESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include <sync.h>
|
#include <sync.h>
|
||||||
#include <txmempool.h> // For CTxMemPool::cs
|
#include <txmempool.h> // For CTxMemPool::cs
|
||||||
#include <txdb.h>
|
#include <txdb.h>
|
||||||
#include <versionbits.h>
|
|
||||||
#include <serialize.h>
|
#include <serialize.h>
|
||||||
#include <util/check.h>
|
#include <util/check.h>
|
||||||
#include <util/hasher.h>
|
#include <util/hasher.h>
|
||||||
@ -345,10 +344,6 @@ bool TestBlockValidity(BlockValidationState& state,
|
|||||||
bool fCheckPOW = true,
|
bool fCheckPOW = true,
|
||||||
bool fCheckMerkleRoot = true) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
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. */
|
/** 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);
|
void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams);
|
||||||
|
|
||||||
@ -1024,13 +1019,6 @@ public:
|
|||||||
/** Global variable that points to the active block tree (protected by cs_main) */
|
/** Global variable that points to the active block tree (protected by cs_main) */
|
||||||
extern std::unique_ptr<CBlockTreeDB> pblocktree;
|
extern std::unique_ptr<CBlockTreeDB> pblocktree;
|
||||||
|
|
||||||
extern VersionBitsCache versionbitscache;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine what nVersion a new block should use.
|
|
||||||
*/
|
|
||||||
int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params);
|
|
||||||
|
|
||||||
using FopenFn = std::function<FILE*(const fs::path&, const char*)>;
|
using FopenFn = std::function<FILE*(const fs::path&, const char*)>;
|
||||||
|
|
||||||
/** Dump the mempool to disk. */
|
/** Dump the mempool to disk. */
|
||||||
|
@ -190,29 +190,48 @@ public:
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
|
ThresholdState VersionBitsCache::State(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
|
||||||
{
|
{
|
||||||
return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]);
|
LOCK(m_mutex);
|
||||||
|
return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, m_caches[pos]);
|
||||||
}
|
}
|
||||||
|
|
||||||
BIP9Stats VersionBitsStatistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
|
BIP9Stats VersionBitsCache::Statistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
|
||||||
{
|
{
|
||||||
return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindexPrev, params);
|
return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindexPrev, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
|
int VersionBitsCache::StateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
|
||||||
{
|
{
|
||||||
return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, cache.caches[pos]);
|
LOCK(m_mutex);
|
||||||
|
return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, m_caches[pos]);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos)
|
uint32_t VersionBitsCache::Mask(const Consensus::Params& params, Consensus::DeploymentPos pos)
|
||||||
{
|
{
|
||||||
return VersionBitsConditionChecker(pos).Mask(params);
|
return VersionBitsConditionChecker(pos).Mask(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t VersionBitsCache::ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params)
|
||||||
|
{
|
||||||
|
LOCK(m_mutex);
|
||||||
|
int32_t nVersion = VERSIONBITS_TOP_BITS;
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
|
||||||
|
Consensus::DeploymentPos pos = static_cast<Consensus::DeploymentPos>(i);
|
||||||
|
ThresholdState state = VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, m_caches[pos]);
|
||||||
|
if (state == ThresholdState::LOCKED_IN || state == ThresholdState::STARTED) {
|
||||||
|
nVersion |= Mask(params, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nVersion;
|
||||||
|
}
|
||||||
|
|
||||||
void VersionBitsCache::Clear()
|
void VersionBitsCache::Clear()
|
||||||
{
|
{
|
||||||
|
LOCK(m_mutex);
|
||||||
for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
|
for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
|
||||||
caches[d].clear();
|
m_caches[d].clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#define BITCOIN_VERSIONBITS_H
|
#define BITCOIN_VERSIONBITS_H
|
||||||
|
|
||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
|
#include <sync.h>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
/** What block version to use for new blocks (pre versionbits) */
|
/** What block version to use for new blocks (pre versionbits) */
|
||||||
@ -71,21 +73,31 @@ public:
|
|||||||
int GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const;
|
int GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** BIP 9 allows multiple softforks to be deployed in parallel. We cache per-period state for every one of them
|
/** BIP 9 allows multiple softforks to be deployed in parallel. We cache
|
||||||
* keyed by the bit position used to signal support. */
|
* per-period state for every one of them. */
|
||||||
struct VersionBitsCache
|
class VersionBitsCache
|
||||||
{
|
{
|
||||||
ThresholdConditionCache caches[Consensus::MAX_VERSION_BITS_DEPLOYMENTS];
|
private:
|
||||||
|
Mutex m_mutex;
|
||||||
|
ThresholdConditionCache m_caches[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] GUARDED_BY(m_mutex);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Get the numerical statistics for a given deployment for the signalling period that includes the block after pindexPrev. */
|
||||||
|
static BIP9Stats Statistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos);
|
||||||
|
|
||||||
|
static uint32_t Mask(const Consensus::Params& params, Consensus::DeploymentPos pos);
|
||||||
|
|
||||||
|
/** Get the BIP9 state for a given deployment for the block after pindexPrev. */
|
||||||
|
ThresholdState State(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos);
|
||||||
|
|
||||||
|
/** Get the block height at which the BIP9 deployment switched into the state for the block after pindexPrev. */
|
||||||
|
int StateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos);
|
||||||
|
|
||||||
|
/** Determine what nVersion a new block should use
|
||||||
|
*/
|
||||||
|
int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Get the BIP9 state for a given deployment at the current tip. */
|
|
||||||
ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache);
|
|
||||||
/** Get the numerical statistics for the BIP9 state for a given deployment at the current tip. */
|
|
||||||
BIP9Stats VersionBitsStatistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos);
|
|
||||||
/** Get the block height at which the BIP9 deployment switched into the state for the block building on the current tip. */
|
|
||||||
int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache);
|
|
||||||
uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos);
|
|
||||||
|
|
||||||
#endif // BITCOIN_VERSIONBITS_H
|
#endif // BITCOIN_VERSIONBITS_H
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
// Copyright (c) 2016-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.
|
|
||||||
|
|
||||||
#include <versionbitsinfo.h>
|
|
||||||
|
|
||||||
#include <consensus/params.h>
|
|
||||||
|
|
||||||
const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = {
|
|
||||||
{
|
|
||||||
/*.name =*/ "testdummy",
|
|
||||||
/*.gbt_force =*/ true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
/*.name =*/ "taproot",
|
|
||||||
/*.gbt_force =*/ true,
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,17 +0,0 @@
|
|||||||
// Copyright (c) 2016-2018 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_VERSIONBITSINFO_H
|
|
||||||
#define BITCOIN_VERSIONBITSINFO_H
|
|
||||||
|
|
||||||
struct VBDeploymentInfo {
|
|
||||||
/** Deployment name */
|
|
||||||
const char *name;
|
|
||||||
/** Whether GBT clients can safely ignore this rule in simplified usage */
|
|
||||||
bool gbt_force;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const struct VBDeploymentInfo VersionBitsDeploymentInfo[];
|
|
||||||
|
|
||||||
#endif // BITCOIN_VERSIONBITSINFO_H
|
|
Loading…
Reference in New Issue
Block a user