1212#include < primitives/transaction.h>
1313#include < primitives/block.h>
1414
15- /* * A "reason" why something was invalid, suitable for determining whether the
16- * provider of the object should be banned/ignored/disconnected/etc.
15+ /* * A "reason" why a transaction was invalid, suitable for determining whether the
16+ * provider of the transaction should be banned/ignored/disconnected/etc.
1717 */
18- enum class ValidationInvalidReason {
19- // txn and blocks:
20- NONE, // !< not actually invalid
21- CONSENSUS, // !< invalid by consensus rules (excluding any below reasons)
18+ enum class TxValidationResult {
19+ TX_RESULT_UNSET, // !< initial value. Tx has not yet been rejected
20+ TX_CONSENSUS, // !< invalid by consensus rules
2221 /* *
2322 * Invalid by a change to consensus rules more recent than SegWit.
2423 * Currently unused as there are no such consensus rule changes, and any download
2524 * sources realistically need to support SegWit in order to provide useful data,
2625 * so differentiating between always-invalid and invalid-by-pre-SegWit-soft-fork
2726 * is uninteresting.
2827 */
29- RECENT_CONSENSUS_CHANGE,
30- // Only blocks (or headers):
31- CACHED_INVALID, // !< this object was cached as being invalid, but we don't know why
32- BLOCK_INVALID_HEADER, // !< invalid proof of work or time too old
33- BLOCK_MUTATED, // !< the block's data didn't match the data committed to by the PoW
34- BLOCK_MISSING_PREV, // !< We don't have the previous block the checked one is built on
35- BLOCK_INVALID_PREV, // !< A block this one builds on is invalid
36- BLOCK_TIME_FUTURE, // !< block timestamp was > 2 hours in the future (or our clock is bad)
37- BLOCK_CHECKPOINT, // !< the block failed to meet one of our checkpoints
38- // Only loose txn:
28+ TX_RECENT_CONSENSUS_CHANGE,
3929 TX_NOT_STANDARD, // !< didn't meet our local policy rules
40- TX_MISSING_INPUTS, // !< a transaction was missing some of its inputs
30+ /* *
31+ * transaction was missing some of its inputs
32+ * TODO: ATMP uses fMissingInputs and a valid ValidationState to indicate missing inputs.
33+ * Change ATMP to use TX_MISSING_INPUTS.
34+ */
35+ TX_MISSING_INPUTS,
4136 TX_PREMATURE_SPEND, // !< transaction spends a coinbase too early, or violates locktime/sequence locks
4237 /* *
4338 * Transaction might be missing a witness, have a witness prior to SegWit
@@ -48,64 +43,67 @@ enum class ValidationInvalidReason {
4843 /* *
4944 * Tx already in mempool or conflicts with a tx in the chain
5045 * (if it conflicts with another tx in mempool, we use MEMPOOL_POLICY as it failed to reach the RBF threshold)
51- * TODO: Currently this is only used if the transaction already exists in the mempool or on chain,
52- * TODO: ATMP's fMissingInputs and a valid CValidationState being used to indicate missing inputs
46+ * Currently this is only used if the transaction already exists in the mempool or on chain.
5347 */
5448 TX_CONFLICT,
5549 TX_MEMPOOL_POLICY, // !< violated mempool's fee/size/descendant/RBF/etc limits
5650};
5751
58- inline bool IsTransactionReason (ValidationInvalidReason r)
59- {
60- return r == ValidationInvalidReason::NONE ||
61- r == ValidationInvalidReason::CONSENSUS ||
62- r == ValidationInvalidReason::RECENT_CONSENSUS_CHANGE ||
63- r == ValidationInvalidReason::TX_NOT_STANDARD ||
64- r == ValidationInvalidReason::TX_PREMATURE_SPEND ||
65- r == ValidationInvalidReason::TX_MISSING_INPUTS ||
66- r == ValidationInvalidReason::TX_WITNESS_MUTATED ||
67- r == ValidationInvalidReason::TX_CONFLICT ||
68- r == ValidationInvalidReason::TX_MEMPOOL_POLICY;
69- }
52+ /* * A "reason" why a block was invalid, suitable for determining whether the
53+ * provider of the block should be banned/ignored/disconnected/etc.
54+ * These are much more granular than the rejection codes, which may be more
55+ * useful for some other use-cases.
56+ */
57+ enum class BlockValidationResult {
58+ BLOCK_RESULT_UNSET, // !< initial value. Block has not yet been rejected
59+ BLOCK_CONSENSUS, // !< invalid by consensus rules (excluding any below reasons)
60+ /* *
61+ * Invalid by a change to consensus rules more recent than SegWit.
62+ * Currently unused as there are no such consensus rule changes, and any download
63+ * sources realistically need to support SegWit in order to provide useful data,
64+ * so differentiating between always-invalid and invalid-by-pre-SegWit-soft-fork
65+ * is uninteresting.
66+ */
67+ BLOCK_RECENT_CONSENSUS_CHANGE,
68+ BLOCK_CACHED_INVALID, // !< this block was cached as being invalid and we didn't store the reason why
69+ BLOCK_INVALID_HEADER, // !< invalid proof of work or time too old
70+ BLOCK_MUTATED, // !< the block's data didn't match the data committed to by the PoW
71+ BLOCK_MISSING_PREV, // !< We don't have the previous block the checked one is built on
72+ BLOCK_INVALID_PREV, // !< A block this one builds on is invalid
73+ BLOCK_TIME_FUTURE, // !< block timestamp was > 2 hours in the future (or our clock is bad)
74+ BLOCK_CHECKPOINT, // !< the block failed to meet one of our checkpoints
75+ };
7076
71- inline bool IsBlockReason (ValidationInvalidReason r)
72- {
73- return r == ValidationInvalidReason::NONE ||
74- r == ValidationInvalidReason::CONSENSUS ||
75- r == ValidationInvalidReason::RECENT_CONSENSUS_CHANGE ||
76- r == ValidationInvalidReason::CACHED_INVALID ||
77- r == ValidationInvalidReason::BLOCK_INVALID_HEADER ||
78- r == ValidationInvalidReason::BLOCK_MUTATED ||
79- r == ValidationInvalidReason::BLOCK_MISSING_PREV ||
80- r == ValidationInvalidReason::BLOCK_INVALID_PREV ||
81- r == ValidationInvalidReason::BLOCK_TIME_FUTURE ||
82- r == ValidationInvalidReason::BLOCK_CHECKPOINT;
83- }
8477
85- /* * Capture information about block/transaction validation */
86- class CValidationState {
78+
79+ /* * Base class for capturing information about block/transaction validation. This is subclassed
80+ * by TxValidationState and BlockValidationState for validation information on transactions
81+ * and blocks respectively. */
82+ class ValidationState {
8783private:
8884 enum mode_state {
8985 MODE_VALID, // !< everything ok
9086 MODE_INVALID, // !< network rule violation (DoS value may be set)
9187 MODE_ERROR, // !< run-time error
9288 } mode;
93- ValidationInvalidReason m_reason;
9489 std::string strRejectReason;
9590 std::string strDebugMessage;
96- public:
97- CValidationState () : mode(MODE_VALID), m_reason(ValidationInvalidReason::NONE) {}
98- bool Invalid (ValidationInvalidReason reasonIn, bool ret = false ,
91+ protected:
92+ bool Invalid (bool ret = false ,
9993 const std::string &strRejectReasonIn=" " ,
10094 const std::string &strDebugMessageIn=" " ) {
101- m_reason = reasonIn;
10295 strRejectReason = strRejectReasonIn;
10396 strDebugMessage = strDebugMessageIn;
10497 if (mode == MODE_ERROR)
10598 return ret;
10699 mode = MODE_INVALID;
107100 return ret;
108101 }
102+ public:
103+ // ValidationState is abstract. Have a pure virtual destructor.
104+ virtual ~ValidationState () = 0 ;
105+
106+ ValidationState () : mode(MODE_VALID) {}
109107 bool Error (const std::string& strRejectReasonIn) {
110108 if (mode == MODE_VALID)
111109 strRejectReason = strRejectReasonIn;
@@ -121,11 +119,38 @@ class CValidationState {
121119 bool IsError () const {
122120 return mode == MODE_ERROR;
123121 }
124- ValidationInvalidReason GetReason () const { return m_reason; }
125122 std::string GetRejectReason () const { return strRejectReason; }
126123 std::string GetDebugMessage () const { return strDebugMessage; }
127124};
128125
126+ inline ValidationState::~ValidationState () {};
127+
128+ class TxValidationState : public ValidationState {
129+ private:
130+ TxValidationResult m_result;
131+ public:
132+ bool Invalid (TxValidationResult result, bool ret = false ,
133+ const std::string &_strRejectReason=" " ,
134+ const std::string &_strDebugMessage=" " ) {
135+ m_result = result;
136+ return ValidationState::Invalid (ret, _strRejectReason, _strDebugMessage);
137+ }
138+ TxValidationResult GetResult () const { return m_result; }
139+ };
140+
141+ class BlockValidationState : public ValidationState {
142+ private:
143+ BlockValidationResult m_result;
144+ public:
145+ bool Invalid (BlockValidationResult result, bool ret = false ,
146+ const std::string &_strRejectReason=" " ,
147+ const std::string &_strDebugMessage=" " ) {
148+ m_result = result;
149+ return ValidationState::Invalid (ret, _strRejectReason, _strDebugMessage);
150+ }
151+ BlockValidationResult GetResult () const { return m_result; }
152+ };
153+
129154// These implement the weight = (stripped_size * 4) + witness_size formula,
130155// using only serialization with and without witness data. As witness_size
131156// is equal to total_size - stripped_size, this formula is identical to:
0 commit comments