diff --git a/src/consensus/validation.h b/src/consensus/validation.h index 54fc7cb13..4ca92ca80 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -1,159 +1,161 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_CONSENSUS_VALIDATION_H #define BITCOIN_CONSENSUS_VALIDATION_H #include #include /** "reject" message codes */ static const uint8_t REJECT_MALFORMED = 0x01; static const uint8_t REJECT_INVALID = 0x10; static const uint8_t REJECT_OBSOLETE = 0x11; static const uint8_t REJECT_DUPLICATE = 0x12; static const uint8_t REJECT_NONSTANDARD = 0x40; static const uint8_t REJECT_INSUFFICIENTFEE = 0x42; static const uint8_t REJECT_CHECKPOINT = 0x43; /** * A "reason" why something was invalid, suitable for determining whether the * provider of the object should be banned/ignored/disconnected/etc. These are * much more granular than the rejection codes, which may be more useful for * some other use-cases. */ enum class ValidationInvalidReason { // txn and blocks: //! not actually invalid NONE, //! invalid by consensus rules (excluding any below reasons) CONSENSUS, /** * Invalid by a recent change to consensus rules. * Currently unused as there are no such consensus rule changes. */ RECENT_CONSENSUS_CHANGE, // Only blocks (or headers): //! this object was cached as being invalid, but we don't know why CACHED_INVALID, //! invalid proof of work or time too old BLOCK_INVALID_HEADER, //! the block's data didn't match the data committed to by the PoW BLOCK_MUTATED, //! We don't have the previous block the checked one is built on BLOCK_MISSING_PREV, //! A block this one builds on is invalid BLOCK_INVALID_PREV, //! block timestamp was > 2 hours in the future (or our clock is bad) BLOCK_TIME_FUTURE, //! the block failed to meet one of our checkpoints BLOCK_CHECKPOINT, //! block finalization problems. BLOCK_FINALIZATION, // Only loose txn: //! didn't meet our local policy rules TX_NOT_STANDARD, //! a transaction was missing some of its inputs (or its inputs were spent //! at < coinbase maturity height) TX_MISSING_INPUTS, /** * Tx already in mempool or conflicts with a tx in the chain * TODO: Currently this is only used if the transaction already exists in * the mempool or on chain, * TODO: ATMP's fMissingInputs and a valid CValidationState being used to * indicate missing inputs */ TX_CONFLICT, //! violated mempool's fee/size/descendant/etc limits TX_MEMPOOL_POLICY, }; /** 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; ValidationInvalidReason m_reason; std::string strRejectReason; unsigned int chRejectCode; std::string strDebugMessage; public: CValidationState() : mode(MODE_VALID), m_reason(ValidationInvalidReason::NONE), chRejectCode(0) {} bool DoS(int level, ValidationInvalidReason reasonIn, bool ret = false, unsigned int chRejectCodeIn = 0, const std::string &strRejectReasonIn = "", bool corruptionPossibleIn = false, const std::string &strDebugMessageIn = "") { + ret = Invalid(reasonIn, ret, chRejectCodeIn, strRejectReasonIn, + strDebugMessageIn); + assert(level == GetDoS()); + assert(corruptionPossibleIn == CorruptionPossible()); + return ret; + } + bool Invalid(ValidationInvalidReason reasonIn, bool ret = false, + unsigned int chRejectCodeIn = 0, + const std::string &strRejectReasonIn = "", + const std::string &strDebugMessageIn = "") { m_reason = reasonIn; chRejectCode = chRejectCodeIn; strRejectReason = strRejectReasonIn; strDebugMessage = strDebugMessageIn; - assert(corruptionPossibleIn == CorruptionPossible()); if (mode == MODE_ERROR) { return ret; } mode = MODE_INVALID; return ret; } - bool Invalid(ValidationInvalidReason _reason, bool ret = false, - unsigned int _chRejectCode = 0, - const std::string &_strRejectReason = "", - const std::string &_strDebugMessage = "") { - return DoS(0, _reason, ret, _chRejectCode, _strRejectReason, false, - _strDebugMessage); - } bool Error(const std::string &strRejectReasonIn) { if (mode == MODE_VALID) { strRejectReason = strRejectReasonIn; } mode = MODE_ERROR; return false; } bool IsValid() const { return mode == MODE_VALID; } bool IsInvalid() const { return mode == MODE_INVALID; } bool IsError() const { return mode == MODE_ERROR; } bool CorruptionPossible() const { return m_reason == ValidationInvalidReason::BLOCK_MUTATED; } int GetDoS() const { switch (m_reason) { case ValidationInvalidReason::NONE: return 0; case ValidationInvalidReason::CONSENSUS: case ValidationInvalidReason::BLOCK_MUTATED: case ValidationInvalidReason::BLOCK_INVALID_HEADER: case ValidationInvalidReason::BLOCK_CHECKPOINT: case ValidationInvalidReason::BLOCK_INVALID_PREV: return 100; case ValidationInvalidReason::BLOCK_FINALIZATION: return 20; case ValidationInvalidReason::BLOCK_MISSING_PREV: return 10; case ValidationInvalidReason::CACHED_INVALID: case ValidationInvalidReason::RECENT_CONSENSUS_CHANGE: case ValidationInvalidReason::BLOCK_TIME_FUTURE: case ValidationInvalidReason::TX_NOT_STANDARD: case ValidationInvalidReason::TX_MISSING_INPUTS: case ValidationInvalidReason::TX_CONFLICT: case ValidationInvalidReason::TX_MEMPOOL_POLICY: return 0; } return 0; } ValidationInvalidReason GetReason() const { return m_reason; } unsigned int GetRejectCode() const { return chRejectCode; } std::string GetRejectReason() const { return strRejectReason; } std::string GetDebugMessage() const { return strDebugMessage; } }; #endif // BITCOIN_CONSENSUS_VALIDATION_H