mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 16:21:06 +00:00
sp-sandbox: move the sandbox module of sp-core into sp-sandbox (#11027)
* sp-sandbox: move the sandbox module of sp-core into sp-sandbox Signed-off-by: koushiro <koushiro.cqx@gmail.com> * Fix Signed-off-by: koushiro <koushiro.cqx@gmail.com> * Fix Signed-off-by: koushiro <koushiro.cqx@gmail.com>
This commit is contained in:
Executable → Regular
+23
-11
@@ -17,18 +17,20 @@
|
||||
|
||||
//! An embedded WASM executor utilizing `wasmi`.
|
||||
|
||||
use super::{Error, HostError, HostFuncType, ReturnValue, Value, TARGET};
|
||||
use alloc::string::String;
|
||||
use log::debug;
|
||||
use sp_std::{
|
||||
borrow::ToOwned, collections::btree_map::BTreeMap, fmt, marker::PhantomData, prelude::*,
|
||||
};
|
||||
|
||||
use wasmi::{
|
||||
memory_units::Pages, Externals, FuncInstance, FuncRef, GlobalDescriptor, GlobalRef,
|
||||
ImportResolver, MemoryDescriptor, MemoryInstance, MemoryRef, Module, ModuleInstance, ModuleRef,
|
||||
RuntimeArgs, RuntimeValue, Signature, TableDescriptor, TableRef, Trap, TrapKind,
|
||||
};
|
||||
|
||||
use sp_std::{
|
||||
borrow::ToOwned, collections::btree_map::BTreeMap, fmt, marker::PhantomData, prelude::*,
|
||||
};
|
||||
|
||||
use crate::{Error, HostError, HostFuncType, ReturnValue, Value, TARGET};
|
||||
|
||||
/// The linear memory used by the sandbox.
|
||||
#[derive(Clone)]
|
||||
pub struct Memory {
|
||||
@@ -162,13 +164,18 @@ impl<T> ImportResolver for EnvironmentDefinitionBuilder<T> {
|
||||
) -> Result<FuncRef, wasmi::Error> {
|
||||
let key = (module_name.as_bytes().to_owned(), field_name.as_bytes().to_owned());
|
||||
let externval = self.map.get(&key).ok_or_else(|| {
|
||||
debug!(target: TARGET, "Export {}:{} not found", module_name, field_name);
|
||||
log::debug!(target: TARGET, "Export {}:{} not found", module_name, field_name);
|
||||
wasmi::Error::Instantiation(String::new())
|
||||
})?;
|
||||
let host_func_idx = match *externval {
|
||||
ExternVal::HostFunc(ref idx) => idx,
|
||||
_ => {
|
||||
debug!(target: TARGET, "Export {}:{} is not a host func", module_name, field_name);
|
||||
log::debug!(
|
||||
target: TARGET,
|
||||
"Export {}:{} is not a host func",
|
||||
module_name,
|
||||
field_name,
|
||||
);
|
||||
return Err(wasmi::Error::Instantiation(String::new()))
|
||||
},
|
||||
};
|
||||
@@ -181,7 +188,7 @@ impl<T> ImportResolver for EnvironmentDefinitionBuilder<T> {
|
||||
_field_name: &str,
|
||||
_global_type: &GlobalDescriptor,
|
||||
) -> Result<GlobalRef, wasmi::Error> {
|
||||
debug!(target: TARGET, "Importing globals is not supported yet");
|
||||
log::debug!(target: TARGET, "Importing globals is not supported yet");
|
||||
Err(wasmi::Error::Instantiation(String::new()))
|
||||
}
|
||||
|
||||
@@ -193,13 +200,18 @@ impl<T> ImportResolver for EnvironmentDefinitionBuilder<T> {
|
||||
) -> Result<MemoryRef, wasmi::Error> {
|
||||
let key = (module_name.as_bytes().to_owned(), field_name.as_bytes().to_owned());
|
||||
let externval = self.map.get(&key).ok_or_else(|| {
|
||||
debug!(target: TARGET, "Export {}:{} not found", module_name, field_name);
|
||||
log::debug!(target: TARGET, "Export {}:{} not found", module_name, field_name);
|
||||
wasmi::Error::Instantiation(String::new())
|
||||
})?;
|
||||
let memory = match *externval {
|
||||
ExternVal::Memory(ref m) => m,
|
||||
_ => {
|
||||
debug!(target: TARGET, "Export {}:{} is not a memory", module_name, field_name);
|
||||
log::debug!(
|
||||
target: TARGET,
|
||||
"Export {}:{} is not a memory",
|
||||
module_name,
|
||||
field_name,
|
||||
);
|
||||
return Err(wasmi::Error::Instantiation(String::new()))
|
||||
},
|
||||
};
|
||||
@@ -212,7 +224,7 @@ impl<T> ImportResolver for EnvironmentDefinitionBuilder<T> {
|
||||
_field_name: &str,
|
||||
_table_type: &TableDescriptor,
|
||||
) -> Result<TableRef, wasmi::Error> {
|
||||
debug!("Importing tables is not supported yet");
|
||||
log::debug!("Importing tables is not supported yet");
|
||||
Err(wasmi::Error::Instantiation(String::new()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Definition of a sandbox environment.
|
||||
|
||||
use codec::{Decode, Encode};
|
||||
|
||||
use sp_core::RuntimeDebug;
|
||||
use sp_std::vec::Vec;
|
||||
|
||||
/// Error error that can be returned from host function.
|
||||
#[derive(Encode, Decode, RuntimeDebug)]
|
||||
pub struct HostError;
|
||||
|
||||
/// Describes an entity to define or import into the environment.
|
||||
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)]
|
||||
pub enum ExternEntity {
|
||||
/// Function that is specified by an index in a default table of
|
||||
/// a module that creates the sandbox.
|
||||
#[codec(index = 1)]
|
||||
Function(u32),
|
||||
|
||||
/// Linear memory that is specified by some identifier returned by sandbox
|
||||
/// module upon creation new sandboxed memory.
|
||||
#[codec(index = 2)]
|
||||
Memory(u32),
|
||||
}
|
||||
|
||||
/// An entry in a environment definition table.
|
||||
///
|
||||
/// Each entry has a two-level name and description of an entity
|
||||
/// being defined.
|
||||
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)]
|
||||
pub struct Entry {
|
||||
/// Module name of which corresponding entity being defined.
|
||||
pub module_name: Vec<u8>,
|
||||
/// Field name in which corresponding entity being defined.
|
||||
pub field_name: Vec<u8>,
|
||||
/// External entity being defined.
|
||||
pub entity: ExternEntity,
|
||||
}
|
||||
|
||||
/// Definition of runtime that could be used by sandboxed code.
|
||||
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)]
|
||||
pub struct EnvironmentDefinition {
|
||||
/// Vector of all entries in the environment definition.
|
||||
pub entries: Vec<Entry>,
|
||||
}
|
||||
|
||||
/// Constant for specifying no limit when creating a sandboxed
|
||||
/// memory instance. For FFI purposes.
|
||||
pub const MEM_UNLIMITED: u32 = -1i32 as u32;
|
||||
|
||||
/// No error happened.
|
||||
///
|
||||
/// For FFI purposes.
|
||||
pub const ERR_OK: u32 = 0;
|
||||
|
||||
/// Validation or instantiation error occurred when creating new
|
||||
/// sandboxed module instance.
|
||||
///
|
||||
/// For FFI purposes.
|
||||
pub const ERR_MODULE: u32 = -1i32 as u32;
|
||||
|
||||
/// Out-of-bounds access attempted with memory or table.
|
||||
///
|
||||
/// For FFI purposes.
|
||||
pub const ERR_OUT_OF_BOUNDS: u32 = -2i32 as u32;
|
||||
|
||||
/// Execution error occurred (typically trap).
|
||||
///
|
||||
/// For FFI purposes.
|
||||
pub const ERR_EXECUTION: u32 = -3i32 as u32;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use codec::Codec;
|
||||
use std::fmt;
|
||||
|
||||
fn roundtrip<S: Codec + PartialEq + fmt::Debug>(s: S) {
|
||||
let encoded = s.encode();
|
||||
assert_eq!(S::decode(&mut &encoded[..]).unwrap(), s);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn env_def_roundtrip() {
|
||||
roundtrip(EnvironmentDefinition { entries: vec![] });
|
||||
|
||||
roundtrip(EnvironmentDefinition {
|
||||
entries: vec![Entry {
|
||||
module_name: b"kernel"[..].into(),
|
||||
field_name: b"memory"[..].into(),
|
||||
entity: ExternEntity::Memory(1337),
|
||||
}],
|
||||
});
|
||||
|
||||
roundtrip(EnvironmentDefinition {
|
||||
entries: vec![Entry {
|
||||
module_name: b"env"[..].into(),
|
||||
field_name: b"abort"[..].into(),
|
||||
entity: ExternEntity::Function(228),
|
||||
}],
|
||||
});
|
||||
}
|
||||
}
|
||||
Executable → Regular
+20
-24
@@ -17,12 +17,13 @@
|
||||
|
||||
//! A WASM executor utilizing the sandbox runtime interface of the host.
|
||||
|
||||
use super::{Error, HostFuncType, ReturnValue, Value};
|
||||
use codec::{Decode, Encode};
|
||||
use sp_core::sandbox as sandbox_primitives;
|
||||
|
||||
use sp_io::sandbox;
|
||||
use sp_std::{marker, mem, prelude::*, rc::Rc, slice, vec};
|
||||
|
||||
use crate::{env, Error, HostFuncType, ReturnValue, Value};
|
||||
|
||||
mod ffi {
|
||||
use super::HostFuncType;
|
||||
use sp_std::mem;
|
||||
@@ -68,11 +69,10 @@ pub struct Memory {
|
||||
|
||||
impl super::SandboxMemory for Memory {
|
||||
fn new(initial: u32, maximum: Option<u32>) -> Result<Memory, Error> {
|
||||
let maximum =
|
||||
if let Some(maximum) = maximum { maximum } else { sandbox_primitives::MEM_UNLIMITED };
|
||||
let maximum = if let Some(maximum) = maximum { maximum } else { env::MEM_UNLIMITED };
|
||||
|
||||
match sandbox::memory_new(initial, maximum) {
|
||||
sandbox_primitives::ERR_MODULE => Err(Error::Module),
|
||||
env::ERR_MODULE => Err(Error::Module),
|
||||
memory_idx => Ok(Memory { handle: Rc::new(MemoryHandle { memory_idx }) }),
|
||||
}
|
||||
}
|
||||
@@ -81,8 +81,8 @@ impl super::SandboxMemory for Memory {
|
||||
let result =
|
||||
sandbox::memory_get(self.handle.memory_idx, offset, buf.as_mut_ptr(), buf.len() as u32);
|
||||
match result {
|
||||
sandbox_primitives::ERR_OK => Ok(()),
|
||||
sandbox_primitives::ERR_OUT_OF_BOUNDS => Err(Error::OutOfBounds),
|
||||
env::ERR_OK => Ok(()),
|
||||
env::ERR_OUT_OF_BOUNDS => Err(Error::OutOfBounds),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
@@ -95,8 +95,8 @@ impl super::SandboxMemory for Memory {
|
||||
val.len() as u32,
|
||||
);
|
||||
match result {
|
||||
sandbox_primitives::ERR_OK => Ok(()),
|
||||
sandbox_primitives::ERR_OUT_OF_BOUNDS => Err(Error::OutOfBounds),
|
||||
env::ERR_OK => Ok(()),
|
||||
env::ERR_OUT_OF_BOUNDS => Err(Error::OutOfBounds),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
@@ -104,22 +104,18 @@ impl super::SandboxMemory for Memory {
|
||||
|
||||
/// A builder for the environment of the sandboxed WASM module.
|
||||
pub struct EnvironmentDefinitionBuilder<T> {
|
||||
env_def: sandbox_primitives::EnvironmentDefinition,
|
||||
env_def: env::EnvironmentDefinition,
|
||||
retained_memories: Vec<Memory>,
|
||||
_marker: marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> EnvironmentDefinitionBuilder<T> {
|
||||
fn add_entry<N1, N2>(
|
||||
&mut self,
|
||||
module: N1,
|
||||
field: N2,
|
||||
extern_entity: sandbox_primitives::ExternEntity,
|
||||
) where
|
||||
fn add_entry<N1, N2>(&mut self, module: N1, field: N2, extern_entity: env::ExternEntity)
|
||||
where
|
||||
N1: Into<Vec<u8>>,
|
||||
N2: Into<Vec<u8>>,
|
||||
{
|
||||
let entry = sandbox_primitives::Entry {
|
||||
let entry = env::Entry {
|
||||
module_name: module.into(),
|
||||
field_name: field.into(),
|
||||
entity: extern_entity,
|
||||
@@ -131,7 +127,7 @@ impl<T> EnvironmentDefinitionBuilder<T> {
|
||||
impl<T> super::SandboxEnvironmentBuilder<T, Memory> for EnvironmentDefinitionBuilder<T> {
|
||||
fn new() -> EnvironmentDefinitionBuilder<T> {
|
||||
EnvironmentDefinitionBuilder {
|
||||
env_def: sandbox_primitives::EnvironmentDefinition { entries: Vec::new() },
|
||||
env_def: env::EnvironmentDefinition { entries: Vec::new() },
|
||||
retained_memories: Vec::new(),
|
||||
_marker: marker::PhantomData::<T>,
|
||||
}
|
||||
@@ -142,7 +138,7 @@ impl<T> super::SandboxEnvironmentBuilder<T, Memory> for EnvironmentDefinitionBui
|
||||
N1: Into<Vec<u8>>,
|
||||
N2: Into<Vec<u8>>,
|
||||
{
|
||||
let f = sandbox_primitives::ExternEntity::Function(f as u32);
|
||||
let f = env::ExternEntity::Function(f as u32);
|
||||
self.add_entry(module, field, f);
|
||||
}
|
||||
|
||||
@@ -154,7 +150,7 @@ impl<T> super::SandboxEnvironmentBuilder<T, Memory> for EnvironmentDefinitionBui
|
||||
// We need to retain memory to keep it alive while the EnvironmentDefinitionBuilder alive.
|
||||
self.retained_memories.push(mem.clone());
|
||||
|
||||
let mem = sandbox_primitives::ExternEntity::Memory(mem.handle.memory_idx as u32);
|
||||
let mem = env::ExternEntity::Memory(mem.handle.memory_idx as u32);
|
||||
self.add_entry(module, field, mem);
|
||||
}
|
||||
}
|
||||
@@ -228,8 +224,8 @@ impl<T> super::SandboxInstance<T> for Instance<T> {
|
||||
);
|
||||
|
||||
let instance_idx = match result {
|
||||
sandbox_primitives::ERR_MODULE => return Err(Error::Module),
|
||||
sandbox_primitives::ERR_EXECUTION => return Err(Error::Execution),
|
||||
env::ERR_MODULE => return Err(Error::Module),
|
||||
env::ERR_EXECUTION => return Err(Error::Execution),
|
||||
instance_idx => instance_idx,
|
||||
};
|
||||
|
||||
@@ -256,12 +252,12 @@ impl<T> super::SandboxInstance<T> for Instance<T> {
|
||||
);
|
||||
|
||||
match result {
|
||||
sandbox_primitives::ERR_OK => {
|
||||
env::ERR_OK => {
|
||||
let return_val =
|
||||
ReturnValue::decode(&mut &return_val[..]).map_err(|_| Error::Execution)?;
|
||||
Ok(return_val)
|
||||
},
|
||||
sandbox_primitives::ERR_EXECUTION => Err(Error::Execution),
|
||||
env::ERR_EXECUTION => Err(Error::Execution),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
Executable → Regular
+13
-12
@@ -40,26 +40,27 @@
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
pub mod embedded_executor;
|
||||
pub mod env;
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub mod host_executor;
|
||||
|
||||
use sp_core::RuntimeDebug;
|
||||
use sp_std::prelude::*;
|
||||
|
||||
pub use sp_core::sandbox::HostError;
|
||||
pub use sp_wasm_interface::{ReturnValue, Value};
|
||||
|
||||
#[cfg(not(all(feature = "wasmer-sandbox", not(feature = "std"))))]
|
||||
pub use self::embedded_executor as default_executor;
|
||||
pub use self::env::HostError;
|
||||
#[cfg(all(feature = "wasmer-sandbox", not(feature = "std")))]
|
||||
pub use self::host_executor as default_executor;
|
||||
|
||||
/// The target used for logging.
|
||||
const TARGET: &str = "runtime::sandbox";
|
||||
|
||||
pub mod embedded_executor;
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub mod host_executor;
|
||||
|
||||
#[cfg(all(feature = "wasmer-sandbox", not(feature = "std")))]
|
||||
pub use host_executor as default_executor;
|
||||
|
||||
#[cfg(not(all(feature = "wasmer-sandbox", not(feature = "std"))))]
|
||||
pub use embedded_executor as default_executor;
|
||||
|
||||
/// Error that can occur while using this crate.
|
||||
#[derive(sp_core::RuntimeDebug)]
|
||||
#[derive(RuntimeDebug)]
|
||||
pub enum Error {
|
||||
/// Module is not valid, couldn't be instantiated.
|
||||
Module,
|
||||
|
||||
Reference in New Issue
Block a user