1use 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}