Skip to content

Commit 8e1913a

Browse files
author
MarcoFalke
committed
Merge #21062: refactor: return MempoolAcceptResult from ATMP
53e716e [refactor] improve style for touched code (gzhao408) 174cb53 [refactor] const ATMPArgs and non-const Workspace (gzhao408) f82baf0 [refactor] return MempoolAcceptResult (gzhao408) 9db10a5 [refactor] clean up logic in testmempoolaccept (gzhao408) Pull request description: This is the first 4 commits of #20833, and does refactoring only. It should be relatively simple to review, and offers a few nice things: - It makes accessing values that don't make sense (e.g. fee) when the tx is invalid an error. - Returning `MempoolAcceptResult` from ATMP makes the interface cleaner. The caller can get a const instead of passing in a mutable "out" param. - We don't have to be iterating through a bunch of lists for package validation, we can just return a `std::vector<MempoolAcceptResult>`. - We don't have to refactor all ATMP call sites again if/when we want to return more stuff from it. ACKs for top commit: MarcoFalke: ACK 53e716e 💿 jnewbery: Code review ACK 53e716e ariard: Code Review ACK 53e716e, I did tweak a bit the touched paths to see if we had good test coverage. Didn't find holes. Tree-SHA512: fa6ec324a08ad9e6e55948615cda324cba176255708bf0a0a0f37cedb7a75311aa334ac6f223be7d8df3c7379502b1081102b9589f9a9afa1713ad3d9ab3c24f
2 parents a1be084 + 53e716e commit 8e1913a

9 files changed

+135
-133
lines changed

src/bench/block_assemble.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,8 @@ static void AssembleBlock(benchmark::Bench& bench)
4848
LOCK(::cs_main); // Required for ::AcceptToMemoryPool.
4949

5050
for (const auto& txr : txs) {
51-
TxValidationState state;
52-
bool ret{::AcceptToMemoryPool(*test_setup.m_node.mempool, state, txr, nullptr /* plTxnReplaced */, false /* bypass_limits */)};
53-
assert(ret);
51+
const MempoolAcceptResult res = ::AcceptToMemoryPool(*test_setup.m_node.mempool, txr, false /* bypass_limits */);
52+
assert(res.m_result_type == MempoolAcceptResult::ResultType::VALID);
5453
}
5554
}
5655

src/net_processing.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2178,10 +2178,10 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
21782178
if (orphan_it == mapOrphanTransactions.end()) continue;
21792179

21802180
const CTransactionRef porphanTx = orphan_it->second.tx;
2181-
TxValidationState state;
2182-
std::list<CTransactionRef> removed_txn;
2181+
const MempoolAcceptResult result = AcceptToMemoryPool(m_mempool, porphanTx, false /* bypass_limits */);
2182+
const TxValidationState& state = result.m_state;
21832183

2184-
if (AcceptToMemoryPool(m_mempool, state, porphanTx, &removed_txn, false /* bypass_limits */)) {
2184+
if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
21852185
LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString());
21862186
RelayTransaction(orphanHash, porphanTx->GetWitnessHash(), m_connman);
21872187
for (unsigned int i = 0; i < porphanTx->vout.size(); i++) {
@@ -2193,7 +2193,7 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
21932193
}
21942194
}
21952195
EraseOrphanTx(orphanHash);
2196-
for (const CTransactionRef& removedTx : removed_txn) {
2196+
for (const CTransactionRef& removedTx : result.m_replaced_transactions.value()) {
21972197
AddToCompactExtraTransactions(removedTx);
21982198
}
21992199
break;
@@ -3200,10 +3200,10 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
32003200
return;
32013201
}
32023202

3203-
TxValidationState state;
3204-
std::list<CTransactionRef> lRemovedTxn;
3203+
const MempoolAcceptResult result = AcceptToMemoryPool(m_mempool, ptx, false /* bypass_limits */);
3204+
const TxValidationState& state = result.m_state;
32053205

3206-
if (AcceptToMemoryPool(m_mempool, state, ptx, &lRemovedTxn, false /* bypass_limits */)) {
3206+
if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
32073207
m_mempool.check(&::ChainstateActive().CoinsTip());
32083208
// As this version of the transaction was acceptable, we can forget about any
32093209
// requests for it.
@@ -3226,7 +3226,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
32263226
tx.GetHash().ToString(),
32273227
m_mempool.size(), m_mempool.DynamicMemoryUsage() / 1000);
32283228

