casper_executor_wasm_interface/
lib.rs1pub mod executor;
2
3use bytes::Bytes;
4use thiserror::Error;
5
6use casper_executor_wasm_common::{
7 error::{CallError, TrapCode, CALLEE_SUCCEEDED},
8 flags::ReturnFlags,
9};
10
11#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
19pub struct InterfaceVersion(u32);
20
21impl From<u32> for InterfaceVersion {
22 fn from(value: u32) -> Self {
23 InterfaceVersion(value)
24 }
25}
26
27pub type HostResult = Result<(), CallError>;
28
29#[must_use]
31pub fn u32_from_host_result(result: HostResult) -> u32 {
32 match result {
33 Ok(()) => CALLEE_SUCCEEDED,
34 Err(host_error) => host_error.into_u32(),
35 }
36}
37
38#[derive(Debug, Error)]
40pub enum Resolver {
41 #[error("export {name} not found.")]
42 Export { name: String },
43 #[error("function pointer {index} not found.")]
45 Table { index: u32 },
46}
47
48#[derive(Error, Debug)]
49pub enum ExportError {
50 #[error("incompatible type")]
53 IncompatibleType,
54 #[error("missing export {0}")]
56 Missing(String),
57}
58
59#[derive(Error, Debug)]
60#[non_exhaustive]
61pub enum MemoryError {
62 #[error("memory access out of bounds")]
64 HeapOutOfBounds,
65 #[error("address calculation overflow")]
67 Overflow,
68 #[error("string is not valid utf-8")]
70 NonUtf8String,
71}
72
73#[derive(Debug, Error)]
77pub enum VMError {
78 #[error("Return 0x{flags:?} {data:?}")]
79 Return {
80 flags: ReturnFlags,
81 data: Option<Bytes>,
82 },
83 #[error("export: {0}")]
84 Export(ExportError),
85 #[error("Out of gas")]
86 OutOfGas,
87 #[error("Trap: {0}")]
92 Trap(TrapCode),
93}
94
95impl VMError {
96 pub fn into_output_data(self) -> Option<Bytes> {
98 match self {
99 VMError::Return { data, .. } => data,
100 _ => None,
101 }
102 }
103}
104
105pub type VMResult<T> = Result<T, VMError>;
107
108#[derive(Clone, Debug)]
110pub struct Config {
111 gas_limit: u64,
112 memory_limit: u32,
113}
114
115impl Config {
116 #[must_use]
117 pub fn gas_limit(&self) -> u64 {
118 self.gas_limit
119 }
120
121 #[must_use]
122 pub fn memory_limit(&self) -> u32 {
123 self.memory_limit
124 }
125}
126
127#[derive(Clone, Debug, Default)]
129pub struct ConfigBuilder {
130 gas_limit: Option<u64>,
131 memory_limit: Option<u32>,
133}
134
135impl ConfigBuilder {
136 #[must_use]
138 pub fn new() -> Self {
139 Self::default()
140 }
141
142 #[must_use]
144 pub fn with_gas_limit(mut self, gas_limit: u64) -> Self {
145 self.gas_limit = Some(gas_limit);
146 self
147 }
148
149 #[must_use]
151 pub fn with_memory_limit(mut self, memory_limit: u32) -> Self {
152 self.memory_limit = Some(memory_limit);
153 self
154 }
155
156 #[must_use]
158 pub fn build(self) -> Config {
159 let gas_limit = self.gas_limit.expect("Required field missing: gas_limit");
160 let memory_limit = self
161 .memory_limit
162 .expect("Required field missing: memory_limit");
163 Config {
164 gas_limit,
165 memory_limit,
166 }
167 }
168}
169
170#[derive(Debug, Copy, Clone, PartialEq, Eq)]
171pub enum MeteringPoints {
172 Remaining(u64),
173 Exhausted,
174}
175
176impl MeteringPoints {
177 pub fn try_into_remaining(self) -> Result<u64, Self> {
178 if let Self::Remaining(v) = self {
179 Ok(v)
180 } else {
181 Err(self)
182 }
183 }
184}
185
186pub trait Caller {
191 type Context;
192
193 fn context(&self) -> &Self::Context;
194 fn context_mut(&mut self) -> &mut Self::Context;
195 fn bytecode(&self) -> Bytes;
197
198 fn has_export(&self, name: &str) -> bool;
200
201 fn memory_read(&self, offset: u32, size: usize) -> VMResult<Vec<u8>> {
202 let mut vec = vec![0; size];
203 self.memory_read_into(offset, &mut vec)?;
204 Ok(vec)
205 }
206 fn memory_read_into(&self, offset: u32, output: &mut [u8]) -> VMResult<()>;
207 fn memory_write(&self, offset: u32, data: &[u8]) -> VMResult<()>;
208 fn alloc(&mut self, idx: u32, size: usize, ctx: u32) -> VMResult<u32>;
212 fn gas_consumed(&mut self) -> MeteringPoints;
214 fn consume_gas(&mut self, value: u64) -> VMResult<()>;
216}
217
218#[derive(Debug, Error)]
219pub enum WasmPreparationError {
220 #[error("Missing export {0}")]
221 MissingExport(String),
222 #[error("Compile error: {0}")]
223 Compile(String),
224 #[error("Memory instantiation error: {0}")]
225 Memory(String),
226 #[error("Instantiation error: {0}")]
227 Instantiation(String),
228}
229
230#[derive(Debug)]
231pub struct GasUsage {
232 gas_limit: u64,
234 remaining_points: u64,
236}
237
238impl GasUsage {
239 #[must_use]
240 pub fn new(gas_limit: u64, remaining_points: u64) -> Self {
241 GasUsage {
242 gas_limit,
243 remaining_points,
244 }
245 }
246
247 #[must_use]
248 pub fn gas_spent(&self) -> u64 {
249 debug_assert!(self.remaining_points <= self.gas_limit);
250 self.gas_limit - self.remaining_points
251 }
252
253 #[must_use]
254 pub fn gas_limit(&self) -> u64 {
255 self.gas_limit
256 }
257
258 #[must_use]
259 pub fn remaining_points(&self) -> u64 {
260 self.remaining_points
261 }
262}
263
264pub trait WasmInstance {
266 type Context;
267
268 fn call_export(&mut self, name: &str) -> (Result<(), VMError>, GasUsage);
269 fn teardown(self) -> Self::Context;
270}