Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Cluster mempool implementation #28676

Draft
wants to merge 71 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
fc331fb
Add cluster linearization code
sipa May 25, 2023
8e53828
Add is_visited helper to epochguard
sdaftuar Apr 8, 2024
923ae0a
Add txgraph module
sdaftuar Apr 8, 2024
dc8f3a8
add fuzz test for txgraph
sdaftuar Apr 13, 2024
66a72b4
Make CTxMemPoolEntry derive from TxEntry
sdaftuar Apr 8, 2024
4778971
Track clusters in mempool with TxGraph
sdaftuar Apr 8, 2024
01b148f
Limit mempool size based on chunk feerate
sdaftuar Sep 21, 2023
72731e0
Select transactions for blocks based on chunk feerate
sdaftuar Sep 21, 2023
0f78393
Add new (unused) limits for cluster size/count
sdaftuar Sep 21, 2023
917952d
Do not allow mempool clusters to exceed configured limits
sdaftuar Sep 21, 2023
04e8acd
policy: Remove CPFP carveout rule
sdaftuar Oct 3, 2023
be6bf4d
fixup! Add txgraph module
sdaftuar Apr 28, 2024
9b75c1f
Implement new RBF logic for cluster mempool
sdaftuar Sep 21, 2023
acd2e12
==== END CLUSTER IMPLEMENTATION ====
sdaftuar Oct 17, 2023
4407d70
==== BEGIN MEMPOOL CLEANUP ====
sdaftuar Oct 17, 2023
81a1873
Remove the ancestor and descendant indices from the mempool
sdaftuar Sep 21, 2023
7cc6e80
Use cluster linearization for transaction relay sort order
sdaftuar Sep 27, 2023
9730c4c
Remove CTxMemPool::GetSortedDepthAndScore
sdaftuar Sep 28, 2023
d36db77
Reimplement GetTransactionAncestry() to not rely on cached data
sdaftuar Sep 28, 2023
acdad95
rpc: Calculate ancestor data from scratch for mempool rpc calls
sdaftuar Sep 28, 2023
59caf38
Remove dependency on cached ancestor data in mini-miner
sdaftuar Sep 28, 2023
4610706
Stop enforcing ancestor size/count limits
sdaftuar Sep 28, 2023
ba1030a
Add test case for cluster size limits to v3 logic
sdaftuar Apr 14, 2024
02e8648
Use mempool/txgraph to determine if a tx has descendants
sdaftuar Oct 3, 2023
644949d
Calculate descendant information for mempool RPC output on-the-fly
sdaftuar Oct 3, 2023
392f5e0
test: fix rbf carveout test in mempool_limit.py
sdaftuar Oct 18, 2023
113ef57
Stop enforcing descendant size/count limits
sdaftuar Oct 3, 2023
d5dfc7a
wallet: Replace max descendantsize with clustersize
sdaftuar Oct 3, 2023
6d2d662
mempool: Remove unused function CalculateDescendantMaximum
sdaftuar Oct 4, 2023
492d3b3
Eliminate RBF workaround for CPFP carveout transactions
sdaftuar Oct 4, 2023
c57b96d
Eliminate use of cached ancestor data in miniminer_tests and v3_policy
sdaftuar Apr 14, 2024
4e60ada
mempool: eliminate accessors to mempool entry ancestor/descendant cac…
sdaftuar Oct 4, 2023
6b7474c
Remove unused members from CTxMemPoolEntry
sdaftuar Oct 4, 2023
ac467d5
Remove mempool logic designed to maintain ancestor/descendant state
sdaftuar Oct 4, 2023
9e3ee4d
mempool: addUnchecked no longer needs ancestors
sdaftuar Oct 5, 2023
944b402
Remove unused limits from CalculateMemPoolAncestors
sdaftuar Oct 15, 2023
6f47ef2
Make removeConflicts private
sdaftuar Oct 15, 2023
e6775bd
==== END MEMPOOL CLEANUP ====
sdaftuar Oct 17, 2023
4c0c429
==== BEGIN OPTIMIZATIONS ====
sdaftuar Oct 17, 2023
ec7e0a4
Rework removeForBlock so that clusters are only touched once
sdaftuar Oct 10, 2023
f6482a6
Simplify ancestor calculation functions
sdaftuar Oct 15, 2023
fa7a146
Use txgraph to calculate ancestors
sdaftuar Apr 14, 2024
23e8167
Use txgraph to calculate descendants
sdaftuar Apr 14, 2024
70f21d4
Move GetNumChildren() to be a mempool function
sdaftuar Apr 16, 2024
05bef2b
Make getting parents/children a function of the mempool, not a mempoo…
sdaftuar Apr 16, 2024
958e7e9
Rewrite GatherClusters to use the txgraph implementation
sdaftuar Apr 16, 2024
02f2661
Switch to using txgraph parents/children in public accessors
sdaftuar Apr 16, 2024
4da6979
Stop tracking parents/children outside of txgraph
sdaftuar Apr 16, 2024
1792fc3
Remove unused argument to RemoveStaged
sdaftuar Apr 16, 2024
91f7d10
Switch to using the faster CalculateDescendants
sdaftuar Oct 16, 2023
bf37a8b
Rewrite removeRecursive to use vectors instead of sets
sdaftuar Apr 16, 2024
0515a60
Rewrite Expire to only invoke CalculateDescendants once
sdaftuar Apr 16, 2024
d6defcf
Rewrite removeForReorg to use a vector instead of a set
sdaftuar Apr 16, 2024
5c4f01f
Drop unnecessary set in TrimToSize
sdaftuar Apr 16, 2024
240f5b4
RemoveStaged takes a vector, not a set
sdaftuar Apr 16, 2024
aaf45b5
Only use CalculateDescendants() with vectors, not sets
sdaftuar Apr 16, 2024
af45c12
Use faster CalculateMemPoolAncestors in rbf
sdaftuar Apr 16, 2024
0fa99a8
Use faster CMPA in rpc/mempool
sdaftuar Apr 16, 2024
668399b
Eliminate need for ancestors in SingleV3Checks
sdaftuar Apr 16, 2024
11258a8
Eliminate need for ancestors in PackageV3Checks
sdaftuar Apr 16, 2024
998ef3a
Don't calculate ancestors except for RBF transactions
sdaftuar Apr 16, 2024
afbcce4
==== END OPTIMIZATIONS ====
sdaftuar Oct 17, 2023
facaa08
==== BEGIN TESTS ====
sdaftuar Oct 17, 2023
3a5650c
bench: add more mempool benchmarks
sdaftuar Oct 11, 2023
f96104b
fuzz: try to add more code coverage for mempool fuzzing
sdaftuar Oct 12, 2023
e8b3db0
Pass through cluster size limits to TxGraph::check()
sdaftuar Jan 29, 2024
0f558e3
Expose cluster information via rpc
sdaftuar Apr 19, 2023
b10940f
doc: Update mempool_replacements.md to reflect feerate diagram checks
sdaftuar Apr 24, 2024
0303d8f
test: add functional test for new cluster mempool RPCs
sdaftuar Apr 27, 2024
8c4ec6c
fuzz: remove comparison between mini_miner block construction and miner
sdaftuar Apr 28, 2024
f3482ed
test: fix interface_zmq.py for new block connection behavior
sdaftuar Apr 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 42 additions & 0 deletions configure.ac
Expand Up @@ -967,6 +967,48 @@ AC_CHECK_DECLS([setsid])

