mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-22 06:52:36 +01:00
Merge bitcoin/bitcoin#21866: [Bundle 7/7] validation: Farewell, global Chainstate!
6f994882de
validation: Farewell, global Chainstate! (Carl Dong)972c5166ee
qt/test: Reset chainman in ~ChainstateManager instead (Carl Dong)6c3b5dc0c1
scripted-diff: tree-wide: Remove all review-only assertions (Carl Dong)3e82abb8dd
tree-wide: Remove stray review-only assertion (Carl Dong)f323248aba
qt/test: Use existing chainman in ::TestGUI (can be scripted-diff) (Carl Dong)6c15de129c
scripted-diff: wallet/test: Use existing chainman (Carl Dong)ee0ab1e959
fuzz: Initialize a TestingSetup for test_one_input (Carl Dong)0d61634c06
scripted-diff: test: Use existing chainman in unit tests (Carl Dong)e197076219
test: Pass in CoinsTip to ValidateCheckInputsForAllFlags (Carl Dong)4d99b61014
test/miner_tests: Pass in chain tip to CreateBlockIndex (Carl Dong)f0dd5e6bb4
test/util: Use existing chainman in ::PrepareBlock (Carl Dong)464c313e30
init: Use existing chainman (Carl Dong) Pull request description: Based on: #21767 à la Mr. Sandman ``` Mr. Chainman, bring me a tip (bung, bung, bung, bung) Make it the most work that I've ever seen (bung, bung, bung, bung) Rewind old tip till we're at the fork point (bung, bung, bung, bung) Then tell it that it's time to call Con-nectTip Chainman, I'm so alone (bung, bung, bung, bung) No local objects to call my own (bung, bung, bung, bung) Please make sure I have a ref Mr. Chainman, bring me a tip! ``` This is the last bundle in the #20158 series. Thanks everyone for their diligent review. I would like to call attention to https://github.com/bitcoin/bitcoin/issues/21766, where a few leftover improvements were collated. - Remove globals: - `ChainstateManager g_chainman` - `CChainState& ChainstateActive()` - `CChain& ChainActive()` - Remove all review-only assertions. ACKs for top commit: jamesob: reACK6f994882de
based on the contents of ariard: Code Review ACK6f99488
. jnewbery: utACK6f994882de
achow101: Code Review ACK6f994882de
ryanofsky: Code review ACK6f994882de
. Tree-SHA512: 4052ea79360cf0efd81ad0ee3f982e1d93aab1837dcec75f875a56ceda085de078bb3099a2137935d7cc2222004ad88da94b605ef5efef35cb6bc733725debe6
This commit is contained in:
commit
a55904a80c
35 changed files with 173 additions and 291 deletions
|
@ -25,7 +25,6 @@ static void DuplicateInputs(benchmark::Bench& bench)
|
||||||
CMutableTransaction naughtyTx{};
|
CMutableTransaction naughtyTx{};
|
||||||
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
assert(std::addressof(::ChainActive()) == std::addressof(testing_setup->m_node.chainman->ActiveChain()));
|
|
||||||
CBlockIndex* pindexPrev = testing_setup->m_node.chainman->ActiveChain().Tip();
|
CBlockIndex* pindexPrev = testing_setup->m_node.chainman->ActiveChain().Tip();
|
||||||
assert(pindexPrev != nullptr);
|
assert(pindexPrev != nullptr);
|
||||||
block.nBits = GetNextWorkRequired(pindexPrev, &block, chainparams.GetConsensus());
|
block.nBits = GetNextWorkRequired(pindexPrev, &block, chainparams.GetConsensus());
|
||||||
|
|
|
@ -340,7 +340,6 @@ void BaseIndex::Interrupt()
|
||||||
|
|
||||||
bool BaseIndex::Start(CChainState& active_chainstate)
|
bool BaseIndex::Start(CChainState& active_chainstate)
|
||||||
{
|
{
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
|
||||||
m_chainstate = &active_chainstate;
|
m_chainstate = &active_chainstate;
|
||||||
// Need to register this ValidationInterface before running Init(), so that
|
// Need to register this ValidationInterface before running Init(), so that
|
||||||
// callbacks are not missed if Init sets m_synced to true.
|
// callbacks are not missed if Init sets m_synced to true.
|
||||||
|
|
18
src/init.cpp
18
src/init.cpp
|
@ -283,7 +283,7 @@ void Shutdown(NodeContext& node)
|
||||||
init::UnsetGlobals();
|
init::UnsetGlobals();
|
||||||
node.mempool.reset();
|
node.mempool.reset();
|
||||||
node.fee_estimator.reset();
|
node.fee_estimator.reset();
|
||||||
node.chainman = nullptr;
|
node.chainman.reset();
|
||||||
node.scheduler.reset();
|
node.scheduler.reset();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -1175,8 +1175,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||||
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get(), check_ratio);
|
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get(), check_ratio);
|
||||||
|
|
||||||
assert(!node.chainman);
|
assert(!node.chainman);
|
||||||
node.chainman = &g_chainman;
|
node.chainman = std::make_unique<ChainstateManager>();
|
||||||
ChainstateManager& chainman = *Assert(node.chainman);
|
ChainstateManager& chainman = *node.chainman;
|
||||||
|
|
||||||
assert(!node.peerman);
|
assert(!node.peerman);
|
||||||
node.peerman = PeerManager::make(chainparams, *node.connman, *node.addrman, node.banman.get(),
|
node.peerman = PeerManager::make(chainparams, *node.connman, *node.addrman, node.banman.get(),
|
||||||
|
@ -1381,7 +1381,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||||
// If the loaded chain has a wrong genesis, bail out immediately
|
// If the loaded chain has a wrong genesis, bail out immediately
|
||||||
// (we're likely using a testnet datadir, or the other way around).
|
// (we're likely using a testnet datadir, or the other way around).
|
||||||
if (!chainman.BlockIndex().empty() &&
|
if (!chainman.BlockIndex().empty() &&
|
||||||
!g_chainman.m_blockman.LookupBlockIndex(chainparams.GetConsensus().hashGenesisBlock)) {
|
!chainman.m_blockman.LookupBlockIndex(chainparams.GetConsensus().hashGenesisBlock)) {
|
||||||
return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
|
return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1396,7 +1396,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||||
// If we're not mid-reindex (based on disk + args), add a genesis block on disk
|
// If we're not mid-reindex (based on disk + args), add a genesis block on disk
|
||||||
// (otherwise we use the one already on disk).
|
// (otherwise we use the one already on disk).
|
||||||
// This is called again in ThreadImport after the reindex completes.
|
// This is called again in ThreadImport after the reindex completes.
|
||||||
if (!fReindex && !::ChainstateActive().LoadGenesisBlock(chainparams)) {
|
if (!fReindex && !chainman.ActiveChainstate().LoadGenesisBlock(chainparams)) {
|
||||||
strLoadError = _("Error initializing block database");
|
strLoadError = _("Error initializing block database");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1545,21 +1545,21 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||||
// ********************************************************* Step 8: start indexers
|
// ********************************************************* Step 8: start indexers
|
||||||
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
|
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
|
||||||
g_txindex = std::make_unique<TxIndex>(nTxIndexCache, false, fReindex);
|
g_txindex = std::make_unique<TxIndex>(nTxIndexCache, false, fReindex);
|
||||||
if (!g_txindex->Start(::ChainstateActive())) {
|
if (!g_txindex->Start(chainman.ActiveChainstate())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& filter_type : g_enabled_filter_types) {
|
for (const auto& filter_type : g_enabled_filter_types) {
|
||||||
InitBlockFilterIndex(filter_type, filter_index_cache, false, fReindex);
|
InitBlockFilterIndex(filter_type, filter_index_cache, false, fReindex);
|
||||||
if (!GetBlockFilterIndex(filter_type)->Start(::ChainstateActive())) {
|
if (!GetBlockFilterIndex(filter_type)->Start(chainman.ActiveChainstate())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.GetBoolArg("-coinstatsindex", DEFAULT_COINSTATSINDEX)) {
|
if (args.GetBoolArg("-coinstatsindex", DEFAULT_COINSTATSINDEX)) {
|
||||||
g_coin_stats_index = std::make_unique<CoinStatsIndex>(/* cache size */ 0, false, fReindex);
|
g_coin_stats_index = std::make_unique<CoinStatsIndex>(/* cache size */ 0, false, fReindex);
|
||||||
if (!g_coin_stats_index->Start(::ChainstateActive())) {
|
if (!g_coin_stats_index->Start(chainman.ActiveChainstate())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1607,7 +1607,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||||
// Either install a handler to notify us when genesis activates, or set fHaveGenesis directly.
|
// Either install a handler to notify us when genesis activates, or set fHaveGenesis directly.
|
||||||
// No locking, as this happens before any background thread is started.
|
// No locking, as this happens before any background thread is started.
|
||||||
boost::signals2::connection block_notify_genesis_wait_connection;
|
boost::signals2::connection block_notify_genesis_wait_connection;
|
||||||
if (::ChainActive().Tip() == nullptr) {
|
if (chainman.ActiveChain().Tip() == nullptr) {
|
||||||
block_notify_genesis_wait_connection = uiInterface.NotifyBlockTip_connect(std::bind(BlockNotifyGenesisWait, std::placeholders::_2));
|
block_notify_genesis_wait_connection = uiInterface.NotifyBlockTip_connect(std::bind(BlockNotifyGenesisWait, std::placeholders::_2));
|
||||||
} else {
|
} else {
|
||||||
fHaveGenesis = true;
|
fHaveGenesis = true;
|
||||||
|
|
|
@ -45,15 +45,7 @@ void RegenerateCommitments(CBlock& block, ChainstateManager& chainman)
|
||||||
tx.vout.erase(tx.vout.begin() + GetWitnessCommitmentIndex(block));
|
tx.vout.erase(tx.vout.begin() + GetWitnessCommitmentIndex(block));
|
||||||
block.vtx.at(0) = MakeTransactionRef(tx);
|
block.vtx.at(0) = MakeTransactionRef(tx);
|
||||||
|
|
||||||
CBlockIndex* prev_block;
|
CBlockIndex* prev_block = WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock));
|
||||||
{
|
|
||||||
// TODO: Temporary scope to check correctness of refactored code.
|
|
||||||
// Should be removed manually after merge of
|
|
||||||
// https://github.com/bitcoin/bitcoin/pull/20158
|
|
||||||
LOCK(::cs_main);
|
|
||||||
assert(std::addressof(g_chainman.m_blockman) == std::addressof(chainman.m_blockman));
|
|
||||||
prev_block = chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock);
|
|
||||||
}
|
|
||||||
GenerateCoinbaseCommitment(block, prev_block, Params().GetConsensus());
|
GenerateCoinbaseCommitment(block, prev_block, Params().GetConsensus());
|
||||||
|
|
||||||
block.hashMerkleRoot = BlockMerkleRoot(block);
|
block.hashMerkleRoot = BlockMerkleRoot(block);
|
||||||
|
@ -124,7 +116,6 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
||||||
pblocktemplate->vTxSigOpsCost.push_back(-1); // updated at end
|
pblocktemplate->vTxSigOpsCost.push_back(-1); // updated at end
|
||||||
|
|
||||||
LOCK2(cs_main, m_mempool.cs);
|
LOCK2(cs_main, m_mempool.cs);
|
||||||
assert(std::addressof(*::ChainActive().Tip()) == std::addressof(*m_chainstate.m_chain.Tip()));
|
|
||||||
CBlockIndex* pindexPrev = m_chainstate.m_chain.Tip();
|
CBlockIndex* pindexPrev = m_chainstate.m_chain.Tip();
|
||||||
assert(pindexPrev != nullptr);
|
assert(pindexPrev != nullptr);
|
||||||
nHeight = pindexPrev->nHeight + 1;
|
nHeight = pindexPrev->nHeight + 1;
|
||||||
|
@ -184,7 +175,6 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
||||||
pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]);
|
pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]);
|
||||||
|
|
||||||
BlockValidationState state;
|
BlockValidationState state;
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(m_chainstate));
|
|
||||||
if (!TestBlockValidity(state, chainparams, m_chainstate, *pblock, pindexPrev, false, false)) {
|
if (!TestBlockValidity(state, chainparams, m_chainstate, *pblock, pindexPrev, false, false)) {
|
||||||
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, state.ToString()));
|
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, state.ToString()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1361,7 +1361,6 @@ PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& conn
|
||||||
m_stale_tip_check_time(0),
|
m_stale_tip_check_time(0),
|
||||||
m_ignore_incoming_txs(ignore_incoming_txs)
|
m_ignore_incoming_txs(ignore_incoming_txs)
|
||||||
{
|
{
|
||||||
assert(std::addressof(g_chainman) == std::addressof(m_chainman));
|
|
||||||
// Initialize global variables that cannot be constructed at startup.
|
// Initialize global variables that cannot be constructed at startup.
|
||||||
recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
|
recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
|
||||||
|
|
||||||
|
|
|
@ -248,7 +248,6 @@ bool FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigned int nHeight,
|
||||||
// when the undo file is keeping up with the block file, we want to flush it explicitly
|
// when the undo file is keeping up with the block file, we want to flush it explicitly
|
||||||
// when it is lagging behind (more blocks arrive than are being connected), we let the
|
// when it is lagging behind (more blocks arrive than are being connected), we let the
|
||||||
// undo block write case handle it
|
// undo block write case handle it
|
||||||
assert(std::addressof(::ChainActive()) == std::addressof(active_chain));
|
|
||||||
finalize_undo = (vinfoBlockFile[nFile].nHeightLast == (unsigned int)active_chain.Tip()->nHeight);
|
finalize_undo = (vinfoBlockFile[nFile].nHeightLast == (unsigned int)active_chain.Tip()->nHeight);
|
||||||
nFile++;
|
nFile++;
|
||||||
if (vinfoBlockFile.size() <= nFile) {
|
if (vinfoBlockFile.size() <= nFile) {
|
||||||
|
|
|
@ -13,7 +13,6 @@ void FindCoins(const NodeContext& node, std::map<COutPoint, Coin>& coins)
|
||||||
assert(node.mempool);
|
assert(node.mempool);
|
||||||
assert(node.chainman);
|
assert(node.chainman);
|
||||||
LOCK2(cs_main, node.mempool->cs);
|
LOCK2(cs_main, node.mempool->cs);
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(node.chainman->ActiveChainstate()));
|
|
||||||
CCoinsViewCache& chain_view = node.chainman->ActiveChainstate().CoinsTip();
|
CCoinsViewCache& chain_view = node.chainman->ActiveChainstate().CoinsTip();
|
||||||
CCoinsViewMemPool mempool_view(&chain_view, *node.mempool);
|
CCoinsViewMemPool mempool_view(&chain_view, *node.mempool);
|
||||||
for (auto& coin : coins) {
|
for (auto& coin : coins) {
|
||||||
|
|
|
@ -97,7 +97,6 @@ static bool GetUTXOStats(CCoinsView* view, BlockManager& blockman, CCoinsStats&
|
||||||
if (!pindex) {
|
if (!pindex) {
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
assert(std::addressof(g_chainman.m_blockman) == std::addressof(blockman));
|
|
||||||
pindex = blockman.LookupBlockIndex(view->GetBestBlock());
|
pindex = blockman.LookupBlockIndex(view->GetBestBlock());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <policy/fees.h>
|
#include <policy/fees.h>
|
||||||
#include <scheduler.h>
|
#include <scheduler.h>
|
||||||
#include <txmempool.h>
|
#include <txmempool.h>
|
||||||
|
#include <validation.h>
|
||||||
|
|
||||||
NodeContext::NodeContext() {}
|
NodeContext::NodeContext() {}
|
||||||
NodeContext::~NodeContext() {}
|
NodeContext::~NodeContext() {}
|
||||||
|
|
|
@ -44,7 +44,7 @@ struct NodeContext {
|
||||||
std::unique_ptr<CTxMemPool> mempool;
|
std::unique_ptr<CTxMemPool> mempool;
|
||||||
std::unique_ptr<CBlockPolicyEstimator> fee_estimator;
|
std::unique_ptr<CBlockPolicyEstimator> fee_estimator;
|
||||||
std::unique_ptr<PeerManager> peerman;
|
std::unique_ptr<PeerManager> peerman;
|
||||||
ChainstateManager* chainman{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
|
std::unique_ptr<ChainstateManager> chainman;
|
||||||
std::unique_ptr<BanMan> banman;
|
std::unique_ptr<BanMan> banman;
|
||||||
ArgsManager* args{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
|
ArgsManager* args{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
|
||||||
std::unique_ptr<interfaces::Chain> chain;
|
std::unique_ptr<interfaces::Chain> chain;
|
||||||
|
|
|
@ -197,26 +197,16 @@ public:
|
||||||
int getNumBlocks() override
|
int getNumBlocks() override
|
||||||
{
|
{
|
||||||
LOCK(::cs_main);
|
LOCK(::cs_main);
|
||||||
assert(std::addressof(::ChainActive()) == std::addressof(chainman().ActiveChain()));
|
|
||||||
return chainman().ActiveChain().Height();
|
return chainman().ActiveChain().Height();
|
||||||
}
|
}
|
||||||
uint256 getBestBlockHash() override
|
uint256 getBestBlockHash() override
|
||||||
{
|
{
|
||||||
const CBlockIndex* tip;
|
const CBlockIndex* tip = WITH_LOCK(::cs_main, return chainman().ActiveChain().Tip());
|
||||||
{
|
|
||||||
// TODO: Temporary scope to check correctness of refactored code.
|
|
||||||
// Should be removed manually after merge of
|
|
||||||
// https://github.com/bitcoin/bitcoin/pull/20158
|
|
||||||
LOCK(cs_main);
|
|
||||||
assert(std::addressof(::ChainActive()) == std::addressof(chainman().ActiveChain()));
|
|
||||||
tip = chainman().ActiveChain().Tip();
|
|
||||||
}
|
|
||||||
return tip ? tip->GetBlockHash() : Params().GenesisBlock().GetHash();
|
return tip ? tip->GetBlockHash() : Params().GenesisBlock().GetHash();
|
||||||
}
|
}
|
||||||
int64_t getLastBlockTime() override
|
int64_t getLastBlockTime() override
|
||||||
{
|
{
|
||||||
LOCK(::cs_main);
|
LOCK(::cs_main);
|
||||||
assert(std::addressof(::ChainActive()) == std::addressof(chainman().ActiveChain()));
|
|
||||||
if (chainman().ActiveChain().Tip()) {
|
if (chainman().ActiveChain().Tip()) {
|
||||||
return chainman().ActiveChain().Tip()->GetBlockTime();
|
return chainman().ActiveChain().Tip()->GetBlockTime();
|
||||||
}
|
}
|
||||||
|
@ -227,22 +217,12 @@ public:
|
||||||
const CBlockIndex* tip;
|
const CBlockIndex* tip;
|
||||||
{
|
{
|
||||||
LOCK(::cs_main);
|
LOCK(::cs_main);
|
||||||
assert(std::addressof(::ChainActive()) == std::addressof(chainman().ActiveChain()));
|
|
||||||
tip = chainman().ActiveChain().Tip();
|
tip = chainman().ActiveChain().Tip();
|
||||||
}
|
}
|
||||||
return GuessVerificationProgress(Params().TxData(), tip);
|
return GuessVerificationProgress(Params().TxData(), tip);
|
||||||
}
|
}
|
||||||
bool isInitialBlockDownload() override {
|
bool isInitialBlockDownload() override {
|
||||||
const CChainState* active_chainstate;
|
return chainman().ActiveChainstate().IsInitialBlockDownload();
|
||||||
{
|
|
||||||
// TODO: Temporary scope to check correctness of refactored code.
|
|
||||||
// Should be removed manually after merge of
|
|
||||||
// https://github.com/bitcoin/bitcoin/pull/20158
|
|
||||||
LOCK(::cs_main);
|
|
||||||
active_chainstate = &m_context->chainman->ActiveChainstate();
|
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(*active_chainstate));
|
|
||||||
}
|
|
||||||
return active_chainstate->IsInitialBlockDownload();
|
|
||||||
}
|
}
|
||||||
bool getReindex() override { return ::fReindex; }
|
bool getReindex() override { return ::fReindex; }
|
||||||
bool getImporting() override { return ::fImporting; }
|
bool getImporting() override { return ::fImporting; }
|
||||||
|
@ -269,7 +249,6 @@ public:
|
||||||
bool getUnspentOutput(const COutPoint& output, Coin& coin) override
|
bool getUnspentOutput(const COutPoint& output, Coin& coin) override
|
||||||
{
|
{
|
||||||
LOCK(::cs_main);
|
LOCK(::cs_main);
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(chainman().ActiveChainstate()));
|
|
||||||
return chainman().ActiveChainstate().CoinsTip().GetCoin(output, coin);
|
return chainman().ActiveChainstate().CoinsTip().GetCoin(output, coin);
|
||||||
}
|
}
|
||||||
WalletClient& walletClient() override
|
WalletClient& walletClient() override
|
||||||
|
@ -476,14 +455,12 @@ public:
|
||||||
bool checkFinalTx(const CTransaction& tx) override
|
bool checkFinalTx(const CTransaction& tx) override
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
assert(std::addressof(::ChainActive()) == std::addressof(chainman().ActiveChain()));
|
|
||||||
return CheckFinalTx(chainman().ActiveChain().Tip(), tx);
|
return CheckFinalTx(chainman().ActiveChain().Tip(), tx);
|
||||||
}
|
}
|
||||||
std::optional<int> findLocatorFork(const CBlockLocator& locator) override
|
std::optional<int> findLocatorFork(const CBlockLocator& locator) override
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
||||||
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
|
|
||||||
if (CBlockIndex* fork = m_node.chainman->m_blockman.FindForkInGlobalIndex(active, locator)) {
|
if (CBlockIndex* fork = m_node.chainman->m_blockman.FindForkInGlobalIndex(active, locator)) {
|
||||||
return fork->nHeight;
|
return fork->nHeight;
|
||||||
}
|
}
|
||||||
|
@ -493,7 +470,6 @@ public:
|
||||||
{
|
{
|
||||||
WAIT_LOCK(cs_main, lock);
|
WAIT_LOCK(cs_main, lock);
|
||||||
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
||||||
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
|
|
||||||
return FillBlock(m_node.chainman->m_blockman.LookupBlockIndex(hash), block, lock, active);
|
return FillBlock(m_node.chainman->m_blockman.LookupBlockIndex(hash), block, lock, active);
|
||||||
}
|
}
|
||||||
bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override
|
bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override
|
||||||
|
@ -506,7 +482,6 @@ public:
|
||||||
{
|
{
|
||||||
WAIT_LOCK(cs_main, lock);
|
WAIT_LOCK(cs_main, lock);
|
||||||
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
||||||
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
|
|
||||||
if (const CBlockIndex* block = m_node.chainman->m_blockman.LookupBlockIndex(block_hash)) {
|
if (const CBlockIndex* block = m_node.chainman->m_blockman.LookupBlockIndex(block_hash)) {
|
||||||
if (const CBlockIndex* ancestor = block->GetAncestor(ancestor_height)) {
|
if (const CBlockIndex* ancestor = block->GetAncestor(ancestor_height)) {
|
||||||
return FillBlock(ancestor, ancestor_out, lock, active);
|
return FillBlock(ancestor, ancestor_out, lock, active);
|
||||||
|
@ -518,9 +493,7 @@ public:
|
||||||
{
|
{
|
||||||
WAIT_LOCK(cs_main, lock);
|
WAIT_LOCK(cs_main, lock);
|
||||||
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
||||||
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
|
|
||||||
const CBlockIndex* block = m_node.chainman->m_blockman.LookupBlockIndex(block_hash);
|
const CBlockIndex* block = m_node.chainman->m_blockman.LookupBlockIndex(block_hash);
|
||||||
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
|
|
||||||
const CBlockIndex* ancestor = m_node.chainman->m_blockman.LookupBlockIndex(ancestor_hash);
|
const CBlockIndex* ancestor = m_node.chainman->m_blockman.LookupBlockIndex(ancestor_hash);
|
||||||
if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr;
|
if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr;
|
||||||
return FillBlock(ancestor, ancestor_out, lock, active);
|
return FillBlock(ancestor, ancestor_out, lock, active);
|
||||||
|
@ -529,9 +502,7 @@ public:
|
||||||
{
|
{
|
||||||
WAIT_LOCK(cs_main, lock);
|
WAIT_LOCK(cs_main, lock);
|
||||||
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
||||||
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
|
|
||||||
const CBlockIndex* block1 = m_node.chainman->m_blockman.LookupBlockIndex(block_hash1);
|
const CBlockIndex* block1 = m_node.chainman->m_blockman.LookupBlockIndex(block_hash1);
|
||||||
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
|
|
||||||
const CBlockIndex* block2 = m_node.chainman->m_blockman.LookupBlockIndex(block_hash2);
|
const CBlockIndex* block2 = m_node.chainman->m_blockman.LookupBlockIndex(block_hash2);
|
||||||
const CBlockIndex* ancestor = block1 && block2 ? LastCommonAncestor(block1, block2) : nullptr;
|
const CBlockIndex* ancestor = block1 && block2 ? LastCommonAncestor(block1, block2) : nullptr;
|
||||||
// Using & instead of && below to avoid short circuiting and leaving
|
// Using & instead of && below to avoid short circuiting and leaving
|
||||||
|
@ -542,7 +513,6 @@ public:
|
||||||
double guessVerificationProgress(const uint256& block_hash) override
|
double guessVerificationProgress(const uint256& block_hash) override
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
assert(std::addressof(g_chainman.m_blockman) == std::addressof(chainman().m_blockman));
|
|
||||||
return GuessVerificationProgress(Params().TxData(), chainman().m_blockman.LookupBlockIndex(block_hash));
|
return GuessVerificationProgress(Params().TxData(), chainman().m_blockman.LookupBlockIndex(block_hash));
|
||||||
}
|
}
|
||||||
bool hasBlocks(const uint256& block_hash, int min_height, std::optional<int> max_height) override
|
bool hasBlocks(const uint256& block_hash, int min_height, std::optional<int> max_height) override
|
||||||
|
@ -555,7 +525,6 @@ public:
|
||||||
// used to limit the range, and passing min_height that's too low or
|
// used to limit the range, and passing min_height that's too low or
|
||||||
// max_height that's too high will not crash or change the result.
|
// max_height that's too high will not crash or change the result.
|
||||||
LOCK(::cs_main);
|
LOCK(::cs_main);
|
||||||
assert(std::addressof(g_chainman.m_blockman) == std::addressof(chainman().m_blockman));
|
|
||||||
if (CBlockIndex* block = chainman().m_blockman.LookupBlockIndex(block_hash)) {
|
if (CBlockIndex* block = chainman().m_blockman.LookupBlockIndex(block_hash)) {
|
||||||
if (max_height && block->nHeight >= *max_height) block = block->GetAncestor(*max_height);
|
if (max_height && block->nHeight >= *max_height) block = block->GetAncestor(*max_height);
|
||||||
for (; block->nStatus & BLOCK_HAVE_DATA; block = block->pprev) {
|
for (; block->nStatus & BLOCK_HAVE_DATA; block = block->pprev) {
|
||||||
|
@ -647,16 +616,7 @@ public:
|
||||||
}
|
}
|
||||||
bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !isInitialBlockDownload(); }
|
bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !isInitialBlockDownload(); }
|
||||||
bool isInitialBlockDownload() override {
|
bool isInitialBlockDownload() override {
|
||||||
const CChainState* active_chainstate;
|
return chainman().ActiveChainstate().IsInitialBlockDownload();
|
||||||
{
|
|
||||||
// TODO: Temporary scope to check correctness of refactored code.
|
|
||||||
// Should be removed manually after merge of
|
|
||||||
// https://github.com/bitcoin/bitcoin/pull/20158
|
|
||||||
LOCK(::cs_main);
|
|
||||||
active_chainstate = &chainman().ActiveChainstate();
|
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(*active_chainstate));
|
|
||||||
}
|
|
||||||
return active_chainstate->IsInitialBlockDownload();
|
|
||||||
}
|
}
|
||||||
bool shutdownRequested() override { return ShutdownRequested(); }
|
bool shutdownRequested() override { return ShutdownRequested(); }
|
||||||
int64_t getAdjustedTime() override { return GetAdjustedTime(); }
|
int64_t getAdjustedTime() override { return GetAdjustedTime(); }
|
||||||
|
|
|
@ -40,7 +40,6 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
|
||||||
{ // cs_main scope
|
{ // cs_main scope
|
||||||
assert(node.chainman);
|
assert(node.chainman);
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(node.chainman->ActiveChainstate()));
|
|
||||||
// If the transaction is already confirmed in the chain, don't do anything
|
// If the transaction is already confirmed in the chain, don't do anything
|
||||||
// and return early.
|
// and return early.
|
||||||
CCoinsViewCache &view = node.chainman->ActiveChainstate().CoinsTip();
|
CCoinsViewCache &view = node.chainman->ActiveChainstate().CoinsTip();
|
||||||
|
|
|
@ -85,11 +85,6 @@ void AppTests::appTests()
|
||||||
// Reset global state to avoid interfering with later tests.
|
// Reset global state to avoid interfering with later tests.
|
||||||
LogInstance().DisconnectTestLogger();
|
LogInstance().DisconnectTestLogger();
|
||||||
AbortShutdown();
|
AbortShutdown();
|
||||||
{
|
|
||||||
LOCK(cs_main);
|
|
||||||
UnloadBlockIndex(/* mempool */ nullptr, g_chainman);
|
|
||||||
g_chainman.Reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Entry point for BitcoinGUI tests.
|
//! Entry point for BitcoinGUI tests.
|
||||||
|
|
|
@ -146,14 +146,14 @@ void TestGUI(interfaces::Node& node)
|
||||||
LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore);
|
LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore);
|
||||||
wallet->SetAddressBook(GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet->m_default_address_type), "", "receive");
|
wallet->SetAddressBook(GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet->m_default_address_type), "", "receive");
|
||||||
spk_man->AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
|
spk_man->AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
|
||||||
wallet->SetLastBlockProcessed(105, ::ChainActive().Tip()->GetBlockHash());
|
wallet->SetLastBlockProcessed(105, node.context()->chainman->ActiveChain().Tip()->GetBlockHash());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
WalletRescanReserver reserver(*wallet);
|
WalletRescanReserver reserver(*wallet);
|
||||||
reserver.reserve();
|
reserver.reserve();
|
||||||
CWallet::ScanResult result = wallet->ScanForWalletTransactions(Params().GetConsensus().hashGenesisBlock, 0 /* block height */, {} /* max height */, reserver, true /* fUpdate */);
|
CWallet::ScanResult result = wallet->ScanForWalletTransactions(Params().GetConsensus().hashGenesisBlock, 0 /* block height */, {} /* max height */, reserver, true /* fUpdate */);
|
||||||
QCOMPARE(result.status, CWallet::ScanResult::SUCCESS);
|
QCOMPARE(result.status, CWallet::ScanResult::SUCCESS);
|
||||||
QCOMPARE(result.last_scanned_block, ::ChainActive().Tip()->GetBlockHash());
|
QCOMPARE(result.last_scanned_block, node.context()->chainman->ActiveChain().Tip()->GetBlockHash());
|
||||||
QVERIFY(result.last_failed_block.IsNull());
|
QVERIFY(result.last_failed_block.IsNull());
|
||||||
}
|
}
|
||||||
wallet->SetBroadcastTransactions(true);
|
wallet->SetBroadcastTransactions(true);
|
||||||
|
|
|
@ -125,7 +125,7 @@ static ChainstateManager* GetChainman(const std::any& context, HTTPRequest* req)
|
||||||
__FILE__, __LINE__, __func__, PACKAGE_BUGREPORT));
|
__FILE__, __LINE__, __func__, PACKAGE_BUGREPORT));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return node_context->chainman;
|
return node_context->chainman.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
static RetFormat ParseDataFormat(std::string& param, const std::string& strReq)
|
static RetFormat ParseDataFormat(std::string& param, const std::string& strReq)
|
||||||
|
|
|
@ -84,7 +84,6 @@ ChainstateManager& EnsureChainman(const NodeContext& node)
|
||||||
if (!node.chainman) {
|
if (!node.chainman) {
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Node chainman not found");
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Node chainman not found");
|
||||||
}
|
}
|
||||||
WITH_LOCK(::cs_main, CHECK_NONFATAL(std::addressof(g_chainman) == std::addressof(*node.chainman)));
|
|
||||||
return *node.chainman;
|
return *node.chainman;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,6 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t&
|
||||||
|
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
CHECK_NONFATAL(std::addressof(::ChainActive()) == std::addressof(chainman.ActiveChain()));
|
|
||||||
IncrementExtraNonce(&block, chainman.ActiveChain().Tip(), extra_nonce);
|
IncrementExtraNonce(&block, chainman.ActiveChain().Tip(), extra_nonce);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +146,6 @@ static UniValue generateBlocks(ChainstateManager& chainman, const CTxMemPool& me
|
||||||
|
|
||||||
{ // Don't keep cs_main locked
|
{ // Don't keep cs_main locked
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
CHECK_NONFATAL(std::addressof(::ChainActive()) == std::addressof(chainman.ActiveChain()));
|
|
||||||
nHeight = chainman.ActiveChain().Height();
|
nHeight = chainman.ActiveChain().Height();
|
||||||
nHeightEnd = nHeight+nGenerate;
|
nHeightEnd = nHeight+nGenerate;
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ CBlock BuildChainTestingSetup::CreateBlock(const CBlockIndex* prev,
|
||||||
const CScript& scriptPubKey)
|
const CScript& scriptPubKey)
|
||||||
{
|
{
|
||||||
const CChainParams& chainparams = Params();
|
const CChainParams& chainparams = Params();
|
||||||
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(::ChainstateActive(), *m_node.mempool, chainparams).CreateNewBlock(scriptPubKey);
|
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(m_node.chainman->ActiveChainstate(), *m_node.mempool, chainparams).CreateNewBlock(scriptPubKey);
|
||||||
CBlock& block = pblocktemplate->block;
|
CBlock& block = pblocktemplate->block;
|
||||||
block.hashPrevBlock = prev->GetBlockHash();
|
block.hashPrevBlock = prev->GetBlockHash();
|
||||||
block.nTime = prev->nTime + 1;
|
block.nTime = prev->nTime + 1;
|
||||||
|
@ -117,9 +117,9 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
|
||||||
std::vector<BlockFilter> filters;
|
std::vector<BlockFilter> filters;
|
||||||
std::vector<uint256> filter_hashes;
|
std::vector<uint256> filter_hashes;
|
||||||
|
|
||||||
for (const CBlockIndex* block_index = ::ChainActive().Genesis();
|
for (const CBlockIndex* block_index = m_node.chainman->ActiveChain().Genesis();
|
||||||
block_index != nullptr;
|
block_index != nullptr;
|
||||||
block_index = ::ChainActive().Next(block_index)) {
|
block_index = m_node.chainman->ActiveChain().Next(block_index)) {
|
||||||
BOOST_CHECK(!filter_index.LookupFilter(block_index, filter));
|
BOOST_CHECK(!filter_index.LookupFilter(block_index, filter));
|
||||||
BOOST_CHECK(!filter_index.LookupFilterHeader(block_index, filter_header));
|
BOOST_CHECK(!filter_index.LookupFilterHeader(block_index, filter_header));
|
||||||
BOOST_CHECK(!filter_index.LookupFilterRange(block_index->nHeight, block_index, filters));
|
BOOST_CHECK(!filter_index.LookupFilterRange(block_index->nHeight, block_index, filters));
|
||||||
|
@ -131,7 +131,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
|
||||||
// BlockUntilSyncedToCurrentChain should return false before index is started.
|
// BlockUntilSyncedToCurrentChain should return false before index is started.
|
||||||
BOOST_CHECK(!filter_index.BlockUntilSyncedToCurrentChain());
|
BOOST_CHECK(!filter_index.BlockUntilSyncedToCurrentChain());
|
||||||
|
|
||||||
BOOST_REQUIRE(filter_index.Start(::ChainstateActive()));
|
BOOST_REQUIRE(filter_index.Start(m_node.chainman->ActiveChainstate()));
|
||||||
|
|
||||||
// Allow filter index to catch up with the block index.
|
// Allow filter index to catch up with the block index.
|
||||||
constexpr int64_t timeout_ms = 10 * 1000;
|
constexpr int64_t timeout_ms = 10 * 1000;
|
||||||
|
@ -145,9 +145,9 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
const CBlockIndex* block_index;
|
const CBlockIndex* block_index;
|
||||||
for (block_index = ::ChainActive().Genesis();
|
for (block_index = m_node.chainman->ActiveChain().Genesis();
|
||||||
block_index != nullptr;
|
block_index != nullptr;
|
||||||
block_index = ::ChainActive().Next(block_index)) {
|
block_index = m_node.chainman->ActiveChain().Next(block_index)) {
|
||||||
CheckFilterLookups(filter_index, block_index, last_header);
|
CheckFilterLookups(filter_index, block_index, last_header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
|
||||||
const CBlockIndex* tip;
|
const CBlockIndex* tip;
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
tip = ::ChainActive().Tip();
|
tip = m_node.chainman->ActiveChain().Tip();
|
||||||
}
|
}
|
||||||
CKey coinbase_key_A, coinbase_key_B;
|
CKey coinbase_key_A, coinbase_key_B;
|
||||||
coinbase_key_A.MakeNewKey(true);
|
coinbase_key_A.MakeNewKey(true);
|
||||||
|
@ -178,7 +178,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
|
||||||
const CBlockIndex* block_index;
|
const CBlockIndex* block_index;
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
block_index = g_chainman.m_blockman.LookupBlockIndex(block->GetHash());
|
block_index = m_node.chainman->m_blockman.LookupBlockIndex(block->GetHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
|
BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
|
||||||
|
@ -196,7 +196,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
|
||||||
const CBlockIndex* block_index;
|
const CBlockIndex* block_index;
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
block_index = g_chainman.m_blockman.LookupBlockIndex(block->GetHash());
|
block_index = m_node.chainman->m_blockman.LookupBlockIndex(block->GetHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
|
BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
|
||||||
|
@ -210,7 +210,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
|
||||||
const CBlockIndex* block_index;
|
const CBlockIndex* block_index;
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
block_index = g_chainman.m_blockman.LookupBlockIndex(block->GetHash());
|
block_index = m_node.chainman->m_blockman.LookupBlockIndex(block->GetHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
|
BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
|
||||||
|
@ -231,14 +231,14 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
|
||||||
|
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
block_index = g_chainman.m_blockman.LookupBlockIndex(chainA[i]->GetHash());
|
block_index = m_node.chainman->m_blockman.LookupBlockIndex(chainA[i]->GetHash());
|
||||||
}
|
}
|
||||||
BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
|
BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
|
||||||
CheckFilterLookups(filter_index, block_index, chainA_last_header);
|
CheckFilterLookups(filter_index, block_index, chainA_last_header);
|
||||||
|
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
block_index = g_chainman.m_blockman.LookupBlockIndex(chainB[i]->GetHash());
|
block_index = m_node.chainman->m_blockman.LookupBlockIndex(chainB[i]->GetHash());
|
||||||
}
|
}
|
||||||
BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
|
BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
|
||||||
CheckFilterLookups(filter_index, block_index, chainB_last_header);
|
CheckFilterLookups(filter_index, block_index, chainB_last_header);
|
||||||
|
@ -250,7 +250,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
|
||||||
|
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
tip = ::ChainActive().Tip();
|
tip = m_node.chainman->ActiveChain().Tip();
|
||||||
}
|
}
|
||||||
BOOST_CHECK(filter_index.LookupFilterRange(0, tip, filters));
|
BOOST_CHECK(filter_index.LookupFilterRange(0, tip, filters));
|
||||||
BOOST_CHECK(filter_index.LookupFilterHashRange(0, tip, filter_hashes));
|
BOOST_CHECK(filter_index.LookupFilterHashRange(0, tip, filter_hashes));
|
||||||
|
|
|
@ -22,7 +22,7 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
|
||||||
const CBlockIndex* block_index;
|
const CBlockIndex* block_index;
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
block_index = ChainActive().Tip();
|
block_index = m_node.chainman->ActiveChain().Tip();
|
||||||
}
|
}
|
||||||
|
|
||||||
// CoinStatsIndex should not be found before it is started.
|
// CoinStatsIndex should not be found before it is started.
|
||||||
|
@ -32,7 +32,7 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
|
||||||
// is started.
|
// is started.
|
||||||
BOOST_CHECK(!coin_stats_index.BlockUntilSyncedToCurrentChain());
|
BOOST_CHECK(!coin_stats_index.BlockUntilSyncedToCurrentChain());
|
||||||
|
|
||||||
BOOST_REQUIRE(coin_stats_index.Start(::ChainstateActive()));
|
BOOST_REQUIRE(coin_stats_index.Start(m_node.chainman->ActiveChainstate()));
|
||||||
|
|
||||||
// Allow the CoinStatsIndex to catch up with the block index that is syncing
|
// Allow the CoinStatsIndex to catch up with the block index that is syncing
|
||||||
// in a background thread.
|
// in a background thread.
|
||||||
|
@ -46,7 +46,7 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
|
||||||
const CBlockIndex* genesis_block_index;
|
const CBlockIndex* genesis_block_index;
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
genesis_block_index = ChainActive().Genesis();
|
genesis_block_index = m_node.chainman->ActiveChain().Genesis();
|
||||||
}
|
}
|
||||||
BOOST_CHECK(coin_stats_index.LookUpStats(genesis_block_index, coin_stats));
|
BOOST_CHECK(coin_stats_index.LookUpStats(genesis_block_index, coin_stats));
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
|
||||||
const CBlockIndex* new_block_index;
|
const CBlockIndex* new_block_index;
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
new_block_index = ChainActive().Tip();
|
new_block_index = m_node.chainman->ActiveChain().Tip();
|
||||||
}
|
}
|
||||||
coin_stats_index.LookUpStats(new_block_index, new_coin_stats);
|
coin_stats_index.LookUpStats(new_block_index, new_coin_stats);
|
||||||
|
|
||||||
|
|
|
@ -66,8 +66,8 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
|
||||||
// This test requires that we have a chain with non-zero work.
|
// This test requires that we have a chain with non-zero work.
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
BOOST_CHECK(::ChainActive().Tip() != nullptr);
|
BOOST_CHECK(m_node.chainman->ActiveChain().Tip() != nullptr);
|
||||||
BOOST_CHECK(::ChainActive().Tip()->nChainWork > 0);
|
BOOST_CHECK(m_node.chainman->ActiveChain().Tip()->nChainWork > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test starts here
|
// Test starts here
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
const TestingSetup* g_setup;
|
||||||
const Coin EMPTY_COIN{};
|
const Coin EMPTY_COIN{};
|
||||||
|
|
||||||
bool operator==(const Coin& a, const Coin& b)
|
bool operator==(const Coin& a, const Coin& b)
|
||||||
|
@ -39,6 +40,7 @@ bool operator==(const Coin& a, const Coin& b)
|
||||||
void initialize_coins_view()
|
void initialize_coins_view()
|
||||||
{
|
{
|
||||||
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
|
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
|
||||||
|
g_setup = testing_setup.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
FUZZ_TARGET_INIT(coins_view, initialize_coins_view)
|
FUZZ_TARGET_INIT(coins_view, initialize_coins_view)
|
||||||
|
@ -268,7 +270,7 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view)
|
||||||
CCoinsStats stats{CoinStatsHashType::HASH_SERIALIZED};
|
CCoinsStats stats{CoinStatsHashType::HASH_SERIALIZED};
|
||||||
bool expected_code_path = false;
|
bool expected_code_path = false;
|
||||||
try {
|
try {
|
||||||
(void)GetUTXOStats(&coins_view_cache, WITH_LOCK(::cs_main, return std::ref(g_chainman.m_blockman)), stats);
|
(void)GetUTXOStats(&coins_view_cache, WITH_LOCK(::cs_main, return std::ref(g_setup->m_node.chainman->m_blockman)), stats);
|
||||||
} catch (const std::logic_error&) {
|
} catch (const std::logic_error&) {
|
||||||
expected_code_path = true;
|
expected_code_path = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,14 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const TestingSetup* g_setup;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void initialize_load_external_block_file()
|
void initialize_load_external_block_file()
|
||||||
{
|
{
|
||||||
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
|
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
|
||||||
|
g_setup = testing_setup.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
FUZZ_TARGET_INIT(load_external_block_file, initialize_load_external_block_file)
|
FUZZ_TARGET_INIT(load_external_block_file, initialize_load_external_block_file)
|
||||||
|
@ -27,5 +32,5 @@ FUZZ_TARGET_INIT(load_external_block_file, initialize_load_external_block_file)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FlatFilePos flat_file_pos;
|
FlatFilePos flat_file_pos;
|
||||||
::ChainstateActive().LoadExternalBlockFile(Params(), fuzzed_block_file, fuzzed_data_provider.ConsumeBool() ? &flat_file_pos : nullptr);
|
g_setup->m_node.chainman->ActiveChainstate().LoadExternalBlockFile(Params(), fuzzed_block_file, fuzzed_data_provider.ConsumeBool() ? &flat_file_pos : nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,14 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const TestingSetup* g_setup;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void initialize_validation_load_mempool()
|
void initialize_validation_load_mempool()
|
||||||
{
|
{
|
||||||
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
|
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
|
||||||
|
g_setup = testing_setup.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
FUZZ_TARGET_INIT(validation_load_mempool, initialize_validation_load_mempool)
|
FUZZ_TARGET_INIT(validation_load_mempool, initialize_validation_load_mempool)
|
||||||
|
@ -29,6 +34,6 @@ FUZZ_TARGET_INIT(validation_load_mempool, initialize_validation_load_mempool)
|
||||||
auto fuzzed_fopen = [&](const fs::path&, const char*) {
|
auto fuzzed_fopen = [&](const fs::path&, const char*) {
|
||||||
return fuzzed_file_provider.open();
|
return fuzzed_file_provider.open();
|
||||||
};
|
};
|
||||||
(void)LoadMempool(pool, ::ChainstateActive(), fuzzed_fopen);
|
(void)LoadMempool(pool, g_setup->m_node.chainman->ActiveChainstate(), fuzzed_fopen);
|
||||||
(void)DumpMempool(pool, fuzzed_fopen, true);
|
(void)DumpMempool(pool, fuzzed_fopen, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ BOOST_AUTO_TEST_CASE(findCommonAncestor)
|
||||||
auto* orig_tip = active.Tip();
|
auto* orig_tip = active.Tip();
|
||||||
for (int i = 0; i < 10; ++i) {
|
for (int i = 0; i < 10; ++i) {
|
||||||
BlockValidationState state;
|
BlockValidationState state;
|
||||||
ChainstateActive().InvalidateBlock(state, Params(), active.Tip());
|
m_node.chainman->ActiveChainstate().InvalidateBlock(state, Params(), active.Tip());
|
||||||
}
|
}
|
||||||
BOOST_CHECK_EQUAL(active.Height(), orig_tip->nHeight - 10);
|
BOOST_CHECK_EQUAL(active.Height(), orig_tip->nHeight - 10);
|
||||||
coinbaseKey.MakeNewKey(true);
|
coinbaseKey.MakeNewKey(true);
|
||||||
|
|
|
@ -45,7 +45,7 @@ BlockAssembler MinerTestingSetup::AssemblerForTest(const CChainParams& params)
|
||||||
|
|
||||||
options.nBlockMaxWeight = MAX_BLOCK_WEIGHT;
|
options.nBlockMaxWeight = MAX_BLOCK_WEIGHT;
|
||||||
options.blockMinFeeRate = blockMinFeeRate;
|
options.blockMinFeeRate = blockMinFeeRate;
|
||||||
return BlockAssembler(::ChainstateActive(), *m_node.mempool, params, options);
|
return BlockAssembler(m_node.chainman->ActiveChainstate(), *m_node.mempool, params, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr static struct {
|
constexpr static struct {
|
||||||
|
@ -82,11 +82,11 @@ constexpr static struct {
|
||||||
{2, 0xbbbeb305}, {2, 0xfe1c810a},
|
{2, 0xbbbeb305}, {2, 0xfe1c810a},
|
||||||
};
|
};
|
||||||
|
|
||||||
static CBlockIndex CreateBlockIndex(int nHeight) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
static CBlockIndex CreateBlockIndex(int nHeight, CBlockIndex* active_chain_tip) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||||
{
|
{
|
||||||
CBlockIndex index;
|
CBlockIndex index;
|
||||||
index.nHeight = nHeight;
|
index.nHeight = nHeight;
|
||||||
index.pprev = ::ChainActive().Tip();
|
index.pprev = active_chain_tip;
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,17 +228,17 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
pblock->nVersion = 1;
|
pblock->nVersion = 1;
|
||||||
pblock->nTime = ::ChainActive().Tip()->GetMedianTimePast()+1;
|
pblock->nTime = m_node.chainman->ActiveChain().Tip()->GetMedianTimePast()+1;
|
||||||
CMutableTransaction txCoinbase(*pblock->vtx[0]);
|
CMutableTransaction txCoinbase(*pblock->vtx[0]);
|
||||||
txCoinbase.nVersion = 1;
|
txCoinbase.nVersion = 1;
|
||||||
txCoinbase.vin[0].scriptSig = CScript();
|
txCoinbase.vin[0].scriptSig = CScript();
|
||||||
txCoinbase.vin[0].scriptSig.push_back(bi.extranonce);
|
txCoinbase.vin[0].scriptSig.push_back(bi.extranonce);
|
||||||
txCoinbase.vin[0].scriptSig.push_back(::ChainActive().Height());
|
txCoinbase.vin[0].scriptSig.push_back(m_node.chainman->ActiveChain().Height());
|
||||||
txCoinbase.vout.resize(1); // Ignore the (optional) segwit commitment added by CreateNewBlock (as the hardcoded nonces don't account for this)
|
txCoinbase.vout.resize(1); // Ignore the (optional) segwit commitment added by CreateNewBlock (as the hardcoded nonces don't account for this)
|
||||||
txCoinbase.vout[0].scriptPubKey = CScript();
|
txCoinbase.vout[0].scriptPubKey = CScript();
|
||||||
pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
|
pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
|
||||||
if (txFirst.size() == 0)
|
if (txFirst.size() == 0)
|
||||||
baseheight = ::ChainActive().Height();
|
baseheight = m_node.chainman->ActiveChain().Height();
|
||||||
if (txFirst.size() < 4)
|
if (txFirst.size() < 4)
|
||||||
txFirst.push_back(pblock->vtx[0]);
|
txFirst.push_back(pblock->vtx[0]);
|
||||||
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
|
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
|
||||||
|
@ -364,29 +364,29 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||||
m_node.mempool->clear();
|
m_node.mempool->clear();
|
||||||
|
|
||||||
// subsidy changing
|
// subsidy changing
|
||||||
int nHeight = ::ChainActive().Height();
|
int nHeight = m_node.chainman->ActiveChain().Height();
|
||||||
// Create an actual 209999-long block chain (without valid blocks).
|
// Create an actual 209999-long block chain (without valid blocks).
|
||||||
while (::ChainActive().Tip()->nHeight < 209999) {
|
while (m_node.chainman->ActiveChain().Tip()->nHeight < 209999) {
|
||||||
CBlockIndex* prev = ::ChainActive().Tip();
|
CBlockIndex* prev = m_node.chainman->ActiveChain().Tip();
|
||||||
CBlockIndex* next = new CBlockIndex();
|
CBlockIndex* next = new CBlockIndex();
|
||||||
next->phashBlock = new uint256(InsecureRand256());
|
next->phashBlock = new uint256(InsecureRand256());
|
||||||
::ChainstateActive().CoinsTip().SetBestBlock(next->GetBlockHash());
|
m_node.chainman->ActiveChainstate().CoinsTip().SetBestBlock(next->GetBlockHash());
|
||||||
next->pprev = prev;
|
next->pprev = prev;
|
||||||
next->nHeight = prev->nHeight + 1;
|
next->nHeight = prev->nHeight + 1;
|
||||||
next->BuildSkip();
|
next->BuildSkip();
|
||||||
::ChainActive().SetTip(next);
|
m_node.chainman->ActiveChain().SetTip(next);
|
||||||
}
|
}
|
||||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
||||||
// Extend to a 210000-long block chain.
|
// Extend to a 210000-long block chain.
|
||||||
while (::ChainActive().Tip()->nHeight < 210000) {
|
while (m_node.chainman->ActiveChain().Tip()->nHeight < 210000) {
|
||||||
CBlockIndex* prev = ::ChainActive().Tip();
|
CBlockIndex* prev = m_node.chainman->ActiveChain().Tip();
|
||||||
CBlockIndex* next = new CBlockIndex();
|
CBlockIndex* next = new CBlockIndex();
|
||||||
next->phashBlock = new uint256(InsecureRand256());
|
next->phashBlock = new uint256(InsecureRand256());
|
||||||
::ChainstateActive().CoinsTip().SetBestBlock(next->GetBlockHash());
|
m_node.chainman->ActiveChainstate().CoinsTip().SetBestBlock(next->GetBlockHash());
|
||||||
next->pprev = prev;
|
next->pprev = prev;
|
||||||
next->nHeight = prev->nHeight + 1;
|
next->nHeight = prev->nHeight + 1;
|
||||||
next->BuildSkip();
|
next->BuildSkip();
|
||||||
::ChainActive().SetTip(next);
|
m_node.chainman->ActiveChain().SetTip(next);
|
||||||
}
|
}
|
||||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
||||||
|
|
||||||
|
@ -409,16 +409,16 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||||
m_node.mempool->clear();
|
m_node.mempool->clear();
|
||||||
|
|
||||||
// Delete the dummy blocks again.
|
// Delete the dummy blocks again.
|
||||||
while (::ChainActive().Tip()->nHeight > nHeight) {
|
while (m_node.chainman->ActiveChain().Tip()->nHeight > nHeight) {
|
||||||
CBlockIndex* del = ::ChainActive().Tip();
|
CBlockIndex* del = m_node.chainman->ActiveChain().Tip();
|
||||||
::ChainActive().SetTip(del->pprev);
|
m_node.chainman->ActiveChain().SetTip(del->pprev);
|
||||||
::ChainstateActive().CoinsTip().SetBestBlock(del->pprev->GetBlockHash());
|
m_node.chainman->ActiveChainstate().CoinsTip().SetBestBlock(del->pprev->GetBlockHash());
|
||||||
delete del->phashBlock;
|
delete del->phashBlock;
|
||||||
delete del;
|
delete del;
|
||||||
}
|
}
|
||||||
|
|
||||||
// non-final txs in mempool
|
// non-final txs in mempool
|
||||||
SetMockTime(::ChainActive().Tip()->GetMedianTimePast()+1);
|
SetMockTime(m_node.chainman->ActiveChain().Tip()->GetMedianTimePast()+1);
|
||||||
int flags = LOCKTIME_VERIFY_SEQUENCE|LOCKTIME_MEDIAN_TIME_PAST;
|
int flags = LOCKTIME_VERIFY_SEQUENCE|LOCKTIME_MEDIAN_TIME_PAST;
|
||||||
// height map
|
// height map
|
||||||
std::vector<int> prevheights;
|
std::vector<int> prevheights;
|
||||||
|
@ -430,7 +430,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||||
tx.vin[0].prevout.hash = txFirst[0]->GetHash(); // only 1 transaction
|
tx.vin[0].prevout.hash = txFirst[0]->GetHash(); // only 1 transaction
|
||||||
tx.vin[0].prevout.n = 0;
|
tx.vin[0].prevout.n = 0;
|
||||||
tx.vin[0].scriptSig = CScript() << OP_1;
|
tx.vin[0].scriptSig = CScript() << OP_1;
|
||||||
tx.vin[0].nSequence = ::ChainActive().Tip()->nHeight + 1; // txFirst[0] is the 2nd block
|
tx.vin[0].nSequence = m_node.chainman->ActiveChain().Tip()->nHeight + 1; // txFirst[0] is the 2nd block
|
||||||
prevheights[0] = baseheight + 1;
|
prevheights[0] = baseheight + 1;
|
||||||
tx.vout.resize(1);
|
tx.vout.resize(1);
|
||||||
tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE;
|
tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE;
|
||||||
|
@ -438,53 +438,62 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||||
tx.nLockTime = 0;
|
tx.nLockTime = 0;
|
||||||
hash = tx.GetHash();
|
hash = tx.GetHash();
|
||||||
m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
|
m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
|
||||||
BOOST_CHECK(CheckFinalTx(::ChainActive().Tip(), CTransaction(tx), flags)); // Locktime passes
|
BOOST_CHECK(CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime passes
|
||||||
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
|
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
|
||||||
BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, CreateBlockIndex(::ChainActive().Tip()->nHeight + 2))); // Sequence locks pass on 2nd block
|
|
||||||
|
{
|
||||||
|
CBlockIndex* active_chain_tip = m_node.chainman->ActiveChain().Tip();
|
||||||
|
BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, CreateBlockIndex(active_chain_tip->nHeight + 2, active_chain_tip))); // Sequence locks pass on 2nd block
|
||||||
|
}
|
||||||
|
|
||||||
// relative time locked
|
// relative time locked
|
||||||
tx.vin[0].prevout.hash = txFirst[1]->GetHash();
|
tx.vin[0].prevout.hash = txFirst[1]->GetHash();
|
||||||
tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | (((::ChainActive().Tip()->GetMedianTimePast()+1-::ChainActive()[1]->GetMedianTimePast()) >> CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) + 1); // txFirst[1] is the 3rd block
|
tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | (((m_node.chainman->ActiveChain().Tip()->GetMedianTimePast()+1-m_node.chainman->ActiveChain()[1]->GetMedianTimePast()) >> CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) + 1); // txFirst[1] is the 3rd block
|
||||||
prevheights[0] = baseheight + 2;
|
prevheights[0] = baseheight + 2;
|
||||||
hash = tx.GetHash();
|
hash = tx.GetHash();
|
||||||
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
|
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
|
||||||
BOOST_CHECK(CheckFinalTx(::ChainActive().Tip(), CTransaction(tx), flags)); // Locktime passes
|
BOOST_CHECK(CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime passes
|
||||||
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
|
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
|
||||||
|
|
||||||
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
|
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
|
||||||
::ChainActive().Tip()->GetAncestor(::ChainActive().Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
|
m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
|
||||||
BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, CreateBlockIndex(::ChainActive().Tip()->nHeight + 1))); // Sequence locks pass 512 seconds later
|
|
||||||
|
{
|
||||||
|
CBlockIndex* active_chain_tip = m_node.chainman->ActiveChain().Tip();
|
||||||
|
BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, CreateBlockIndex(active_chain_tip->nHeight + 1, active_chain_tip))); // Sequence locks pass 512 seconds later
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
|
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
|
||||||
::ChainActive().Tip()->GetAncestor(::ChainActive().Tip()->nHeight - i)->nTime -= 512; //undo tricked MTP
|
m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i)->nTime -= 512; //undo tricked MTP
|
||||||
|
|
||||||
// absolute height locked
|
// absolute height locked
|
||||||
tx.vin[0].prevout.hash = txFirst[2]->GetHash();
|
tx.vin[0].prevout.hash = txFirst[2]->GetHash();
|
||||||
tx.vin[0].nSequence = CTxIn::SEQUENCE_FINAL - 1;
|
tx.vin[0].nSequence = CTxIn::SEQUENCE_FINAL - 1;
|
||||||
prevheights[0] = baseheight + 3;
|
prevheights[0] = baseheight + 3;
|
||||||
tx.nLockTime = ::ChainActive().Tip()->nHeight + 1;
|
tx.nLockTime = m_node.chainman->ActiveChain().Tip()->nHeight + 1;
|
||||||
hash = tx.GetHash();
|
hash = tx.GetHash();
|
||||||
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
|
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
|
||||||
BOOST_CHECK(!CheckFinalTx(::ChainActive().Tip(), CTransaction(tx), flags)); // Locktime fails
|
BOOST_CHECK(!CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime fails
|
||||||
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
|
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
|
||||||
BOOST_CHECK(IsFinalTx(CTransaction(tx), ::ChainActive().Tip()->nHeight + 2, ::ChainActive().Tip()->GetMedianTimePast())); // Locktime passes on 2nd block
|
BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast())); // Locktime passes on 2nd block
|
||||||
|
|
||||||
// absolute time locked
|
// absolute time locked
|
||||||
tx.vin[0].prevout.hash = txFirst[3]->GetHash();
|
tx.vin[0].prevout.hash = txFirst[3]->GetHash();
|
||||||
tx.nLockTime = ::ChainActive().Tip()->GetMedianTimePast();
|
tx.nLockTime = m_node.chainman->ActiveChain().Tip()->GetMedianTimePast();
|
||||||
prevheights.resize(1);
|
prevheights.resize(1);
|
||||||
prevheights[0] = baseheight + 4;
|
prevheights[0] = baseheight + 4;
|
||||||
hash = tx.GetHash();
|
hash = tx.GetHash();
|
||||||
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
|
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
|
||||||
BOOST_CHECK(!CheckFinalTx(::ChainActive().Tip(), CTransaction(tx), flags)); // Locktime fails
|
BOOST_CHECK(!CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime fails
|
||||||
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
|
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
|
||||||
BOOST_CHECK(IsFinalTx(CTransaction(tx), ::ChainActive().Tip()->nHeight + 2, ::ChainActive().Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later
|
BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later
|
||||||
|
|
||||||
// mempool-dependent transactions (not added)
|
// mempool-dependent transactions (not added)
|
||||||
tx.vin[0].prevout.hash = hash;
|
tx.vin[0].prevout.hash = hash;
|
||||||
prevheights[0] = ::ChainActive().Tip()->nHeight + 1;
|
prevheights[0] = m_node.chainman->ActiveChain().Tip()->nHeight + 1;
|
||||||
tx.nLockTime = 0;
|
tx.nLockTime = 0;
|
||||||
tx.vin[0].nSequence = 0;
|
tx.vin[0].nSequence = 0;
|
||||||
BOOST_CHECK(CheckFinalTx(::ChainActive().Tip(), CTransaction(tx), flags)); // Locktime passes
|
BOOST_CHECK(CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime passes
|
||||||
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
|
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
|
||||||
tx.vin[0].nSequence = 1;
|
tx.vin[0].nSequence = 1;
|
||||||
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
|
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
|
||||||
|
@ -502,14 +511,14 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||||
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3U);
|
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3U);
|
||||||
// However if we advance height by 1 and time by 512, all of them should be mined
|
// However if we advance height by 1 and time by 512, all of them should be mined
|
||||||
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
|
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
|
||||||
::ChainActive().Tip()->GetAncestor(::ChainActive().Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
|
m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
|
||||||
::ChainActive().Tip()->nHeight++;
|
m_node.chainman->ActiveChain().Tip()->nHeight++;
|
||||||
SetMockTime(::ChainActive().Tip()->GetMedianTimePast() + 1);
|
SetMockTime(m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1);
|
||||||
|
|
||||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
||||||
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U);
|
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U);
|
||||||
|
|
||||||
::ChainActive().Tip()->nHeight--;
|
m_node.chainman->ActiveChain().Tip()->nHeight--;
|
||||||
SetMockTime(0);
|
SetMockTime(0);
|
||||||
m_node.mempool->clear();
|
m_node.mempool->clear();
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup)
|
||||||
// BlockUntilSyncedToCurrentChain should return false before txindex is started.
|
// BlockUntilSyncedToCurrentChain should return false before txindex is started.
|
||||||
BOOST_CHECK(!txindex.BlockUntilSyncedToCurrentChain());
|
BOOST_CHECK(!txindex.BlockUntilSyncedToCurrentChain());
|
||||||
|
|
||||||
BOOST_REQUIRE(txindex.Start(::ChainstateActive()));
|
BOOST_REQUIRE(txindex.Start(m_node.chainman->ActiveChainstate()));
|
||||||
|
|
||||||
// Allow tx index to catch up with the block index.
|
// Allow tx index to catch up with the block index.
|
||||||
constexpr int64_t timeout_ms = 10 * 1000;
|
constexpr int64_t timeout_ms = 10 * 1000;
|
||||||
|
|
|
@ -37,7 +37,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
unsigned int initialPoolSize = m_node.mempool->size();
|
unsigned int initialPoolSize = m_node.mempool->size();
|
||||||
const MempoolAcceptResult result = AcceptToMemoryPool(::ChainstateActive(), *m_node.mempool, MakeTransactionRef(coinbaseTx),
|
const MempoolAcceptResult result = AcceptToMemoryPool(m_node.chainman->ActiveChainstate(), *m_node.mempool, MakeTransactionRef(coinbaseTx),
|
||||||
true /* bypass_limits */);
|
true /* bypass_limits */);
|
||||||
|
|
||||||
BOOST_CHECK(result.m_result_type == MempoolAcceptResult::ResultType::INVALID);
|
BOOST_CHECK(result.m_result_type == MempoolAcceptResult::ResultType::INVALID);
|
||||||
|
|
|
@ -31,7 +31,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
|
||||||
const auto ToMemPool = [this](const CMutableTransaction& tx) {
|
const auto ToMemPool = [this](const CMutableTransaction& tx) {
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
const MempoolAcceptResult result = AcceptToMemoryPool(::ChainstateActive(), *m_node.mempool, MakeTransactionRef(tx),
|
const MempoolAcceptResult result = AcceptToMemoryPool(m_node.chainman->ActiveChainstate(), *m_node.mempool, MakeTransactionRef(tx),
|
||||||
true /* bypass_limits */);
|
true /* bypass_limits */);
|
||||||
return result.m_result_type == MempoolAcceptResult::ResultType::VALID;
|
return result.m_result_type == MempoolAcceptResult::ResultType::VALID;
|
||||||
};
|
};
|
||||||
|
@ -63,7 +63,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
|
||||||
block = CreateAndProcessBlock(spends, scriptPubKey);
|
block = CreateAndProcessBlock(spends, scriptPubKey);
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash());
|
BOOST_CHECK(m_node.chainman->ActiveChain().Tip()->GetBlockHash() != block.GetHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test 2: ... and should be rejected if spend1 is in the memory pool
|
// Test 2: ... and should be rejected if spend1 is in the memory pool
|
||||||
|
@ -71,7 +71,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
|
||||||
block = CreateAndProcessBlock(spends, scriptPubKey);
|
block = CreateAndProcessBlock(spends, scriptPubKey);
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash());
|
BOOST_CHECK(m_node.chainman->ActiveChain().Tip()->GetBlockHash() != block.GetHash());
|
||||||
}
|
}
|
||||||
m_node.mempool->clear();
|
m_node.mempool->clear();
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
|
||||||
block = CreateAndProcessBlock(spends, scriptPubKey);
|
block = CreateAndProcessBlock(spends, scriptPubKey);
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash());
|
BOOST_CHECK(m_node.chainman->ActiveChain().Tip()->GetBlockHash() != block.GetHash());
|
||||||
}
|
}
|
||||||
m_node.mempool->clear();
|
m_node.mempool->clear();
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
|
||||||
block = CreateAndProcessBlock(oneSpend, scriptPubKey);
|
block = CreateAndProcessBlock(oneSpend, scriptPubKey);
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() == block.GetHash());
|
BOOST_CHECK(m_node.chainman->ActiveChain().Tip()->GetBlockHash() == block.GetHash());
|
||||||
}
|
}
|
||||||
// spends[1] should have been removed from the mempool when the
|
// spends[1] should have been removed from the mempool when the
|
||||||
// block with spends[0] is accepted:
|
// block with spends[0] is accepted:
|
||||||
|
@ -109,7 +109,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
|
||||||
// should fail.
|
// should fail.
|
||||||
// Capture this interaction with the upgraded_nop argument: set it when evaluating
|
// Capture this interaction with the upgraded_nop argument: set it when evaluating
|
||||||
// any script flag that is implemented as an upgraded NOP code.
|
// any script flag that is implemented as an upgraded NOP code.
|
||||||
static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t failing_flags, bool add_to_cache) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t failing_flags, bool add_to_cache, CCoinsViewCache& active_coins_tip) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||||
{
|
{
|
||||||
PrecomputedTransactionData txdata;
|
PrecomputedTransactionData txdata;
|
||||||
// If we add many more flags, this loop can get too expensive, but we can
|
// If we add many more flags, this loop can get too expensive, but we can
|
||||||
|
@ -126,7 +126,7 @@ static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t fail
|
||||||
// WITNESS requires P2SH
|
// WITNESS requires P2SH
|
||||||
test_flags |= SCRIPT_VERIFY_P2SH;
|
test_flags |= SCRIPT_VERIFY_P2SH;
|
||||||
}
|
}
|
||||||
bool ret = CheckInputScripts(tx, state, &::ChainstateActive().CoinsTip(), test_flags, true, add_to_cache, txdata, nullptr);
|
bool ret = CheckInputScripts(tx, state, &active_coins_tip, test_flags, true, add_to_cache, txdata, nullptr);
|
||||||
// CheckInputScripts should succeed iff test_flags doesn't intersect with
|
// CheckInputScripts should succeed iff test_flags doesn't intersect with
|
||||||
// failing_flags
|
// failing_flags
|
||||||
bool expected_return_value = !(test_flags & failing_flags);
|
bool expected_return_value = !(test_flags & failing_flags);
|
||||||
|
@ -136,13 +136,13 @@ static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t fail
|
||||||
if (ret && add_to_cache) {
|
if (ret && add_to_cache) {
|
||||||
// Check that we get a cache hit if the tx was valid
|
// Check that we get a cache hit if the tx was valid
|
||||||
std::vector<CScriptCheck> scriptchecks;
|
std::vector<CScriptCheck> scriptchecks;
|
||||||
BOOST_CHECK(CheckInputScripts(tx, state, &::ChainstateActive().CoinsTip(), test_flags, true, add_to_cache, txdata, &scriptchecks));
|
BOOST_CHECK(CheckInputScripts(tx, state, &active_coins_tip, test_flags, true, add_to_cache, txdata, &scriptchecks));
|
||||||
BOOST_CHECK(scriptchecks.empty());
|
BOOST_CHECK(scriptchecks.empty());
|
||||||
} else {
|
} else {
|
||||||
// Check that we get script executions to check, if the transaction
|
// Check that we get script executions to check, if the transaction
|
||||||
// was invalid, or we didn't add to cache.
|
// was invalid, or we didn't add to cache.
|
||||||
std::vector<CScriptCheck> scriptchecks;
|
std::vector<CScriptCheck> scriptchecks;
|
||||||
BOOST_CHECK(CheckInputScripts(tx, state, &::ChainstateActive().CoinsTip(), test_flags, true, add_to_cache, txdata, &scriptchecks));
|
BOOST_CHECK(CheckInputScripts(tx, state, &active_coins_tip, test_flags, true, add_to_cache, txdata, &scriptchecks));
|
||||||
BOOST_CHECK_EQUAL(scriptchecks.size(), tx.vin.size());
|
BOOST_CHECK_EQUAL(scriptchecks.size(), tx.vin.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,20 +205,20 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
|
||||||
TxValidationState state;
|
TxValidationState state;
|
||||||
PrecomputedTransactionData ptd_spend_tx;
|
PrecomputedTransactionData ptd_spend_tx;
|
||||||
|
|
||||||
BOOST_CHECK(!CheckInputScripts(CTransaction(spend_tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, nullptr));
|
BOOST_CHECK(!CheckInputScripts(CTransaction(spend_tx), state, &m_node.chainman->ActiveChainstate().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, nullptr));
|
||||||
|
|
||||||
// If we call again asking for scriptchecks (as happens in
|
// If we call again asking for scriptchecks (as happens in
|
||||||
// ConnectBlock), we should add a script check object for this -- we're
|
// ConnectBlock), we should add a script check object for this -- we're
|
||||||
// not caching invalidity (if that changes, delete this test case).
|
// not caching invalidity (if that changes, delete this test case).
|
||||||
std::vector<CScriptCheck> scriptchecks;
|
std::vector<CScriptCheck> scriptchecks;
|
||||||
BOOST_CHECK(CheckInputScripts(CTransaction(spend_tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, &scriptchecks));
|
BOOST_CHECK(CheckInputScripts(CTransaction(spend_tx), state, &m_node.chainman->ActiveChainstate().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, &scriptchecks));
|
||||||
BOOST_CHECK_EQUAL(scriptchecks.size(), 1U);
|
BOOST_CHECK_EQUAL(scriptchecks.size(), 1U);
|
||||||
|
|
||||||
// Test that CheckInputScripts returns true iff DERSIG-enforcing flags are
|
// Test that CheckInputScripts returns true iff DERSIG-enforcing flags are
|
||||||
// not present. Don't add these checks to the cache, so that we can
|
// not present. Don't add these checks to the cache, so that we can
|
||||||
// test later that block validation works fine in the absence of cached
|
// test later that block validation works fine in the absence of cached
|
||||||
// successes.
|
// successes.
|
||||||
ValidateCheckInputsForAllFlags(CTransaction(spend_tx), SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC, false);
|
ValidateCheckInputsForAllFlags(CTransaction(spend_tx), SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC, false, m_node.chainman->ActiveChainstate().CoinsTip());
|
||||||
}
|
}
|
||||||
|
|
||||||
// And if we produce a block with this tx, it should be valid (DERSIG not
|
// And if we produce a block with this tx, it should be valid (DERSIG not
|
||||||
|
@ -227,8 +227,8 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
|
||||||
|
|
||||||
block = CreateAndProcessBlock({spend_tx}, p2pk_scriptPubKey);
|
block = CreateAndProcessBlock({spend_tx}, p2pk_scriptPubKey);
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() == block.GetHash());
|
BOOST_CHECK(m_node.chainman->ActiveChain().Tip()->GetBlockHash() == block.GetHash());
|
||||||
BOOST_CHECK(::ChainstateActive().CoinsTip().GetBestBlock() == block.GetHash());
|
BOOST_CHECK(m_node.chainman->ActiveChainstate().CoinsTip().GetBestBlock() == block.GetHash());
|
||||||
|
|
||||||
// Test P2SH: construct a transaction that is valid without P2SH, and
|
// Test P2SH: construct a transaction that is valid without P2SH, and
|
||||||
// then test validity with P2SH.
|
// then test validity with P2SH.
|
||||||
|
@ -244,7 +244,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
|
||||||
std::vector<unsigned char> vchSig2(p2pk_scriptPubKey.begin(), p2pk_scriptPubKey.end());
|
std::vector<unsigned char> vchSig2(p2pk_scriptPubKey.begin(), p2pk_scriptPubKey.end());
|
||||||
invalid_under_p2sh_tx.vin[0].scriptSig << vchSig2;
|
invalid_under_p2sh_tx.vin[0].scriptSig << vchSig2;
|
||||||
|
|
||||||
ValidateCheckInputsForAllFlags(CTransaction(invalid_under_p2sh_tx), SCRIPT_VERIFY_P2SH, true);
|
ValidateCheckInputsForAllFlags(CTransaction(invalid_under_p2sh_tx), SCRIPT_VERIFY_P2SH, true, m_node.chainman->ActiveChainstate().CoinsTip());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test CHECKLOCKTIMEVERIFY
|
// Test CHECKLOCKTIMEVERIFY
|
||||||
|
@ -267,13 +267,13 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
|
||||||
vchSig.push_back((unsigned char)SIGHASH_ALL);
|
vchSig.push_back((unsigned char)SIGHASH_ALL);
|
||||||
invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 101;
|
invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 101;
|
||||||
|
|
||||||
ValidateCheckInputsForAllFlags(CTransaction(invalid_with_cltv_tx), SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true);
|
ValidateCheckInputsForAllFlags(CTransaction(invalid_with_cltv_tx), SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, m_node.chainman->ActiveChainstate().CoinsTip());
|
||||||
|
|
||||||
// Make it valid, and check again
|
// Make it valid, and check again
|
||||||
invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
|
invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
|
||||||
TxValidationState state;
|
TxValidationState state;
|
||||||
PrecomputedTransactionData txdata;
|
PrecomputedTransactionData txdata;
|
||||||
BOOST_CHECK(CheckInputScripts(CTransaction(invalid_with_cltv_tx), state, ::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr));
|
BOOST_CHECK(CheckInputScripts(CTransaction(invalid_with_cltv_tx), state, m_node.chainman->ActiveChainstate().CoinsTip(), SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TEST CHECKSEQUENCEVERIFY
|
// TEST CHECKSEQUENCEVERIFY
|
||||||
|
@ -295,13 +295,13 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
|
||||||
vchSig.push_back((unsigned char)SIGHASH_ALL);
|
vchSig.push_back((unsigned char)SIGHASH_ALL);
|
||||||
invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 101;
|
invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 101;
|
||||||
|
|
||||||
ValidateCheckInputsForAllFlags(CTransaction(invalid_with_csv_tx), SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true);
|
ValidateCheckInputsForAllFlags(CTransaction(invalid_with_csv_tx), SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, m_node.chainman->ActiveChainstate().CoinsTip());
|
||||||
|
|
||||||
// Make it valid, and check again
|
// Make it valid, and check again
|
||||||
invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
|
invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
|
||||||
TxValidationState state;
|
TxValidationState state;
|
||||||
PrecomputedTransactionData txdata;
|
PrecomputedTransactionData txdata;
|
||||||
BOOST_CHECK(CheckInputScripts(CTransaction(invalid_with_csv_tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr));
|
BOOST_CHECK(CheckInputScripts(CTransaction(invalid_with_csv_tx), state, &m_node.chainman->ActiveChainstate().CoinsTip(), SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add tests for remaining script flags
|
// TODO: add tests for remaining script flags
|
||||||
|
@ -324,11 +324,11 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
|
||||||
UpdateInput(valid_with_witness_tx.vin[0], sigdata);
|
UpdateInput(valid_with_witness_tx.vin[0], sigdata);
|
||||||
|
|
||||||
// This should be valid under all script flags.
|
// This should be valid under all script flags.
|
||||||
ValidateCheckInputsForAllFlags(CTransaction(valid_with_witness_tx), 0, true);
|
ValidateCheckInputsForAllFlags(CTransaction(valid_with_witness_tx), 0, true, m_node.chainman->ActiveChainstate().CoinsTip());
|
||||||
|
|
||||||
// Remove the witness, and check that it is now invalid.
|
// Remove the witness, and check that it is now invalid.
|
||||||
valid_with_witness_tx.vin[0].scriptWitness.SetNull();
|
valid_with_witness_tx.vin[0].scriptWitness.SetNull();
|
||||||
ValidateCheckInputsForAllFlags(CTransaction(valid_with_witness_tx), SCRIPT_VERIFY_WITNESS, true);
|
ValidateCheckInputsForAllFlags(CTransaction(valid_with_witness_tx), SCRIPT_VERIFY_WITNESS, true, m_node.chainman->ActiveChainstate().CoinsTip());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -353,7 +353,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should be valid under all script flags
|
// This should be valid under all script flags
|
||||||
ValidateCheckInputsForAllFlags(CTransaction(tx), 0, true);
|
ValidateCheckInputsForAllFlags(CTransaction(tx), 0, true, m_node.chainman->ActiveChainstate().CoinsTip());
|
||||||
|
|
||||||
// Check that if the second input is invalid, but the first input is
|
// Check that if the second input is invalid, but the first input is
|
||||||
// valid, the transaction is not cached.
|
// valid, the transaction is not cached.
|
||||||
|
@ -363,12 +363,12 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
|
||||||
TxValidationState state;
|
TxValidationState state;
|
||||||
PrecomputedTransactionData txdata;
|
PrecomputedTransactionData txdata;
|
||||||
// This transaction is now invalid under segwit, because of the second input.
|
// This transaction is now invalid under segwit, because of the second input.
|
||||||
BOOST_CHECK(!CheckInputScripts(CTransaction(tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, nullptr));
|
BOOST_CHECK(!CheckInputScripts(CTransaction(tx), state, &m_node.chainman->ActiveChainstate().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, nullptr));
|
||||||
|
|
||||||
std::vector<CScriptCheck> scriptchecks;
|
std::vector<CScriptCheck> scriptchecks;
|
||||||
// Make sure this transaction was not cached (ie because the first
|
// Make sure this transaction was not cached (ie because the first
|
||||||
// input was valid)
|
// input was valid)
|
||||||
BOOST_CHECK(CheckInputScripts(CTransaction(tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, &scriptchecks));
|
BOOST_CHECK(CheckInputScripts(CTransaction(tx), state, &m_node.chainman->ActiveChainstate().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, &scriptchecks));
|
||||||
// Should get 2 script checks back -- caching is on a whole-transaction basis.
|
// Should get 2 script checks back -- caching is on a whole-transaction basis.
|
||||||
BOOST_CHECK_EQUAL(scriptchecks.size(), 2U);
|
BOOST_CHECK_EQUAL(scriptchecks.size(), 2U);
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,12 +74,12 @@ CTxIn MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
|
||||||
std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
|
std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
|
||||||
{
|
{
|
||||||
auto block = std::make_shared<CBlock>(
|
auto block = std::make_shared<CBlock>(
|
||||||
BlockAssembler{::ChainstateActive(), *Assert(node.mempool), Params()}
|
BlockAssembler{Assert(node.chainman)->ActiveChainstate(), *Assert(node.mempool), Params()}
|
||||||
.CreateNewBlock(coinbase_scriptPubKey)
|
.CreateNewBlock(coinbase_scriptPubKey)
|
||||||
->block);
|
->block);
|
||||||
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
block->nTime = ::ChainActive().Tip()->GetMedianTimePast() + 1;
|
block->nTime = Assert(node.chainman)->ActiveChain().Tip()->GetMedianTimePast() + 1;
|
||||||
block->hashMerkleRoot = BlockMerkleRoot(*block);
|
block->hashMerkleRoot = BlockMerkleRoot(*block);
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
|
|
|
@ -146,7 +146,7 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve
|
||||||
m_node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
|
m_node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
|
||||||
m_node.mempool = std::make_unique<CTxMemPool>(m_node.fee_estimator.get(), 1);
|
m_node.mempool = std::make_unique<CTxMemPool>(m_node.fee_estimator.get(), 1);
|
||||||
|
|
||||||
m_node.chainman = &::g_chainman;
|
m_node.chainman = std::make_unique<ChainstateManager>();
|
||||||
|
|
||||||
// Start script-checking threads. Set g_parallel_script_checks to true so they are used.
|
// Start script-checking threads. Set g_parallel_script_checks to true so they are used.
|
||||||
constexpr int script_check_threads = 2;
|
constexpr int script_check_threads = 2;
|
||||||
|
@ -168,7 +168,7 @@ ChainTestingSetup::~ChainTestingSetup()
|
||||||
m_node.mempool.reset();
|
m_node.mempool.reset();
|
||||||
m_node.scheduler.reset();
|
m_node.scheduler.reset();
|
||||||
m_node.chainman->Reset();
|
m_node.chainman->Reset();
|
||||||
m_node.chainman = nullptr;
|
m_node.chainman.reset();
|
||||||
pblocktree.reset();
|
pblocktree.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,17 +181,17 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
|
||||||
RegisterAllCoreRPCCommands(tableRPC);
|
RegisterAllCoreRPCCommands(tableRPC);
|
||||||
|
|
||||||
m_node.chainman->InitializeChainstate(*m_node.mempool);
|
m_node.chainman->InitializeChainstate(*m_node.mempool);
|
||||||
::ChainstateActive().InitCoinsDB(
|
m_node.chainman->ActiveChainstate().InitCoinsDB(
|
||||||
/* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
|
/* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
|
||||||
assert(!::ChainstateActive().CanFlushToDisk());
|
assert(!m_node.chainman->ActiveChainstate().CanFlushToDisk());
|
||||||
::ChainstateActive().InitCoinsCache(1 << 23);
|
m_node.chainman->ActiveChainstate().InitCoinsCache(1 << 23);
|
||||||
assert(::ChainstateActive().CanFlushToDisk());
|
assert(m_node.chainman->ActiveChainstate().CanFlushToDisk());
|
||||||
if (!::ChainstateActive().LoadGenesisBlock(chainparams)) {
|
if (!m_node.chainman->ActiveChainstate().LoadGenesisBlock(chainparams)) {
|
||||||
throw std::runtime_error("LoadGenesisBlock failed.");
|
throw std::runtime_error("LoadGenesisBlock failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockValidationState state;
|
BlockValidationState state;
|
||||||
if (!::ChainstateActive().ActivateBestChain(state, chainparams)) {
|
if (!m_node.chainman->ActiveChainstate().ActivateBestChain(state, chainparams)) {
|
||||||
throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", state.ToString()));
|
throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", state.ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +241,7 @@ CBlock TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransa
|
||||||
{
|
{
|
||||||
const CChainParams& chainparams = Params();
|
const CChainParams& chainparams = Params();
|
||||||
CTxMemPool empty_pool;
|
CTxMemPool empty_pool;
|
||||||
CBlock block = BlockAssembler(::ChainstateActive(), empty_pool, chainparams).CreateNewBlock(scriptPubKey)->block;
|
CBlock block = BlockAssembler(m_node.chainman->ActiveChainstate(), empty_pool, chainparams).CreateNewBlock(scriptPubKey)->block;
|
||||||
|
|
||||||
Assert(block.vtx.size() == 1);
|
Assert(block.vtx.size() == 1);
|
||||||
for (const CMutableTransaction& tx : txns) {
|
for (const CMutableTransaction& tx : txns) {
|
||||||
|
@ -300,7 +300,7 @@ CMutableTransaction TestChain100Setup::CreateValidMempoolTransaction(CTransactio
|
||||||
// If submit=true, add transaction to the mempool.
|
// If submit=true, add transaction to the mempool.
|
||||||
if (submit) {
|
if (submit) {
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
const MempoolAcceptResult result = AcceptToMemoryPool(::ChainstateActive(), *m_node.mempool.get(), MakeTransactionRef(mempool_txn), /* bypass_limits */ false);
|
const MempoolAcceptResult result = AcceptToMemoryPool(m_node.chainman->ActiveChainstate(), *m_node.mempool.get(), MakeTransactionRef(mempool_txn), /* bypass_limits */ false);
|
||||||
assert(result.m_result_type == MempoolAcceptResult::ResultType::VALID);
|
assert(result.m_result_type == MempoolAcceptResult::ResultType::VALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,8 +84,8 @@ std::shared_ptr<CBlock> MinerTestingSetup::Block(const uint256& prev_hash)
|
||||||
|
|
||||||
std::shared_ptr<CBlock> MinerTestingSetup::FinalizeBlock(std::shared_ptr<CBlock> pblock)
|
std::shared_ptr<CBlock> MinerTestingSetup::FinalizeBlock(std::shared_ptr<CBlock> pblock)
|
||||||
{
|
{
|
||||||
LOCK(cs_main); // For g_chainman.m_blockman.LookupBlockIndex
|
LOCK(cs_main); // For m_node.chainman->m_blockman.LookupBlockIndex
|
||||||
GenerateCoinbaseCommitment(*pblock, g_chainman.m_blockman.LookupBlockIndex(pblock->hashPrevBlock), Params().GetConsensus());
|
GenerateCoinbaseCommitment(*pblock, m_node.chainman->m_blockman.LookupBlockIndex(pblock->hashPrevBlock), Params().GetConsensus());
|
||||||
|
|
||||||
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
|
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
|
||||||
const CBlockIndex* initial_tip = nullptr;
|
const CBlockIndex* initial_tip = nullptr;
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
initial_tip = ::ChainActive().Tip();
|
initial_tip = m_node.chainman->ActiveChain().Tip();
|
||||||
}
|
}
|
||||||
auto sub = std::make_shared<TestSubscriber>(initial_tip->GetBlockHash());
|
auto sub = std::make_shared<TestSubscriber>(initial_tip->GetBlockHash());
|
||||||
RegisterSharedValidationInterface(sub);
|
RegisterSharedValidationInterface(sub);
|
||||||
|
@ -198,7 +198,7 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
|
||||||
UnregisterSharedValidationInterface(sub);
|
UnregisterSharedValidationInterface(sub);
|
||||||
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
BOOST_CHECK_EQUAL(sub->m_expected_tip, ::ChainActive().Tip()->GetBlockHash());
|
BOOST_CHECK_EQUAL(sub->m_expected_tip, m_node.chainman->ActiveChain().Tip()->GetBlockHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -232,7 +232,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
|
||||||
|
|
||||||
// Run the test multiple times
|
// Run the test multiple times
|
||||||
for (int test_runs = 3; test_runs > 0; --test_runs) {
|
for (int test_runs = 3; test_runs > 0; --test_runs) {
|
||||||
BOOST_CHECK_EQUAL(last_mined->GetHash(), ::ChainActive().Tip()->GetBlockHash());
|
BOOST_CHECK_EQUAL(last_mined->GetHash(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
|
||||||
|
|
||||||
// Later on split from here
|
// Later on split from here
|
||||||
const uint256 split_hash{last_mined->hashPrevBlock};
|
const uint256 split_hash{last_mined->hashPrevBlock};
|
||||||
|
@ -273,7 +273,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
for (const auto& tx : txs) {
|
for (const auto& tx : txs) {
|
||||||
const MempoolAcceptResult result = AcceptToMemoryPool(::ChainstateActive(), *m_node.mempool, tx, false /* bypass_limits */);
|
const MempoolAcceptResult result = AcceptToMemoryPool(m_node.chainman->ActiveChainstate(), *m_node.mempool, tx, false /* bypass_limits */);
|
||||||
BOOST_REQUIRE(result.m_result_type == MempoolAcceptResult::ResultType::VALID);
|
BOOST_REQUIRE(result.m_result_type == MempoolAcceptResult::ResultType::VALID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,7 +306,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
|
||||||
}
|
}
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
// We are done with the reorg, so the tip must have changed
|
// We are done with the reorg, so the tip must have changed
|
||||||
assert(tip_init != ::ChainActive().Tip()->GetBlockHash());
|
assert(tip_init != m_node.chainman->ActiveChain().Tip()->GetBlockHash());
|
||||||
}};
|
}};
|
||||||
|
|
||||||
// Submit the reorg in this thread to invalidate and remove the txs from the tx pool
|
// Submit the reorg in this thread to invalidate and remove the txs from the tx pool
|
||||||
|
@ -314,7 +314,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
|
||||||
ProcessBlock(b);
|
ProcessBlock(b);
|
||||||
}
|
}
|
||||||
// Check that the reorg was eventually successful
|
// Check that the reorg was eventually successful
|
||||||
BOOST_CHECK_EQUAL(last_mined->GetHash(), ::ChainActive().Tip()->GetBlockHash());
|
BOOST_CHECK_EQUAL(last_mined->GetHash(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
|
||||||
|
|
||||||
// We can join the other thread, which returns when the reorg was successful
|
// We can join the other thread, which returns when the reorg was successful
|
||||||
rpc_thread.join();
|
rpc_thread.join();
|
||||||
|
|
|
@ -513,7 +513,6 @@ void CTxMemPool::removeForReorg(CChainState& active_chainstate, int flags)
|
||||||
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
|
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
|
||||||
const CTransaction& tx = it->GetTx();
|
const CTransaction& tx = it->GetTx();
|
||||||
LockPoints lp = it->GetLockPoints();
|
LockPoints lp = it->GetLockPoints();
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
|
||||||
bool validLP = TestLockPointValidity(active_chainstate.m_chain, &lp);
|
bool validLP = TestLockPointValidity(active_chainstate.m_chain, &lp);
|
||||||
CCoinsViewMemPool view_mempool(&active_chainstate.CoinsTip(), *this);
|
CCoinsViewMemPool view_mempool(&active_chainstate.CoinsTip(), *this);
|
||||||
if (!CheckFinalTx(active_chainstate.m_chain.Tip(), tx, flags)
|
if (!CheckFinalTx(active_chainstate.m_chain.Tip(), tx, flags)
|
||||||
|
@ -638,10 +637,8 @@ void CTxMemPool::check(CChainState& active_chainstate) const
|
||||||
uint64_t innerUsage = 0;
|
uint64_t innerUsage = 0;
|
||||||
|
|
||||||
CCoinsViewCache& active_coins_tip = active_chainstate.CoinsTip();
|
CCoinsViewCache& active_coins_tip = active_chainstate.CoinsTip();
|
||||||
assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(active_coins_tip)); // TODO: REVIEW-ONLY, REMOVE IN FUTURE COMMIT
|
|
||||||
CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(&active_coins_tip));
|
CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(&active_coins_tip));
|
||||||
const int64_t spendheight = active_chainstate.m_chain.Height() + 1;
|
const int64_t spendheight = active_chainstate.m_chain.Height() + 1;
|
||||||
assert(g_chainman.m_blockman.GetSpendHeight(mempoolDuplicate) == spendheight); // TODO: REVIEW-ONLY, REMOVE IN FUTURE COMMIT
|
|
||||||
|
|
||||||
std::list<const CTxMemPoolEntry*> waitingOnDependants;
|
std::list<const CTxMemPoolEntry*> waitingOnDependants;
|
||||||
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
|
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
|
||||||
|
|
|
@ -101,21 +101,6 @@ bool CBlockIndexWorkComparator::operator()(const CBlockIndex *pa, const CBlockIn
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChainstateManager g_chainman;
|
|
||||||
|
|
||||||
CChainState& ChainstateActive()
|
|
||||||
{
|
|
||||||
LOCK(::cs_main);
|
|
||||||
assert(g_chainman.m_active_chainstate);
|
|
||||||
return *g_chainman.m_active_chainstate;
|
|
||||||
}
|
|
||||||
|
|
||||||
CChain& ChainActive()
|
|
||||||
{
|
|
||||||
LOCK(::cs_main);
|
|
||||||
return ::ChainstateActive().m_chain;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mutex to guard access to validation specific variables, such as reading
|
* Mutex to guard access to validation specific variables, such as reading
|
||||||
* or changing the chainstate.
|
* or changing the chainstate.
|
||||||
|
@ -161,7 +146,6 @@ void FlushBlockFile(bool fFinalize = false, bool finalize_undo = false);
|
||||||
CBlockIndex* BlockManager::LookupBlockIndex(const uint256& hash) const
|
CBlockIndex* BlockManager::LookupBlockIndex(const uint256& hash) const
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
assert(std::addressof(g_chainman.BlockIndex()) == std::addressof(m_block_index));
|
|
||||||
BlockMap::const_iterator it = m_block_index.find(hash);
|
BlockMap::const_iterator it = m_block_index.find(hash);
|
||||||
return it == m_block_index.end() ? nullptr : it->second;
|
return it == m_block_index.end() ? nullptr : it->second;
|
||||||
}
|
}
|
||||||
|
@ -170,7 +154,6 @@ CBlockIndex* BlockManager::FindForkInGlobalIndex(const CChain& chain, const CBlo
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
|
|
||||||
assert(std::addressof(g_chainman.m_blockman) == std::addressof(*this));
|
|
||||||
// Find the latest block common to locator and chain - we expect that
|
// Find the latest block common to locator and chain - we expect that
|
||||||
// locator.vHave is sorted descending by height.
|
// locator.vHave is sorted descending by height.
|
||||||
for (const uint256& hash : locator.vHave) {
|
for (const uint256& hash : locator.vHave) {
|
||||||
|
@ -198,7 +181,6 @@ bool CheckFinalTx(const CBlockIndex* active_chain_tip, const CTransaction &tx, i
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
assert(active_chain_tip); // TODO: Make active_chain_tip a reference
|
assert(active_chain_tip); // TODO: Make active_chain_tip a reference
|
||||||
assert(std::addressof(*::ChainActive().Tip()) == std::addressof(*active_chain_tip));
|
|
||||||
|
|
||||||
// By convention a negative value for flags indicates that the
|
// By convention a negative value for flags indicates that the
|
||||||
// current network-enforced consensus rules should be used. In
|
// current network-enforced consensus rules should be used. In
|
||||||
|
@ -237,7 +219,6 @@ bool TestLockPointValidity(CChain& active_chain, const LockPoints* lp)
|
||||||
if (lp->maxInputBlock) {
|
if (lp->maxInputBlock) {
|
||||||
// Check whether ::ChainActive() is an extension of the block at which the LockPoints
|
// Check whether ::ChainActive() is an extension of the block at which the LockPoints
|
||||||
// calculation was valid. If not LockPoints are no longer valid
|
// calculation was valid. If not LockPoints are no longer valid
|
||||||
assert(std::addressof(::ChainActive()) == std::addressof(active_chain));
|
|
||||||
if (!active_chain.Contains(lp->maxInputBlock)) {
|
if (!active_chain.Contains(lp->maxInputBlock)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -331,7 +312,6 @@ static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache, siz
|
||||||
|
|
||||||
std::vector<COutPoint> vNoSpendsRemaining;
|
std::vector<COutPoint> vNoSpendsRemaining;
|
||||||
pool.TrimToSize(limit, &vNoSpendsRemaining);
|
pool.TrimToSize(limit, &vNoSpendsRemaining);
|
||||||
assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(coins_cache));
|
|
||||||
for (const COutPoint& removed : vNoSpendsRemaining)
|
for (const COutPoint& removed : vNoSpendsRemaining)
|
||||||
coins_cache.Uncache(removed);
|
coins_cache.Uncache(removed);
|
||||||
}
|
}
|
||||||
|
@ -339,7 +319,6 @@ static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache, siz
|
||||||
static bool IsCurrentForFeeEstimation(CChainState& active_chainstate) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
static bool IsCurrentForFeeEstimation(CChainState& active_chainstate) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
|
||||||
if (active_chainstate.IsInitialBlockDownload())
|
if (active_chainstate.IsInitialBlockDownload())
|
||||||
return false;
|
return false;
|
||||||
if (active_chainstate.m_chain.Tip()->GetBlockTime() < count_seconds(GetTime<std::chrono::seconds>() - MAX_FEE_ESTIMATION_TIP_AGE))
|
if (active_chainstate.m_chain.Tip()->GetBlockTime() < count_seconds(GetTime<std::chrono::seconds>() - MAX_FEE_ESTIMATION_TIP_AGE))
|
||||||
|
@ -366,7 +345,6 @@ static void UpdateMempoolForReorg(CChainState& active_chainstate, CTxMemPool& me
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
AssertLockHeld(mempool.cs);
|
AssertLockHeld(mempool.cs);
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
|
||||||
std::vector<uint256> vHashUpdate;
|
std::vector<uint256> vHashUpdate;
|
||||||
// disconnectpool's insertion_order index sorts the entries from
|
// disconnectpool's insertion_order index sorts the entries from
|
||||||
// oldest to newest, but the oldest entry will be the last tx from the
|
// oldest to newest, but the oldest entry will be the last tx from the
|
||||||
|
@ -433,7 +411,6 @@ static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, TxValidationS
|
||||||
assert(txFrom->vout.size() > txin.prevout.n);
|
assert(txFrom->vout.size() > txin.prevout.n);
|
||||||
assert(txFrom->vout[txin.prevout.n] == coin.out);
|
assert(txFrom->vout[txin.prevout.n] == coin.out);
|
||||||
} else {
|
} else {
|
||||||
assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(coins_tip));
|
|
||||||
const Coin& coinFromUTXOSet = coins_tip.AccessCoin(txin.prevout);
|
const Coin& coinFromUTXOSet = coins_tip.AccessCoin(txin.prevout);
|
||||||
assert(!coinFromUTXOSet.IsSpent());
|
assert(!coinFromUTXOSet.IsSpent());
|
||||||
assert(coinFromUTXOSet.out == coin.out);
|
assert(coinFromUTXOSet.out == coin.out);
|
||||||
|
@ -454,7 +431,6 @@ public:
|
||||||
m_limit_ancestor_size(gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000),
|
m_limit_ancestor_size(gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000),
|
||||||
m_limit_descendants(gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT)),
|
m_limit_descendants(gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT)),
|
||||||
m_limit_descendant_size(gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000) {
|
m_limit_descendant_size(gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000) {
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(m_active_chainstate));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We put the arguments we're handed into a struct, so we can pass them
|
// We put the arguments we're handed into a struct, so we can pass them
|
||||||
|
@ -607,7 +583,6 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||||
// Only accept nLockTime-using transactions that can be mined in the next
|
// Only accept nLockTime-using transactions that can be mined in the next
|
||||||
// block; we don't want our mempool filled up with transactions that can't
|
// block; we don't want our mempool filled up with transactions that can't
|
||||||
// be mined yet.
|
// be mined yet.
|
||||||
assert(std::addressof(::ChainActive()) == std::addressof(m_active_chainstate.m_chain));
|
|
||||||
if (!CheckFinalTx(m_active_chainstate.m_chain.Tip(), tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
|
if (!CheckFinalTx(m_active_chainstate.m_chain.Tip(), tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
|
||||||
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-final");
|
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-final");
|
||||||
|
|
||||||
|
@ -663,7 +638,6 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||||
LockPoints lp;
|
LockPoints lp;
|
||||||
m_view.SetBackend(m_viewmempool);
|
m_view.SetBackend(m_viewmempool);
|
||||||
|
|
||||||
assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(m_active_chainstate.CoinsTip()));
|
|
||||||
const CCoinsViewCache& coins_cache = m_active_chainstate.CoinsTip();
|
const CCoinsViewCache& coins_cache = m_active_chainstate.CoinsTip();
|
||||||
// do all inputs exist?
|
// do all inputs exist?
|
||||||
for (const CTxIn& txin : tx.vin) {
|
for (const CTxIn& txin : tx.vin) {
|
||||||
|
@ -701,18 +675,15 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||||
// be mined yet.
|
// be mined yet.
|
||||||
// Pass in m_view which has all of the relevant inputs cached. Note that, since m_view's
|
// Pass in m_view which has all of the relevant inputs cached. Note that, since m_view's
|
||||||
// backend was removed, it no longer pulls coins from the mempool.
|
// backend was removed, it no longer pulls coins from the mempool.
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(m_active_chainstate));
|
|
||||||
if (!CheckSequenceLocks(m_active_chainstate.m_chain.Tip(), m_view, tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
|
if (!CheckSequenceLocks(m_active_chainstate.m_chain.Tip(), m_view, tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
|
||||||
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-BIP68-final");
|
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-BIP68-final");
|
||||||
|
|
||||||
assert(std::addressof(g_chainman.m_blockman) == std::addressof(m_active_chainstate.m_blockman));
|
|
||||||
if (!Consensus::CheckTxInputs(tx, state, m_view, m_active_chainstate.m_blockman.GetSpendHeight(m_view), ws.m_base_fees)) {
|
if (!Consensus::CheckTxInputs(tx, state, m_view, m_active_chainstate.m_blockman.GetSpendHeight(m_view), ws.m_base_fees)) {
|
||||||
return false; // state filled in by CheckTxInputs
|
return false; // state filled in by CheckTxInputs
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 auto& params = args.m_chainparams.GetConsensus();
|
||||||
assert(std::addressof(::ChainActive()) == std::addressof(m_active_chainstate.m_chain));
|
|
||||||
auto taproot_state = VersionBitsState(m_active_chainstate.m_chain.Tip(), params, Consensus::DEPLOYMENT_TAPROOT, versionbitscache);
|
auto taproot_state = VersionBitsState(m_active_chainstate.m_chain.Tip(), params, Consensus::DEPLOYMENT_TAPROOT, versionbitscache);
|
||||||
if (fRequireStandard && !AreInputsStandard(tx, m_view, taproot_state == ThresholdState::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");
|
||||||
|
@ -739,7 +710,6 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(std::addressof(::ChainActive()) == std::addressof(m_active_chainstate.m_chain));
|
|
||||||
entry.reset(new CTxMemPoolEntry(ptx, ws.m_base_fees, nAcceptTime, m_active_chainstate.m_chain.Height(),
|
entry.reset(new CTxMemPoolEntry(ptx, ws.m_base_fees, nAcceptTime, m_active_chainstate.m_chain.Height(),
|
||||||
fSpendsCoinbase, nSigOpsCost, lp));
|
fSpendsCoinbase, nSigOpsCost, lp));
|
||||||
unsigned int nSize = entry->GetTxSize();
|
unsigned int nSize = entry->GetTxSize();
|
||||||
|
@ -992,9 +962,7 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws, P
|
||||||
// There is a similar check in CreateNewBlock() to prevent creating
|
// There is a similar check in CreateNewBlock() to prevent creating
|
||||||
// invalid blocks (using TestBlockValidity), however allowing such
|
// invalid blocks (using TestBlockValidity), however allowing such
|
||||||
// transactions into the mempool can be exploited as a DoS attack.
|
// transactions into the mempool can be exploited as a DoS attack.
|
||||||
assert(std::addressof(::ChainActive()) == std::addressof(m_active_chainstate.m_chain));
|
|
||||||
unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(m_active_chainstate.m_chain.Tip(), chainparams.GetConsensus());
|
unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(m_active_chainstate.m_chain.Tip(), chainparams.GetConsensus());
|
||||||
assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(m_active_chainstate.CoinsTip()));
|
|
||||||
if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags, txdata, m_active_chainstate.CoinsTip())) {
|
if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags, txdata, m_active_chainstate.CoinsTip())) {
|
||||||
return error("%s: BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s",
|
return error("%s: BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s",
|
||||||
__func__, hash.ToString(), state.ToString());
|
__func__, hash.ToString(), state.ToString());
|
||||||
|
@ -1035,7 +1003,6 @@ bool MemPoolAccept::Finalize(const ATMPArgs& args, Workspace& ws)
|
||||||
// - it's not being re-added during a reorg which bypasses typical mempool fee limits
|
// - it's not being re-added during a reorg which bypasses typical mempool fee limits
|
||||||
// - the node is not behind
|
// - the node is not behind
|
||||||
// - the transaction is not dependent on any other transactions in the mempool
|
// - the transaction is not dependent on any other transactions in the mempool
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(m_active_chainstate));
|
|
||||||
bool validForFeeEstimation = !fReplacementTransaction && !bypass_limits && IsCurrentForFeeEstimation(m_active_chainstate) && m_pool.HasNoInputsOf(tx);
|
bool validForFeeEstimation = !fReplacementTransaction && !bypass_limits && IsCurrentForFeeEstimation(m_active_chainstate) && m_pool.HasNoInputsOf(tx);
|
||||||
|
|
||||||
// Store transaction in memory
|
// Store transaction in memory
|
||||||
|
@ -1043,7 +1010,6 @@ bool MemPoolAccept::Finalize(const ATMPArgs& args, Workspace& ws)
|
||||||
|
|
||||||
// trim mempool and check if tx was trimmed
|
// trim mempool and check if tx was trimmed
|
||||||
if (!bypass_limits) {
|
if (!bypass_limits) {
|
||||||
assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(m_active_chainstate.CoinsTip()));
|
|
||||||
LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip(), gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, std::chrono::hours{gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
|
LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip(), gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, std::chrono::hours{gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
|
||||||
if (!m_pool.exists(hash))
|
if (!m_pool.exists(hash))
|
||||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool full");
|
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool full");
|
||||||
|
@ -1146,7 +1112,6 @@ static MempoolAcceptResult AcceptToMemoryPoolWithTime(const CChainParams& chainp
|
||||||
MemPoolAccept::ATMPArgs args { chainparams, nAcceptTime, bypass_limits, coins_to_uncache,
|
MemPoolAccept::ATMPArgs args { chainparams, nAcceptTime, bypass_limits, coins_to_uncache,
|
||||||
test_accept, /* m_allow_bip125_replacement */ true };
|
test_accept, /* m_allow_bip125_replacement */ true };
|
||||||
|
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
|
||||||
const MempoolAcceptResult result = MemPoolAccept(pool, active_chainstate).AcceptSingleTransaction(tx, args);
|
const MempoolAcceptResult result = MemPoolAccept(pool, active_chainstate).AcceptSingleTransaction(tx, args);
|
||||||
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
|
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
|
||||||
// Remove coins that were not present in the coins cache before calling
|
// Remove coins that were not present in the coins cache before calling
|
||||||
|
@ -1166,7 +1131,6 @@ static MempoolAcceptResult AcceptToMemoryPoolWithTime(const CChainParams& chainp
|
||||||
MempoolAcceptResult AcceptToMemoryPool(CChainState& active_chainstate, CTxMemPool& pool, const CTransactionRef& tx,
|
MempoolAcceptResult AcceptToMemoryPool(CChainState& active_chainstate, CTxMemPool& pool, const CTransactionRef& tx,
|
||||||
bool bypass_limits, bool test_accept)
|
bool bypass_limits, bool test_accept)
|
||||||
{
|
{
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
|
||||||
return AcceptToMemoryPoolWithTime(Params(), pool, active_chainstate, tx, GetTime(), bypass_limits, test_accept);
|
return AcceptToMemoryPoolWithTime(Params(), pool, active_chainstate, tx, GetTime(), bypass_limits, test_accept);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1182,7 +1146,6 @@ PackageMempoolAcceptResult ProcessNewPackage(CChainState& active_chainstate, CTx
|
||||||
const CChainParams& chainparams = Params();
|
const CChainParams& chainparams = Params();
|
||||||
MemPoolAccept::ATMPArgs args { chainparams, GetTime(), /* bypass_limits */ false, coins_to_uncache,
|
MemPoolAccept::ATMPArgs args { chainparams, GetTime(), /* bypass_limits */ false, coins_to_uncache,
|
||||||
test_accept, /* m_allow_bip125_replacement */ false };
|
test_accept, /* m_allow_bip125_replacement */ false };
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
|
||||||
const PackageMempoolAcceptResult result = MemPoolAccept(pool, active_chainstate).AcceptMultipleTransactions(package, args);
|
const PackageMempoolAcceptResult result = MemPoolAccept(pool, active_chainstate).AcceptMultipleTransactions(package, args);
|
||||||
|
|
||||||
// Uncache coins pertaining to transactions that were not submitted to the mempool.
|
// Uncache coins pertaining to transactions that were not submitted to the mempool.
|
||||||
|
@ -1321,7 +1284,6 @@ static void AlertNotify(const std::string& strMessage)
|
||||||
void CChainState::CheckForkWarningConditions()
|
void CChainState::CheckForkWarningConditions()
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(*this));
|
|
||||||
|
|
||||||
// Before we get past initial download, we cannot reliably alert about forks
|
// Before we get past initial download, we cannot reliably alert about forks
|
||||||
// (we assume we don't get stuck on a fork before finishing our initial sync)
|
// (we assume we don't get stuck on a fork before finishing our initial sync)
|
||||||
|
@ -1340,7 +1302,6 @@ void CChainState::CheckForkWarningConditions()
|
||||||
// Called both upon regular invalid block discovery *and* InvalidateBlock
|
// Called both upon regular invalid block discovery *and* InvalidateBlock
|
||||||
void CChainState::InvalidChainFound(CBlockIndex* pindexNew)
|
void CChainState::InvalidChainFound(CBlockIndex* pindexNew)
|
||||||
{
|
{
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(*this));
|
|
||||||
if (!pindexBestInvalid || pindexNew->nChainWork > pindexBestInvalid->nChainWork)
|
if (!pindexBestInvalid || pindexNew->nChainWork > pindexBestInvalid->nChainWork)
|
||||||
pindexBestInvalid = pindexNew;
|
pindexBestInvalid = pindexNew;
|
||||||
if (pindexBestHeader != nullptr && pindexBestHeader->GetAncestor(pindexNew->nHeight) == pindexNew) {
|
if (pindexBestHeader != nullptr && pindexBestHeader->GetAncestor(pindexNew->nHeight) == pindexNew) {
|
||||||
|
@ -1401,7 +1362,6 @@ bool CScriptCheck::operator()() {
|
||||||
int BlockManager::GetSpendHeight(const CCoinsViewCache& inputs)
|
int BlockManager::GetSpendHeight(const CCoinsViewCache& inputs)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
assert(std::addressof(g_chainman.m_blockman) == std::addressof(*this));
|
|
||||||
CBlockIndex* pindexPrev = LookupBlockIndex(inputs.GetBestBlock());
|
CBlockIndex* pindexPrev = LookupBlockIndex(inputs.GetBestBlock());
|
||||||
return pindexPrev->nHeight + 1;
|
return pindexPrev->nHeight + 1;
|
||||||
}
|
}
|
||||||
|
@ -2285,7 +2245,6 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C
|
||||||
}
|
}
|
||||||
|
|
||||||
bilingual_str warning_messages;
|
bilingual_str warning_messages;
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
|
||||||
if (!active_chainstate.IsInitialBlockDownload()) {
|
if (!active_chainstate.IsInitialBlockDownload()) {
|
||||||
const CBlockIndex* pindex = pindexNew;
|
const CBlockIndex* pindex = pindexNew;
|
||||||
for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) {
|
for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) {
|
||||||
|
@ -2301,7 +2260,6 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
|
||||||
LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%f tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)%s\n", __func__,
|
LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%f tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)%s\n", __func__,
|
||||||
pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, pindexNew->nVersion,
|
pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, pindexNew->nVersion,
|
||||||
log(pindexNew->nChainWork.getdouble())/log(2.0), (unsigned long)pindexNew->nChainTx,
|
log(pindexNew->nChainWork.getdouble())/log(2.0), (unsigned long)pindexNew->nChainTx,
|
||||||
|
@ -2561,7 +2519,6 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
AssertLockHeld(m_mempool.cs);
|
AssertLockHeld(m_mempool.cs);
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(*this));
|
|
||||||
|
|
||||||
const CBlockIndex* pindexOldTip = m_chain.Tip();
|
const CBlockIndex* pindexOldTip = m_chain.Tip();
|
||||||
const CBlockIndex* pindexFork = m_chain.FindFork(pindexMostWork);
|
const CBlockIndex* pindexFork = m_chain.FindFork(pindexMostWork);
|
||||||
|
@ -2661,7 +2618,6 @@ static bool NotifyHeaderTip(CChainState& chainstate) LOCKS_EXCLUDED(cs_main) {
|
||||||
|
|
||||||
if (pindexHeader != pindexHeaderOld) {
|
if (pindexHeader != pindexHeaderOld) {
|
||||||
fNotify = true;
|
fNotify = true;
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(chainstate));
|
|
||||||
fInitialBlockDownload = chainstate.IsInitialBlockDownload();
|
fInitialBlockDownload = chainstate.IsInitialBlockDownload();
|
||||||
pindexHeaderOld = pindexHeader;
|
pindexHeaderOld = pindexHeader;
|
||||||
}
|
}
|
||||||
|
@ -2872,7 +2828,6 @@ bool CChainState::InvalidateBlock(BlockValidationState& state, const CChainParam
|
||||||
// transactions back to the mempool if disconnecting was successful,
|
// transactions back to the mempool if disconnecting was successful,
|
||||||
// and we're not doing a very deep invalidation (in which case
|
// and we're not doing a very deep invalidation (in which case
|
||||||
// keeping the mempool up to date is probably futile anyway).
|
// keeping the mempool up to date is probably futile anyway).
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(*this));
|
|
||||||
UpdateMempoolForReorg(*this, m_mempool, disconnectpool, /* fAddToMempool = */ (++disconnected <= 10) && ret);
|
UpdateMempoolForReorg(*this, m_mempool, disconnectpool, /* fAddToMempool = */ (++disconnected <= 10) && ret);
|
||||||
if (!ret) return false;
|
if (!ret) return false;
|
||||||
assert(invalid_walk_tip->pprev == m_chain.Tip());
|
assert(invalid_walk_tip->pprev == m_chain.Tip());
|
||||||
|
@ -3203,7 +3158,6 @@ CBlockIndex* BlockManager::GetLastCheckpoint(const CCheckpointData& data)
|
||||||
for (const MapCheckpoints::value_type& i : reverse_iterate(checkpoints))
|
for (const MapCheckpoints::value_type& i : reverse_iterate(checkpoints))
|
||||||
{
|
{
|
||||||
const uint256& hash = i.second;
|
const uint256& hash = i.second;
|
||||||
assert(std::addressof(g_chainman.m_blockman) == std::addressof(*this));
|
|
||||||
CBlockIndex* pindex = LookupBlockIndex(hash);
|
CBlockIndex* pindex = LookupBlockIndex(hash);
|
||||||
if (pindex) {
|
if (pindex) {
|
||||||
return pindex;
|
return pindex;
|
||||||
|
@ -3236,7 +3190,6 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio
|
||||||
// Don't accept any forks from the main chain prior to last checkpoint.
|
// Don't accept any forks from the main chain prior to last checkpoint.
|
||||||
// GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our
|
// GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our
|
||||||
// BlockIndex().
|
// BlockIndex().
|
||||||
assert(std::addressof(g_chainman.m_blockman) == std::addressof(blockman));
|
|
||||||
CBlockIndex* pcheckpoint = blockman.GetLastCheckpoint(params.Checkpoints());
|
CBlockIndex* pcheckpoint = blockman.GetLastCheckpoint(params.Checkpoints());
|
||||||
if (pcheckpoint && nHeight < pcheckpoint->nHeight) {
|
if (pcheckpoint && nHeight < pcheckpoint->nHeight) {
|
||||||
LogPrintf("ERROR: %s: forked chain older than last checkpoint (height %d)\n", __func__, nHeight);
|
LogPrintf("ERROR: %s: forked chain older than last checkpoint (height %d)\n", __func__, nHeight);
|
||||||
|
@ -3440,7 +3393,6 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationS
|
||||||
// Exposed wrapper for AcceptBlockHeader
|
// 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 CChainParams& chainparams, const CBlockIndex** ppindex)
|
||||||
{
|
{
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(ActiveChainstate()));
|
|
||||||
AssertLockNotHeld(cs_main);
|
AssertLockNotHeld(cs_main);
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
@ -3531,7 +3483,6 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, Block
|
||||||
|
|
||||||
// Write block to history file
|
// Write block to history file
|
||||||
if (fNewBlock) *fNewBlock = true;
|
if (fNewBlock) *fNewBlock = true;
|
||||||
assert(std::addressof(::ChainActive()) == std::addressof(m_chain));
|
|
||||||
try {
|
try {
|
||||||
FlatFilePos blockPos = SaveBlockToDisk(block, pindex->nHeight, m_chain, chainparams, dbp);
|
FlatFilePos blockPos = SaveBlockToDisk(block, pindex->nHeight, m_chain, chainparams, dbp);
|
||||||
if (blockPos.IsNull()) {
|
if (blockPos.IsNull()) {
|
||||||
|
@ -3553,7 +3504,6 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, Block
|
||||||
bool ChainstateManager::ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<const CBlock>& block, bool force_processing, bool* new_block)
|
bool ChainstateManager::ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<const CBlock>& block, bool force_processing, bool* new_block)
|
||||||
{
|
{
|
||||||
AssertLockNotHeld(cs_main);
|
AssertLockNotHeld(cs_main);
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(ActiveChainstate()));
|
|
||||||
|
|
||||||
{
|
{
|
||||||
CBlockIndex *pindex = nullptr;
|
CBlockIndex *pindex = nullptr;
|
||||||
|
@ -3598,7 +3548,6 @@ bool TestBlockValidity(BlockValidationState& state,
|
||||||
bool fCheckMerkleRoot)
|
bool fCheckMerkleRoot)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(chainstate));
|
|
||||||
assert(pindexPrev && pindexPrev == chainstate.m_chain.Tip());
|
assert(pindexPrev && pindexPrev == chainstate.m_chain.Tip());
|
||||||
CCoinsViewCache viewNew(&chainstate.CoinsTip());
|
CCoinsViewCache viewNew(&chainstate.CoinsTip());
|
||||||
uint256 block_hash(block.GetHash());
|
uint256 block_hash(block.GetHash());
|
||||||
|
@ -3608,7 +3557,6 @@ bool TestBlockValidity(BlockValidationState& state,
|
||||||
indexDummy.phashBlock = &block_hash;
|
indexDummy.phashBlock = &block_hash;
|
||||||
|
|
||||||
// NOTE: CheckBlockHeader is called by CheckBlock
|
// NOTE: CheckBlockHeader is called by CheckBlock
|
||||||
assert(std::addressof(g_chainman.m_blockman) == std::addressof(chainstate.m_blockman));
|
|
||||||
if (!ContextualCheckBlockHeader(block, state, chainstate.m_blockman, chainparams, pindexPrev, GetAdjustedTime()))
|
if (!ContextualCheckBlockHeader(block, state, chainstate.m_blockman, chainparams, pindexPrev, GetAdjustedTime()))
|
||||||
return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, state.ToString());
|
return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, state.ToString());
|
||||||
if (!CheckBlock(block, state, chainparams.GetConsensus(), fCheckPOW, fCheckMerkleRoot))
|
if (!CheckBlock(block, state, chainparams.GetConsensus(), fCheckPOW, fCheckMerkleRoot))
|
||||||
|
@ -3688,7 +3636,6 @@ void PruneBlockFilesManual(CChainState& active_chainstate, int nManualPruneHeigh
|
||||||
{
|
{
|
||||||
BlockValidationState state;
|
BlockValidationState state;
|
||||||
const CChainParams& chainparams = Params();
|
const CChainParams& chainparams = Params();
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
|
||||||
if (!active_chainstate.FlushStateToDisk(
|
if (!active_chainstate.FlushStateToDisk(
|
||||||
chainparams, state, FlushStateMode::NONE, nManualPruneHeight)) {
|
chainparams, state, FlushStateMode::NONE, nManualPruneHeight)) {
|
||||||
LogPrintf("%s: failed to flush state (%s)\n", __func__, state.ToString());
|
LogPrintf("%s: failed to flush state (%s)\n", __func__, state.ToString());
|
||||||
|
@ -3842,7 +3789,6 @@ void BlockManager::Unload() {
|
||||||
|
|
||||||
bool CChainState::LoadBlockIndexDB(const CChainParams& chainparams)
|
bool CChainState::LoadBlockIndexDB(const CChainParams& chainparams)
|
||||||
{
|
{
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(*this));
|
|
||||||
if (!m_blockman.LoadBlockIndex(
|
if (!m_blockman.LoadBlockIndex(
|
||||||
chainparams.GetConsensus(), *pblocktree,
|
chainparams.GetConsensus(), *pblocktree,
|
||||||
setBlockIndexCandidates)) {
|
setBlockIndexCandidates)) {
|
||||||
|
@ -3899,7 +3845,6 @@ bool CChainState::LoadBlockIndexDB(const CChainParams& chainparams)
|
||||||
void CChainState::LoadMempool(const ArgsManager& args)
|
void CChainState::LoadMempool(const ArgsManager& args)
|
||||||
{
|
{
|
||||||
if (args.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
|
if (args.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(*this));
|
|
||||||
::LoadMempool(m_mempool, *this);
|
::LoadMempool(m_mempool, *this);
|
||||||
}
|
}
|
||||||
m_mempool.SetIsLoaded(!ShutdownRequested());
|
m_mempool.SetIsLoaded(!ShutdownRequested());
|
||||||
|
@ -3951,7 +3896,6 @@ bool CVerifyDB::VerifyDB(
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
|
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(chainstate));
|
|
||||||
if (chainstate.m_chain.Tip() == nullptr || chainstate.m_chain.Tip()->pprev == nullptr)
|
if (chainstate.m_chain.Tip() == nullptr || chainstate.m_chain.Tip()->pprev == nullptr)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -4220,7 +4164,6 @@ bool CChainState::LoadGenesisBlock(const CChainParams& chainparams)
|
||||||
if (m_blockman.m_block_index.count(chainparams.GenesisBlock().GetHash()))
|
if (m_blockman.m_block_index.count(chainparams.GenesisBlock().GetHash()))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
assert(std::addressof(::ChainActive()) == std::addressof(m_chain));
|
|
||||||
try {
|
try {
|
||||||
const CBlock& block = chainparams.GenesisBlock();
|
const CBlock& block = chainparams.GenesisBlock();
|
||||||
FlatFilePos blockPos = SaveBlockToDisk(block, 0, m_chain, chainparams, nullptr);
|
FlatFilePos blockPos = SaveBlockToDisk(block, 0, m_chain, chainparams, nullptr);
|
||||||
|
@ -4284,7 +4227,6 @@ void CChainState::LoadExternalBlockFile(const CChainParams& chainparams, FILE* f
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
// detect out of order blocks, and store them for later
|
// detect out of order blocks, and store them for later
|
||||||
assert(std::addressof(g_chainman.m_blockman) == std::addressof(m_blockman));
|
|
||||||
if (hash != chainparams.GetConsensus().hashGenesisBlock && !m_blockman.LookupBlockIndex(block.hashPrevBlock)) {
|
if (hash != chainparams.GetConsensus().hashGenesisBlock && !m_blockman.LookupBlockIndex(block.hashPrevBlock)) {
|
||||||
LogPrint(BCLog::REINDEX, "%s: Out of order block %s, parent %s not known\n", __func__, hash.ToString(),
|
LogPrint(BCLog::REINDEX, "%s: Out of order block %s, parent %s not known\n", __func__, hash.ToString(),
|
||||||
block.hashPrevBlock.ToString());
|
block.hashPrevBlock.ToString());
|
||||||
|
@ -4294,11 +4236,9 @@ void CChainState::LoadExternalBlockFile(const CChainParams& chainparams, FILE* f
|
||||||
}
|
}
|
||||||
|
|
||||||
// process in case the block isn't known yet
|
// process in case the block isn't known yet
|
||||||
assert(std::addressof(g_chainman.m_blockman) == std::addressof(m_blockman));
|
|
||||||
CBlockIndex* pindex = m_blockman.LookupBlockIndex(hash);
|
CBlockIndex* pindex = m_blockman.LookupBlockIndex(hash);
|
||||||
if (!pindex || (pindex->nStatus & BLOCK_HAVE_DATA) == 0) {
|
if (!pindex || (pindex->nStatus & BLOCK_HAVE_DATA) == 0) {
|
||||||
BlockValidationState state;
|
BlockValidationState state;
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(*this));
|
|
||||||
if (AcceptBlock(pblock, state, chainparams, nullptr, true, dbp, nullptr)) {
|
if (AcceptBlock(pblock, state, chainparams, nullptr, true, dbp, nullptr)) {
|
||||||
nLoaded++;
|
nLoaded++;
|
||||||
}
|
}
|
||||||
|
@ -4313,13 +4253,11 @@ void CChainState::LoadExternalBlockFile(const CChainParams& chainparams, FILE* f
|
||||||
// Activate the genesis block so normal node progress can continue
|
// Activate the genesis block so normal node progress can continue
|
||||||
if (hash == chainparams.GetConsensus().hashGenesisBlock) {
|
if (hash == chainparams.GetConsensus().hashGenesisBlock) {
|
||||||
BlockValidationState state;
|
BlockValidationState state;
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(*this));
|
|
||||||
if (!ActivateBestChain(state, chainparams, nullptr)) {
|
if (!ActivateBestChain(state, chainparams, nullptr)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(*this));
|
|
||||||
NotifyHeaderTip(*this);
|
NotifyHeaderTip(*this);
|
||||||
|
|
||||||
// Recursively process earlier encountered successors of this block
|
// Recursively process earlier encountered successors of this block
|
||||||
|
@ -4338,7 +4276,6 @@ void CChainState::LoadExternalBlockFile(const CChainParams& chainparams, FILE* f
|
||||||
head.ToString());
|
head.ToString());
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
BlockValidationState dummy;
|
BlockValidationState dummy;
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(*this));
|
|
||||||
if (AcceptBlock(pblockrecursive, dummy, chainparams, nullptr, true, &it->second, nullptr))
|
if (AcceptBlock(pblockrecursive, dummy, chainparams, nullptr, true, &it->second, nullptr))
|
||||||
{
|
{
|
||||||
nLoaded++;
|
nLoaded++;
|
||||||
|
@ -4347,7 +4284,6 @@ void CChainState::LoadExternalBlockFile(const CChainParams& chainparams, FILE* f
|
||||||
}
|
}
|
||||||
range.first++;
|
range.first++;
|
||||||
mapBlocksUnknownParent.erase(it);
|
mapBlocksUnknownParent.erase(it);
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(*this));
|
|
||||||
NotifyHeaderTip(*this);
|
NotifyHeaderTip(*this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4628,7 +4564,6 @@ bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate, FopenFn mocka
|
||||||
}
|
}
|
||||||
if (nTime > nNow - nExpiryTimeout) {
|
if (nTime > nNow - nExpiryTimeout) {
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
|
||||||
if (AcceptToMemoryPoolWithTime(chainparams, pool, active_chainstate, tx, nTime, false /* bypass_limits */,
|
if (AcceptToMemoryPoolWithTime(chainparams, pool, active_chainstate, tx, nTime, false /* bypass_limits */,
|
||||||
false /* test_accept */).m_result_type == MempoolAcceptResult::ResultType::VALID) {
|
false /* test_accept */).m_result_type == MempoolAcceptResult::ResultType::VALID) {
|
||||||
++count;
|
++count;
|
||||||
|
|
|
@ -891,10 +891,6 @@ private:
|
||||||
CAutoFile& coins_file,
|
CAutoFile& coins_file,
|
||||||
const SnapshotMetadata& metadata);
|
const SnapshotMetadata& metadata);
|
||||||
|
|
||||||
// For access to m_active_chainstate.
|
|
||||||
friend CChainState& ChainstateActive();
|
|
||||||
friend CChain& ChainActive();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::thread m_load_block;
|
std::thread m_load_block;
|
||||||
//! A single BlockManager instance is shared across each constructed
|
//! A single BlockManager instance is shared across each constructed
|
||||||
|
@ -1017,17 +1013,14 @@ public:
|
||||||
//! Check to see if caches are out of balance and if so, call
|
//! Check to see if caches are out of balance and if so, call
|
||||||
//! ResizeCoinsCaches() as needed.
|
//! ResizeCoinsCaches() as needed.
|
||||||
void MaybeRebalanceCaches() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
void MaybeRebalanceCaches() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||||
|
|
||||||
|
~ChainstateManager() {
|
||||||
|
LOCK(::cs_main);
|
||||||
|
UnloadBlockIndex(/* mempool */ nullptr, *this);
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** DEPRECATED! Please use node.chainman instead. May only be used in validation.cpp internally */
|
|
||||||
extern ChainstateManager g_chainman GUARDED_BY(::cs_main);
|
|
||||||
|
|
||||||
/** Please prefer the identical ChainstateManager::ActiveChainstate */
|
|
||||||
CChainState& ChainstateActive();
|
|
||||||
|
|
||||||
/** Please prefer the identical ChainstateManager::ActiveChain */
|
|
||||||
CChain& ChainActive();
|
|
||||||
|
|
||||||
/** 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;
|
||||||
|
|
||||||
|
|
|
@ -83,17 +83,17 @@ static void AddKey(CWallet& wallet, const CKey& key)
|
||||||
BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
|
BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
|
||||||
{
|
{
|
||||||
// Cap last block file size, and mine new block in a new block file.
|
// Cap last block file size, and mine new block in a new block file.
|
||||||
CBlockIndex* oldTip = ::ChainActive().Tip();
|
CBlockIndex* oldTip = m_node.chainman->ActiveChain().Tip();
|
||||||
GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE;
|
GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE;
|
||||||
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
|
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
|
||||||
CBlockIndex* newTip = ::ChainActive().Tip();
|
CBlockIndex* newTip = m_node.chainman->ActiveChain().Tip();
|
||||||
|
|
||||||
// Verify ScanForWalletTransactions fails to read an unknown start block.
|
// Verify ScanForWalletTransactions fails to read an unknown start block.
|
||||||
{
|
{
|
||||||
CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
|
CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
|
||||||
{
|
{
|
||||||
LOCK(wallet.cs_wallet);
|
LOCK(wallet.cs_wallet);
|
||||||
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
|
wallet.SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
|
||||||
}
|
}
|
||||||
AddKey(wallet, coinbaseKey);
|
AddKey(wallet, coinbaseKey);
|
||||||
WalletRescanReserver reserver(wallet);
|
WalletRescanReserver reserver(wallet);
|
||||||
|
@ -112,7 +112,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
|
||||||
CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
|
CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
|
||||||
{
|
{
|
||||||
LOCK(wallet.cs_wallet);
|
LOCK(wallet.cs_wallet);
|
||||||
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
|
wallet.SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
|
||||||
}
|
}
|
||||||
AddKey(wallet, coinbaseKey);
|
AddKey(wallet, coinbaseKey);
|
||||||
WalletRescanReserver reserver(wallet);
|
WalletRescanReserver reserver(wallet);
|
||||||
|
@ -138,7 +138,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
|
||||||
CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
|
CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
|
||||||
{
|
{
|
||||||
LOCK(wallet.cs_wallet);
|
LOCK(wallet.cs_wallet);
|
||||||
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
|
wallet.SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
|
||||||
}
|
}
|
||||||
AddKey(wallet, coinbaseKey);
|
AddKey(wallet, coinbaseKey);
|
||||||
WalletRescanReserver reserver(wallet);
|
WalletRescanReserver reserver(wallet);
|
||||||
|
@ -163,7 +163,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
|
||||||
CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
|
CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
|
||||||
{
|
{
|
||||||
LOCK(wallet.cs_wallet);
|
LOCK(wallet.cs_wallet);
|
||||||
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
|
wallet.SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
|
||||||
}
|
}
|
||||||
AddKey(wallet, coinbaseKey);
|
AddKey(wallet, coinbaseKey);
|
||||||
WalletRescanReserver reserver(wallet);
|
WalletRescanReserver reserver(wallet);
|
||||||
|
@ -180,10 +180,10 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
|
||||||
BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
|
BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
|
||||||
{
|
{
|
||||||
// Cap last block file size, and mine new block in a new block file.
|
// Cap last block file size, and mine new block in a new block file.
|
||||||
CBlockIndex* oldTip = ::ChainActive().Tip();
|
CBlockIndex* oldTip = m_node.chainman->ActiveChain().Tip();
|
||||||
GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE;
|
GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE;
|
||||||
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
|
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
|
||||||
CBlockIndex* newTip = ::ChainActive().Tip();
|
CBlockIndex* newTip = m_node.chainman->ActiveChain().Tip();
|
||||||
|
|
||||||
// Prune the older block file.
|
// Prune the older block file.
|
||||||
{
|
{
|
||||||
|
@ -242,7 +242,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
|
||||||
{
|
{
|
||||||
// Create two blocks with same timestamp to verify that importwallet rescan
|
// Create two blocks with same timestamp to verify that importwallet rescan
|
||||||
// will pick up both blocks, not just the first.
|
// will pick up both blocks, not just the first.
|
||||||
const int64_t BLOCK_TIME = ::ChainActive().Tip()->GetBlockTimeMax() + 5;
|
const int64_t BLOCK_TIME = m_node.chainman->ActiveChain().Tip()->GetBlockTimeMax() + 5;
|
||||||
SetMockTime(BLOCK_TIME);
|
SetMockTime(BLOCK_TIME);
|
||||||
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
|
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
|
||||||
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
|
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
|
||||||
|
@ -265,7 +265,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
|
||||||
spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
|
spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
|
||||||
|
|
||||||
AddWallet(wallet);
|
AddWallet(wallet);
|
||||||
wallet->SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
|
wallet->SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
|
||||||
}
|
}
|
||||||
JSONRPCRequest request;
|
JSONRPCRequest request;
|
||||||
request.params.setArray();
|
request.params.setArray();
|
||||||
|
@ -286,7 +286,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
|
||||||
request.params.setArray();
|
request.params.setArray();
|
||||||
request.params.push_back(backup_file);
|
request.params.push_back(backup_file);
|
||||||
AddWallet(wallet);
|
AddWallet(wallet);
|
||||||
wallet->SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
|
wallet->SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
|
||||||
::importwallet().HandleRequest(request);
|
::importwallet().HandleRequest(request);
|
||||||
RemoveWallet(wallet, std::nullopt);
|
RemoveWallet(wallet, std::nullopt);
|
||||||
|
|
||||||
|
@ -313,9 +313,9 @@ BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
|
||||||
CWalletTx wtx(&wallet, m_coinbase_txns.back());
|
CWalletTx wtx(&wallet, m_coinbase_txns.back());
|
||||||
|
|
||||||
LOCK2(wallet.cs_wallet, spk_man->cs_KeyStore);
|
LOCK2(wallet.cs_wallet, spk_man->cs_KeyStore);
|
||||||
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
|
wallet.SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
|
||||||
|
|
||||||
CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, ::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash(), 0);
|
CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash(), 0);
|
||||||
wtx.m_confirm = confirm;
|
wtx.m_confirm = confirm;
|
||||||
|
|
||||||
// Call GetImmatureCredit() once before adding the key to the wallet to
|
// Call GetImmatureCredit() once before adding the key to the wallet to
|
||||||
|
@ -483,16 +483,16 @@ public:
|
||||||
wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
|
wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
|
||||||
{
|
{
|
||||||
LOCK2(wallet->cs_wallet, ::cs_main);
|
LOCK2(wallet->cs_wallet, ::cs_main);
|
||||||
wallet->SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
|
wallet->SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
|
||||||
}
|
}
|
||||||
wallet->LoadWallet();
|
wallet->LoadWallet();
|
||||||
AddKey(*wallet, coinbaseKey);
|
AddKey(*wallet, coinbaseKey);
|
||||||
WalletRescanReserver reserver(*wallet);
|
WalletRescanReserver reserver(*wallet);
|
||||||
reserver.reserve();
|
reserver.reserve();
|
||||||
CWallet::ScanResult result = wallet->ScanForWalletTransactions(::ChainActive().Genesis()->GetBlockHash(), 0 /* start_height */, {} /* max_height */, reserver, false /* update */);
|
CWallet::ScanResult result = wallet->ScanForWalletTransactions(m_node.chainman->ActiveChain().Genesis()->GetBlockHash(), 0 /* start_height */, {} /* max_height */, reserver, false /* update */);
|
||||||
BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::SUCCESS);
|
BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::SUCCESS);
|
||||||
BOOST_CHECK_EQUAL(result.last_scanned_block, ::ChainActive().Tip()->GetBlockHash());
|
BOOST_CHECK_EQUAL(result.last_scanned_block, m_node.chainman->ActiveChain().Tip()->GetBlockHash());
|
||||||
BOOST_CHECK_EQUAL(*result.last_scanned_height, ::ChainActive().Height());
|
BOOST_CHECK_EQUAL(*result.last_scanned_height, m_node.chainman->ActiveChain().Height());
|
||||||
BOOST_CHECK(result.last_failed_block.IsNull());
|
BOOST_CHECK(result.last_failed_block.IsNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,10 +521,10 @@ public:
|
||||||
CreateAndProcessBlock({CMutableTransaction(blocktx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
|
CreateAndProcessBlock({CMutableTransaction(blocktx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
|
||||||
|
|
||||||
LOCK(wallet->cs_wallet);
|
LOCK(wallet->cs_wallet);
|
||||||
wallet->SetLastBlockProcessed(wallet->GetLastBlockHeight() + 1, ::ChainActive().Tip()->GetBlockHash());
|
wallet->SetLastBlockProcessed(wallet->GetLastBlockHeight() + 1, m_node.chainman->ActiveChain().Tip()->GetBlockHash());
|
||||||
auto it = wallet->mapWallet.find(tx->GetHash());
|
auto it = wallet->mapWallet.find(tx->GetHash());
|
||||||
BOOST_CHECK(it != wallet->mapWallet.end());
|
BOOST_CHECK(it != wallet->mapWallet.end());
|
||||||
CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, ::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash(), 1);
|
CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash(), 1);
|
||||||
it->second.m_confirm = confirm;
|
it->second.m_confirm = confirm;
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue