use std::{fmt, error};
use vapory_types::U256;
use tetsy_crypto::publickey::{Error as VapPublicKeyCryptoError};
use tetsy_rlp;
use tetsy_unexpected::OutOfBounds;
use crate::errors::ExecutionError;
#[derive(Debug, PartialEq, Clone)]
pub enum Error {
AlreadyImported,
Old,
LimitReached,
InsufficientGasPrice {
minimal: U256,
got: U256,
},
TooCheapToReplace {
prev: Option<U256>,
new: Option<U256>,
},
InsufficientGas {
minimal: U256,
got: U256,
},
InsufficientBalance {
balance: U256,
cost: U256,
},
GasLimitExceeded {
limit: U256,
got: U256,
},
InvalidGasLimit(OutOfBounds<U256>),
SenderBanned,
RecipientBanned,
CodeBanned,
InvalidChainId,
NotAllowed,
InvalidSignature(String),
TooBig,
InvalidRlp(String),
}
impl From<VapPublicKeyCryptoError> for Error {
fn from(err: VapPublicKeyCryptoError) -> Self {
Error::InvalidSignature(format!("{}", err))
}
}
impl From<tetsy_rlp::DecoderError> for Error {
fn from(err: tetsy_rlp::DecoderError) -> Self {
Error::InvalidRlp(format!("{}", err))
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Error::*;
let msg = match *self {
AlreadyImported => "Already imported".into(),
Old => "No longer valid".into(),
TooCheapToReplace { prev, new } =>
format!("Gas price too low to replace, previous tx gas: {:?}, new tx gas: {:?}",
prev, new
),
LimitReached => "Transaction limit reached".into(),
InsufficientGasPrice { minimal, got } =>
format!("Insufficient gas price. Min={}, Given={}", minimal, got),
InsufficientGas { minimal, got } =>
format!("Insufficient gas. Min={}, Given={}", minimal, got),
InsufficientBalance { balance, cost } =>
format!("Insufficient balance for transaction. Balance={}, Cost={}",
balance, cost),
GasLimitExceeded { limit, got } =>
format!("Gas limit exceeded. Limit={}, Given={}", limit, got),
InvalidGasLimit(ref err) => format!("Invalid gas limit. {}", err),
SenderBanned => "Sender is temporarily banned.".into(),
RecipientBanned => "Recipient is temporarily banned.".into(),
CodeBanned => "Contract code is temporarily banned.".into(),
InvalidChainId => "Transaction of this chain ID is not allowed on this chain.".into(),
InvalidSignature(ref err) => format!("Transaction has invalid signature: {}.", err),
NotAllowed => "Sender does not have permissions to execute this type of transaction".into(),
TooBig => "Transaction too big".into(),
InvalidRlp(ref err) => format!("Transaction has invalid RLP structure: {}.", err),
};
f.write_fmt(format_args!("Transaction error ({})", msg))
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Transaction error"
}
}
#[derive(PartialEq, Debug, Clone)]
pub enum CallError {
TransactionNotFound,
StatePruned,
Exceptional(tetsy_vm::Error),
StateCorrupt,
Execution(ExecutionError),
}
impl From<ExecutionError> for CallError {
fn from(error: ExecutionError) -> Self {
CallError::Execution(error)
}
}
impl fmt::Display for CallError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::CallError::*;
let msg = match *self {
TransactionNotFound => "Transaction couldn't be found in the chain".into(),
StatePruned => "Couldn't find the transaction block's state in the chain".into(),
Exceptional(ref e) => format!("An exception ({}) happened in the execution", e),
StateCorrupt => "Stored state found to be corrupted.".into(),
Execution(ref e) => format!("{}", e),
};
f.write_fmt(format_args!("Transaction execution error ({}).", msg))
}
}