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

refactor: return MempoolAcceptResult from ATMP #21062

Merged
merged 4 commits into from
Feb 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/bench/block_assemble.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,8 @@ static void AssembleBlock(benchmark::Bench& bench)
LOCK(::cs_main); // Required for ::AcceptToMemoryPool.

for (const auto& txr : txs) {
TxValidationState state;
bool ret{::AcceptToMemoryPool(*test_setup.m_node.mempool, state, txr, nullptr /* plTxnReplaced */, false /* bypass_limits */)};
assert(ret);
const MempoolAcceptResult res = ::AcceptToMemoryPool(*test_setup.m_node.mempool, txr, false /* bypass_limits */);
assert(res.m_result_type == MempoolAcceptResult::ResultType::VALID);
}
}

Expand Down
16 changes: 8 additions & 8 deletions src/net_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2178,10 +2178,10 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
if (orphan_it == mapOrphanTransactions.end()) continue;

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

if (AcceptToMemoryPool(m_mempool, state, porphanTx, &removed_txn, false /* bypass_limits */)) {
if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString());
RelayTransaction(orphanHash, porphanTx->GetWitnessHash(), m_connman);
for (unsigned int i = 0; i < porphanTx->vout.size(); i++) {
Expand All @@ -2193,7 +2193,7 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
}
}
EraseOrphanTx(orphanHash);
for (const CTransactionRef& removedTx : removed_txn) {
for (const CTransactionRef& removedTx : result.m_replaced_transactions.value()) {
AddToCompactExtraTransactions(removedTx);
}
break;
Expand Down Expand Up @@ -3197,10 +3197,10 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
return;
}

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

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

for (const CTransactionRef& removedTx : lRemovedTxn) {
for (const CTransactionRef& removedTx : result.m_replaced_transactions.value()) {
AddToCompactExtraTransactions(removedTx);
}

Expand Down
18 changes: 9 additions & 9 deletions src/node/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,22 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
}
if (!node.mempool->exists(hashTx)) {
// Transaction is not already in the mempool.
TxValidationState state;
if (max_tx_fee > 0) {
// First, call ATMP with test_accept and check the fee. If ATMP
// fails here, return error immediately.
CAmount fee{0};
if (!AcceptToMemoryPool(*node.mempool, state, tx,
nullptr /* plTxnReplaced */, false /* bypass_limits */, /* test_accept */ true, &fee)) {
return HandleATMPError(state, err_string);
} else if (fee > max_tx_fee) {
const MempoolAcceptResult result = AcceptToMemoryPool(*node.mempool, tx, false /* bypass_limits */,
true /* test_accept */);
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
return HandleATMPError(result.m_state, err_string);
} else if (result.m_base_fees.value() > max_tx_fee) {
return TransactionError::MAX_FEE_EXCEEDED;
}
}
// Try to submit the transaction to the mempool.
if (!AcceptToMemoryPool(*node.mempool, state, tx,
nullptr /* plTxnReplaced */, false /* bypass_limits */)) {
return HandleATMPError(state, err_string);
const MempoolAcceptResult result = AcceptToMemoryPool(*node.mempool, tx, false /* bypass_limits */,
false /* test_accept */);
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
return HandleATMPError(result.m_state, err_string);
}

// Transaction was accepted to the mempool.
Expand Down
51 changes: 21 additions & 30 deletions src/rpc/rawtransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -946,44 +946,35 @@ static RPCHelpMan testmempoolaccept()
result_0.pushKV("txid", tx->GetHash().GetHex());
result_0.pushKV("wtxid", tx->GetWitnessHash().GetHex());

TxValidationState state;
bool test_accept_res;
CAmount fee{0};
{
LOCK(cs_main);
test_accept_res = AcceptToMemoryPool(mempool, state, std::move(tx),
nullptr /* plTxnReplaced */, false /* bypass_limits */, /* test_accept */ true, &fee);
}

// Check that fee does not exceed maximum fee
if (test_accept_res && max_raw_tx_fee && fee > max_raw_tx_fee) {
result_0.pushKV("allowed", false);
result_0.pushKV("reject-reason", "max-fee-exceeded");
result.push_back(std::move(result_0));
return result;
}
result_0.pushKV("allowed", test_accept_res);
const MempoolAcceptResult accept_result = WITH_LOCK(cs_main, return AcceptToMemoryPool(mempool, std::move(tx),
false /* bypass_limits */, /* test_accept */ true));

// Only return the fee and vsize if the transaction would pass ATMP.
// These can be used to calculate the feerate.
if (test_accept_res) {
result_0.pushKV("vsize", virtual_size);
UniValue fees(UniValue::VOBJ);
fees.pushKV("base", ValueFromAmount(fee));
result_0.pushKV("fees", fees);
if (accept_result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
const CAmount fee = accept_result.m_base_fees.value();
// Check that fee does not exceed maximum fee
if (max_raw_tx_fee && fee > max_raw_tx_fee) {
result_0.pushKV("allowed", false);
result_0.pushKV("reject-reason", "max-fee-exceeded");
glozow marked this conversation as resolved.
Show resolved Hide resolved
} else {
result_0.pushKV("allowed", true);
result_0.pushKV("vsize", virtual_size);
UniValue fees(UniValue::VOBJ);
fees.pushKV("base", ValueFromAmount(fee));
result_0.pushKV("fees", fees);
}
result.push_back(std::move(result_0));
jnewbery marked this conversation as resolved.
Show resolved Hide resolved
} else {
if (state.IsInvalid()) {
if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
result_0.pushKV("reject-reason", "missing-inputs");
} else {
result_0.pushKV("reject-reason", strprintf("%s", state.GetRejectReason()));
}
result_0.pushKV("allowed", false);
const TxValidationState state = accept_result.m_state;
if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
result_0.pushKV("reject-reason", "missing-inputs");
} else {
result_0.pushKV("reject-reason", state.GetRejectReason());
}
result.push_back(std::move(result_0));
}

result.push_back(std::move(result_0));
return result;
},
};
Expand Down
16 changes: 6 additions & 10 deletions src/test/txvalidation_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,21 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)

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

