From bf55db4c7e3b4298597aec868713428a18d53e4d Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 17 Jun 2019 07:44:59 +0100 Subject: [PATCH] Die error_chain, die (#10747) * Replace error chain for network error * Fix usages and add manual From impls * OnDemand Error and remove remaining dependencies * Die error_chain, die. * DIE * Hasta la vista, baby --- Cargo.lock | 5 +- ethcore/light/Cargo.toml | 1 + ethcore/light/src/client/header_chain.rs | 4 +- ethcore/light/src/lib.rs | 3 +- ethcore/light/src/on_demand/mod.rs | 43 +++-- ethcore/private-tx/src/lib.rs | 4 - ethcore/service/Cargo.toml | 2 +- ethcore/service/src/error.rs | 26 +-- ethcore/service/src/lib.rs | 5 +- ethcore/service/src/service.rs | 4 +- ethcore/src/lib.rs | 4 - ethcore/sync/src/api.rs | 6 +- ethcore/sync/src/blocks.rs | 8 +- ethcore/sync/src/lib.rs | 2 +- miner/src/lib.rs | 2 - miner/src/pool/verifier.rs | 22 +-- parity/configuration.rs | 2 +- parity/helpers.rs | 2 +- rpc/src/v1/helpers/errors.rs | 17 +- util/network-devp2p/src/connection.rs | 12 +- util/network-devp2p/src/discovery.rs | 8 +- util/network-devp2p/src/handshake.rs | 10 +- util/network-devp2p/src/host.rs | 8 +- util/network-devp2p/src/lib.rs | 2 - util/network-devp2p/src/node_table.rs | 18 +-- util/network-devp2p/src/session.rs | 18 +-- util/network/Cargo.toml | 2 +- util/network/src/error.rs | 193 ++++++++++++----------- util/network/src/lib.rs | 6 +- 29 files changed, 214 insertions(+), 225 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c3a00e53f..1d884f503 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1013,6 +1013,7 @@ version = "1.12.0" dependencies = [ "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "common-types 0.1.0", + "derive_more 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", "ethcore-blockchain 0.1.0", @@ -1106,7 +1107,7 @@ name = "ethcore-network" version = "1.12.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-io 1.12.0", "ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", @@ -1243,7 +1244,7 @@ name = "ethcore-service" version = "0.1.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", "ethcore-blockchain 0.1.0", "ethcore-db 0.1.0", diff --git a/ethcore/light/Cargo.toml b/ethcore/light/Cargo.toml index 8f76651d0..fe0901dd3 100644 --- a/ethcore/light/Cargo.toml +++ b/ethcore/light/Cargo.toml @@ -10,6 +10,7 @@ authors = ["Parity Technologies "] log = "0.4" parity-bytes = "0.1" common-types = { path = "../types" } +derive_more = "0.14.0" ethcore = { path = ".."} ethcore-db = { path = "../db" } ethcore-blockchain = { path = "../blockchain" } diff --git a/ethcore/light/src/client/header_chain.rs b/ethcore/light/src/client/header_chain.rs index 2bcf53cb9..be52185bc 100644 --- a/ethcore/light/src/client/header_chain.rs +++ b/ethcore/light/src/client/header_chain.rs @@ -260,7 +260,7 @@ impl HeaderChain { let best_block = { let era = match candidates.get(&curr.best_num) { Some(era) => era, - None => bail!("Database corrupt: highest block referenced but no data."), + None => return Err("Database corrupt: highest block referenced but no data.".into()), }; let best = &era.candidates[0]; @@ -582,7 +582,7 @@ impl HeaderChain { } else { let msg = format!("header of block #{} not found in DB ; database in an \ inconsistent state", h_num); - bail!(msg); + return Err(msg.into()); }; let decoded = header.decode().expect("decoding db value failed"); diff --git a/ethcore/light/src/lib.rs b/ethcore/light/src/lib.rs index 31deecf31..5221830af 100644 --- a/ethcore/light/src/lib.rs +++ b/ethcore/light/src/lib.rs @@ -86,8 +86,7 @@ extern crate keccak_hash as hash; extern crate triehash_ethereum as triehash; extern crate kvdb; extern crate memory_cache; -#[macro_use] -extern crate error_chain; +extern crate derive_more; #[cfg(test)] extern crate kvdb_memorydb; diff --git a/ethcore/light/src/on_demand/mod.rs b/ethcore/light/src/on_demand/mod.rs index 7d1f4fabf..b54257c27 100644 --- a/ethcore/light/src/on_demand/mod.rs +++ b/ethcore/light/src/on_demand/mod.rs @@ -66,32 +66,31 @@ pub const DEFAULT_NUM_CONSECUTIVE_FAILED_REQUESTS: usize = 1; /// OnDemand related errors pub mod error { - // Silence: `use of deprecated item 'std::error::Error::cause': replaced by Error::source, which can support downcasting` - // https://github.com/paritytech/parity-ethereum/issues/10302 - #![allow(deprecated)] - use futures::sync::oneshot::Canceled; - error_chain! { + /// OnDemand Error + #[derive(Debug, derive_more::Display, derive_more::From)] + pub enum Error { + /// Canceled oneshot channel + ChannelCanceled(Canceled), + /// Timeout bad response + BadResponse(String), + /// OnDemand requests limit exceeded + #[display(fmt = "OnDemand request maximum backoff iterations exceeded")] + RequestLimit, + } - foreign_links { - ChannelCanceled(Canceled) #[doc = "Canceled oneshot channel"]; - } - - errors { - #[doc = "Timeout bad response"] - BadResponse(err: String) { - description("Max response evaluation time exceeded") - display("{}", err) - } - - #[doc = "OnDemand requests limit exceeded"] - RequestLimit { - description("OnDemand request maximum backoff iterations exceeded") - display("OnDemand request maximum backoff iterations exceeded") + impl std::error::Error for Error { + fn source(&self) -> Option<&(std::error::Error + 'static)> { + match self { + Error::ChannelCanceled(err) => Some(err), + _ => None, } } } + + /// OnDemand Result + pub type Result = std::result::Result; } /// Public interface for performing network requests `OnDemand` @@ -272,7 +271,7 @@ impl Pending { response_err ); - let err = self::error::ErrorKind::BadResponse(err); + let err = self::error::Error::BadResponse(err); if self.sender.send(Err(err.into())).is_err() { debug!(target: "on_demand", "Dropped oneshot channel receiver on no response"); } @@ -280,7 +279,7 @@ impl Pending { // returning a peer discovery timeout during query attempts fn request_limit_reached(self) { - let err = self::error::ErrorKind::RequestLimit; + let err = self::error::Error::RequestLimit; if self.sender.send(Err(err.into())).is_err() { debug!(target: "on_demand", "Dropped oneshot channel receiver on time out"); } diff --git a/ethcore/private-tx/src/lib.rs b/ethcore/private-tx/src/lib.rs index b5d36d359..b9de9e167 100644 --- a/ethcore/private-tx/src/lib.rs +++ b/ethcore/private-tx/src/lib.rs @@ -16,10 +16,6 @@ //! Private transactions module. -// Recursion limit required because of -// error_chain foreign_links. -#![recursion_limit="256"] - mod encryptor; mod key_server_keys; mod private_transactions; diff --git a/ethcore/service/Cargo.toml b/ethcore/service/Cargo.toml index 218d4f475..be9c3d453 100644 --- a/ethcore/service/Cargo.toml +++ b/ethcore/service/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] [dependencies] ansi_term = "0.10" -error-chain = { version = "0.12", default-features = false } +derive_more = "0.14.0" ethcore = { path = ".." } ethcore-blockchain = { path = "../blockchain" } ethcore-io = { path = "../../util/io" } diff --git a/ethcore/service/src/error.rs b/ethcore/service/src/error.rs index c73cb0dfc..b2787e978 100644 --- a/ethcore/service/src/error.rs +++ b/ethcore/service/src/error.rs @@ -14,18 +14,26 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -// Silence: `use of deprecated item 'std::error::Error::cause': replaced by Error::source, which can support downcasting` -// https://github.com/paritytech/parity-ethereum/issues/10302 -#![allow(deprecated)] - use ethcore; use io; use ethcore_private_tx; -error_chain! { - foreign_links { - Ethcore(ethcore::error::Error); - IoError(io::IoError); - PrivateTransactions(ethcore_private_tx::Error); +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// Ethcore Error + Ethcore(ethcore::error::Error), + /// Io Error + IoError(io::IoError), + /// Private Transactions Error + PrivateTransactions(ethcore_private_tx::Error), +} + +impl std::error::Error for Error { + fn source(&self) -> Option<&(std::error::Error + 'static)> { + match self { + Error::Ethcore(err) => Some(err), + Error::IoError(err) => Some(err), + Error::PrivateTransactions(err) => Some(err), + } } } diff --git a/ethcore/service/src/lib.rs b/ethcore/service/src/lib.rs index 7828fff8b..67292e1d8 100644 --- a/ethcore/service/src/lib.rs +++ b/ethcore/service/src/lib.rs @@ -23,8 +23,7 @@ extern crate ethcore_sync as sync; extern crate ethereum_types; extern crate kvdb; -#[macro_use] -extern crate error_chain; +extern crate derive_more; #[macro_use] extern crate log; #[macro_use] @@ -42,5 +41,5 @@ mod stop_guard; #[cfg(test)] extern crate kvdb_rocksdb; -pub use error::{Error, ErrorKind}; +pub use error::Error; pub use service::{ClientService, PrivateTxService}; diff --git a/ethcore/service/src/service.rs b/ethcore/service/src/service.rs index c16a07189..10909f985 100644 --- a/ethcore/service/src/service.rs +++ b/ethcore/service/src/service.rs @@ -59,7 +59,7 @@ impl PrivateTxHandler for PrivateTxService { Ok(import_result) => Ok(import_result), Err(err) => { warn!(target: "privatetx", "Unable to import private transaction packet: {}", err); - bail!(err.to_string()) + return Err(err.to_string()) } } } @@ -69,7 +69,7 @@ impl PrivateTxHandler for PrivateTxService { Ok(import_result) => Ok(import_result), Err(err) => { warn!(target: "privatetx", "Unable to import signed private transaction packet: {}", err); - bail!(err.to_string()) + return Err(err.to_string()) } } } diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 87a1b4a0b..a5f3adf58 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -54,10 +54,6 @@ //! cargo build --release //! ``` -// Recursion limit required because of -// error_chain foreign_links. -#![recursion_limit="128"] - extern crate ansi_term; extern crate bn; extern crate byteorder; diff --git a/ethcore/sync/src/api.rs b/ethcore/sync/src/api.rs index ddb7542b7..7aa9e71ae 100644 --- a/ethcore/sync/src/api.rs +++ b/ethcore/sync/src/api.rs @@ -22,7 +22,7 @@ use std::time::Duration; use bytes::Bytes; use devp2p::NetworkService; use network::{NetworkProtocolHandler, NetworkContext, PeerId, ProtocolId, - NetworkConfiguration as BasicNetworkConfiguration, NonReservedPeerMode, Error, ErrorKind, + NetworkConfiguration as BasicNetworkConfiguration, NonReservedPeerMode, Error, ConnectionFilter}; use network::client_version::ClientVersion; @@ -593,7 +593,7 @@ impl ChainNotify for EthSync { match self.network.start() { Err((err, listen_address)) => { match err.into() { - ErrorKind::Io(ref e) if e.kind() == io::ErrorKind::AddrInUse => { + Error::Io(ref e) if e.kind() == io::ErrorKind::AddrInUse => { warn!("Network port {:?} is already in use, make sure that another instance of an Ethereum client is not running or change the port using the --port option.", listen_address.expect("Listen address is not set.")) }, err => warn!("Error starting network: {}", err), @@ -983,7 +983,7 @@ impl ManageNetwork for LightSync { match self.network.start() { Err((err, listen_address)) => { match err.into() { - ErrorKind::Io(ref e) if e.kind() == io::ErrorKind::AddrInUse => { + Error::Io(ref e) if e.kind() == io::ErrorKind::AddrInUse => { warn!("Network port {:?} is already in use, make sure that another instance of an Ethereum client is not running or change the port using the --port option.", listen_address.expect("Listen address is not set.")) }, err => warn!("Error starting network: {}", err), diff --git a/ethcore/sync/src/blocks.rs b/ethcore/sync/src/blocks.rs index 7d9ad428a..2ce2be333 100644 --- a/ethcore/sync/src/blocks.rs +++ b/ethcore/sync/src/blocks.rs @@ -435,13 +435,13 @@ impl BlockCollection { }, None => { warn!("Got body with no header {}", h); - Err(network::ErrorKind::BadProtocol.into()) + Err(network::Error::BadProtocol) } } } None => { trace!(target: "sync", "Ignored unknown/stale block body. tx_root = {:?}, uncles = {:?}", header_id.transactions_root, header_id.uncles); - Err(network::ErrorKind::BadProtocol.into()) + Err(network::Error::BadProtocol) } } } @@ -463,7 +463,7 @@ impl BlockCollection { }, None => { warn!("Got receipt with no header {}", h); - return Err(network::ErrorKind::BadProtocol.into()) + return Err(network::Error::BadProtocol) } } } @@ -471,7 +471,7 @@ impl BlockCollection { }, hash_map::Entry::Vacant(_) => { trace!(target: "sync", "Ignored unknown/stale block receipt {:?}", receipt_root); - Err(network::ErrorKind::BadProtocol.into()) + Err(network::Error::BadProtocol) } } } diff --git a/ethcore/sync/src/lib.rs b/ethcore/sync/src/lib.rs index aecf8fbb8..8ed8befc8 100644 --- a/ethcore/sync/src/lib.rs +++ b/ethcore/sync/src/lib.rs @@ -76,5 +76,5 @@ mod api; pub use api::*; pub use chain::{SyncStatus, SyncState}; pub use devp2p::validate_node_url; -pub use network::{NonReservedPeerMode, Error, ErrorKind, ConnectionFilter, ConnectionDirection}; +pub use network::{NonReservedPeerMode, Error, ConnectionFilter, ConnectionDirection}; pub use private_tx::{PrivateTxHandler, NoopPrivateTxHandler, SimplePrivateTxHandler}; diff --git a/miner/src/lib.rs b/miner/src/lib.rs index 5babec098..99f7a293b 100644 --- a/miner/src/lib.rs +++ b/miner/src/lib.rs @@ -41,8 +41,6 @@ extern crate ethabi_contract; #[macro_use] extern crate ethabi_derive; #[macro_use] -extern crate error_chain; -#[macro_use] extern crate log; #[macro_use] extern crate serde_derive; diff --git a/miner/src/pool/verifier.rs b/miner/src/pool/verifier.rs index 1fded3763..5c8273dd5 100644 --- a/miner/src/pool/verifier.rs +++ b/miner/src/pool/verifier.rs @@ -168,7 +168,7 @@ impl txpool::Verifier for Verifier txpool::Verifier for Verifier txpool::Verifier for Verifier txpool::Verifier for Verifier txpool::Verifier for Verifier txpool::Verifier for Verifier signed.into(), Err(err) => { debug!(target: "txqueue", "[{:?}] Rejected tx {:?}", hash, err); - bail!(err) + return Err(err) }, }, Transaction::Local(tx) => tx, @@ -256,7 +256,7 @@ impl txpool::Verifier for Verifier txpool::Verifier for Verifier txpool::Verifier for Verifier txpool::Verifier for Verifier txpool::Verifier for Verifier continue, - Some(sync::ErrorKind::AddressResolve(_)) => return Err(format!("Failed to resolve hostname of a boot node: {}", line)), + Some(sync::Error::AddressResolve(_)) => return Err(format!("Failed to resolve hostname of a boot node: {}", line)), Some(_) => return Err(format!("Invalid node address format given for a boot node: {}", line)), } } diff --git a/parity/helpers.rs b/parity/helpers.rs index 2f0046f22..61947d6bf 100644 --- a/parity/helpers.rs +++ b/parity/helpers.rs @@ -186,7 +186,7 @@ pub fn to_bootnodes(bootnodes: &Option) -> Result, String> { Some(ref x) if !x.is_empty() => x.split(',').map(|s| { match validate_node_url(s).map(Into::into) { None => Ok(s.to_owned()), - Some(sync::ErrorKind::AddressResolve(_)) => Err(format!("Failed to resolve hostname of a boot node: {}", s)), + Some(sync::Error::AddressResolve(_)) => Err(format!("Failed to resolve hostname of a boot node: {}", s)), Some(_) => Err(format!("Invalid node address format given for a boot node: {}", s)), } }).collect(), diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index 023f7df3c..3365c5490 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -25,7 +25,7 @@ use rlp::DecoderError; use types::transaction::Error as TransactionError; use ethcore_private_tx::Error as PrivateTransactionError; use vm::Error as VMError; -use light::on_demand::error::{Error as OnDemandError, ErrorKind as OnDemandErrorKind}; +use light::on_demand::error::{Error as OnDemandError}; use ethcore::client::BlockChainClient; use types::blockchain_info::BlockChainInfo; use v1::types::BlockNumber; @@ -555,10 +555,9 @@ pub fn filter_block_not_found(id: BlockId) -> Error { pub fn on_demand_error(err: OnDemandError) -> Error { match err { - OnDemandError(OnDemandErrorKind::ChannelCanceled(e), _) => on_demand_cancel(e), - OnDemandError(OnDemandErrorKind::RequestLimit, _) => timeout_new_peer(&err), - OnDemandError(OnDemandErrorKind::BadResponse(_), _) => max_attempts_reached(&err), - _ => on_demand_others(&err), + OnDemandError::ChannelCanceled(e) => on_demand_cancel(e), + OnDemandError::RequestLimit => timeout_new_peer(&err), + OnDemandError::BadResponse(_) => max_attempts_reached(&err), } } @@ -583,14 +582,6 @@ pub fn timeout_new_peer(err: &OnDemandError) -> Error { } } -pub fn on_demand_others(err: &OnDemandError) -> Error { - Error { - code: ErrorCode::ServerError(codes::UNKNOWN_ERROR), - message: err.to_string(), - data: None, - } -} - pub fn status_error(has_peers: bool) -> Error { if has_peers { no_work() diff --git a/util/network-devp2p/src/connection.rs b/util/network-devp2p/src/connection.rs index 424e7e176..218fa924a 100644 --- a/util/network-devp2p/src/connection.rs +++ b/util/network-devp2p/src/connection.rs @@ -37,7 +37,7 @@ use tiny_keccak::Keccak; use ethkey::crypto; use handshake::Handshake; use io::{IoContext, StreamToken}; -use network::{Error, ErrorKind}; +use network::Error; const ENCRYPTED_HEADER_LEN: usize = 32; const RECEIVE_PAYLOAD: Duration = Duration::from_secs(30); @@ -358,7 +358,7 @@ impl EncryptedConnection { let mut header = RlpStream::new(); let len = payload.len(); if len > MAX_PAYLOAD_SIZE { - bail!(ErrorKind::OversizedPacket); + return Err(Error::OversizedPacket); } header.append_raw(&[(len >> 16) as u8, (len >> 8) as u8, len as u8], 1); header.append_raw(&[0xc2u8, 0x80u8, 0x80u8], 1); @@ -386,14 +386,14 @@ impl EncryptedConnection { /// Decrypt and authenticate an incoming packet header. Prepare for receiving payload. fn read_header(&mut self, header: &[u8]) -> Result<(), Error> { if header.len() != ENCRYPTED_HEADER_LEN { - return Err(ErrorKind::Auth.into()); + return Err(Error::Auth); } EncryptedConnection::update_mac(&mut self.ingress_mac, &mut self.mac_encoder, &header[0..16]); let mac = &header[16..]; let mut expected = H256::zero(); self.ingress_mac.clone().finalize(expected.as_bytes_mut()); if mac != &expected[0..16] { - return Err(ErrorKind::Auth.into()); + return Err(Error::Auth); } let mut hdec = H128::default(); @@ -422,7 +422,7 @@ impl EncryptedConnection { let padding = (16 - (self.payload_len % 16)) % 16; let full_length = self.payload_len + padding + 16; if payload.len() != full_length { - return Err(ErrorKind::Auth.into()); + return Err(Error::Auth); } self.ingress_mac.update(&payload[0..payload.len() - 16]); EncryptedConnection::update_mac(&mut self.ingress_mac, &mut self.mac_encoder, &[0u8; 0]); @@ -430,7 +430,7 @@ impl EncryptedConnection { let mut expected = H128::default(); self.ingress_mac.clone().finalize(expected.as_bytes_mut()); if mac != &expected[..] { - return Err(ErrorKind::Auth.into()); + return Err(Error::Auth); } let mut packet = vec![0u8; self.payload_len]; diff --git a/util/network-devp2p/src/discovery.rs b/util/network-devp2p/src/discovery.rs index bd5cd09a6..e196a2f1d 100644 --- a/util/network-devp2p/src/discovery.rs +++ b/util/network-devp2p/src/discovery.rs @@ -27,7 +27,7 @@ use parity_bytes::Bytes; use rlp::{Rlp, RlpStream}; use ethkey::{KeyPair, recover, Secret, sign}; -use network::{Error, ErrorKind}; +use network::Error; use network::IpFilter; use node_table::*; use PROTOCOL_VERSION; @@ -482,12 +482,12 @@ impl<'a> Discovery<'a> { pub fn on_packet(&mut self, packet: &[u8], from: SocketAddr) -> Result, Error> { // validate packet if packet.len() < 32 + 65 + 4 + 1 { - return Err(ErrorKind::BadProtocol.into()); + return Err(Error::BadProtocol); } let hash_signed = keccak(&packet[32..]); if hash_signed[..] != packet[0..32] { - return Err(ErrorKind::BadProtocol.into()); + return Err(Error::BadProtocol); } let signed = &packet[(32 + 65)..]; @@ -512,7 +512,7 @@ impl<'a> Discovery<'a> { let secs_since_epoch = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_secs(); if self.check_timestamps && timestamp < secs_since_epoch { debug!(target: "discovery", "Expired packet"); - return Err(ErrorKind::Expired.into()); + return Err(Error::Expired); } Ok(()) } diff --git a/util/network-devp2p/src/handshake.rs b/util/network-devp2p/src/handshake.rs index aee73d0e8..69c2ba22d 100644 --- a/util/network-devp2p/src/handshake.rs +++ b/util/network-devp2p/src/handshake.rs @@ -28,7 +28,7 @@ use ethkey::{Generator, KeyPair, Public, Random, recover, Secret, sign}; use ethkey::crypto::{ecdh, ecies}; use host::HostInfo; use io::{IoContext, StreamToken}; -use network::{Error, ErrorKind}; +use network::Error; use node_table::NodeId; #[derive(PartialEq, Eq, Debug)] @@ -166,7 +166,7 @@ impl Handshake { trace!(target: "network", "Received handshake auth from {:?}", self.connection.remote_addr_str()); if data.len() != V4_AUTH_PACKET_SIZE { debug!(target: "network", "Wrong auth packet size"); - return Err(ErrorKind::BadProtocol.into()); + return Err(Error::BadProtocol); } self.auth_cipher = data.to_vec(); match ecies::decrypt(secret, &[], data) { @@ -183,7 +183,7 @@ impl Handshake { let total = ((u16::from(data[0]) << 8 | (u16::from(data[1]))) as usize) + 2; if total < V4_AUTH_PACKET_SIZE { debug!(target: "network", "Wrong EIP8 auth packet size"); - return Err(ErrorKind::BadProtocol.into()); + return Err(Error::BadProtocol); } let rest = total - data.len(); self.state = HandshakeState::ReadingAuthEip8; @@ -212,7 +212,7 @@ impl Handshake { trace!(target: "network", "Received handshake ack from {:?}", self.connection.remote_addr_str()); if data.len() != V4_ACK_PACKET_SIZE { debug!(target: "network", "Wrong ack packet size"); - return Err(ErrorKind::BadProtocol.into()); + return Err(Error::BadProtocol); } self.ack_cipher = data.to_vec(); match ecies::decrypt(secret, &[], data) { @@ -226,7 +226,7 @@ impl Handshake { let total = (((u16::from(data[0])) << 8 | (u16::from(data[1]))) as usize) + 2; if total < V4_ACK_PACKET_SIZE { debug!(target: "network", "Wrong EIP8 ack packet size"); - return Err(ErrorKind::BadProtocol.into()); + return Err(Error::BadProtocol); } let rest = total - data.len(); self.state = HandshakeState::ReadingAckEip8; diff --git a/util/network-devp2p/src/host.rs b/util/network-devp2p/src/host.rs index cf9f6ac5b..be50929b6 100644 --- a/util/network-devp2p/src/host.rs +++ b/util/network-devp2p/src/host.rs @@ -44,7 +44,7 @@ use io::*; use ip_utils::{map_external_address, select_public_address}; use network::{NetworkConfiguration, NetworkIoMessage, PacketId, PeerId, ProtocolId}; use network::{NetworkContext as NetworkContextTrait, NonReservedPeerMode}; -use network::{DisconnectReason, Error, ErrorKind, NetworkProtocolHandler, SessionInfo}; +use network::{DisconnectReason, Error, NetworkProtocolHandler, SessionInfo}; use network::{ConnectionDirection, ConnectionFilter}; use network::client_version::ClientVersion; use node_table::*; @@ -157,7 +157,7 @@ impl<'s> NetworkContextTrait for NetworkContext<'s> { fn respond(&self, packet_id: PacketId, data: Vec) -> Result<(), Error> { assert!(self.session.is_some(), "Respond called without network context"); - self.session_id.map_or_else(|| Err(ErrorKind::Expired.into()), |id| self.send(id, packet_id, data)) + self.session_id.map_or_else(|| Err(Error::Expired), |id| self.send(id, packet_id, data)) } fn disable_peer(&self, peer: PeerId) { @@ -719,8 +719,8 @@ impl Host { Err(e) => { let s = session.lock(); trace!(target: "network", "Session read error: {}:{:?} ({:?}) {:?}", token, s.id(), s.remote_addr(), e); - match *e.kind() { - ErrorKind::Disconnect(DisconnectReason::IncompatibleProtocol) | ErrorKind::Disconnect(DisconnectReason::UselessPeer) => { + match e { + Error::Disconnect(DisconnectReason::IncompatibleProtocol) | Error::Disconnect(DisconnectReason::UselessPeer) => { if let Some(id) = s.id() { if !self.reserved_nodes.read().contains(id) { let mut nodes = self.nodes.write(); diff --git a/util/network-devp2p/src/lib.rs b/util/network-devp2p/src/lib.rs index a0ded7d6b..b9417341a 100644 --- a/util/network-devp2p/src/lib.rs +++ b/util/network-devp2p/src/lib.rs @@ -68,8 +68,6 @@ extern crate bytes; extern crate crypto as rcrypto; #[cfg(test)] extern crate env_logger; -#[macro_use] -extern crate error_chain; extern crate ethcore_io as io; extern crate ethcore_network as network; extern crate ethereum_types; diff --git a/util/network-devp2p/src/node_table.rs b/util/network-devp2p/src/node_table.rs index 0e39c43ce..b65b5bd0a 100644 --- a/util/network-devp2p/src/node_table.rs +++ b/util/network-devp2p/src/node_table.rs @@ -31,7 +31,7 @@ use serde_json; use discovery::{NodeEntry, TableUpdates}; use ip_utils::*; -use network::{AllowIP, Error, ErrorKind, IpFilter}; +use network::{AllowIP, Error, IpFilter}; /// Node public key pub type NodeId = H512; @@ -133,8 +133,8 @@ impl FromStr for NodeEndpoint { address: a, udp_port: a.port() }), - Ok(None) => bail!(ErrorKind::AddressResolve(None)), - Err(_) => Err(ErrorKind::AddressParse.into()) // always an io::Error of InvalidInput kind + Ok(None) => return Err(Error::AddressResolve(None.into())), + Err(_) => Err(Error::AddressParse) // always an io::Error of InvalidInput kind } } } @@ -216,7 +216,7 @@ impl FromStr for Node { type Err = Error; fn from_str(s: &str) -> Result { let (id, endpoint) = if s.len() > 136 && &s[0..8] == "enode://" && &s[136..137] == "@" { - (s[8..136].parse().map_err(|_| ErrorKind::InvalidNodeId)?, NodeEndpoint::from_str(&s[137..])?) + (s[8..136].parse().map_err(|_| Error::InvalidNodeId)?, NodeEndpoint::from_str(&s[137..])?) } else { (NodeId::default(), NodeEndpoint::from_str(s)?) @@ -629,21 +629,21 @@ mod tests { fn endpoint_parse_empty_ip_string_returns_error() { let endpoint = NodeEndpoint::from_str(""); assert!(endpoint.is_err()); - assert_matches!(endpoint.unwrap_err().kind(), &ErrorKind::AddressParse); + assert_matches!(endpoint.unwrap_err(), Error::AddressParse); } #[test] fn endpoint_parse_invalid_ip_string_returns_error() { let endpoint = NodeEndpoint::from_str("beef"); assert!(endpoint.is_err()); - assert_matches!(endpoint.unwrap_err().kind(), &ErrorKind::AddressParse); + assert_matches!(endpoint.unwrap_err(), Error::AddressParse); } #[test] fn endpoint_parse_valid_ip_without_port_returns_error() { let endpoint = NodeEndpoint::from_str("123.123.123.123"); assert!(endpoint.is_err()); - assert_matches!(endpoint.unwrap_err().kind(), &ErrorKind::AddressParse); + assert_matches!(endpoint.unwrap_err(), Error::AddressParse); let endpoint = NodeEndpoint::from_str("123.123.123.123:123"); assert!(endpoint.is_ok()) } @@ -668,11 +668,11 @@ mod tests { fn node_parse_fails_for_invalid_urls() { let node = Node::from_str("foo"); assert!(node.is_err()); - assert_matches!(node.unwrap_err().kind(), &ErrorKind::AddressParse); + assert_matches!(node.unwrap_err(), Error::AddressParse); let node = Node::from_str("enode://foo@bar"); assert!(node.is_err()); - assert_matches!(node.unwrap_err().kind(), &ErrorKind::AddressParse); + assert_matches!(node.unwrap_err(), Error::AddressParse); } #[test] diff --git a/util/network-devp2p/src/session.rs b/util/network-devp2p/src/session.rs index 8087342a1..6776f0418 100644 --- a/util/network-devp2p/src/session.rs +++ b/util/network-devp2p/src/session.rs @@ -30,7 +30,7 @@ use connection::{Connection, EncryptedConnection, MAX_PAYLOAD_SIZE, Packet}; use handshake::Handshake; use host::*; use io::{IoContext, StreamToken}; -use network::{DisconnectReason, Error, ErrorKind, PeerCapabilityInfo, ProtocolId, SessionInfo}; +use network::{DisconnectReason, Error, PeerCapabilityInfo, ProtocolId, SessionInfo}; use network::client_version::ClientVersion; use network::SessionCapabilityInfo; use node_table::NodeId; @@ -256,10 +256,10 @@ impl Session { where Message: Send + Sync + Clone { if protocol.is_some() && (self.info.capabilities.is_empty() || !self.had_hello) { debug!(target: "network", "Sending to unconfirmed session {}, protocol: {:?}, packet: {}", self.token(), protocol.as_ref().map(|p| str::from_utf8(&p[..]).unwrap_or("??")), packet_id); - bail!(ErrorKind::BadProtocol); + return Err(Error::BadProtocol); } if self.expired() { - return Err(ErrorKind::Expired.into()); + return Err(Error::Expired); } let mut i = 0usize; let pid = match protocol { @@ -281,7 +281,7 @@ impl Session { let mut payload = data; // create a reference with local lifetime if self.compression { if payload.len() > MAX_PAYLOAD_SIZE { - bail!(ErrorKind::OversizedPacket); + return Err(Error::OversizedPacket); } let len = snappy::compress_into(&payload, &mut compressed); trace!(target: "network", "compressed {} to {}", payload.len(), len); @@ -331,16 +331,16 @@ impl Session { fn read_packet(&mut self, io: &IoContext, packet: &Packet, host: &HostInfo) -> Result where Message: Send + Sync + Clone { if packet.data.len() < 2 { - return Err(ErrorKind::BadProtocol.into()); + return Err(Error::BadProtocol); } let packet_id = packet.data[0]; if packet_id != PACKET_HELLO && packet_id != PACKET_DISCONNECT && !self.had_hello { - return Err(ErrorKind::BadProtocol.into()); + return Err(Error::BadProtocol); } let data = if self.compression { let compressed = &packet.data[1..]; if snappy::decompressed_len(&compressed)? > MAX_PAYLOAD_SIZE { - bail!(ErrorKind::OversizedPacket); + return Err(Error::OversizedPacket); } snappy::decompress(&compressed)? } else { @@ -358,7 +358,7 @@ impl Session { if self.had_hello { debug!(target:"network", "Disconnected: {}: {:?}", self.token(), DisconnectReason::from_u8(reason)); } - Err(ErrorKind::Disconnect(DisconnectReason::from_u8(reason)).into()) + Err(Error::Disconnect(DisconnectReason::from_u8(reason))) } PACKET_PING => { self.send_pong(io)?; @@ -500,7 +500,7 @@ impl Session { rlp.append(&(reason as u32)); self.send_packet(io, None, PACKET_DISCONNECT, &rlp.drain()).ok(); } - ErrorKind::Disconnect(reason).into() + Error::Disconnect(reason) } fn send(&mut self, io: &IoContext, data: &[u8]) -> Result<(), Error> where Message: Send + Sync + Clone { diff --git a/util/network/Cargo.toml b/util/network/Cargo.toml index 018152c72..55c15d7d1 100644 --- a/util/network/Cargo.toml +++ b/util/network/Cargo.toml @@ -7,7 +7,7 @@ version = "1.12.0" authors = ["Parity Technologies "] [dependencies] -error-chain = { version = "0.12", default-features = false } +derive_more = "0.14.0" parity-crypto = "0.4.0" ethcore-io = { path = "../io" } ethereum-types = "0.6.0" diff --git a/util/network/src/error.rs b/util/network/src/error.rs index bd48830c1..81e3b78b8 100644 --- a/util/network/src/error.rs +++ b/util/network/src/error.rs @@ -14,11 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -// Silence: `use of deprecated item 'std::error::Error::cause': replaced by Error::source, which can support downcasting` -// https://github.com/paritytech/parity-ethereum/issues/10302 -#![allow(deprecated)] - -use std::{io, net, fmt}; +use std::{error, io, net, fmt}; use libc::{ENFILE, EMFILE}; use io::IoError; use {rlp, ethkey, crypto, snappy}; @@ -85,118 +81,127 @@ impl fmt::Display for DisconnectReason { } } -error_chain! { - foreign_links { - SocketIo(IoError) #[doc = "Socket IO error."]; - Decompression(snappy::InvalidInput) #[doc = "Decompression error."]; - Rlp(rlp::DecoderError) #[doc = "Rlp decoder error."]; +/// Queue error +#[derive(Debug, derive_more::Display)] +pub enum Error { + /// Socket IO error. + SocketIo(IoError), + /// Decompression error. + Decompression(snappy::InvalidInput), + /// Rlp decoder error. + Rlp(rlp::DecoderError), + /// Error concerning the network address parsing subsystem. + #[display(fmt = "Failed to parse network address")] + AddressParse, + /// Error concerning the network address resolution subsystem. + #[display(fmt = "Failed to resolve network address {}", _0)] + AddressResolve(AddressResolveError), + /// Authentication failure + #[display(fmt = "Authentication failure")] + Auth, + /// Unrecognised protocol + #[display(fmt = "Bad protocol")] + BadProtocol, + /// Expired message + #[display(fmt = "Expired message")] + Expired, + /// Peer not found + #[display(fmt = "Peer not found")] + PeerNotFound, + /// Peer is disconnected + #[display(fmt = "Peer disconnected: {}", _0)] + Disconnect(DisconnectReason), + /// Invalid node id + #[display(fmt = "Invalid node id")] + InvalidNodeId, + /// Packet size is over the protocol limit + #[display(fmt = "Packet is too large")] + OversizedPacket, + /// Reached system resource limits for this process + #[display(fmt = "Too many open files in this process. Check your resource limits and restart parity")] + ProcessTooManyFiles, + /// Reached system wide resource limits + #[display(fmt = "Too many open files on system. Consider closing some processes/release some file handlers or increas the system-wide resource limits and restart parity.")] + SystemTooManyFiles, + /// An unknown IO error occurred. + #[display(fmt = "Unexpected IO error: {}", _0)] + Io(io::Error), +} + +/// Wraps io::Error for Display impl +#[derive(Debug)] +pub struct AddressResolveError(Option); + +impl fmt::Display for AddressResolveError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "{}", self.0.as_ref().map_or("".to_string(), |e| e.to_string())) } +} - errors { - #[doc = "Error concerning the network address parsing subsystem."] - AddressParse { - description("Failed to parse network address"), - display("Failed to parse network address"), - } +impl From> for AddressResolveError { + fn from(err: Option) -> Self { + AddressResolveError(err) + } +} - #[doc = "Error concerning the network address resolution subsystem."] - AddressResolve(err: Option) { - description("Failed to resolve network address"), - display("Failed to resolve network address {}", err.as_ref().map_or("".to_string(), |e| e.to_string())), +impl error::Error for Error { + fn source(&self) -> Option<&(error::Error + 'static)> { + match self { + Error::Decompression(e) => Some(e), + Error::Rlp(e) => Some(e), + _ => None, } + } +} - #[doc = "Authentication failure"] - Auth { - description("Authentication failure"), - display("Authentication failure"), - } +impl From for Error { + fn from(err: IoError) -> Self { + Error::SocketIo(err) + } +} - #[doc = "Unrecognised protocol"] - BadProtocol { - description("Bad protocol"), - display("Bad protocol"), - } +impl From for Error { + fn from(err: snappy::InvalidInput) -> Self { + Error::Decompression(err) + } +} - #[doc = "Expired message"] - Expired { - description("Expired message"), - display("Expired message"), - } - - #[doc = "Peer not found"] - PeerNotFound { - description("Peer not found"), - display("Peer not found"), - } - - #[doc = "Peer is disconnected"] - Disconnect(reason: DisconnectReason) { - description("Peer disconnected"), - display("Peer disconnected: {}", reason), - } - - #[doc = "Invalid node id"] - InvalidNodeId { - description("Invalid node id"), - display("Invalid node id"), - } - - #[doc = "Packet size is over the protocol limit"] - OversizedPacket { - description("Packet is too large"), - display("Packet is too large"), - } - - #[doc = "Reached system resource limits for this process"] - ProcessTooManyFiles { - description("Too many open files in process."), - display("Too many open files in this process. Check your resource limits and restart parity"), - } - - #[doc = "Reached system wide resource limits"] - SystemTooManyFiles { - description("Too many open files on system."), - display("Too many open files on system. Consider closing some processes/release some file handlers or increas the system-wide resource limits and restart parity."), - } - - #[doc = "An unknown IO error occurred."] - Io(err: io::Error) { - description("IO Error"), - display("Unexpected IO error: {}", err), - } +impl From for Error { + fn from(err: rlp::DecoderError) -> Self { + Error::Rlp(err) } } impl From for Error { fn from(err: io::Error) -> Self { match err.raw_os_error() { - Some(ENFILE) => ErrorKind::ProcessTooManyFiles.into(), - Some(EMFILE) => ErrorKind::SystemTooManyFiles.into(), - _ => Error::from_kind(ErrorKind::Io(err)) + Some(ENFILE) => Error::ProcessTooManyFiles, + Some(EMFILE) => Error::SystemTooManyFiles, + _ => Error::Io(err) } } } impl From for Error { fn from(_err: ethkey::Error) -> Self { - ErrorKind::Auth.into() + Error::Auth } } impl From for Error { fn from(_err: ethkey::crypto::Error) -> Self { - ErrorKind::Auth.into() + Error::Auth } } impl From for Error { fn from(_err: crypto::error::SymmError) -> Self { - ErrorKind::Auth.into() + Error::Auth } } impl From for Error { - fn from(_err: net::AddrParseError) -> Self { ErrorKind::AddressParse.into() } + fn from(_err: net::AddrParseError) -> Self { Error::AddressParse } } #[test] @@ -208,13 +213,13 @@ fn test_errors() { } assert_eq!(DisconnectReason::Unknown, r); - match *>::from(rlp::DecoderError::RlpIsTooBig).kind() { - ErrorKind::Rlp(_) => {}, + match >::from(rlp::DecoderError::RlpIsTooBig) { + Error::Rlp(_) => {}, _ => panic!("Unexpected error"), } - match *>::from(ethkey::crypto::Error::InvalidMessage).kind() { - ErrorKind::Auth => {}, + match >::from(ethkey::crypto::Error::InvalidMessage) { + Error::Auth => {}, _ => panic!("Unexpected error"), } } @@ -226,18 +231,18 @@ fn test_io_errors() { assert_matches!( >::from( io::Error::from_raw_os_error(ENFILE) - ).kind(), - ErrorKind::ProcessTooManyFiles); + ), + Error::ProcessTooManyFiles); assert_matches!( >::from( io::Error::from_raw_os_error(EMFILE) - ).kind(), - ErrorKind::SystemTooManyFiles); + ), + Error::SystemTooManyFiles); assert_matches!( >::from( io::Error::from_raw_os_error(0) - ).kind(), - ErrorKind::Io(_)); + ), + Error::Io(_)); } diff --git a/util/network/src/lib.rs b/util/network/src/lib.rs index 9e6f71fdd..be47fa367 100644 --- a/util/network/src/lib.rs +++ b/util/network/src/lib.rs @@ -32,9 +32,7 @@ extern crate serde_derive; #[cfg(test)] #[macro_use] extern crate assert_matches; - -#[macro_use] -extern crate error_chain; +extern crate derive_more; #[macro_use] extern crate lazy_static; @@ -46,7 +44,7 @@ mod error; pub use connection_filter::{ConnectionFilter, ConnectionDirection}; pub use io::TimerToken; -pub use error::{Error, ErrorKind, DisconnectReason}; +pub use error::{Error, DisconnectReason}; use client_version::ClientVersion; use std::cmp::Ordering;