bitcoin_wallet/
error.rs

1//
2// Copyright 2018-2019 Tamas Blummer
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16//!
17//! # Wallet Error
18//!
19//! Modules of this library use this error class to indicate problems.
20//!
21
22use std::{convert, error, fmt, io};
23
24use bitcoin::util::bip32;
25use crypto::symmetriccipher;
26
27/// An error class to offer a unified error interface upstream
28pub enum Error {
29    /// Unsupported
30    Unsupported(&'static str),
31    /// mnemonic related error
32    Mnemonic(&'static str),
33    /// wrong passphrase
34    Passphrase,
35    /// wrong network
36    Network,
37    /// Network IO error
38    IO(io::Error),
39    /// key derivation error
40    KeyDerivation(bip32::Error),
41    /// sekp256k1 error
42    SecpError(secp256k1::Error),
43    /// cipher error
44    SymmetricCipherError(symmetriccipher::SymmetricCipherError),
45}
46
47impl error::Error for Error {
48    fn description(&self) -> &str {
49        match *self {
50            Error::Passphrase => "wrong passphrase",
51            Error::Network => "wrong network",
52            Error::Unsupported(s) => s,
53            Error::Mnemonic(s) => s,
54            Error::IO(ref err) => err.description(),
55            Error::KeyDerivation(ref err) => err.description(),
56            Error::SecpError(ref err) => err.description(),
57            Error::SymmetricCipherError(ref err) => match err {
58                &symmetriccipher::SymmetricCipherError::InvalidLength => "invalid length",
59                &symmetriccipher::SymmetricCipherError::InvalidPadding => "invalid padding",
60            },
61        }
62    }
63
64    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
65        match *self {
66            Error::Network => None,
67            Error::Passphrase => None,
68            Error::Unsupported(_) => None,
69            Error::Mnemonic(_) => None,
70            Error::IO(ref err) => Some(err),
71            Error::KeyDerivation(ref err) => Some(err),
72            Error::SecpError(ref err) => Some(err),
73            Error::SymmetricCipherError(_) => None,
74        }
75    }
76}
77
78impl fmt::Display for Error {
79    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80        match *self {
81            // Both underlying errors already impl `Display`, so we defer to
82            // their implementations.
83            Error::Passphrase => write!(f, "wrong passphrase"),
84            Error::Network => write!(f, "wrong network"),
85            Error::Unsupported(ref s) => write!(f, "Unsupported: {}", s),
86            Error::Mnemonic(ref s) => write!(f, "Mnemonic: {}", s),
87            Error::IO(ref err) => write!(f, "IO error: {}", err),
88            Error::KeyDerivation(ref err) => write!(f, "BIP32 error: {}", err),
89            Error::SecpError(ref err) => write!(f, "Secp256k1 error: {}", err),
90            Error::SymmetricCipherError(ref err) => write!(
91                f,
92                "Cipher error: {}",
93                match err {
94                    &symmetriccipher::SymmetricCipherError::InvalidLength => "invalid length",
95                    &symmetriccipher::SymmetricCipherError::InvalidPadding => "invalid padding",
96                }
97            ),
98        }
99    }
100}
101
102impl fmt::Debug for Error {
103    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104        (self as &dyn fmt::Display).fmt(f)
105    }
106}
107
108impl convert::From<Error> for io::Error {
109    fn from(err: Error) -> io::Error {
110        match err {
111            Error::IO(e) => e,
112            _ => {
113                use std::error::Error;
114                io::Error::new(io::ErrorKind::Other, err.description())
115            }
116        }
117    }
118}
119
120impl convert::From<io::Error> for Error {
121    fn from(err: io::Error) -> Error {
122        Error::IO(err)
123    }
124}
125
126impl convert::From<bip32::Error> for Error {
127    fn from(err: bip32::Error) -> Error {
128        Error::KeyDerivation(err)
129    }
130}
131
132impl convert::From<symmetriccipher::SymmetricCipherError> for Error {
133    fn from(err: symmetriccipher::SymmetricCipherError) -> Error {
134        Error::SymmetricCipherError(err)
135    }
136}
137
138impl convert::From<secp256k1::Error> for Error {
139    fn from(err: secp256k1::Error) -> Error {
140        Error::SecpError(err)
141    }
142}