12
12
#include < primitives/transaction.h>
13
13
#include < primitives/block.h>
14
14
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.
17
17
*/
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
22
21
/* *
23
22
* Invalid by a change to consensus rules more recent than SegWit.
24
23
* Currently unused as there are no such consensus rule changes, and any download
25
24
* sources realistically need to support SegWit in order to provide useful data,
26
25
* so differentiating between always-invalid and invalid-by-pre-SegWit-soft-fork
27
26
* is uninteresting.
28
27
*/
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,
39
29
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,
41
36
TX_PREMATURE_SPEND, // !< transaction spends a coinbase too early, or violates locktime/sequence locks
42
37
/* *
43
38
* Transaction might be missing a witness, have a witness prior to SegWit
@@ -48,64 +43,67 @@ enum class ValidationInvalidReason {
48
43
/* *
49
44
* Tx already in mempool or conflicts with a tx in the chain
50
45
* (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.
53
47
*/
54
48
TX_CONFLICT,
55
49
TX_MEMPOOL_POLICY, // !< violated mempool's fee/size/descendant/RBF/etc limits
56
50
};
57
51
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
+ };
70
76
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
- }
84
77
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 {
87
83
private:
88
84
enum mode_state {
89
85
MODE_VALID, // !< everything ok
90
86
MODE_INVALID, // !< network rule violation (DoS value may be set)
91
87
MODE_ERROR, // !< run-time error
92
88
} mode;
93
- ValidationInvalidReason m_reason;
94
89
std::string strRejectReason;
95
90
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 ,
99
93
const std::string &strRejectReasonIn=" " ,
100
94
const std::string &strDebugMessageIn=" " ) {
101
- m_reason = reasonIn;
102
95
strRejectReason = strRejectReasonIn;
103
96
strDebugMessage = strDebugMessageIn;
104
97
if (mode == MODE_ERROR)
105
98
return ret;
106
99
mode = MODE_INVALID;
107
100
return ret;
108
101
}
102
+ public:
103
+ // ValidationState is abstract. Have a pure virtual destructor.
104
+ virtual ~ValidationState () = 0 ;
105
+
106
+ ValidationState () : mode(MODE_VALID) {}
109
107
bool Error (const std::string& strRejectReasonIn) {
110
108
if (mode == MODE_VALID)
111
109
strRejectReason = strRejectReasonIn;
@@ -121,11 +119,38 @@ class CValidationState {
121
119
bool IsError () const {
122
120
return mode == MODE_ERROR;
123
121
}
124
- ValidationInvalidReason GetReason () const { return m_reason; }
125
122
std::string GetRejectReason () const { return strRejectReason; }
126
123
std::string GetDebugMessage () const { return strDebugMessage; }
127
124
};
128
125
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
+
129
154
// These implement the weight = (stripped_size * 4) + witness_size formula,
130
155
// using only serialization with and without witness data. As witness_size
131
156
// is equal to total_size - stripped_size, this formula is identical to:
0 commit comments