mirror of
https://github.com/pezkuwichain/wasm-instrument.git
synced 2026-06-12 19:21:07 +00:00
fully working rust runner
This commit is contained in:
@@ -31,11 +31,8 @@ impl From<interpreter::Error> for Error {
|
||||
pub fn init(
|
||||
env: &interpreter::ModuleInstanceInterface,
|
||||
runtime: &runtime::Runtime,
|
||||
context: &[u8],
|
||||
input: &[u8],
|
||||
) -> Result<WasmMemoryPtr, Error> {
|
||||
let mut context_ptr_slc = [0u8; 4];
|
||||
let mut context_length = [0u8; 4];
|
||||
let mut input_ptr_slc = [0u8; 4];
|
||||
let mut input_length = [0u8; 4];
|
||||
|
||||
@@ -46,29 +43,40 @@ pub fn init(
|
||||
println!("descriptor_ptr: {}", descriptor_ptr);
|
||||
let memory = env.memory(DEFAULT_MEMORY_INDEX)?;
|
||||
|
||||
if context.len() > 0 {
|
||||
let context_ptr = allocator.alloc(context.len() as u32)?;
|
||||
write_u32(&mut context_ptr_slc, context_ptr);
|
||||
write_u32(&mut context_length, context.len() as u32);
|
||||
memory.set(context_ptr, context)?;
|
||||
println!("context_ptr: {}", context_ptr);
|
||||
}
|
||||
|
||||
if input.len() > 0 {
|
||||
if input.len() > 0 {
|
||||
let input_ptr = allocator.alloc(input.len() as u32)?;
|
||||
write_u32(&mut input_ptr_slc, input_ptr);
|
||||
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()));
|
||||
} else {
|
||||
write_u32(&mut input_ptr_slc, 0);
|
||||
write_u32(&mut input_length, 0);
|
||||
}
|
||||
|
||||
memory.set(descriptor_ptr, &context_ptr_slc)?;
|
||||
memory.set(descriptor_ptr+4, &context_length)?;
|
||||
memory.set(descriptor_ptr+8, &input_ptr_slc)?;
|
||||
memory.set(descriptor_ptr+12, &input_length)?;
|
||||
memory.set(descriptor_ptr, &input_ptr_slc)?;
|
||||
memory.set(descriptor_ptr+4, &input_length)?;
|
||||
|
||||
// zero result ptr/len
|
||||
memory.set(descriptor_ptr+8, &[0u8; 4])?;
|
||||
memory.set(descriptor_ptr+12, &[0u8; 4])?;
|
||||
|
||||
println!("descriptor: {:?}", memory.get(descriptor_ptr, 16));
|
||||
|
||||
Ok(descriptor_ptr as i32)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_u32(slc: &[u8]) -> u32 {
|
||||
use std::ops::Shl;
|
||||
(slc[0] as u32) + (slc[1] as u32).shl(8) + (slc[2] as u32).shl(16) + (slc[3] as u32).shl(24)
|
||||
}
|
||||
|
||||
// pub fn retrieve(env:
|
||||
// env: &interpreter::ModuleInstanceInterface,
|
||||
// runtime: &runtime::Runtime,
|
||||
// descriptor_ptr: u32,
|
||||
// result_ptr: u32,
|
||||
// ) -> Result<Vec<u8>, Error> {
|
||||
// let memory = env.memory(DEFAULT_MEMORY_INDEX)?;
|
||||
|
||||
// }
|
||||
+7
-12
@@ -53,28 +53,22 @@ 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],
|
||||
params: vec![elements::ValueType::I32, 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],
|
||||
params: vec![elements::ValueType::I32, 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_trap(&mut user_functions, "invoke_vii");
|
||||
runtime::user_noop(&mut user_functions, "_free");
|
||||
|
||||
let program = parity_wasm::interpreter::ProgramInstance::with_functions(user_functions)
|
||||
@@ -87,12 +81,13 @@ fn main() {
|
||||
let descriptor = call_args::init(
|
||||
&*program.module("env").expect("env module to exist"),
|
||||
&runtime,
|
||||
&[],
|
||||
&[0u8; 128],
|
||||
&[3u8; 128],
|
||||
).expect("call descriptor initialization to succeed");
|
||||
|
||||
// Invoke _call method of the module
|
||||
module_instance.execute_export("_call", vec![descriptor.into()]).expect("_call to execute successfully");
|
||||
let return_ptr = module_instance.execute_export("_call", vec![descriptor.into()])
|
||||
.expect("_call to execute successfully")
|
||||
.expect("_call function to return result ptr");
|
||||
|
||||
// ???
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use parity_wasm::{interpreter, elements};
|
||||
use {alloc, gas_counter, storage};
|
||||
@@ -9,7 +10,7 @@ pub struct RuntimeEnv {
|
||||
pub gas_counter: Cell<u64>,
|
||||
pub gas_limit: u64,
|
||||
pub dynamic_top: Cell<u32>,
|
||||
pub storage: RefCell<Vec<u8>>,
|
||||
pub storage: RefCell<HashMap<storage::StorageKey, storage::StorageValue>>,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
@@ -21,7 +22,7 @@ impl Runtime {
|
||||
gas_counter: Cell::new(0),
|
||||
gas_limit: gas_limit,
|
||||
dynamic_top: Cell::new(stack_space),
|
||||
storage: Default::default(),
|
||||
storage: RefCell::new(HashMap::new()),
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
+66
-62
@@ -4,6 +4,37 @@ use std::sync::Arc;
|
||||
use DEFAULT_MEMORY_INDEX;
|
||||
use runtime::Runtime;
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Debug)]
|
||||
pub struct StorageKey([u8; 32]);
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct StorageValue([u8; 32]);
|
||||
|
||||
impl StorageKey {
|
||||
// todo: deal with memory views
|
||||
fn from_mem(vec: Vec<u8>) -> Result<Self, Error> {
|
||||
if vec.len() != 32 { return Err(Error); }
|
||||
let mut result = StorageKey([0u8; 32]);
|
||||
result.0.copy_from_slice(&vec[0..32]);
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl StorageValue {
|
||||
// todo: deal with memory views
|
||||
// todo: deal with variable-length values when it comes
|
||||
fn from_mem(vec: Vec<u8>) -> Result<Self, Error> {
|
||||
if vec.len() != 32 { return Err(Error); }
|
||||
let mut result = StorageValue([0u8; 32]);
|
||||
result.0.copy_from_slice(&vec[0..32]);
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn as_slice(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Storage {
|
||||
runtime: Runtime,
|
||||
}
|
||||
@@ -18,46 +49,6 @@ impl Storage {
|
||||
}
|
||||
}
|
||||
|
||||
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, &data[offset as usize..offset as usize + len as usize]) {
|
||||
Err(_) => { return -1; }
|
||||
Ok(_) => { return len as i32; }
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
let slice = match memory.get(src, len as usize) {
|
||||
Err(_) => { return -1; }
|
||||
Ok(slice) => slice,
|
||||
};
|
||||
|
||||
if data.len() < offset as usize + slice.len() {
|
||||
data.reserve(offset as usize + slice.len());
|
||||
unsafe {
|
||||
data.set_len(offset as usize + slice.len());
|
||||
}
|
||||
}
|
||||
data[offset as usize..offset as usize + slice.len()].copy_from_slice(&slice[..]);
|
||||
|
||||
slice.len() as i32
|
||||
}
|
||||
|
||||
pub fn size(&self, _module: &interpreter::ModuleInstance) -> u32 { self.runtime.env().storage.borrow().len() as u32 }
|
||||
|
||||
pub fn writer(self) -> StorageWrite {
|
||||
StorageWrite(self)
|
||||
}
|
||||
@@ -65,10 +56,6 @@ impl Storage {
|
||||
pub fn reader(self) -> StorageRead {
|
||||
StorageRead(self)
|
||||
}
|
||||
|
||||
pub fn sizer(self) -> StorageSize {
|
||||
StorageSize(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StorageWrite(Storage);
|
||||
@@ -78,11 +65,24 @@ impl interpreter::UserFunctionInterface for StorageWrite {
|
||||
module: &interpreter::ModuleInstance,
|
||||
context: interpreter::CallerContext,
|
||||
) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
|
||||
let offset = context.value_stack.pop_as::<i32>()?;
|
||||
let len = context.value_stack.pop_as::<i32>()?;
|
||||
let ptr = context.value_stack.pop_as::<i32>()?;
|
||||
|
||||
Ok(Some(self.0.write(module, offset as u32, len as u32, ptr as u32).into()))
|
||||
// arguments passed are in backward order (since it is stack)
|
||||
let val_ptr = context.value_stack.pop_as::<i32>()?;
|
||||
let key_ptr = context.value_stack.pop_as::<i32>()?;
|
||||
|
||||
let memory = match module.memory(DEFAULT_MEMORY_INDEX) {
|
||||
Err(_) => { return Ok(Some((-1i32).into())) },
|
||||
Ok(memory) => memory,
|
||||
};
|
||||
|
||||
let key = StorageKey::from_mem(memory.get(key_ptr as u32, 32)?)
|
||||
.map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))?;
|
||||
let val = StorageValue::from_mem(memory.get(val_ptr as u32, 32)?)
|
||||
.map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))?;
|
||||
|
||||
println!("set storage {:?} = {:?}", key, val);
|
||||
|
||||
Ok(Some(0.into()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,22 +93,26 @@ impl interpreter::UserFunctionInterface for StorageRead {
|
||||
module: &interpreter::ModuleInstance,
|
||||
context: interpreter::CallerContext,
|
||||
) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
|
||||
let offset = context.value_stack.pop_as::<i32>()?;
|
||||
let len = context.value_stack.pop_as::<i32>()?;
|
||||
let ptr = context.value_stack.pop_as::<i32>()?;
|
||||
|
||||
Ok(Some(self.0.read(module, offset as u32, len as u32, ptr as u32).into()))
|
||||
}
|
||||
}
|
||||
// arguments passed are in backward order (since it is stack)
|
||||
let val_ptr = context.value_stack.pop_as::<i32>()?;
|
||||
let key_ptr = context.value_stack.pop_as::<i32>()?;
|
||||
|
||||
let memory = match module.memory(DEFAULT_MEMORY_INDEX) {
|
||||
Err(_) => { return Ok(Some((-1i32).into())) },
|
||||
Ok(memory) => memory,
|
||||
};
|
||||
|
||||
pub struct StorageSize(Storage);
|
||||
let key = StorageKey::from_mem(memory.get(key_ptr as u32, 32)?)
|
||||
.map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))?;
|
||||
let empty = StorageValue([0u8; 32]);
|
||||
let storage = self.0.runtime.env().storage.borrow();
|
||||
let val = storage.get(&key).unwrap_or(&empty);
|
||||
|
||||
impl interpreter::UserFunctionInterface for StorageSize {
|
||||
fn call(&mut self,
|
||||
module: &interpreter::ModuleInstance,
|
||||
context: interpreter::CallerContext,
|
||||
) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
|
||||
{
|
||||
Ok(Some((self.0.size(module) as i32).into()))
|
||||
memory.set(val_ptr as u32, val.as_slice());
|
||||
|
||||
println!("read storage {:?} (evaluated as {:?})", key, val);
|
||||
|
||||
Ok(Some(0.into()))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user