Skip to content

Commit cbb3598

Browse files
committed
[validation/refactor] store precomputed txdata in workspace
We want to be able to re-use the precomputed transaction data between PolicyScriptChecks and ConsensusScriptChecks in AcceptMultipleTransactions.
1 parent 0a79eab commit cbb3598

File tree

1 file changed

+17
-18
lines changed

1 file changed

+17
-18
lines changed

src/validation.cpp

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)