Skip to content

Commit

Permalink
Merge pull request #111 from dusk-network/wasmtime
Browse files Browse the repository at this point in the history
Drop `wasmer` in favor of `wasmtime` for tests
  • Loading branch information
Eduardo Leegwater Simões authored May 8, 2024
2 parents 361484c + 7f18666 commit ffef2d6
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 66 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ rusk-abi = { version = "0.12.0-rc.0", default-features = false }

[dev-dependencies]
rand = "^0.8"
wasmer = "=3.1"
wasmtime = "20"

[build-dependencies]
schemafy_lib = "0.6"
Binary file modified assets/dusk_wallet_core.wasm
Binary file not shown.
31 changes: 19 additions & 12 deletions src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@

//! FFI bindings exposed to WASM module.

use alloc::{vec, vec::Vec};
use alloc::{
alloc::{alloc, dealloc, Layout},
vec::Vec,
};
use core::mem;

use dusk_bytes::Serializable;
Expand All @@ -15,22 +18,28 @@ use sha2::{Digest, Sha512};

use crate::{key, tx, types, utils, MAX_KEY, MAX_LEN};

/// The alignment of the memory allocated by the FFI.
///
/// This is 1 because we're not allocating any complex data structures, and
/// just interacting with the memory directly.
const ALIGNMENT: usize = 1;

/// Allocates a buffer of `len` bytes on the WASM memory.
#[no_mangle]
pub fn allocate(len: i32) -> i32 {
let bytes = vec![0u8; len as usize];
let ptr = bytes.as_ptr();
mem::forget(bytes);
ptr as i32
unsafe {
let layout = Layout::from_size_align_unchecked(len as usize, ALIGNMENT);
let ptr = alloc(layout);
ptr as _
}
}

/// Frees a previously allocated buffer on the WASM memory.
#[no_mangle]
pub fn free_mem(ptr: i32, len: i32) {
let ptr = ptr as *mut u8;
let len = len as usize;
unsafe {
Vec::from_raw_parts(ptr, len, len);
let layout = Layout::from_size_align_unchecked(len as usize, ALIGNMENT);
dealloc(ptr as _, layout);
}
}

Expand All @@ -53,11 +62,9 @@ pub fn seed(args: i32, len: i32) -> i64 {
hash.update(b"SEED");

let seed = hash.finalize().to_vec();
let ptr = seed.as_ptr() as u32;
let len = seed.len() as u32;

mem::forget(seed);
utils::compose(true, ptr, len)
let (ptr, len) = utils::allocated_copy(seed);
utils::compose(true, ptr as _, len as _)
}

/// Computes the total balance of the given notes.
Expand Down
33 changes: 20 additions & 13 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

//! Misc utilities required by the library implementation.

use crate::{tx, MAX_INPUT_NOTES, MAX_LEN, RNG_SEED};
use crate::{ffi, tx, MAX_INPUT_NOTES, MAX_LEN, RNG_SEED};

use alloc::vec::Vec;
use core::mem;
use core::ptr;

use dusk_bytes::DeserializableSlice;
use dusk_jubjub::JubJubScalar;
Expand Down Expand Up @@ -93,14 +93,9 @@ pub fn into_ptr<T>(response: T) -> i64
where
T: Serialize,
{
let response = serde_json::to_string(&response).unwrap_or_default();
let ptr = response.as_ptr() as u32;
let len = response.len() as u32;
let result = compose(true, ptr, len);

mem::forget(response);

result
let response = serde_json::to_string(&response).unwrap_or_default().leak();
let (ptr, len) = allocated_copy(response);
compose(true, ptr as _, len as _)
}

/// Returns the provided bytes as a pointer
Expand All @@ -113,13 +108,25 @@ where
Err(_) => return fail(),
};

let ptr = bytes.as_ptr() as u32;
let len = bytes.len() as u32;
let (ptr, len) = allocated_copy(bytes);

mem::forget(bytes);
compose(true, ptr, len)
}

