mirror of
https://github.com/fluencelabs/wasm-utils
synced 2025-05-16 17:21:23 +00:00
convert to tabs
This commit is contained in:
parent
b81573d2b8
commit
a2922a6fb0
@ -12,154 +12,154 @@ pub struct StorageValue([u8; 32]);
|
|||||||
struct ErrorStorage;
|
struct ErrorStorage;
|
||||||
|
|
||||||
impl StorageKey {
|
impl StorageKey {
|
||||||
// todo: deal with memory views
|
// todo: deal with memory views
|
||||||
fn from_mem(vec: Vec<u8>) -> Result<Self, ErrorStorage> {
|
fn from_mem(vec: Vec<u8>) -> Result<Self, ErrorStorage> {
|
||||||
if vec.len() != 32 { return Err(ErrorStorage); }
|
if vec.len() != 32 { return Err(ErrorStorage); }
|
||||||
let mut result = StorageKey([0u8; 32]);
|
let mut result = StorageKey([0u8; 32]);
|
||||||
result.0.copy_from_slice(&vec[0..32]);
|
result.0.copy_from_slice(&vec[0..32]);
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StorageValue {
|
impl StorageValue {
|
||||||
// todo: deal with memory views
|
// todo: deal with memory views
|
||||||
// todo: deal with variable-length values when it comes
|
// todo: deal with variable-length values when it comes
|
||||||
fn from_mem(vec: Vec<u8>) -> Result<Self, ErrorStorage> {
|
fn from_mem(vec: Vec<u8>) -> Result<Self, ErrorStorage> {
|
||||||
if vec.len() != 32 { return Err(ErrorStorage); }
|
if vec.len() != 32 { return Err(ErrorStorage); }
|
||||||
let mut result = StorageValue([0u8; 32]);
|
let mut result = StorageValue([0u8; 32]);
|
||||||
result.0.copy_from_slice(&vec[0..32]);
|
result.0.copy_from_slice(&vec[0..32]);
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_slice(&self) -> &[u8] {
|
fn as_slice(&self) -> &[u8] {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Runtime {
|
pub struct Runtime {
|
||||||
gas_counter: u64,
|
gas_counter: u64,
|
||||||
gas_limit: u64,
|
gas_limit: u64,
|
||||||
dynamic_top: u32,
|
dynamic_top: u32,
|
||||||
storage: HashMap<StorageKey, StorageValue>,
|
storage: HashMap<StorageKey, StorageValue>,
|
||||||
memory: Arc<interpreter::MemoryInstance>,
|
memory: Arc<interpreter::MemoryInstance>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ErrorAlloc;
|
pub struct ErrorAlloc;
|
||||||
|
|
||||||
impl Runtime {
|
impl Runtime {
|
||||||
pub fn with_params(memory: Arc<interpreter::MemoryInstance>, stack_space: u32, gas_limit: u64) -> Runtime {
|
pub fn with_params(memory: Arc<interpreter::MemoryInstance>, stack_space: u32, gas_limit: u64) -> Runtime {
|
||||||
Runtime {
|
Runtime {
|
||||||
gas_counter: 0,
|
gas_counter: 0,
|
||||||
gas_limit: gas_limit,
|
gas_limit: gas_limit,
|
||||||
dynamic_top: stack_space,
|
dynamic_top: stack_space,
|
||||||
storage: HashMap::new(),
|
storage: HashMap::new(),
|
||||||
memory: memory,
|
memory: memory,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn storage_write(&mut self, context: interpreter::CallerContext)
|
pub fn storage_write(&mut self, context: interpreter::CallerContext)
|
||||||
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
|
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
|
||||||
{
|
{
|
||||||
let val_ptr = context.value_stack.pop_as::<i32>()?;
|
let val_ptr = context.value_stack.pop_as::<i32>()?;
|
||||||
let key_ptr = context.value_stack.pop_as::<i32>()?;
|
let key_ptr = context.value_stack.pop_as::<i32>()?;
|
||||||
|
|
||||||
let key = StorageKey::from_mem(self.memory.get(key_ptr as u32, 32)?)
|
let key = StorageKey::from_mem(self.memory.get(key_ptr as u32, 32)?)
|
||||||
.map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))?;
|
.map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))?;
|
||||||
let val = StorageValue::from_mem(self.memory.get(val_ptr as u32, 32)?)
|
let val = StorageValue::from_mem(self.memory.get(val_ptr as u32, 32)?)
|
||||||
.map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))?;
|
.map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))?;
|
||||||
|
|
||||||
println!("write storage {:?} = {:?}", key, val);
|
println!("write storage {:?} = {:?}", key, val);
|
||||||
|
|
||||||
self.storage.insert(key, val);
|
self.storage.insert(key, val);
|
||||||
|
|
||||||
Ok(Some(0i32.into()))
|
Ok(Some(0i32.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn storage_read(&mut self, context: interpreter::CallerContext)
|
pub fn storage_read(&mut self, context: interpreter::CallerContext)
|
||||||
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
|
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
|
||||||
{
|
{
|
||||||
// arguments passed are in backward order (since it is stack)
|
// arguments passed are in backward order (since it is stack)
|
||||||
let val_ptr = context.value_stack.pop_as::<i32>()?;
|
let val_ptr = context.value_stack.pop_as::<i32>()?;
|
||||||
let key_ptr = context.value_stack.pop_as::<i32>()?;
|
let key_ptr = context.value_stack.pop_as::<i32>()?;
|
||||||
|
|
||||||
let key = StorageKey::from_mem(self.memory.get(key_ptr as u32, 32)?)
|
let key = StorageKey::from_mem(self.memory.get(key_ptr as u32, 32)?)
|
||||||
.map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))?;
|
.map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))?;
|
||||||
let empty = StorageValue([0u8; 32]);
|
let empty = StorageValue([0u8; 32]);
|
||||||
let val = self.storage.get(&key).unwrap_or(&empty);
|
let val = self.storage.get(&key).unwrap_or(&empty);
|
||||||
|
|
||||||
self.memory.set(val_ptr as u32, val.as_slice())?;
|
self.memory.set(val_ptr as u32, val.as_slice())?;
|
||||||
|
|
||||||
println!("read storage {:?} (evaluated as {:?})", key, val);
|
println!("read storage {:?} (evaluated as {:?})", key, val);
|
||||||
|
|
||||||
Ok(Some(0.into()))
|
Ok(Some(0.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn malloc(&mut self, context: interpreter::CallerContext)
|
pub fn malloc(&mut self, context: interpreter::CallerContext)
|
||||||
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
|
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
|
||||||
{
|
{
|
||||||
let amount = context.value_stack.pop_as::<i32>()? as u32;
|
let amount = context.value_stack.pop_as::<i32>()? as u32;
|
||||||
let previous_top = self.dynamic_top;
|
let previous_top = self.dynamic_top;
|
||||||
self.dynamic_top = previous_top + amount;
|
self.dynamic_top = previous_top + amount;
|
||||||
Ok(Some((previous_top as i32).into()))
|
Ok(Some((previous_top as i32).into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn alloc(&mut self, amount: u32) -> Result<u32, ErrorAlloc> {
|
pub fn alloc(&mut self, amount: u32) -> Result<u32, ErrorAlloc> {
|
||||||
let previous_top = self.dynamic_top;
|
let previous_top = self.dynamic_top;
|
||||||
self.dynamic_top = previous_top + amount;
|
self.dynamic_top = previous_top + amount;
|
||||||
Ok(previous_top.into())
|
Ok(previous_top.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gas(&mut self, context: interpreter::CallerContext)
|
fn gas(&mut self, context: interpreter::CallerContext)
|
||||||
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
|
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
|
||||||
{
|
{
|
||||||
let prev = self.gas_counter;
|
let prev = self.gas_counter;
|
||||||
let update = context.value_stack.pop_as::<i32>()? as u64;
|
let update = context.value_stack.pop_as::<i32>()? as u64;
|
||||||
if prev + update > self.gas_limit {
|
if prev + update > self.gas_limit {
|
||||||
// exceeds gas
|
// exceeds gas
|
||||||
Err(interpreter::Error::Trap(format!("Gas exceeds limits of {}", self.gas_limit)))
|
Err(interpreter::Error::Trap(format!("Gas exceeds limits of {}", self.gas_limit)))
|
||||||
} else {
|
} else {
|
||||||
self.gas_counter = prev + update;
|
self.gas_counter = prev + update;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn user_trap(&mut self, _context: interpreter::CallerContext)
|
fn user_trap(&mut self, _context: interpreter::CallerContext)
|
||||||
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
|
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
|
||||||
{
|
{
|
||||||
Err(interpreter::Error::Trap("unknown trap".to_owned()))
|
Err(interpreter::Error::Trap("unknown trap".to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn user_noop(&mut self,
|
fn user_noop(&mut self,
|
||||||
_context: interpreter::CallerContext
|
_context: interpreter::CallerContext
|
||||||
) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
|
) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl interpreter::UserFunctionExecutor for Runtime {
|
impl interpreter::UserFunctionExecutor for Runtime {
|
||||||
fn execute(&mut self, name: &str, context: interpreter::CallerContext)
|
fn execute(&mut self, name: &str, context: interpreter::CallerContext)
|
||||||
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
|
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
|
||||||
{
|
{
|
||||||
match name {
|
match name {
|
||||||
"_malloc" => {
|
"_malloc" => {
|
||||||
self.malloc(context)
|
self.malloc(context)
|
||||||
},
|
},
|
||||||
"_free" => {
|
"_free" => {
|
||||||
self.user_noop(context)
|
self.user_noop(context)
|
||||||
},
|
},
|
||||||
"_storage_read" => {
|
"_storage_read" => {
|
||||||
self.storage_read(context)
|
self.storage_read(context)
|
||||||
},
|
},
|
||||||
"_storage_write" => {
|
"_storage_write" => {
|
||||||
self.storage_write(context)
|
self.storage_write(context)
|
||||||
},
|
},
|
||||||
"gas" => {
|
"gas" => {
|
||||||
self.gas(context)
|
self.gas(context)
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
self.user_trap(context)
|
self.user_trap(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user