@@ -513,6 +513,9 @@ class MemPoolAccept
513513 const CTransactionRef& m_ptx;
514514 const uint256& m_hash;
515515 TxValidationState m_state;
516+ /* * A temporary cache containing serialized transaction data for signature verification.
517+ * Reused across PolicyScriptChecks and ConsensusScriptChecks. */
518+ PrecomputedTransactionData m_precomputed_txdata;
516519 };
517520
518521 // Run the policy checks on a given transaction, excluding any script checks.
@@ -523,13 +526,13 @@ class MemPoolAccept
523526
524527 // Run the script checks using our policy flags. As this can be slow, we should
525528 // only invoke this on transactions that have otherwise passed policy checks.
526- bool PolicyScriptChecks (const ATMPArgs& args, Workspace& ws, PrecomputedTransactionData& txdata ) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
529+ bool PolicyScriptChecks (const ATMPArgs& args, Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
527530
528531 // Re-run the script checks, using consensus flags, and try to cache the
529532 // result in the scriptcache. This should be done after
530533 // PolicyScriptChecks(). This requires that all inputs either be in our
531534 // utxo set or in the mempool.
532- bool ConsensusScriptChecks (const ATMPArgs& args, Workspace& ws, PrecomputedTransactionData &txdata ) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
535+ bool ConsensusScriptChecks (const ATMPArgs& args, Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
533536
534537 // Try to add the transaction to the mempool, removing any conflicts first.
535538 // Returns true if the transaction is in the mempool after any size
@@ -842,7 +845,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
842845 return true ;
843846}
844847
845- bool MemPoolAccept::PolicyScriptChecks (const ATMPArgs& args, Workspace& ws, PrecomputedTransactionData& txdata )
848+ bool MemPoolAccept::PolicyScriptChecks (const ATMPArgs& args, Workspace& ws)
846849{
847850 const CTransaction& tx = *ws.m_ptx ;
848851 TxValidationState& state = ws.m_state ;
@@ -851,13 +854,13 @@ bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws, Prec
851854
852855 // Check input scripts and signatures.
853856 // This is done last to help prevent CPU exhaustion denial-of-service attacks.
854- if (!CheckInputScripts (tx, state, m_view, scriptVerifyFlags, true , false , txdata )) {
857+ if (!CheckInputScripts (tx, state, m_view, scriptVerifyFlags, true , false , ws. m_precomputed_txdata )) {
855858 // SCRIPT_VERIFY_CLEANSTACK requires SCRIPT_VERIFY_WITNESS, so we
856859 // need to turn both off, and compare against just turning off CLEANSTACK
857860 // to see if the failure is specifically due to witness validation.
858861 TxValidationState state_dummy; // Want reported failures to be from first CheckInputScripts
859- if (!tx.HasWitness () && CheckInputScripts (tx, state_dummy, m_view, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true , false , txdata ) &&
860- !CheckInputScripts (tx, state_dummy, m_view, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true , false , txdata )) {
862+ if (!tx.HasWitness () && CheckInputScripts (tx, state_dummy, m_view, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true , false , ws. m_precomputed_txdata ) &&
863+ !CheckInputScripts (tx, state_dummy, m_view, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true , false , ws. m_precomputed_txdata )) {
861864 // Only the witness is missing, so the transaction itself may be fine.
862865 state.Invalid (TxValidationResult::TX_WITNESS_STRIPPED,
863866 state.GetRejectReason (), state.GetDebugMessage ());
@@ -868,7 +871,7 @@ bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws, Prec
868871 return true ;
869872}
870873
871- bool MemPoolAccept::ConsensusScriptChecks (const ATMPArgs& args, Workspace& ws, PrecomputedTransactionData& txdata )
874+ bool MemPoolAccept::ConsensusScriptChecks (const ATMPArgs& args, Workspace& ws)
872875{
873876 const CTransaction& tx = *ws.m_ptx ;
874877 const uint256& hash = ws.m_hash ;
@@ -891,7 +894,8 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws, P
891894 // invalid blocks (using TestBlockValidity), however allowing such
892895 // transactions into the mempool can be exploited as a DoS attack.
893896 unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags (m_active_chainstate.m_chain .Tip (), chainparams.GetConsensus ());
894- if (!CheckInputsFromMempoolAndCache (tx, state, m_view, m_pool, currentBlockScriptVerifyFlags, txdata, m_active_chainstate.CoinsTip ())) {
897+ if (!CheckInputsFromMempoolAndCache (tx, state, m_view, m_pool, currentBlockScriptVerifyFlags,
898+ ws.m_precomputed_txdata , m_active_chainstate.CoinsTip ())) {
895899 return error (" %s: BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s" ,
896900 __func__, hash.ToString (), state.ToString ());
897901 }
@@ -952,15 +956,11 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
952956
953957 if (!PreChecks (args, ws)) return MempoolAcceptResult::Failure (ws.m_state );
954958
955- // Only compute the precomputed transaction data if we need to verify
956- // scripts (ie, other policy checks pass). We perform the inexpensive
957- // checks first and avoid hashing and signature verification unless those
958- // checks pass, to mitigate CPU exhaustion denial-of-service attacks.
959- PrecomputedTransactionData txdata;
959+ // Perform the inexpensive checks first and avoid hashing and signature verification unless
960+ // those checks pass, to mitigate CPU exhaustion denial-of-service attacks.
961+ if (!PolicyScriptChecks (args, ws)) return MempoolAcceptResult::Failure (ws.m_state );
960962
961- if (!PolicyScriptChecks (args, ws, txdata)) return MempoolAcceptResult::Failure (ws.m_state );
962-
963- if (!ConsensusScriptChecks (args, ws, txdata)) return MempoolAcceptResult::Failure (ws.m_state );
963+ if (!ConsensusScriptChecks (args, ws)) return MempoolAcceptResult::Failure (ws.m_state );
964964
965965 // Tx was accepted, but not added
966966 if (args.m_test_accept ) {
@@ -1020,8 +1020,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
10201020 }
10211021
10221022 for (Workspace& ws : workspaces) {
1023- PrecomputedTransactionData txdata;
1024- if (!PolicyScriptChecks (args, ws, txdata)) {
1023+ if (!PolicyScriptChecks (args, ws)) {
10251024 // Exit early to avoid doing pointless work. Update the failed tx result; the rest are unfinished.
10261025 package_state.Invalid (PackageValidationResult::PCKG_TX, " transaction failed" );
10271026 results.emplace (ws.m_ptx ->GetWitnessHash (), MempoolAcceptResult::Failure (ws.m_state ));
0 commit comments