mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-10 20:03:34 -03:00
Merge bitcoin/bitcoin#24595: deploymentstatus: move g_versionbitscache global to ChainstateManager
bb5c24b120
validation: move g_versionbitscache into ChainstateManager (Anthony Towns)eca22c726a
test/versionbits: make versionbitscache a parameter (Anthony Towns)d603f1d8a7
deploymentstatus: make versionbitscache a parameter (Anthony Towns)78adef1753
refactor: use chainman instead of chainParams for DeploymentActive* (Anthony Towns)deffe0df6c
deploymentstatus: allow chainman in place of consensusParams (Anthony Towns)eaa2e3f25c
validation: move UpdateUncommittedBlockStructures and GenerateCoinbaseCommitment into ChainstateManager (Anthony Towns)5c67e84d37
validation: replace ::Params() calls with chainstate/chainman member (Anthony Towns)38860f93b6
validation: remove redundant CChainParams params from ChainstateManager methods (Anthony Towns)69675ea4e7
validation: add CChainParams to ChainstateManager (Anthony Towns) Pull request description: Gives `ChainstateManager` a reference to the `CChainParams` its working on, and simplifies some of the functions that would otherwise take that as a parameter. Removes the `g_versionbitscache` global by moving it into `ChainstateManager`. ACKs for top commit: dongcarl: reACKbb5c24b120
MarcoFalke: review ACKbb5c24b120
📙 Tree-SHA512: 3fa74905e5df561e3e74bb0b8fce6085c5311e6633e7d74c0fb0c82a907f5bbb1fd4ebc5d11d4f0b1c019bb51eabb9f6e4bcc4652a696d36a5878c807b85f121
This commit is contained in:
commit
25dd4d8513
18 changed files with 200 additions and 170 deletions
|
@ -70,7 +70,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
|
||||
// SETUP: Chainstate
|
||||
ChainstateManager chainman;
|
||||
ChainstateManager chainman{chainparams};
|
||||
|
||||
auto rv = node::LoadChainstate(false,
|
||||
std::ref(chainman),
|
||||
|
@ -163,7 +163,7 @@ int main(int argc, char* argv[])
|
|||
LOCK(cs_main);
|
||||
const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock);
|
||||
if (pindex) {
|
||||
UpdateUncommittedBlockStructures(block, pindex, chainparams.GetConsensus());
|
||||
chainman.UpdateUncommittedBlockStructures(block, pindex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,7 +190,7 @@ int main(int argc, char* argv[])
|
|||
bool new_block;
|
||||
auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash());
|
||||
RegisterSharedValidationInterface(sc);
|
||||
bool accepted = chainman.ProcessNewBlock(chainparams, blockptr, /*force_processing=*/true, /*new_block=*/&new_block);
|
||||
bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*new_block=*/&new_block);
|
||||
UnregisterSharedValidationInterface(sc);
|
||||
if (!new_block && accepted) {
|
||||
std::cerr << "duplicate" << std::endl;
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
|
||||
#include <type_traits>
|
||||
|
||||
VersionBitsCache g_versionbitscache;
|
||||
|
||||
/* Basic sanity checking for BuriedDeployment/DeploymentPos enums and
|
||||
* ValidDeployment check */
|
||||
|
||||
|
|
|
@ -10,33 +10,30 @@
|
|||
|
||||
#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)
|
||||
inline bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::BuriedDeployment dep, [[maybe_unused]] VersionBitsCache& versionbitscache)
|
||||
{
|
||||
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)
|
||||
inline bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos dep, VersionBitsCache& versionbitscache)
|
||||
{
|
||||
assert(Consensus::ValidDeployment(dep));
|
||||
return ThresholdState::ACTIVE == g_versionbitscache.State(pindexPrev, params, dep);
|
||||
return ThresholdState::ACTIVE == 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)
|
||||
inline bool DeploymentActiveAt(const CBlockIndex& index, const Consensus::Params& params, Consensus::BuriedDeployment dep, [[maybe_unused]] VersionBitsCache& versionbitscache)
|
||||
{
|
||||
assert(Consensus::ValidDeployment(dep));
|
||||
return index.nHeight >= params.DeploymentHeight(dep);
|
||||
}
|
||||
|
||||
inline bool DeploymentActiveAt(const CBlockIndex& index, const Consensus::Params& params, Consensus::DeploymentPos dep)
|
||||
inline bool DeploymentActiveAt(const CBlockIndex& index, const Consensus::Params& params, Consensus::DeploymentPos dep, VersionBitsCache& versionbitscache)
|
||||
{
|
||||
assert(Consensus::ValidDeployment(dep));
|
||||
return DeploymentActiveAfter(index.pprev, params, dep);
|
||||
return DeploymentActiveAfter(index.pprev, params, dep, versionbitscache);
|
||||
}
|
||||
|
||||
/** Determine if a deployment is enabled (can ever be active) */
|
||||
|
|
|
@ -1424,7 +1424,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||
for (bool fLoaded = false; !fLoaded && !ShutdownRequested();) {
|
||||
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get(), mempool_check_ratio);
|
||||
|
||||
node.chainman = std::make_unique<ChainstateManager>();
|
||||
node.chainman = std::make_unique<ChainstateManager>(chainparams);
|
||||
ChainstateManager& chainman = *node.chainman;
|
||||
|
||||
const bool fReset = fReindex;
|
||||
|
|
|
@ -1110,7 +1110,6 @@ void PeerManagerImpl::FindNextBlocksToDownload(NodeId nodeid, unsigned int count
|
|||
if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
|
||||
return;
|
||||
|
||||
const Consensus::Params& consensusParams = m_chainparams.GetConsensus();
|
||||
std::vector<const CBlockIndex*> vToFetch;
|
||||
const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
|
||||
// Never fetch further than the best block we know the peer has, or more than BLOCK_DOWNLOAD_WINDOW + 1 beyond the last
|
||||
|
@ -1140,7 +1139,7 @@ void PeerManagerImpl::FindNextBlocksToDownload(NodeId nodeid, unsigned int count
|
|||
// We consider the chain that this peer is on invalid.
|
||||
return;
|
||||
}
|
||||
if (!State(nodeid)->fHaveWitness && DeploymentActiveAt(*pindex, consensusParams, Consensus::DEPLOYMENT_SEGWIT)) {
|
||||
if (!State(nodeid)->fHaveWitness && DeploymentActiveAt(*pindex, m_chainman, Consensus::DEPLOYMENT_SEGWIT)) {
|
||||
// We wouldn't download this block or its descendants from this peer.
|
||||
return;
|
||||
}
|
||||
|
@ -1641,7 +1640,7 @@ void PeerManagerImpl::NewPoWValidBlock(const CBlockIndex *pindex, const std::sha
|
|||
return;
|
||||
m_highest_fast_announce = pindex->nHeight;
|
||||
|
||||
bool fWitnessEnabled = DeploymentActiveAt(*pindex, m_chainparams.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT);
|
||||
bool fWitnessEnabled = DeploymentActiveAt(*pindex, m_chainman, Consensus::DEPLOYMENT_SEGWIT);
|
||||
uint256 hashBlock(pblock->GetHash());
|
||||
const std::shared_future<CSerializedNetMsg> lazy_ser{
|
||||
std::async(std::launch::deferred, [&] { return msgMaker.Make(NetMsgType::CMPCTBLOCK, *pcmpctblock); })};
|
||||
|
@ -2214,7 +2213,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
|
|||
}
|
||||
|
||||
BlockValidationState state;
|
||||
if (!m_chainman.ProcessNewBlockHeaders(headers, state, m_chainparams, &pindexLast)) {
|
||||
if (!m_chainman.ProcessNewBlockHeaders(headers, state, &pindexLast)) {
|
||||
if (state.IsInvalid()) {
|
||||
MaybePunishNodeForBlock(pfrom.GetId(), state, via_compact_block, "invalid header received");
|
||||
return;
|
||||
|
@ -2258,7 +2257,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()) &&
|
||||
(!DeploymentActiveAt(*pindexWalk, m_chainparams.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT) || State(pfrom.GetId())->fHaveWitness)) {
|
||||
(!DeploymentActiveAt(*pindexWalk, m_chainman, Consensus::DEPLOYMENT_SEGWIT) || State(pfrom.GetId())->fHaveWitness)) {
|
||||
// We don't have this block, and it's not yet in flight.
|
||||
vToFetch.push_back(pindexWalk);
|
||||
}
|
||||
|
@ -2591,7 +2590,7 @@ void PeerManagerImpl::ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv)
|
|||
void PeerManagerImpl::ProcessBlock(CNode& node, const std::shared_ptr<const CBlock>& block, bool force_processing)
|
||||
{
|
||||
bool new_block{false};
|
||||
m_chainman.ProcessNewBlock(m_chainparams, block, force_processing, &new_block);
|
||||
m_chainman.ProcessNewBlock(block, force_processing, &new_block);
|
||||
if (new_block) {
|
||||
node.m_last_block_time = GetTime<std::chrono::seconds>();
|
||||
} else {
|
||||
|
@ -3569,7 +3568,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
|
||||
const CBlockIndex *pindex = nullptr;
|
||||
BlockValidationState state;
|
||||
if (!m_chainman.ProcessNewBlockHeaders({cmpctblock.header}, state, m_chainparams, &pindex)) {
|
||||
if (!m_chainman.ProcessNewBlockHeaders({cmpctblock.header}, state, &pindex)) {
|
||||
if (state.IsInvalid()) {
|
||||
MaybePunishNodeForBlock(pfrom.GetId(), state, /*via_compact_block=*/true, "invalid header via cmpctblock");
|
||||
return;
|
||||
|
@ -3629,7 +3628,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
return;
|
||||
}
|
||||
|
||||
if (DeploymentActiveAt(*pindex, m_chainparams.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT) && !nodestate->fSupportsDesiredCmpctVersion) {
|
||||
if (DeploymentActiveAt(*pindex, m_chainman, Consensus::DEPLOYMENT_SEGWIT) && !nodestate->fSupportsDesiredCmpctVersion) {
|
||||
// Don't bother trying to process compact blocks from v1 peers
|
||||
// after segwit activates.
|
||||
return;
|
||||
|
|
|
@ -51,7 +51,7 @@ void RegenerateCommitments(CBlock& block, ChainstateManager& chainman)
|
|||
block.vtx.at(0) = MakeTransactionRef(tx);
|
||||
|
||||
const CBlockIndex* prev_block = WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock));
|
||||
GenerateCoinbaseCommitment(block, prev_block, Params().GetConsensus());
|
||||
chainman.GenerateCoinbaseCommitment(block, prev_block);
|
||||
|
||||
block.hashMerkleRoot = BlockMerkleRoot(block);
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
|||
assert(pindexPrev != nullptr);
|
||||
nHeight = pindexPrev->nHeight + 1;
|
||||
|
||||
pblock->nVersion = g_versionbitscache.ComputeBlockVersion(pindexPrev, chainparams.GetConsensus());
|
||||
pblock->nVersion = m_chainstate.m_chainman.m_versionbitscache.ComputeBlockVersion(pindexPrev, chainparams.GetConsensus());
|
||||
// -regtest only: allow overriding block.nVersion with
|
||||
// -blockversion=N to test forking scenarios
|
||||
if (chainparams.MineBlocksOnDemand()) {
|
||||
|
@ -154,7 +154,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
|||
coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus());
|
||||
coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0;
|
||||
pblock->vtx[0] = MakeTransactionRef(std::move(coinbaseTx));
|
||||
pblocktemplate->vchCoinbaseCommitment = GenerateCoinbaseCommitment(*pblock, pindexPrev, chainparams.GetConsensus());
|
||||
pblocktemplate->vchCoinbaseCommitment = m_chainstate.m_chainman.GenerateCoinbaseCommitment(*pblock, pindexPrev);
|
||||
pblocktemplate->vTxFees[0] = -nFees;
|
||||
|
||||
LogPrintf("CreateNewBlock(): block weight: %u txs: %u fees: %ld sigops %d\n", GetBlockWeight(*pblock), nBlockTx, nFees, nBlockSigOpsCost);
|
||||
|
|
|
@ -1064,26 +1064,26 @@ static RPCHelpMan verifychain()
|
|||
};
|
||||
}
|
||||
|
||||
static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softforks, const Consensus::Params& params, Consensus::BuriedDeployment dep)
|
||||
static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softforks, const ChainstateManager& chainman, Consensus::BuriedDeployment dep)
|
||||
{
|
||||
// For buried deployments.
|
||||
|
||||
if (!DeploymentEnabled(params, dep)) return;
|
||||
if (!DeploymentEnabled(chainman, dep)) return;
|
||||
|
||||
UniValue rv(UniValue::VOBJ);
|
||||
rv.pushKV("type", "buried");
|
||||
// getdeploymentinfo reports the softfork as active from when the chain height is
|
||||
// one below the activation height
|
||||
rv.pushKV("active", DeploymentActiveAfter(blockindex, params, dep));
|
||||
rv.pushKV("height", params.DeploymentHeight(dep));
|
||||
rv.pushKV("active", DeploymentActiveAfter(blockindex, chainman, dep));
|
||||
rv.pushKV("height", chainman.GetConsensus().DeploymentHeight(dep));
|
||||
softforks.pushKV(DeploymentName(dep), rv);
|
||||
}
|
||||
|
||||
static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
|
||||
static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softforks, const ChainstateManager& chainman, Consensus::DeploymentPos id)
|
||||
{
|
||||
// For BIP9 deployments.
|
||||
|
||||
if (!DeploymentEnabled(consensusParams, id)) return;
|
||||
if (!DeploymentEnabled(chainman, id)) return;
|
||||
if (blockindex == nullptr) return;
|
||||
|
||||
auto get_state_name = [](const ThresholdState state) -> std::string {
|
||||
|
@ -1099,29 +1099,29 @@ static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softfo
|
|||
|
||||
UniValue bip9(UniValue::VOBJ);
|
||||
|
||||
const ThresholdState next_state = g_versionbitscache.State(blockindex, consensusParams, id);
|
||||
const ThresholdState current_state = g_versionbitscache.State(blockindex->pprev, consensusParams, id);
|
||||
const ThresholdState next_state = chainman.m_versionbitscache.State(blockindex, chainman.GetConsensus(), id);
|
||||
const ThresholdState current_state = chainman.m_versionbitscache.State(blockindex->pprev, chainman.GetConsensus(), id);
|
||||
|
||||
const bool has_signal = (ThresholdState::STARTED == current_state || ThresholdState::LOCKED_IN == current_state);
|
||||
|
||||
// BIP9 parameters
|
||||
if (has_signal) {
|
||||
bip9.pushKV("bit", consensusParams.vDeployments[id].bit);
|
||||
bip9.pushKV("bit", chainman.GetConsensus().vDeployments[id].bit);
|
||||
}
|
||||
bip9.pushKV("start_time", consensusParams.vDeployments[id].nStartTime);
|
||||
bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
|
||||
bip9.pushKV("min_activation_height", consensusParams.vDeployments[id].min_activation_height);
|
||||
bip9.pushKV("start_time", chainman.GetConsensus().vDeployments[id].nStartTime);
|
||||
bip9.pushKV("timeout", chainman.GetConsensus().vDeployments[id].nTimeout);
|
||||
bip9.pushKV("min_activation_height", chainman.GetConsensus().vDeployments[id].min_activation_height);
|
||||
|
||||
// BIP9 status
|
||||
bip9.pushKV("status", get_state_name(current_state));
|
||||
bip9.pushKV("since", g_versionbitscache.StateSinceHeight(blockindex->pprev, consensusParams, id));
|
||||
bip9.pushKV("since", chainman.m_versionbitscache.StateSinceHeight(blockindex->pprev, chainman.GetConsensus(), id));
|
||||
bip9.pushKV("status_next", get_state_name(next_state));
|
||||
|
||||
// BIP9 signalling status, if applicable
|
||||
if (has_signal) {
|
||||
UniValue statsUV(UniValue::VOBJ);
|
||||
std::vector<bool> signals;
|
||||
BIP9Stats statsStruct = g_versionbitscache.Statistics(blockindex, consensusParams, id, &signals);
|
||||
BIP9Stats statsStruct = chainman.m_versionbitscache.Statistics(blockindex, chainman.GetConsensus(), id, &signals);
|
||||
statsUV.pushKV("period", statsStruct.period);
|
||||
statsUV.pushKV("elapsed", statsStruct.elapsed);
|
||||
statsUV.pushKV("count", statsStruct.count);
|
||||
|
@ -1142,7 +1142,7 @@ static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softfo
|
|||
UniValue rv(UniValue::VOBJ);
|
||||
rv.pushKV("type", "bip9");
|
||||
if (ThresholdState::ACTIVE == next_state) {
|
||||
rv.pushKV("height", g_versionbitscache.StateSinceHeight(blockindex, consensusParams, id));
|
||||
rv.pushKV("height", chainman.m_versionbitscache.StateSinceHeight(blockindex, chainman.GetConsensus(), id));
|
||||
}
|
||||
rv.pushKV("active", ThresholdState::ACTIVE == next_state);
|
||||
rv.pushKV("bip9", bip9);
|
||||
|
@ -1152,7 +1152,7 @@ static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softfo
|
|||
|
||||
namespace {
|
||||
/* TODO: when -deprecatedrpc=softforks is removed, drop these */
|
||||
UniValue DeploymentInfo(const CBlockIndex* tip, const Consensus::Params& consensusParams);
|
||||
UniValue DeploymentInfo(const CBlockIndex* tip, const ChainstateManager& chainman);
|
||||
extern const std::vector<RPCResult> RPCHelpForDeployment;
|
||||
}
|
||||
|
||||
|
@ -1227,8 +1227,7 @@ RPCHelpMan getblockchaininfo()
|
|||
}
|
||||
|
||||
if (IsDeprecatedRPCEnabled("softforks")) {
|
||||
const Consensus::Params& consensusParams = Params().GetConsensus();
|
||||
obj.pushKV("softforks", DeploymentInfo(&tip, consensusParams));
|
||||
obj.pushKV("softforks", DeploymentInfo(&tip, chainman));
|
||||
}
|
||||
|
||||
obj.pushKV("warnings", GetWarnings(false).original);
|
||||
|
@ -1263,16 +1262,16 @@ const std::vector<RPCResult> RPCHelpForDeployment{
|
|||
}},
|
||||
};
|
||||
|
||||
UniValue DeploymentInfo(const CBlockIndex* blockindex, const Consensus::Params& consensusParams)
|
||||
UniValue DeploymentInfo(const CBlockIndex* blockindex, const ChainstateManager& chainman)
|
||||
{
|
||||
UniValue softforks(UniValue::VOBJ);
|
||||
SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB);
|
||||
SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_DERSIG);
|
||||
SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_CLTV);
|
||||
SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_CSV);
|
||||
SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_SEGWIT);
|
||||
SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_TESTDUMMY);
|
||||
SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_TAPROOT);
|
||||
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_HEIGHTINCB);
|
||||
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_DERSIG);
|
||||
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_CLTV);
|
||||
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_CSV);
|
||||
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_SEGWIT);
|
||||
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_TESTDUMMY);
|
||||
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_TAPROOT);
|
||||
return softforks;
|
||||
}
|
||||
} // anon namespace
|
||||
|
@ -1311,12 +1310,10 @@ static RPCHelpMan getdeploymentinfo()
|
|||
}
|
||||
}
|
||||
|
||||
const Consensus::Params& consensusParams = Params().GetConsensus();
|
||||
|
||||
UniValue deploymentinfo(UniValue::VOBJ);
|
||||
deploymentinfo.pushKV("hash", blockindex->GetBlockHash().ToString());
|
||||
deploymentinfo.pushKV("height", blockindex->nHeight);
|
||||
deploymentinfo.pushKV("deployments", DeploymentInfo(blockindex, consensusParams));
|
||||
deploymentinfo.pushKV("deployments", DeploymentInfo(blockindex, chainman));
|
||||
return deploymentinfo;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -133,7 +133,7 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t&
|
|||
}
|
||||
|
||||
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);
|
||||
if (!chainman.ProcessNewBlock(chainparams, shared_pblock, true, nullptr)) {
|
||||
if (!chainman.ProcessNewBlock(shared_pblock, true, nullptr)) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
|
||||
}
|
||||
|
||||
|
@ -770,7 +770,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 = !DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT);
|
||||
const bool fPreSegWit = !DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_SEGWIT);
|
||||
|
||||
UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
|
||||
|
||||
|
@ -836,7 +836,7 @@ static RPCHelpMan getblocktemplate()
|
|||
UniValue vbavailable(UniValue::VOBJ);
|
||||
for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
|
||||
Consensus::DeploymentPos pos = Consensus::DeploymentPos(j);
|
||||
ThresholdState state = g_versionbitscache.State(pindexPrev, consensusParams, pos);
|
||||
ThresholdState state = chainman.m_versionbitscache.State(pindexPrev, consensusParams, pos);
|
||||
switch (state) {
|
||||
case ThresholdState::DEFINED:
|
||||
case ThresholdState::FAILED:
|
||||
|
@ -844,7 +844,7 @@ static RPCHelpMan getblocktemplate()
|
|||
break;
|
||||
case ThresholdState::LOCKED_IN:
|
||||
// Ensure bit is set in block version
|
||||
pblock->nVersion |= g_versionbitscache.Mask(consensusParams, pos);
|
||||
pblock->nVersion |= chainman.m_versionbitscache.Mask(consensusParams, pos);
|
||||
[[fallthrough]];
|
||||
case ThresholdState::STARTED:
|
||||
{
|
||||
|
@ -853,7 +853,7 @@ static RPCHelpMan getblocktemplate()
|
|||
if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
|
||||
if (!vbinfo.gbt_force) {
|
||||
// If the client doesn't support this, don't indicate it in the [default] version
|
||||
pblock->nVersion &= ~g_versionbitscache.Mask(consensusParams, pos);
|
||||
pblock->nVersion &= ~chainman.m_versionbitscache.Mask(consensusParams, pos);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -993,14 +993,14 @@ static RPCHelpMan submitblock()
|
|||
LOCK(cs_main);
|
||||
const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock);
|
||||
if (pindex) {
|
||||
UpdateUncommittedBlockStructures(block, pindex, Params().GetConsensus());
|
||||
chainman.UpdateUncommittedBlockStructures(block, pindex);
|
||||
}
|
||||
}
|
||||
|
||||
bool new_block;
|
||||
auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash());
|
||||
RegisterSharedValidationInterface(sc);
|
||||
bool accepted = chainman.ProcessNewBlock(Params(), blockptr, /*force_processing=*/true, /*new_block=*/&new_block);
|
||||
bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*new_block=*/&new_block);
|
||||
UnregisterSharedValidationInterface(sc);
|
||||
if (!new_block && accepted) {
|
||||
return "duplicate";
|
||||
|
@ -1042,7 +1042,7 @@ static RPCHelpMan submitheader()
|
|||
}
|
||||
|
||||
BlockValidationState state;
|
||||
chainman.ProcessNewBlockHeaders({h}, state, Params());
|
||||
chainman.ProcessNewBlockHeaders({h}, state);
|
||||
if (state.IsValid()) return NullUniValue;
|
||||
if (state.IsError()) {
|
||||
throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString());
|
||||
|
|
|
@ -101,7 +101,7 @@ bool BuildChainTestingSetup::BuildChain(const CBlockIndex* pindex,
|
|||
CBlockHeader header = block->GetBlockHeader();
|
||||
|
||||
BlockValidationState state;
|
||||
if (!Assert(m_node.chainman)->ProcessNewBlockHeaders({header}, state, Params(), &pindex)) {
|
||||
if (!Assert(m_node.chainman)->ProcessNewBlockHeaders({header}, state, &pindex)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
|
|||
uint256 chainA_last_header = last_header;
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
const auto& block = chainA[i];
|
||||
BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(Params(), block, true, nullptr));
|
||||
BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(block, true, nullptr));
|
||||
}
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
const auto& block = chainA[i];
|
||||
|
@ -196,7 +196,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
|
|||
uint256 chainB_last_header = last_header;
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
const auto& block = chainB[i];
|
||||
BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(Params(), block, true, nullptr));
|
||||
BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(block, true, nullptr));
|
||||
}
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
const auto& block = chainB[i];
|
||||
|
@ -227,7 +227,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
|
|||
// Reorg back to chain A.
|
||||
for (size_t i = 2; i < 4; i++) {
|
||||
const auto& block = chainA[i];
|
||||
BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(Params(), block, true, nullptr));
|
||||
BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(block, true, nullptr));
|
||||
}
|
||||
|
||||
// Check that chain A and B blocks can be retrieved.
|
||||
|
|
|
@ -58,7 +58,7 @@ FUZZ_TARGET_INIT(utxo_snapshot, initialize_chain)
|
|||
if (fuzzed_data_provider.ConsumeBool()) {
|
||||
for (const auto& block : *g_chain) {
|
||||
BlockValidationState dummy;
|
||||
bool processed{chainman.ProcessNewBlockHeaders({*block}, dummy, ::Params())};
|
||||
bool processed{chainman.ProcessNewBlockHeaders({*block}, dummy)};
|
||||
Assert(processed);
|
||||
const auto* index{WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(block->GetHash()))};
|
||||
Assert(index);
|
||||
|
|
|
@ -587,7 +587,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
pblock->nNonce = bi.nonce;
|
||||
}
|
||||
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock);
|
||||
BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(chainparams, shared_pblock, true, nullptr));
|
||||
BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(shared_pblock, true, nullptr));
|
||||
pblock->hashPrevBlock = pblock->GetHash();
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ CTxIn MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
|
|||
assert(block->nNonce);
|
||||
}
|
||||
|
||||
bool processed{Assert(node.chainman)->ProcessNewBlock(Params(), block, true, nullptr)};
|
||||
bool processed{Assert(node.chainman)->ProcessNewBlock(block, true, nullptr)};
|
||||
assert(processed);
|
||||
|
||||
return CTxIn{block->vtx[0]->GetHash(), 0};
|
||||
|
|
|
@ -151,6 +151,8 @@ BasicTestingSetup::~BasicTestingSetup()
|
|||
ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args)
|
||||
: BasicTestingSetup(chainName, extra_args)
|
||||
{
|
||||
const CChainParams& chainparams = Params();
|
||||
|
||||
// We have to run a scheduler thread to prevent ActivateBestChain
|
||||
// from blocking due to queue overrun.
|
||||
m_node.scheduler = std::make_unique<CScheduler>();
|
||||
|
@ -162,7 +164,7 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve
|
|||
|
||||
m_cache_sizes = CalculateCacheSizes(m_args);
|
||||
|
||||
m_node.chainman = std::make_unique<ChainstateManager>();
|
||||
m_node.chainman = std::make_unique<ChainstateManager>(chainparams);
|
||||
m_node.chainman->m_blockman.m_block_tree_db = std::make_unique<CBlockTreeDB>(m_cache_sizes.block_tree_db, true);
|
||||
|
||||
// Start script-checking threads. Set g_parallel_script_checks to true so they are used.
|
||||
|
@ -298,10 +300,9 @@ CBlock TestChain100Setup::CreateAndProcessBlock(
|
|||
chainstate = &Assert(m_node.chainman)->ActiveChainstate();
|
||||
}
|
||||
|
||||
const CChainParams& chainparams = Params();
|
||||
const CBlock block = this->CreateBlock(txns, scriptPubKey, *chainstate);
|
||||
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);
|
||||
Assert(m_node.chainman)->ProcessNewBlock(chainparams, shared_pblock, true, nullptr);
|
||||
Assert(m_node.chainman)->ProcessNewBlock(shared_pblock, true, nullptr);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ std::shared_ptr<CBlock> MinerTestingSetup::Block(const uint256& prev_hash)
|
|||
std::shared_ptr<CBlock> MinerTestingSetup::FinalizeBlock(std::shared_ptr<CBlock> pblock)
|
||||
{
|
||||
const CBlockIndex* prev_block{WITH_LOCK(::cs_main, return m_node.chainman->m_blockman.LookupBlockIndex(pblock->hashPrevBlock))};
|
||||
GenerateCoinbaseCommitment(*pblock, prev_block, Params().GetConsensus());
|
||||
m_node.chainman->GenerateCoinbaseCommitment(*pblock, prev_block);
|
||||
|
||||
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
|
||||
|
||||
|
@ -100,7 +100,7 @@ std::shared_ptr<CBlock> MinerTestingSetup::FinalizeBlock(std::shared_ptr<CBlock>
|
|||
// submit block header, so that miner can get the block height from the
|
||||
// global state and the node has the topology of the chain
|
||||
BlockValidationState ignored;
|
||||
BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlockHeaders({pblock->GetBlockHeader()}, ignored, Params()));
|
||||
BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlockHeaders({pblock->GetBlockHeader()}, ignored));
|
||||
|
||||
return pblock;
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
|
|||
|
||||
bool ignored;
|
||||
// Connect the genesis block and drain any outstanding events
|
||||
BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(Params(), std::make_shared<CBlock>(Params().GenesisBlock()), true, &ignored));
|
||||
BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(std::make_shared<CBlock>(Params().GenesisBlock()), true, &ignored));
|
||||
SyncWithValidationInterfaceQueue();
|
||||
|
||||
// subscribe to events (this subscriber will validate event ordering)
|
||||
|
@ -179,13 +179,13 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
|
|||
FastRandomContext insecure;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
auto block = blocks[insecure.randrange(blocks.size() - 1)];
|
||||
Assert(m_node.chainman)->ProcessNewBlock(Params(), block, true, &ignored);
|
||||
Assert(m_node.chainman)->ProcessNewBlock(block, true, &ignored);
|
||||
}
|
||||
|
||||
// to make sure that eventually we process the full chain - do it here
|
||||
for (auto block : blocks) {
|
||||
if (block->vtx.size() == 1) {
|
||||
bool processed = Assert(m_node.chainman)->ProcessNewBlock(Params(), block, true, &ignored);
|
||||
bool processed = Assert(m_node.chainman)->ProcessNewBlock(block, true, &ignored);
|
||||
assert(processed);
|
||||
}
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
|
|||
{
|
||||
bool ignored;
|
||||
auto ProcessBlock = [&](std::shared_ptr<const CBlock> block) -> bool {
|
||||
return Assert(m_node.chainman)->ProcessNewBlock(Params(), block, /*force_processing=*/true, /*new_block=*/&ignored);
|
||||
return Assert(m_node.chainman)->ProcessNewBlock(block, /*force_processing=*/true, /*new_block=*/&ignored);
|
||||
};
|
||||
|
||||
// Process all mined blocks
|
||||
|
|
|
@ -22,7 +22,8 @@ BOOST_FIXTURE_TEST_SUITE(validation_chainstate_tests, TestingSetup)
|
|||
//!
|
||||
BOOST_AUTO_TEST_CASE(validation_chainstate_resize_caches)
|
||||
{
|
||||
ChainstateManager manager;
|
||||
const CChainParams& chainparams = Params();
|
||||
ChainstateManager manager(chainparams);
|
||||
WITH_LOCK(::cs_main, manager.m_blockman.m_block_tree_db = std::make_unique<CBlockTreeDB>(1 << 20, true));
|
||||
CTxMemPool mempool;
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include <chain.h>
|
||||
#include <chainparams.h>
|
||||
#include <consensus/params.h>
|
||||
#include <deploymentstatus.h>
|
||||
#include <test/util/setup_common.h>
|
||||
#include <validation.h>
|
||||
#include <versionbits.h>
|
||||
|
@ -257,10 +256,10 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
|
|||
}
|
||||
|
||||
/** Check that ComputeBlockVersion will set the appropriate bit correctly */
|
||||
static void check_computeblockversion(const Consensus::Params& params, Consensus::DeploymentPos dep)
|
||||
static void check_computeblockversion(VersionBitsCache& versionbitscache, const Consensus::Params& params, Consensus::DeploymentPos dep)
|
||||
{
|
||||
// This implicitly uses g_versionbitscache, so clear it every time
|
||||
g_versionbitscache.Clear();
|
||||
// Clear the cache everytime
|
||||
versionbitscache.Clear();
|
||||
|
||||
int64_t bit = params.vDeployments[dep].bit;
|
||||
int64_t nStartTime = params.vDeployments[dep].nStartTime;
|
||||
|
@ -268,7 +267,7 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
|
|||
int min_activation_height = params.vDeployments[dep].min_activation_height;
|
||||
|
||||
// should not be any signalling for first block
|
||||
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(nullptr, params), VERSIONBITS_TOP_BITS);
|
||||
BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(nullptr, params), VERSIONBITS_TOP_BITS);
|
||||
|
||||
// always/never active deployments shouldn't need to be tested further
|
||||
if (nStartTime == Consensus::BIP9Deployment::ALWAYS_ACTIVE ||
|
||||
|
@ -288,7 +287,7 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
|
|||
// Check min_activation_height is on a retarget boundary
|
||||
BOOST_REQUIRE_EQUAL(min_activation_height % params.nMinerConfirmationWindow, 0U);
|
||||
|
||||
const uint32_t bitmask{g_versionbitscache.Mask(params, dep)};
|
||||
const uint32_t bitmask{versionbitscache.Mask(params, dep)};
|
||||
BOOST_CHECK_EQUAL(bitmask, uint32_t{1} << bit);
|
||||
|
||||
// In the first chain, test that the bit is set by CBV until it has failed.
|
||||
|
@ -307,9 +306,9 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
|
|||
// earlier time, so will transition from DEFINED to STARTED at the
|
||||
// end of the first period by mining blocks at nTime == 0
|
||||
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||
BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
// then we'll keep mining at nStartTime...
|
||||
} else {
|
||||
// use a time 1s earlier than start time to check we stay DEFINED
|
||||
|
@ -317,28 +316,28 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
|
|||
|
||||
// Start generating blocks before nStartTime
|
||||
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||
BOOST_CHECK_EQUAL(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.
|
||||
for (uint32_t i = 1; i < params.nMinerConfirmationWindow - 4; i++) {
|
||||
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||
BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||
}
|
||||
// Now mine 5 more blocks at the start time -- MTP should not have passed yet, so
|
||||
// CBV should still not yet set the bit.
|
||||
nTime = nStartTime;
|
||||
for (uint32_t i = params.nMinerConfirmationWindow - 4; i <= params.nMinerConfirmationWindow; i++) {
|
||||
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||
BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||
}
|
||||
// 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();
|
||||
// so ComputeBlockVersion should now set the bit,
|
||||
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
// and should also be using the VERSIONBITS_TOP_BITS.
|
||||
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
|
||||
BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
|
||||
|
||||
// Check that ComputeBlockVersion will set the bit until nTimeout
|
||||
nTime += 600;
|
||||
|
@ -347,8 +346,8 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
|
|||
// These blocks are all before nTimeout is reached.
|
||||
while (nTime < nTimeout && blocksToMine > 0) {
|
||||
lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
|
||||
BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
|
||||
blocksToMine--;
|
||||
nTime += 600;
|
||||
nHeight += 1;
|
||||
|
@ -362,7 +361,7 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
|
|||
// finish the last period before we start timing out
|
||||
while (nHeight % params.nMinerConfirmationWindow != 0) {
|
||||
lastBlock = firstChain.Mine(nHeight+1, nTime - 1, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
nHeight += 1;
|
||||
}
|
||||
|
||||
|
@ -370,12 +369,12 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
|
|||
// the bit until the period transition.
|
||||
for (uint32_t i = 0; i < params.nMinerConfirmationWindow - 1; i++) {
|
||||
lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
nHeight += 1;
|
||||
}
|
||||
// The next block should trigger no longer setting the bit.
|
||||
lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||
BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||
}
|
||||
|
||||
// On a new chain:
|
||||
|
@ -386,34 +385,36 @@ 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
|
||||
// next period.
|
||||
lastBlock = secondChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
|
||||
// Mine another period worth of blocks, signaling the new bit.
|
||||
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.
|
||||
// We keep setting the bit for one more period though, until activation.
|
||||
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
|
||||
// Now check that we keep mining the block until the end of this period, and
|
||||
// then stop at the beginning of the next period.
|
||||
lastBlock = secondChain.Mine((params.nMinerConfirmationWindow * 3) - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
lastBlock = secondChain.Mine(params.nMinerConfirmationWindow * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||
|
||||
if (lastBlock->nHeight + 1 < min_activation_height) {
|
||||
// check signalling continues while min_activation_height is not reached
|
||||
lastBlock = secondChain.Mine(min_activation_height - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
|
||||
BOOST_CHECK((g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
|
||||
// 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();
|
||||
}
|
||||
|
||||
// Check that we don't signal after activation
|
||||
BOOST_CHECK_EQUAL(g_versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||
BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
|
||||
{
|
||||
VersionBitsCache vbcache; // don't use chainman versionbitscache since we want custom chain params
|
||||
|
||||
// check that any deployment on any chain can conceivably reach both
|
||||
// ACTIVE and FAILED states in roughly the way we expect
|
||||
for (const auto& chain_name : {CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::SIGNET, CBaseChainParams::REGTEST}) {
|
||||
|
@ -426,10 +427,10 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
|
|||
// not take precedence over STARTED/LOCKED_IN. So all softforks on
|
||||
// the same bit might overlap, even when non-overlapping start-end
|
||||
// times are picked.
|
||||
const uint32_t dep_mask{g_versionbitscache.Mask(chainParams->GetConsensus(), dep)};
|
||||
const uint32_t dep_mask{vbcache.Mask(chainParams->GetConsensus(), dep)};
|
||||
BOOST_CHECK(!(chain_all_vbits & dep_mask));
|
||||
chain_all_vbits |= dep_mask;
|
||||
check_computeblockversion(chainParams->GetConsensus(), dep);
|
||||
check_computeblockversion(vbcache, chainParams->GetConsensus(), dep);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -439,7 +440,7 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
|
|||
ArgsManager args;
|
||||
args.ForceSetArg("-vbparams", "testdummy:1199145601:1230767999"); // January 1, 2008 - December 31, 2008
|
||||
const auto chainParams = CreateChainParams(args, CBaseChainParams::REGTEST);
|
||||
check_computeblockversion(chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY);
|
||||
check_computeblockversion(vbcache, chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -449,7 +450,7 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
|
|||
ArgsManager args;
|
||||
args.ForceSetArg("-vbparams", "testdummy:1199145601:1230767999:403200"); // January 1, 2008 - December 31, 2008, min act height 403200
|
||||
const auto chainParams = CreateChainParams(args, CBaseChainParams::REGTEST);
|
||||
check_computeblockversion(chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY);
|
||||
check_computeblockversion(vbcache, chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include <consensus/tx_verify.h>
|
||||
#include <consensus/validation.h>
|
||||
#include <cuckoocache.h>
|
||||
#include <deploymentstatus.h>
|
||||
#include <flatfile.h>
|
||||
#include <hash.h>
|
||||
#include <logging.h>
|
||||
|
@ -262,7 +261,7 @@ bool CheckSequenceLocksAtTip(CBlockIndex* tip,
|
|||
}
|
||||
|
||||
// Returns the script flags which should be checked for a given block
|
||||
static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const Consensus::Params& chainparams);
|
||||
static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman);
|
||||
|
||||
static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache, size_t limit, std::chrono::seconds age)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs)
|
||||
|
@ -1027,7 +1026,6 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws)
|
|||
const CTransaction& tx = *ws.m_ptx;
|
||||
const uint256& hash = ws.m_hash;
|
||||
TxValidationState& state = ws.m_state;
|
||||
const CChainParams& chainparams = args.m_chainparams;
|
||||
|
||||
// Check again against the current block tip's script verification
|
||||
// flags to cache our script execution flags. This is, of course,
|
||||
|
@ -1044,7 +1042,7 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws)
|
|||
// There is a similar check in CreateNewBlock() to prevent creating
|
||||
// invalid blocks (using TestBlockValidity), however allowing such
|
||||
// transactions into the mempool can be exploited as a DoS attack.
|
||||
unsigned int currentBlockScriptVerifyFlags{GetBlockScriptFlags(*m_active_chainstate.m_chain.Tip(), chainparams.GetConsensus())};
|
||||
unsigned int currentBlockScriptVerifyFlags{GetBlockScriptFlags(*m_active_chainstate.m_chain.Tip(), m_active_chainstate.m_chainman)};
|
||||
if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags,
|
||||
ws.m_precomputed_txdata, m_active_chainstate.CoinsTip())) {
|
||||
LogPrintf("BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s\n", hash.ToString(), state.ToString());
|
||||
|
@ -1457,7 +1455,7 @@ PackageMempoolAcceptResult ProcessNewPackage(CChainState& active_chainstate, CTx
|
|||
assert(std::all_of(package.cbegin(), package.cend(), [](const auto& tx){return tx != nullptr;}));
|
||||
|
||||
std::vector<COutPoint> coins_to_uncache;
|
||||
const CChainParams& chainparams = Params();
|
||||
const CChainParams& chainparams = active_chainstate.m_params;
|
||||
const auto result = [&]() EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
|
||||
AssertLockHeld(cs_main);
|
||||
if (test_accept) {
|
||||
|
@ -1515,7 +1513,7 @@ CChainState::CChainState(
|
|||
std::optional<uint256> from_snapshot_blockhash)
|
||||
: m_mempool(mempool),
|
||||
m_blockman(blockman),
|
||||
m_params(::Params()),
|
||||
m_params(chainman.GetParams()),
|
||||
m_chainman(chainman),
|
||||
m_from_snapshot_blockhash(from_snapshot_blockhash) {}
|
||||
|
||||
|
@ -1909,10 +1907,11 @@ void StopScriptCheckWorkerThreads()
|
|||
class WarningBitsConditionChecker : public AbstractThresholdConditionChecker
|
||||
{
|
||||
private:
|
||||
int bit;
|
||||
const ChainstateManager& m_chainman;
|
||||
int m_bit;
|
||||
|
||||
public:
|
||||
explicit WarningBitsConditionChecker(int bitIn) : bit(bitIn) {}
|
||||
explicit WarningBitsConditionChecker(const ChainstateManager& chainman, int bit) : m_chainman{chainman}, m_bit(bit) {}
|
||||
|
||||
int64_t BeginTime(const Consensus::Params& params) const override { return 0; }
|
||||
int64_t EndTime(const Consensus::Params& params) const override { return std::numeric_limits<int64_t>::max(); }
|
||||
|
@ -1923,15 +1922,17 @@ public:
|
|||
{
|
||||
return pindex->nHeight >= params.MinBIP9WarningHeight &&
|
||||
((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) &&
|
||||
((pindex->nVersion >> bit) & 1) != 0 &&
|
||||
((g_versionbitscache.ComputeBlockVersion(pindex->pprev, params) >> bit) & 1) == 0;
|
||||
((pindex->nVersion >> m_bit) & 1) != 0 &&
|
||||
((m_chainman.m_versionbitscache.ComputeBlockVersion(pindex->pprev, params) >> m_bit) & 1) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
static std::array<ThresholdConditionCache, VERSIONBITS_NUM_BITS> warningcache GUARDED_BY(cs_main);
|
||||
|
||||
static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const Consensus::Params& consensusparams)
|
||||
static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman)
|
||||
{
|
||||
const Consensus::Params& consensusparams = chainman.GetConsensus();
|
||||
|
||||
// BIP16 didn't become active until Apr 1 2012 (on mainnet, and
|
||||
// retroactively applied to testnet)
|
||||
// However, only one historical block violated the P2SH rules (on both
|
||||
|
@ -1947,22 +1948,22 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const Co
|
|||
}
|
||||
|
||||
// Enforce the DERSIG (BIP66) rule
|
||||
if (DeploymentActiveAt(block_index, consensusparams, Consensus::DEPLOYMENT_DERSIG)) {
|
||||
if (DeploymentActiveAt(block_index, chainman, Consensus::DEPLOYMENT_DERSIG)) {
|
||||
flags |= SCRIPT_VERIFY_DERSIG;
|
||||
}
|
||||
|
||||
// Enforce CHECKLOCKTIMEVERIFY (BIP65)
|
||||
if (DeploymentActiveAt(block_index, consensusparams, Consensus::DEPLOYMENT_CLTV)) {
|
||||
if (DeploymentActiveAt(block_index, chainman, Consensus::DEPLOYMENT_CLTV)) {
|
||||
flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
|
||||
}
|
||||
|
||||
// Enforce CHECKSEQUENCEVERIFY (BIP112)
|
||||
if (DeploymentActiveAt(block_index, consensusparams, Consensus::DEPLOYMENT_CSV)) {
|
||||
if (DeploymentActiveAt(block_index, chainman, Consensus::DEPLOYMENT_CSV)) {
|
||||
flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
|
||||
}
|
||||
|
||||
// Enforce BIP147 NULLDUMMY (activated simultaneously with segwit)
|
||||
if (DeploymentActiveAt(block_index, consensusparams, Consensus::DEPLOYMENT_SEGWIT)) {
|
||||
if (DeploymentActiveAt(block_index, chainman, Consensus::DEPLOYMENT_SEGWIT)) {
|
||||
flags |= SCRIPT_VERIFY_NULLDUMMY;
|
||||
}
|
||||
|
||||
|
@ -2153,12 +2154,12 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
|
|||
|
||||
// Enforce BIP68 (sequence locks)
|
||||
int nLockTimeFlags = 0;
|
||||
if (DeploymentActiveAt(*pindex, m_params.GetConsensus(), Consensus::DEPLOYMENT_CSV)) {
|
||||
if (DeploymentActiveAt(*pindex, m_chainman, Consensus::DEPLOYMENT_CSV)) {
|
||||
nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE;
|
||||
}
|
||||
|
||||
// Get the script flags for this block
|
||||
unsigned int flags{GetBlockScriptFlags(*pindex, m_params.GetConsensus())};
|
||||
unsigned int flags{GetBlockScriptFlags(*pindex, m_chainman)};
|
||||
|
||||
int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1;
|
||||
LogPrint(BCLog::BENCH, " - Fork checks: %.2fms [%.2fs (%.2fms/blk)]\n", MILLI * (nTime2 - nTime1), nTimeForks * MICRO, nTimeForks * MILLI / nBlocksTotal);
|
||||
|
@ -2556,7 +2557,7 @@ void CChainState::UpdateTip(const CBlockIndex* pindexNew)
|
|||
if (!this->IsInitialBlockDownload()) {
|
||||
const CBlockIndex* pindex = pindexNew;
|
||||
for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) {
|
||||
WarningBitsConditionChecker checker(bit);
|
||||
WarningBitsConditionChecker checker(m_chainman, bit);
|
||||
ThresholdState state = checker.GetStateFor(pindex, m_params.GetConsensus(), warningcache.at(bit));
|
||||
if (state == ThresholdState::ACTIVE || state == ThresholdState::LOCKED_IN) {
|
||||
const bilingual_str warning = strprintf(_("Unknown new rules activated (versionbit %i)"), bit);
|
||||
|
@ -3280,7 +3281,7 @@ void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pi
|
|||
pindexNew->nDataPos = pos.nPos;
|
||||
pindexNew->nUndoPos = 0;
|
||||
pindexNew->nStatus |= BLOCK_HAVE_DATA;
|
||||
if (DeploymentActiveAt(*pindexNew, m_params.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) {
|
||||
if (DeploymentActiveAt(*pindexNew, m_chainman, Consensus::DEPLOYMENT_SEGWIT)) {
|
||||
pindexNew->nStatus |= BLOCK_OPT_WITNESS;
|
||||
}
|
||||
pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS);
|
||||
|
@ -3398,11 +3399,11 @@ bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensu
|
|||
return true;
|
||||
}
|
||||
|
||||
void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams)
|
||||
void ChainstateManager::UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev) const
|
||||
{
|
||||
int commitpos = GetWitnessCommitmentIndex(block);
|
||||
static const std::vector<unsigned char> nonce(32, 0x00);
|
||||
if (commitpos != NO_WITNESS_COMMITMENT && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT) && !block.vtx[0]->HasWitness()) {
|
||||
if (commitpos != NO_WITNESS_COMMITMENT && DeploymentActiveAfter(pindexPrev, *this, 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;
|
||||
|
@ -3410,7 +3411,7 @@ void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPr
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams)
|
||||
std::vector<unsigned char> ChainstateManager::GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev) const
|
||||
{
|
||||
std::vector<unsigned char> commitment;
|
||||
int commitpos = GetWitnessCommitmentIndex(block);
|
||||
|
@ -3433,7 +3434,7 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
|
|||
tx.vout.push_back(out);
|
||||
block.vtx[0] = MakeTransactionRef(std::move(tx));
|
||||
}
|
||||
UpdateUncommittedBlockStructures(block, pindexPrev, consensusParams);
|
||||
UpdateUncommittedBlockStructures(block, pindexPrev);
|
||||
return commitment;
|
||||
}
|
||||
|
||||
|
@ -3446,14 +3447,14 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
|
|||
* in ConnectBlock().
|
||||
* Note that -reindex-chainstate skips the validation that happens here!
|
||||
*/
|
||||
static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidationState& state, BlockManager& blockman, const CChainParams& params, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
|
||||
static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidationState& state, BlockManager& blockman, const ChainstateManager& chainman, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
|
||||
{
|
||||
AssertLockHeld(::cs_main);
|
||||
assert(pindexPrev != nullptr);
|
||||
const int nHeight = pindexPrev->nHeight + 1;
|
||||
|
||||
// Check proof of work
|
||||
const Consensus::Params& consensusParams = params.GetConsensus();
|
||||
const Consensus::Params& consensusParams = chainman.GetConsensus();
|
||||
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))
|
||||
return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, "bad-diffbits", "incorrect proof of work");
|
||||
|
||||
|
@ -3462,7 +3463,7 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio
|
|||
// Don't accept any forks from the main chain prior to last checkpoint.
|
||||
// GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our
|
||||
// BlockIndex().
|
||||
const CBlockIndex* pcheckpoint = blockman.GetLastCheckpoint(params.Checkpoints());
|
||||
const CBlockIndex* pcheckpoint = blockman.GetLastCheckpoint(chainman.GetParams().Checkpoints());
|
||||
if (pcheckpoint && nHeight < pcheckpoint->nHeight) {
|
||||
LogPrintf("ERROR: %s: forked chain older than last checkpoint (height %d)\n", __func__, nHeight);
|
||||
return state.Invalid(BlockValidationResult::BLOCK_CHECKPOINT, "bad-fork-prior-to-checkpoint");
|
||||
|
@ -3478,9 +3479,9 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio
|
|||
return state.Invalid(BlockValidationResult::BLOCK_TIME_FUTURE, "time-too-new", "block timestamp too far in the future");
|
||||
|
||||
// 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))) {
|
||||
if ((block.nVersion < 2 && DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_HEIGHTINCB)) ||
|
||||
(block.nVersion < 3 && DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_DERSIG)) ||
|
||||
(block.nVersion < 4 && DeploymentActiveAfter(pindexPrev, chainman, 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));
|
||||
}
|
||||
|
@ -3494,13 +3495,13 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio
|
|||
* in ConnectBlock().
|
||||
* Note that -reindex-chainstate skips the validation that happens here!
|
||||
*/
|
||||
static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
|
||||
static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& state, const ChainstateManager& chainman, const CBlockIndex* pindexPrev)
|
||||
{
|
||||
const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1;
|
||||
|
||||
// Enforce BIP113 (Median Time Past).
|
||||
int nLockTimeFlags = 0;
|
||||
if (DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CSV)) {
|
||||
if (DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_CSV)) {
|
||||
assert(pindexPrev != nullptr);
|
||||
nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST;
|
||||
}
|
||||
|
@ -3517,7 +3518,7 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
|
|||
}
|
||||
|
||||
// Enforce rule that the coinbase starts with serialized block height
|
||||
if (DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB))
|
||||
if (DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_HEIGHTINCB))
|
||||
{
|
||||
CScript expect = CScript() << nHeight;
|
||||
if (block.vtx[0]->vin[0].scriptSig.size() < expect.size() ||
|
||||
|
@ -3535,7 +3536,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 (DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT)) {
|
||||
if (DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_SEGWIT)) {
|
||||
int commitpos = GetWitnessCommitmentIndex(block);
|
||||
if (commitpos != NO_WITNESS_COMMITMENT) {
|
||||
bool malleated = false;
|
||||
|
@ -3576,13 +3577,13 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex)
|
||||
bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationState& state, CBlockIndex** ppindex)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
// Check for duplicate
|
||||
uint256 hash = block.GetHash();
|
||||
BlockMap::iterator miSelf{m_blockman.m_block_index.find(hash)};
|
||||
if (hash != chainparams.GetConsensus().hashGenesisBlock) {
|
||||
if (hash != GetConsensus().hashGenesisBlock) {
|
||||
if (miSelf != m_blockman.m_block_index.end()) {
|
||||
// Block header is already known.
|
||||
CBlockIndex* pindex = &(miSelf->second);
|
||||
|
@ -3595,7 +3596,7 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!CheckBlockHeader(block, state, chainparams.GetConsensus())) {
|
||||
if (!CheckBlockHeader(block, state, GetConsensus())) {
|
||||
LogPrint(BCLog::VALIDATION, "%s: Consensus::CheckBlockHeader: %s, %s\n", __func__, hash.ToString(), state.ToString());
|
||||
return false;
|
||||
}
|
||||
|
@ -3612,7 +3613,7 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
|
|||
LogPrint(BCLog::VALIDATION, "%s: %s prev block invalid\n", __func__, hash.ToString());
|
||||
return state.Invalid(BlockValidationResult::BLOCK_INVALID_PREV, "bad-prevblk");
|
||||
}
|
||||
if (!ContextualCheckBlockHeader(block, state, m_blockman, chainparams, pindexPrev, GetAdjustedTime())) {
|
||||
if (!ContextualCheckBlockHeader(block, state, m_blockman, *this, pindexPrev, GetAdjustedTime())) {
|
||||
LogPrint(BCLog::VALIDATION, "%s: Consensus::ContextualCheckBlockHeader: %s, %s\n", __func__, hash.ToString(), state.ToString());
|
||||
return false;
|
||||
}
|
||||
|
@ -3665,14 +3666,14 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
|
|||
}
|
||||
|
||||
// Exposed wrapper for AcceptBlockHeader
|
||||
bool ChainstateManager::ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, BlockValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex)
|
||||
bool ChainstateManager::ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, BlockValidationState& state, const CBlockIndex** ppindex)
|
||||
{
|
||||
AssertLockNotHeld(cs_main);
|
||||
{
|
||||
LOCK(cs_main);
|
||||
for (const CBlockHeader& header : headers) {
|
||||
CBlockIndex *pindex = nullptr; // Use a temp pindex instead of ppindex to avoid a const_cast
|
||||
bool accepted{AcceptBlockHeader(header, state, chainparams, &pindex)};
|
||||
bool accepted{AcceptBlockHeader(header, state, &pindex)};
|
||||
ActiveChainstate().CheckBlockIndex();
|
||||
|
||||
if (!accepted) {
|
||||
|
@ -3686,7 +3687,7 @@ bool ChainstateManager::ProcessNewBlockHeaders(const std::vector<CBlockHeader>&
|
|||
if (NotifyHeaderTip(ActiveChainstate())) {
|
||||
if (ActiveChainstate().IsInitialBlockDownload() && ppindex && *ppindex) {
|
||||
const CBlockIndex& last_accepted{**ppindex};
|
||||
const int64_t blocks_left{(GetTime() - last_accepted.GetBlockTime()) / chainparams.GetConsensus().nPowTargetSpacing};
|
||||
const int64_t blocks_left{(GetTime() - last_accepted.GetBlockTime()) / GetConsensus().nPowTargetSpacing};
|
||||
const double progress{100.0 * last_accepted.nHeight / (last_accepted.nHeight + blocks_left)};
|
||||
LogPrintf("Synchronizing blockheaders, height: %d (~%.2f%%)\n", last_accepted.nHeight, progress);
|
||||
}
|
||||
|
@ -3705,7 +3706,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, Block
|
|||
CBlockIndex *pindexDummy = nullptr;
|
||||
CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy;
|
||||
|
||||
bool accepted_header{m_chainman.AcceptBlockHeader(block, state, m_params, &pindex)};
|
||||
bool accepted_header{m_chainman.AcceptBlockHeader(block, state, &pindex)};
|
||||
CheckBlockIndex();
|
||||
|
||||
if (!accepted_header)
|
||||
|
@ -3745,7 +3746,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, Block
|
|||
}
|
||||
|
||||
if (!CheckBlock(block, state, m_params.GetConsensus()) ||
|
||||
!ContextualCheckBlock(block, state, m_params.GetConsensus(), pindex->pprev)) {
|
||||
!ContextualCheckBlock(block, state, m_chainman, pindex->pprev)) {
|
||||
if (state.IsInvalid() && state.GetResult() != BlockValidationResult::BLOCK_MUTATED) {
|
||||
pindex->nStatus |= BLOCK_FAILED_VALID;
|
||||
m_blockman.m_dirty_blockindex.insert(pindex);
|
||||
|
@ -3778,7 +3779,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, Block
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ChainstateManager::ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<const CBlock>& block, bool force_processing, bool* new_block)
|
||||
bool ChainstateManager::ProcessNewBlock(const std::shared_ptr<const CBlock>& block, bool force_processing, bool* new_block)
|
||||
{
|
||||
AssertLockNotHeld(cs_main);
|
||||
|
||||
|
@ -3796,7 +3797,7 @@ bool ChainstateManager::ProcessNewBlock(const CChainParams& chainparams, const s
|
|||
// malleability that cause CheckBlock() to fail; see e.g. CVE-2012-2459 and
|
||||
// https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-February/016697.html. Because CheckBlock() is
|
||||
// not very expensive, the anti-DoS benefits of caching failure (of a definitely-invalid block) are not substantial.
|
||||
bool ret = CheckBlock(*block, state, chainparams.GetConsensus());
|
||||
bool ret = CheckBlock(*block, state, GetConsensus());
|
||||
if (ret) {
|
||||
// Store to disk
|
||||
ret = ActiveChainstate().AcceptBlock(block, state, &pindex, force_processing, nullptr, new_block);
|
||||
|
@ -3849,11 +3850,11 @@ bool TestBlockValidity(BlockValidationState& state,
|
|||
indexDummy.phashBlock = &block_hash;
|
||||
|
||||
// NOTE: CheckBlockHeader is called by CheckBlock
|
||||
if (!ContextualCheckBlockHeader(block, state, chainstate.m_blockman, chainparams, pindexPrev, GetAdjustedTime()))
|
||||
if (!ContextualCheckBlockHeader(block, state, chainstate.m_blockman, chainstate.m_chainman, pindexPrev, GetAdjustedTime()))
|
||||
return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, state.ToString());
|
||||
if (!CheckBlock(block, state, chainparams.GetConsensus(), fCheckPOW, fCheckMerkleRoot))
|
||||
return error("%s: Consensus::CheckBlock: %s", __func__, state.ToString());
|
||||
if (!ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindexPrev))
|
||||
if (!ContextualCheckBlock(block, state, chainstate.m_chainman, pindexPrev))
|
||||
return error("%s: Consensus::ContextualCheckBlock: %s", __func__, state.ToString());
|
||||
if (!chainstate.ConnectBlock(block, state, &indexDummy, viewNew, true)) {
|
||||
return false;
|
||||
|
@ -4133,7 +4134,7 @@ bool CChainState::NeedsRedownload() const
|
|||
// At and above m_params.SegwitHeight, segwit consensus rules must be validated
|
||||
CBlockIndex* block{m_chain.Tip()};
|
||||
|
||||
while (block != nullptr && DeploymentActiveAt(*block, m_params.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) {
|
||||
while (block != nullptr && DeploymentActiveAt(*block, m_chainman, Consensus::DEPLOYMENT_SEGWIT)) {
|
||||
if (!(block->nStatus & BLOCK_OPT_WITNESS)) {
|
||||
// block is insufficiently validated for a segwit client
|
||||
return true;
|
||||
|
@ -4993,7 +4994,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
|
|||
}
|
||||
|
||||
int base_height = snapshot_start_block->nHeight;
|
||||
auto maybe_au_data = ExpectedAssumeutxo(base_height, ::Params());
|
||||
auto maybe_au_data = ExpectedAssumeutxo(base_height, GetParams());
|
||||
|
||||
if (!maybe_au_data) {
|
||||
LogPrintf("[snapshot] assumeutxo height in snapshot metadata not recognized " /* Continued */
|
||||
|
@ -5147,7 +5148,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 (DeploymentActiveAt(*index, ::Params().GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) {
|
||||
if (DeploymentActiveAt(*index, *this, Consensus::DEPLOYMENT_SEGWIT)) {
|
||||
index->nStatus |= BLOCK_OPT_WITNESS;
|
||||
}
|
||||
|
||||
|
@ -5216,9 +5217,9 @@ ChainstateManager::~ChainstateManager()
|
|||
{
|
||||
LOCK(::cs_main);
|
||||
|
||||
// TODO: The version bits cache and warning cache should probably become
|
||||
// non-globals
|
||||
g_versionbitscache.Clear();
|
||||
m_versionbitscache.Clear();
|
||||
|
||||
// TODO: The warning cache should probably become non-global
|
||||
for (auto& i : warningcache) {
|
||||
i.clear();
|
||||
}
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
#include <arith_uint256.h>
|
||||
#include <attributes.h>
|
||||
#include <chain.h>
|
||||
#include <chainparams.h>
|
||||
#include <consensus/amount.h>
|
||||
#include <deploymentstatus.h>
|
||||
#include <fs.h>
|
||||
#include <node/blockstorage.h>
|
||||
#include <policy/feerate.h>
|
||||
|
@ -26,6 +28,7 @@
|
|||
#include <util/check.h>
|
||||
#include <util/hasher.h>
|
||||
#include <util/translation.h>
|
||||
#include <versionbits.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
|
@ -40,7 +43,6 @@
|
|||
|
||||
class CChainState;
|
||||
class CBlockTreeDB;
|
||||
class CChainParams;
|
||||
class CTxMemPool;
|
||||
class ChainstateManager;
|
||||
struct ChainTxData;
|
||||
|
@ -51,6 +53,9 @@ struct AssumeutxoData;
|
|||
namespace node {
|
||||
class SnapshotMetadata;
|
||||
} // namespace node
|
||||
namespace Consensus {
|
||||
struct Params;
|
||||
} // namespace Consensus
|
||||
|
||||
/** Default for -minrelaytxfee, minimum relay fee for transactions */
|
||||
static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 1000;
|
||||
|
@ -359,12 +364,6 @@ bool TestBlockValidity(BlockValidationState& state,
|
|||
bool fCheckPOW = true,
|
||||
bool fCheckMerkleRoot = true) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** Produce the necessary coinbase commitment for a block (modifies the hash, don't call for mined blocks). */
|
||||
std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams);
|
||||
|
||||
/** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */
|
||||
class CVerifyDB {
|
||||
public:
|
||||
|
@ -495,6 +494,7 @@ public:
|
|||
node::BlockManager& m_blockman;
|
||||
|
||||
/** Chain parameters for this chainstate */
|
||||
/* TODO: replace with m_chainman.GetParams() */
|
||||
const CChainParams& m_params;
|
||||
|
||||
//! The chainstate manager that owns this chainstate. The reference is
|
||||
|
@ -834,6 +834,8 @@ private:
|
|||
|
||||
CBlockIndex* m_best_invalid GUARDED_BY(::cs_main){nullptr};
|
||||
|
||||
const CChainParams& m_chainparams;
|
||||
|
||||
//! Internal helper for ActivateSnapshot().
|
||||
[[nodiscard]] bool PopulateAndValidateSnapshot(
|
||||
CChainState& snapshot_chainstate,
|
||||
|
@ -847,11 +849,15 @@ private:
|
|||
bool AcceptBlockHeader(
|
||||
const CBlockHeader& block,
|
||||
BlockValidationState& state,
|
||||
const CChainParams& chainparams,
|
||||
CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
friend CChainState;
|
||||
|
||||
public:
|
||||
explicit ChainstateManager(const CChainParams& chainparams) : m_chainparams{chainparams} { }
|
||||
|
||||
const CChainParams& GetParams() const { return m_chainparams; }
|
||||
const Consensus::Params& GetConsensus() const { return m_chainparams.GetConsensus(); }
|
||||
|
||||
std::thread m_load_block;
|
||||
//! A single BlockManager instance is shared across each constructed
|
||||
//! chainstate to avoid duplicating block metadata.
|
||||
|
@ -932,6 +938,11 @@ public:
|
|||
return m_blockman.m_block_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Track versionbit status
|
||||
*/
|
||||
mutable VersionBitsCache m_versionbitscache;
|
||||
|
||||
//! @returns true if a snapshot-based chainstate is in use. Also implies
|
||||
//! that a background validation chainstate is also in use.
|
||||
bool IsSnapshotActive() const;
|
||||
|
@ -960,7 +971,7 @@ public:
|
|||
* @param[out] new_block A boolean which is set to indicate if the block was first received via this call
|
||||
* @returns If the block was processed, independently of block validity
|
||||
*/
|
||||
bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<const CBlock>& block, bool force_processing, bool* new_block) LOCKS_EXCLUDED(cs_main);
|
||||
bool ProcessNewBlock(const std::shared_ptr<const CBlock>& block, bool force_processing, bool* new_block) LOCKS_EXCLUDED(cs_main);
|
||||
|
||||
/**
|
||||
* Process incoming block headers.
|
||||
|
@ -970,10 +981,9 @@ public:
|
|||
*
|
||||
* @param[in] block The block headers themselves
|
||||
* @param[out] state This may be set to an Error state if any error occurred processing them
|
||||
* @param[in] chainparams The params for the chain we want to connect to
|
||||
* @param[out] ppindex If set, the pointer will be set to point to the last new block index object for the given headers
|
||||
*/
|
||||
bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, BlockValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex = nullptr) LOCKS_EXCLUDED(cs_main);
|
||||
bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, BlockValidationState& state, const CBlockIndex** ppindex = nullptr) LOCKS_EXCLUDED(cs_main);
|
||||
|
||||
/**
|
||||
* Try to add a transaction to the memory pool.
|
||||
|
@ -991,9 +1001,34 @@ public:
|
|||
//! ResizeCoinsCaches() as needed.
|
||||
void MaybeRebalanceCaches() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||
|
||||
/** Update uncommitted block structures (currently: only the witness reserved value). This is safe for submitted blocks. */
|
||||
void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev) const;
|
||||
|
||||
/** Produce the necessary coinbase commitment for a block (modifies the hash, don't call for mined blocks). */
|
||||
std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev) const;
|
||||
|
||||
~ChainstateManager();
|
||||
};
|
||||
|
||||
/** Deployment* info via ChainstateManager */
|
||||
template<typename DEP>
|
||||
bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const ChainstateManager& chainman, DEP dep)
|
||||
{
|
||||
return DeploymentActiveAfter(pindexPrev, chainman.GetConsensus(), dep, chainman.m_versionbitscache);
|
||||
}
|
||||
|
||||
template<typename DEP>
|
||||
bool DeploymentActiveAt(const CBlockIndex& index, const ChainstateManager& chainman, DEP dep)
|
||||
{
|
||||
return DeploymentActiveAt(index, chainman.GetConsensus(), dep, chainman.m_versionbitscache);
|
||||
}
|
||||
|
||||
template<typename DEP>
|
||||
bool DeploymentEnabled(const ChainstateManager& chainman, DEP dep)
|
||||
{
|
||||
return DeploymentEnabled(chainman.GetConsensus(), dep);
|
||||
}
|
||||
|
||||
using FopenFn = std::function<FILE*(const fs::path&, const char*)>;
|
||||
|
||||
/** Dump the mempool to disk. */
|
||||
|
|
Loading…
Reference in a new issue