diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -388,7 +388,8 @@ // evaluates package limits, etc. As this function can be invoked for "free" // by a peer, only tests that are fast should be done here (to avoid CPU // DoS). - bool PreChecks(ATMPArgs &args, Workspace &ws) + bool PreChecks(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 @@ -422,7 +423,8 @@ size_t m_limit_descendant_size; }; -bool MemPoolAccept::PreChecks(ATMPArgs &args, Workspace &ws) { +bool MemPoolAccept::PreChecks(ATMPArgs &args, Workspace &ws, + PrecomputedTransactionData &txdata) { const CTransactionRef &ptx = ws.m_ptx; const CTransaction &tx = *ws.m_ptx; const TxId &txid = ws.m_ptx->GetId(); @@ -584,7 +586,7 @@ // Validate input scripts against standard script flags. const uint32_t scriptVerifyFlags = ws.m_next_block_script_verify_flags | STANDARD_SCRIPT_VERIFY_FLAGS; - PrecomputedTransactionData txdata(tx); + txdata = PrecomputedTransactionData{tx}; if (!CheckInputScripts(tx, state, m_view, scriptVerifyFlags, true, false, txdata, ws.m_sig_checks_standard)) { // State filled in by CheckInputScripts @@ -700,15 +702,14 @@ args.m_config.GetChainParams().GetConsensus(), m_active_chainstate.m_chain.Tip())); - if (!PreChecks(args, ws)) { - return MempoolAcceptResult::Failure(ws.m_state); - } - // Only compute the precomputed transaction data if we need to verify // scripts (ie, other policy checks pass). We perform the inexpensive // checks first and avoid hashing and signature verification unless those // checks pass, to mitigate CPU exhaustion denial-of-service attacks. - PrecomputedTransactionData txdata(*ptx); + PrecomputedTransactionData txdata; + if (!PreChecks(args, ws, txdata)) { + return MempoolAcceptResult::Failure(ws.m_state); + } if (!ConsensusScriptChecks(args, ws, txdata)) { return MempoolAcceptResult::Failure(ws.m_state); @@ -757,7 +758,8 @@ // Do all PreChecks first and fail fast to avoid running expensive script // checks when unnecessary. for (Workspace &ws : workspaces) { - if (!PreChecks(args, ws)) { + PrecomputedTransactionData txdata; + if (!PreChecks(args, ws, txdata)) { package_state.Invalid(PackageValidationResult::PCKG_TX, "transaction failed"); // Exit early to avoid doing pointless work. Update the failed tx