mithril_stm/
error.rs

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