1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
// Copyright 2021-2023 Protocol Labs
// SPDX-License-Identifier: Apache-2.0, MIT
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::event::StampedEvent;
use fvm_shared::message::Message;
use fvm_shared::receipt::Receipt;
use num_traits::Zero;
pub use threaded::ThreadedExecutor;
use crate::call_manager::Backtrace;
use crate::trace::ExecutionTrace;
use crate::Kernel;
/// An executor executes messages on the underlying machine/kernel. It's responsible for:
///
/// 1. Validating messages (nonce, sender, etc).
/// 2. Creating message receipts.
/// 3. Charging message inclusion gas, overestimation gas, miner tip, etc.
pub trait Executor {
/// The [`Kernel`] on which messages will be applied. We specify a [`Kernel`] here, not a
/// [`Machine`](crate::machine::Machine), because the [`Kernel`] implies the
/// [`Machine`](crate::machine::Machine).
type Kernel: Kernel;
/// This is the entrypoint to execute a message.
///
/// NOTE: The "raw length" is the length of the message as it appears on-chain and is used to
/// charge message inclusion gas.
fn execute_message(
&mut self,
msg: Message,
apply_kind: ApplyKind,
raw_length: usize,
) -> anyhow::Result<ApplyRet>;
/// Flushes the state-tree, returning the new root CID.
fn flush(&mut self) -> anyhow::Result<Cid>;
}
/// A description of some failure encountered when applying a message.
#[derive(Debug, Clone)]
pub enum ApplyFailure {
/// The backtrace from a message failure.
MessageBacktrace(Backtrace),
/// A message describing a pre-validation failure.
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(())
}
}
/// Apply message return data.
#[derive(Clone, Debug)]
pub struct ApplyRet {
/// Message receipt for the transaction. This data is stored on chain.
pub msg_receipt: Receipt,
/// Gas penalty from transaction, if any.
pub penalty: TokenAmount,
/// Tip given to miner from message.
pub miner_tip: TokenAmount,
// Gas stuffs
pub base_fee_burn: TokenAmount,
pub over_estimation_burn: TokenAmount,
pub refund: TokenAmount,
pub gas_refund: u64,
pub gas_burned: u64,
/// Additional failure information for debugging, if any.
pub failure_info: Option<ApplyFailure>,
/// Execution trace information, for debugging.
pub exec_trace: ExecutionTrace,
/// Events generated while applying the message.
pub events: Vec<StampedEvent>,
}
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,
events_root: None,
},
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![],
events: vec![],
}
}
}
/// The kind of message being applied:
///
/// 1. Explicit messages may only come from account actors and charge the sending account for gas
/// consumed.
/// 2. Implicit messages may come from any actor, ignore the nonce, and charge no gas (but still
/// account for it).
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum ApplyKind {
Explicit,
Implicit,
}