Skip to content

Commit

Permalink
piecrust: switch from wasmer to wasmtime
Browse files Browse the repository at this point in the history
We switch WebAssembly runtime - from `wasmer` to `wasmtime` - to make
use of the features it has available, notably `memory64` support.

In the process we are one step further to having 64-bit contracts, and
have gotten rid of the 4 page minimum memory requirement.

See-also: #281
  • Loading branch information
Eduardo Leegwater Simões committed Oct 23, 2023
1 parent 45edf62 commit f0817ae
Show file tree
Hide file tree
Showing 12 changed files with 477 additions and 542 deletions.
28 changes: 28 additions & 0 deletions piecrust/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## Added

- Add some `Error` variants:
* `InvalidFunction`
* `InvalidMemory`
- Add `once_cell` dependency

## Changed

- Change `Error::RuntimeError` variant to contain `dusk_wasmtime::Error`,
and changed `From` implementation
- Switch runtime from `wasmer` to `wasmtime`

## Removed

- Remove 4 page - 256KiB - minimum memory requirement for contracts
- Remove `Clone` derivation for `Error`
- Remove some `Error` variants, along with `From` implementations:
* `CompileError`
* `DeserializeError`
* `ExportError`
* `InstantiationError`
* `InvalidFunctionSignature`
* `MemorySetupError`
* `ParsingError`
* `SerializeError`
* `Trap`

## [0.11.0] - 2023-10-11

### Added
Expand Down
8 changes: 2 additions & 6 deletions piecrust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,10 @@ license = "MPL-2.0"
crumbles = { version = "0.3", path = "../crumbles" }
piecrust-uplink = { version = "0.8", path = "../piecrust-uplink" }

wasmer = "=3.1"
wasmer-vm = "=3.1"
wasmer-types = "=3.1"
wasmer-middlewares = "=3.1"
wasmer-compiler-singlepass = "=3.1"
dusk-wasmtime = { version = "14", default-features = false, features = ["cranelift", "parallel-compilation"] }
bytecheck = "0.6"
rkyv = { version = "0.7", features = ["size_32", "validation"] }
once_cell = "1.18"
parking_lot = "0.12"
blake3 = "1"
colored = "2"
Expand All @@ -37,7 +34,6 @@ const-decoder = "0.3"
[dev-dependencies]
criterion = "0.4"
dusk-plonk = { version = "0.14", features = ["rkyv-impl"] }
once_cell = "1.18"

[features]
debug = []
Expand Down
9 changes: 4 additions & 5 deletions piecrust/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@
use std::sync::Arc;

use bytecheck::CheckBytes;
use dusk_wasmtime::{Engine, Module};
use piecrust_uplink::ContractId;
use rkyv::{Archive, Deserialize, Serialize};
use wasmer::Module;

use crate::error::Error;
use crate::instance::Store;
use piecrust_uplink::ContractId;

