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("State transition creation failed: {0}")]
73    FailedTransitionCreation(StateTransitionError),
74    #[error("State transition verification failed: {0}")]
75    FailedTransitionVerification(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    #[error("Invalid blob: {0}")]
87    InvalidBlob(String),
88}
89
90#[derive(Debug, Error)]
91pub enum HeaderError {
92    #[error("unsupported block version")]
93    UnsupportedVersion,
94    #[error("empty block hash")]
95    EmptyHash,
96    #[error("invalid block height block_height: {0}, curr_height: {1}")]
97    MismatchHeight(u64, u64),
98    #[error("block time is less than minimum block time")]
99    BlockTimeLess,
100    #[error("block timestamp {0} is higher than local time")]
101    BlockTimeHigher(u64),
102    #[error("invalid previous block hash")]
103    PrevBlockHash,
104    #[error("block already exists")]
105    BlockExists,
106    #[error("invalid block signature: {0}")]
107    InvalidBlockSignature(String),
108    #[error("invalid seed: {0}")]
109    InvalidSeed(String),
110
111    #[error("Invalid Attestation: {0}")]
112    InvalidAttestation(AttestationError),
113    #[error("Invalid Failed Iterations: {0}")]
114    InvalidFailedIterations(FailedIterationError),
115
116    #[error("Generic error in header verification: {0}")]
117    Generic(&'static str),
118
119    #[error("Storage error '{0}' in header verification: {1}")]
120    Storage(&'static str, anyhow::Error),
121}
122
123#[derive(Debug, Error)]
124pub enum StateTransitionError {
125    #[error("Chain tip updated during operation")]
126    TipChanged,
127    #[error("Invalid slash from block: {0}")]
128    InvalidSlash(io::Error),
129    #[error("Invalid generator: {0:?}")]
130    InvalidGenerator(dusk_bytes::Error),
131    #[error("Session instantiation failed: {0}")]
132    SessionError(String),
133    #[error("Execution failed: {0}")]
134    ExecutionError(String),
135    #[error(
136      "State root mismatch. transition result: {}, block header: {}",
137      hex::encode(.0),
138      hex::encode(.1)
139    )]
140    StateRootMismatch([u8; 32], [u8; 32]),
141    #[error(
142      "Event bloom mismatch. transition result: {}, block header: {}",
143      hex::encode(.0.as_ref()),
144      hex::encode(.1.as_ref())
145    )]
146    EventBloomMismatch(Box<[u8; 256]>, Box<[u8; 256]>),
147    #[error("Failed to persist state: {0}")]
148    PersistenceError(String),
149}
150
151impl OperationError {
152    pub fn must_vote(&self) -> bool {
153        match self {
154            Self::InvalidHeader(e) => e.must_vote(),
155            Self::FailedTransitionVerification(
156                StateTransitionError::TipChanged,
157            ) => false,
158            _ => true,
159        }
160    }
161}
162
163impl HeaderError {
164    pub fn must_vote(&self) -> bool {
165        match self {
166            HeaderError::MismatchHeight(_, _) => false,
167            HeaderError::BlockTimeHigher(_) => false,
168            HeaderError::PrevBlockHash => false,
169            HeaderError::BlockExists => false,
170            HeaderError::InvalidBlockSignature(_) => false,
171            HeaderError::Storage(..) => false,
172
173            HeaderError::BlockTimeLess => true,
174            HeaderError::UnsupportedVersion => true,
175            HeaderError::EmptyHash => true,
176            HeaderError::InvalidSeed(_) => true,
177            HeaderError::InvalidAttestation(_) => true,
178            HeaderError::InvalidFailedIterations(_) => true,
179
180            HeaderError::Generic(..) => false,
181        }
182    }
183}
184
185#[derive(Debug, Clone, Copy, Error)]
186pub enum AttestationError {
187    #[error("Invalid votes for {0:?}: {1:?}")]
188    InvalidVotes(StepName, StepSigError),
189    #[error("Expected block hash: {0:?}, Got: {1:?}")]
190    InvalidHash(Hash, Hash),
191    #[error("Result: {0:?}, Expected: {1:?}")]
192    InvalidResult(RatificationResult, RatificationResult),
193}
194
195#[derive(Debug, Clone, Copy, Error)]
196pub enum FailedIterationError {
197    #[error("Too many {0}")]
198    TooMany(usize),
199    #[error("Invalid generator. Expected {0:?}")]
200    InvalidGenerator(PublicKeyBytes),
201    #[error("Invalid attestation: {0}")]
202    InvalidAttestation(AttestationError),
203}
204
205impl From<AttestationError> for HeaderError {
206    fn from(value: AttestationError) -> Self {
207        Self::InvalidAttestation(value)
208    }
209}
210
211impl From<AttestationError> for FailedIterationError {
212    fn from(value: AttestationError) -> Self {
213        Self::InvalidAttestation(value)
214    }
215}
216
217impl From<FailedIterationError> for HeaderError {
218    fn from(value: FailedIterationError) -> Self {
219        Self::InvalidFailedIterations(value)
220    }
221}
222
223impl From<io::Error> for OperationError {
224    fn from(value: io::Error) -> Self {
225        Self::InvalidIterationInfo(value)
226    }
227}
228
229impl From<InvalidFault> for OperationError {
230    fn from(value: InvalidFault) -> Self {
231        Self::InvalidFaults(value)
232    }
233}
234
235impl From<HeaderError> for OperationError {
236    fn from(value: HeaderError) -> Self {
237        Self::InvalidHeader(value)
238    }
239}
240
241#[derive(Debug, Error)]
242pub enum BlobError {
243    #[error("Missing blob sidecar for hash: {}", hex::encode(.0))]
244    MissingSidecar([u8; 32]),
245    #[error("No blobs provided")]
246    BlobEmpty,
247    #[error("Transaction has too many blobs: {0}")]
248    BlobTooMany(usize),
249    #[error("Invalid blob: {0}")]
250    BlobInvalid(String),
251}