mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-03 09:56:38 -05:00
[REFACTOR] Initialize PrecomputedTransactionData in CheckInputScripts
Add a default constructor to `PrecomputedTransactionData`, which doesn't initialize the struct's members. Instead they're initialized inside the `CheckInputScripts()` function. This allows a later commit to add the spent UTXOs to that structure.
This commit is contained in:
parent
5504703a9f
commit
f63dec189c
3 changed files with 32 additions and 9 deletions
|
@ -1279,18 +1279,29 @@ uint256 GetOutputsHash(const T& txTo)
|
|||
} // namespace
|
||||
|
||||
template <class T>
|
||||
PrecomputedTransactionData::PrecomputedTransactionData(const T& txTo)
|
||||
void PrecomputedTransactionData::Init(const T& txTo)
|
||||
{
|
||||
assert(!m_ready);
|
||||
|
||||
// Cache is calculated only for transactions with witness
|
||||
if (txTo.HasWitness()) {
|
||||
hashPrevouts = GetPrevoutHash(txTo);
|
||||
hashSequence = GetSequenceHash(txTo);
|
||||
hashOutputs = GetOutputsHash(txTo);
|
||||
ready = true;
|
||||
}
|
||||
|
||||
m_ready = true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PrecomputedTransactionData::PrecomputedTransactionData(const T& txTo)
|
||||
{
|
||||
Init(txTo);
|
||||
}
|
||||
|
||||
// explicit instantiation
|
||||
template void PrecomputedTransactionData::Init(const CTransaction& txTo);
|
||||
template void PrecomputedTransactionData::Init(const CMutableTransaction& txTo);
|
||||
template PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo);
|
||||
template PrecomputedTransactionData::PrecomputedTransactionData(const CMutableTransaction& txTo);
|
||||
|
||||
|
@ -1303,7 +1314,7 @@ uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn
|
|||
uint256 hashPrevouts;
|
||||
uint256 hashSequence;
|
||||
uint256 hashOutputs;
|
||||
const bool cacheready = cache && cache->ready;
|
||||
const bool cacheready = cache && cache->m_ready;
|
||||
|
||||
if (!(nHashType & SIGHASH_ANYONECANPAY)) {
|
||||
hashPrevouts = cacheready ? cache->hashPrevouts : GetPrevoutHash(txTo);
|
||||
|
|
|
@ -121,7 +121,12 @@ bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned i
|
|||
struct PrecomputedTransactionData
|
||||
{
|
||||
uint256 hashPrevouts, hashSequence, hashOutputs;
|
||||
bool ready = false;
|
||||
bool m_ready = false;
|
||||
|
||||
PrecomputedTransactionData() = default;
|
||||
|
||||
template <class T>
|
||||
void Init(const T& tx);
|
||||
|
||||
template <class T>
|
||||
explicit PrecomputedTransactionData(const T& tx);
|
||||
|
|
|
@ -1016,7 +1016,7 @@ bool MemPoolAccept::AcceptSingleTransaction(const CTransactionRef& ptx, ATMPArgs
|
|||
// 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 (!PolicyScriptChecks(args, workspace, txdata)) return false;
|
||||
|
||||
|
@ -1512,6 +1512,10 @@ bool CheckInputScripts(const CTransaction& tx, TxValidationState &state, const C
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!txdata.m_ready) {
|
||||
txdata.Init(tx);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < tx.vin.size(); i++) {
|
||||
const COutPoint &prevout = tx.vin[i].prevout;
|
||||
const Coin& coin = inputs.AccessCoin(prevout);
|
||||
|
@ -2075,15 +2079,19 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
|
|||
|
||||
CBlockUndo blockundo;
|
||||
|
||||
// Precomputed transaction data pointers must not be invalidated
|
||||
// until after `control` has run the script checks (potentially
|
||||
// in multiple threads). Preallocate the vector size so a new allocation
|
||||
// doesn't invalidate pointers into the vector, and keep txsdata in scope
|
||||
// for as long as `control`.
|
||||
CCheckQueueControl<CScriptCheck> control(fScriptChecks && g_parallel_script_checks ? &scriptcheckqueue : nullptr);
|
||||
std::vector<PrecomputedTransactionData> txsdata(block.vtx.size());
|
||||
|
||||
std::vector<int> prevheights;
|
||||
CAmount nFees = 0;
|
||||
int nInputs = 0;
|
||||
int64_t nSigOpsCost = 0;
|
||||
blockundo.vtxundo.reserve(block.vtx.size() - 1);
|
||||
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]);
|
||||
|
@ -2130,13 +2138,12 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
|
|||
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-blk-sigops");
|
||||
}
|
||||
|
||||
txdata.emplace_back(tx);
|
||||
if (!tx.IsCoinBase())
|
||||
{
|
||||
std::vector<CScriptCheck> vChecks;
|
||||
bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
|
||||
TxValidationState tx_state;
|
||||
if (fScriptChecks && !CheckInputScripts(tx, tx_state, view, flags, fCacheResults, fCacheResults, txdata[i], g_parallel_script_checks ? &vChecks : nullptr)) {
|
||||
if (fScriptChecks && !CheckInputScripts(tx, tx_state, view, flags, fCacheResults, fCacheResults, txsdata[i], g_parallel_script_checks ? &vChecks : nullptr)) {
|
||||
// Any transaction validation failure in ConnectBlock is a block consensus failure
|
||||
state.Invalid(BlockValidationResult::BLOCK_CONSENSUS,
|
||||
tx_state.GetRejectReason(), tx_state.GetDebugMessage());
|
||||
|
|
Loading…
Add table
Reference in a new issue