pub struct ContractData<'a, A, const N: usize> {
pub(crate) contract_id: Option<ContractId>,
Expand Down Expand Up @@ -89,14 +88,14 @@ pub struct WrappedContract {

impl WrappedContract {
pub fn new<B: AsRef<[u8]>, C: AsRef<[u8]>>(
engine: &Engine,
bytecode: B,
objectcode: Option<C>,
) -> Result<Self, Error> {
let store = Store::new_store();
let serialized = match objectcode {
Some(obj) => obj.as_ref().to_vec(),
_ => {
let contract = Module::new(&store, bytecode.as_ref())?;
let contract = Module::new(engine, bytecode.as_ref())?;
contract.serialize()?.to_vec()
}
};
Expand Down
64 changes: 7 additions & 57 deletions piecrust/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,34 +21,28 @@ pub type Compo = CompositeSerializerError<
>;

/// The error type returned by the piecrust VM.
#[derive(Error, Debug, Clone)]
#[derive(Error, Debug)]
pub enum Error {
#[error("Commit error: {0}")]
CommitError(Cow<'static, str>),
#[error(transparent)]
CompileError(Arc<wasmer::CompileError>),
#[error(transparent)]
CompositeSerializerError(Arc<Compo>),
#[error(transparent)]
ContractCacheError(Arc<std::io::Error>),
#[error("Contract does not exist: {0}")]
ContractDoesNotExist(ContractId),
#[error(transparent)]
DeserializeError(Arc<wasmer::DeserializeError>),
#[error(transparent)]
ExportError(Arc<wasmer::ExportError>),
#[error(transparent)]
FeedPulled(mpsc::SendError<Vec<u8>>),
#[error(transparent)]
Infallible(std::convert::Infallible),
#[error("InitalizationError: {0}")]
InitalizationError(Cow<'static, str>),
#[error(transparent)]
InstantiationError(Arc<wasmer::InstantiationError>),
#[error("Invalid global")]
InvalidArgumentBuffer,
#[error("Invalid function: {0}")]
InvalidFunction(String),
#[error("Invalid memory")]
InvalidFunctionSignature(String),
InvalidMemory,
#[error("Memory access out of bounds: offset {offset}, length {len}, memory length {mem_len}")]
MemoryAccessOutOfBounds {
offset: usize,
Expand All @@ -60,8 +54,6 @@ pub enum Error {
reason: Option<Arc<Self>>,
io: Arc<std::io::Error>,
},
#[error(transparent)]
MemorySetupError(Arc<std::io::Error>),
#[error("Missing feed")]
MissingFeed,
#[error("Missing host data: {0}")]
Expand All @@ -73,21 +65,15 @@ pub enum Error {
#[error("Contract panic: {0}")]
ContractPanic(String),
#[error(transparent)]
ParsingError(wasmer::wasmparser::BinaryReaderError),
#[error(transparent)]
PersistenceError(Arc<std::io::Error>),
#[error(transparent)]
RestoreError(Arc<std::io::Error>),
#[error(transparent)]
RuntimeError(wasmer::RuntimeError),
#[error(transparent)]
SerializeError(Arc<wasmer::SerializeError>),
RuntimeError(dusk_wasmtime::Error),
#[error("Session error: {0}")]
SessionError(Cow<'static, str>),
#[error("Too many memories: {0}")]
TooManyMemories(usize),
#[error("WASMER TRAP")]
Trap(Arc<wasmer_vm::Trap>),
#[error(transparent)]
Utf8(std::str::Utf8Error),
#[error("ValidationError")]
Expand Down Expand Up @@ -118,54 +104,18 @@ impl From<std::str::Utf8Error> for Error {
}
}

impl From<wasmer::InstantiationError> for Error {
fn from(e: wasmer::InstantiationError) -> Self {
Error::InstantiationError(Arc::from(e))
}
}

impl From<wasmer::CompileError> for Error {
fn from(e: wasmer::CompileError) -> Self {
Error::CompileError(Arc::from(e))
}
}

impl From<wasmer::ExportError> for Error {
fn from(e: wasmer::ExportError) -> Self {
Error::ExportError(Arc::from(e))
}
}

impl From<wasmer::RuntimeError> for Error {
fn from(e: wasmer::RuntimeError) -> Self {
impl From<dusk_wasmtime::Error> for Error {
fn from(e: dusk_wasmtime::Error) -> Self {
Error::RuntimeError(e)
}
}

impl From<wasmer::SerializeError> for Error {
fn from(e: wasmer::SerializeError) -> Self {
Error::SerializeError(Arc::from(e))
}
}

impl From<wasmer::DeserializeError> for Error {
fn from(e: wasmer::DeserializeError) -> Self {
Error::DeserializeError(Arc::from(e))
}
}

impl From<Compo> for Error {
fn from(e: Compo) -> Self {
Error::CompositeSerializerError(Arc::from(e))
}
}

impl From<wasmer_vm::Trap> for Error {
fn from(e: wasmer_vm::Trap) -> Self {
Error::Trap(Arc::from(e))
}
}

impl<A, B> From<rkyv::validation::CheckArchiveError<A, B>> for Error {
fn from(_e: rkyv::validation::CheckArchiveError<A, B>) -> Self {
Error::ValidationError
Expand Down
Loading

0 comments on commit f0817ae

Please sign in to comment.