use corevm_host::{fs, Outcome, PageNum};
use jam_pvm_common::ApiError;
#[derive(thiserror::Error, Debug)]
pub enum InitError {
#[error("JAM error: {0:?}")]
Jam(ApiError),
#[error("CoreVM FS error: {0:?}")]
Fs(fs::Error),
#[error("Invalid program blob")]
ProgramBlob,
#[error("Invalid exec blob")]
ExecBlob,
#[error("None or both `main` and `_pvm_start` entry points were found")]
EntryPoint,
#[error("Invalid memory page was imported into the package")]
InvalidPage,
#[error("Input limit reached while initializing the engine")]
InputLimitReached,
}
impl From<polkavm::program::ProgramParseError> for InitError {
fn from(_: polkavm::program::ProgramParseError) -> Self {
Self::ProgramBlob
}
}
impl From<ApiError> for InitError {
fn from(e: ApiError) -> Self {
Self::Jam(e)
}
}
impl From<fs::Error> for InitError {
fn from(e: fs::Error) -> Self {
Self::Fs(e)
}
}
#[derive(thiserror::Error, Debug)]
pub enum FatalError {
#[error("Input space limit reached while restarting a host-call")]
NotEnoughInputSpace,
#[error("Output space limit reached while restarting a host-call")]
NotEnoughOutputSpace,
#[error("Unknown host-call")]
UnknownHostCall,
#[error("Guest attempted to read/write reserved/unmapped memory address")]
InvalidMemoryAccess,
}
#[derive(thiserror::Error, Debug)]
pub enum RunError {
#[error("JAM error: {0:?}")]
Jam(ApiError),
#[error("CoreVM FS error: {0:?}")]
Fs(fs::Error),
#[error("Fatal error: {0:?}")]
Fatal(FatalError),
#[error("Failed to initialize libc")]
LibcInit,
}
impl From<ApiError> for RunError {
fn from(e: ApiError) -> Self {
Self::Jam(e)
}
}
impl From<fs::Error> for RunError {
fn from(e: fs::Error) -> Self {
Self::Fs(e)
}
}
impl From<FatalError> for RunError {
fn from(e: FatalError) -> Self {
Self::Fatal(e)
}
}
#[derive(Debug)]
pub(crate) enum HostCallError {
Jam(ApiError),
Fs(fs::Error),
Outcome(Outcome),
Fatal(FatalError),
}
impl From<Outcome> for HostCallError {
fn from(outcome: Outcome) -> Self {
Self::Outcome(outcome)
}
}
impl From<TimeLimitReached> for HostCallError {
fn from(_: TimeLimitReached) -> Self {
Self::Outcome(Outcome::TimeLimitReached)
}
}
impl From<OutputLimitReached> for HostCallError {
fn from(_: OutputLimitReached) -> Self {
Self::Outcome(Outcome::OutputLimitReached)
}
}
impl From<InputLimitReached> for HostCallError {
fn from(_: InputLimitReached) -> Self {
Self::Outcome(Outcome::InputLimitReached)
}
}
impl From<ApiError> for HostCallError {
fn from(e: ApiError) -> Self {
Self::Jam(e)
}
}
impl From<fs::Error> for HostCallError {
fn from(e: fs::Error) -> Self {
Self::Fs(e)
}
}
impl From<FatalError> for HostCallError {
fn from(e: FatalError) -> Self {
Self::Fatal(e)
}
}
impl From<TouchError> for HostCallError {
fn from(e: TouchError) -> Self {
match e {
TouchError::PageFault { page, num_pages } =>
Self::Outcome(Outcome::PageFault { page, num_pages }),
TouchError::Jam(e) => Self::Jam(e),
TouchError::InvalidMemoryAccess => Self::Fatal(FatalError::InvalidMemoryAccess),
TouchError::InputLimitReached => Self::Outcome(Outcome::InputLimitReached),
}
}
}
impl From<polkakernel::MachineError> for HostCallError {
fn from(e: polkakernel::MachineError) -> Self {
match e {
polkakernel::MachineError::BadAddress => Self::Fatal(FatalError::InvalidMemoryAccess),
}
}
}
impl From<TooLargeWorkOutput> for HostCallError {
fn from(_: TooLargeWorkOutput) -> Self {
Self::Outcome(Outcome::OutputLimitReached)
}
}
#[derive(Debug)]
pub(crate) enum TouchError {
PageFault { page: PageNum, num_pages: u32 },
Jam(ApiError),
InvalidMemoryAccess,
InputLimitReached,
}
impl From<ApiError> for TouchError {
fn from(e: ApiError) -> Self {
Self::Jam(e)
}
}
impl From<InputLimitReached> for TouchError {
fn from(_: InputLimitReached) -> Self {
Self::InputLimitReached
}
}
#[derive(Debug)]
pub(crate) struct TimeLimitReached;
#[derive(Debug)]
pub(crate) struct OutputLimitReached;
#[derive(Debug)]
pub(crate) struct TooLargeWorkOutput;
#[derive(Debug)]
pub(crate) struct InputLimitReached;