dusk_consensus/
errors.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4//
5// Copyright (c) DUSK NETWORK. All rights reserved.
6
7use std::io;
8
9use dusk_core::signatures::bls::Error as BlsSigError;
10use node_data::bls::PublicKeyBytes;
11use node_data::ledger::{Hash, InvalidFault};
12use node_data::message::payload::{RatificationResult, Vote};
13use node_data::StepName;
14use thiserror::Error;
15
16#[derive(Debug, Clone, Copy, Error)]
17pub enum StepSigError {
18    #[error("Failed to reach a quorum")]
19    VoteSetTooSmall,
20    #[error("Verification error {0}")]
21    VerificationFailed(BlsSigError),
22    #[error("Invalid Type")]
23    InvalidType,
24}
25
26impl From<BlsSigError> for StepSigError {
27    fn from(inner: BlsSigError) -> Self {
28        Self::VerificationFailed(inner)
29    }
30}
31
32#[derive(Debug, Clone)]
33pub enum ConsensusError {
34    InvalidBlock,
35    InvalidBlockHash,
36    InvalidBlockSize(usize),
37    InvalidSignature(BlsSigError),
38    InvalidMsgType,
39    InvalidValidationStepVotes(StepSigError),
40    InvalidPrevBlockHash(Hash),
41    InvalidQuorumType,
42    InvalidVote(Vote),
43    InvalidMsgIteration(u8),
44    FutureEvent,
45    PastEvent,
46    NotCommitteeMember,
47    CommitteeNotGenerated,
48    NotImplemented,
49    NotReady,
50    ChildTaskTerminated,
51    Canceled(u64),
52    VoteAlreadyCollected,
53    VoteMismatch(Vote, Vote),
54    TooManyTransactions(usize),
55    TooManyFaults(usize),
56    UnknownBlockSize,
57}
58
59impl From<StepSigError> for ConsensusError {
60    fn from(e: StepSigError) -> Self {
61        Self::InvalidValidationStepVotes(e)
62    }
63}
64impl From<BlsSigError> for ConsensusError {
65    fn from(e: BlsSigError) -> Self {
66        Self::InvalidSignature(e)
67    }
68}
69
70#[derive(Debug, Error)]
71pub enum OperationError {
72    #[error("VST failed: {0}")]
73    FailedVST(StateTransitionError),
74    #[error("EST failed: {0}")]
75    FailedEST(StateTransitionError),
76    #[error("Invalid header: {0}")]
77    InvalidHeader(HeaderError),
78    #[error("Unable to update metrics: {0}")]
79    MetricsUpdate(anyhow::Error),
80    #[error("Invalid Iteration Info: {0}")]
81    InvalidIterationInfo(io::Error),
82    #[error("Invalid Faults: {0}")]
83    InvalidFaults(InvalidFault),
84    #[error("Block creation failed: {0}")]
85    BlockCreation(String),
86}
87
88#[derive(Debug, Error)]
89pub enum HeaderError {
90    #[error("unsupported block version")]
91    UnsupportedVersion,
92    #[error("empty block hash")]
93    EmptyHash,
94    #[error("invalid block height block_height: {0}, curr_height: {1}")]
95    MismatchHeight(u64, u64),
96    #[error("block time is less than minimum block time")]
97    BlockTimeLess,
98    #[error("block timestamp {0} is higher than local time")]
99    BlockTimeHigher(u64),
100    #[error("invalid previous block hash")]
101    PrevBlockHash,
102    #[error("block already exists")]
103    BlockExists,
104    #[error("invalid block signature: {0}")]
105    InvalidBlockSignature(String),
106    #[error("invalid seed: {0}")]
107    InvalidSeed(String),
108
109    #[error("Invalid Attestation: {0}")]
110    InvalidAttestation(AttestationError),
111    #[error("Invalid Failed Iterations: {0}")]
112    InvalidFailedIterations(FailedIterationError),
113
114    #[error(
115        "mismatch, event_bloom: {}, candidate_event_bloom: {}",
116        hex::encode(.0.as_ref()),
117        hex::encode(.1.as_ref())
118    )]
119    EventBloomMismatch(Box<[u8; 256]>, Box<[u8; 256]>),
120    #[error(
121        "mismatch, state_hash: {}, candidate_state_hash: {}",
122        hex::encode(.0),
123        hex::encode(.1)
124    )]
125    StateRootMismatch([u8; 32], [u8; 32]),
126
127    #[error("Generic error in header verification: {0}")]
128    Generic(&'static str),
129
130    #[error("Storage error '{0}' in header verification: {1}")]
131    Storage(&'static str, anyhow::Error),
132}
133
134#[derive(Debug, Error)]
135pub enum StateTransitionError {
136    #[error("Chain tip updated during operation")]
137    TipChanged,
138    #[error("Invalid slash from block: {0}")]
139    InvalidSlash(io::Error),
140    #[error("Invalid generator: {0:?}")]
141    InvalidGenerator(dusk_bytes::Error),
142    #[error("Execution failed: {0}")]
143    ExecutionError(String),
144    #[error("Verification failed: {0}")]
145    VerificationError(String),
146}
147
148impl OperationError {
149    pub fn must_vote(&self) -> bool {
150        !matches!(self, Self::FailedVST(StateTransitionError::TipChanged))
151    }
152}
153
154impl HeaderError {
155    pub fn must_vote(&self) -> bool {
156        match self {
157            HeaderError::MismatchHeight(_, _) => false,
158            HeaderError::BlockTimeHigher(_) => false,
159            HeaderError::PrevBlockHash => false,
160            HeaderError::BlockExists => false,
161            HeaderError::InvalidBlockSignature(_) => false,
162            HeaderError::Storage(..) => false,
163
164            HeaderError::BlockTimeLess => true,
165            HeaderError::UnsupportedVersion => true,
166            HeaderError::EmptyHash => true,
167            HeaderError::InvalidSeed(_) => true,
168            HeaderError::InvalidAttestation(_) => true,
169            HeaderError::InvalidFailedIterations(_) => true,
170            HeaderError::EventBloomMismatch(_, _) => true,
171            HeaderError::StateRootMismatch(_, _) => true,
172
173            HeaderError::Generic(..) => false,
174        }
175    }
176}
177
178#[derive(Debug, Clone, Copy, Error)]
179pub enum AttestationError {
180    #[error("Invalid votes for {0:?}: {1:?}")]
181    InvalidVotes(StepName, StepSigError),
182    #[error("Expected block hash: {0:?}, Got: {1:?}")]
183    InvalidHash(Hash, Hash),
184    #[error("Result: {0:?}, Expected: {1:?}")]
185    InvalidResult(RatificationResult, RatificationResult),
186}
187
188#[derive(Debug, Clone, Copy, Error)]
189pub enum FailedIterationError {
190    #[error("Too many {0}")]
191    TooMany(usize),
192    #[error("Invalid generator. Expected {0:?}")]
193    InvalidGenerator(PublicKeyBytes),
194    #[error("Invalid attestation: {0}")]
195    InvalidAttestation(AttestationError),
196}
197
198impl From<AttestationError> for HeaderError {
199    fn from(value: AttestationError) -> Self {
200        Self::InvalidAttestation(value)
201    }
202}
203
204impl From<AttestationError> for FailedIterationError {
205    fn from(value: AttestationError) -> Self {
206        Self::InvalidAttestation(value)
207    }
208}
209
210impl From<FailedIterationError> for HeaderError {
211    fn from(value: FailedIterationError) -> Self {
212        Self::InvalidFailedIterations(value)
213    }
214}
215
216impl From<io::Error> for OperationError {
217    fn from(value: io::Error) -> Self {
218        Self::InvalidIterationInfo(value)
219    }
220}
221
222impl From<InvalidFault> for OperationError {
223    fn from(value: InvalidFault) -> Self {
224        Self::InvalidFaults(value)
225    }
226}