AC_CHECK_DECLS([pipe2])

AC_CHECK_FUNCS([timingsafe_bcmp])

AC_MSG_CHECKING([for __builtin_clzl])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]], [[
(void) __builtin_clzl(0);
]])],
[ AC_MSG_RESULT([yes]); have_clzl=yes; AC_DEFINE([HAVE_BUILTIN_CLZL], [1], [Define this symbol if you have __builtin_clzl])],
[ AC_MSG_RESULT([no]); have_clzl=no;]
)

AC_MSG_CHECKING([for __builtin_clzll])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]], [[
(void) __builtin_clzll(0);
]])],
[ AC_MSG_RESULT([yes]); have_clzll=yes; AC_DEFINE([HAVE_BUILTIN_CLZLL], [1], [Define this symbol if you have __builtin_clzll])],
[ AC_MSG_RESULT([no]); have_clzll=no;]
)

AC_MSG_CHECKING([for __builtin_ctz])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]], [[
(void) __builtin_ctz(0);
]])],
[ AC_MSG_RESULT([yes]); have_ctz=yes; AC_DEFINE([HAVE_BUILTIN_CTZ], [1], [Define this symbol if you have __builtin_ctz])],
[ AC_MSG_RESULT([no]); have_ctz=no;]
)

AC_MSG_CHECKING([for __builtin_ctzl])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]], [[
(void) __builtin_ctzl(0);
]])],
[ AC_MSG_RESULT([yes]); have_ctzl=yes; AC_DEFINE([HAVE_BUILTIN_CTZL], [1], [Define this symbol if you have __builtin_ctzl])],
[ AC_MSG_RESULT([no]); have_ctzl=no;]
)

