|
|
@ -1347,8 +1347,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa |
|
|
|
|
|
|
|
// Check against previous transactions
|
|
|
|
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
|
|
|
|
CachedHashes cachedHashes(tx); |
|
|
|
if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, cachedHashes, Params().GetConsensus())) |
|
|
|
PrecomputedTransactionData txdata(tx); |
|
|
|
if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus())) |
|
|
|
{ |
|
|
|
return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString()); |
|
|
|
} |
|
|
@ -1362,7 +1362,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa |
|
|
|
// There is a similar check in CreateNewBlock() to prevent creating
|
|
|
|
// invalid blocks, however allowing such transactions into the mempool
|
|
|
|
// can be exploited as a DoS attack.
|
|
|
|
if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, cachedHashes, Params().GetConsensus())) |
|
|
|
if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus())) |
|
|
|
{ |
|
|
|
return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s", hash.ToString()); |
|
|
|
} |
|
|
@ -1727,7 +1727,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) |
|
|
|
|
|
|
|
bool CScriptCheck::operator()() { |
|
|
|
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; |
|
|
|
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *cachedHashes), &error)) { |
|
|
|
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), &error)) { |
|
|
|
return ::error("CScriptCheck(): %s:%d VerifySignature failed: %s", ptxTo->GetHash().ToString(), nIn, ScriptErrorString(error)); |
|
|
|
} |
|
|
|
return true; |
|
|
@ -1810,7 +1810,7 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins |
|
|
|
} |
|
|
|
}// namespace Consensus
|
|
|
|
|
|
|
|
bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, CachedHashes& cachedHashes, const Consensus::Params& consensusParams, std::vector<CScriptCheck> *pvChecks) |
|
|
|
bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, const Consensus::Params& consensusParams, std::vector<CScriptCheck> *pvChecks) |
|
|
|
{ |
|
|
|
if (!tx.IsCoinBase()) |
|
|
|
{ |
|
|
@ -1835,7 +1835,7 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons |
|
|
|
assert(coins); |
|
|
|
|
|
|
|
// Verify signature
|
|
|
|
CScriptCheck check(*coins, tx, i, flags, cacheStore, &cachedHashes); |
|
|
|
CScriptCheck check(*coins, tx, i, flags, cacheStore, &txdata); |
|
|
|
if (pvChecks) { |
|
|
|
pvChecks->push_back(CScriptCheck()); |
|
|
|
check.swap(pvChecks->back()); |
|
|
@ -1848,7 +1848,7 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons |
|
|
|
// avoid splitting the network between upgraded and
|
|
|
|
// non-upgraded nodes.
|
|
|
|
CScriptCheck check2(*coins, tx, i, |
|
|
|
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, &cachedHashes); |
|
|
|
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, &txdata); |
|
|
|
if (check2()) |
|
|
|
return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError()))); |
|
|
|
} |
|
|
@ -2238,8 +2238,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin |
|
|
|
assert(tree.root() == old_tree_root); |
|
|
|
} |
|
|
|
|
|
|
|
std::vector<CachedHashes> cachedHashes; |
|
|
|
cachedHashes.reserve(block.vtx.size()); // Required so that pointers to individual CachedHashes don't get invalidated
|
|
|
|
std::vector<PrecomputedTransactionData> txdata; |
|
|
|
txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated
|
|
|
|
for (unsigned int i = 0; i < block.vtx.size(); i++) |
|
|
|
{ |
|
|
|
const CTransaction &tx = block.vtx[i]; |
|
|
@ -2270,14 +2270,14 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin |
|
|
|
REJECT_INVALID, "bad-blk-sigops"); |
|
|
|
} |
|
|
|
|
|
|
|
cachedHashes.emplace_back(tx); |
|
|
|
txdata.emplace_back(tx); |
|
|
|
|
|
|
|
if (!tx.IsCoinBase()) |
|
|
|
{ |
|
|
|
nFees += view.GetValueIn(tx)-tx.GetValueOut(); |
|
|
|
|
|
|
|
std::vector<CScriptCheck> vChecks; |
|
|
|
if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, false, cachedHashes[i], chainparams.GetConsensus(), nScriptCheckThreads ? &vChecks : NULL)) |
|
|
|
if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, false, txdata[i], chainparams.GetConsensus(), nScriptCheckThreads ? &vChecks : NULL)) |
|
|
|
return false; |
|
|
|
control.Add(vChecks); |
|
|
|
} |
|
|
|