use std::error;
use std::fmt;
use std::result;
use bitcoin;
use bitcoin::util::base58;
use bitcoin_hashes::sha256d;
use protobuf::error::ProtobufError;
use secp256k1;
use crate::client::InteractionType;
use crate::protos;
use crate::transport;
#[derive(Debug)]
pub enum Error {
NoDeviceFound,
DeviceNotUnique,
TransportConnect(transport::error::Error),
TransportBeginSession(transport::error::Error),
TransportEndSession(transport::error::Error),
TransportSendMessage(transport::error::Error),
TransportReceiveMessage(transport::error::Error),
UnexpectedMessageType(protos::MessageType), Protobuf(ProtobufError),
FailureResponse(protos::Failure),
UnexpectedInteractionRequest(InteractionType),
Base58(base58::Error),
UnsupportedNetwork,
InvalidEntropy,
TxRequestInvalidIndex(usize),
TxRequestUnknownTxid(sha256d::Hash),
PsbtMissingInputTx(sha256d::Hash),
MalformedTxRequest(protos::TxRequest),
InvalidPsbt(String),
BitcoinEncode(bitcoin::consensus::encode::Error),
Secp256k1(secp256k1::Error),
}
impl From<ProtobufError> for Error {
fn from(e: ProtobufError) -> Error {
Error::Protobuf(e)
}
}
impl From<base58::Error> for Error {
fn from(e: base58::Error) -> Error {
Error::Base58(e)
}
}
impl From<bitcoin::consensus::encode::Error> for Error {
fn from(e: bitcoin::consensus::encode::Error) -> Error {
Error::BitcoinEncode(e)
}
}
impl From<secp256k1::Error> for Error {
fn from(e: secp256k1::Error) -> Error {
Error::Secp256k1(e)
}
}
impl error::Error for Error {
fn cause(&self) -> Option<&dyn error::Error> {
match *self {
Error::TransportConnect(ref e) => Some(e),
Error::TransportBeginSession(ref e) => Some(e),
Error::TransportEndSession(ref e) => Some(e),
Error::TransportSendMessage(ref e) => Some(e),
Error::TransportReceiveMessage(ref e) => Some(e),
Error::Base58(ref e) => Some(e),
_ => None,
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::NoDeviceFound => write!(f, "Trezor device not found"),
Error::DeviceNotUnique => write!(f, "multiple Trezor devices found"),
Error::TransportConnect(ref e) => write!(f, "transport connect: {}", e),
Error::TransportBeginSession(ref e) => write!(f, "transport beginning session: {}", e),
Error::TransportEndSession(ref e) => write!(f, "transport ending session: {}", e),
Error::TransportSendMessage(ref e) => write!(f, "transport sending message: {}", e),
Error::TransportReceiveMessage(ref e) => {
write!(f, "transport receiving message: {}", e)
}
Error::UnexpectedMessageType(ref t) => {
write!(f, "received unexpected message type: {:?}", t)
}
Error::Protobuf(ref e) => write!(f, "protobuf: {}", e),
Error::FailureResponse(ref e) => write!(
f,
r#"failure received: code={:?} message="{}""#,
e.get_code(),
e.get_message()
),
Error::UnexpectedInteractionRequest(ref r) => {
write!(f, "unexpected interaction request: {:?}", r)
}
Error::Base58(ref e) => fmt::Display::fmt(e, f),
Error::UnsupportedNetwork => write!(f, "given network is not supported"),
Error::InvalidEntropy => write!(f, "provided entropy is not 32 bytes"),
Error::TxRequestInvalidIndex(ref i) => {
write!(f, "device referenced non-existing input or output index: {}", i)
}
Error::TxRequestUnknownTxid(ref txid) => {
write!(f, "device referenced unknown TXID: {}", txid)
}
Error::PsbtMissingInputTx(ref txid) => write!(f, "PSBT missing input tx: {}", txid),
Error::MalformedTxRequest(ref m) => write!(f, "malformed TxRequest: {:?}", m),
Error::InvalidPsbt(ref m) => write!(f, "invalid PSBT: {}", m),
Error::BitcoinEncode(ref e) => write!(f, "bitcoin encoding error: {}", e),
Error::Secp256k1(ref e) => write!(f, "ECDSA signature error: {}", e),
}
}
}
pub type Result<T> = result::Result<T, Error>;