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