mithril_stm/
error.rs

1//! Crate specific errors
2use blake2::digest::{Digest, FixedOutput};
3use blst::BLST_ERROR;
4
5use crate::bls_multi_signature::{Signature, VerificationKey, VerificationKeyPoP};
6use crate::merkle_tree::{BatchPath, Path};
7
8/// Error types for multi signatures.
9#[derive(Debug, thiserror::Error, Eq, PartialEq)]
10pub enum MultiSignatureError {
11    /// Invalid Single signature
12    #[error("Invalid single signature")]
13    SignatureInvalid(Signature),
14
15    /// Invalid aggregate signature
16    #[error("Invalid aggregated signature")]
17    AggregateSignatureInvalid,
18
19    /// This error occurs when the the serialization of the raw bytes failed
20    #[error("Invalid bytes")]
21    SerializationError,
22
23    /// Incorrect proof of possession
24    #[error("Key with invalid PoP")]
25    KeyInvalid(Box<VerificationKeyPoP>),
26
27    /// At least one signature in the batch is invalid
28    #[error("One signature in the batch is invalid")]
29    BatchInvalid,
30
31    /// Single signature is the infinity
32    #[error("Single signature is the infinity")]
33    SignatureInfinity(Signature),
34
35    /// Verification key is the infinity
36    #[error("Verification key is the infinity")]
37    VerificationKeyInfinity(Box<VerificationKey>),
38}
39
40/// Error types related to merkle trees.
41#[derive(Debug, Clone, thiserror::Error)]
42pub enum MerkleTreeError<D: Digest + FixedOutput> {
43    /// Serialization error
44    #[error("Serialization of a merkle tree failed")]
45    SerializationError,
46
47    /// Invalid merkle path
48    #[error("Path does not verify against root")]
49    PathInvalid(Path<D>),
50
51    /// Invalid merkle batch path
52    #[error("Batch path does not verify against root")]
53    BatchPathInvalid(BatchPath<D>),
54}
55
56/// Errors which can be output by Mithril single signature verification.
57#[derive(Debug, Clone, thiserror::Error)]
58pub enum StmSignatureError {
59    /// There is an index out of bounds
60    #[error("Received index, {0}, is higher than what the security parameter allows, {1}.")]
61    IndexBoundFailed(u64, u64),
62
63    /// MSP.Eval was computed incorrectly
64    #[error("The claimed evaluation of function phi is incorrect.")]
65    EvalInvalid([u8; 64]),
66
67    /// The lottery was actually lost for the signature
68    #[error("Lottery for this epoch was lost.")]
69    LotteryLost,
70
71    /// A party submitted an invalid signature
72    #[error("A provided signature is invalid")]
73    SignatureInvalid(Signature),
74
75    /// Batch verification of STM signatures failed
76    #[error("Batch verification of STM signatures failed")]
77    BatchInvalid,
78
79    /// This error occurs when the the serialization of the raw bytes failed
80    #[error("Invalid bytes")]
81    SerializationError,
82}
83
84impl From<MultiSignatureError> for StmSignatureError {
85    fn from(e: MultiSignatureError) -> Self {
86        match e {
87            MultiSignatureError::SerializationError => Self::SerializationError,
88            MultiSignatureError::SignatureInvalid(e) => Self::SignatureInvalid(e),
89            MultiSignatureError::BatchInvalid => unreachable!(),
90            MultiSignatureError::KeyInvalid(_) => unreachable!(),
91            MultiSignatureError::AggregateSignatureInvalid => unreachable!(),
92            MultiSignatureError::SignatureInfinity(_) => unreachable!(),
93            MultiSignatureError::VerificationKeyInfinity(_) => unreachable!(),
94        }
95    }
96}
97
98impl<D: Digest + FixedOutput> From<MerkleTreeError<D>> for StmSignatureError {
99    fn from(e: MerkleTreeError<D>) -> Self {
100        match e {
101            MerkleTreeError::SerializationError => Self::SerializationError,
102            _ => unreachable!(),
103        }
104    }
105}
106
107/// Error types for aggregation.
108#[derive(Debug, Clone, thiserror::Error)]
109pub enum AggregationError {
110    /// Not enough signatures were collected, got this many instead.
111    #[error("Not enough signatures. Got only {0} out of {1}.")]
112    NotEnoughSignatures(u64, u64),
113
114    /// This error happens when we try to convert a u64 to a usize and it does not fit
115    #[error("Invalid usize conversion")]
116    UsizeConversionInvalid,
117}
118
119/// Errors which can be output by `CoreVerifier`.
120#[derive(Debug, Clone, thiserror::Error)]
121pub enum CoreVerifierError {
122    /// No quorum was found
123    #[error("No Quorum was found. Expected {0} signatures but got {1}")]
124    NoQuorum(u64, u64),
125
126    /// There is a duplicate index
127    #[error("Indices are not unique.")]
128    IndexNotUnique,
129
130    /// The aggregated signature is invalid
131    #[error("Aggregate signature is invalid")]
132    AggregateSignatureInvalid,
133
134    /// One of the aggregated signatures is invalid
135    #[error("Individual signature is invalid: {0}")]
136    IndividualSignatureInvalid(#[source] StmSignatureError),
137}
138
139impl From<AggregationError> for CoreVerifierError {
140    fn from(e: AggregationError) -> Self {
141        match e {
142            AggregationError::NotEnoughSignatures(e, _e) => Self::NoQuorum(e, e),
143            AggregationError::UsizeConversionInvalid => unreachable!(),
144        }
145    }
146}
147
148impl From<MultiSignatureError> for CoreVerifierError {
149    fn from(e: MultiSignatureError) -> Self {
150        match e {
151            MultiSignatureError::AggregateSignatureInvalid => Self::AggregateSignatureInvalid,
152            MultiSignatureError::BatchInvalid => unreachable!(),
153            MultiSignatureError::SerializationError => unreachable!(),
154            MultiSignatureError::KeyInvalid(_) => unreachable!(),
155            MultiSignatureError::SignatureInvalid(_e) => unreachable!(),
156            MultiSignatureError::SignatureInfinity(_) => unreachable!(),
157            MultiSignatureError::VerificationKeyInfinity(_) => unreachable!(),
158        }
159    }
160}
161
162impl From<StmSignatureError> for CoreVerifierError {
163    fn from(e: StmSignatureError) -> Self {
164        CoreVerifierError::IndividualSignatureInvalid(e)
165    }
166}
167
168/// Errors which can be output by Mithril aggregate verification.
169#[derive(Debug, Clone, thiserror::Error)]
170pub enum StmAggregateSignatureError<D: Digest + FixedOutput> {
171    /// The IVK is invalid after aggregating the keys
172    #[error("Aggregated key does not correspond to the expected key.")]
173    IvkInvalid(Box<VerificationKey>),
174
175    /// This error occurs when the the serialization of the raw bytes failed
176    #[error("Invalid bytes")]
177    SerializationError,
178
179    /// Invalid merkle batch path
180    #[error("Batch path does not verify against root")]
181    PathInvalid(BatchPath<D>),
182
183    /// Batch verification of STM aggregate signatures failed
184    #[error("Batch verification of STM aggregate signatures failed")]
185    BatchInvalid,
186
187    /// `CoreVerifier` check failed
188    #[error("Core verification error: {0}")]
189    CoreVerificationError(#[source] CoreVerifierError),
190}
191
192impl<D: Digest + FixedOutput> From<MerkleTreeError<D>> for StmAggregateSignatureError<D> {
193    fn from(e: MerkleTreeError<D>) -> Self {
194        match e {
195            MerkleTreeError::BatchPathInvalid(e) => Self::PathInvalid(e),
196            MerkleTreeError::SerializationError => Self::SerializationError,
197            MerkleTreeError::PathInvalid(_e) => unreachable!(),
198        }
199    }
200}
201
202impl<D: Digest + FixedOutput> From<MultiSignatureError> for StmAggregateSignatureError<D> {
203    fn from(e: MultiSignatureError) -> Self {
204        match e {
205            MultiSignatureError::AggregateSignatureInvalid => {
206                Self::from(CoreVerifierError::from(e))
207            }
208            MultiSignatureError::BatchInvalid => Self::BatchInvalid,
209            MultiSignatureError::SerializationError => unreachable!(),
210            MultiSignatureError::KeyInvalid(_) => unreachable!(),
211            MultiSignatureError::SignatureInvalid(_) => {
212                Self::CoreVerificationError(CoreVerifierError::from(e))
213            }
214            MultiSignatureError::SignatureInfinity(_) => {
215                Self::CoreVerificationError(CoreVerifierError::from(e))
216            }
217            MultiSignatureError::VerificationKeyInfinity(_) => {
218                Self::CoreVerificationError(CoreVerifierError::from(e))
219            }
220        }
221    }
222}
223
224impl<D: Digest + FixedOutput> From<CoreVerifierError> for StmAggregateSignatureError<D> {
225    fn from(e: CoreVerifierError) -> Self {
226        Self::CoreVerificationError(e)
227    }
228}
229
230impl<D: Digest + FixedOutput> From<StmSignatureError> for StmAggregateSignatureError<D> {
231    fn from(e: StmSignatureError) -> Self {
232        match e {
233            StmSignatureError::SerializationError => Self::SerializationError,
234            _ => unreachable!(),
235        }
236    }
237}
238
239/// Errors which can be outputted by key registration.
240#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)]
241pub enum RegisterError {
242    /// This key has already been registered by a participant
243    #[error("This key has already been registered.")]
244    KeyRegistered(Box<VerificationKey>),
245
246    /// Verification key is the infinity
247    #[error("Verification key is the infinity")]
248    VerificationKeyInfinity(Box<VerificationKey>),
249
250    /// The supplied key is not valid
251    #[error("The verification of correctness of the supplied key is invalid.")]
252    KeyInvalid(Box<VerificationKeyPoP>),
253
254    /// Serialization error
255    #[error("Serialization error")]
256    SerializationError,
257
258    /// UnregisteredInitializer error
259    #[error("Initializer not registered. Cannot participate as a signer.")]
260    UnregisteredInitializer,
261}
262
263impl From<MultiSignatureError> for RegisterError {
264    fn from(e: MultiSignatureError) -> Self {
265        match e {
266            MultiSignatureError::SerializationError => Self::SerializationError,
267            MultiSignatureError::KeyInvalid(e) => Self::KeyInvalid(e),
268            MultiSignatureError::VerificationKeyInfinity(e) => Self::VerificationKeyInfinity(e),
269            _ => unreachable!(),
270        }
271    }
272}
273
274/// If verifying a single signature, the signature should be provided. If verifying a multi-sig,
275/// no need to provide the signature
276pub(crate) fn blst_err_to_mithril(
277    e: BLST_ERROR,
278    sig: Option<Signature>,
279    key: Option<VerificationKey>,
280) -> Result<(), MultiSignatureError> {
281    match e {
282        BLST_ERROR::BLST_SUCCESS => Ok(()),
283        BLST_ERROR::BLST_PK_IS_INFINITY => {
284            if let Some(s) = sig {
285                return Err(MultiSignatureError::SignatureInfinity(s));
286            }
287            if let Some(vk) = key {
288                return Err(MultiSignatureError::VerificationKeyInfinity(Box::new(vk)));
289            }
290            Err(MultiSignatureError::SerializationError)
291        }
292        BLST_ERROR::BLST_VERIFY_FAIL => {
293            if let Some(s) = sig {
294                Err(MultiSignatureError::SignatureInvalid(s))
295            } else {
296                Err(MultiSignatureError::AggregateSignatureInvalid)
297            }
298        }
299        _ => Err(MultiSignatureError::SerializationError),
300    }
301}