Refactored ConnectInputs, so valid-transaction-checks are done before ECDSA-verifying signatures.

This commit is contained in:
Gavin Andresen
2012-01-10 20:18:00 -05:00
parent 922e8e2929
commit 8d7849b6db
3 changed files with 256 additions and 65 deletions

View File

@@ -402,6 +402,8 @@ enum GetMinFee_mode
GMF_SEND,
};
typedef std::map<uint256, std::pair<CTxIndex, CTransaction> > MapPrevTx;
//
// The basic transaction that is broadcasted on the network and contained in
// blocks. A transaction can contain multiple inputs and outputs.
@@ -502,11 +504,36 @@ public:
return (vin.size() == 1 && vin[0].prevout.IsNull());
}
/** Check for standard transaction types
@return True if all outputs (scriptPubKeys) use only standard transaction forms
*/
bool IsStandard() const;
bool AreInputsStandard(const std::map<uint256, std::pair<CTxIndex, CTransaction> >& mapInputs) const;
/** Check for standard transaction types
@param[in] mapInputs Map of previous transactions that have outputs we're spending
@return True if all inputs (scriptSigs) use only standard transaction forms
@see CTransaction::FetchInputs
*/
bool AreInputsStandard(const MapPrevTx& mapInputs) const;
/** Count ECDSA signature operations the old-fashioned (pre-0.6) way
@return number of sigops this transaction's outputs will produce when spent
@see CTransaction::FetchInputs
*/
int GetLegacySigOpCount() const;
/** Count ECDSA signature operations the new (0.6-and-later) way
This is a better measure of how expensive it is to process this transaction.
@param[in] mapInputs Map of previous transactions that have outputs we're spending
@return maximum number of sigops required to validate this transaction's inputs
@see CTransaction::FetchInputs
*/
int GetSigOpCount(const MapPrevTx& mapInputs) const;
/** Amount of bitcoins spent by this transaction.
@return sum of all outputs (note: does not include fees)
*/
int64 GetValueOut() const
{
int64 nValueOut = 0;
@@ -519,6 +546,16 @@ public:
return nValueOut;
}
/** Amount of bitcoins coming in to this transaction
Note that lightweight clients may not know anything besides the hash of previous transactions,
so may not be able to calculate this.
@param[in] mapInputs Map of previous transactions that have outputs we're spending
@return Sum of value of all inputs (scriptSigs)
@see CTransaction::FetchInputs
*/
int64 GetValueIn(const MapPrevTx& mapInputs) const;
static bool AllowFree(double dPriority)
{
// Large (in bytes) low-priority (new, small-coin) transactions
@@ -634,17 +671,39 @@ public:
bool ReadFromDisk(COutPoint prevout);
bool DisconnectInputs(CTxDB& txdb);
// Fetch from memory and/or disk. inputsRet keys are transaction hashes.
/** Fetch from memory and/or disk. inputsRet keys are transaction hashes.
@param[in] txdb Transaction database
@param[in] mapTestPool List of pending changes to the transaction index database
@param[in] fBlock True if being called to add a new best-block to the chain
@param[in] fMiner True if being called by CreateNewBlock
@param[out] inputsRet Pointers to this transaction's inputs
@return Returns true if all inputs are in txdb or mapTestPool
*/
bool FetchInputs(CTxDB& txdb, const std::map<uint256, CTxIndex>& mapTestPool,
bool fBlock, bool fMiner, std::map<uint256, std::pair<CTxIndex, CTransaction> >& inputsRet);
bool ConnectInputs(std::map<uint256, std::pair<CTxIndex, CTransaction> > inputs,
bool fBlock, bool fMiner, MapPrevTx& inputsRet);
/** Sanity check previous transactions, then, if all checks succeed,
mark them as spent by this transaction.
@param[in] inputs Previous transactions (from FetchInputs)
@param[out] mapTestPool Keeps track of inputs that need to be updated on disk
@param[in] posThisTx Position of this transaction on disk
@param[in] pindexBlock
@param[in] fBlock true if called from ConnectBlock
@param[in] fMiner true if called from CreateNewBlock
@return Returns true if all checks succeed
*/
bool ConnectInputs(MapPrevTx inputs,
std::map<uint256, CTxIndex>& mapTestPool, const CDiskTxPos& posThisTx,
const CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int& nSigOpsRet, int64 nMinFee=0);
const CBlockIndex* pindexBlock, bool fBlock, bool fMiner);
bool ClientConnectInputs();
bool CheckTransaction() const;
bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL);
protected:
const CTxOut& GetOutputFor(const CTxIn& input, const MapPrevTx& inputs) const;
bool AddToMemoryPoolUnchecked();
public:
bool RemoveFromMemoryPool();