1#![warn(missing_docs)]
11#![allow(unreachable_code)]
12
13use std::collections::HashMap;
14use std::{fmt, io};
15
16use canonical::CanonError;
17
18mod call_context;
19mod compiler;
20mod compiler_config;
21mod contract;
22mod env;
23mod gas;
24mod memory;
25mod modules;
26mod ops;
27mod resolver;
28mod state;
29
30pub use dusk_abi;
31
32pub use contract::{Contract, ContractId};
33pub use gas::{Gas, GasMeter};
34pub use state::NetworkState;
35
36#[cfg(feature = "persistence")]
37pub use state::persist::NetworkStateId;
38
39use thiserror::Error;
40use wasmer_vm::TrapCode;
41
42#[derive(Error)]
43pub enum VMError {
45 InvalidArguments,
47 ContractPanic(String),
49 MemoryNotFound,
51 InstrumentationError(modules::InstrumentationError),
53 InvalidABICall,
55 InvalidUtf8,
57 InvalidEd25519PublicKey,
59 InvalidEd25519Signature,
61 ContractReturn(i32, i32),
63 OutOfGas,
65 NotEnoughFunds,
67 UnknownContract,
69 WASMError(failure::Error),
71 IOError(io::Error),
73 InvalidWASMModule,
75 StoreError(CanonError),
77 PersistenceSerializationError(CanonError),
79 PersistenceError(String),
81 WasmerExportError(wasmer::ExportError),
83 WasmerRuntimeError(wasmer::RuntimeError),
85 WasmerCompileError(wasmer::CompileError),
87 WasmerTrap(TrapCode),
89 WasmerInstantiationError(wasmer::InstantiationError),
91}
92
93impl From<io::Error> for VMError {
94 fn from(e: io::Error) -> Self {
95 VMError::IOError(e)
96 }
97}
98
99impl From<modules::InstrumentationError> for VMError {
100 fn from(e: modules::InstrumentationError) -> Self {
101 VMError::InstrumentationError(e)
102 }
103}
104
105impl From<gas::GasError> for VMError {
106 fn from(_: gas::GasError) -> Self {
107 VMError::OutOfGas
109 }
110}
111
112impl From<wasmer::InstantiationError> for VMError {
113 fn from(e: wasmer::InstantiationError) -> Self {
114 VMError::WasmerInstantiationError(e)
115 }
116}
117
118impl From<wasmer::ExportError> for VMError {
119 fn from(e: wasmer::ExportError) -> Self {
120 VMError::WasmerExportError(e)
121 }
122}
123
124impl From<wasmer::CompileError> for VMError {
125 fn from(e: wasmer::CompileError) -> Self {
126 VMError::WasmerCompileError(e)
127 }
128}
129
130impl From<wasmer::RuntimeError> for VMError {
131 fn from(e: wasmer::RuntimeError) -> Self {
132 let runtime_error = e.clone();
133 match e.to_trap() {
134 Some(trap_code) => VMError::WasmerTrap(trap_code),
135 _ => VMError::WasmerRuntimeError(runtime_error),
136 }
137 }
138}
139
140impl VMError {
143 pub fn from_store_error(err: CanonError) -> Self {
145 VMError::StoreError(err)
146 }
147}
148
149impl fmt::Display for VMError {
150 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
151 match self {
152 VMError::InvalidArguments => write!(f, "Invalid arguments")?,
153 VMError::ContractPanic(string) => {
154 write!(f, "Contract panic \"{}\"", string)?
155 }
156 VMError::InvalidUtf8 => write!(f, "Invalid UTF-8")?,
157 VMError::InvalidEd25519PublicKey => {
158 write!(f, "Invalid Ed25519 Public Key")?
159 }
160 VMError::InvalidEd25519Signature => {
161 write!(f, "Invalid Ed25519 Signature")?
162 }
163 VMError::ContractReturn(_, _) => write!(f, "Contract Return")?,
164 VMError::OutOfGas => write!(f, "Out of Gas error")?,
165 VMError::NotEnoughFunds => write!(f, "Not enough funds error")?,
166 VMError::WASMError(e) => write!(f, "WASM Error ({:?})", e)?,
167 VMError::MemoryNotFound => write!(f, "Memory not found")?,
168 VMError::InvalidABICall => write!(f, "Invalid ABI Call")?,
169 VMError::IOError(e) => write!(f, "Input/Output Error ({:?})", e)?,
170 VMError::UnknownContract => write!(f, "Unknown Contract")?,
171 VMError::InvalidWASMModule => write!(f, "Invalid WASM module")?,
172 VMError::StoreError(e) => write!(f, "Store error {:?}", e)?,
173 VMError::InstrumentationError(e) => {
174 write!(f, "Instrumentalization error {:?}", e)?
175 }
176 VMError::PersistenceSerializationError(e) => {
177 write!(f, "Persistence serialization error {:?}", e)?
178 }
179 VMError::PersistenceError(string) => {
180 write!(f, "Persistence error \"{}\"", string)?
181 }
182 VMError::WasmerExportError(e) => match e {
183 wasmer::ExportError::IncompatibleType => {
184 write!(f, "WASMER Export Error - incompatible export type")?
185 }
186 wasmer::ExportError::Missing(s) => {
187 write!(f, "WASMER Export Error - missing: \"{}\"", s)?
188 }
189 },
190 VMError::WasmerRuntimeError(e) => {
191 write!(f, "WASMER Runtime Error {:?}", e)?
192 }
193 VMError::WasmerTrap(e) => write!(f, "WASMER Trap ({:?})", e)?,
194 VMError::WasmerInstantiationError(e) => {
195 write!(f, "WASMER Instantiation Error ({:?})", e)?
196 }
197 VMError::WasmerCompileError(e) => {
198 write!(f, "WASMER Compile Error {:?}", e)?
199 }
200 }
201 Ok(())
202 }
203}
204
205impl fmt::Debug for VMError {
206 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
207 write!(f, "{}", self)
208 }
209}
210
211#[derive(Clone, PartialEq, Eq)]
213pub struct Schedule {
214 pub version: u32,
216
217 pub regular_op_cost: Gas,
219
220 pub grow_mem_cost: Gas,
222
223 pub max_stack_height: u32,
228
229 pub max_table_size: u32,
231
232 pub max_memory_pages: u32,
234
235 pub has_forbidden_floats: bool,
237
238 pub has_grow_cost: bool,
240
241 pub has_metering: bool,
243
244 pub has_table_size_limit: bool,
246
247 pub per_type_op_cost: HashMap<String, u32>,
249}
250
251impl Default for Schedule {
252 fn default() -> Schedule {
253 let per_type_op_cost: HashMap<String, u32> = [
254 ("bit", 1),
255 ("add", 1),
256 ("mul", 1),
257 ("div", 1),
258 ("load", 1),
259 ("store", 1),
260 ("const", 1),
261 ("local", 1),
262 ("global", 1),
263 ("flow", 1),
264 ("integer_comp", 1),
265 ("float_comp", 1),
266 ("float", 1),
267 ("conversion", 1),
268 ("float_conversion", 1),
269 ("reinterpret", 1),
270 ("unreachable", 1),
271 ("nop", 1),
272 ("current_mem", 1),
273 ("grow_mem", 1),
274 ]
275 .iter()
276 .map(|(s, c)| (s.to_string(), *c))
277 .collect();
278 Schedule {
279 version: 0,
280 regular_op_cost: 1,
281 grow_mem_cost: 1,
282 max_stack_height: 65536,
283 max_table_size: 16384,
284 max_memory_pages: 16384,
285 has_forbidden_floats: true,
286 has_grow_cost: true,
287 has_metering: true,
288 has_table_size_limit: true,
289 per_type_op_cost,
290 }
291 }
292}
293
294impl Schedule {
295 pub fn with_version(version: u32) -> Self {
297 Self {
298 version,
299 ..Self::default()
300 }
301 }
302}