#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
mod accessors;
pub mod env;
pub mod error;
mod funcs;
mod log;
pub mod memory;
#[cfg(any(feature = "mock", test))]
pub mod mock;
mod runtime;
pub mod state;
use gear_core::{
env::Externalities,
gas::{CountersOwner, GasAmount},
memory::MemoryInterval,
};
use gear_lazy_pages_common::ProcessAccessError;
pub trait BackendExternalities: Externalities + CountersOwner {
fn gas_amount(&self) -> GasAmount;
fn pre_process_memory_accesses(
&mut self,
reads: &[MemoryInterval],
writes: &[MemoryInterval],
gas_counter: &mut u64,
) -> Result<(), ProcessAccessError>;
}
#[cfg(test)]
mod tests {
use crate::{
env::{BackendReport, Environment},
error::ActorTerminationReason,
mock::MockExt,
};
use gear_core::{gas_metering::CustomConstantCostRules, message::DispatchKind};
use gear_wasm_instrument::{
FuncType, Function, Import, InstrumentationBuilder, ModuleBuilder, SyscallKind, SyscallName,
};
use tracing_subscriber::EnvFilter;
#[test]
fn test_syscalls_table() {
tracing_subscriber::fmt::fmt()
.with_env_filter(EnvFilter::from_default_env())
.with_test_writer()
.init();
for syscall_kind in [SyscallKind::Vara, SyscallKind::Eth] {
let mut module = ModuleBuilder::default();
module.add_func(FuncType::new([], []), Function::default());
for name in SyscallName::instrumentable(syscall_kind) {
let sign = name.signature();
let type_no = module.push_type(sign.func_type());
module.push_import(Import::func("env", name.to_str(), type_no));
}
let module = InstrumentationBuilder::new("env")
.with_gas_limiter(|_| CustomConstantCostRules::default())
.instrument(module.build())
.unwrap();
let code = module.serialize().unwrap();
let ext = MockExt::default();
let env = Environment::new(
ext,
&code,
DispatchKind::Init,
Default::default(),
0.into(),
syscall_kind,
)
.unwrap();
let report = env.execute(|_, _, _| {}).unwrap();
let BackendReport {
termination_reason, ..
} = report;
assert_eq!(termination_reason, ActorTerminationReason::Success.into());
}
}
}