mirror of
https://github.com/fluencelabs/wasm-utils
synced 2025-03-28 08:51:05 +00:00
upto _emscripten_memcpy_big and user traps
This commit is contained in:
parent
7c4d12adeb
commit
bcdb942036
20
rust-runner/src/gas_counter.rs
Normal file
20
rust-runner/src/gas_counter.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use parity_wasm::interpreter;
|
||||||
|
use runtime::Runtime;
|
||||||
|
|
||||||
|
pub struct GasCounter {
|
||||||
|
pub runtime: Runtime,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl interpreter::UserFunctionInterface for GasCounter {
|
||||||
|
fn call(&mut self, context: interpreter::CallerContext) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
|
||||||
|
let prev = self.runtime.env().gas_counter.get();
|
||||||
|
let update = context.value_stack.pop_as::<i32>()? as u64;
|
||||||
|
if prev + update > self.runtime.env().gas_limit {
|
||||||
|
// exceeds gas
|
||||||
|
Err(interpreter::Error::Trap(format!("Gas exceeds limits of {}", self.runtime.env().gas_limit)))
|
||||||
|
} else {
|
||||||
|
self.runtime.env().gas_counter.set(prev + update);
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ mod gas_counter;
|
|||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use parity_wasm::interpreter::{self, ModuleInstanceInterface};
|
use parity_wasm::interpreter::{self, ModuleInstanceInterface};
|
||||||
|
use parity_wasm::elements;
|
||||||
|
|
||||||
pub const DEFAULT_MEMORY_INDEX: interpreter::ItemIndex = interpreter::ItemIndex::Internal(0);
|
pub const DEFAULT_MEMORY_INDEX: interpreter::ItemIndex = interpreter::ItemIndex::Internal(0);
|
||||||
pub type WasmMemoryPtr = i32;
|
pub type WasmMemoryPtr = i32;
|
||||||
@ -31,14 +32,36 @@ fn main() {
|
|||||||
|
|
||||||
let module = parity_wasm::deserialize_file(&args[1]).expect("Module deserialization to succeed");
|
let module = parity_wasm::deserialize_file(&args[1]).expect("Module deserialization to succeed");
|
||||||
|
|
||||||
// Second, create program instance
|
// Second, create runtime and program instance
|
||||||
let program = parity_wasm::interpreter::ProgramInstance::new().expect("Program instance to be created");
|
let runtime = runtime::Runtime::with_params(
|
||||||
|
5*1024*1024, // default stack space
|
||||||
|
65536, // runner arbitrary gas limit
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut user_functions = interpreter::UserFunctions::new();
|
||||||
|
user_functions.insert("gas".to_owned(),
|
||||||
|
interpreter::UserFunction {
|
||||||
|
params: vec![elements::ValueType::I32],
|
||||||
|
result: None,
|
||||||
|
closure: Box::new(runtime.gas_counter()),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
user_functions.insert("_malloc".to_owned(),
|
||||||
|
interpreter::UserFunction {
|
||||||
|
params: vec![elements::ValueType::I32],
|
||||||
|
result: Some(elements::ValueType::I32),
|
||||||
|
closure: Box::new(runtime.allocator()),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
runtime::user_trap(&mut user_functions, "_emscripten_memcpy_big");
|
||||||
|
|
||||||
|
let program = parity_wasm::interpreter::ProgramInstance::with_functions(user_functions)
|
||||||
|
.expect("Program instance to be created");
|
||||||
|
|
||||||
// Add module to the programm
|
// Add module to the programm
|
||||||
let module_instance = program.add_module("contract", module).expect("Module to be added successfully");
|
let module_instance = program.add_module("contract", module).expect("Module to be added successfully");
|
||||||
|
|
||||||
// Create allocator
|
// Create allocator
|
||||||
let runtime = runtime::Runtime::default();
|
|
||||||
runtime.allocator().alloc(5*1024*1024).expect("to allocate 5mb successfully"); // reserve stack space
|
runtime.allocator().alloc(5*1024*1024).expect("to allocate 5mb successfully"); // reserve stack space
|
||||||
|
|
||||||
// Initialize call descriptor
|
// Initialize call descriptor
|
||||||
|
60
rust-runner/src/runtime.rs
Normal file
60
rust-runner/src/runtime.rs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
use std::cell::Cell;
|
||||||
|
|
||||||
|
use parity_wasm::{interpreter, elements};
|
||||||
|
use {alloc, gas_counter};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct RuntimeEnv {
|
||||||
|
pub gas_counter: Cell<u64>,
|
||||||
|
pub gas_limit: u64,
|
||||||
|
pub dynamic_top: Cell<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
pub struct Runtime(Arc<RuntimeEnv>);
|
||||||
|
|
||||||
|
impl Runtime {
|
||||||
|
pub fn with_params(stack_space: u32, gas_limit: u64) -> Runtime {
|
||||||
|
Runtime(Arc::new(RuntimeEnv {
|
||||||
|
gas_counter: Cell::new(0),
|
||||||
|
gas_limit: gas_limit,
|
||||||
|
dynamic_top: Cell::new(stack_space),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allocator(&self) -> alloc::Arena {
|
||||||
|
alloc::Arena {
|
||||||
|
runtime: self.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gas_counter(&self) -> gas_counter::GasCounter {
|
||||||
|
gas_counter::GasCounter {
|
||||||
|
runtime: self.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn env(&self) -> &RuntimeEnv {
|
||||||
|
&*self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn user_trap(funcs: &mut interpreter::UserFunctions, func_name: &str) {
|
||||||
|
let func_str = func_name.to_owned();
|
||||||
|
funcs.insert(func_str.clone(),
|
||||||
|
interpreter::UserFunction {
|
||||||
|
params: vec![elements::ValueType::I32],
|
||||||
|
result: Some(elements::ValueType::I32),
|
||||||
|
closure: Box::new(UserTrap(func_str)),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct UserTrap(String);
|
||||||
|
|
||||||
|
impl interpreter::UserFunctionInterface for UserTrap {
|
||||||
|
fn call(&mut self, context: interpreter::CallerContext) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
|
||||||
|
Err(interpreter::Error::Trap(self.0.clone()))
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user