From 2c901fd87d62d1d393af65dd1a461d30554e2955 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Mon, 13 Jun 2016 11:52:46 -0600 Subject: [PATCH] Refactor contextual and noncontextual input checks. --- src/main.cpp | 41 +++++++++++++++++++++++++++++++---------- src/main.h | 3 +++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index a16d59f8f..09c357b01 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1604,7 +1604,7 @@ bool CScriptCheck::operator()() { return true; } -bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, std::vector *pvChecks) +bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, std::vector *pvChecks) { if (!tx.IsCoinBase()) { @@ -1620,10 +1620,6 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons if (!inputs.HavePourRequirements(tx)) return state.Invalid(error("CheckInputs(): %s pour requirements not met", tx.GetHash().ToString())); - // While checking, GetBestBlock() refers to the parent block. - // This is also true for mempool checks. - CBlockIndex *pindexPrev = mapBlockIndex.find(inputs.GetBestBlock())->second; - int nSpendHeight = pindexPrev->nHeight + 1; CAmount nValueIn = 0; CAmount nFees = 0; for (unsigned int i = 0; i < tx.vin.size(); i++) @@ -1632,12 +1628,8 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons const CCoins *coins = inputs.AccessCoins(prevout.hash); assert(coins); - // If prev is coinbase, check that it's matured if (coins->IsCoinBase()) { - if (nSpendHeight - coins->nHeight < COINBASE_MATURITY) - return state.Invalid( - error("CheckInputs(): tried to spend coinbase at depth %d", nSpendHeight - coins->nHeight), - REJECT_INVALID, "bad-txns-premature-spend-of-coinbase"); + } // Check for negative or overflow input values @@ -1715,6 +1707,35 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons return true; } +bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, std::vector *pvChecks) +{ + if (!tx.IsCoinBase()) + { + // While checking, GetBestBlock() refers to the parent block. + // This is also true for mempool checks. + CBlockIndex *pindexPrev = mapBlockIndex.find(inputs.GetBestBlock())->second; + int nSpendHeight = pindexPrev->nHeight + 1; + for (unsigned int i = 0; i < tx.vin.size(); i++) + { + const COutPoint &prevout = tx.vin[i].prevout; + const CCoins *coins = inputs.AccessCoins(prevout.hash); + assert(coins); + + // If prev is coinbase, check that it's matured + if (coins->IsCoinBase()) { + if (nSpendHeight - coins->nHeight < COINBASE_MATURITY) + return state.Invalid( + error("CheckInputs(): tried to spend coinbase at depth %d", nSpendHeight - coins->nHeight), + REJECT_INVALID, "bad-txns-premature-spend-of-coinbase"); + } + } + } + + return NonContextualCheckInputs( + tx, state, inputs, fScriptChecks, flags, cacheStore, pvChecks + ); +} + namespace { bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart) diff --git a/src/main.h b/src/main.h index 9357ce9f5..f1627e621 100644 --- a/src/main.h +++ b/src/main.h @@ -320,6 +320,9 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& ma bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks, unsigned int flags, bool cacheStore, std::vector *pvChecks = NULL); +bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks, + unsigned int flags, bool cacheStore, std::vector *pvChecks = NULL); + /** Apply the effects of this transaction on the UTXO set represented by view */ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, int nHeight);