Some clarifications after a code review by Mike Hearn.tags/v0.15.1
@@ -698,6 +698,8 @@ bool CTxMemPool::accept(CTransaction &tx, bool fCheckInputs, | |||
return false; | |||
// do all inputs exist? | |||
// Note that this does not check for the presence of actual outputs (see the next check for that), | |||
// only helps filling in pfMissingInputs (to determine missing vs spent). | |||
BOOST_FOREACH(const CTxIn txin, tx.vin) { | |||
if (!view.HaveCoins(txin.prevout.hash)) { | |||
if (pfMissingInputs) | |||
@@ -706,6 +708,7 @@ bool CTxMemPool::accept(CTransaction &tx, bool fCheckInputs, | |||
} | |||
} | |||
// are the actual inputs available? | |||
if (!tx.HaveInputs(view)) | |||
return error("CTxMemPool::accept() : inputs already spent"); | |||
@@ -1956,9 +1959,13 @@ bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot) const | |||
if (!tx.CheckTransaction()) | |||
return DoS(tx.nDoS, error("CheckBlock() : CheckTransaction failed")); | |||
// Build the merkle tree already. We need it anyway later, and it makes the | |||
// block cache the transaction hashes, which means they don't need to be | |||
// recalculated many times during this block's validation. | |||
BuildMerkleTree(); | |||
// Check for duplicate txids. This is caught by ConnectInputs(), | |||
// but catching it earlier avoids a potential DoS attack: | |||
BuildMerkleTree(); | |||
set<uint256> uniqueTx; | |||
for (unsigned int i=0; i<vtx.size(); i++) { | |||
uniqueTx.insert(GetTxHash(i)); |
@@ -1820,7 +1820,11 @@ public: | |||
// Modify the currently active block index | |||
virtual bool SetBestBlock(CBlockIndex *pindex); | |||
// Do a bulk modification (multiple SetCoins + one SetBestBlock) | |||
virtual bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex); | |||
// Calculate statistics about the unspent transaction output set | |||
virtual bool GetStats(CCoinsStats &stats); | |||
}; | |||
@@ -1851,14 +1855,25 @@ protected: | |||
public: | |||
CCoinsViewCache(CCoinsView &baseIn, bool fDummy = false); | |||
// Standard CCoinsView methods | |||
bool GetCoins(uint256 txid, CCoins &coins); | |||
bool SetCoins(uint256 txid, const CCoins &coins); | |||
bool HaveCoins(uint256 txid); | |||
CCoins &GetCoins(uint256 txid); | |||
CBlockIndex *GetBestBlock(); | |||
bool SetBestBlock(CBlockIndex *pindex); | |||
bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex); | |||
// Return a modifiable reference to a CCoins. Check HaveCoins first. | |||
// Many methods explicitly require a CCoinsViewCache because of this method, to reduce | |||
// copying. | |||
CCoins &GetCoins(uint256 txid); | |||
// Push the modifications applied to this cache to its base. | |||
// Failure to call this method before destruction will cause the changes to be forgotten. | |||
bool Flush(); | |||
// Calculate the size of the cache (in number of transactions) | |||
unsigned int GetCacheSize(); | |||
private: |