openethereum/ethcore/types/src/errors/ethcore_error.rs

206 lines
6.3 KiB
Rust

// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! General error types for use in ethcore.
use std::{error, fmt};
use derive_more::{Display, From};
use ethereum_types::{U256, U512};
use ethtrie::TrieError;
use parity_snappy::InvalidInput;
use parity_crypto::publickey::Error as EthPublicKeyCryptoError;
use errors::{BlockError, EngineError, ImportError, SnapshotError};
use transaction::Error as TransactionError;
/// Ethcore Result
pub type EthcoreResult<T> = Result<T, EthcoreError>;
/// Ethcore Error
#[derive(Debug, Display, From)]
pub enum EthcoreError {
/// Error concerning block import.
#[display(fmt = "Import error: {}", _0)]
Import(ImportError),
/// Io channel queue error
#[display(fmt = "Queue is full: {}", _0)]
FullQueue(usize),
/// Io create error
#[display(fmt = "Io error: {}", _0)]
Io(ethcore_io::IoError),
/// Error concerning the Rust standard library's IO subsystem.
#[display(fmt = "Std Io error: {}", _0)]
StdIo(::std::io::Error),
/// Error concerning TrieDBs.
#[display(fmt = "Trie error: {}", _0)]
Trie(TrieError),
/// Error concerning EVM code execution.
#[display(fmt = "Execution error: {}", _0)]
Execution(ExecutionError),
/// Error concerning block processing.
#[display(fmt = "Block error: {}", _0)]
Block(BlockError),
/// Error concerning transaction processing.
#[display(fmt = "Transaction error: {}", _0)]
Transaction(TransactionError),
/// Snappy error
#[display(fmt = "Snappy error: {}", _0)]
Snappy(InvalidInput),
/// Consensus vote error.
#[display(fmt = "Engine error: {}", _0)]
Engine(EngineError),
/// Ethkey error."
#[display(fmt = "Ethkey error: {}", _0)]
Ethkey(EthPublicKeyCryptoError),
/// RLP decoding errors
#[display(fmt = "Decoder error: {}", _0)]
Decoder(rlp::DecoderError),
/// Snapshot error.
#[display(fmt = "Snapshot error {}", _0)]
Snapshot(SnapshotError),
/// PoW hash is invalid or out of date.
#[display(fmt = "PoW hash is invalid or out of date.")]
PowHashInvalid,
/// The value of the nonce or mishash is invalid.
#[display(fmt = "The value of the nonce or mishash is invalid.")]
PowInvalid,
/// A convenient variant for String.
#[display(fmt = "{}", _0)]
Msg(String),
}
impl error::Error for EthcoreError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
use self::EthcoreError::*;
match self {
Io(e) => Some(e),
StdIo(e) => Some(e),
Trie(e) => Some(e),
Execution(e) => Some(e),
Block(e) => Some(e),
Transaction(e) => Some(e),
Snappy(e) => Some(e),
Engine(e) => Some(e),
Ethkey(e) => Some(e),
Decoder(e) => Some(e),
Snapshot(e) => Some(e),
_ => None,
}
}
}
impl From<&str> for EthcoreError {
fn from(s: &str) -> Self {
EthcoreError::Msg(s.into())
}
}
impl<E> From<Box<E>> for EthcoreError where EthcoreError: From<E> {
fn from(err: Box<E>) -> EthcoreError {
EthcoreError::from(*err)
}
}
/// Error type for executing a transaction.
#[derive(PartialEq, Debug, Clone)]
pub enum ExecutionError {
/// Returned when there gas paid for transaction execution is
/// lower than base gas required.
NotEnoughBaseGas {
/// Absolute minimum gas required.
required: U256,
/// Gas provided.
got: U256
},
/// Returned when block (gas_used + gas) > gas_limit.
///
/// If gas =< gas_limit, upstream may try to execute the transaction
/// in next block.
BlockGasLimitReached {
/// Gas limit of block for transaction.
gas_limit: U256,
/// Gas used in block prior to transaction.
gas_used: U256,
/// Amount of gas in block.
gas: U256
},
/// Returned when transaction nonce does not match state nonce.
InvalidNonce {
/// Nonce expected.
expected: U256,
/// Nonce found.
got: U256
},
/// Returned when cost of transaction (value + gas_price * gas) exceeds
/// current sender balance.
NotEnoughCash {
/// Minimum required balance.
required: U512,
/// Actual balance.
got: U512
},
/// When execution tries to modify the state in static context
MutableCallInStaticContext,
/// Returned when transacting from a non-existing account with dust protection enabled.
SenderMustExist,
/// Returned when internal evm error occurs.
Internal(String),
/// Returned when generic transaction occurs
TransactionMalformed(String),
}
impl error::Error for ExecutionError {
fn description(&self) -> &str {
"Transaction execution error"
}
}
impl From<Box<TrieError>> for ExecutionError {
fn from(err: Box<TrieError>) -> Self {
ExecutionError::Internal(format!("{:?}", err))
}
}
impl From<TrieError> for ExecutionError {
fn from(err: TrieError) -> Self {
ExecutionError::Internal(format!("{:?}", err))
}
}
impl fmt::Display for ExecutionError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::ExecutionError::*;
let msg = match *self {
NotEnoughBaseGas { ref required, ref got } =>
format!("Not enough base gas. {} is required, but only {} paid", required, got),
BlockGasLimitReached { ref gas_limit, ref gas_used, ref gas } =>
format!("Block gas limit reached. The limit is {}, {} has \
already been used, and {} more is required", gas_limit, gas_used, gas),
InvalidNonce { ref expected, ref got } =>
format!("Invalid transaction nonce: expected {}, found {}", expected, got),
NotEnoughCash { ref required, ref got } =>
format!("Cost of transaction exceeds sender balance. {} is required \
but the sender only has {}", required, got),
MutableCallInStaticContext => "Mutable Call in static context".to_owned(),
SenderMustExist => "Transacting from an empty account".to_owned(),
Internal(ref msg) => msg.clone(),
TransactionMalformed(ref err) => format!("Malformed transaction: {}", err),
};
f.write_fmt(format_args!("Transaction execution error ({}).", msg))
}
}