Skip to content

Commit 7fb62f7

Browse files
committed
Apply mempool changeset transactions directly into the mempool
Rather than individually calling addUnchecked for each transaction added in a changeset (after removing all the to-be-removed transactions), instead we can take advantage of boost::multi_index's splicing features to extract and insert entries directly from the staging multi_index into mapTx. This has the immediate advantage of saving allocation overhead for mempool entries which have already been allocated once. This also means that the memory locations of mempool entries will not change when transactions go from staging to the main mempool. Additionally, eliminate addUnchecked and require all new transactions to enter the mempool via a CTxMemPoolChangeSet.
1 parent 34b6c58 commit 7fb62f7

20 files changed

+268
-209
lines changed

src/bench/mempool_ephemeral_spends.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <script/script.h>
1212
#include <sync.h>
1313
#include <test/util/setup_common.h>
14+
#include <test/util/txmempool.h>
1415
#include <txmempool.h>
1516
#include <util/check.h>
1617

@@ -28,7 +29,7 @@ static void AddTx(const CTransactionRef& tx, CTxMemPool& pool) EXCLUSIVE_LOCKS_R
2829
unsigned int sigOpCost{4};
2930
uint64_t fee{0};
3031
LockPoints lp;
31-
pool.addUnchecked(CTxMemPoolEntry(
32+
AddToMempool(pool, CTxMemPoolEntry(
3233
tx, fee, nTime, nHeight, sequence,
3334
spendsCoinbase, sigOpCost, lp));
3435
}

src/bench/mempool_eviction.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <script/script.h>
1111
#include <sync.h>
1212
#include <test/util/setup_common.h>
13+
#include <test/util/txmempool.h>
1314
#include <txmempool.h>
1415
#include <util/check.h>
1516

@@ -26,7 +27,7 @@ static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& po
2627
bool spendsCoinbase = false;
2728
unsigned int sigOpCost = 4;
2829
LockPoints lp;
29-
pool.addUnchecked(CTxMemPoolEntry(
30+
AddToMempool(pool, CTxMemPoolEntry(
3031
tx, nFee, nTime, nHeight, sequence,
3132
spendsCoinbase, sigOpCost, lp));
3233
}

src/bench/mempool_stress.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <script/script.h>
1111
#include <sync.h>
1212
#include <test/util/setup_common.h>
13+
#include <test/util/txmempool.h>
1314
#include <txmempool.h>
1415
#include <validation.h>
1516

@@ -28,7 +29,7 @@ static void AddTx(const CTransactionRef& tx, CTxMemPool& pool) EXCLUSIVE_LOCKS_R
2829
bool spendsCoinbase = false;
2930
unsigned int sigOpCost = 4;
3031
LockPoints lp;
31-
pool.addUnchecked(CTxMemPoolEntry(tx, 1000, nTime, nHeight, sequence, spendsCoinbase, sigOpCost, lp));
32+
AddToMempool(pool, CTxMemPoolEntry(tx, 1000, nTime, nHeight, sequence, spendsCoinbase, sigOpCost, lp));
3233
}
3334

3435
struct Available {

src/bench/rpc_mempool.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <script/script.h>
1111
#include <sync.h>
1212
#include <test/util/setup_common.h>
13+
#include <test/util/txmempool.h>
1314
#include <txmempool.h>
1415
#include <univalue.h>
1516
#include <util/check.h>
@@ -21,7 +22,7 @@
2122
static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs)
2223
{
2324
LockPoints lp;
24-
pool.addUnchecked(CTxMemPoolEntry(tx, fee, /*time=*/0, /*entry_height=*/1, /*entry_sequence=*/0, /*spends_coinbase=*/false, /*sigops_cost=*/4, lp));
25+
AddToMempool(pool, CTxMemPoolEntry(tx, fee, /*time=*/0, /*entry_height=*/1, /*entry_sequence=*/0, /*spends_coinbase=*/false, /*sigops_cost=*/4, lp));
2526
}
2627

2728
static void RpcMempool(benchmark::Bench& bench)

src/test/blockencodings_tests.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(SimpleRoundTripTest)
6767
CBlock block(BuildBlockTestCase(rand_ctx));
6868

6969
LOCK2(cs_main, pool.cs);
70-
pool.addUnchecked(entry.FromTx(block.vtx[2]));
70+
AddToMempool(pool, entry.FromTx(block.vtx[2]));
7171
BOOST_CHECK_EQUAL(pool.get(block.vtx[2]->GetHash()).use_count(), SHARED_TX_OFFSET + 0);
7272

7373
// Do a simple ShortTxIDs RT
@@ -151,7 +151,7 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
151151
CBlock block(BuildBlockTestCase(rand_ctx));
152152

153153
LOCK2(cs_main, pool.cs);
154-
pool.addUnchecked(entry.FromTx(block.vtx[2]));
154+
AddToMempool(pool, entry.FromTx(block.vtx[2]));
155155
BOOST_CHECK_EQUAL(pool.get(block.vtx[2]->GetHash()).use_count(), SHARED_TX_OFFSET + 0);
156156

157157
uint256 txhash;
@@ -222,7 +222,7 @@ BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
222222
CBlock block(BuildBlockTestCase(rand_ctx));
223223

224224
LOCK2(cs_main, pool.cs);
225-
pool.addUnchecked(entry.FromTx(block.vtx[1]));
225+
AddToMempool(pool, entry.FromTx(block.vtx[1]));
226226
BOOST_CHECK_EQUAL(pool.get(block.vtx[1]->GetHash()).use_count(), SHARED_TX_OFFSET + 0);
227227

228228
uint256 txhash;
@@ -322,7 +322,7 @@ BOOST_AUTO_TEST_CASE(ReceiveWithExtraTransactions) {
322322
extra_txn.resize(10);
323323

324324
LOCK2(cs_main, pool.cs);
325-
pool.addUnchecked(entry.FromTx(block.vtx[2]));
325+
AddToMempool(pool, entry.FromTx(block.vtx[2]));
326326
BOOST_CHECK_EQUAL(pool.get(block.vtx[2]->GetHash()).use_count(), SHARED_TX_OFFSET + 0);
327327
// Ensure the non_block_tx is actually not in the block
328328
for (const auto &block_tx : block.vtx) {

src/test/fuzz/mini_miner.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ FUZZ_TARGET(mini_miner, .init = initialize_miner)
5959
TestMemPoolEntryHelper entry;
6060
const CAmount fee{ConsumeMoney(fuzzed_data_provider, /*max=*/MAX_MONEY/100000)};
6161
assert(MoneyRange(fee));
62-
pool.addUnchecked(entry.Fee(fee).FromTx(tx));
62+
AddToMempool(pool, entry.Fee(fee).FromTx(tx));
6363

6464
// All outputs are available to spend
6565
for (uint32_t n{0}; n < num_outputs; ++n) {
@@ -154,7 +154,7 @@ FUZZ_TARGET(mini_miner_selection, .init = initialize_miner)
154154
TestMemPoolEntryHelper entry;
155155
const CAmount fee{ConsumeMoney(fuzzed_data_provider, /*max=*/MAX_MONEY/100000)};
156156
assert(MoneyRange(fee));
157-
pool.addUnchecked(entry.Fee(fee).FromTx(tx));
157+
AddToMempool(pool, entry.Fee(fee).FromTx(tx));
158158
transactions.push_back(tx);
159159
}
160160
std::vector<COutPoint> outpoints;

src/test/fuzz/partially_downloaded_block.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ FUZZ_TARGET(partially_downloaded_block, .init = initialize_pdb)
7878

7979
if (add_to_mempool && !pool.exists(GenTxid::Txid(tx->GetHash()))) {
8080
LOCK2(cs_main, pool.cs);
81-
pool.addUnchecked(ConsumeTxMemPoolEntry(fuzzed_data_provider, *tx));
81+
AddToMempool(pool, ConsumeTxMemPoolEntry(fuzzed_data_provider, *tx));
8282
available.insert(i);
8383
}
8484
}

src/test/fuzz/rbf.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,12 @@ FUZZ_TARGET(rbf, .init = initialize_rbf)
7373
mtx->vin[0].prevout = COutPoint{another_tx.GetHash(), 0};
7474
}
7575
LOCK2(cs_main, pool.cs);
76-
pool.addUnchecked(ConsumeTxMemPoolEntry(fuzzed_data_provider, another_tx));
76+
AddToMempool(pool, ConsumeTxMemPoolEntry(fuzzed_data_provider, another_tx));
7777
}
7878
const CTransaction tx{*mtx};
7979
if (fuzzed_data_provider.ConsumeBool()) {
8080
LOCK2(cs_main, pool.cs);
81-
pool.addUnchecked(ConsumeTxMemPoolEntry(fuzzed_data_provider, tx));
81+
AddToMempool(pool, ConsumeTxMemPoolEntry(fuzzed_data_provider, tx));
8282
}
8383
{
8484
LOCK(pool.cs);
@@ -129,7 +129,7 @@ FUZZ_TARGET(package_rbf, .init = initialize_package_rbf)
129129
mempool_txs.pop_back();
130130
break;
131131
}
132-
pool.addUnchecked(parent_entry);
132+
AddToMempool(pool, parent_entry);
133133
if (fuzzed_data_provider.ConsumeBool()) {
134134
child.vin[0].prevout = COutPoint{mempool_txs.back().GetHash(), 0};
135135
}
@@ -141,7 +141,7 @@ FUZZ_TARGET(package_rbf, .init = initialize_package_rbf)
141141
mempool_txs.pop_back();
142142
break;
143143
}
144-
pool.addUnchecked(child_entry);
144+
AddToMempool(pool, child_entry);
145145

146146
if (fuzzed_data_provider.ConsumeBool()) {
147147
pool.PrioritiseTransaction(mempool_txs.back().GetHash().ToUint256(), fuzzed_data_provider.ConsumeIntegralInRange<int32_t>(-100000, 100000));

0 commit comments

Comments
 (0)