mod default;
mod threaded;
use std::fmt::Display;
use cid::Cid;
pub use default::DefaultExecutor;
use fvm_ipld_encoding::RawBytes;
use fvm_shared::econ::TokenAmount;
use fvm_shared::error::ExitCode;
use fvm_shared::message::Message;
use fvm_shared::receipt::Receipt;
use num_traits::Zero;
pub use threaded::ThreadedExecutor;
use crate::Kernel;
use crate::call_manager::Backtrace;
use crate::trace::ExecutionTrace;
pub trait Executor {
type Kernel: Kernel;
fn execute_message(
&mut self,
msg: Message,
apply_kind: ApplyKind,
raw_length: usize,
) -> anyhow::Result<ApplyRet>;
fn flush(&mut self) -> anyhow::Result<Cid>;
}
#[derive(Debug, Clone)]
pub enum ApplyFailure {
MessageBacktrace(Backtrace),
PreValidation(String),
}
impl Display for ApplyFailure {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ApplyFailure::MessageBacktrace(bt) => {
writeln!(f, "message failed with backtrace:")?;
write!(f, "{}", bt)?;
}
ApplyFailure::PreValidation(msg) => {
writeln!(f, "pre-validation failed: {}", msg)?;
}
}
Ok(())
}
}
#[derive(Clone, Debug)]
pub struct ApplyRet {
pub msg_receipt: Receipt,
pub penalty: TokenAmount,
pub miner_tip: TokenAmount,
pub base_fee_burn: TokenAmount,
pub over_estimation_burn: TokenAmount,
pub refund: TokenAmount,
pub gas_refund: i64,
pub gas_burned: i64,
pub failure_info: Option<ApplyFailure>,
pub exec_trace: ExecutionTrace,
}
impl ApplyRet {
#[inline]
pub fn prevalidation_fail(
code: ExitCode,
message: impl Into<String>,
miner_penalty: TokenAmount,
) -> ApplyRet {
ApplyRet {
msg_receipt: Receipt {
exit_code: code,
return_data: RawBytes::default(),
gas_used: 0,
},
penalty: miner_penalty,
miner_tip: TokenAmount::zero(),
base_fee_burn: TokenAmount::zero(),
over_estimation_burn: TokenAmount::zero(),
refund: TokenAmount::zero(),
gas_refund: 0,
gas_burned: 0,
failure_info: Some(ApplyFailure::PreValidation(message.into())),
exec_trace: vec![],
}
}
}
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum ApplyKind {
Explicit,
Implicit,
}