use std::str::Utf8Error;
use thiserror::Error;
use casper_storage::{global_state, tracking_copy::TrackingCopyError};
use casper_types::{
account::{AddKeyFailure, RemoveKeyFailure, SetThresholdFailure, UpdateKeyFailure},
bytesrepr,
execution::TransformError,
system, AccessRights, AddressableEntityHash, ApiError, ByteCodeHash, CLType, CLValueError,
ContractRuntimeTag, EntityVersionKey, Key, PackageHash, StoredValueTypeMismatch, URef,
};
use casper_wasm::elements;
use crate::{
resolvers::error::ResolverError,
runtime::{stack, PreprocessingError},
};
#[derive(Error, Debug, Clone)]
#[non_exhaustive]
pub enum Error {
#[error("Interpreter error: {}", _0)]
Interpreter(String),
#[error("Storage error: {}", _0)]
Storage(global_state::error::Error),
#[error("Serialization error: {}", _0)]
BytesRepr(bytesrepr::Error),
#[error("Named key {} not found", _0)]
NamedKeyNotFound(String),
#[error("Key {} not found", _0)]
KeyNotFound(Key),
#[error("Account {:?} not found", _0)]
AccountNotFound(Key),
#[error("{}", _0)]
TypeMismatch(StoredValueTypeMismatch),
#[error("Invalid access rights: {}", required)]
InvalidAccess {
required: AccessRights,
},
#[error("Forged reference: {}", _0)]
ForgedReference(URef),
#[error("Function not found: {}", _0)]
FunctionNotFound(String),
#[error("{}", _0)]
ParityWasm(elements::Error),
#[error("WASM optimizer error")]
WasmOptimizer,
#[error("Out of gas error")]
GasLimit,
#[error("Return")]
Ret(Vec<URef>),
#[error("Resolver error: {}", _0)]
Resolver(ResolverError),
#[error("{}", _0)]
Revert(ApiError),
#[error("{}", _0)]
AddKeyFailure(AddKeyFailure),
#[error("{}", _0)]
RemoveKeyFailure(RemoveKeyFailure),
#[error("{}", _0)]
UpdateKeyFailure(UpdateKeyFailure),
#[error("{}", _0)]
SetThresholdFailure(SetThresholdFailure),
#[error("{}", _0)]
SystemContract(system::Error),
#[error("Deployment authorization failure")]
DeploymentAuthorizationFailure,
#[error("Expected return value")]
ExpectedReturnValue,
#[error("Invalid context")]
InvalidContext,
#[error("Incompatible protocol major version. Expected version {expected} but actual version is {actual}")]
IncompatibleProtocolMajorVersion {
expected: u32,
actual: u32,
},
#[error("{0}")]
CLValue(CLValueError),
#[error("Unsupported Wasm start")]
UnsupportedWasmStart,
#[error("No active contract versions for contract package")]
NoActiveEntityVersions(PackageHash),
#[error("Invalid entity version: {}", _0)]
InvalidEntityVersion(EntityVersionKey),
#[error("Disabled entity version: {}", _0)]
DisabledEntityVersion(EntityVersionKey),
#[error("Missing entity version: {}", _0)]
MissingEntityVersion(EntityVersionKey),
#[error("No such method: {}", _0)]
NoSuchMethod(String),
#[error("Error calling a template entry point: {}", _0)]
TemplateMethod(String),
#[error("Wasm preprocessing error: {}", _0)]
WasmPreprocessing(PreprocessingError),
#[error("Unexpected variant of a stored value")]
UnexpectedStoredValueVariant,
#[error("A locked contract cannot be upgraded")]
LockedEntity(PackageHash),
#[error("Invalid contract: {}", _0)]
InvalidEntity(AddressableEntityHash),
#[error("Invalid contract WASM: {}", _0)]
InvalidByteCode(ByteCodeHash),
#[error("Missing argument: {name}")]
MissingArgument {
name: String,
},
#[error("Dictionary item key exceeded maximum length")]
DictionaryItemKeyExceedsLength,
#[error("Missing system contract hash: {0}")]
MissingSystemContractHash(String),
#[error("Runtime stack overflow")]
RuntimeStackOverflow,
#[error("Runtime stack missing")]
MissingRuntimeStack,
#[error("Contract is disabled")]
DisabledEntity(AddressableEntityHash),
#[error(transparent)]
Transform(TransformError),
#[error("Invalid key {0}")]
UnexpectedKeyVariant(Key),
#[error("Failed to transfer with unrestricted transfers disabled")]
DisabledUnrestrictedTransfers,
#[error("Tracking copy error: {0}")]
TrackingCopy(TrackingCopyError),
#[error("Deployment authorization failure")]
UpgradeAuthorizationFailure,
#[error("The EntryPoints contains an invalid entry")]
InvalidEntryPointType,
#[error("The imputed operation is invalid")]
InvalidImputedOperation,
#[error("Invalid UTF-8 string encoding: {0}")]
InvalidUtf8Encoding(Utf8Error),
#[error("Incompatible runtime: {0}")]
IncompatibleRuntime(ContractRuntimeTag),
#[error("No matching entity version key")]
NoMatchingEntityVersionKey,
#[error("Ambiguous entity version")]
AmbiguousEntityVersion,
}
impl From<PreprocessingError> for Error {
fn from(error: PreprocessingError) -> Self {
Error::WasmPreprocessing(error)
}
}
impl From<casper_wasm_utils::OptimizerError> for Error {
fn from(_optimizer_error: casper_wasm_utils::OptimizerError) -> Self {
Error::WasmOptimizer
}
}
impl Error {
pub fn type_mismatch(expected: CLType, found: CLType) -> Error {
Error::TypeMismatch(StoredValueTypeMismatch::new(
format!("{:?}", expected),
format!("{:?}", found),
))
}
}
impl casper_wasmi::HostError for Error {}
impl From<casper_wasmi::Error> for Error {
fn from(error: casper_wasmi::Error) -> Self {
match error
.as_host_error()
.and_then(|host_error| host_error.downcast_ref::<Error>())
{
Some(error) => error.clone(),
None => Error::Interpreter(error.into()),
}
}
}
impl From<global_state::error::Error> for Error {
fn from(e: global_state::error::Error) -> Self {
Error::Storage(e)
}
}
impl From<bytesrepr::Error> for Error {
fn from(e: bytesrepr::Error) -> Self {
Error::BytesRepr(e)
}
}
impl From<elements::Error> for Error {
fn from(e: elements::Error) -> Self {
Error::ParityWasm(e)
}
}
impl From<ResolverError> for Error {
fn from(err: ResolverError) -> Self {
Error::Resolver(err)
}
}
impl From<AddKeyFailure> for Error {
fn from(err: AddKeyFailure) -> Self {
Error::AddKeyFailure(err)
}
}
impl From<RemoveKeyFailure> for Error {
fn from(err: RemoveKeyFailure) -> Self {
Error::RemoveKeyFailure(err)
}
}
impl From<UpdateKeyFailure> for Error {
fn from(err: UpdateKeyFailure) -> Self {
Error::UpdateKeyFailure(err)
}
}
impl From<SetThresholdFailure> for Error {
fn from(err: SetThresholdFailure) -> Self {
Error::SetThresholdFailure(err)
}
}
impl From<system::Error> for Error {
fn from(error: system::Error) -> Self {
Error::SystemContract(error)
}
}
impl From<CLValueError> for Error {
fn from(e: CLValueError) -> Self {
Error::CLValue(e)
}
}
impl From<stack::RuntimeStackOverflow> for Error {
fn from(_: stack::RuntimeStackOverflow) -> Self {
Error::RuntimeStackOverflow
}
}
impl From<TrackingCopyError> for Error {
fn from(e: TrackingCopyError) -> Self {
Error::TrackingCopy(e)
}
}