/// Allocated a new buffer, copies the provided bytes to it, and returns the
/// pointer and length of the new buffer.
pub fn allocated_copy<B: AsRef<[u8]>>(bytes: B) -> (u32, u32) {
unsafe {
let bytes = bytes.as_ref();
let len = bytes.len();

let ptr = ffi::allocate(bytes.len() as _);
ptr::copy_nonoverlapping(bytes.as_ptr(), ptr as _, len);

(ptr as _, len as _)
}
}

/// Creates a secure RNG directly a seed.
pub fn rng(seed: [u8; 32]) -> ChaCha12Rng {
ChaCha12Rng::from_seed(seed)
Expand Down
83 changes: 43 additions & 40 deletions tests/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use phoenix_core::Crossover;
use rusk_abi::ContractId;
use serde::{Deserialize, Serialize};
use serde_json::json;
use wasmer::{imports, Instance, Module, Store, Value};
use wasmtime::{Engine, Instance, Module, Store, Val};

#[test]
fn seed_works() {
Expand Down Expand Up @@ -356,7 +356,7 @@ mod node {
}

pub struct Wallet {
pub store: Store,
pub store: Store<()>,
pub module: Module,
pub instance: Instance,
}
Expand Down Expand Up @@ -386,21 +386,19 @@ impl<'a> CallResult<'a> {

self.wallet
.instance
.exports
.get_memory("memory")
.unwrap()
.view(&self.wallet.store)
.read(self.val as u64, &mut bytes)
.get_memory(&mut self.wallet.store, "memory")
.expect("There should be one memory")
.read(&mut self.wallet.store, self.val as usize, &mut bytes)
.unwrap();

self.wallet
.instance
.exports
.get_function("free_mem")
.unwrap()
.get_func(&mut self.wallet.store, "free_mem")
.expect("free_mem should exist")
.call(
&mut self.wallet.store,
&[Value::I32(self.val as i32), Value::I32(self.aux as i32)],
&[Val::I32(self.val as i32), Val::I32(self.aux as i32)],
&mut [],
)
.unwrap();

Expand Down Expand Up @@ -429,49 +427,54 @@ impl Wallet {
T: Serialize,
{
let bytes = serde_json::to_string(&args).unwrap();
let len = Value::I32(bytes.len() as i32);
let ptr = self

let len_params = [Val::I32(bytes.len() as i32)];
let mut ptr_results = [Val::I32(0)];

let allocate = self
.instance
.exports
.get_function("allocate")
.unwrap()
.call(&mut self.store, &[len.clone()])
.unwrap()[0]
.unwrap_i32();
.get_func(&mut self.store, "allocate")
.expect("allocate should exist");

self.instance
.exports
.get_memory("memory")
.unwrap()
.view(&self.store)
.write(ptr as u64, bytes.as_bytes())
allocate
.call(&mut self.store, &len_params, &mut ptr_results)
.unwrap();

let ptr = Value::I32(ptr);
let result = self
.instance
.exports
.get_function(f)
.unwrap()
.call(&mut self.store, &[ptr, len])
.unwrap()[0]
.unwrap_i64();
self.instance
.get_memory(&mut self.store, "memory")
.expect("There should be one memory")
.write(
&mut self.store,
ptr_results[0].unwrap_i32() as usize,
bytes.as_bytes(),
)
.expect("Writing to memory should succeed");

let params = [ptr_results[0].clone(), len_params[0].clone()];
let mut results = [Val::I64(0)];

CallResult::new(self, result)
self.instance
.get_func(&mut self.store, f)
.expect("allocate should exist")
.call(&mut self.store, &params, &mut results)
.unwrap();

CallResult::new(self, results[0].unwrap_i64())
}
}

impl Default for Wallet {
fn default() -> Self {
const WALLET: &[u8] = include_bytes!("../assets/dusk_wallet_core.wasm");

let mut store = Store::default();
let engine = Engine::default();
let mut store = Store::new(&engine, ());

let module =
Module::new(&store, WALLET).expect("failed to create wasm module");
Module::new(&engine, WALLET).expect("failed to create wasm module");

let import_object = imports! {};
let instance = Instance::new(&mut store, &module, &import_object)
.expect("failed to instanciate the wasm module");
let instance = Instance::new(&mut store, &module, &[])
.expect("failed to instantiate the wasm module");

Self {
store,
Expand Down

0 comments on commit ffef2d6

Please sign in to comment.