aboutsummaryrefslogtreecommitdiff
path: root/src/consensus/validation.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/consensus/validation.h')
-rw-r--r--src/consensus/validation.h129
1 files changed, 77 insertions, 52 deletions
diff --git a/src/consensus/validation.h b/src/consensus/validation.h
index 4920cdf881..c285817c0d 100644
--- a/src/consensus/validation.h
+++ b/src/consensus/validation.h
@@ -12,13 +12,12 @@
#include <primitives/transaction.h>
#include <primitives/block.h>
-/** A "reason" why something was invalid, suitable for determining whether the
- * provider of the object should be banned/ignored/disconnected/etc.
+/** A "reason" why a transaction was invalid, suitable for determining whether the
+ * provider of the transaction should be banned/ignored/disconnected/etc.
*/
-enum class ValidationInvalidReason {
- // txn and blocks:
- NONE, //!< not actually invalid
- CONSENSUS, //!< invalid by consensus rules (excluding any below reasons)
+enum class TxValidationResult {
+ TX_RESULT_UNSET, //!< initial value. Tx has not yet been rejected
+ TX_CONSENSUS, //!< invalid by consensus rules
/**
* Invalid by a change to consensus rules more recent than SegWit.
* Currently unused as there are no such consensus rule changes, and any download
@@ -26,18 +25,14 @@ enum class ValidationInvalidReason {
* so differentiating between always-invalid and invalid-by-pre-SegWit-soft-fork
* is uninteresting.
*/
- RECENT_CONSENSUS_CHANGE,
- // Only blocks (or headers):
- CACHED_INVALID, //!< this object was cached as being invalid, but we don't know why
- BLOCK_INVALID_HEADER, //!< invalid proof of work or time too old
- BLOCK_MUTATED, //!< the block's data didn't match the data committed to by the PoW
- BLOCK_MISSING_PREV, //!< We don't have the previous block the checked one is built on
- BLOCK_INVALID_PREV, //!< A block this one builds on is invalid
- BLOCK_TIME_FUTURE, //!< block timestamp was > 2 hours in the future (or our clock is bad)
- BLOCK_CHECKPOINT, //!< the block failed to meet one of our checkpoints
- // Only loose txn:
+ TX_RECENT_CONSENSUS_CHANGE,
TX_NOT_STANDARD, //!< didn't meet our local policy rules
- TX_MISSING_INPUTS, //!< a transaction was missing some of its inputs
+ /**
+ * transaction was missing some of its inputs
+ * TODO: ATMP uses fMissingInputs and a valid ValidationState to indicate missing inputs.
+ * Change ATMP to use TX_MISSING_INPUTS.
+ */
+ TX_MISSING_INPUTS,
TX_PREMATURE_SPEND, //!< transaction spends a coinbase too early, or violates locktime/sequence locks
/**
* Transaction might be missing a witness, have a witness prior to SegWit
@@ -48,57 +43,55 @@ enum class ValidationInvalidReason {
/**
* Tx already in mempool or conflicts with a tx in the chain
* (if it conflicts with another tx in mempool, we use MEMPOOL_POLICY as it failed to reach the RBF threshold)
- * 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
+ * Currently this is only used if the transaction already exists in the mempool or on chain.
*/
TX_CONFLICT,
TX_MEMPOOL_POLICY, //!< violated mempool's fee/size/descendant/RBF/etc limits
};
-inline bool IsTransactionReason(ValidationInvalidReason r)
-{
- return r == ValidationInvalidReason::NONE ||
- r == ValidationInvalidReason::CONSENSUS ||
- r == ValidationInvalidReason::RECENT_CONSENSUS_CHANGE ||
- r == ValidationInvalidReason::TX_NOT_STANDARD ||
- r == ValidationInvalidReason::TX_PREMATURE_SPEND ||
- r == ValidationInvalidReason::TX_MISSING_INPUTS ||
- r == ValidationInvalidReason::TX_WITNESS_MUTATED ||
- r == ValidationInvalidReason::TX_CONFLICT ||
- r == ValidationInvalidReason::TX_MEMPOOL_POLICY;
-}
+/** A "reason" why a block was invalid, suitable for determining whether the
+ * provider of the block 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 BlockValidationResult {
+ BLOCK_RESULT_UNSET, //!< initial value. Block has not yet been rejected
+ BLOCK_CONSENSUS, //!< invalid by consensus rules (excluding any below reasons)
+ /**
+ * Invalid by a change to consensus rules more recent than SegWit.
+ * Currently unused as there are no such consensus rule changes, and any download
+ * sources realistically need to support SegWit in order to provide useful data,
+ * so differentiating between always-invalid and invalid-by-pre-SegWit-soft-fork
+ * is uninteresting.
+ */
+ BLOCK_RECENT_CONSENSUS_CHANGE,
+ BLOCK_CACHED_INVALID, //!< this block was cached as being invalid and we didn't store the reason why
+ BLOCK_INVALID_HEADER, //!< invalid proof of work or time too old
+ BLOCK_MUTATED, //!< the block's data didn't match the data committed to by the PoW
+ BLOCK_MISSING_PREV, //!< We don't have the previous block the checked one is built on
+ BLOCK_INVALID_PREV, //!< A block this one builds on is invalid
+ BLOCK_TIME_FUTURE, //!< block timestamp was > 2 hours in the future (or our clock is bad)
+ BLOCK_CHECKPOINT, //!< the block failed to meet one of our checkpoints
+};
-inline bool IsBlockReason(ValidationInvalidReason r)
-{
- return r == ValidationInvalidReason::NONE ||
- r == ValidationInvalidReason::CONSENSUS ||
- r == ValidationInvalidReason::RECENT_CONSENSUS_CHANGE ||
- r == ValidationInvalidReason::CACHED_INVALID ||
- r == ValidationInvalidReason::BLOCK_INVALID_HEADER ||
- r == ValidationInvalidReason::BLOCK_MUTATED ||
- r == ValidationInvalidReason::BLOCK_MISSING_PREV ||
- r == ValidationInvalidReason::BLOCK_INVALID_PREV ||
- r == ValidationInvalidReason::BLOCK_TIME_FUTURE ||
- r == ValidationInvalidReason::BLOCK_CHECKPOINT;
-}
-/** Capture information about block/transaction validation */
-class CValidationState {
+
+/** Base class for capturing information about block/transaction validation. This is subclassed
+ * by TxValidationState and BlockValidationState for validation information on transactions
+ * and blocks respectively. */
+class ValidationState {
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;
std::string strDebugMessage;
-public:
- CValidationState() : mode(MODE_VALID), m_reason(ValidationInvalidReason::NONE) {}
- bool Invalid(ValidationInvalidReason reasonIn, bool ret = false,
+protected:
+ bool Invalid(bool ret = false,
const std::string &strRejectReasonIn="",
const std::string &strDebugMessageIn="") {
- m_reason = reasonIn;
strRejectReason = strRejectReasonIn;
strDebugMessage = strDebugMessageIn;
if (mode == MODE_ERROR)
@@ -106,6 +99,11 @@ public:
mode = MODE_INVALID;
return ret;
}
+public:
+ // ValidationState is abstract. Have a pure virtual destructor.
+ virtual ~ValidationState() = 0;
+
+ ValidationState() : mode(MODE_VALID) {}
bool Error(const std::string& strRejectReasonIn) {
if (mode == MODE_VALID)
strRejectReason = strRejectReasonIn;
@@ -121,11 +119,38 @@ public:
bool IsError() const {
return mode == MODE_ERROR;
}
- ValidationInvalidReason GetReason() const { return m_reason; }
std::string GetRejectReason() const { return strRejectReason; }
std::string GetDebugMessage() const { return strDebugMessage; }
};
+inline ValidationState::~ValidationState() {};
+
+class TxValidationState : public ValidationState {
+private:
+ TxValidationResult m_result;
+public:
+ bool Invalid(TxValidationResult result, bool ret = false,
+ const std::string &_strRejectReason="",
+ const std::string &_strDebugMessage="") {
+ m_result = result;
+ return ValidationState::Invalid(ret, _strRejectReason, _strDebugMessage);
+ }
+ TxValidationResult GetResult() const { return m_result; }
+};
+
+class BlockValidationState : public ValidationState {
+private:
+ BlockValidationResult m_result;
+public:
+ bool Invalid(BlockValidationResult result, bool ret = false,
+ const std::string &_strRejectReason="",
+ const std::string &_strDebugMessage="") {
+ m_result = result;
+ return ValidationState::Invalid(ret, _strRejectReason, _strDebugMessage);
+ }
+ BlockValidationResult GetResult() const { return m_result; }
+};
+
// These implement the weight = (stripped_size * 4) + witness_size formula,
// using only serialization with and without witness data. As witness_size
// is equal to total_size - stripped_size, this formula is identical to: