diff --git a/ethcore/src/types/executed.rs b/ethcore/src/types/executed.rs index f03a1c26b..fc0f864ed 100644 --- a/ethcore/src/types/executed.rs +++ b/ethcore/src/types/executed.rs @@ -21,6 +21,7 @@ use util::Bytes; use trace::Trace; use types::log_entry::LogEntry; use ipc::binary::BinaryConvertError; +use std::fmt; use std::mem; use std::collections::VecDeque; @@ -104,6 +105,39 @@ pub enum ExecutionError { TransactionMalformed(String), } +impl fmt::Display for ExecutionError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::ExecutionError::*; + + let msg = match *self { + NotEnoughBaseGas { required, got } => { + format!("Not enough base gas. {} is required, but only {} paid", + required, got) + } + BlockGasLimitReached { gas_limit, gas_used, gas } => { + format!("Block gas limit reached. The limit is {}, {} has \ + already been used, and {} more is required", + gas_limit, gas_used, gas) + } + InvalidNonce { expected, got } => { + format!("Invalid transaction nonce: expected {}, found {}", + expected, got) + } + NotEnoughCash { required, got } => { + format!("Cost of transaction exceeds sender balance. {} is required \ + but the sender only has {}", required, got) + } + Internal => { + "Internal evm error".into() + } + TransactionMalformed(ref err) => { + format!("Malformed transaction: {}", err) + } + }; + + f.write_fmt(format_args!("Transaction execution error ({}).", msg)) + } +} /// Transaction execution result. pub type ExecutionResult = Result; diff --git a/util/src/crypto.rs b/util/src/crypto.rs index 040db3bca..3eff70717 100644 --- a/util/src/crypto.rs +++ b/util/src/crypto.rs @@ -21,6 +21,7 @@ use bytes::*; use secp256k1::{key, Secp256k1}; use rand::os::OsRng; use sha3::Hashable; +use std::fmt; /// Secret key for secp256k1 EC operations. 256 bit generic "hash" data. pub type Secret = H256; @@ -69,6 +70,20 @@ pub enum CryptoError { Io(::std::io::Error), } +impl fmt::Display for CryptoError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let msg = match *self { + CryptoError::InvalidSecret => "Invalid secret key".into(), + CryptoError::InvalidPublic => "Invalid public key".into(), + CryptoError::InvalidSignature => "Invalid EC signature".into(), + CryptoError::InvalidMessage => "Invalid AES message".into(), + CryptoError::Io(ref err) => format!("I/O error: {}", err), + }; + + f.write_fmt(format_args!("Crypto error ({})", msg)) + } +} + impl From<::secp256k1::Error> for CryptoError { fn from(e: ::secp256k1::Error) -> CryptoError { match e { diff --git a/util/src/io/mod.rs b/util/src/io/mod.rs index 40cdbc368..93805a46a 100644 --- a/util/src/io/mod.rs +++ b/util/src/io/mod.rs @@ -56,6 +56,7 @@ mod service; mod worker; use mio::{EventLoop, Token}; +use std::fmt; #[derive(Debug)] /// IO Error @@ -64,6 +65,16 @@ pub enum IoError { Mio(::std::io::Error), } +impl fmt::Display for IoError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // just defer to the std implementation for now. + // we can refine the formatting when more variants are added. + match *self { + IoError::Mio(ref std_err) => std_err.fmt(f) + } + } +} + impl From<::mio::NotifyError>> for IoError where Message: Send + Clone { fn from(_err: ::mio::NotifyError>) -> IoError { IoError::Mio(::std::io::Error::new(::std::io::ErrorKind::ConnectionAborted, "Network IO notification error")) diff --git a/util/src/network/error.rs b/util/src/network/error.rs index 31e1d785b..e4705fc9e 100644 --- a/util/src/network/error.rs +++ b/util/src/network/error.rs @@ -17,6 +17,7 @@ use io::IoError; use crypto::CryptoError; use rlp::*; +use std::fmt; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum DisconnectReason @@ -56,6 +57,30 @@ impl DisconnectReason { } } +impl fmt::Display for DisconnectReason { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::DisconnectReason::*; + + let msg = match *self { + DisconnectRequested => "disconnect requested", + TCPError => "TCP error", + BadProtocol => "bad protocol", + UselessPeer => "useless peer", + TooManyPeers => "too many peers", + DuplicatePeer => "duplicate peer", + IncompatibleProtocol => "incompatible protocol", + NullIdentity => "null identity", + ClientQuit => "client quit", + UnexpectedIdentity => "unexpected identity", + LocalIdentity => "local identity", + PingTimeout => "ping timeout", + Unknown => "unknown", + }; + + f.write_str(msg) + } +} + #[derive(Debug)] /// Network error. pub enum NetworkError { @@ -73,6 +98,23 @@ pub enum NetworkError { Io(IoError), } +impl fmt::Display for NetworkError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::NetworkError::*; + + let msg = match *self { + Auth => "Authentication failure".into(), + BadProtocol => "Bad protocol".into(), + Expired => "Expired message".into(), + PeerNotFound => "Peer not found".into(), + Disconnect(ref reason) => format!("Peer disconnected: {}", reason), + Io(ref err) => format!("Socket I/O error: {}", err), + }; + + f.write_fmt(format_args!("Network error ({})", msg)) + } +} + impl From for NetworkError { fn from(_err: DecoderError) -> NetworkError { NetworkError::Auth