use fvm_shared::address::Address;
use fvm_shared::econ::TokenAmount;
use fvm_shared::error::ExitCode;
use fvm_shared::{ActorID, MethodNum};
use crate::Kernel;
use crate::gas::{GasCharge, GasTracker, PriceList};
use crate::kernel::{self, Result};
use crate::machine::{Machine, MachineContext};
use crate::state_tree::StateTree;
pub mod backtrace;
pub use backtrace::Backtrace;
mod default;
pub use default::DefaultCallManager;
use crate::trace::{ExecutionEvent, ExecutionTrace};
pub const NO_DATA_BLOCK_ID: u32 = 0;
pub trait CallManager: 'static {
type Machine: Machine;
fn new(machine: Self::Machine, gas_limit: i64, origin: Address, nonce: u64) -> Self;
fn send<K: Kernel<CallManager = Self>>(
&mut self,
from: ActorID,
to: Address,
method: MethodNum,
params: Option<kernel::Block>,
value: &TokenAmount,
) -> Result<InvocationResult>;
fn with_transaction(
&mut self,
f: impl FnOnce(&mut Self) -> Result<InvocationResult>,
) -> Result<InvocationResult>;
fn finish(self) -> (FinishRet, Self::Machine);
fn machine(&self) -> &Self::Machine;
fn machine_mut(&mut self) -> &mut Self::Machine;
fn gas_tracker(&self) -> &GasTracker;
fn gas_tracker_mut(&mut self) -> &mut GasTracker;
fn origin(&self) -> Address;
fn nonce(&self) -> u64;
fn next_actor_idx(&mut self) -> u64;
fn invocation_count(&self) -> u64;
fn price_list(&self) -> &PriceList {
self.machine().context().price_list
}
fn context(&self) -> &MachineContext {
self.machine().context()
}
fn blockstore(&self) -> &<Self::Machine as Machine>::Blockstore {
self.machine().blockstore()
}
fn externs(&self) -> &<Self::Machine as Machine>::Externs {
self.machine().externs()
}
fn state_tree(&self) -> &StateTree<<Self::Machine as Machine>::Blockstore> {
self.machine().state_tree()
}
fn state_tree_mut(&mut self) -> &mut StateTree<<Self::Machine as Machine>::Blockstore> {
self.machine_mut().state_tree_mut()
}
fn charge_gas(&mut self, charge: GasCharge) -> Result<()> {
self.gas_tracker_mut().apply_charge(charge)?;
Ok(())
}
fn tracing(&self) -> bool {
self.machine().context().tracing
}
fn trace(&mut self, event: ExecutionEvent);
}
#[derive(Clone, Debug)]
pub enum InvocationResult {
Return(Option<kernel::Block>),
Failure(ExitCode),
}
impl Default for InvocationResult {
fn default() -> Self {
Self::Return(Default::default())
}
}
impl InvocationResult {
pub fn exit_code(&self) -> ExitCode {
match self {
Self::Return(_) => ExitCode::OK,
Self::Failure(e) => *e,
}
}
}
pub struct FinishRet {
pub gas_used: i64,
pub backtrace: Backtrace,
pub exec_trace: ExecutionTrace,
}