diff options
Diffstat (limited to 'src/main.h')
-rw-r--r-- | src/main.h | 112 |
1 files changed, 72 insertions, 40 deletions
diff --git a/src/main.h b/src/main.h index d5f7093e42..c1af0c3706 100644 --- a/src/main.h +++ b/src/main.h @@ -28,6 +28,8 @@ struct CBlockIndexWorkComparator; static const unsigned int MAX_BLOCK_SIZE = 1000000; /** The maximum size for mined blocks */ static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2; +/** The maximum size for transactions we're willing to relay/mine **/ +static const unsigned int MAX_STANDARD_TX_SIZE = MAX_BLOCK_SIZE_GEN/5; /** The maximum allowed number of signature check operations in a block (network rule) */ static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; /** The maximum number of orphan transactions kept in memory */ @@ -106,15 +108,17 @@ static const uint64 nMinDiskSpace = 52428800; class CReserveKey; class CCoinsDB; class CBlockTreeDB; -class CDiskBlockPos; +struct CDiskBlockPos; class CCoins; 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 +126,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) */ @@ -131,8 +135,12 @@ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false); FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false); /** Import blocks from an external file */ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp = NULL); +/** Initialize a new block tree database + block data on disk */ +bool InitBlockIndex(); /** Load the block tree and coins database from disk */ bool LoadBlockIndex(); +/** Unload database information */ +void UnloadBlockIndex(); /** Verify consistency of the block and coin databases */ bool VerifyDB(); /** Print the loaded block tree */ @@ -172,13 +180,15 @@ 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 */ bool VerifySignature(const CCoins& txFrom, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType); +/** Abort with a message */ +bool AbortNode(const std::string &msg); @@ -454,7 +464,6 @@ public: - enum GetMinFee_mode { GMF_BLOCK, @@ -474,10 +483,6 @@ public: std::vector<CTxOut> 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 +503,6 @@ public: vin.clear(); vout.clear(); nLockTime = 0; - nDoS = 0; // Denial-of-service prevention } bool IsNull() const @@ -654,27 +658,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<CScriptCheck> *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* 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); @@ -814,22 +815,12 @@ public: uint256 hashChecksum; try { filein >> *this; + filein >> hashChecksum; } catch (std::exception &e) { return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__); } - // for compatibility with pre-release code that didn't write checksums to undo data - // TODO: replace by a simply 'filein >> hashChecksum' in the above try block - try { - filein >> hashChecksum; - } catch (std::exception &e) { - hashChecksum = 0; - } - uint32_t hashInit = hashChecksum.Get64(0) & 0xFFFFFFFFUL; - if (hashChecksum == 0 || memcmp(&hashInit, pchMessageStart, 4) == 0) - return true; - // Verify checksum CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION); hasher << hashBlock; @@ -1163,7 +1154,7 @@ public: int GetDepthInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); } bool IsInMainChain() const { return GetDepthInMainChain() > 0; } int GetBlocksToMaturity() const; - bool AcceptToMemoryPool(bool fCheckInputs=true); + bool AcceptToMemoryPool(bool fCheckInputs=true, bool fLimitFree=true); }; @@ -1339,10 +1330,6 @@ public: // memory only mutable std::vector<uint256> vMerkleTree; - // Denial-of-service detection: - mutable int nDoS; - bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; } - CBlock() { SetNull(); @@ -1365,7 +1352,6 @@ public: CBlockHeader::SetNull(); vtx.clear(); vMerkleTree.clear(); - nDoS = 0; } CBlockHeader GetBlockHeader() const @@ -1513,23 +1499,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); }; @@ -1896,6 +1882,52 @@ 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() { + mode = MODE_ERROR; + return false; + } + bool Abort(const std::string &msg) { + AbortNode(msg); + return Error(); + } + 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; + } +}; @@ -2044,7 +2076,7 @@ public: std::map<uint256, CTransaction> mapTx; std::map<COutPoint, CInPoint> mapNextTx; - bool accept(CTransaction &tx, bool fCheckInputs, 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); |