Skip to content
This repository has been archived by the owner on Jan 16, 2025. It is now read-only.

Drop wasmer in favor of wasmtime for tests #111

Merged
merged 4 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading