Changeset View
Changeset View
Standalone View
Standalone View
src/consensus/validation.h
Show All 9 Lines | |||||
#include <string> | #include <string> | ||||
/** | /** | ||||
* A "reason" why a transaction was invalid, suitable for determining whether | * A "reason" why a transaction was invalid, suitable for determining whether | ||||
* the provider of the transaction should be banned/ignored/disconnected/etc. | * the provider of the transaction should be banned/ignored/disconnected/etc. | ||||
*/ | */ | ||||
enum class TxValidationResult { | enum class TxValidationResult { | ||||
//! initial value. Tx has not yet been rejected | //! initial value. Tx has not yet been rejected | ||||
TX_RESULT_UNSET, | TX_RESULT_UNSET = 0, | ||||
//! invalid by consensus rules | //! invalid by consensus rules | ||||
TX_CONSENSUS, | TX_CONSENSUS, | ||||
/** | /** | ||||
* Invalid by a recent change to consensus rules. | * Invalid by a recent change to consensus rules. | ||||
* Currently unused as there are no such consensus rule changes. | * Currently unused as there are no such consensus rule changes. | ||||
*/ | */ | ||||
TX_RECENT_CONSENSUS_CHANGE, | TX_RECENT_CONSENSUS_CHANGE, | ||||
//! didn't meet our local policy rules | //! didn't meet our local policy rules | ||||
Show All 16 Lines | |||||
/** | /** | ||||
* A "reason" why a block was invalid, suitable for determining whether the | * A "reason" why a block was invalid, suitable for determining whether the | ||||
* provider of the block should be banned/ignored/disconnected/etc. | * provider of the block should be banned/ignored/disconnected/etc. | ||||
* These are much more granular than the rejection codes, which may be more | * These are much more granular than the rejection codes, which may be more | ||||
* useful for some other use-cases. | * useful for some other use-cases. | ||||
*/ | */ | ||||
enum class BlockValidationResult { | enum class BlockValidationResult { | ||||
//! initial value. Block has not yet been rejected | //! initial value. Block has not yet been rejected | ||||
BLOCK_RESULT_UNSET, | BLOCK_RESULT_UNSET = 0, | ||||
//! invalid by consensus rules (excluding any below reasons) | //! invalid by consensus rules (excluding any below reasons) | ||||
BLOCK_CONSENSUS, | BLOCK_CONSENSUS, | ||||
/** | /** | ||||
* Invalid by a change to consensus rules more recent than SegWit. | * Invalid by a change to consensus rules more recent than SegWit. | ||||
* Currently unused as there are no such consensus rule changes, and any | * Currently unused as there are no such consensus rule changes, and any | ||||
* download sources realistically need to support SegWit in order to provide | * download sources realistically need to support SegWit in order to provide | ||||
* useful data, so differentiating between always-invalid and | * useful data, so differentiating between always-invalid and | ||||
* invalid-by-pre-SegWit-soft-fork is uninteresting. | * invalid-by-pre-SegWit-soft-fork is uninteresting. | ||||
Show All 14 Lines | enum class BlockValidationResult { | ||||
BLOCK_TIME_FUTURE, | BLOCK_TIME_FUTURE, | ||||
//! the block failed to meet one of our checkpoints | //! the block failed to meet one of our checkpoints | ||||
BLOCK_CHECKPOINT, | BLOCK_CHECKPOINT, | ||||
//! block finalization problems | //! block finalization problems | ||||
BLOCK_FINALIZATION, | BLOCK_FINALIZATION, | ||||
}; | }; | ||||
/** | /** | ||||
* Base class for capturing information about block/transaction validation. | * Template for capturing information about block/transaction validation. | ||||
* This is subclassed by TxValidationState and BlockValidationState for | * This is instantiated by TxValidationState and BlockValidationState for | ||||
* validation information on transactions and blocks respectively. | * validation information on transactions and blocks respectively. | ||||
*/ | */ | ||||
class ValidationState { | template <typename Result> class ValidationState { | ||||
private: | private: | ||||
enum mode_state { | enum mode_state { | ||||
MODE_VALID, //!< everything ok | MODE_VALID, //!< everything ok | ||||
MODE_INVALID, //!< network rule violation (DoS value may be set) | MODE_INVALID, //!< network rule violation (DoS value may be set) | ||||
MODE_ERROR, //!< run-time error | MODE_ERROR, //!< run-time error | ||||
} m_mode{MODE_VALID}; | } m_mode{MODE_VALID}; | ||||
Result m_result{}; | |||||
std::string m_reject_reason; | std::string m_reject_reason; | ||||
std::string m_debug_message; | std::string m_debug_message; | ||||
protected: | public: | ||||
void Invalid(const std::string &reject_reason = "", | bool Invalid(Result result, const std::string &reject_reason = "", | ||||
const std::string &debug_message = "") { | const std::string &debug_message = "") { | ||||
m_result = result; | |||||
m_reject_reason = reject_reason; | m_reject_reason = reject_reason; | ||||
m_debug_message = debug_message; | m_debug_message = debug_message; | ||||
if (m_mode != MODE_ERROR) { | if (m_mode != MODE_ERROR) { | ||||
m_mode = MODE_INVALID; | m_mode = MODE_INVALID; | ||||
} | } | ||||
return false; | |||||
} | } | ||||
public: | |||||
// ValidationState is abstract. Have a pure virtual destructor. | |||||
virtual ~ValidationState() = 0; | |||||
bool Error(const std::string &reject_reason) { | bool Error(const std::string &reject_reason) { | ||||
if (m_mode == MODE_VALID) { | if (m_mode == MODE_VALID) { | ||||
m_reject_reason = reject_reason; | m_reject_reason = reject_reason; | ||||
} | } | ||||
m_mode = MODE_ERROR; | m_mode = MODE_ERROR; | ||||
return false; | return false; | ||||
} | } | ||||
bool IsValid() const { return m_mode == MODE_VALID; } | bool IsValid() const { return m_mode == MODE_VALID; } | ||||
bool IsInvalid() const { return m_mode == MODE_INVALID; } | bool IsInvalid() const { return m_mode == MODE_INVALID; } | ||||
bool IsError() const { return m_mode == MODE_ERROR; } | bool IsError() const { return m_mode == MODE_ERROR; } | ||||
Result GetResult() const { return m_result; } | |||||
std::string GetRejectReason() const { return m_reject_reason; } | std::string GetRejectReason() const { return m_reject_reason; } | ||||
std::string GetDebugMessage() const { return m_debug_message; } | std::string GetDebugMessage() const { return m_debug_message; } | ||||
std::string ToString() const { | std::string ToString() const { | ||||
if (IsValid()) { | if (IsValid()) { | ||||
return "Valid"; | return "Valid"; | ||||
} | } | ||||
if (!m_debug_message.empty()) { | if (!m_debug_message.empty()) { | ||||
return m_reject_reason + ", " + m_debug_message; | return m_reject_reason + ", " + m_debug_message; | ||||
} | } | ||||
return m_reject_reason; | return m_reject_reason; | ||||
} | } | ||||
}; | }; | ||||
inline ValidationState::~ValidationState(){}; | class TxValidationState : public ValidationState<TxValidationResult> {}; | ||||
class BlockValidationState : public ValidationState<BlockValidationResult> {}; | |||||
class TxValidationState : public ValidationState { | |||||
private: | |||||
TxValidationResult m_result = TxValidationResult::TX_RESULT_UNSET; | |||||
public: | |||||
bool Invalid(TxValidationResult result, | |||||
const std::string &reject_reason = "", | |||||
const std::string &debug_message = "") { | |||||
m_result = result; | |||||
ValidationState::Invalid(reject_reason, debug_message); | |||||
return false; | |||||
} | |||||
TxValidationResult GetResult() const { return m_result; } | |||||
}; | |||||
class BlockValidationState : public ValidationState { | |||||
private: | |||||
BlockValidationResult m_result = BlockValidationResult::BLOCK_RESULT_UNSET; | |||||
public: | |||||
bool Invalid(BlockValidationResult result, | |||||
const std::string &reject_reason = "", | |||||
const std::string &debug_message = "") { | |||||
m_result = result; | |||||
ValidationState::Invalid(reject_reason, debug_message); | |||||
return false; | |||||
} | |||||
BlockValidationResult GetResult() const { return m_result; } | |||||
}; | |||||
#endif // BITCOIN_CONSENSUS_VALIDATION_H | #endif // BITCOIN_CONSENSUS_VALIDATION_H |