From ef3988ca369900206b0cfc32cc1958aee0e43710 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 27 Jan 2013 00:14:11 +0100 Subject: CValidationState framework --- src/main.h | 84 ++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 27 deletions(-) (limited to 'src/main.h') diff --git a/src/main.h b/src/main.h index 9dbcac0b5a..9c2029c9b7 100644 --- a/src/main.h +++ b/src/main.h @@ -112,9 +112,11 @@ class CTxUndo; class CCoinsView; class CCoinsViewCache; class CScriptCheck; +class CValidationState; struct CBlockTemplate; + /** Register a wallet to receive updates from core */ void RegisterWallet(CWallet* pwalletIn); /** Unregister a wallet from core */ @@ -122,7 +124,7 @@ void UnregisterWallet(CWallet* pwalletIn); /** Push an updated transaction to all registered wallets */ void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false); /** Process an incoming block */ -bool ProcessBlock(CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL); +bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL); /** Check whether enough disk space is available for an incoming block */ bool CheckDiskSpace(uint64 nAdditionalBytes = 0); /** Open a block file (blk?????.dat) */ @@ -172,9 +174,9 @@ std::string GetWarnings(std::string strFor); /** Retrieve a transaction (from memory pool, or from disk, if possible) */ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fAllowSlow = false); /** Connect/disconnect blocks until pindexNew is the new tip of the active block chain */ -bool SetBestChain(CBlockIndex* pindexNew); +bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew); /** Find the best known block, and make it the tip of the block chain */ -bool ConnectBestBlock(); +bool ConnectBestBlock(CValidationState &state); /** Create a new block index entry for a given block hash */ CBlockIndex * InsertBlockIndex(uint256 hash); /** Verify a signature */ @@ -454,7 +456,6 @@ public: - enum GetMinFee_mode { GMF_BLOCK, @@ -474,10 +475,6 @@ public: std::vector vout; unsigned int nLockTime; - // Denial-of-service detection: - mutable int nDoS; - bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; } - CTransaction() { SetNull(); @@ -498,7 +495,6 @@ public: vin.clear(); vout.clear(); nLockTime = 0; - nDoS = 0; // Denial-of-service prevention } bool IsNull() const @@ -654,27 +650,24 @@ public: } - // Do all possible client-mode checks - bool ClientCheckInputs() const; - // Check whether all prevouts of this transaction are present in the UTXO set represented by view bool HaveInputs(CCoinsViewCache &view) const; // Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts) // This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it // instead of being performed inline. - bool CheckInputs(CCoinsViewCache &view, bool fScriptChecks = true, + bool CheckInputs(CValidationState &state, CCoinsViewCache &view, bool fScriptChecks = true, unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, std::vector *pvChecks = NULL) const; // Apply the effects of this transaction on the UTXO set represented by view - bool UpdateCoins(CCoinsViewCache &view, CTxUndo &txundo, int nHeight, const uint256 &txhash) const; + bool UpdateCoins(CValidationState &state, CCoinsViewCache &view, CTxUndo &txundo, int nHeight, const uint256 &txhash) const; // Context-independent validity checks - bool CheckTransaction() const; + bool CheckTransaction(CValidationState &state) const; // Try to accept this transaction into the memory pool - bool AcceptToMemoryPool(bool fCheckInputs=true, bool fLimitFree = true, bool* pfMissingInputs=NULL); + bool AcceptToMemoryPool(CValidationState &state, bool fCheckInputs=true, bool fLimitFree = true, bool* pfMissingInputs=NULL); protected: static const CTxOut &GetOutputFor(const CTxIn& input, CCoinsViewCache& mapInputs); @@ -1320,10 +1313,6 @@ public: // memory only mutable std::vector vMerkleTree; - // Denial-of-service detection: - mutable int nDoS; - bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; } - CBlock() { SetNull(); @@ -1346,7 +1335,6 @@ public: CBlockHeader::SetNull(); vtx.clear(); vMerkleTree.clear(); - nDoS = 0; } CBlockHeader GetBlockHeader() const @@ -1494,23 +1482,23 @@ public: * In case pfClean is provided, operation will try to be tolerant about errors, and *pfClean * will be true if no problems were found. Otherwise, the return value will be false in case * of problems. Note that in any case, coins may be modified. */ - bool DisconnectBlock(CBlockIndex *pindex, CCoinsViewCache &coins, bool *pfClean = NULL); + bool DisconnectBlock(CValidationState &state, CBlockIndex *pindex, CCoinsViewCache &coins, bool *pfClean = NULL); // Apply the effects of this block (with given index) on the UTXO set represented by coins - bool ConnectBlock(CBlockIndex *pindex, CCoinsViewCache &coins, bool fJustCheck=false); + bool ConnectBlock(CValidationState &state, CBlockIndex *pindex, CCoinsViewCache &coins, bool fJustCheck=false); // Read a block from disk bool ReadFromDisk(const CBlockIndex* pindex); // Add this block to the block index, and if necessary, switch the active block chain to this - bool AddToBlockIndex(const CDiskBlockPos &pos); + bool AddToBlockIndex(CValidationState &state, const CDiskBlockPos &pos); // Context-independent validity checks - bool CheckBlock(bool fCheckPOW=true, bool fCheckMerkleRoot=true) const; + bool CheckBlock(CValidationState &state, bool fCheckPOW=true, bool fCheckMerkleRoot=true) const; // Store block on disk // if dbp is provided, the file is known to already reside on disk - bool AcceptBlock(CDiskBlockPos *dbp = NULL); + bool AcceptBlock(CValidationState &state, CDiskBlockPos *dbp = NULL); }; @@ -1877,6 +1865,48 @@ public: } }; +/** Capture information about block/transaction validation */ +class CValidationState { +private: + enum mode_state { + MODE_VALID, // everything ok + MODE_INVALID, // network rule violation (DoS value may be set) + MODE_ERROR, // run-time error + } mode; + int nDoS; +public: + CValidationState() : mode(MODE_VALID), nDoS(0) {} + bool DoS(int level, bool ret = false) { + if (mode == MODE_ERROR) + return ret; + nDoS += level; + mode = MODE_INVALID; + return ret; + } + bool Invalid(bool ret = false) { + return DoS(0, ret); + } + bool Error(bool ret = false) { + mode = MODE_ERROR; + return ret; + } + bool IsValid() { + return mode == MODE_VALID; + } + bool IsInvalid() { + return mode == MODE_INVALID; + } + bool IsError() { + return mode == MODE_ERROR; + } + bool IsInvalid(int &nDoSOut) { + if (IsInvalid()) { + nDoSOut = nDoS; + return true; + } + return false; + } +}; @@ -2025,7 +2055,7 @@ public: std::map mapTx; std::map mapNextTx; - bool accept(CTransaction &tx, bool fCheckInputs, bool fLimitFree, bool* pfMissingInputs); + bool accept(CValidationState &state, CTransaction &tx, bool fCheckInputs, bool fLimitFree, bool* pfMissingInputs); bool addUnchecked(const uint256& hash, CTransaction &tx); bool remove(const CTransaction &tx, bool fRecursive = false); bool removeConflicts(const CTransaction &tx); -- cgit v1.2.3