Skip to content

Commit

Permalink
piecrust: fix compile time
Browse files Browse the repository at this point in the history
  • Loading branch information
Eduardo Leegwater Simões committed Oct 19, 2023
1 parent fe7bbd4 commit 34cfeee
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 106 deletions.
2 changes: 1 addition & 1 deletion piecrust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ piecrust-uplink = { version = "0.8", path = "../piecrust-uplink" }
wasmtime = { version = "13", 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 @@ -33,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
6 changes: 3 additions & 3 deletions piecrust/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ 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>),
Expand All @@ -41,6 +41,8 @@ pub enum Error {
InvalidArgumentBuffer,
#[error("Invalid memory")]
InvalidFunctionSignature(String),
#[error("Invalid memory")]
InvalidMemory,
#[error("Memory access out of bounds: offset {offset}, length {len}, memory length {mem_len}")]
MemoryAccessOutOfBounds {
offset: usize,
Expand All @@ -52,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 Down
1 change: 1 addition & 0 deletions piecrust/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub(crate) struct DefaultImports;

impl DefaultImports {
pub fn default(store: &mut Store<Env>) -> Vec<Extern> {
#[allow(unused_mut)]
let mut num_imports = 11;

#[cfg(feature = "debug")]
Expand Down
154 changes: 76 additions & 78 deletions piecrust/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,14 @@ impl WrappedInstance {
contract: &WrappedContract,
memory: Memory,
) -> Result<Self, Error> {
let engine = session.engine();
let engine = session.engine().clone();

let env = Env {
self_id: contract_id,
session,
};

let mut store = Store::new(session.engine(), env);
let mut store = Store::new(&engine, env);

let imports = DefaultImports::default(&mut store);

Expand All @@ -117,7 +117,7 @@ impl WrappedInstance {

let val = global.get(&mut store);

val.i32().ok_or(Error::InvalidArgumentBuffer)?
val.i32().ok_or(Error::InvalidArgumentBuffer)? as usize
}
_ => return Err(Error::InvalidArgumentBuffer),
};
Expand All @@ -128,9 +128,9 @@ impl WrappedInstance {

// Ensure there is at most one memory exported, and that it is called
// "memory".
let n_memories = instance
.exports(&mut store)
.filter(|exp| exp.into_memory().is_some())
let n_memories = module
.exports()
.filter(|exp| exp.ty().memory().is_some())
.count();

if n_memories > 1 {
Expand All @@ -139,42 +139,42 @@ impl WrappedInstance {

let _ = instance
.get_memory(&mut store, "memory")
.ok_or(Error::NoMemoryExported)?;
.ok_or(Error::InvalidMemory)?;

// Ensure that every exported function has a signature that matches the
// calling convention `F: I32 -> I32`.
for (func_name, func) in instance
.exports(&mut store)
.filter_map(|exp| exp.into_func().map(|func| (exp.name(), func)))
{
let func_ty = func.ty(&store);

// There must be only one parameter with type `I32`.
let params = func_ty.params();
if params.len() != 1 {
return Err(Error::InvalidFunctionSignature(
func_name.to_string(),
));
}
let param = params.next().unwrap();
if param != ValType::I32 {
return Err(Error::InvalidFunctionSignature(
func_name.to_string(),
));
}
for exp in module.exports() {
let exp_ty = exp.ty();
if let Some(func_ty) = exp_ty.func() {
let func_name = exp.name();

// There must be only one parameter with type `I32`.
let mut params = func_ty.params();
if params.len() != 1 {
return Err(Error::InvalidFunctionSignature(
func_name.to_string(),
));
}
let param = params.next().unwrap();
if param != ValType::I32 {
return Err(Error::InvalidFunctionSignature(
func_name.to_string(),
));
}

// There must be only one result with type `I32`.
let results = func_ty.results();
if results.len() != 1 {
return Err(Error::InvalidFunctionSignature(
func_name.to_string(),
));
}
let result = results.next().unwrap();
if result != ValType::I32 {
return Err(Error::InvalidFunctionSignature(
func_name.to_string(),
));
// There must be only one result with type `I32`.
let mut results = func_ty.results();
if results.len() != 1 {
return Err(Error::InvalidFunctionSignature(
func_name.to_string(),
));
}
let result = results.next().unwrap();
if result != ValType::I32 {
return Err(Error::InvalidFunctionSignature(
func_name.to_string(),
));
}
}
}

Expand Down Expand Up @@ -228,15 +228,15 @@ impl WrappedInstance {
F: FnOnce(&[u8]) -> R,
{
let memory = self.memory.read();
f(memory)
f(&memory)
}

pub(crate) fn with_memory_mut<F, R>(&self, f: F) -> R
where
F: FnOnce(&mut [u8]) -> R,
{
let memory = self.memory.write();
f(memory)
let mut memory = self.memory.write();
f(&mut memory)
}

/// Returns the current length of the memory.
Expand Down Expand Up @@ -274,7 +274,7 @@ impl WrappedInstance {
) -> Result<i32, Error> {
let fun = self
.instance
.get_typed_func::<u32, i32>(&self.store, method_name)?;
.get_typed_func::<u32, i32>(&mut self.store, method_name)?;

self.set_remaining_points(limit);

Expand All @@ -287,57 +287,55 @@ impl WrappedInstance {
self.store
.consume_fuel(remaining)
.expect("Consuming all fuel should succeed");
self.store.add_fuel(limit);
self.store
.add_fuel(limit)
.expect("Adding fuel should succeed");
}

pub fn get_remaining_points(&mut self) -> Option<u64> {
self.store.fuel_remaining()
}

pub fn is_function_exported<N: AsRef<str>>(&self, name: N) -> bool {
self.instance.get_func(self.store, name.as_ref()).is_some()
pub fn is_function_exported<N: AsRef<str>>(&mut self, name: N) -> bool {
self.instance
.get_func(&mut self.store, name.as_ref())
.is_some()
}

#[allow(unused)]
pub fn print_state(&self) {
let mem = self
.instance
.get_memory(&self.store, "memory")
.expect("memory export is checked at contract creation time");

let view = mem.view(&self.store);
let maybe_interesting = unsafe { view.data_unchecked_mut() };

const CSZ: usize = 128;
const RSZ: usize = 16;

for (chunk_nr, chunk) in maybe_interesting.chunks(CSZ).enumerate() {
if chunk[..] != [0; CSZ][..] {
for (row_nr, row) in chunk.chunks(RSZ).enumerate() {
let ofs = chunk_nr * CSZ + row_nr * RSZ;

print!("{ofs:08x}:");

for (i, byte) in row.iter().enumerate() {
if i % 4 == 0 {
print!(" ");
self.with_memory(|mem| {
const CSZ: usize = 128;
const RSZ: usize = 16;

for (chunk_nr, chunk) in mem.chunks(CSZ).enumerate() {
if chunk[..] != [0; CSZ][..] {
for (row_nr, row) in chunk.chunks(RSZ).enumerate() {
let ofs = chunk_nr * CSZ + row_nr * RSZ;

print!("{ofs:08x}:");

for (i, byte) in row.iter().enumerate() {
if i % 4 == 0 {
print!(" ");
}

let buf_start = self.arg_buf_ofs;
let buf_end = buf_start + ARGBUF_LEN;

if ofs + i >= buf_start && ofs + i < buf_end {
print!("{}", format!("{byte:02x}").green());
print!(" ");
} else {
print!("{byte:02x} ")
}
}

let buf_start = self.arg_buf_ofs;
let buf_end = buf_start + ARGBUF_LEN;

if ofs + i >= buf_start && ofs + i < buf_end {
print!("{}", format!("{byte:02x}").green());
print!(" ");
} else {
print!("{byte:02x} ")
}
println!();
}

println!();
}
}
}
});
}

pub fn arg_buffer_offset(&self) -> usize {
Expand Down
46 changes: 25 additions & 21 deletions piecrust/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::mem;
use std::sync::{mpsc, Arc};

use bytecheck::CheckBytes;
use once_cell::sync::OnceCell;
use piecrust_uplink::{ContractId, Event, ARGBUF_LEN, SCRATCH_BUF_BYTES};
use rkyv::ser::serializers::{
BufferScratch, BufferSerializer, CompositeSerializer,
Expand Down Expand Up @@ -81,6 +82,11 @@ impl Drop for Session {
}
}

fn dummy_engine() -> Engine {
static DUMMY_ENGINE: OnceCell<Engine> = OnceCell::new();
DUMMY_ENGINE.get_or_init(Engine::default).clone()
}

#[derive(Debug)]
struct SessionInner {
call_tree: CallTree,
Expand All @@ -101,19 +107,21 @@ unsafe impl MemoryCreator for Session {
/// call tree.
fn new_memory(
&self,
ty: MemoryType,
_ty: MemoryType,
minimum: usize,
maximum: Option<usize>,
reserved_size_in_bytes: Option<usize>,
guard_size_in_bytes: usize,
_maximum: Option<usize>,
_reserved_size_in_bytes: Option<usize>,
_guard_size_in_bytes: usize,
) -> Result<Box<dyn LinearMemory>, String> {
let elem = self
.inner
.call_tree
.nth_parent(0)
.expect("There should be an element on the stack");

let contract_data = self
let session = self.clone();

let contract_data = session
.inner
.contract_session
.contract(elem.contract_id)
Expand All @@ -124,8 +132,8 @@ unsafe impl MemoryCreator for Session {
let memory = match contract_data {
Some(contract_data) => contract_data.memory,
None => {
let mut memory = Memory::new().map_err(|err| {
format!("Failed to instantiate a new memory")
let memory = Memory::new().map_err(|err| {
format!("Failed to instantiate a new memory: {err}")
})?;
memory.write().inner.current_len = minimum;
memory
Expand Down Expand Up @@ -155,25 +163,21 @@ impl Session {
events: vec![],
};

// This implementation purposefully boxes and leaks the `SessionInner`.
let inner = Box::leak(Box::new(inner));

config.with_host_memory(Arc::new(inner));

Self {
engine: Engine::new(&config)
.expect("Configuration is set at compile time"),
let mut session = Self {
engine: dummy_engine(),
inner,
original: true,
}
}
};

/// This implementation purposefully boxes and leaks the `SessionInner`.
pub(crate) fn with_inner(config: Config, inner: SessionInner) -> Self {
Self {
engine: Engine::new(&config),
inner: Box::leak(Box::new(inner)),
original: true,
}
config.with_host_memory(Arc::new(session.clone()));

session.engine = Engine::new(&config)
.expect("Engine configuration is set at compile time");

session
}

/// Clone the given session. We explicitly **do not** implement the
Expand Down
7 changes: 4 additions & 3 deletions piecrust/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@ fn config() -> Config {
config.static_memory_forced(true);
config.static_memory_maximum_size(0x100000000);
config.static_memory_guard_size(0);
config.dynamic_memory_guard_size(0);
config.guard_before_linear_memory(false);
config.memory_init_cow(false);

config.module_version(ModuleVersionStrategy::Custom(String::from(
"piecrust",
)));
config
.module_version(ModuleVersionStrategy::Custom(String::from("piecrust")))
.expect("Module version should be valid");
config.generate_address_map(false);
config.macos_use_mach_ports(false);

Expand Down

0 comments on commit 34cfeee

Please sign in to comment.