AC_MSG_CHECKING([for __builtin_ctzll])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]], [[
(void) __builtin_ctzll(0);
]])],
[ AC_MSG_RESULT([yes]); have_ctzll=yes; AC_DEFINE([HAVE_BUILTIN_CTZLL], [1], [Define this symbol if you have __builtin_ctzll])],
[ AC_MSG_RESULT([no]); have_ctzll=no;]
)

dnl Check for malloc_info (for memory statistics information in getmemoryinfo)
AC_MSG_CHECKING([for getmemoryinfo])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <malloc.h>]],
Expand Down
28 changes: 9 additions & 19 deletions doc/policy/mempool-replacements.md
Expand Up @@ -19,12 +19,7 @@ other consensus and policy rules, each of the following conditions are met:
Use the (`-mempoolfullrbf`) configuration option to allow transaction replacement without enforcement of the
opt-in signaling rule.

2. The replacement transaction only include an unconfirmed input if that input was included in
one of the directly conflicting transactions. An unconfirmed input spends an output from a
currently-unconfirmed transaction.

*Rationale*: When RBF was originally implemented, the mempool did not keep track of
ancestor feerates yet. This rule was suggested as a temporary restriction.
2. [REDACTED]

3. The replacement transaction pays an absolute fee of at least the sum paid by the original
sdaftuar marked this conversation as resolved.
Show resolved Hide resolved
transactions.
Expand All @@ -45,23 +40,16 @@ other consensus and policy rules, each of the following conditions are met:
*Rationale*: Try to prevent DoS attacks where an attacker causes the network to repeatedly relay
transactions each paying a tiny additional amount in fees, e.g. just 1 satoshi.

5. The number of original transactions does not exceed 100. More precisely, the sum of all
directly conflicting transactions' descendant counts (number of transactions inclusive of itself
and its descendants) must not exceed 100; it is possible that this overestimates the true number
of original transactions.
5. The number of directly conflicting transactions does not exceed 100.

*Rationale*: Try to prevent DoS attacks where an attacker is able to easily occupy and flush out
significant portions of the node's mempool using replacements with multiple directly conflicting
transactions, each with large descendant sets.
*Rationale*: Limit CPU usage required to update the mempool for so many transactions being
removed at once.

6. The replacement transaction's feerate is greater than the feerates of all directly conflicting
transactions.
6. The feerate diagram of the mempool must be strictly improved by the replacement transaction.

*Rationale*: This rule was originally intended to ensure that the replacement transaction is
preferable for block-inclusion, compared to what would be removed from the mempool. This rule
predates ancestor feerate-based transaction selection.
*Rationale*: This ensures that block fees in all future blocks will go up
after the replacement (ignoring tail effects at the end of a block).

This set of rules is similar but distinct from BIP125.

Copy link
Member

