mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-27 20:57:59 +00:00
8778ca7dc8
* Rename: Phase 1. * Unify codec. * Fixing: Phase 2 * Fixing: Phase 3. * Fixing: Phase 4. * Fixing: Phase 5. * Fixing: Phase 6. * Fixing: Phase 7. * Fixing: Phase 8. Tests * Fixing: Phase 9. Tests!!! * Fixing: Phase 10. Moar tests! * Finally done! * More fixes. * Rename primitives:: to sp_core:: * Apply renames in finality-grandpa. * Fix benches. * Fix benches 2. * Revert node-template. * Fix frame-system in our modules.
187 lines
5.6 KiB
Rust
187 lines
5.6 KiB
Rust
// Copyright 2017-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/>.
|
|
|
|
//! Utilities for defining the wasm host environment.
|
|
|
|
use sp_wasm_interface::{Pointer, WordSize};
|
|
|
|
/// 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 )* } )*
|
|
)
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
/// Runtime API functions return an i64 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 interpret_runtime_api_result(retval: i64) -> (Pointer<u8>, WordSize) {
|
|
let ptr = <Pointer<u8>>::new(retval as u32);
|
|
// The first cast to u64 is necessary so that the right shift does not sign-extend.
|
|
let len = ((retval as u64) >> 32) as WordSize;
|
|
(ptr, len)
|
|
}
|
|
|