mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-25 02:33:24 -03:00
Merge #17781: rpc: Remove mempool global from miner
faa92a2297
rpc: Remove mempool global from miner (MarcoFalke)6666ef13f1
test: Properly document blockinfo size in miner_tests (MarcoFalke) Pull request description: The miner needs read-only access to the mempool. Instead of using the mutable global `::mempool`, keep a immutable reference to a mempool that is passed to the miner. Apart from the obvious benefits of removing a global and making things immutable, this might also simplify testing with multiple mempools. ACKs for top commit: promag: ACKfaa92a2297
. fjahr: ACKfaa92a2297
jnewbery: Code review ACKfaa92a2297
Tree-SHA512: c44027b5d2217a724791166f3f3112c45110ac1dbb37bdae27148a0657e0d1a1d043b0d24e49fd45465ec014224d1b7eb15c92a33069ad883fa8ffeadc24735b
This commit is contained in:
commit
17e14ac92f
13 changed files with 95 additions and 56 deletions
|
@ -15,6 +15,8 @@
|
|||
#include <numeric>
|
||||
#include <regex>
|
||||
|
||||
const RegTestingSetup* g_testing_setup = nullptr;
|
||||
|
||||
void benchmark::ConsolePrinter::header()
|
||||
{
|
||||
std::cout << "# Benchmark, evals, iterations, total, min, max, median" << std::endl;
|
||||
|
@ -113,6 +115,8 @@ void benchmark::BenchRunner::RunAll(Printer& printer, uint64_t num_evals, double
|
|||
|
||||
for (const auto& p : benchmarks()) {
|
||||
RegTestingSetup test{};
|
||||
assert(g_testing_setup == nullptr);
|
||||
g_testing_setup = &test;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
assert(::ChainActive().Height() == 0);
|
||||
|
@ -133,6 +137,7 @@ void benchmark::BenchRunner::RunAll(Printer& printer, uint64_t num_evals, double
|
|||
p.second.func(state);
|
||||
}
|
||||
printer.result(state);
|
||||
g_testing_setup = nullptr;
|
||||
}
|
||||
|
||||
printer.footer();
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
|
||||
struct RegTestingSetup;
|
||||
extern const RegTestingSetup* g_testing_setup; //!< A pointer to the current testing setup
|
||||
|
||||
// Simple micro-benchmarking framework; API mostly matches a subset of the Google Benchmark
|
||||
// framework (see https://github.com/google/benchmark)
|
||||
// Why not use the Google Benchmark framework? Because adding Yet Another Dependency
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <consensus/validation.h>
|
||||
#include <crypto/sha256.h>
|
||||
#include <test/util/mining.h>
|
||||
#include <test/util/setup_common.h>
|
||||
#include <test/util/wallet.h>
|
||||
#include <txmempool.h>
|
||||
#include <validation.h>
|
||||
|
@ -29,7 +30,7 @@ static void AssembleBlock(benchmark::State& state)
|
|||
std::array<CTransactionRef, NUM_BLOCKS - COINBASE_MATURITY + 1> txs;
|
||||
for (size_t b{0}; b < NUM_BLOCKS; ++b) {
|
||||
CMutableTransaction tx;
|
||||
tx.vin.push_back(MineBlock(SCRIPT_PUB));
|
||||
tx.vin.push_back(MineBlock(g_testing_setup->m_node, SCRIPT_PUB));
|
||||
tx.vin.back().scriptWitness = witness;
|
||||
tx.vout.emplace_back(1337, SCRIPT_PUB);
|
||||
if (NUM_BLOCKS - b >= COINBASE_MATURITY)
|
||||
|
@ -46,7 +47,7 @@ static void AssembleBlock(benchmark::State& state)
|
|||
}
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
PrepareBlock(SCRIPT_PUB);
|
||||
PrepareBlock(g_testing_setup->m_node, SCRIPT_PUB);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <node/context.h>
|
||||
#include <optional.h>
|
||||
#include <test/util/mining.h>
|
||||
#include <test/util/setup_common.h>
|
||||
#include <test/util/wallet.h>
|
||||
#include <validationinterface.h>
|
||||
#include <wallet/wallet.h>
|
||||
|
@ -29,8 +30,8 @@ static void WalletBalance(benchmark::State& state, const bool set_dirty, const b
|
|||
if (add_watchonly) importaddress(wallet, ADDRESS_WATCHONLY);
|
||||
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
generatetoaddress(address_mine.get_value_or(ADDRESS_WATCHONLY));
|
||||
generatetoaddress(ADDRESS_WATCHONLY);
|
||||
generatetoaddress(g_testing_setup->m_node, address_mine.get_value_or(ADDRESS_WATCHONLY));
|
||||
generatetoaddress(g_testing_setup->m_node, ADDRESS_WATCHONLY);
|
||||
}
|
||||
SyncWithValidationInterfaceQueue();
|
||||
|
||||
|
|
|
@ -45,7 +45,9 @@ BlockAssembler::Options::Options() {
|
|||
nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
|
||||
}
|
||||
|
||||
BlockAssembler::BlockAssembler(const CChainParams& params, const Options& options) : chainparams(params)
|
||||
BlockAssembler::BlockAssembler(const CTxMemPool& mempool, const CChainParams& params, const Options& options)
|
||||
: chainparams(params),
|
||||
m_mempool(mempool)
|
||||
{
|
||||
blockMinFeeRate = options.blockMinFeeRate;
|
||||
// Limit weight to between 4K and MAX_BLOCK_WEIGHT-4K for sanity:
|
||||
|
@ -67,7 +69,8 @@ static BlockAssembler::Options DefaultOptions()
|
|||
return options;
|
||||
}
|
||||
|
||||
BlockAssembler::BlockAssembler(const CChainParams& params) : BlockAssembler(params, DefaultOptions()) {}
|
||||
BlockAssembler::BlockAssembler(const CTxMemPool& mempool, const CChainParams& params)
|
||||
: BlockAssembler(mempool, params, DefaultOptions()) {}
|
||||
|
||||
void BlockAssembler::resetBlock()
|
||||
{
|
||||
|
@ -103,7 +106,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
|||
pblocktemplate->vTxFees.push_back(-1); // updated at end
|
||||
pblocktemplate->vTxSigOpsCost.push_back(-1); // updated at end
|
||||
|
||||
LOCK2(cs_main, mempool.cs);
|
||||
LOCK2(cs_main, m_mempool.cs);
|
||||
CBlockIndex* pindexPrev = ::ChainActive().Tip();
|
||||
assert(pindexPrev != nullptr);
|
||||
nHeight = pindexPrev->nHeight + 1;
|
||||
|
@ -236,7 +239,7 @@ int BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& already
|
|||
int nDescendantsUpdated = 0;
|
||||
for (CTxMemPool::txiter it : alreadyAdded) {
|
||||
CTxMemPool::setEntries descendants;
|
||||
mempool.CalculateDescendants(it, descendants);
|
||||
m_mempool.CalculateDescendants(it, descendants);
|
||||
// Insert all descendants (not yet in block) into the modified set
|
||||
for (CTxMemPool::txiter desc : descendants) {
|
||||
if (alreadyAdded.count(desc))
|
||||
|
@ -268,7 +271,7 @@ int BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& already
|
|||
// cached size/sigops/fee values that are not actually correct.
|
||||
bool BlockAssembler::SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx)
|
||||
{
|
||||
assert (it != mempool.mapTx.end());
|
||||
assert(it != m_mempool.mapTx.end());
|
||||
return mapModifiedTx.count(it) || inBlock.count(it) || failedTx.count(it);
|
||||
}
|
||||
|
||||
|
@ -305,7 +308,7 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
|
|||
// and modifying them for their already included ancestors
|
||||
UpdatePackagesForAdded(inBlock, mapModifiedTx);
|
||||
|
||||
CTxMemPool::indexed_transaction_set::index<ancestor_score>::type::iterator mi = mempool.mapTx.get<ancestor_score>().begin();
|
||||
CTxMemPool::indexed_transaction_set::index<ancestor_score>::type::iterator mi = m_mempool.mapTx.get<ancestor_score>().begin();
|
||||
CTxMemPool::txiter iter;
|
||||
|
||||
// Limit the number of attempts to add transactions to the block when it is
|
||||
|
@ -314,11 +317,10 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
|
|||
const int64_t MAX_CONSECUTIVE_FAILURES = 1000;
|
||||
int64_t nConsecutiveFailed = 0;
|
||||
|
||||
while (mi != mempool.mapTx.get<ancestor_score>().end() || !mapModifiedTx.empty())
|
||||
{
|
||||
while (mi != m_mempool.mapTx.get<ancestor_score>().end() || !mapModifiedTx.empty()) {
|
||||
// First try to find a new transaction in mapTx to evaluate.
|
||||
if (mi != mempool.mapTx.get<ancestor_score>().end() &&
|
||||
SkipMapTxEntry(mempool.mapTx.project<0>(mi), mapModifiedTx, failedTx)) {
|
||||
if (mi != m_mempool.mapTx.get<ancestor_score>().end() &&
|
||||
SkipMapTxEntry(m_mempool.mapTx.project<0>(mi), mapModifiedTx, failedTx)) {
|
||||
++mi;
|
||||
continue;
|
||||
}
|
||||
|
@ -328,13 +330,13 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
|
|||
bool fUsingModified = false;
|
||||
|
||||
modtxscoreiter modit = mapModifiedTx.get<ancestor_score>().begin();
|
||||
if (mi == mempool.mapTx.get<ancestor_score>().end()) {
|
||||
if (mi == m_mempool.mapTx.get<ancestor_score>().end()) {
|
||||
// We're out of entries in mapTx; use the entry from mapModifiedTx
|
||||
iter = modit->iter;
|
||||
fUsingModified = true;
|
||||
} else {
|
||||
// Try to compare the mapTx entry to the mapModifiedTx entry
|
||||
iter = mempool.mapTx.project<0>(mi);
|
||||
iter = m_mempool.mapTx.project<0>(mi);
|
||||
if (modit != mapModifiedTx.get<ancestor_score>().end() &&
|
||||
CompareTxMemPoolEntryByAncestorFee()(*modit, CTxMemPoolModifiedEntry(iter))) {
|
||||
// The best entry in mapModifiedTx has higher score
|
||||
|
@ -389,7 +391,7 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
|
|||
CTxMemPool::setEntries ancestors;
|
||||
uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
|
||||
std::string dummy;
|
||||
mempool.CalculateMemPoolAncestors(*iter, ancestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
|
||||
m_mempool.CalculateMemPoolAncestors(*iter, ancestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
|
||||
|
||||
onlyUnconfirmed(ancestors);
|
||||
ancestors.insert(iter);
|
||||
|
|
11
src/miner.h
11
src/miner.h
|
@ -147,6 +147,7 @@ private:
|
|||
int nHeight;
|
||||
int64_t nLockTimeCutoff;
|
||||
const CChainParams& chainparams;
|
||||
const CTxMemPool& m_mempool;
|
||||
|
||||
public:
|
||||
struct Options {
|
||||
|
@ -155,8 +156,8 @@ public:
|
|||
CFeeRate blockMinFeeRate;
|
||||
};
|
||||
|
||||
explicit BlockAssembler(const CChainParams& params);
|
||||
BlockAssembler(const CChainParams& params, const Options& options);
|
||||
explicit BlockAssembler(const CTxMemPool& mempool, const CChainParams& params);
|
||||
explicit BlockAssembler(const CTxMemPool& mempool, const CChainParams& params, const Options& options);
|
||||
|
||||
/** Construct a new block template with coinbase to scriptPubKeyIn */
|
||||
std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn);
|
||||
|
@ -175,7 +176,7 @@ private:
|
|||
/** Add transactions based on feerate including unconfirmed ancestors
|
||||
* Increments nPackagesSelected / nDescendantsUpdated with corresponding
|
||||
* statistics from the package selection (for logging statistics). */
|
||||
void addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);
|
||||
void addPackageTxs(int& nPackagesSelected, int& nDescendantsUpdated) EXCLUSIVE_LOCKS_REQUIRED(m_mempool.cs);
|
||||
|
||||
// helper functions for addPackageTxs()
|
||||
/** Remove confirmed (inBlock) entries from given set */
|
||||
|
@ -189,13 +190,13 @@ private:
|
|||
bool TestPackageTransactions(const CTxMemPool::setEntries& package);
|
||||
/** Return true if given transaction from mapTx has already been evaluated,
|
||||
* or if the transaction's cached data in mapTx is incorrect. */
|
||||
bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);
|
||||
bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set& mapModifiedTx, CTxMemPool::setEntries& failedTx) EXCLUSIVE_LOCKS_REQUIRED(m_mempool.cs);
|
||||
/** Sort the package in an order that is valid to appear in a block */
|
||||
void SortForBlock(const CTxMemPool::setEntries& package, std::vector<CTxMemPool::txiter>& sortedEntries);
|
||||
/** Add descendants of given transactions to mapModifiedTx with ancestor
|
||||
* state updated assuming given transactions are inBlock. Returns number
|
||||
* of updated descendants. */
|
||||
int UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set &mapModifiedTx) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);
|
||||
int UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set& mapModifiedTx) EXCLUSIVE_LOCKS_REQUIRED(m_mempool.cs);
|
||||
};
|
||||
|
||||
/** Modify the extranonce in a block */
|
||||
|
|
|
@ -102,7 +102,7 @@ static UniValue getnetworkhashps(const JSONRPCRequest& request)
|
|||
return GetNetworkHashPS(!request.params[0].isNull() ? request.params[0].get_int() : 120, !request.params[1].isNull() ? request.params[1].get_int() : -1);
|
||||
}
|
||||
|
||||
static UniValue generateBlocks(const CScript& coinbase_script, int nGenerate, uint64_t nMaxTries)
|
||||
static UniValue generateBlocks(const CTxMemPool& mempool, const CScript& coinbase_script, int nGenerate, uint64_t nMaxTries)
|
||||
{
|
||||
int nHeightEnd = 0;
|
||||
int nHeight = 0;
|
||||
|
@ -116,7 +116,7 @@ static UniValue generateBlocks(const CScript& coinbase_script, int nGenerate, ui
|
|||
UniValue blockHashes(UniValue::VARR);
|
||||
while (nHeight < nHeightEnd && !ShutdownRequested())
|
||||
{
|
||||
std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(Params()).CreateNewBlock(coinbase_script));
|
||||
std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(mempool, Params()).CreateNewBlock(coinbase_script));
|
||||
if (!pblocktemplate.get())
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
|
||||
CBlock *pblock = &pblocktemplate->block;
|
||||
|
@ -179,9 +179,11 @@ static UniValue generatetodescriptor(const JSONRPCRequest& request)
|
|||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys"));
|
||||
}
|
||||
|
||||
const CTxMemPool& mempool = EnsureMemPool();
|
||||
|
||||
CHECK_NONFATAL(coinbase_script.size() == 1);
|
||||
|
||||
return generateBlocks(coinbase_script.at(0), num_blocks, max_tries);
|
||||
return generateBlocks(mempool, coinbase_script.at(0), num_blocks, max_tries);
|
||||
}
|
||||
|
||||
static UniValue generatetoaddress(const JSONRPCRequest& request)
|
||||
|
@ -215,9 +217,11 @@ static UniValue generatetoaddress(const JSONRPCRequest& request)
|
|||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address");
|
||||
}
|
||||
|
||||
const CTxMemPool& mempool = EnsureMemPool();
|
||||
|
||||
CScript coinbase_script = GetScriptForDestination(destination);
|
||||
|
||||
return generateBlocks(coinbase_script, nGenerate, nMaxTries);
|
||||
return generateBlocks(mempool, coinbase_script, nGenerate, nMaxTries);
|
||||
}
|
||||
|
||||
static UniValue getmininginfo(const JSONRPCRequest& request)
|
||||
|
@ -548,7 +552,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
|
|||
|
||||
// Create new block
|
||||
CScript scriptDummy = CScript() << OP_TRUE;
|
||||
pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy);
|
||||
pblocktemplate = BlockAssembler(mempool, Params()).CreateNewBlock(scriptDummy);
|
||||
if (!pblocktemplate)
|
||||
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
|
||||
|
||||
|
|
|
@ -18,6 +18,11 @@
|
|||
|
||||
BOOST_AUTO_TEST_SUITE(blockfilter_index_tests)
|
||||
|
||||
struct BuildChainTestingSetup : public TestChain100Setup {
|
||||
CBlock CreateBlock(const CBlockIndex* prev, const std::vector<CMutableTransaction>& txns, const CScript& scriptPubKey);
|
||||
bool BuildChain(const CBlockIndex* pindex, const CScript& coinbase_script_pub_key, size_t length, std::vector<std::shared_ptr<CBlock>>& chain);
|
||||
};
|
||||
|
||||
static bool CheckFilterLookups(BlockFilterIndex& filter_index, const CBlockIndex* block_index,
|
||||
uint256& last_header)
|
||||
{
|
||||
|
@ -52,12 +57,12 @@ static bool CheckFilterLookups(BlockFilterIndex& filter_index, const CBlockIndex
|
|||
return true;
|
||||
}
|
||||
|
||||
static CBlock CreateBlock(const CBlockIndex* prev,
|
||||
const std::vector<CMutableTransaction>& txns,
|
||||
const CScript& scriptPubKey)
|
||||
CBlock BuildChainTestingSetup::CreateBlock(const CBlockIndex* prev,
|
||||
const std::vector<CMutableTransaction>& txns,
|
||||
const CScript& scriptPubKey)
|
||||
{
|
||||
const CChainParams& chainparams = Params();
|
||||
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);
|
||||
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(*m_node.mempool, chainparams).CreateNewBlock(scriptPubKey);
|
||||
CBlock& block = pblocktemplate->block;
|
||||
block.hashPrevBlock = prev->GetBlockHash();
|
||||
block.nTime = prev->nTime + 1;
|
||||
|
@ -76,8 +81,10 @@ static CBlock CreateBlock(const CBlockIndex* prev,
|
|||
return block;
|
||||
}
|
||||
|
||||
static bool BuildChain(const CBlockIndex* pindex, const CScript& coinbase_script_pub_key,
|
||||
size_t length, std::vector<std::shared_ptr<CBlock>>& chain)
|
||||
bool BuildChainTestingSetup::BuildChain(const CBlockIndex* pindex,
|
||||
const CScript& coinbase_script_pub_key,
|
||||
size_t length,
|
||||
std::vector<std::shared_ptr<CBlock>>& chain)
|
||||
{
|
||||
std::vector<CMutableTransaction> no_txns;
|
||||
|
||||
|
@ -95,7 +102,7 @@ static bool BuildChain(const CBlockIndex* pindex, const CScript& coinbase_script
|
|||
return true;
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, TestChain100Setup)
|
||||
BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
|
||||
{
|
||||
BlockFilterIndex filter_index(BlockFilterType::BASIC, 1 << 20, true);
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ struct MinerTestingSetup : public TestingSetup {
|
|||
{
|
||||
return CheckSequenceLocks(*m_node.mempool, tx, flags);
|
||||
}
|
||||
BlockAssembler AssemblerForTest(const CChainParams& params);
|
||||
};
|
||||
} // namespace miner_tests
|
||||
|
||||
|
@ -48,16 +49,16 @@ private:
|
|||
|
||||
static CFeeRate blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);
|
||||
|
||||
static BlockAssembler AssemblerForTest(const CChainParams& params) {
|
||||
BlockAssembler MinerTestingSetup::AssemblerForTest(const CChainParams& params)
|
||||
{
|
||||
BlockAssembler::Options options;
|
||||
|
||||
options.nBlockMaxWeight = MAX_BLOCK_WEIGHT;
|
||||
options.blockMinFeeRate = blockMinFeeRate;
|
||||
return BlockAssembler(params, options);
|
||||
return BlockAssembler(*m_node.mempool, params, options);
|
||||
}
|
||||
|
||||
static
|
||||
struct {
|
||||
constexpr static struct {
|
||||
unsigned char extranonce;
|
||||
unsigned int nonce;
|
||||
} blockinfo[] = {
|
||||
|
@ -225,7 +226,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
||||
|
||||
// We can't make transactions until we have inputs
|
||||
// Therefore, load 100 blocks :)
|
||||
// Therefore, load 110 blocks :)
|
||||
static_assert(sizeof(blockinfo) / sizeof(*blockinfo) == 110, "Should have 110 blocks to import");
|
||||
int baseheight = 0;
|
||||
std::vector<CTransactionRef> txFirst;
|
||||
for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i)
|
||||
|
|
|
@ -8,22 +8,23 @@
|
|||
#include <consensus/merkle.h>
|
||||
#include <key_io.h>
|
||||
#include <miner.h>
|
||||
#include <node/context.h>
|
||||
#include <pow.h>
|
||||
#include <script/standard.h>
|
||||
#include <validation.h>
|
||||
|
||||
CTxIn generatetoaddress(const std::string& address)
|
||||
CTxIn generatetoaddress(const NodeContext& node, const std::string& address)
|
||||
{
|
||||
const auto dest = DecodeDestination(address);
|
||||
assert(IsValidDestination(dest));
|
||||
const auto coinbase_script = GetScriptForDestination(dest);
|
||||
|
||||
return MineBlock(coinbase_script);
|
||||
return MineBlock(node, coinbase_script);
|
||||
}
|
||||
|
||||
CTxIn MineBlock(const CScript& coinbase_scriptPubKey)
|
||||
CTxIn MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
|
||||
{
|
||||
auto block = PrepareBlock(coinbase_scriptPubKey);
|
||||
auto block = PrepareBlock(node, coinbase_scriptPubKey);
|
||||
|
||||
while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) {
|
||||
++block->nNonce;
|
||||
|
@ -36,10 +37,11 @@ CTxIn MineBlock(const CScript& coinbase_scriptPubKey)
|
|||
return CTxIn{block->vtx[0]->GetHash(), 0};
|
||||
}
|
||||
|
||||
std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey)
|
||||
std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
|
||||
{
|
||||
assert(node.mempool);
|
||||
auto block = std::make_shared<CBlock>(
|
||||
BlockAssembler{Params()}
|
||||
BlockAssembler{*node.mempool, Params()}
|
||||
.CreateNewBlock(coinbase_scriptPubKey)
|
||||
->block);
|
||||
|
||||
|
|
|
@ -11,14 +11,15 @@
|
|||
class CBlock;
|
||||
class CScript;
|
||||
class CTxIn;
|
||||
struct NodeContext;
|
||||
|
||||
/** Returns the generated coin */
|
||||
CTxIn MineBlock(const CScript& coinbase_scriptPubKey);
|
||||
CTxIn MineBlock(const NodeContext&, const CScript& coinbase_scriptPubKey);
|
||||
|
||||
/** Prepare a block to be mined */
|
||||
std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey);
|
||||
std::shared_ptr<CBlock> PrepareBlock(const NodeContext&, const CScript& coinbase_scriptPubKey);
|
||||
|
||||
/** RPC-like helper function, returns the generated coin */
|
||||
CTxIn generatetoaddress(const std::string& address);
|
||||
CTxIn generatetoaddress(const NodeContext&, const std::string& address);
|
||||
|
||||
#endif // BITCOIN_TEST_UTIL_MINING_H
|
||||
|
|
|
@ -175,7 +175,7 @@ TestChain100Setup::TestChain100Setup()
|
|||
CBlock TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns, const CScript& scriptPubKey)
|
||||
{
|
||||
const CChainParams& chainparams = Params();
|
||||
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);
|
||||
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(*m_node.mempool, chainparams).CreateNewBlock(scriptPubKey);
|
||||
CBlock& block = pblocktemplate->block;
|
||||
|
||||
// Replace mempool-selected txns with just coinbase plus passed-in txns:
|
||||
|
|
|
@ -20,7 +20,17 @@
|
|||
|
||||
static const std::vector<unsigned char> V_OP_TRUE{OP_TRUE};
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(validation_block_tests, RegTestingSetup)
|
||||
namespace validation_block_tests {
|
||||
struct MinerTestingSetup : public RegTestingSetup {
|
||||
std::shared_ptr<CBlock> Block(const uint256& prev_hash);
|
||||
std::shared_ptr<const CBlock> GoodBlock(const uint256& prev_hash);
|
||||
std::shared_ptr<const CBlock> BadBlock(const uint256& prev_hash);
|
||||
std::shared_ptr<CBlock> FinalizeBlock(std::shared_ptr<CBlock> pblock);
|
||||
void BuildChain(const uint256& root, int height, const unsigned int invalid_rate, const unsigned int branch_rate, const unsigned int max_size, std::vector<std::shared_ptr<const CBlock>>& blocks);
|
||||
};
|
||||
} // namespace validation_block_tests
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(validation_block_tests, MinerTestingSetup)
|
||||
|
||||
struct TestSubscriber : public CValidationInterface {
|
||||
uint256 m_expected_tip;
|
||||
|
@ -49,7 +59,7 @@ struct TestSubscriber : public CValidationInterface {
|
|||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<CBlock> Block(const uint256& prev_hash)
|
||||
std::shared_ptr<CBlock> MinerTestingSetup::Block(const uint256& prev_hash)
|
||||
{
|
||||
static int i = 0;
|
||||
static uint64_t time = Params().GenesisBlock().nTime;
|
||||
|
@ -57,7 +67,7 @@ std::shared_ptr<CBlock> Block(const uint256& prev_hash)
|
|||
CScript pubKey;
|
||||
pubKey << i++ << OP_TRUE;
|
||||
|
||||
auto ptemplate = BlockAssembler(Params()).CreateNewBlock(pubKey);
|
||||
auto ptemplate = BlockAssembler(*m_node.mempool, Params()).CreateNewBlock(pubKey);
|
||||
auto pblock = std::make_shared<CBlock>(ptemplate->block);
|
||||
pblock->hashPrevBlock = prev_hash;
|
||||
pblock->nTime = ++time;
|
||||
|
@ -83,7 +93,7 @@ std::shared_ptr<CBlock> Block(const uint256& prev_hash)
|
|||
return pblock;
|
||||
}
|
||||
|
||||
std::shared_ptr<CBlock> FinalizeBlock(std::shared_ptr<CBlock> pblock)
|
||||
std::shared_ptr<CBlock> MinerTestingSetup::FinalizeBlock(std::shared_ptr<CBlock> pblock)
|
||||
{
|
||||
LOCK(cs_main); // For LookupBlockIndex
|
||||
GenerateCoinbaseCommitment(*pblock, LookupBlockIndex(pblock->hashPrevBlock), Params().GetConsensus());
|
||||
|
@ -98,13 +108,13 @@ std::shared_ptr<CBlock> FinalizeBlock(std::shared_ptr<CBlock> pblock)
|
|||
}
|
||||
|
||||
// construct a valid block
|
||||
std::shared_ptr<const CBlock> GoodBlock(const uint256& prev_hash)
|
||||
std::shared_ptr<const CBlock> MinerTestingSetup::GoodBlock(const uint256& prev_hash)
|
||||
{
|
||||
return FinalizeBlock(Block(prev_hash));
|
||||
}
|
||||
|
||||
// construct an invalid block (but with a valid header)
|
||||
std::shared_ptr<const CBlock> BadBlock(const uint256& prev_hash)
|
||||
std::shared_ptr<const CBlock> MinerTestingSetup::BadBlock(const uint256& prev_hash)
|
||||
{
|
||||
auto pblock = Block(prev_hash);
|
||||
|
||||
|
@ -119,7 +129,7 @@ std::shared_ptr<const CBlock> BadBlock(const uint256& prev_hash)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void BuildChain(const uint256& root, int height, const unsigned int invalid_rate, const unsigned int branch_rate, const unsigned int max_size, std::vector<std::shared_ptr<const CBlock>>& blocks)
|
||||
void MinerTestingSetup::BuildChain(const uint256& root, int height, const unsigned int invalid_rate, const unsigned int branch_rate, const unsigned int max_size, std::vector<std::shared_ptr<const CBlock>>& blocks)
|
||||
{
|
||||
if (height <= 0 || blocks.size() >= max_size) return;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue