Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sp-wasm-interface): Gear sandbox #35

Merged
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
39 changes: 25 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ members = [
"client/network/test",
"client/offchain",
"client/peerset",
"client/allocator",
"client/proposer-metrics",
"client/rpc",
"client/rpc-api",
Expand Down Expand Up @@ -172,6 +171,7 @@ members = [
"frame/vesting",
"frame/glutton",
"frame/whitelist",
"primitives/allocator",
"primitives/api",
"primitives/api/proc-macro",
"primitives/api/test",
Expand Down
20 changes: 0 additions & 20 deletions client/allocator/Cargo.toml

This file was deleted.

2 changes: 1 addition & 1 deletion client/executor/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"]
thiserror = "1.0.30"
wasm-instrument = "0.3"
wasmi = { git = "https://github.com/gear-tech/wasmi", branch = "v0.13.2-sign-ext", features = ["virtual_memory"] }
sc-allocator = { version = "4.1.0-dev", path = "../../allocator" }
sp-allocator = { version = "4.1.0-dev", path = "../../../primitives/allocator" }
sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../../primitives/maybe-compressed-blob" }
sp-wasm-interface = { version = "7.0.0", path = "../../../primitives/wasm-interface" }

Expand Down
2 changes: 1 addition & 1 deletion client/executor/common/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pub enum Error {
Other(String),

#[error(transparent)]
Allocator(#[from] sc_allocator::Error),
Allocator(#[from] sp_allocator::Error),

#[error("Host function {0} execution failed with: {1}")]
FunctionExecution(String, String),
Expand Down
8 changes: 0 additions & 8 deletions client/executor/common/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,6 @@

use crate::error::Result;
use sp_wasm_interface::Pointer;
use std::ops::Range;

/// Construct a range from an offset to a data length after the offset.
/// Returns None if the end of the range would exceed some maximum offset.
pub fn checked_range(offset: usize, len: usize, max: usize) -> Option<Range<usize>> {
let end = offset.checked_add(len)?;
(end <= max).then(|| offset..end)
}

/// Provides safe memory access interface using an external buffer
pub trait MemoryTransfer {
Expand Down
2 changes: 1 addition & 1 deletion client/executor/common/src/wasm_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
use crate::error::Error;
use sp_wasm_interface::Value;

pub use sc_allocator::AllocationStats;
pub use sp_allocator::AllocationStats;

/// A method to be used to find the entrypoint when calling into the runtime
///
Expand Down
2 changes: 1 addition & 1 deletion client/executor/wasmi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
log = "0.4.17"
wasmi = { git = "https://github.com/gear-tech/wasmi", branch = "v0.13.2-sign-ext", features = ["virtual_memory"] }
sc-allocator = { version = "4.1.0-dev", path = "../../allocator" }
sc-executor-common = { version = "0.10.0-dev", path = "../common" }
sp-allocator = { version = "4.1.0-dev", path = "../../../primitives/allocator" }
sp-runtime-interface = { version = "7.0.0", path = "../../../primitives/runtime-interface" }
sp-wasm-interface = { version = "7.0.0", path = "../../../primitives/wasm-interface" }
13 changes: 8 additions & 5 deletions client/executor/wasmi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ use wasmi::{
TableRef,
};

use sc_allocator::{AllocationStats, FreeingBumpHeapAllocator};
use sp_allocator::AllocationStats;
use sc_executor_common::{
error::{Error, MessageWithBacktrace, WasmError},
runtime_blob::{DataSegmentsSnapshot, RuntimeBlob},
wasm_runtime::{HeapAllocStrategy, InvokeMethod, WasmInstance, WasmModule},
};
use sp_runtime_interface::unpack_ptr_and_len;
use sp_wasm_interface::{Function, FunctionContext, Pointer, Result as WResult, WordSize};
use sp_wasm_interface::{Function, FunctionContext, FunctionContextToken, Pointer, Result as WResult, WordSize, Caller, StoreData};

/// Wrapper around [`MemorRef`] that implements [`sc_allocator::Memory`].
struct MemoryWrapper<'a>(&'a MemoryRef);

impl sc_allocator::Memory for MemoryWrapper<'_> {
impl sp_allocator::Memory for MemoryWrapper<'_> {
fn with_access_mut<R>(&mut self, run: impl FnOnce(&mut [u8]) -> R) -> R {
self.0.with_direct_access_mut(run)
}
Expand Down Expand Up @@ -73,7 +73,7 @@ impl sc_allocator::Memory for MemoryWrapper<'_> {
}

struct FunctionExecutor {
heap: RefCell<sc_allocator::FreeingBumpHeapAllocator>,
heap: RefCell<sp_allocator::FreeingBumpHeapAllocator>,
memory: MemoryRef,
host_functions: Arc<Vec<&'static dyn Function>>,
allow_missing_func_imports: bool,
Expand All @@ -90,7 +90,7 @@ impl FunctionExecutor {
missing_functions: Arc<Vec<String>>,
) -> Result<Self, Error> {
Ok(FunctionExecutor {
heap: RefCell::new(FreeingBumpHeapAllocator::new(heap_base)),
heap: RefCell::new(sp_allocator::FreeingBumpHeapAllocator::new(heap_base)),
memory: m,
host_functions,
allow_missing_func_imports,
Expand Down Expand Up @@ -126,6 +126,9 @@ impl FunctionContext for FunctionExecutor {
fn register_panic_error_message(&mut self, message: &str) {
self.panic_message = Some(message.to_owned());
}

fn with_caller_mut_impl(&mut self, _: FunctionContextToken, _context: *mut (), _callback: fn(*mut (), &mut Caller<StoreData>)) {
}
}

/// Will be used on initialization of a module to resolve function and memory imports.
Expand Down
2 changes: 1 addition & 1 deletion client/executor/wasmtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ wasmtime = { version = "6.0.1", default-features = false, features = [
"pooling-allocator"
] }
anyhow = "1.0.68"
sc-allocator = { version = "4.1.0-dev", path = "../../allocator" }
sc-executor-common = { version = "0.10.0-dev", path = "../common" }
sp-allocator = { version = "4.1.0-dev", path = "../../../primitives/allocator" }
sp-runtime-interface = { version = "7.0.0", path = "../../../primitives/runtime-interface" }
sp-wasm-interface = { version = "7.0.0", path = "../../../primitives/wasm-interface", features = ["wasmtime"] }

Expand Down
88 changes: 14 additions & 74 deletions client/executor/wasmtime/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,41 +21,10 @@

use wasmtime::Caller;

use sc_allocator::{AllocationStats, FreeingBumpHeapAllocator};
use sp_wasm_interface::{Pointer, WordSize};
use sp_wasm_interface::{FunctionContextToken, Pointer, WordSize, util};
pub use sp_wasm_interface::HostState;

use crate::{instance_wrapper::MemoryWrapper, runtime::StoreData, util};

/// The state required to construct a HostContext context. The context only lasts for one host
/// call, whereas the state is maintained for the duration of a Wasm runtime call, which may make
/// many different host calls that must share state.
pub struct HostState {
/// The allocator instance to keep track of allocated memory.
///
/// This is stored as an `Option` as we need to temporarly set this to `None` when we are
/// allocating/deallocating memory. The problem being that we can only mutable access `caller`
/// once.
allocator: Option<FreeingBumpHeapAllocator>,
panic_message: Option<String>,
}

impl HostState {
/// Constructs a new `HostState`.
pub fn new(allocator: FreeingBumpHeapAllocator) -> Self {
HostState { allocator: Some(allocator), panic_message: None }
}

/// Takes the error message out of the host state, leaving a `None` in its place.
pub fn take_panic_message(&mut self) -> Option<String> {
self.panic_message.take()
}

pub(crate) fn allocation_stats(&self) -> AllocationStats {
self.allocator.as_ref()
.expect("Allocator is always set and only unavailable when doing an allocation/deallocation; qed")
.stats()
}
}
use crate::runtime::StoreData;

/// A `HostContext` implements `FunctionContext` for making host calls from a Wasmtime
/// runtime. The `HostContext` exists only for the lifetime of the call and borrows state from
Expand All @@ -64,15 +33,6 @@ pub(crate) struct HostContext<'a> {
pub(crate) caller: Caller<'a, StoreData>,
}

impl<'a> HostContext<'a> {
fn host_state_mut(&mut self) -> &mut HostState {
self.caller
.data_mut()
.host_state_mut()
.expect("host state is not empty when calling a function in wasm; qed")
}
}

impl<'a> sp_wasm_interface::FunctionContext for HostContext<'a> {
fn read_memory_into(
&self,
Expand All @@ -87,42 +47,22 @@ impl<'a> sp_wasm_interface::FunctionContext for HostContext<'a> {
}

fn allocate_memory(&mut self, size: WordSize) -> sp_wasm_interface::Result<Pointer<u8>> {
let memory = self.caller.data().memory();
let mut allocator = self
.host_state_mut()
.allocator
.take()
.expect("allocator is not empty when calling a function in wasm; qed");

// We can not return on error early, as we need to store back allocator.
let res = allocator
.allocate(&mut MemoryWrapper(&memory, &mut self.caller), size)
.map_err(|e| e.to_string());

self.host_state_mut().allocator = Some(allocator);

res
util::allocate_memory(&mut self.caller, size)
}

fn deallocate_memory(&mut self, ptr: Pointer<u8>) -> sp_wasm_interface::Result<()> {
let memory = self.caller.data().memory();
let mut allocator = self
.host_state_mut()
.allocator
.take()
.expect("allocator is not empty when calling a function in wasm; qed");

// We can not return on error early, as we need to store back allocator.
let res = allocator
.deallocate(&mut MemoryWrapper(&memory, &mut self.caller), ptr)
.map_err(|e| e.to_string());

self.host_state_mut().allocator = Some(allocator);

res
util::deallocate_memory(&mut self.caller, ptr)
}

fn register_panic_error_message(&mut self, message: &str) {
self.host_state_mut().panic_message = Some(message.to_owned());
self.caller
.data_mut()
.host_state_mut()
.expect("host state is not empty when calling a function in wasm; qed")
.panic_message = Some(message.to_owned());
}

fn with_caller_mut_impl(&mut self, _: FunctionContextToken, context: *mut (), callback: fn(*mut (), &mut Caller<StoreData>)) {
callback(context, &mut self.caller)
}
}
Loading