TxValidationState state;

LOCK(cs_main);

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

BOOST_CHECK_EQUAL(
false,
AcceptToMemoryPool(*m_node.mempool, state, MakeTransactionRef(coinbaseTx),
nullptr /* plTxnReplaced */,
true /* bypass_limits */));
BOOST_CHECK(result.m_result_type == MempoolAcceptResult::ResultType::INVALID);

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

// Check that the validation state reflects the unsuccessful attempt.
BOOST_CHECK(state.IsInvalid());
BOOST_CHECK_EQUAL(state.GetRejectReason(), "coinbase");
BOOST_CHECK(state.GetResult() == TxValidationResult::TX_CONSENSUS);
BOOST_CHECK(result.m_state.IsInvalid());
BOOST_CHECK_EQUAL(result.m_state.GetRejectReason(), "coinbase");
BOOST_CHECK(result.m_state.GetResult() == TxValidationResult::TX_CONSENSUS);
}

BOOST_AUTO_TEST_SUITE_END()
6 changes: 3 additions & 3 deletions src/test/txvalidationcache_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
const auto ToMemPool = [this](const CMutableTransaction& tx) {
LOCK(cs_main);

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

// Create a double-spend of mature coinbase txn:
Expand Down
10 changes: 2 additions & 8 deletions src/test/validation_block_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,15 +283,9 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
// Add the txs to the tx pool
{
LOCK(cs_main);
TxValidationState state;
std::list<CTransactionRef> plTxnReplaced;
for (const auto& tx : txs) {
BOOST_REQUIRE(AcceptToMemoryPool(
*m_node.mempool,
state,
tx,
&plTxnReplaced,
/* bypass_limits */ false));
const MempoolAcceptResult result = AcceptToMemoryPool(*m_node.mempool, tx, false /* bypass_limits */);
BOOST_REQUIRE(result.m_result_type == MempoolAcceptResult::ResultType::VALID);
}
}

Expand Down
Loading