@@ -380,10 +380,8 @@ static void UpdateMempoolForReorg(CTxMemPool& mempool, DisconnectedBlockTransact
380
380
auto it = disconnectpool.queuedTx .get <insertion_order>().rbegin ();
381
381
while (it != disconnectpool.queuedTx .get <insertion_order>().rend ()) {
382
382
// ignore validation errors in resurrected transactions
383
- TxValidationState stateDummy;
384
383
if (!fAddToMempool || (*it)->IsCoinBase () ||
385
- !AcceptToMemoryPool (mempool, stateDummy, *it,
386
- nullptr /* plTxnReplaced */ , true /* bypass_limits */ )) {
384
+ AcceptToMemoryPool (mempool, *it, true /* bypass_limits */ ).m_result_type != MempoolAcceptResult::ResultType::VALID) {
387
385
// If the transaction doesn't make it in to the mempool, remove any
388
386
// transactions that depend on it (which would now be orphans).
389
387
mempool.removeRecursive (**it, MemPoolRemovalReason::REORG);
@@ -465,7 +463,7 @@ class MemPoolAccept
465
463
const CChainParams& m_chainparams;
466
464
TxValidationState &m_state;
467
465
const int64_t m_accept_time;
468
- std::list<CTransactionRef>* m_replaced_transactions;
466
+ std::list<CTransactionRef> m_replaced_transactions;
469
467
const bool m_bypass_limits;
470
468
/*
471
469
* Return any outpoints which were not previously present in the coins
@@ -476,11 +474,11 @@ class MemPoolAccept
476
474
*/
477
475
std::vector<COutPoint>& m_coins_to_uncache;
478
476
const bool m_test_accept;
479
- CAmount* m_fee_out;
477
+ CAmount m_fee_out;
480
478
};
481
479
482
480
// Single transaction acceptance
483
- bool AcceptSingleTransaction (const CTransactionRef& ptx, ATMPArgs& args) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
481
+ MempoolAcceptResult AcceptSingleTransaction (const CTransactionRef& ptx, ATMPArgs& args) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
484
482
485
483
private:
486
484
// All the intermediate state that gets passed between the various levels
@@ -688,10 +686,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
688
686
return false ; // state filled in by CheckTxInputs
689
687
}
690
688
691
- // If fee_out is passed, return the fee to the caller
692
- if (args.m_fee_out ) {
693
- *args.m_fee_out = nFees;
694
- }
689
+ args.m_fee_out = nFees;
695
690
696
691
// Check for non-standard pay-to-script-hash in inputs
697
692
const auto & params = args.m_chainparams .GetConsensus ();
@@ -1007,8 +1002,7 @@ bool MemPoolAccept::Finalize(ATMPArgs& args, Workspace& ws)
1007
1002
hash.ToString (),
1008
1003
FormatMoney (nModifiedFees - nConflictingFees),
1009
1004
(int )entry->GetTxSize () - (int )nConflictingSize);
1010
- if (args.m_replaced_transactions )
1011
- args.m_replaced_transactions ->push_back (it->GetSharedTx ());
1005
+ args.m_replaced_transactions .push_back (it->GetSharedTx ());
1012
1006
}
1013
1007
m_pool.RemoveStaged (allConflicting, false , MemPoolRemovalReason::REPLACED);
1014
1008
@@ -1031,46 +1025,51 @@ bool MemPoolAccept::Finalize(ATMPArgs& args, Workspace& ws)
1031
1025
return true ;
1032
1026
}
1033
1027
1034
- bool MemPoolAccept::AcceptSingleTransaction (const CTransactionRef& ptx, ATMPArgs& args)
1028
+ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction (const CTransactionRef& ptx, ATMPArgs& args)
1035
1029
{
1036
1030
AssertLockHeld (cs_main);
1037
1031
LOCK (m_pool.cs ); // mempool "read lock" (held through GetMainSignals().TransactionAddedToMempool())
1038
1032
1039
1033
Workspace workspace (ptx);
1040
1034
1041
- if (!PreChecks (args, workspace)) return false ;
1035
+ if (!PreChecks (args, workspace)) return MempoolAcceptResult (args. m_state ) ;
1042
1036
1043
1037
// Only compute the precomputed transaction data if we need to verify
1044
1038
// scripts (ie, other policy checks pass). We perform the inexpensive
1045
1039
// checks first and avoid hashing and signature verification unless those
1046
1040
// checks pass, to mitigate CPU exhaustion denial-of-service attacks.
1047
1041
PrecomputedTransactionData txdata;
1048
1042
1049
- if (!PolicyScriptChecks (args, workspace, txdata)) return false ;
1043
+ if (!PolicyScriptChecks (args, workspace, txdata)) return MempoolAcceptResult (args. m_state ) ;
1050
1044
1051
- if (!ConsensusScriptChecks (args, workspace, txdata)) return false ;
1045
+ if (!ConsensusScriptChecks (args, workspace, txdata)) return MempoolAcceptResult (args. m_state ) ;
1052
1046
1053
1047
// Tx was accepted, but not added
1054
- if (args.m_test_accept ) return true ;
1048
+ if (args.m_test_accept ) {
1049
+ return MempoolAcceptResult (std::move (args.m_replaced_transactions ), args.m_fee_out );
1050
+ }
1055
1051
1056
- if (!Finalize (args, workspace)) return false ;
1052
+ if (!Finalize (args, workspace)) return MempoolAcceptResult (args. m_state ) ;
1057
1053
1058
1054
GetMainSignals ().TransactionAddedToMempool (ptx, m_pool.GetAndIncrementSequence ());
1059
1055
1060
- return true ;
1056
+ return MempoolAcceptResult ( std::move (args. m_replaced_transactions ), args. m_fee_out ) ;
1061
1057
}
1062
1058
1063
1059
} // anon namespace
1064
1060
1065
1061
/* * (try to) add transaction to memory pool with a specified acceptance time **/
1066
- static bool AcceptToMemoryPoolWithTime (const CChainParams& chainparams, CTxMemPool& pool, TxValidationState &state, const CTransactionRef &tx,
1067
- int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced,
1068
- bool bypass_limits, bool test_accept, CAmount* fee_out=nullptr ) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
1062
+ static MempoolAcceptResult AcceptToMemoryPoolWithTime (const CChainParams& chainparams, CTxMemPool& pool,
1063
+ const CTransactionRef &tx, int64_t nAcceptTime,
1064
+ bool bypass_limits, bool test_accept)
1065
+ EXCLUSIVE_LOCKS_REQUIRED(cs_main)
1069
1066
{
1067
+ TxValidationState state;
1070
1068
std::vector<COutPoint> coins_to_uncache;
1071
- MemPoolAccept::ATMPArgs args { chainparams, state, nAcceptTime, plTxnReplaced, bypass_limits, coins_to_uncache, test_accept, fee_out };
1072
- bool res = MemPoolAccept (pool).AcceptSingleTransaction (tx, args);
1073
- if (!res) {
1069
+ MemPoolAccept::ATMPArgs args { chainparams, state, nAcceptTime, {}, bypass_limits, coins_to_uncache, test_accept, {} };
1070
+
1071
+ const MempoolAcceptResult result = MemPoolAccept (pool).AcceptSingleTransaction (tx, args);
1072
+ if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
1074
1073
// Remove coins that were not present in the coins cache before calling ATMPW;
1075
1074
// this is to prevent memory DoS in case we receive a large number of
1076
1075
// invalid transactions that attempt to overrun the in-memory coins cache
@@ -1082,15 +1081,13 @@ static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPo
1082
1081
// After we've (potentially) uncached entries, ensure our coins cache is still within its size limits
1083
1082
BlockValidationState state_dummy;
1084
1083
::ChainstateActive ().FlushStateToDisk(chainparams, state_dummy, FlushStateMode::PERIODIC);
1085
- return res ;
1084
+ return result ;
1086
1085
}
1087
1086
1088
- bool AcceptToMemoryPool (CTxMemPool& pool, TxValidationState &state, const CTransactionRef &tx,
1089
- std::list<CTransactionRef>* plTxnReplaced,
1090
- bool bypass_limits, bool test_accept, CAmount* fee_out)
1087
+ MempoolAcceptResult AcceptToMemoryPool (CTxMemPool& pool, const CTransactionRef &tx, bool bypass_limits, bool test_accept)
1091
1088
{
1092
1089
const CChainParams& chainparams = Params ();
1093
- return AcceptToMemoryPoolWithTime (chainparams, pool, state, tx, GetTime (), plTxnReplaced, bypass_limits, test_accept, fee_out );
1090
+ return AcceptToMemoryPoolWithTime (chainparams, pool, tx, GetTime (), bypass_limits, test_accept);
1094
1091
}
1095
1092
1096
1093
CTransactionRef GetTransaction (const CBlockIndex* const block_index, const CTxMemPool* const mempool, const uint256& hash, const Consensus::Params& consensusParams, uint256& hashBlock)
@@ -5029,13 +5026,10 @@ bool LoadMempool(CTxMemPool& pool)
5029
5026
if (amountdelta) {
5030
5027
pool.PrioritiseTransaction (tx->GetHash (), amountdelta);
5031
5028
}
5032
- TxValidationState state;
5033
5029
if (nTime > nNow - nExpiryTimeout) {
5034
5030
LOCK (cs_main);
5035
- AcceptToMemoryPoolWithTime (chainparams, pool, state, tx, nTime,
5036
- nullptr /* plTxnReplaced */ , false /* bypass_limits */ ,
5037
- false /* test_accept */ );
5038
- if (state.IsValid ()) {
5031
+ if (AcceptToMemoryPoolWithTime (chainparams, pool, tx, nTime, false /* bypass_limits */ ,
5032
+ false /* test_accept */ ).m_result_type == MempoolAcceptResult::ResultType::VALID) {
5039
5033
++count;
5040
5034
} else {
5041
5035
// mempool may contain the transaction already, e.g. from
0 commit comments