3229-
for (const CTransactionRef& removedTx : lRemovedTxn) {
3229+
for (const CTransactionRef& removedTx : result.m_replaced_transactions.value()) {
32303230
AddToCompactExtraTransactions(removedTx);
32313231
}
32323232

src/node/transaction.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,22 +50,22 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
5050
}
5151
if (!node.mempool->exists(hashTx)) {
5252
// Transaction is not already in the mempool.
53-
TxValidationState state;
5453
if (max_tx_fee > 0) {
5554
// First, call ATMP with test_accept and check the fee. If ATMP
5655
// fails here, return error immediately.
57-
CAmount fee{0};
58-
if (!AcceptToMemoryPool(*node.mempool, state, tx,
59-
nullptr /* plTxnReplaced */, false /* bypass_limits */, /* test_accept */ true, &fee)) {
60-
return HandleATMPError(state, err_string);
61-
} else if (fee > max_tx_fee) {
56+
const MempoolAcceptResult result = AcceptToMemoryPool(*node.mempool, tx, false /* bypass_limits */,
57+
true /* test_accept */);
58+
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
59+
return HandleATMPError(result.m_state, err_string);
60+
} else if (result.m_base_fees.value() > max_tx_fee) {
6261
return TransactionError::MAX_FEE_EXCEEDED;
6362
}
6463
}
6564
// Try to submit the transaction to the mempool.
66-
if (!AcceptToMemoryPool(*node.mempool, state, tx,
67-
nullptr /* plTxnReplaced */, false /* bypass_limits */)) {
68-
return HandleATMPError(state, err_string);
65+
const MempoolAcceptResult result = AcceptToMemoryPool(*node.mempool, tx, false /* bypass_limits */,
66+
false /* test_accept */);
67+
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
68+
return HandleATMPError(result.m_state, err_string);
6969
}
7070

7171
// Transaction was accepted to the mempool.

src/rpc/rawtransaction.cpp

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -946,44 +946,35 @@ static RPCHelpMan testmempoolaccept()
946946
result_0.pushKV("txid", tx->GetHash().GetHex());
947947
result_0.pushKV("wtxid", tx->GetWitnessHash().GetHex());
948948

949-
TxValidationState state;
950-
bool test_accept_res;
951-
CAmount fee{0};
952-
{
953-
LOCK(cs_main);
954-
test_accept_res = AcceptToMemoryPool(mempool, state, std::move(tx),
955-
nullptr /* plTxnReplaced */, false /* bypass_limits */, /* test_accept */ true, &fee);
956-
}
957-
958-
// Check that fee does not exceed maximum fee
959-
if (test_accept_res && max_raw_tx_fee && fee > max_raw_tx_fee) {
960-
result_0.pushKV("allowed", false);
961-
result_0.pushKV("reject-reason", "max-fee-exceeded");
962-
result.push_back(std::move(result_0));
963-
return result;
964-
}
965-
result_0.pushKV("allowed", test_accept_res);
949+
const MempoolAcceptResult accept_result = WITH_LOCK(cs_main, return AcceptToMemoryPool(mempool, std::move(tx),
950+
false /* bypass_limits */, /* test_accept */ true));
966951

967952
// Only return the fee and vsize if the transaction would pass ATMP.
968953
// These can be used to calculate the feerate.
969-
if (test_accept_res) {
970-
result_0.pushKV("vsize", virtual_size);
971-
UniValue fees(UniValue::VOBJ);
972-
fees.pushKV("base", ValueFromAmount(fee));
973-
result_0.pushKV("fees", fees);
954+
if (accept_result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
955+
const CAmount fee = accept_result.m_base_fees.value();
956+
// Check that fee does not exceed maximum fee
957+
if (max_raw_tx_fee && fee > max_raw_tx_fee) {
958+
result_0.pushKV("allowed", false);
959+
result_0.pushKV("reject-reason", "max-fee-exceeded");
960+
} else {
961+
result_0.pushKV("allowed", true);
962+
result_0.pushKV("vsize", virtual_size);
963+
UniValue fees(UniValue::VOBJ);
964+
fees.pushKV("base", ValueFromAmount(fee));
965+
result_0.pushKV("fees", fees);
966+
}
967+
result.push_back(std::move(result_0));
974968
} else {
975-
if (state.IsInvalid()) {
976-
if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
977-
result_0.pushKV("reject-reason", "missing-inputs");
978-
} else {
979-
result_0.pushKV("reject-reason", strprintf("%s", state.GetRejectReason()));
980-
}
969+
result_0.pushKV("allowed", false);
970+
const TxValidationState state = accept_result.m_state;
971+
if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
972+
result_0.pushKV("reject-reason", "missing-inputs");
981973
} else {
982974
result_0.pushKV("reject-reason", state.GetRejectReason());
983975
}
976+
result.push_back(std::move(result_0));
984977
}
985-
986-
result.push_back(std::move(result_0));
987978
return result;
988979
},
989980
};

