use bitcoin::consensus::encode;
use bitcoin::util;
use bitcoin::util::bip158;
use hammersbald;
use std::convert;
use std::fmt;
use std::io;
pub enum Error {
SpvBadTarget,
SpvBadProofOfWork,
UnconnectedHeader,
NoTip,
NoPeers,
UnknownUTXO,
BadMerkleRoot,
Downstream(String),
IO(io::Error),
Util(util::Error),
Serialize(encode::Error),
Hammersbald(hammersbald::Error),
Handshake,
Lost(String)
}
impl std::error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::SpvBadTarget => "bad proof of work target",
Error::SpvBadProofOfWork => "bad proof of work",
Error::UnconnectedHeader => "unconnected header",
Error::NoTip => "no chain tip found",
Error::UnknownUTXO => "unknown utxo",
Error::NoPeers => "no peers",
Error::BadMerkleRoot => "merkle root of header does not match transaction list",
Error::Downstream(ref s) => s,
Error::IO(ref err) => err.description(),
Error::Util(ref err) => err.description(),
Error::Hammersbald(ref err) => err.description(),
Error::Serialize(ref err) => err.description(),
Error::Handshake => "handshake",
Error::Lost(ref s) => s
}
}
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match *self {
Error::SpvBadTarget => None,
Error::SpvBadProofOfWork => None,
Error::UnconnectedHeader => None,
Error::NoTip => None,
Error::NoPeers => None,
Error::UnknownUTXO => None,
Error::Downstream(_) => None,
Error::BadMerkleRoot => None,
Error::IO(ref err) => Some(err),
Error::Util(ref err) => Some(err),
Error::Hammersbald(ref err) => Some(err),
Error::Serialize(ref err) => Some(err),
Error::Handshake => None,
Error::Lost(_) => None
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::SpvBadTarget |
Error::SpvBadProofOfWork |
Error::UnconnectedHeader |
Error::NoTip |
Error::NoPeers | Error::BadMerkleRoot |
Error::Handshake |
Error::UnknownUTXO => {
use std::error::Error;
write!(f, "{}", self.description())
},
Error::Lost(ref s) |
Error::Downstream(ref s) => write!(f, "{}", s),
Error::IO(ref err) => write!(f, "IO error: {}", err),
Error::Util(ref err) => write!(f, "Util error: {}", err),
Error::Hammersbald(ref err) => write!(f, "Hammersbald error: {}", err),
Error::Serialize(ref err) => write!(f, "Serialize error: {}", err),
}
}
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
(self as &dyn fmt::Display).fmt(f)
}
}
impl convert::From<Error> for io::Error {
fn from(err: Error) -> io::Error {
match err {
Error::IO(e) => e,
_ => {
use std::error::Error;
io::Error::new(io::ErrorKind::Other, err.description())
}
}
}
}
impl convert::From<io::Error> for Error {
fn from(err: io::Error) -> Error {
Error::IO(err)
}
}
impl convert::From<util::Error> for Error {
fn from(err: util::Error) -> Error {
Error::Util(err)
}
}
impl convert::From<hammersbald::Error> for Error {
fn from(err: hammersbald::Error) -> Error {
Error::Hammersbald(err)
}
}
impl convert::From<encode::Error> for Error {
fn from(err: encode::Error) -> Error {
Error::Serialize(err)
}
}
impl convert::From<Box<dyn std::error::Error>> for Error {
fn from(err: Box<dyn std::error::Error>) -> Self {
Error::Downstream(err.description().to_owned())
}
}
impl convert::From<bip158::Error> for Error {
fn from(err: bip158::Error) -> Self {
match err {
bip158::Error::Io(io) => Error::IO(io),
bip158::Error::UtxoMissing(_) => Error::UnknownUTXO
}
}
}