From 20496ae9b2652ee3084e2bd9ebb9f7d98253c14d Mon Sep 17 00:00:00 2001 From: NikVolf Date: Mon, 15 May 2017 19:15:09 +0300 Subject: [PATCH] somewhat working --- rust-runner/src/alloc.rs | 4 +- rust-runner/src/call_args.rs | 1 + rust-runner/src/gas_counter.rs | 4 +- rust-runner/src/main.rs | 22 ++++++++ rust-runner/src/runtime.rs | 39 +++++++++++++-- rust-runner/src/storage.rs | 91 ++++++++++++++++++++++++++++------ 6 files changed, 139 insertions(+), 22 deletions(-) diff --git a/rust-runner/src/alloc.rs b/rust-runner/src/alloc.rs index 05822c3..63c0eff 100644 --- a/rust-runner/src/alloc.rs +++ b/rust-runner/src/alloc.rs @@ -1,4 +1,4 @@ -use parity_wasm::interpreter; +use parity_wasm::interpreter::{self, ModuleInstance}; use runtime::Runtime; pub struct Arena { @@ -18,7 +18,7 @@ impl Arena { } impl interpreter::UserFunctionInterface for Arena { - fn call(&mut self, context: interpreter::CallerContext) -> Result, interpreter::Error> { + fn call(&mut self, _module: &ModuleInstance, context: interpreter::CallerContext) -> Result, interpreter::Error> { let amount = context.value_stack.pop_as::()?; self.alloc(amount as u32) .map(|val| Some((val as i32).into())) diff --git a/rust-runner/src/call_args.rs b/rust-runner/src/call_args.rs index 55805f3..75f244d 100644 --- a/rust-runner/src/call_args.rs +++ b/rust-runner/src/call_args.rs @@ -60,6 +60,7 @@ pub fn init( write_u32(&mut input_length, input.len() as u32); memory.set(input_ptr, input)?; println!("input_ptr: {}", input_ptr); + println!("input: {:?}", memory.get(input_ptr, input.len())); } memory.set(descriptor_ptr, &context_ptr_slc)?; diff --git a/rust-runner/src/gas_counter.rs b/rust-runner/src/gas_counter.rs index 924147a..2dc3e84 100644 --- a/rust-runner/src/gas_counter.rs +++ b/rust-runner/src/gas_counter.rs @@ -1,4 +1,4 @@ -use parity_wasm::interpreter; +use parity_wasm::interpreter::{self, ModuleInstance}; use runtime::Runtime; pub struct GasCounter { @@ -6,7 +6,7 @@ pub struct GasCounter { } impl interpreter::UserFunctionInterface for GasCounter { - fn call(&mut self, context: interpreter::CallerContext) -> Result, interpreter::Error> { + fn call(&mut self, _module: &ModuleInstance, context: interpreter::CallerContext) -> Result, interpreter::Error> { let prev = self.runtime.env().gas_counter.get(); let update = context.value_stack.pop_as::()? as u64; if prev + update > self.runtime.env().gas_limit { diff --git a/rust-runner/src/main.rs b/rust-runner/src/main.rs index 9f980da..1e00daf 100644 --- a/rust-runner/src/main.rs +++ b/rust-runner/src/main.rs @@ -53,7 +53,29 @@ fn main() { closure: Box::new(runtime.allocator()), } ); + user_functions.insert("_storage_size".to_owned(), + interpreter::UserFunction { + params: vec![elements::ValueType::I32], + result: Some(elements::ValueType::I32), + closure: Box::new(runtime.storage().sizer()), + } + ); + user_functions.insert("_storage_read".to_owned(), + interpreter::UserFunction { + params: vec![elements::ValueType::I32], + result: Some(elements::ValueType::I32), + closure: Box::new(runtime.storage().reader()), + } + ); + user_functions.insert("_storage_write".to_owned(), + interpreter::UserFunction { + params: vec![elements::ValueType::I32], + result: Some(elements::ValueType::I32), + closure: Box::new(runtime.storage().writer()), + } + ); runtime::user_trap(&mut user_functions, "_emscripten_memcpy_big"); + runtime::user_noop(&mut user_functions, "_free"); let program = parity_wasm::interpreter::ProgramInstance::with_functions(user_functions) .expect("Program instance to be created"); diff --git a/rust-runner/src/runtime.rs b/rust-runner/src/runtime.rs index ff48a04..83ecf35 100644 --- a/rust-runner/src/runtime.rs +++ b/rust-runner/src/runtime.rs @@ -1,14 +1,15 @@ use std::sync::Arc; -use std::cell::Cell; +use std::cell::{Cell, RefCell}; use parity_wasm::{interpreter, elements}; -use {alloc, gas_counter}; +use {alloc, gas_counter, storage}; #[derive(Default)] pub struct RuntimeEnv { pub gas_counter: Cell, pub gas_limit: u64, pub dynamic_top: Cell, + pub storage: RefCell>, } #[derive(Default, Clone)] @@ -20,6 +21,7 @@ impl Runtime { gas_counter: Cell::new(0), gas_limit: gas_limit, dynamic_top: Cell::new(stack_space), + storage: Default::default(), })) } @@ -35,6 +37,10 @@ impl Runtime { } } + pub fn storage(&self) -> storage::Storage { + storage::Storage::new(self.clone()) + } + pub fn env(&self) -> &RuntimeEnv { &*self.0 } @@ -44,7 +50,7 @@ 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], + params: vec![], result: Some(elements::ValueType::I32), closure: Box::new(UserTrap(func_str)), } @@ -54,7 +60,32 @@ pub fn user_trap(funcs: &mut interpreter::UserFunctions, func_name: &str) { struct UserTrap(String); impl interpreter::UserFunctionInterface for UserTrap { - fn call(&mut self, context: interpreter::CallerContext) -> Result, interpreter::Error> { + fn call(&mut self, + _module: &interpreter::ModuleInstance, + _context: interpreter::CallerContext + ) -> Result, interpreter::Error> { Err(interpreter::Error::Trap(self.0.clone())) } +} + +struct UserNoop; + +pub fn user_noop(funcs: &mut interpreter::UserFunctions, func_name: &str) { + let func_str = func_name.to_owned(); + funcs.insert(func_str.clone(), + interpreter::UserFunction { + params: vec![], + result: None, + closure: Box::new(UserNoop), + } + ); +} + +impl interpreter::UserFunctionInterface for UserNoop { + fn call(&mut self, + _module: &interpreter::ModuleInstance, + _context: interpreter::CallerContext + ) -> Result, interpreter::Error> { + Ok(None) + } } \ No newline at end of file diff --git a/rust-runner/src/storage.rs b/rust-runner/src/storage.rs index f35e2bd..4e97a28 100644 --- a/rust-runner/src/storage.rs +++ b/rust-runner/src/storage.rs @@ -1,32 +1,41 @@ -use parity_wasm::interpreter::ModuleInstanceInterface; -use parity_wasm::interpreter::ItemIndex; +use parity_wasm::interpreter::{self, ItemIndex, ModuleInstanceInterface}; use std::sync::Arc; use DEFAULT_MEMORY_INDEX; +use runtime::Runtime; pub struct Storage { - data: Vec, - module: Arc, + runtime: Runtime, } pub struct Error; impl Storage { - pub fn read(&self, offset: u32, len: u32, dst: u32) -> i32 { - let memory = match self.module.memory(DEFAULT_MEMORY_INDEX) { + pub fn new(runtime: Runtime) -> Self { + Storage { + runtime: runtime, + } + } + + pub fn read(&self, module: &interpreter::ModuleInstance, offset: u32, len: u32, dst: u32) -> i32 { + let data = self.runtime.env().storage.borrow(); + + let memory = match module.memory(DEFAULT_MEMORY_INDEX) { Err(_) => { return -1; }, Ok(memory) => memory, }; - match memory.set(dst, &self.data[offset as usize..offset as usize + len as usize]) { + match memory.set(dst, &data[offset as usize..offset as usize + len as usize]) { Err(_) => { return -1; } Ok(_) => { return len as i32; } } } - pub fn write(&mut self, offset: u32, len: u32, src: u32) -> i32 { - let memory = match self.module.memory(DEFAULT_MEMORY_INDEX) { + pub fn write(&mut self, module: &interpreter::ModuleInstance, offset: u32, len: u32, src: u32) -> i32 { + let mut data = self.runtime.env().storage.borrow_mut(); + + let memory = match module.memory(DEFAULT_MEMORY_INDEX) { Err(_) => { return -1; }, Ok(memory) => memory, }; @@ -36,16 +45,70 @@ impl Storage { Ok(slice) => slice, }; - if self.data.len() < offset as usize + slice.len() { - self.data.reserve(offset as usize + slice.len()); + if data.len() < offset as usize + slice.len() { + data.reserve(offset as usize + slice.len()); unsafe { - self.data.set_len(offset as usize + slice.len()); + data.set_len(offset as usize + slice.len()); } } - self.data[offset as usize..offset as usize + slice.len()].copy_from_slice(&slice[..]); + data[offset as usize..offset as usize + slice.len()].copy_from_slice(&slice[..]); slice.len() as i32 } - pub fn size(&self) -> u32 { self.data.len() as u32 } + pub fn size(&self, _module: &interpreter::ModuleInstance) -> u32 { self.runtime.env().storage.borrow().len() as u32 } + + pub fn writer(self) -> StorageWrite { + StorageWrite(self) + } + + pub fn reader(self) -> StorageRead { + StorageRead(self) + } + + pub fn sizer(self) -> StorageSize { + StorageSize(self) + } +} + +pub struct StorageWrite(Storage); + +impl interpreter::UserFunctionInterface for StorageWrite { + fn call(&mut self, + module: &interpreter::ModuleInstance, + context: interpreter::CallerContext, + ) -> Result, interpreter::Error> { + let offset = context.value_stack.pop_as::()?; + let len = context.value_stack.pop_as::()?; + let ptr = context.value_stack.pop_as::()?; + + Ok(Some(self.0.write(module, offset as u32, len as u32, ptr as u32).into())) + } +} + +pub struct StorageRead(Storage); + +impl interpreter::UserFunctionInterface for StorageRead { + fn call(&mut self, + module: &interpreter::ModuleInstance, + context: interpreter::CallerContext, + ) -> Result, interpreter::Error> { + let offset = context.value_stack.pop_as::()?; + let len = context.value_stack.pop_as::()?; + let ptr = context.value_stack.pop_as::()?; + + Ok(Some(self.0.read(module, offset as u32, len as u32, ptr as u32).into())) + } +} + +pub struct StorageSize(Storage); + +impl interpreter::UserFunctionInterface for StorageSize { + fn call(&mut self, + module: &interpreter::ModuleInstance, + context: interpreter::CallerContext, + ) -> Result, interpreter::Error> + { + Ok(Some((self.0.size(module) as i32).into())) + } } \ No newline at end of file