aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/script/interpreter.cpp10
-rw-r--r--src/script/interpreter.h4
-rw-r--r--src/validation.cpp19
3 files changed, 22 insertions, 11 deletions
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 2fa7e5e1ab..c322ecb1a0 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1294,10 +1294,12 @@ uint256 GetOutputsSHA256(const T& txTo)
} // namespace
template <class T>
-void PrecomputedTransactionData::Init(const T& txTo)
+void PrecomputedTransactionData::Init(const T& txTo, std::vector<CTxOut>&& spent_outputs)
{
assert(!m_ready);
+ m_spent_outputs = std::move(spent_outputs);
+
// Cache is calculated only for transactions with witness
if (txTo.HasWitness()) {
hashPrevouts = SHA256Uint256(GetPrevoutsSHA256(txTo));
@@ -1311,12 +1313,12 @@ void PrecomputedTransactionData::Init(const T& txTo)
template <class T>
PrecomputedTransactionData::PrecomputedTransactionData(const T& txTo)
{
- Init(txTo);
+ Init(txTo, {});
}
// explicit instantiation
-template void PrecomputedTransactionData::Init(const CTransaction& txTo);
-template void PrecomputedTransactionData::Init(const CMutableTransaction& txTo);
+template void PrecomputedTransactionData::Init(const CTransaction& txTo, std::vector<CTxOut>&& spent_outputs);
+template void PrecomputedTransactionData::Init(const CMutableTransaction& txTo, std::vector<CTxOut>&& spent_outputs);
template PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo);
template PrecomputedTransactionData::PrecomputedTransactionData(const CMutableTransaction& txTo);
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index 0ff4c4bc95..64cefc0d6c 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -15,6 +15,7 @@
class CPubKey;
class CScript;
class CTransaction;
+class CTxOut;
class uint256;
/** Signature hash types/flags */
@@ -122,11 +123,12 @@ struct PrecomputedTransactionData
{
uint256 hashPrevouts, hashSequence, hashOutputs;
bool m_ready = false;
+ std::vector<CTxOut> m_spent_outputs;
PrecomputedTransactionData() = default;
template <class T>
- void Init(const T& tx);
+ void Init(const T& tx, std::vector<CTxOut>&& spent_outputs);
template <class T>
explicit PrecomputedTransactionData(const T& tx);
diff --git a/src/validation.cpp b/src/validation.cpp
index e9c0607ced..2090d9477f 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -1539,13 +1539,20 @@ bool CheckInputScripts(const CTransaction& tx, TxValidationState &state, const C
}
if (!txdata.m_ready) {
- txdata.Init(tx);
+ std::vector<CTxOut> spent_outputs;
+ spent_outputs.reserve(tx.vin.size());
+
+ for (const auto& txin : tx.vin) {
+ const COutPoint& prevout = txin.prevout;
+ const Coin& coin = inputs.AccessCoin(prevout);
+ assert(!coin.IsSpent());
+ spent_outputs.emplace_back(coin.out);
+ }
+ txdata.Init(tx, std::move(spent_outputs));
}
+ assert(txdata.m_spent_outputs.size() == tx.vin.size());
for (unsigned int i = 0; i < tx.vin.size(); i++) {
- const COutPoint &prevout = tx.vin[i].prevout;
- const Coin& coin = inputs.AccessCoin(prevout);
- assert(!coin.IsSpent());
// We very carefully only pass in things to CScriptCheck which
// are clearly committed to by tx' witness hash. This provides
@@ -1554,7 +1561,7 @@ bool CheckInputScripts(const CTransaction& tx, TxValidationState &state, const C
// spent being checked as a part of CScriptCheck.
// Verify signature
- CScriptCheck check(coin.out, tx, i, flags, cacheSigStore, &txdata);
+ CScriptCheck check(txdata.m_spent_outputs[i], tx, i, flags, cacheSigStore, &txdata);
if (pvChecks) {
pvChecks->push_back(CScriptCheck());
check.swap(pvChecks->back());
@@ -1568,7 +1575,7 @@ bool CheckInputScripts(const CTransaction& tx, TxValidationState &state, const C
// splitting the network between upgraded and
// non-upgraded nodes by banning CONSENSUS-failing
// data providers.
- CScriptCheck check2(coin.out, tx, i,
+ CScriptCheck check2(txdata.m_spent_outputs[i], tx, i,
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheSigStore, &txdata);
if (check2())
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));