mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 08:47:57 +00:00
Extract execution engines definitions into their own crates (#4489)
* Clean imports in wasmi_execution * Replace `interpret_runtime_api_result` with `pointer_and_len_from_u64`. * Extract sc-executor-common crate * Extract `sc-executor-wasmi` into its own crate * Extract `sc-executor-wasmtime` into its own crate. * Add missing headers. * Clean and docs * Docs for sc-executor-wasmi * Expand a comment about sandboxing * Fix assert_matches * Rename (un)pack_ptr_and_len and move them into util module * Remove wasmtime errors in sc-executor-common
This commit is contained in:
@@ -16,7 +16,10 @@
|
||||
|
||||
//! Provides implementations for the runtime interface traits.
|
||||
|
||||
use crate::{RIType, Pointer, pass_by::{PassBy, Codec, Inner, PassByInner}};
|
||||
use crate::{
|
||||
RIType, Pointer, pass_by::{PassBy, Codec, Inner, PassByInner},
|
||||
util::{unpack_ptr_and_len, pack_ptr_and_len},
|
||||
};
|
||||
#[cfg(feature = "std")]
|
||||
use crate::host::*;
|
||||
#[cfg(not(feature = "std"))]
|
||||
@@ -44,27 +47,6 @@ assert_eq_size!(usize, u32);
|
||||
#[cfg(all(not(feature = "std"), not(feature = "disable_target_static_assertions")))]
|
||||
assert_eq_size!(*const u8, u32);
|
||||
|
||||
/// Converts a pointer and length into an `u64`.
|
||||
pub fn pointer_and_len_to_u64(ptr: u32, len: u32) -> u64 {
|
||||
// The static assertions from above are changed into a runtime check.
|
||||
#[cfg(all(not(feature = "std"), feature = "disable_target_static_assertions"))]
|
||||
assert_eq!(4, sp_std::mem::size_of::<usize>());
|
||||
|
||||
(u64::from(len) << 32) | u64::from(ptr)
|
||||
}
|
||||
|
||||
/// Splits an `u64` into the pointer and length.
|
||||
pub fn pointer_and_len_from_u64(val: u64) -> (u32, u32) {
|
||||
// The static assertions from above are changed into a runtime check.
|
||||
#[cfg(all(not(feature = "std"), feature = "disable_target_static_assertions"))]
|
||||
assert_eq!(4, sp_std::mem::size_of::<usize>());
|
||||
|
||||
let ptr = (val & (!0u32 as u64)) as u32;
|
||||
let len = (val >> 32) as u32;
|
||||
|
||||
(ptr, len)
|
||||
}
|
||||
|
||||
/// Implement the traits for the given primitive traits.
|
||||
macro_rules! impl_traits_for_primitives {
|
||||
(
|
||||
@@ -186,7 +168,7 @@ impl<T: 'static + Encode> IntoFFIValue for Vec<T> {
|
||||
let ptr = context.allocate_memory(vec.as_ref().len() as u32)?;
|
||||
context.write_memory(ptr, &vec)?;
|
||||
|
||||
Ok(pointer_and_len_to_u64(ptr.into(), vec.len() as u32))
|
||||
Ok(pack_ptr_and_len(ptr.into(), vec.len() as u32))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +193,7 @@ impl<T: 'static + Encode> IntoFFIValue for Vec<T> {
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl<T: 'static + Decode> FromFFIValue for Vec<T> {
|
||||
fn from_ffi_value(arg: u64) -> Vec<T> {
|
||||
let (ptr, len) = pointer_and_len_from_u64(arg);
|
||||
let (ptr, len) = unpack_ptr_and_len(arg);
|
||||
let len = len as usize;
|
||||
|
||||
if TypeId::of::<T>() == TypeId::of::<u8>() {
|
||||
@@ -238,7 +220,7 @@ impl<T: 'static + Decode> FromFFIValue for [T] {
|
||||
type SelfInstance = Vec<T>;
|
||||
|
||||
fn from_ffi_value(context: &mut dyn FunctionContext, arg: u64) -> Result<Vec<T>> {
|
||||
let (ptr, len) = pointer_and_len_from_u64(arg);
|
||||
let (ptr, len) = unpack_ptr_and_len(arg);
|
||||
|
||||
let vec = context.read_memory(Pointer::new(ptr), len)?;
|
||||
|
||||
@@ -259,7 +241,7 @@ impl IntoPreallocatedFFIValue for [u8] {
|
||||
context: &mut dyn FunctionContext,
|
||||
allocated: u64,
|
||||
) -> Result<()> {
|
||||
let (ptr, len) = pointer_and_len_from_u64(allocated);
|
||||
let (ptr, len) = unpack_ptr_and_len(allocated);
|
||||
|
||||
if (len as usize) < self_instance.len() {
|
||||
Err(
|
||||
@@ -282,10 +264,10 @@ impl<T: 'static + Encode> IntoFFIValue for [T] {
|
||||
fn into_ffi_value(&self) -> WrappedFFIValue<u64, Vec<u8>> {
|
||||
if TypeId::of::<T>() == TypeId::of::<u8>() {
|
||||
let slice = unsafe { mem::transmute::<&[T], &[u8]>(self) };
|
||||
pointer_and_len_to_u64(slice.as_ptr() as u32, slice.len() as u32).into()
|
||||
pack_ptr_and_len(slice.as_ptr() as u32, slice.len() as u32).into()
|
||||
} else {
|
||||
let data = self.encode();
|
||||
let ffi_value = pointer_and_len_to_u64(data.as_ptr() as u32, data.len() as u32);
|
||||
let ffi_value = pack_ptr_and_len(data.as_ptr() as u32, data.len() as u32);
|
||||
(ffi_value, data).into()
|
||||
}
|
||||
}
|
||||
@@ -428,7 +410,7 @@ impl FromFFIValue for str {
|
||||
type SelfInstance = String;
|
||||
|
||||
fn from_ffi_value(context: &mut dyn FunctionContext, arg: u64) -> Result<String> {
|
||||
let (ptr, len) = pointer_and_len_from_u64(arg);
|
||||
let (ptr, len) = unpack_ptr_and_len(arg);
|
||||
|
||||
let vec = context.read_memory(Pointer::new(ptr), len)?;
|
||||
|
||||
@@ -443,7 +425,7 @@ impl IntoFFIValue for str {
|
||||
|
||||
fn into_ffi_value(&self) -> WrappedFFIValue<u64, ()> {
|
||||
let bytes = self.as_bytes();
|
||||
pointer_and_len_to_u64(bytes.as_ptr() as u32, bytes.len() as u32).into()
|
||||
pack_ptr_and_len(bytes.as_ptr() as u32, bytes.len() as u32).into()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -241,6 +241,10 @@ pub mod host;
|
||||
pub mod wasm;
|
||||
pub mod pass_by;
|
||||
|
||||
mod util;
|
||||
|
||||
pub use util::unpack_ptr_and_len;
|
||||
|
||||
/// Something that can be used by the runtime interface as type to communicate between wasm and the
|
||||
/// host.
|
||||
///
|
||||
@@ -260,4 +264,4 @@ pub type Pointer<T> = *mut T;
|
||||
|
||||
/// A pointer that can be used in a runtime interface function signature.
|
||||
#[cfg(feature = "std")]
|
||||
pub type Pointer<T> = sp_wasm_interface::Pointer<T>;
|
||||
pub type Pointer<T> = sp_wasm_interface::Pointer<T>;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
//! [`Codec`](pass_by::Codec), [`Inner`](pass_by::Inner) and [`Enum`](pass_by::Enum) are the
|
||||
//! provided strategy implementations.
|
||||
|
||||
use crate::{RIType, impls::{pointer_and_len_from_u64, pointer_and_len_to_u64}};
|
||||
use crate::{RIType, util::{unpack_ptr_and_len, pack_ptr_and_len}};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use crate::host::*;
|
||||
@@ -228,14 +228,14 @@ impl<T: codec::Codec> PassByImpl<T> for Codec<T> {
|
||||
let ptr = context.allocate_memory(vec.len() as u32)?;
|
||||
context.write_memory(ptr, &vec)?;
|
||||
|
||||
Ok(pointer_and_len_to_u64(ptr.into(), vec.len() as u32))
|
||||
Ok(pack_ptr_and_len(ptr.into(), vec.len() as u32))
|
||||
}
|
||||
|
||||
fn from_ffi_value(
|
||||
context: &mut dyn FunctionContext,
|
||||
arg: Self::FFIType,
|
||||
) -> Result<T> {
|
||||
let (ptr, len) = pointer_and_len_from_u64(arg);
|
||||
let (ptr, len) = unpack_ptr_and_len(arg);
|
||||
let vec = context.read_memory(Pointer::new(ptr), len)?;
|
||||
T::decode(&mut &vec[..])
|
||||
.map_err(|e| format!("Could not decode value from wasm: {}", e.what()))
|
||||
@@ -248,12 +248,12 @@ impl<T: codec::Codec> PassByImpl<T> for Codec<T> {
|
||||
|
||||
fn into_ffi_value(instance: &T) -> WrappedFFIValue<Self::FFIType, Self::Owned> {
|
||||
let data = instance.encode();
|
||||
let ffi_value = pointer_and_len_to_u64(data.as_ptr() as u32, data.len() as u32);
|
||||
let ffi_value = pack_ptr_and_len(data.as_ptr() as u32, data.len() as u32);
|
||||
(ffi_value, data).into()
|
||||
}
|
||||
|
||||
fn from_ffi_value(arg: Self::FFIType) -> T {
|
||||
let (ptr, len) = pointer_and_len_from_u64(arg);
|
||||
let (ptr, len) = unpack_ptr_and_len(arg);
|
||||
let len = len as usize;
|
||||
|
||||
let slice = unsafe { slice::from_raw_parts(ptr as *const u8, len) };
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Various utilities that help interfacing with wasm runtime code.
|
||||
|
||||
/// Pack a pointer and length into an `u64`.
|
||||
pub fn pack_ptr_and_len(ptr: u32, len: u32) -> u64 {
|
||||
// The static assertions from above are changed into a runtime check.
|
||||
#[cfg(all(not(feature = "std"), feature = "disable_target_static_assertions"))]
|
||||
assert_eq!(4, sp_std::mem::size_of::<usize>());
|
||||
|
||||
(u64::from(len) << 32) | u64::from(ptr)
|
||||
}
|
||||
|
||||
/// Unpacks an `u64` into the pointer and length.
|
||||
///
|
||||
/// Runtime API functions return a 64-bit value which encodes a pointer in the least-significant
|
||||
/// 32-bits and a length in the most-significant 32 bits. This interprets the returned value as a pointer,
|
||||
/// length tuple.
|
||||
pub fn unpack_ptr_and_len(val: u64) -> (u32, u32) {
|
||||
// The static assertions from above are changed into a runtime check.
|
||||
#[cfg(all(not(feature = "std"), feature = "disable_target_static_assertions"))]
|
||||
assert_eq!(4, sp_std::mem::size_of::<usize>());
|
||||
|
||||
let ptr = (val & (!0u32 as u64)) as u32;
|
||||
let len = (val >> 32) as u32;
|
||||
|
||||
(ptr, len)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{pack_ptr_and_len, unpack_ptr_and_len};
|
||||
|
||||
#[test]
|
||||
fn ptr_len_packing_unpacking() {
|
||||
const PTR: u32 = 0x1337;
|
||||
const LEN: u32 = 0x7f000000;
|
||||
|
||||
let packed = pack_ptr_and_len(PTR, LEN);
|
||||
let (ptr, len) = unpack_ptr_and_len(packed);
|
||||
|
||||
assert_eq!(PTR, ptr);
|
||||
assert_eq!(LEN, len);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user