15#include <validation.h>
17#include <test/util/mining.h>
18#include <test/util/setup_common.h>
33static const CScript
SCRIPT_SIG = CScript() << std::vector<uint8_t>(100, 0xff)
39 std::vector<CTxIn> utxos;
42 for (
size_t i = 0; i < n; ++i) {
56 tx.
vin.emplace_back(txin);
63static std::vector<CTransactionRef>
65 auto firstTx =
toTx(config, std::move(utxo));
68 std::vector<CTransactionRef> chain = {firstTx};
69 chain.reserve(chainLength);
70 while (chain.size() < chainLength) {
71 const COutPoint parent(chain.back()->GetId(), 0);
72 const Amount inAmount(chain.back()->vout[0].nValue);
78 assert(chain.size() == chainLength);
87 const size_t treeDepth) {
90 for (
size_t i = 0; i <= treeDepth; ++i) {
91 txs += std::pow(2, i);
93 const size_t leafs = std::pow(2, treeDepth);
95 std::vector<CTransactionRef> chain;
98 std::queue<CTransactionRef> queue;
100 auto tx =
toTx(config, std::move(txin));
102 chain.emplace_back(tx);
113 const Amount inAmount = txin1->vout[0].nValue + txin2->vout[0].nValue;
115 tx.
vin.emplace_back(CTxIn(COutPoint(txin1->GetId(), 0),
SCRIPT_SIG));
116 tx.
vin.emplace_back(CTxIn(COutPoint(txin2->GetId(), 0),
SCRIPT_SIG));
120 chain.push_back(txref);
124 queue.emplace(txref);
126 assert(chain.size() == txs);
132 const std::vector<CTransactionRef> chainedTxs) {
134 Chainstate &activeChainState = chainman->ActiveChainstate();
137 assert(mempool.size() == 0);
141 for (
const auto &tx : chainedTxs) {
159 size_t chainSizePerBlock,
bool includeMempoolTxRemoval) {
161 std::vector<std::vector<CTransactionRef>> chains;
162 chains.reserve(utxos.size());
163 for (
auto &utxo : utxos) {
169 Chainstate &activeChainState = chainman->ActiveChainstate();
173 assert(tipBeforeInvalidate !=
nullptr);
178 assert(mempool.size() == 0);
181 TestMemPoolEntryHelper entry;
183 for (
const auto &chain : chains) {
186 for (
const auto &tx : chain) {
187 mempool.addUnchecked(entry.FromTx(tx));
190 assert(mempool.size() == chain.size());
192 assert(mempool.size() == 0);
197 if (blockToInvalidate ==
nullptr) {
198 blockToInvalidate = activeChainState.
m_chain.
Tip();
215 assert(mempool.size() == reorgDepth * chainSizePerBlock);
217 if (!includeMempoolTxRemoval) {
233 assert(mempool.size() == 0);
240 const std::vector<std::vector<CTransactionRef>> &chains) {
241 TestMemPoolEntryHelper entry;
245 Chainstate &activeChainState = chainman->ActiveChainstate();
250 for (
const auto &chain : chains) {
252 for (
const auto &tx : chain) {
253 mempool.addUnchecked(entry.FromTx(tx));
257 assert(mempool.size() == txCount);
259 const CScript dummy = CScript() <<
OP_TRUE;
263 .CreateNewBlock(dummy);
266 assert(blocktemplate->block.vtx.size() == txCount + 1);
272 const std::vector<std::vector<CTransactionRef>> &chains,
273 bool revFee =
true) {
274 std::list<CTxMemPool> pools;
287 pools.emplace_back(config, mempool_opts);
289 TestMemPoolEntryHelper entry;
296 for (
const auto &chain : chains) {
298 entry.nFee += int64_t(chain.size()) *
SATOSHI;
301 for (
const auto &tx : chain) {
303 entry.nFee += feeBump;
309 entry.nFee += int64_t(chain.size()) *
SATOSHI;
315 auto it = pools.begin();
318 assert(it != pools.end());
321 while (
auto prevSize = pool.size()) {
322 pool.TrimToSize(pool.DynamicMemoryUsage() * 99 / 100);
323 assert(pool.size() < prevSize);
330 RegTestingSetup test_setup{};
331 const Config &config = test_setup.m_node.chainman->GetConfig();
333 config,
createUTXOs(config, 1, test_setup.m_node).back(), 50);
334 benchATMP(test_setup.m_node, bench, chainedTxs);
339 RegTestingSetup test_setup{};
340 const Config &config = test_setup.m_node.chainman->GetConfig();
342 config,
createUTXOs(config, 1, test_setup.m_node).back(), 500);
343 benchATMP(test_setup.m_node, bench, chainedTxs);
348 RegTestingSetup test_setup{};
349 const Config &config = test_setup.m_node.chainman->GetConfig();
350 const std::vector<CTransactionRef> chainedTxs =
352 assert(chainedTxs.size() == 63);
353 benchATMP(test_setup.m_node, bench, chainedTxs);
358 RegTestingSetup test_setup{};
359 const Config &config = test_setup.m_node.chainman->GetConfig();
360 const std::vector<CTransactionRef> chainedTxs =
362 assert(chainedTxs.size() == 511);
363 benchATMP(test_setup.m_node, bench, chainedTxs);
369 RegTestingSetup test_setup{};
370 const Config &config = test_setup.m_node.chainman->GetConfig();
371 benchReorg(config, test_setup.m_node, bench, 10, 50,
true);
377 RegTestingSetup test_setup{};
378 const Config &config = test_setup.m_node.chainman->GetConfig();
379 benchReorg(config, test_setup.m_node, bench, 10, 500,
true);
386 RegTestingSetup test_setup{};
387 const Config &config = test_setup.m_node.chainman->GetConfig();
388 benchReorg(config, test_setup.m_node, bench, 10, 50,
false);
395 RegTestingSetup test_setup{};
396 const Config &config = test_setup.m_node.chainman->GetConfig();
397 benchReorg(config, test_setup.m_node, bench, 10, 500,
false);
402 RegTestingSetup test_setup{};
403 const Config &config = test_setup.m_node.chainman->GetConfig();
404 CTxIn utxo =
createUTXOs(config, 1, test_setup.m_node).back();
406 {oneInOneOutChain(config, std::move(utxo), 50)});
411 RegTestingSetup test_setup{};
412 const Config &config = test_setup.m_node.chainman->GetConfig();
413 CTxIn utxo =
createUTXOs(config, 1, test_setup.m_node).back();
415 {oneInOneOutChain(config, std::move(utxo), 500)});
421 RegTestingSetup test_setup{};
422 const Config &config = test_setup.m_node.chainman->GetConfig();
424 constexpr int NChains = 2000;
425 std::vector<std::vector<CTransactionRef>> chains;
426 chains.reserve(NChains);
427 const auto utxos =
createUTXOs(config, NChains, test_setup.m_node);
428 for (
int i = 0; i < NChains; ++i) {
437 RegTestingSetup test_setup{};
438 const Config &config = test_setup.m_node.chainman->GetConfig();
440 constexpr int NChains = 2000;
441 std::vector<std::vector<CTransactionRef>> chains;
442 chains.reserve(NChains);
443 const auto utxos =
createUTXOs(config, NChains, test_setup.m_node);
444 for (
int i = 0; i < NChains; ++i) {
static constexpr Amount SATOSHI
static constexpr Amount COIN
static void EvictChained50Tx(benchmark::Bench &bench)
Fill a mempool then evict 2000 x 50 1-input-1-output transactions, CTxMemPool version,...
static void Reorg10BlocksWith500TxChain(benchmark::Bench &bench)
Try to reorg a chain of depth 10 where each block has a 500 tx 1-input-1-output chain.
static void MempoolAcceptance50ChainedTxs(benchmark::Bench &bench)
Tests a chain of 50 1-input-1-output transactions.
static void MempoolAcceptance511TxTree(benchmark::Bench &bench)
Test a tree of 511 2-inputs-1-output transactions.
static void MempoolAcceptance63TxTree(benchmark::Bench &bench)
Test a tree of 63 2-inputs-1-output transactions.
static void EvictChained50TxRev(benchmark::Bench &bench)
Fill a mempool then evict 2000 x 50 1-input-1-output transactions, CTxMemPool version,...
static void Reorg10BlocksWith500TxChainSkipMempool(benchmark::Bench &bench)
Try to reorg a chain of depth 10 where each block has a 500 tx 1-input-1-output chain,...
static void MempoolAcceptance500ChainedTxs(benchmark::Bench &bench)
Tests a chain of 500 1-input-1-output transactions.
static void benchGenerateNewBlock(const Config &config, node::NodeContext &node, benchmark::Bench &bench, const std::vector< std::vector< CTransactionRef > > &chains)
static void GenerateBlock50ChainedTxs(benchmark::Bench &bench)
Generate a block with 50 1-input-1-output transactions.
static void Reorg10BlocksWith50TxChain(benchmark::Bench &bench)
Try to reorg a chain of depth 10 where each block has a 50 tx 1-input-1-output chain.
static void benchReorg(const Config &config, node::NodeContext &node, benchmark::Bench &bench, size_t reorgDepth, size_t chainSizePerBlock, bool includeMempoolTxRemoval)
Run benchmark that reorganizes blocks with one-input-one-output transaction chains in them.
static const CScript REDEEM_SCRIPT
This file contains benchmarks focusing on chained transactions in the mempool.
static std::vector< CTxIn > createUTXOs(const Config &config, size_t n, node::NodeContext &node)
Mine new utxos.
static void GenerateBlock500ChainedTxs(benchmark::Bench &bench)
Generate a block with 500 1-input-1-output transactions.
static std::vector< CTransactionRef > twoInOneOutTree(const Config &config, node::NodeContext &node, const size_t treeDepth)
Creates a tree of transactions with 2-inputs-1-output.
static std::vector< CTransactionRef > oneInOneOutChain(const Config &config, CTxIn utxo, const size_t chainLength)
Creates a chain of transactions with 1-input-1-output.
static void benchEviction(const Config &config, benchmark::Bench &bench, const std::vector< std::vector< CTransactionRef > > &chains, bool revFee=true)
static const CScript SCRIPT_PUB_KEY
static void Reorg10BlocksWith50TxChainSkipMempool(benchmark::Bench &bench)
Try to reorg a chain of depth 10 where each block has a 50 tx 1-input-1-output chain,...
BENCHMARK(MempoolAcceptance50ChainedTxs)
static CTransactionRef toTx(const Config &config, CTxIn txin)
Create a transaction spending a coinbase utxo.
static const CScript SCRIPT_SIG
static void benchATMP(node::NodeContext &node, benchmark::Bench &bench, const std::vector< CTransactionRef > chainedTxs)
Run benchmark on AcceptToMemoryPool.
#define Assert(val)
Identity function.
The block chain is a tree shaped structure starting with the genesis block at the root,...
unsigned int nTx
Number of transactions in this block.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
A mutable version of CTransaction.
std::vector< CTxOut > vout
A reference to a CScript: the Hash160 of its serialization (see script.h)
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
void check(const CCoinsViewCache &active_coins_tip, int64_t spendheight) const EXCLUSIVE_LOCKS_REQUIRED(void addUnchecked(CTxMemPoolEntryRef entry) EXCLUSIVE_LOCKS_REQUIRED(cs
If sanity-checking is turned on, check makes sure the pool is consistent (does not contain two transa...
unsigned long size() const
Chainstate stores and provides an API to update our local knowledge of the current best chain.
bool ActivateBestChain(BlockValidationState &state, std::shared_ptr< const CBlock > pblock=nullptr, avalanche::Processor *const avalanche=nullptr) EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex
Find the best known block, and make it the tip of the block chain.
CChain m_chain
The current chain of blockheaders we consult and build on.
CTxMemPool * GetMempool()
void SetBlockFailureFlags(CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(voi ResetBlockFailureFlags)(CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Set invalidity status to all descendants of a block.
bool InvalidateBlock(BlockValidationState &state, CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex
Mark a block as invalid.
Main entry point to nanobench's benchmarking facility.
Bench & run(char const *benchmarkName, Op &&op)
Repeatedly calls op() based on the configuration, and performs measurements.
Bench & epochs(size_t numEpochs) noexcept
Controls number of epochs, the number of measurements to perform.
Bench & epochIterations(uint64_t numIters) noexcept
Sets exactly the number of iterations for each epoch.
Generate a new block, without valid proof-of-work.
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule).
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
static CTransactionRef MakeTransactionRef()
std::shared_ptr< const CTransaction > CTransactionRef
std::vector< uint8_t > ToByteVector(const T &in)
Validation result for a transaction evaluated by MemPoolAccept (single or package).
const ResultType m_result_type
Result type.
@ VALID
Fully validated, valid.
Options struct containing options for constructing a CTxMemPool.
int check_ratio
The ratio used to determine how often sanity checks will run.
NodeContext struct containing references to chain state and connection state.
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
MempoolAcceptResult AcceptToMemoryPool(Chainstate &active_chainstate, const CTransactionRef &tx, int64_t accept_time, bool bypass_limits, bool test_accept, unsigned int heightOverride)
Try to add a transaction to the mempool.