mirror of
https://github.com/fluencelabs/wasm-utils
synced 2025-07-04 00:41:37 +00:00
somewhat working
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
use parity_wasm::interpreter;
|
use parity_wasm::interpreter::{self, ModuleInstance};
|
||||||
use runtime::Runtime;
|
use runtime::Runtime;
|
||||||
|
|
||||||
pub struct Arena {
|
pub struct Arena {
|
||||||
@ -18,7 +18,7 @@ impl Arena {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl interpreter::UserFunctionInterface for Arena {
|
impl interpreter::UserFunctionInterface for Arena {
|
||||||
fn call(&mut self, context: interpreter::CallerContext) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
|
fn call(&mut self, _module: &ModuleInstance, context: interpreter::CallerContext) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
|
||||||
let amount = context.value_stack.pop_as::<i32>()?;
|
let amount = context.value_stack.pop_as::<i32>()?;
|
||||||
self.alloc(amount as u32)
|
self.alloc(amount as u32)
|
||||||
.map(|val| Some((val as i32).into()))
|
.map(|val| Some((val as i32).into()))
|
||||||
|
@ -60,6 +60,7 @@ pub fn init(
|
|||||||
write_u32(&mut input_length, input.len() as u32);
|
write_u32(&mut input_length, input.len() as u32);
|
||||||
memory.set(input_ptr, input)?;
|
memory.set(input_ptr, input)?;
|
||||||
println!("input_ptr: {}", input_ptr);
|
println!("input_ptr: {}", input_ptr);
|
||||||
|
println!("input: {:?}", memory.get(input_ptr, input.len()));
|
||||||
}
|
}
|
||||||
|
|
||||||
memory.set(descriptor_ptr, &context_ptr_slc)?;
|
memory.set(descriptor_ptr, &context_ptr_slc)?;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use parity_wasm::interpreter;
|
use parity_wasm::interpreter::{self, ModuleInstance};
|
||||||
use runtime::Runtime;
|
use runtime::Runtime;
|
||||||
|
|
||||||
pub struct GasCounter {
|
pub struct GasCounter {
|
||||||
@ -6,7 +6,7 @@ pub struct GasCounter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl interpreter::UserFunctionInterface for GasCounter {
|
impl interpreter::UserFunctionInterface for GasCounter {
|
||||||
fn call(&mut self, context: interpreter::CallerContext) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
|
fn call(&mut self, _module: &ModuleInstance, context: interpreter::CallerContext) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
|
||||||
let prev = self.runtime.env().gas_counter.get();
|
let prev = self.runtime.env().gas_counter.get();
|
||||||
let update = context.value_stack.pop_as::<i32>()? as u64;
|
let update = context.value_stack.pop_as::<i32>()? as u64;
|
||||||
if prev + update > self.runtime.env().gas_limit {
|
if prev + update > self.runtime.env().gas_limit {
|
||||||
|
@ -53,7 +53,29 @@ fn main() {
|
|||||||
closure: Box::new(runtime.allocator()),
|
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_trap(&mut user_functions, "_emscripten_memcpy_big");
|
||||||
|
runtime::user_noop(&mut user_functions, "_free");
|
||||||
|
|
||||||
let program = parity_wasm::interpreter::ProgramInstance::with_functions(user_functions)
|
let program = parity_wasm::interpreter::ProgramInstance::with_functions(user_functions)
|
||||||
.expect("Program instance to be created");
|
.expect("Program instance to be created");
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::cell::Cell;
|
use std::cell::{Cell, RefCell};
|
||||||
|
|
||||||
use parity_wasm::{interpreter, elements};
|
use parity_wasm::{interpreter, elements};
|
||||||
use {alloc, gas_counter};
|
use {alloc, gas_counter, storage};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct RuntimeEnv {
|
pub struct RuntimeEnv {
|
||||||
pub gas_counter: Cell<u64>,
|
pub gas_counter: Cell<u64>,
|
||||||
pub gas_limit: u64,
|
pub gas_limit: u64,
|
||||||
pub dynamic_top: Cell<u32>,
|
pub dynamic_top: Cell<u32>,
|
||||||
|
pub storage: RefCell<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
@ -20,6 +21,7 @@ impl Runtime {
|
|||||||
gas_counter: Cell::new(0),
|
gas_counter: Cell::new(0),
|
||||||
gas_limit: gas_limit,
|
gas_limit: gas_limit,
|
||||||
dynamic_top: Cell::new(stack_space),
|
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 {
|
pub fn env(&self) -> &RuntimeEnv {
|
||||||
&*self.0
|
&*self.0
|
||||||
}
|
}
|
||||||
@ -44,7 +50,7 @@ pub fn user_trap(funcs: &mut interpreter::UserFunctions, func_name: &str) {
|
|||||||
let func_str = func_name.to_owned();
|
let func_str = func_name.to_owned();
|
||||||
funcs.insert(func_str.clone(),
|
funcs.insert(func_str.clone(),
|
||||||
interpreter::UserFunction {
|
interpreter::UserFunction {
|
||||||
params: vec![elements::ValueType::I32],
|
params: vec![],
|
||||||
result: Some(elements::ValueType::I32),
|
result: Some(elements::ValueType::I32),
|
||||||
closure: Box::new(UserTrap(func_str)),
|
closure: Box::new(UserTrap(func_str)),
|
||||||
}
|
}
|
||||||
@ -54,7 +60,32 @@ pub fn user_trap(funcs: &mut interpreter::UserFunctions, func_name: &str) {
|
|||||||
struct UserTrap(String);
|
struct UserTrap(String);
|
||||||
|
|
||||||
impl interpreter::UserFunctionInterface for UserTrap {
|
impl interpreter::UserFunctionInterface for UserTrap {
|
||||||
fn call(&mut self, context: interpreter::CallerContext) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
|
fn call(&mut self,
|
||||||
|
_module: &interpreter::ModuleInstance,
|
||||||
|
_context: interpreter::CallerContext
|
||||||
|
) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
|
||||||
Err(interpreter::Error::Trap(self.0.clone()))
|
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<Option<interpreter::RuntimeValue>, interpreter::Error> {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,32 +1,41 @@
|
|||||||
use parity_wasm::interpreter::ModuleInstanceInterface;
|
use parity_wasm::interpreter::{self, ItemIndex, ModuleInstanceInterface};
|
||||||
use parity_wasm::interpreter::ItemIndex;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use DEFAULT_MEMORY_INDEX;
|
use DEFAULT_MEMORY_INDEX;
|
||||||
|
use runtime::Runtime;
|
||||||
|
|
||||||
pub struct Storage {
|
pub struct Storage {
|
||||||
data: Vec<u8>,
|
runtime: Runtime,
|
||||||
module: Arc<ModuleInstanceInterface>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Error;
|
pub struct Error;
|
||||||
|
|
||||||
impl Storage {
|
impl Storage {
|
||||||
|
|
||||||
pub fn read(&self, offset: u32, len: u32, dst: u32) -> i32 {
|
pub fn new(runtime: Runtime) -> Self {
|
||||||
let memory = match self.module.memory(DEFAULT_MEMORY_INDEX) {
|
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; },
|
Err(_) => { return -1; },
|
||||||
Ok(memory) => memory,
|
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; }
|
Err(_) => { return -1; }
|
||||||
Ok(_) => { return len as i32; }
|
Ok(_) => { return len as i32; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(&mut self, offset: u32, len: u32, src: u32) -> i32 {
|
pub fn write(&mut self, module: &interpreter::ModuleInstance, offset: u32, len: u32, src: u32) -> i32 {
|
||||||
let memory = match self.module.memory(DEFAULT_MEMORY_INDEX) {
|
let mut data = self.runtime.env().storage.borrow_mut();
|
||||||
|
|
||||||
|
let memory = match module.memory(DEFAULT_MEMORY_INDEX) {
|
||||||
Err(_) => { return -1; },
|
Err(_) => { return -1; },
|
||||||
Ok(memory) => memory,
|
Ok(memory) => memory,
|
||||||
};
|
};
|
||||||
@ -36,16 +45,70 @@ impl Storage {
|
|||||||
Ok(slice) => slice,
|
Ok(slice) => slice,
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.data.len() < offset as usize + slice.len() {
|
if data.len() < offset as usize + slice.len() {
|
||||||
self.data.reserve(offset as usize + slice.len());
|
data.reserve(offset as usize + slice.len());
|
||||||
unsafe {
|
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
|
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<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()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct StorageRead(Storage);
|
||||||
|
|
||||||
|
impl interpreter::UserFunctionInterface for StorageRead {
|
||||||
|
fn call(&mut self,
|
||||||
|
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()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct StorageSize(Storage);
|
||||||
|
|
||||||
|
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()))
|
||||||
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user