Skip to main content

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 dusk_core::transfer::TransactionFormat;
11use node_data::StepName;
12use node_data::bls::PublicKeyBytes;
13use node_data::ledger::{Hash, InvalidFault};
14use node_data::message::payload::{RatificationResult, Vote};
15use thiserror::Error;
16
17#[derive(Debug, Clone, Copy, Error)]
18pub enum StepSigError {
19    #[error("Failed to reach a quorum")]
20    VoteSetTooSmall,
21    #[error("Verification error {0}")]
22    VerificationFailed(BlsSigError),
23    #[error("Invalid Type")]
24    InvalidType,
25}
26
27impl From<BlsSigError> for StepSigError {
28    fn from(inner: BlsSigError) -> Self {
29        Self::VerificationFailed(inner)
30    }
31}
32
33#[derive(Debug, Clone)]
34pub enum ConsensusError {
35    InvalidBlock,
36    InvalidBlockHash,
37    InvalidBlockSize(usize),
38    InvalidSignature(BlsSigError),
39    InvalidMsgType,
40    InvalidValidationStepVotes(StepSigError),
41    InvalidPrevBlockHash(Hash),
42    InvalidQuorumType,
43    InvalidVote(Vote),
44    InvalidMsgIteration(u8),
45    FutureEvent,
46    PastEvent,
47    NotCommitteeMember,
48    CommitteeNotGenerated,
49    NotImplemented,
50    NotReady,
51    ChildTaskTerminated,
52    Canceled(u64),
53    VoteAlreadyCollected,
54    VoteMismatch(Vote, Vote),
55    TooManyTransactions(usize),
56    TooManyFaults(usize),
57    UnknownBlockSize,
58}
59
60impl From<StepSigError> for ConsensusError {
61    fn from(e: StepSigError) -> Self {
62        Self::InvalidValidationStepVotes(e)
63    }
64}
65impl From<BlsSigError> for ConsensusError {
66    fn from(e: BlsSigError) -> Self {
67        Self::InvalidSignature(e)
68    }
69}
70
71#[derive(Debug, Error)]
72pub enum OperationError {
73    #[error("State transition creation failed: {0}")]
74    FailedTransitionCreation(StateTransitionError),
75    #[error("State transition verification failed: {0}")]
76    FailedTransitionVerification(StateTransitionError),
77    #[error("Invalid header: {0}")]
78    InvalidHeader(HeaderError),
79    #[error("Unable to update metrics: {0}")]
80    MetricsUpdate(anyhow::Error),
81    #[error("Invalid Iteration Info: {0}")]
82    InvalidIterationInfo(io::Error),
83    #[error("Invalid Faults: {0}")]
84    InvalidFaults(InvalidFault),
85    #[error("Block creation failed: {0}")]
86    BlockCreation(String),
87    #[error("Invalid blob: {0}")]
88    InvalidBlob(String),
89    #[error(
90        "Invalid ledger tx format for tx {tx_id}: got {actual:?}, expected {expected:?} at height {block_height}"
91    )]
92    InvalidTxFormat {
93        tx_id: String,
94        actual: TransactionFormat,
95        expected: TransactionFormat,
96        block_height: u64,
97    },
98}
99
100#[derive(Debug, Error)]
101pub enum HeaderError {
102    #[error("unsupported block version")]
103    UnsupportedVersion,
104    #[error("empty block hash")]
105    EmptyHash,
106    #[error("invalid block height block_height: {0}, curr_height: {1}")]
107    MismatchHeight(u64, u64),
108    #[error("block time is less than minimum block time")]
109    BlockTimeLess,
110    #[error("block timestamp {0} is higher than local time")]
111    BlockTimeHigher(u64),
112    #[error("invalid previous block hash")]
113    PrevBlockHash,
114    #[error("block already exists")]
115    BlockExists,
116    #[error("invalid block signature: {0}")]
117    InvalidBlockSignature(String),
118    #[error("invalid seed: {0}")]
119    InvalidSeed(String),
120
121    #[error("Invalid Attestation: {0}")]
122    InvalidAttestation(AttestationError),
123    #[error("Invalid Failed Iterations: {0}")]
124    InvalidFailedIterations(FailedIterationError),
125
126    #[error("Generic error in header verification: {0}")]
127    Generic(&'static str),
128
129    #[error("Storage error '{0}' in header verification: {1}")]
130    Storage(&'static str, anyhow::Error),
131}
132
133#[derive(Debug, Error)]
134pub enum StateTransitionError {
135    #[error("Chain tip updated during operation")]
136    TipChanged,
137    #[error("Invalid slash from block: {0}")]
138    InvalidSlash(io::Error),
139    #[error("Invalid generator: {0:?}")]
140    InvalidGenerator(dusk_bytes::Error),
141    #[error("Session instantiation failed: {0}")]
142    SessionError(String),
143    #[error("Execution failed: {0}")]
144    ExecutionError(String),
145    #[error(
146      "State root mismatch. transition result: {}, block header: {}",
147      hex::encode(.0),
148      hex::encode(.1)
149    )]
150    StateRootMismatch([u8; 32], [u8; 32]),
151    #[error(
152      "Event bloom mismatch. transition result: {}, block header: {}",
153      hex::encode(.0.as_ref()),
154      hex::encode(.1.as_ref())
155    )]
156    EventBloomMismatch(Box<[u8; 256]>, Box<[u8; 256]>),
157    #[error("Failed to persist state: {0}")]
158    PersistenceError(String),
159}
160
161impl OperationError {
162    pub fn must_vote(&self) -> bool {
163        match self {
164            Self::InvalidHeader(e) => e.must_vote(),
165            Self::FailedTransitionVerification(
166                StateTransitionError::TipChanged,
167            ) => false,
168            _ => true,
169        }
170    }
171}
172
173impl HeaderError {
174    pub fn must_vote(&self) -> bool {
175        match self {
176            HeaderError::MismatchHeight(_, _) => false,
177            HeaderError::BlockTimeHigher(_) => false,
178            HeaderError::PrevBlockHash => false,
179            HeaderError::BlockExists => false,
180            HeaderError::InvalidBlockSignature(_) => false,
181            HeaderError::Storage(..) => false,
182
183            HeaderError::BlockTimeLess => true,
184            HeaderError::UnsupportedVersion => true,
185            HeaderError::EmptyHash => true,
186            HeaderError::InvalidSeed(_) => true,
187            HeaderError::InvalidAttestation(_) => true,
188            HeaderError::InvalidFailedIterations(_) => true,
189
190            HeaderError::Generic(..) => false,
191        }
192    }
193}
194
195#[derive(Debug, Clone, Copy, Error)]
196pub enum AttestationError {
197    #[error("Invalid votes for {0:?}: {1:?}")]
198    InvalidVotes(StepName, StepSigError),
199    #[error("Expected block hash: {0:?}, Got: {1:?}")]
200    InvalidHash(Hash, Hash),
201    #[error("Result: {0:?}, Expected: {1:?}")]
202    InvalidResult(RatificationResult, RatificationResult),
203}
204
205#[derive(Debug, Clone, Copy, Error)]
206pub enum FailedIterationError {
207    #[error("Too many {0}")]
208    TooMany(usize),
209    #[error("Invalid generator. Expected {0:?}")]
210    InvalidGenerator(PublicKeyBytes),
211    #[error("Invalid attestation: {0}")]
212    InvalidAttestation(AttestationError),
213}
214
215impl From<AttestationError> for HeaderError {
216    fn from(value: AttestationError) -> Self {
217        Self::InvalidAttestation(value)
218    }
219}
220
221impl From<AttestationError> for FailedIterationError {
222    fn from(value: AttestationError) -> Self {
223        Self::InvalidAttestation(value)
224    }
225}
226
227impl From<FailedIterationError> for HeaderError {
228    fn from(value: FailedIterationError) -> Self {
229        Self::InvalidFailedIterations(value)
230    }
231}
232
233impl From<io::Error> for OperationError {
234    fn from(value: io::Error) -> Self {
235        Self::InvalidIterationInfo(value)
236    }
237}
238
239impl From<InvalidFault> for OperationError {
240    fn from(value: InvalidFault) -> Self {
241        Self::InvalidFaults(value)
242    }
243}
244
245impl From<HeaderError> for OperationError {
246    fn from(value: HeaderError) -> Self {
247        Self::InvalidHeader(value)
248    }
249}
250
251#[derive(Debug, Error)]
252pub enum BlobError {
253    #[error("Missing blob sidecar for hash: {}", hex::encode(.0))]
254    MissingSidecar([u8; 32]),
255    #[error("No blobs provided")]
256    BlobEmpty,
257    #[error("Transaction has too many blobs: {0}")]
258    BlobTooMany(usize),
259    #[error("Invalid blob: {0}")]
260    BlobInvalid(String),
261}