@Sjors Sjors Nov 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bf467f8: history can be expanded:

  * Cluster mempool introduced, dropping rule 2 and introducing rule 7.
    As of **v27.0** ([PR 28676](https://github.com/bitcoin/bitcoin/pull/28676)).

## History

Expand All @@ -80,3 +68,5 @@ This set of rules is similar but distinct from BIP125.

* Full replace-by-fee enabled as a configurable mempool policy as of **v24.0** ([PR
#25353](https://github.com/bitcoin/bitcoin/pull/25353)).

* Feerate diagram policy enabled in conjunction with switch to cluster mempool as of **v??.0**.
5 changes: 5 additions & 0 deletions src/Makefile.am
Expand Up @@ -132,6 +132,7 @@ BITCOIN_CORE_H = \
chainparamsseeds.h \
checkqueue.h \
clientversion.h \
cluster_linearize.h \
coins.h \
common/args.h \
common/bloom.h \
Expand Down Expand Up @@ -192,6 +193,7 @@ BITCOIN_CORE_H = \
kernel/mempool_removal_reason.h \
kernel/messagestartchars.h \
kernel/notifications_interface.h \
kernel/txgraph.h \
kernel/validation_cache_sizes.h \
key.h \
key_io.h \
Expand Down Expand Up @@ -292,6 +294,7 @@ BITCOIN_CORE_H = \
util/batchpriority.h \
util/bip32.h \
util/bitdeque.h \
util/bitset.h \
util/bytevectorhash.h \
util/chaintype.h \
util/check.h \
Expand Down Expand Up @@ -408,6 +411,7 @@ libbitcoin_node_a_SOURCES = \
kernel/disconnected_transactions.cpp \
kernel/mempool_persist.cpp \
kernel/mempool_removal_reason.cpp \
kernel/txgraph.cpp \
mapport.cpp \
net.cpp \
net_processing.cpp \
Expand Down Expand Up @@ -945,6 +949,7 @@ libbitcoinkernel_la_SOURCES = \
kernel/disconnected_transactions.cpp \
kernel/mempool_persist.cpp \
kernel/mempool_removal_reason.cpp \
kernel/txgraph.cpp \
key.cpp \
logging.cpp \
node/blockstorage.cpp \
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile.test.include
Expand Up @@ -157,6 +157,7 @@ BITCOIN_TESTS =\
test/torcontrol_tests.cpp \
test/transaction_tests.cpp \
test/translation_tests.cpp \
test/txgraph_tests.cpp \
test/txindex_tests.cpp \
test/txpackage_tests.cpp \
test/txreconciliation_tests.cpp \
Expand Down Expand Up @@ -390,6 +391,7 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/tx_in.cpp \
test/fuzz/tx_out.cpp \
test/fuzz/tx_pool.cpp \
test/fuzz/txgraph.cpp \
test/fuzz/txorphan.cpp \
test/fuzz/txrequest.cpp \
test/fuzz/utxo_snapshot.cpp \
Expand Down
164 changes: 153 additions & 11 deletions src/bench/mempool_stress.cpp
Expand Up @@ -13,15 +13,15 @@

#include <vector>

static void AddTx(const CTransactionRef& tx, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs)
static void AddTx(const CTransactionRef& tx, CTxMemPool& pool, FastRandomContext& det_rand) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs)
{
int64_t nTime = 0;
unsigned int nHeight = 1;
uint64_t sequence = 0;
bool spendsCoinbase = false;
unsigned int sigOpCost = 4;
LockPoints lp;
pool.addUnchecked(CTxMemPoolEntry(tx, 1000, nTime, nHeight, sequence, spendsCoinbase, sigOpCost, lp));
pool.addUnchecked(CTxMemPoolEntry(tx, det_rand.randrange(10000)+1000, nTime, nHeight, sequence, spendsCoinbase, sigOpCost, lp));
}

struct Available {
Expand All @@ -31,15 +31,17 @@ struct Available {
Available(CTransactionRef& ref, size_t tx_count) : ref(ref), tx_count(tx_count){}
};

static std::vector<CTransactionRef> CreateOrderedCoins(FastRandomContext& det_rand, int childTxs, int min_ancestors)
// Create a cluster of transactions, randomly.
static std::vector<CTransactionRef> CreateCoinCluster(FastRandomContext& det_rand, int childTxs, int min_ancestors)
{
std::vector<Available> available_coins;
std::vector<CTransactionRef> ordered_coins;
// Create some base transactions
size_t tx_counter = 1;
for (auto x = 0; x < 100; ++x) {
for (auto x = 0; x < 10; ++x) {
CMutableTransaction tx = CMutableTransaction();
tx.vin.resize(1);
tx.vin[0].prevout = COutPoint(Txid::FromUint256(GetRandHash()), 1);
tx.vin[0].scriptSig = CScript() << CScriptNum(tx_counter);
tx.vin[0].scriptWitness.stack.push_back(CScriptNum(x).getvch());
tx.vout.resize(det_rand.randrange(10)+2);
Expand Down Expand Up @@ -83,26 +85,104 @@ static std::vector<CTransactionRef> CreateOrderedCoins(FastRandomContext& det_ra
return ordered_coins;
}

static void MemPoolAddTransactions(benchmark::Bench& bench)
{
FastRandomContext det_rand{true};
int childTxs = 90;
if (bench.complexityN() > 1) {
childTxs = static_cast<int>(bench.complexityN());
}
const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(ChainType::MAIN);
CTxMemPool& pool = *testing_setup.get()->m_node.mempool;

std::vector<CTransactionRef> transactions;
// Create 1000 clusters of 100 transactions each
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

numbers in comments are off

shower thought: Should we/can we bound the number of clusters in addition to total memory in TrimToSize? I can't think of a good way to do that that doesn't complicate things quite a bit, and perhaps practical mempool sizes make this moot. Just something to consider in case I missed something obvious.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The immediate downside to a cap on number of clusters is that singleton, high-feerate transactions would not be accepted. And I don't think we need to -- the only places where having more clusters makes us slower is in eviction and mining, and for both of those use cases we could improve performance (if we need to) by maintaining the relevant heap data structures (or something equivalent) as chunks are modified, rather than all at once.

For now in this branch I've created these from scratch each time, but if it turns out that performance is meaningfully impacted when the mempool is busy, then I can optimize this further by just using a bit more memory.

for (int i=0; i<100; i++) {
auto new_txs = CreateCoinCluster(det_rand, childTxs, /*min_ancestors*/ 1);
transactions.insert(transactions.end(), new_txs.begin(), new_txs.end());
}

LOCK2(cs_main, pool.cs);

bench.run([&]() NO_THREAD_SAFETY_ANALYSIS {
for (auto& tx : transactions) {
AddTx(tx, pool, det_rand);
}
pool.TrimToSize(0, nullptr);
});
}

static void ComplexMemPool(benchmark::Bench& bench)
{
FastRandomContext det_rand{true};
int childTxs = 800;
int childTxs = 90;
if (bench.complexityN() > 1) {
childTxs = static_cast<int>(bench.complexityN());
}
std::vector<CTransactionRef> ordered_coins = CreateOrderedCoins(det_rand, childTxs, /*min_ancestors=*/1);
const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(ChainType::MAIN);
CTxMemPool& pool = *testing_setup.get()->m_node.mempool;

std::vector<CTransactionRef> tx_remove_for_block;
std::vector<uint256> hashes_remove_for_block;

LOCK2(cs_main, pool.cs);

for (int i=0; i<1000; i++) {
std::vector<CTransactionRef> transactions = CreateCoinCluster(det_rand, childTxs, /*min_ancestors=*/1);

// Add all transactions to the mempool.
// Also store the first 10 transactions from each cluster as the
// transactions we'll "mine" in the the benchmark.
int tx_count = 0;
for (auto& tx : transactions) {
if (tx_count < 10) {
tx_remove_for_block.push_back(tx);
++tx_count;
hashes_remove_for_block.emplace_back(tx->GetHash());
}
AddTx(tx, pool, det_rand);
}
}

// Since the benchmark will be run repeatedly, we have to leave the mempool
// in the same state at the end of the function, so we benchmark both
// mining a block and reorging the block's contents back into the mempool.
bench.run([&]() NO_THREAD_SAFETY_ANALYSIS {
for (auto& tx : ordered_coins) {
AddTx(tx, pool);
pool.removeForBlock(tx_remove_for_block, /*nBlockHeight*/100);
for (auto& tx: tx_remove_for_block) {
AddTx(tx, pool, det_rand);
}
pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4);
pool.TrimToSize(GetVirtualTransactionSize(*ordered_coins.front()));
pool.UpdateTransactionsFromBlock(hashes_remove_for_block);
});
}

static void MemPoolAncestorsDescendants(benchmark::Bench& bench)
{
FastRandomContext det_rand{true};
int childTxs = 90;
if (bench.complexityN() > 1) {
childTxs = static_cast<int>(bench.complexityN());
}
const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(ChainType::MAIN);
CTxMemPool& pool = *testing_setup.get()->m_node.mempool;

LOCK2(cs_main, pool.cs);

std::vector<CTransactionRef> transactions = CreateCoinCluster(det_rand, childTxs, /*min_ancestors=*/1);
for (auto& tx : transactions) {
AddTx(tx, pool, det_rand);
}

CTxMemPool::txiter first_tx = *pool.GetIter(transactions[0]->GetHash());
CTxMemPool::txiter last_tx = *pool.GetIter(transactions.back()->GetHash());

bench.run([&]() NO_THREAD_SAFETY_ANALYSIS {
ankerl::nanobench::doNotOptimizeAway(pool.CalculateDescendants({first_tx}));
ankerl::nanobench::doNotOptimizeAway(pool.CalculateMemPoolAncestors(*last_tx, false));
});
}


static void MempoolCheck(benchmark::Bench& bench)
{
FastRandomContext det_rand{true};
Expand All @@ -112,11 +192,73 @@ static void MempoolCheck(benchmark::Bench& bench)
testing_setup->PopulateMempool(det_rand, 400, true);
const CCoinsViewCache& coins_tip = testing_setup.get()->m_node.chainman->ActiveChainstate().CoinsTip();

CTxMemPool::Limits limits(kernel::MemPoolLimits::NoLimits());

bench.run([&]() NO_THREAD_SAFETY_ANALYSIS {
// Bump up the spendheight so we don't hit premature coinbase spend errors.
pool.check(coins_tip, /*spendheight=*/300);
pool.check(coins_tip, /*spendheight=*/300, &limits);
});
}

#if 0
static void MemPoolMiningScoreCheck(benchmark::Bench& bench)
{
// Default test: each cluster is of size 20, and we'll try to RBF with a
// transaction that merges 10 clusters, evicting 10 transactions from each.

FastRandomContext det_rand{true};
int childTxs = 10;
if (bench.complexityN() > 1) {
childTxs = static_cast<int>(bench.complexityN());
}
const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(ChainType::MAIN);
CTxMemPool& pool = *testing_setup.get()->m_node.mempool;

LOCK2(cs_main, pool.cs);

std::vector<CTransactionRef> parent_txs_for_rbf;
std::set<uint256> child_txs_to_conflict_with;

for (int i=0; i<10; i++) {
std::vector<CTransactionRef> transactions = CreateCoinCluster(det_rand, childTxs, /*min_ancestors=*/1);
parent_txs_for_rbf.push_back(transactions[0]);
// Conflict with everything after the first 10 transactions
for (size_t j=10; j<transactions.size(); ++j) {
child_txs_to_conflict_with.insert(transactions[j]->GetHash());
}

// Add all transactions to the mempool.
for (auto& tx : transactions) {
AddTx(tx, pool, det_rand);
}
}

// Construct a transaction that spends from each of the parent transactions
// selected.
CMutableTransaction tx = CMutableTransaction();
tx.vin.resize(10);
for (size_t i=0; i<parent_txs_for_rbf.size(); ++i) {
tx.vin[i].prevout = COutPoint(parent_txs_for_rbf[i]->GetHash(), 0);
tx.vin[i].scriptSig = CScript() << i;
}
tx.vout.resize(1);
for (auto& out : tx.vout) {
out.scriptPubKey = CScript() << CScriptNum(det_rand.randrange(19)+1) << OP_EQUAL;
out.nValue = 10 * COIN;
}

CTxMemPool::setEntries all_conflicts = pool.GetIterSet(child_txs_to_conflict_with);
CTxMemPoolEntry entry(MakeTransactionRef(tx), det_rand.randrange(10000)+1000, 0, 1, 0, false, 4, LockPoints());

bench.run([&]() NO_THREAD_SAFETY_ANALYSIS {
CTxMemPool::Limits limits(pool.m_limits);
pool.CalculateMiningScoreOfReplacementTx(entry, det_rand.randrange(30000)+1000, all_conflicts, limits);
});
}
#endif

BENCHMARK(MemPoolAncestorsDescendants, benchmark::PriorityLevel::HIGH);
BENCHMARK(MemPoolAddTransactions, benchmark::PriorityLevel::HIGH);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dd6684a: While you're touching this, can you rename MempoolCheck to MemPoolCheck, MempoolEviction to MemPoolEviction and ComplexMemPool to MempoolComplex? That makes -filter=MemPool.* work

As a workaround, -filter=.*Mem.* does work.

BENCHMARK(ComplexMemPool, benchmark::PriorityLevel::HIGH);
BENCHMARK(MempoolCheck, benchmark::PriorityLevel::HIGH);
//BENCHMARK(MemPoolMiningScoreCheck, benchmark::PriorityLevel::HIGH);