Skip to content

Commit

Permalink
rpc: Remove mempool global from miner
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcoFalke committed Dec 22, 2019
1 parent 6666ef1 commit faa92a2
Show file tree
Hide file tree
Showing 13 changed files with 92 additions and 53 deletions.
5 changes: 5 additions & 0 deletions src/bench/bench.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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();
Expand Down
3 changes: 3 additions & 0 deletions src/bench/bench.h
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions src/bench/block_assemble.cpp
Expand Up @@ -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>
Expand All @@ -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)
Expand All @@ -46,7 +47,7 @@ static void AssembleBlock(benchmark::State& state)
}

while (state.KeepRunning()) {
PrepareBlock(SCRIPT_PUB);
PrepareBlock(g_testing_setup->m_node, SCRIPT_PUB);
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/bench/wallet_balance.cpp
Expand Up @@ -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>
Expand All @@ -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();

Expand Down
28 changes: 15 additions & 13 deletions src/miner.cpp
Expand Up @@ -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:
Expand All @@ -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()
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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
Expand All @@ -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;
}
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down
11 changes: 6 additions & 5 deletions src/miner.h
Expand Up @@ -147,6 +147,7 @@ class BlockAssembler
int nHeight;
int64_t nLockTimeCutoff;
const CChainParams& chainparams;
const CTxMemPool& m_mempool;

public:
struct Options {
Expand All @@ -155,8 +156,8 @@ class BlockAssembler
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);
Expand All @@ -175,7 +176,7 @@ class BlockAssembler
/** 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 */
Expand All @@ -189,13 +190,13 @@ class BlockAssembler
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 */
Expand Down
14 changes: 9 additions & 5 deletions src/rpc/mining.cpp
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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");

Expand Down
21 changes: 14 additions & 7 deletions src/test/blockfilter_index_tests.cpp
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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);

Expand Down
6 changes: 4 additions & 2 deletions src/test/miner_tests.cpp
Expand Up @@ -30,6 +30,7 @@ struct MinerTestingSetup : public TestingSetup {
{
return CheckSequenceLocks(*m_node.mempool, tx, flags);
}
BlockAssembler AssemblerForTest(const CChainParams& params);
};
} // namespace miner_tests

Expand All @@ -48,12 +49,13 @@ class HasReason {

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);
}

constexpr static struct {
Expand Down
14 changes: 8 additions & 6 deletions src/test/util/mining.cpp
Expand Up @@ -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;
Expand All @@ -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);

Expand Down

0 comments on commit faa92a2

Please sign in to comment.