src/test/txvalidation_tests.cpp

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,21 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)
3030

3131
BOOST_CHECK(CTransaction(coinbaseTx).IsCoinBase());
3232

33-
TxValidationState state;
34-
3533
LOCK(cs_main);
3634

3735
unsigned int initialPoolSize = m_node.mempool->size();
36+
const MempoolAcceptResult result = AcceptToMemoryPool(*m_node.mempool, MakeTransactionRef(coinbaseTx),
37+
true /* bypass_limits */);
3838

39-
BOOST_CHECK_EQUAL(
40-
false,
41-
AcceptToMemoryPool(*m_node.mempool, state, MakeTransactionRef(coinbaseTx),
42-
nullptr /* plTxnReplaced */,
43-
true /* bypass_limits */));
39+
BOOST_CHECK(result.m_result_type == MempoolAcceptResult::ResultType::INVALID);
4440

4541
// Check that the transaction hasn't been added to mempool.
4642
BOOST_CHECK_EQUAL(m_node.mempool->size(), initialPoolSize);
4743

4844
// Check that the validation state reflects the unsuccessful attempt.
49-
BOOST_CHECK(state.IsInvalid());
50-
BOOST_CHECK_EQUAL(state.GetRejectReason(), "coinbase");
51-
BOOST_CHECK(state.GetResult() == TxValidationResult::TX_CONSENSUS);
45+
BOOST_CHECK(result.m_state.IsInvalid());
46+
BOOST_CHECK_EQUAL(result.m_state.GetRejectReason(), "coinbase");
47+
BOOST_CHECK(result.m_state.GetResult() == TxValidationResult::TX_CONSENSUS);
5248
}
5349

5450
BOOST_AUTO_TEST_SUITE_END()

src/test/txvalidationcache_tests.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
2828
const auto ToMemPool = [this](const CMutableTransaction& tx) {
2929
LOCK(cs_main);
3030

31-
TxValidationState state;
32-
return AcceptToMemoryPool(*m_node.mempool, state, MakeTransactionRef(tx),
33-
nullptr /* plTxnReplaced */, true /* bypass_limits */);
31+
const MempoolAcceptResult result = AcceptToMemoryPool(*m_node.mempool, MakeTransactionRef(tx),
32+
true /* bypass_limits */);
33+
return result.m_result_type == MempoolAcceptResult::ResultType::VALID;
3434
};
3535

3636
// Create a double-spend of mature coinbase txn:

src/test/validation_block_tests.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -283,15 +283,9 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
283283
// Add the txs to the tx pool
284284
{
285285
LOCK(cs_main);
286-
TxValidationState state;
287-
std::list<CTransactionRef> plTxnReplaced;
288286
for (const auto& tx : txs) {
289-
BOOST_REQUIRE(AcceptToMemoryPool(
290-
*m_node.mempool,
291-
state,
292-
tx,
293-
&plTxnReplaced,
294-
/* bypass_limits */ false));
287+
const MempoolAcceptResult result = AcceptToMemoryPool(*m_node.mempool, tx, false /* bypass_limits */);
288+
BOOST_REQUIRE(result.m_result_type == MempoolAcceptResult::ResultType::VALID);
295289
}
296290
}
297291

0 commit comments

Comments
 (0)