Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto 2 : // Copyright (c) 2009-2021 The Bitcoin Core developers 3 : // Distributed under the MIT software license, see the accompanying 4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 : 6 : #ifndef BITCOIN_CONSENSUS_VALIDATION_H 7 : #define BITCOIN_CONSENSUS_VALIDATION_H 8 : 9 : #include <string> 10 : 11 : /** A "reason" why a transaction was invalid, suitable for determining whether the 12 : * provider of the transaction should be banned/ignored/disconnected/etc. 13 : */ 14 : enum class TxValidationResult { 15 : TX_RESULT_UNSET = 0, //!< initial value. Tx has not yet been rejected 16 : TX_CONSENSUS, //!< invalid by consensus rules 17 : /** 18 : * Invalid by a change to consensus rules more recent than some major deployment. 19 : */ 20 : // Only loose txn: 21 : TX_RECENT_CONSENSUS_CHANGE, 22 : TX_INPUTS_NOT_STANDARD, //!< inputs (covered by txid) failed policy rules 23 : TX_NOT_STANDARD, //!< otherwise didn't meet our local policy rules 24 : TX_MISSING_INPUTS, //!< transaction was missing some of its inputs 25 : TX_PREMATURE_SPEND, //!< transaction spends a coinbase too early, or violates locktime/sequence locks 26 : TX_BAD_SPECIAL, //!< special transaction violates some rules that are not enough for insta-ban 27 : /** 28 : * Tx already in mempool or conflicts with a tx in the chain 29 : * Currently this is only used if the transaction already exists in the mempool or on chain. 30 : */ 31 : TX_CONFLICT, 32 : TX_CONFLICT_LOCK, //!< conflicts with InstantSend lock 33 : TX_MEMPOOL_POLICY, //!< violated mempool's fee/size/descendant/etc limits 34 : TX_NO_MEMPOOL, //!< this node does not have a mempool so can't validate the transaction 35 : }; 36 : 37 : /** A "reason" why a block was invalid, suitable for determining whether the 38 : * provider of the block should be banned/ignored/disconnected/etc. 39 : * These are much more granular than the rejection codes, which may be more 40 : * useful for some other use-cases. 41 : */ 42 : enum class BlockValidationResult { 43 : BLOCK_RESULT_UNSET = 0, //!< initial value. Block has not yet been rejected 44 : BLOCK_CONSENSUS, //!< invalid by consensus rules (excluding any below reasons) 45 : /** 46 : * Invalid by a change to consensus rules more recent than SegWit. 47 : * Currently unused as there are no such consensus rule changes, and any download 48 : * sources realistically need to support SegWit in order to provide useful data, 49 : * so differentiating between always-invalid and invalid-by-pre-SegWit-soft-fork 50 : * is uninteresting. 51 : */ 52 : BLOCK_RECENT_CONSENSUS_CHANGE, 53 : BLOCK_CACHED_INVALID, //!< this block was cached as being invalid and we didn't store the reason why 54 : BLOCK_INVALID_HEADER, //!< invalid proof of work or time too old 55 : BLOCK_MUTATED, //!< the block's data didn't match the data committed to by the PoW 56 : BLOCK_MISSING_PREV, //!< We don't have the previous block the checked one is built on 57 : BLOCK_INVALID_PREV, //!< A block this one builds on is invalid 58 : BLOCK_TIME_FUTURE, //!< block timestamp was > 2 hours in the future (or our clock is bad) 59 : BLOCK_CHECKPOINT, //!< the block failed to meet one of our checkpoints 60 : BLOCK_CHAINLOCK, //!< the block conflicts with the ChainLock 61 : }; 62 : 63 : 64 : 65 : /** Template for capturing information about block/transaction validation. This is instantiated 66 : * by TxValidationState and BlockValidationState for validation information on transactions 67 : * and blocks respectively. */ 68 : template <typename Result> 69 12680352 : class ValidationState 70 : { 71 : private: 72 : enum class ModeState { 73 : M_VALID, //!< everything ok 74 : M_INVALID, //!< network rule violation (DoS value may be set) 75 : M_ERROR, //!< run-time error 76 12629589 : } m_mode{ModeState::M_VALID}; 77 12629589 : Result m_result{}; 78 : std::string m_reject_reason; 79 : std::string m_debug_message; 80 : 81 : public: 82 49315 : bool Invalid(Result result, 83 : const std::string& reject_reason = "", 84 : const std::string& debug_message = "") 85 : { 86 49315 : m_result = result; 87 49315 : m_reject_reason = reject_reason; 88 49315 : m_debug_message = debug_message; 89 49315 : if (m_mode != ModeState::M_ERROR) m_mode = ModeState::M_INVALID; 90 49315 : return false; 91 : } 92 2 : bool Error(const std::string& reject_reason) 93 : { 94 2 : if (m_mode == ModeState::M_VALID) 95 2 : m_reject_reason = reject_reason; 96 2 : m_mode = ModeState::M_ERROR; 97 2 : return false; 98 : } 99 603447 : bool IsValid() const { return m_mode == ModeState::M_VALID; } 100 256438 : bool IsInvalid() const { return m_mode == ModeState::M_INVALID; } 101 10498 : bool IsError() const { return m_mode == ModeState::M_ERROR; } 102 14842 : Result GetResult() const { return m_result; } 103 18915 : std::string GetRejectReason() const { return m_reject_reason; } 104 18337 : std::string GetDebugMessage() const { return m_debug_message; } 105 269463 : std::string ToString() const 106 : { 107 269463 : if (IsValid()) { 108 257671 : return "Valid"; 109 : } 110 : 111 11792 : if (!m_debug_message.empty()) { 112 6001 : return m_reject_reason + ", " + m_debug_message; 113 : } 114 : 115 5791 : return m_reject_reason; 116 269463 : } 117 : }; 118 : 119 : class TxValidationState : public ValidationState<TxValidationResult> {}; 120 : class BlockValidationState : public ValidationState<BlockValidationResult> {}; 121 : 122 : #endif // BITCOIN_CONSENSUS_VALIDATION_H