[refactor] const ATMPArgs and non-const Workspace

ATMPArgs should contain const arguments for validation.
The Workspace should contain state that may change
throughout validation.
This commit is contained in:
gzhao408 2021-01-19 09:32:20 -08:00
parent f82baf0762
commit 174cb5330a

View File

@ -461,9 +461,7 @@ public:
// around easier. // around easier.
struct ATMPArgs { struct ATMPArgs {
const CChainParams& m_chainparams; const CChainParams& m_chainparams;
TxValidationState &m_state;
const int64_t m_accept_time; const int64_t m_accept_time;
std::list<CTransactionRef> m_replaced_transactions;
const bool m_bypass_limits; const bool m_bypass_limits;
/* /*
* Return any outpoints which were not previously present in the coins * Return any outpoints which were not previously present in the coins
@ -474,7 +472,6 @@ public:
*/ */
std::vector<COutPoint>& m_coins_to_uncache; std::vector<COutPoint>& m_coins_to_uncache;
const bool m_test_accept; const bool m_test_accept;
CAmount m_fee_out;
}; };
// Single transaction acceptance // Single transaction acceptance
@ -489,14 +486,17 @@ private:
CTxMemPool::setEntries m_all_conflicting; CTxMemPool::setEntries m_all_conflicting;
CTxMemPool::setEntries m_ancestors; CTxMemPool::setEntries m_ancestors;
std::unique_ptr<CTxMemPoolEntry> m_entry; std::unique_ptr<CTxMemPoolEntry> m_entry;
std::list<CTransactionRef> m_replaced_transactions;
bool m_replacement_transaction; bool m_replacement_transaction;
CAmount m_fee_out;
CAmount m_modified_fees; CAmount m_modified_fees;
CAmount m_conflicting_fees; CAmount m_conflicting_fees;
size_t m_conflicting_size; size_t m_conflicting_size;
const CTransactionRef& m_ptx; const CTransactionRef& m_ptx;
const uint256& m_hash; const uint256& m_hash;
TxValidationState m_state;
}; };
// Run the policy checks on a given transaction, excluding any script checks. // Run the policy checks on a given transaction, excluding any script checks.
@ -507,18 +507,18 @@ private:
// Run the script checks using our policy flags. As this can be slow, we should // Run the script checks using our policy flags. As this can be slow, we should
// only invoke this on transactions that have otherwise passed policy checks. // only invoke this on transactions that have otherwise passed policy checks.
bool PolicyScriptChecks(ATMPArgs& args, const Workspace& ws, PrecomputedTransactionData& txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs); bool PolicyScriptChecks(const ATMPArgs& args, Workspace& ws, PrecomputedTransactionData& txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
// Re-run the script checks, using consensus flags, and try to cache the // Re-run the script checks, using consensus flags, and try to cache the
// result in the scriptcache. This should be done after // result in the scriptcache. This should be done after
// PolicyScriptChecks(). This requires that all inputs either be in our // PolicyScriptChecks(). This requires that all inputs either be in our
// utxo set or in the mempool. // utxo set or in the mempool.
bool ConsensusScriptChecks(ATMPArgs& args, const Workspace& ws, PrecomputedTransactionData &txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs); bool ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws, PrecomputedTransactionData &txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
// Try to add the transaction to the mempool, removing any conflicts first. // Try to add the transaction to the mempool, removing any conflicts first.
// Returns true if the transaction is in the mempool after any size // Returns true if the transaction is in the mempool after any size
// limiting is performed, false otherwise. // limiting is performed, false otherwise.
bool Finalize(ATMPArgs& args, Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs); bool Finalize(const ATMPArgs& args, Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
// Compare a package's feerate against minimum allowed. // Compare a package's feerate against minimum allowed.
bool CheckFeeRate(size_t package_size, CAmount package_fee, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs) bool CheckFeeRate(size_t package_size, CAmount package_fee, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs)
@ -556,12 +556,12 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
const uint256& hash = ws.m_hash; const uint256& hash = ws.m_hash;
// Copy/alias what we need out of args // Copy/alias what we need out of args
TxValidationState &state = args.m_state;
const int64_t nAcceptTime = args.m_accept_time; const int64_t nAcceptTime = args.m_accept_time;
const bool bypass_limits = args.m_bypass_limits; const bool bypass_limits = args.m_bypass_limits;
std::vector<COutPoint>& coins_to_uncache = args.m_coins_to_uncache; std::vector<COutPoint>& coins_to_uncache = args.m_coins_to_uncache;
// Alias what we need out of ws // Alias what we need out of ws
TxValidationState &state = ws.m_state;
std::set<uint256>& setConflicts = ws.m_conflicts; std::set<uint256>& setConflicts = ws.m_conflicts;
CTxMemPool::setEntries& allConflicting = ws.m_all_conflicting; CTxMemPool::setEntries& allConflicting = ws.m_all_conflicting;
CTxMemPool::setEntries& setAncestors = ws.m_ancestors; CTxMemPool::setEntries& setAncestors = ws.m_ancestors;
@ -681,13 +681,10 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
if (!CheckSequenceLocks(m_pool, tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp)) if (!CheckSequenceLocks(m_pool, tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-BIP68-final"); return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-BIP68-final");
CAmount nFees = 0; if (!Consensus::CheckTxInputs(tx, state, m_view, g_chainman.m_blockman.GetSpendHeight(m_view), ws.m_fee_out)) {
if (!Consensus::CheckTxInputs(tx, state, m_view, g_chainman.m_blockman.GetSpendHeight(m_view), nFees)) {
return false; // state filled in by CheckTxInputs return false; // state filled in by CheckTxInputs
} }
args.m_fee_out = nFees;
// Check for non-standard pay-to-script-hash in inputs // Check for non-standard pay-to-script-hash in inputs
const auto& params = args.m_chainparams.GetConsensus(); const auto& params = args.m_chainparams.GetConsensus();
auto taproot_state = VersionBitsState(::ChainActive().Tip(), params, Consensus::DEPLOYMENT_TAPROOT, versionbitscache); auto taproot_state = VersionBitsState(::ChainActive().Tip(), params, Consensus::DEPLOYMENT_TAPROOT, versionbitscache);
@ -702,7 +699,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
int64_t nSigOpsCost = GetTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS); int64_t nSigOpsCost = GetTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS);
// nModifiedFees includes any fee deltas from PrioritiseTransaction // nModifiedFees includes any fee deltas from PrioritiseTransaction
nModifiedFees = nFees; nModifiedFees = ws.m_fee_out;
m_pool.ApplyDelta(hash, nModifiedFees); m_pool.ApplyDelta(hash, nModifiedFees);
// Keep track of transactions that spend a coinbase, which we re-scan // Keep track of transactions that spend a coinbase, which we re-scan
@ -716,7 +713,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
} }
} }
entry.reset(new CTxMemPoolEntry(ptx, nFees, nAcceptTime, ::ChainActive().Height(), entry.reset(new CTxMemPoolEntry(ptx, ws.m_fee_out, nAcceptTime, ::ChainActive().Height(),
fSpendsCoinbase, nSigOpsCost, lp)); fSpendsCoinbase, nSigOpsCost, lp));
unsigned int nSize = entry->GetTxSize(); unsigned int nSize = entry->GetTxSize();
@ -920,11 +917,10 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
return true; return true;
} }
bool MemPoolAccept::PolicyScriptChecks(ATMPArgs& args, const Workspace& ws, PrecomputedTransactionData& txdata) bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws, PrecomputedTransactionData& txdata)
{ {
const CTransaction& tx = *ws.m_ptx; const CTransaction& tx = *ws.m_ptx;
TxValidationState &state = ws.m_state;
TxValidationState &state = args.m_state;
constexpr unsigned int scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS; constexpr unsigned int scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS;
@ -947,12 +943,11 @@ bool MemPoolAccept::PolicyScriptChecks(ATMPArgs& args, const Workspace& ws, Prec
return true; return true;
} }
bool MemPoolAccept::ConsensusScriptChecks(ATMPArgs& args, const Workspace& ws, PrecomputedTransactionData& txdata) bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws, PrecomputedTransactionData& txdata)
{ {
const CTransaction& tx = *ws.m_ptx; const CTransaction& tx = *ws.m_ptx;
const uint256& hash = ws.m_hash; const uint256& hash = ws.m_hash;
TxValidationState &state = ws.m_state;
TxValidationState &state = args.m_state;
const CChainParams& chainparams = args.m_chainparams; const CChainParams& chainparams = args.m_chainparams;
// Check again against the current block tip's script verification // Check again against the current block tip's script verification
@ -979,11 +974,11 @@ bool MemPoolAccept::ConsensusScriptChecks(ATMPArgs& args, const Workspace& ws, P
return true; return true;
} }
bool MemPoolAccept::Finalize(ATMPArgs& args, Workspace& ws) bool MemPoolAccept::Finalize(const ATMPArgs& args, Workspace& ws)
{ {
const CTransaction& tx = *ws.m_ptx; const CTransaction& tx = *ws.m_ptx;
const uint256& hash = ws.m_hash; const uint256& hash = ws.m_hash;
TxValidationState &state = args.m_state; TxValidationState &state = ws.m_state;
const bool bypass_limits = args.m_bypass_limits; const bool bypass_limits = args.m_bypass_limits;
CTxMemPool::setEntries& allConflicting = ws.m_all_conflicting; CTxMemPool::setEntries& allConflicting = ws.m_all_conflicting;
@ -1002,7 +997,7 @@ bool MemPoolAccept::Finalize(ATMPArgs& args, Workspace& ws)
hash.ToString(), hash.ToString(),
FormatMoney(nModifiedFees - nConflictingFees), FormatMoney(nModifiedFees - nConflictingFees),
(int)entry->GetTxSize() - (int)nConflictingSize); (int)entry->GetTxSize() - (int)nConflictingSize);
args.m_replaced_transactions.push_back(it->GetSharedTx()); ws.m_replaced_transactions.push_back(it->GetSharedTx());
} }
m_pool.RemoveStaged(allConflicting, false, MemPoolRemovalReason::REPLACED); m_pool.RemoveStaged(allConflicting, false, MemPoolRemovalReason::REPLACED);
@ -1032,7 +1027,7 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
Workspace workspace(ptx); Workspace workspace(ptx);
if (!PreChecks(args, workspace)) return MempoolAcceptResult(args.m_state); if (!PreChecks(args, workspace)) return MempoolAcceptResult(workspace.m_state);
// Only compute the precomputed transaction data if we need to verify // Only compute the precomputed transaction data if we need to verify
// scripts (ie, other policy checks pass). We perform the inexpensive // scripts (ie, other policy checks pass). We perform the inexpensive
@ -1040,20 +1035,20 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
// checks pass, to mitigate CPU exhaustion denial-of-service attacks. // checks pass, to mitigate CPU exhaustion denial-of-service attacks.
PrecomputedTransactionData txdata; PrecomputedTransactionData txdata;
if (!PolicyScriptChecks(args, workspace, txdata)) return MempoolAcceptResult(args.m_state); if (!PolicyScriptChecks(args, workspace, txdata)) return MempoolAcceptResult(workspace.m_state);
if (!ConsensusScriptChecks(args, workspace, txdata)) return MempoolAcceptResult(args.m_state); if (!ConsensusScriptChecks(args, workspace, txdata)) return MempoolAcceptResult(workspace.m_state);
// Tx was accepted, but not added // Tx was accepted, but not added
if (args.m_test_accept) { if (args.m_test_accept) {
return MempoolAcceptResult(std::move(args.m_replaced_transactions), args.m_fee_out); return MempoolAcceptResult(std::move(workspace.m_replaced_transactions), workspace.m_fee_out);
} }
if (!Finalize(args, workspace)) return MempoolAcceptResult(args.m_state); if (!Finalize(args, workspace)) return MempoolAcceptResult(workspace.m_state);
GetMainSignals().TransactionAddedToMempool(ptx, m_pool.GetAndIncrementSequence()); GetMainSignals().TransactionAddedToMempool(ptx, m_pool.GetAndIncrementSequence());
return MempoolAcceptResult(std::move(args.m_replaced_transactions), args.m_fee_out); return MempoolAcceptResult(std::move(workspace.m_replaced_transactions), workspace.m_fee_out);
} }
} // anon namespace } // anon namespace
@ -1064,9 +1059,8 @@ static MempoolAcceptResult AcceptToMemoryPoolWithTime(const CChainParams& chainp
bool bypass_limits, bool test_accept) bool bypass_limits, bool test_accept)
EXCLUSIVE_LOCKS_REQUIRED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{ {
TxValidationState state;
std::vector<COutPoint> coins_to_uncache; std::vector<COutPoint> coins_to_uncache;
MemPoolAccept::ATMPArgs args { chainparams, state, nAcceptTime, {}, bypass_limits, coins_to_uncache, test_accept, {} }; MemPoolAccept::ATMPArgs args { chainparams, nAcceptTime, bypass_limits, coins_to_uncache, test_accept };
const MempoolAcceptResult result = MemPoolAccept(pool).AcceptSingleTransaction(tx, args); const MempoolAcceptResult result = MemPoolAccept(pool).AcceptSingleTransaction(tx, args);
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) { if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {