bbs/
errors.rs

1use crate::pok_sig::PoKOfSignatureProofStatus;
2use crate::pok_vc::PoKVCError;
3use failure::{Backtrace, Context, Fail};
4#[cfg(feature = "wasm")]
5use wasm_bindgen::prelude::*;
6
7/// Convenience importing module
8pub mod prelude {
9    pub use super::{BBSError, BBSErrorExt, BBSErrorKind};
10}
11
12/// The kinds of errors that can be generated
13#[derive(Debug, Fail, Clone)]
14pub enum BBSErrorKind {
15    /// Error during key generation
16    #[fail(display = "Key Generation Error")]
17    KeyGenError,
18    /// When there are more messages than public key generators
19    #[fail(
20        display = "Public key to message mismatch. Expected {}, found {}",
21        0, 0
22    )]
23    PublicKeyGeneratorMessageCountMismatch(usize, usize),
24    /// When the signature is the incorrect size when calling from_bytes
25    #[fail(display = "Signature incorrect size. Expected 193, found {}", 0)]
26    SignatureIncorrectSize(usize),
27    /// When the signature bytes are not a valid curve point
28    #[fail(display = "Signature cannot be loaded due to a bad value")]
29    SignatureValueIncorrectSize,
30    /// When the public key bytes are not valid curve points
31    #[fail(display = "Malformed public key")]
32    MalformedPublicKey,
33    /// Error during proof of knowledge generation
34    #[fail(display = "Error from PoKVC module {:?}", msg)]
35    PoKVCError {
36        /// The error message
37        msg: String,
38    },
39    /// Incorrect number of bytes passed to from_bytes methods
40    #[fail(display = "Invalid number of bytes. Expected {}, found {}", 0, 0)]
41    InvalidNumberOfBytes(usize, usize),
42    /// Failed signature poof of knowledge
43    #[fail(display = "The proof failed due to {}", status)]
44    InvalidProof {
45        /// The status of the invalid proof
46        status: PoKOfSignatureProofStatus,
47    },
48    /// A Generic error
49    #[fail(display = "{:?}", msg)]
50    GeneralError {
51        /// The error message
52        msg: String,
53    },
54}
55
56/// Wrapper to hold the kind of error and a backtrace
57#[derive(Debug)]
58pub struct BBSError {
59    inner: Context<BBSErrorKind>,
60}
61
62impl Fail for BBSError {
63    fn cause(&self) -> Option<&dyn Fail> {
64        self.inner.cause()
65    }
66
67    fn backtrace(&self) -> Option<&Backtrace> {
68        self.inner.backtrace()
69    }
70}
71
72impl BBSError {
73    /// Convert from a kind and a static string
74    pub fn from_msg<D>(kind: BBSErrorKind, msg: D) -> Self
75    where
76        D: std::fmt::Display + std::fmt::Debug + Send + Sync + 'static,
77    {
78        BBSError {
79            inner: Context::new(msg).context(kind),
80        }
81    }
82
83    /// Get the inner error kind
84    pub fn from_kind(kind: BBSErrorKind) -> Self {
85        BBSError {
86            inner: Context::new("").context(kind),
87        }
88    }
89
90    /// Get the inner error kind
91    pub fn kind(&self) -> BBSErrorKind {
92        self.inner.get_context().clone()
93    }
94}
95
96impl From<BBSErrorKind> for BBSError {
97    fn from(error: BBSErrorKind) -> Self {
98        BBSError::from_kind(error)
99    }
100}
101
102impl From<std::io::Error> for BBSError {
103    fn from(err: std::io::Error) -> BBSError {
104        BBSError::from_kind(BBSErrorKind::GeneralError {
105            msg: format!("{:?}", err),
106        })
107    }
108}
109
110impl std::fmt::Display for BBSError {
111    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
112        let mut first = true;
113
114        for cause in Fail::iter_chain(&self.inner) {
115            if first {
116                first = false;
117                writeln!(f, "Error: {}", cause)?;
118            } else {
119                writeln!(f, "Caused by: {}", cause)?;
120            }
121        }
122
123        Ok(())
124    }
125}
126
127#[cfg(feature = "wasm")]
128impl From<BBSError> for JsValue {
129    fn from(error: BBSError) -> Self {
130        JsValue::from_str(&format!("{}", error))
131    }
132}
133
134#[cfg(feature = "wasm")]
135impl From<JsValue> for BBSError {
136    fn from(js: JsValue) -> Self {
137        if js.is_string() {
138            BBSError::from(BBSErrorKind::GeneralError {
139                msg: js.as_string().unwrap(),
140            })
141        } else {
142            BBSError::from(BBSErrorKind::GeneralError {
143                msg: "".to_string(),
144            })
145        }
146    }
147}
148
149#[cfg(feature = "wasm")]
150impl From<serde_wasm_bindgen::Error> for BBSError {
151    fn from(err: serde_wasm_bindgen::Error) -> Self {
152        BBSError::from(BBSErrorKind::GeneralError {
153            msg: format!("{:?}", err),
154        })
155    }
156}
157
158#[cfg(feature = "wasm")]
159impl From<BBSError> for serde_wasm_bindgen::Error {
160    fn from(err: BBSError) -> Self {
161        serde_wasm_bindgen::Error::new(err)
162    }
163}
164
165/// Generate an error from a kind and static string
166pub fn err_msg<D>(kind: BBSErrorKind, msg: D) -> BBSError
167where
168    D: std::fmt::Display + std::fmt::Debug + Send + Sync + 'static,
169{
170    BBSError::from_msg(kind, msg)
171}
172
173impl From<Context<BBSErrorKind>> for BBSError {
174    fn from(inner: Context<BBSErrorKind>) -> BBSError {
175        BBSError { inner }
176    }
177}
178
179/// Extension methods for `Error`.
180pub trait BBSErrorExt {
181    /// convert self with kind and static string into an error
182    fn to_bbs<D>(self, kind: BBSErrorKind, msg: D) -> BBSError
183    where
184        D: std::fmt::Display + Send + Sync + 'static;
185}
186
187impl<E> BBSErrorExt for E
188where
189    E: Fail,
190{
191    fn to_bbs<D>(self, kind: BBSErrorKind, msg: D) -> BBSError
192    where
193        D: std::fmt::Display + Send + Sync + 'static,
194    {
195        self.context(msg).context(kind).into()
196    }
197}
198
199impl From<PoKVCError> for BBSError {
200    fn from(err: PoKVCError) -> Self {
201        let message = format!(
202            "PoKVCError: {}",
203            Fail::iter_causes(&err)
204                .map(|e| e.to_string())
205                .collect::<String>()
206        );
207
208        BBSError::from_kind(BBSErrorKind::PoKVCError { msg: message })
209    }
210}