#![deny(missing_docs, unsafe_code)]
pub use access::Access;
pub use cached::LazyCache;
#[doc(inline)]
pub use essential_asm::{self as asm, Op};
pub use essential_types as types;
#[doc(inline)]
pub use memory::Memory;
#[doc(inline)]
pub use op_access::OpAccess;
#[doc(inline)]
pub use repeat::Repeat;
#[doc(inline)]
pub use stack::Stack;
#[doc(inline)]
pub use state_read::StateRead;
#[doc(inline)]
pub use state_read::StateReads;
#[doc(inline)]
pub use total_control_flow::ProgramControlFlow;
#[doc(inline)]
pub use vm::Vm;
mod access;
mod alu;
pub mod bytecode;
mod cached;
mod compute;
mod crypto;
pub mod error;
mod memory;
mod op_access;
mod pred;
mod repeat;
mod sets;
mod stack;
mod state_read;
pub mod sync;
mod total_control_flow;
mod vm;
#[cfg(test)]
pub(crate) mod utils {
use crate::{StateRead, StateReads};
pub struct EmptyState;
impl StateRead for EmptyState {
type Error = String;
fn key_range(
&self,
_contract_addr: essential_types::ContentAddress,
_key: essential_types::Key,
_num_values: usize,
) -> Result<Vec<Vec<essential_asm::Word>>, Self::Error> {
Ok(vec![])
}
}
impl StateReads for EmptyState {
type Error = String;
type Pre = Self;
type Post = Self;
fn pre(&self) -> &Self::Pre {
self
}
fn post(&self) -> &Self::Post {
self
}
}
}
pub type BytecodeMapped<Bytes = Vec<u8>> = bytecode::BytecodeMapped<Op, Bytes>;
pub type BytecodeMappedSlice<'a> = bytecode::BytecodeMappedSlice<'a, Op>;
pub type Gas = u64;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct GasLimit {
pub per_yield: Gas,
pub total: Gas,
}
pub trait OpGasCost: Send + Sync {
fn op_gas_cost(&self, op: &Op) -> Gas;
}
impl GasLimit {
pub const DEFAULT_PER_YIELD: Gas = 4_096;
pub const UNLIMITED: Self = Self {
per_yield: Self::DEFAULT_PER_YIELD,
total: Gas::MAX,
};
}
impl<F> OpGasCost for F
where
F: Fn(&Op) -> Gas + Send + Sync,
{
fn op_gas_cost(&self, op: &Op) -> Gas {
(*self)(op)
}
}
#[cfg(feature = "tracing")]
pub(crate) fn trace_op_res<OA, T, E>(
oa: &OA,
pc: usize,
stack: &Stack,
memory: &Memory,
parent_memory: &Vec<std::sync::Arc<Memory>>,
halt: bool,
op_res: &Result<T, E>,
) where
OA: OpAccess,
OA::Op: core::fmt::Debug,
E: core::fmt::Display,
{
let op = oa
.op_access(pc)
.expect("must exist as retrieved previously")
.expect("must exist as retrieved previously");
let pc_op = format!("0x{:02X}: {op:?}", pc);
match op_res {
Ok(_) => {
if parent_memory.is_empty() {
tracing::trace!("{pc_op}\n ├── {:?}\n └── {:?}", stack, memory)
} else {
tracing::trace!(
"{pc_op}\n ├── {:?}\n ├── {:?}\n ├── {:?}\n └── {:?}",
stack,
memory,
parent_memory,
halt
)
}
}
Err(ref err) => {
tracing::trace!("{pc_op}");
tracing::debug!("{err}");
}
}
}