Skip to content
Snippets Groups Projects
Commit e5123166 authored by Bastian Köcher's avatar Bastian Köcher Committed by GitHub
Browse files

Remove deprecated host functions (#5038)

Sadly we need to keep one function `ext_blake2_256`. This function is
manually defined in `sp-core`.
parent 5907b0d9
No related merge requests found
This diff is collapsed.
......@@ -29,11 +29,8 @@
#![warn(missing_docs)]
#![recursion_limit="128"]
#[macro_use]
mod wasm_utils;
#[macro_use]
mod native_executor;
pub mod deprecated_host_interface;
mod wasm_runtime;
#[cfg(test)]
mod integration_tests;
......
......@@ -101,10 +101,6 @@ impl<D: NativeExecutionDispatch> NativeExecutor<D> {
/// Defaults to `DEFAULT_HEAP_PAGES` if `None` is provided.
pub fn new(fallback_method: WasmExecutionMethod, default_heap_pages: Option<u64>) -> Self {
let mut host_functions = sp_io::SubstrateHostFunctions::host_functions();
// Add the old and deprecated host functions as well, so that we support old wasm runtimes.
host_functions.extend(
crate::deprecated_host_interface::SubstrateExternals::host_functions(),
);
// Add the custom host functions provided by the user.
host_functions.extend(D::ExtendHostFunctions::host_functions());
......
// Copyright 2017-2020 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/>.
//! Utilities for defining the wasm host environment.
/// Converts arguments into respective WASM types.
#[macro_export]
macro_rules! convert_args {
() => ([]);
( $( $t:ty ),* ) => ( [ $( <$t as $crate::sp_wasm_interface::IntoValue>::VALUE_TYPE, )* ] );
}
/// Generates a WASM signature for given list of parameters.
#[macro_export]
macro_rules! gen_signature {
( ( $( $params: ty ),* ) ) => (
$crate::sp_wasm_interface::Signature {
args: std::borrow::Cow::Borrowed(&convert_args!( $( $params ),* )[..]),
return_value: None,
}
);
( ( $( $params: ty ),* ) -> $returns:ty ) => (
$crate::sp_wasm_interface::Signature {
args: std::borrow::Cow::Borrowed(&convert_args!( $( $params ),* )[..]),
return_value: Some(<$returns as $crate::sp_wasm_interface::IntoValue>::VALUE_TYPE),
}
);
}
macro_rules! gen_functions {
(@INTERNAL
{ $( $generated:tt )* }
$context:ident,
) => (
vec![ $( $generated )* ]
);
(@INTERNAL
{ $( $generated:tt )* }
$context:ident,
$name:ident ( $( $names:ident: $params:ty ),* ) $( -> $returns:ty )? { $( $body:tt )* }
$( $tail:tt )*
) => (
gen_functions! {
@INTERNAL
{
$( $generated )*
{
struct $name;
#[allow(unused)]
impl $crate::sp_wasm_interface::Function for $name {
fn name(&self) -> &str {
stringify!($name)
}
fn signature(&self) -> $crate::sp_wasm_interface::Signature {
gen_signature!( ( $( $params ),* ) $( -> $returns )? )
}
fn execute(
&self,
context: &mut dyn $crate::sp_wasm_interface::FunctionContext,
args: &mut dyn Iterator<Item=$crate::sp_wasm_interface::Value>,
) -> ::std::result::Result<Option<$crate::sp_wasm_interface::Value>, String> {
let mut $context = context;
marshall! {
args,
( $( $names : $params ),* ) $( -> $returns )? => { $( $body )* }
}
}
}
&$name as &dyn $crate::sp_wasm_interface::Function
},
}
$context,
$( $tail )*
}
);
( $context:ident, $( $tail:tt )* ) => (
gen_functions!(@INTERNAL {} $context, $($tail)*);
);
}
/// Converts the list of arguments coming from WASM into their native types.
#[macro_export]
macro_rules! unmarshall_args {
( $body:tt, $args_iter:ident, $( $names:ident : $params:ty ),*) => ({
$(
let $names : $params =
$args_iter.next()
.and_then(|val| <$params as $crate::sp_wasm_interface::TryFromValue>::try_from_value(val))
.expect(
"`$args_iter` comes from an argument of Externals::execute_function;
args to an external call always matches the signature of the external;
external signatures are built with count and types and in order defined by `$params`;
here, we iterating on `$params`;
qed;
"
);
)*
$body
})
}
/// Since we can't specify the type of closure directly at binding site:
///
/// ```nocompile
/// let f: FnOnce() -> Result<<u32 as ConvertibleToWasm>::NativeType, _> = || { /* ... */ };
/// ```
///
/// we use this function to constrain the type of the closure.
#[inline(always)]
pub fn constrain_closure<R, F>(f: F) -> F
where
F: FnOnce() -> Result<R, String>
{
f
}
/// Pass the list of parameters by converting them to respective WASM types.
#[macro_export]
macro_rules! marshall {
( $args_iter:ident, ( $( $names:ident : $params:ty ),* ) -> $returns:ty => $body:tt ) => ({
let body = $crate::wasm_utils::constrain_closure::<$returns, _>(|| {
unmarshall_args!($body, $args_iter, $( $names : $params ),*)
});
let r = body()?;
return Ok(Some($crate::sp_wasm_interface::IntoValue::into_value(r)))
});
( $args_iter:ident, ( $( $names:ident : $params:ty ),* ) => $body:tt ) => ({
let body = $crate::wasm_utils::constrain_closure::<(), _>(|| {
unmarshall_args!($body, $args_iter, $( $names : $params ),*)
});
body()?;
return Ok(None)
})
}
/// Implements the wasm host interface for the given type.
#[macro_export]
macro_rules! impl_wasm_host_interface {
(
impl $interface_name:ident where $context:ident {
$(
$name:ident($( $names:ident : $params:ty ),* $(,)? ) $( -> $returns:ty )?
{ $( $body:tt )* }
)*
}
) => (
impl $crate::sp_wasm_interface::HostFunctions for $interface_name {
#[allow(non_camel_case_types)]
fn host_functions() -> Vec<&'static dyn $crate::sp_wasm_interface::Function> {
gen_functions!(
$context,
$( $name( $( $names: $params ),* ) $( -> $returns )? { $( $body )* } )*
)
}
}
);
}
......@@ -915,6 +915,56 @@ pub fn oom(_: core::alloc::Layout) -> ! {
#[cfg(feature = "std")]
pub type TestExternalities = sp_state_machine::TestExternalities<sp_core::Blake2Hasher, u64>;
#[cfg(feature = "std")]
mod ext_blake2_256 {
use sp_wasm_interface::{Signature, Function, HostFunctions, ValueType, Value, FunctionContext};
/// There is a custom `extern function` in `sp_core::hasher` for `ext_blake2_256` hasher. This
/// custom extern was missed to remove and requires us to support this now. This type is a custom
/// implementation for the wasm function in native.
pub struct ExtBlake2_256;
impl HostFunctions for ExtBlake2_256 {
fn host_functions() -> Vec<&'static dyn Function> {
vec![&ExtBlake2_256]
}
}
impl Function for ExtBlake2_256 {
fn name(&self) -> &str {
"ext_blake2_256"
}
fn signature(&self) -> Signature {
Signature::new_with_args(&[ValueType::I32, ValueType::I32, ValueType::I32][..])
}
fn execute(
&self,
context: &mut dyn FunctionContext,
args: &mut dyn Iterator<Item = Value>,
) -> sp_wasm_interface::Result<Option<Value>> {
let data = args.next().and_then(|v| v.as_i32())
.ok_or_else(|| "`data` not present or not an `i32`")? as u32;
let len = args.next().and_then(|v| v.as_i32())
.ok_or_else(|| "`len` not present or not an `i32`")? as u32;
let out = args.next().and_then(|v| v.as_i32())
.ok_or_else(|| "`out` not present or not an `i32`")? as u32;
let result: [u8; 32] = if len == 0 {
sp_core::hashing::blake2_256(&[0u8; 0])
} else {
let mem = context.read_memory(data.into(), len)
.map_err(|_| "Invalid attempt to get data in ext_blake2_256")?;
sp_core::hashing::blake2_256(&mem)
};
context.write_memory(out.into(), &result)
.map_err(|_| "Invalid attempt to set result in ext_blake2_256")?;
Ok(None)
}
}
}
/// The host functions Substrate provides for the Wasm runtime environment.
///
/// All these host functions will be callable from inside the Wasm environment.
......@@ -929,6 +979,7 @@ pub type SubstrateHostFunctions = (
logging::HostFunctions,
sandbox::HostFunctions,
crate::trie::HostFunctions,
ext_blake2_256::ExtBlake2_256,
);
#[cfg(test)]
......
......@@ -105,23 +105,6 @@ pub trait TestApi {
}
}
/// Two random external functions from the old runtime interface.
/// This ensures that we still inherently export these functions from the host and that we are still
/// compatible with old wasm runtimes.
#[cfg(not(feature = "std"))]
extern "C" {
pub fn ext_clear_storage(key_data: *const u8, key_len: u32);
pub fn ext_keccak_256(data: *const u8, len: u32, out: *mut u8);
}
/// Make sure the old runtime interface needs to be imported.
#[no_mangle]
#[cfg(not(feature = "std"))]
pub fn force_old_runtime_interface_import() {
unsafe { ext_clear_storage(sp_std::ptr::null(), 0); }
unsafe { ext_keccak_256(sp_std::ptr::null(), 0, sp_std::ptr::null_mut()); }
}
/// This function is not used, but we require it for the compiler to include `sp-io`.
/// `sp-io` is required for its panic and oom handler.
#[no_mangle]
......@@ -248,4 +231,14 @@ wasm_export_functions! {
}
assert_eq!(0, len);
}
fn test_ext_blake2_256() {
use sp_core::Hasher;
let data = "hey, hash me please!";
let hash = sp_core::Blake2Hasher::hash(data.as_bytes());
let expected = sp_io::hashing::blake2_256(data.as_bytes());
assert_eq!(&expected, hash.as_ref());
}
}
......@@ -33,7 +33,6 @@ fn call_wasm_method<HF: HostFunctionsT>(method: &str) -> TestExternalities {
(
HF,
sp_io::SubstrateHostFunctions,
sc_executor::deprecated_host_interface::SubstrateExternals
)
>(
method,
......@@ -128,3 +127,8 @@ fn test_encoded_return_value_memory_is_freed() {
fn test_array_return_value_memory_is_freed() {
call_wasm_method::<HostFunctions>("test_array_return_value_memory_is_freed");
}
#[test]
fn test_ext_blake2_256() {
call_wasm_method::<HostFunctions>("test_ext_blake2_256");
}
......@@ -170,6 +170,12 @@ impl<T: PointerType> Pointer<T> {
}
}
impl<T: PointerType> From<u32> for Pointer<T> {
fn from(ptr: u32) -> Self {
Pointer::new(ptr)
}
}
impl<T: PointerType> From<Pointer<T>> for u32 {
fn from(ptr: Pointer<T>) -> Self {
ptr.ptr
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment