diff --git a/example/smart-contract/tests/runtime.rs b/example/smart-contract/tests/runtime.rs index 54f3be769..1c7d28d17 100644 --- a/example/smart-contract/tests/runtime.rs +++ b/example/smart-contract/tests/runtime.rs @@ -17,7 +17,6 @@ */ use darkfi::{ - node::{MemoryState, State}, runtime::{util::serialize_payload, vm_runtime::Runtime}, Result, }; @@ -41,16 +40,16 @@ fn run_contract() -> Result<()> { // ============================================================= // Build a ledger state so the runtime has something to work on // ============================================================= - let state_machine = State::dummy()?; + //let state_machine = State::dummy()?; // Add a nullifier to the nullifier set. (This is checked by the contract) - state_machine.nullifiers.insert(&[Nullifier::from(pallas::Base::from(0x10))])?; + //state_machine.nullifiers.insert(&[Nullifier::from(pallas::Base::from(0x10))])?; // ================================================================ // Load the wasm binary into memory and create an execution runtime // ================================================================ let wasm_bytes = std::fs::read("contract.wasm")?; - let mut runtime = Runtime::new(&wasm_bytes, MemoryState::new(state_machine))?; + let mut runtime = Runtime::new(&wasm_bytes)?; // ============================================= // Build some kind of payload to show an example diff --git a/src/error.rs b/src/error.rs index 9498b25d8..73bdca4cd 100644 --- a/src/error.rs +++ b/src/error.rs @@ -286,10 +286,18 @@ pub enum Error { #[error("Wasmer instantiation error: {0}")] WasmerInstantiationError(String), + #[cfg(feature = "wasm-runtime")] + #[error("wasm memory error")] + WasmerMemoryError, + #[cfg(feature = "wasm-runtime")] #[error("wasm runtime out of memory")] WasmerOomError, + #[cfg(feature = "wasm-runtime")] + #[error("contract execution error")] + ContractExecError(u64), + // ==================== // Miscellaneous errors // ==================== diff --git a/src/runtime/memory.rs b/src/runtime/memory.rs index 2f0dab0a6..6d65ab3c8 100644 --- a/src/runtime/memory.rs +++ b/src/runtime/memory.rs @@ -16,42 +16,27 @@ * along with this program. If not, see . */ -use wasmer::{Memory, WasmPtr}; +use wasmer::{MemoryView, WasmPtr}; use crate::{Error, Result}; pub trait MemoryManipulation { - fn write(&self, mem_offset: u32, value_slice: &[u8]) -> Result<()>; - fn read(&self, mem_offset: u32, value_len: usize) -> Option<&[u8]>; + fn write_slice(&self, value_slice: &[u8], mem_offset: u32) -> Result<()>; + fn read_slice(&self, value_len: usize, mem_offset: u32) -> Option<&[u8]>; } -impl MemoryManipulation for Memory { - fn write(&self, mem_offset: u32, value_slice: &[u8]) -> Result<()> { - // DISABLED - /* +impl<'a> MemoryManipulation for MemoryView<'a> { + fn write_slice(&self, value_slice: &[u8], mem_offset: u32) -> Result<()> { // Prepare WasmPtr - let target_ptr: WasmPtr = WasmPtr::new(mem_offset); + let ptr: WasmPtr = WasmPtr::new(mem_offset); - // Allocate necessary memory space on guest - let guest_value_slice = match target_ptr.deref(self, 0, value_slice.len() as u32) { - Some(slice) => slice, - None => [].to_vec(), - }; + // Write to the slice + let slice = ptr.slice(self, value_slice.len() as u32).map_err(|_| Error::WasmerOomError)?; - if guest_value_slice.is_empty() { - return Err(Error::WasmerOomError) - } - - // Copy bytes to guest - for i in 0..value_slice.len() { - guest_value_slice[i].set(value_slice[i]); - } - */ - - Ok(()) + slice.write_slice(value_slice).map_err(|_| Error::WasmerOomError) } - fn read(&self, mem_offset: u32, value_len: usize) -> Option<&[u8]> { + fn read_slice(&self, value_len: usize, mem_offset: u32) -> Option<&[u8]> { // TODO: use data_size() ? // DISABLED /* diff --git a/src/runtime/util.rs b/src/runtime/util.rs index 322ac6dd9..52bb04134 100644 --- a/src/runtime/util.rs +++ b/src/runtime/util.rs @@ -17,7 +17,7 @@ */ use log::{error, warn}; -use wasmer::{FunctionEnvMut, AsStoreRef, WasmPtr}; +use wasmer::{AsStoreRef, FunctionEnvMut, WasmPtr}; use super::{memory::MemoryManipulation, vm_runtime::Env}; @@ -45,10 +45,9 @@ pub(crate) fn drk_log(mut ctx: FunctionEnvMut, ptr: WasmPtr, len: u32) let mut logs = env.logs.borrow_mut(); logs.push(msg); std::mem::drop(logs); - }, + } Err(_) => { error!(target: "wasm_runtime::drk_log", "Failed to read UTF-8 string from VM memory"); } } } - diff --git a/src/runtime/vm_runtime.rs b/src/runtime/vm_runtime.rs index 12e3ab775..00f37489d 100644 --- a/src/runtime/vm_runtime.rs +++ b/src/runtime/vm_runtime.rs @@ -38,10 +38,7 @@ use super::{ memory::MemoryManipulation, util::drk_log, }; -use crate::{ - node::{state::StateUpdate, MemoryState}, - Result, -}; +use crate::{Error, Result}; /// Name of the wasm linear memory in our guest module const MEMORY: &str = "memory"; @@ -56,10 +53,6 @@ pub struct Env { pub logs: RefCell>, /// Direct memory access to the VM pub memory: Option, - /// Cloned state machine living in memory - pub state_machine: Arc, - /// State updates produced by the contract - pub state_updates: Arc>>, } impl Env { @@ -86,8 +79,6 @@ pub struct ExecutionResult { pub exitcode: u8, /// Logs written from the wasm program pub logs: Vec, - /// State machine updates produced by the wasm program - pub state_updates: Vec, } pub struct Runtime { @@ -98,7 +89,7 @@ pub struct Runtime { impl Runtime { /// Create a new wasm runtime instance that contains the given wasm module. - pub fn new(wasm_bytes: &[u8], state_machine: MemoryState) -> Result { + pub fn new(wasm_bytes: &[u8]) -> Result { info!(target: "warm_runtime::new", "Instantiating a new runtime"); // This function will be called for each `Operator` encountered during // the wasm module execution. It should return the cost of the operator @@ -129,11 +120,8 @@ impl Runtime { // This section will need changing debug!(target: "wasm_runtime::new", "Importing functions"); let logs = RefCell::new(vec![]); - let state_machine = Arc::new(state_machine); - let state_updates = Arc::new(Mutex::new(vec![])); - let ctx = - FunctionEnv::new(&mut store, Env { logs, memory: None, state_machine, state_updates }); + let ctx = FunctionEnv::new(&mut store, Env { logs, memory: None }); let imports = imports! { "env" => { @@ -169,7 +157,7 @@ impl Runtime { /// Run the hardcoded `ENTRYPOINT` function with the given payload as input. pub fn run(&mut self, payload: &[u8]) -> Result<()> { let pages_required = payload.len() / WASM_PAGE_SIZE + 1; - self.set_memory_page_size(pages_required as u32); + self.set_memory_page_size(pages_required as u32)?; self.copy_to_memory(payload)?; @@ -200,8 +188,7 @@ impl Runtime { match retval { entrypoint::SUCCESS => Ok(()), - // _ => Err(ContractError(retval)), - _ => todo!(), + _ => Err(Error::ContractExecError(retval)), } } @@ -226,13 +213,14 @@ impl Runtime { } /// Set the memory page size - fn set_memory_page_size(&mut self, pages: u32) { + fn set_memory_page_size(&mut self, pages: u32) -> Result<()> { // Grab memory by value let memory = self.take_memory(); // Modify the memory - memory.grow(&mut self.store, Pages(pages)); + memory.grow(&mut self.store, Pages(pages)).map_err(|_| Error::WasmerMemoryError)?; // Replace the memory back again self.ctx.as_mut(&mut self.store).memory = Some(memory); + Ok(()) } /// Take Memory by value. Needed to modify the Memory object /// Will panic if memory isn't set. @@ -247,13 +235,6 @@ impl Runtime { // Get the memory view let env = self.ctx.as_ref(&self.store); let memory_view = env.memory_view(&self.store); - - // Pointer to offset 0 - let ptr: WasmPtr = WasmPtr::new(0); - - // Write to the slice - let slice = ptr.slice(&memory_view, payload.len() as u32).expect("FIXME FIXME FIXME"); - slice.write_slice(payload).expect("FIXME FIXME FIXME"); - Ok(()) + memory_view.write_slice(payload, 0) } } diff --git a/src/sdk/src/entrypoint.rs b/src/sdk/src/entrypoint.rs index d5730edde..9cbc66add 100644 --- a/src/sdk/src/entrypoint.rs +++ b/src/sdk/src/entrypoint.rs @@ -53,4 +53,3 @@ pub unsafe fn deserialize<'a>(input: *mut u8) -> &'a [u8] { instruction_data } -