Skip to main content

rns_hooks/
runtime.rs

1use crate::engine_access::EngineAccess;
2use crate::wire::ActionWire;
3
4/// Default fuel budget per WASM invocation.
5pub const DEFAULT_FUEL: u64 = 10_000_000;
6/// Default maximum memory for WASM modules (16 MB).
7pub const DEFAULT_MAX_MEMORY: usize = 16 * 1024 * 1024;
8
9/// Data stored in each wasmtime `Store`.
10///
11/// Uses a raw pointer for `EngineAccess` because `Linker<T>` requires `T`
12/// without lifetime parameters. The Store is cached across calls for instance
13/// persistence, but `engine_access` is refreshed each call via `reset_per_call`
14/// and must only be dereferenced during the active call.
15pub struct StoreData {
16    pub engine_access: *const dyn EngineAccess,
17    pub now: f64,
18    pub injected_actions: Vec<ActionWire>,
19    pub log_messages: Vec<String>,
20}
21
22// Safety: StoreData is only used within a single-threaded driver loop.
23// The `engine_access` raw pointer is refreshed each call and only dereferenced
24// during that call while the borrow is live.
25unsafe impl Send for StoreData {}
26unsafe impl Sync for StoreData {}
27
28impl StoreData {
29    /// Access the engine through the raw pointer.
30    ///
31    /// # Safety
32    /// The caller must ensure the pointer is still valid.
33    pub unsafe fn engine(&self) -> &dyn EngineAccess {
34        &*self.engine_access
35    }
36
37    /// Reset per-call fields while preserving the store (and WASM linear memory).
38    pub fn reset_per_call(
39        &mut self,
40        engine_access: *const dyn EngineAccess,
41        now: f64,
42    ) {
43        self.engine_access = engine_access;
44        self.now = now;
45        self.injected_actions.clear();
46        self.log_messages.clear();
47    }
48}
49
50/// Wrapper around `wasmtime::Engine` with fuel-metering enabled.
51pub struct WasmRuntime {
52    engine: wasmtime::Engine,
53    fuel: u64,
54}
55
56impl WasmRuntime {
57    pub fn new() -> Result<Self, wasmtime::Error> {
58        let mut config = wasmtime::Config::new();
59        config.consume_fuel(true);
60        let engine = wasmtime::Engine::new(&config)?;
61        Ok(WasmRuntime {
62            engine,
63            fuel: DEFAULT_FUEL,
64        })
65    }
66
67    pub fn compile(&self, bytes: &[u8]) -> Result<wasmtime::Module, wasmtime::Error> {
68        wasmtime::Module::new(&self.engine, bytes)
69    }
70
71    pub fn engine(&self) -> &wasmtime::Engine {
72        &self.engine
73    }
74
75    pub fn fuel(&self) -> u64 {
76        self.fuel
77    }
78}