mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 13:27:57 +00:00
Fix cycle dependency in sp-runtime-interface (#4353)
* Fix cycle dependency in `sp-runtime-interface` * Fixes tests
This commit is contained in:
@@ -72,6 +72,8 @@
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate self as sp_runtime_interface;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "std")]
|
||||
pub use wasm_interface;
|
||||
@@ -79,6 +81,148 @@ pub use wasm_interface;
|
||||
#[doc(hidden)]
|
||||
pub use sp_std;
|
||||
|
||||
/// Attribute macro for transforming a trait declaration into a runtime interface.
|
||||
///
|
||||
/// A runtime interface is a fixed interface between a Substrate compatible runtime and the native
|
||||
/// node. This interface is callable from a native and a wasm runtime. The macro will generate the
|
||||
/// corresponding code for the native implementation and the code for calling from the wasm
|
||||
/// side to the native implementation.
|
||||
///
|
||||
/// The macro expects the runtime interface declaration as trait declaration:
|
||||
///
|
||||
/// ```
|
||||
/// # use sp_runtime_interface::runtime_interface;
|
||||
///
|
||||
/// #[runtime_interface]
|
||||
/// trait Interface {
|
||||
/// /// A function that can be called from native/wasm.
|
||||
/// ///
|
||||
/// /// The implementation given to this function is only compiled on native.
|
||||
/// fn call_some_complex_code(data: &[u8]) -> Vec<u8> {
|
||||
/// // Here you could call some rather complex code that only compiles on native or
|
||||
/// // is way faster in native than executing it in wasm.
|
||||
/// Vec::new()
|
||||
/// }
|
||||
///
|
||||
/// /// A function can take a `&self` or `&mut self` argument to get access to the
|
||||
/// /// `Externalities`. (The generated method does not require
|
||||
/// /// this argument, so the function can be called just with the `optional` argument)
|
||||
/// fn set_or_clear(&mut self, optional: Option<Vec<u8>>) {
|
||||
/// match optional {
|
||||
/// Some(value) => self.set_storage([1, 2, 3, 4].to_vec(), value),
|
||||
/// None => self.clear_storage(&[1, 2, 3, 4]),
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// The given example will generate roughly the following code for native:
|
||||
///
|
||||
/// ```
|
||||
/// // The name of the trait is converted to snake case and used as mod name.
|
||||
/// //
|
||||
/// // Be aware that this module is not `public`, the visibility of the module is determined based
|
||||
/// // on the visibility of the trait declaration.
|
||||
/// mod interface {
|
||||
/// trait Interface {
|
||||
/// fn call_some_complex_code(data: &[u8]) -> Vec<u8>;
|
||||
/// fn set_or_clear(&mut self, optional: Option<Vec<u8>>);
|
||||
/// }
|
||||
///
|
||||
/// impl Interface for &mut dyn externalities::Externalities {
|
||||
/// fn call_some_complex_code(data: &[u8]) -> Vec<u8> { Vec::new() }
|
||||
/// fn set_or_clear(&mut self, optional: Option<Vec<u8>>) {
|
||||
/// match optional {
|
||||
/// Some(value) => self.set_storage([1, 2, 3, 4].to_vec(), value),
|
||||
/// None => self.clear_storage(&[1, 2, 3, 4]),
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// pub fn call_some_complex_code(data: &[u8]) -> Vec<u8> {
|
||||
/// <&mut dyn externalities::Externalities as Interface>::call_some_complex_code(data)
|
||||
/// }
|
||||
///
|
||||
/// pub fn set_or_clear(optional: Option<Vec<u8>>) {
|
||||
/// externalities::with_externalities(|mut ext| Interface::set_or_clear(&mut ext, optional))
|
||||
/// .expect("`set_or_clear` called outside of an Externalities-provided environment.")
|
||||
/// }
|
||||
///
|
||||
/// /// This type implements the `HostFunctions` trait (from `sp-wasm-interface`) and
|
||||
/// /// provides the host implementation for the wasm side. The host implementation converts the
|
||||
/// /// arguments from wasm to native and calls the corresponding native function.
|
||||
/// ///
|
||||
/// /// This type needs to be passed to the wasm executor, so that the host functions will be
|
||||
/// /// registered in the executor.
|
||||
/// pub struct HostFunctions;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// The given example will generate roughly the following code for wasm:
|
||||
///
|
||||
/// ```
|
||||
/// mod interface {
|
||||
/// mod extern_host_functions_impls {
|
||||
/// extern "C" {
|
||||
/// /// Every function is exported as `ext_TRAIT_NAME_FUNCTION_NAME_version_VERSION`.
|
||||
/// ///
|
||||
/// /// `TRAIT_NAME` is converted into snake case.
|
||||
/// ///
|
||||
/// /// The type for each argument of the exported function depends on
|
||||
/// /// `<ARGUMENT_TYPE as RIType>::FFIType`.
|
||||
/// ///
|
||||
/// /// `data` holds the pointer and the length to the `[u8]` slice.
|
||||
/// pub fn ext_Interface_call_some_complex_code_version_1(data: u64) -> u64;
|
||||
/// /// `optional` holds the pointer and the length of the encoded value.
|
||||
/// pub fn ext_Interface_set_or_clear_version_1(optional: u64);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// /// The type is actually `ExchangeableFunction` (from `sp-runtime-interface`).
|
||||
/// ///
|
||||
/// /// This can be used to replace the implementation of the `call_some_complex_code` function.
|
||||
/// /// Instead of calling into the host, the callee will automatically call the other
|
||||
/// /// implementation.
|
||||
/// ///
|
||||
/// /// To replace the implementation:
|
||||
/// ///
|
||||
/// /// `host_call_some_complex_code.replace_implementation(some_other_impl)`
|
||||
/// pub static host_call_some_complex_code: () = ();
|
||||
/// pub static host_set_or_clear: () = ();
|
||||
///
|
||||
/// pub fn call_some_complex_code(data: &[u8]) -> Vec<u8> {
|
||||
/// // This is the actual call: `host_call_some_complex_code.get()(data)`
|
||||
/// //
|
||||
/// // But that does not work for several reasons in this example, so we just return an
|
||||
/// // empty vector.
|
||||
/// Vec::new()
|
||||
/// }
|
||||
///
|
||||
/// pub fn set_or_clear(optional: Option<Vec<u8>>) {
|
||||
/// // Same as above
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Argument types
|
||||
///
|
||||
/// The macro supports any kind of argument type, as long as it implements [`RIType`] and the
|
||||
/// required `FromFFIValue`/`IntoFFIValue`. The macro will convert each
|
||||
/// argument to the corresponding FFI representation and will call into the host using this FFI
|
||||
/// representation. On the host each argument is converted back to the native representation and
|
||||
/// the native implementation is called. Any return value is handled in the same way.
|
||||
///
|
||||
/// # Wasm only interfaces
|
||||
///
|
||||
/// Some interfaces are only required from within the wasm runtime e.g. the allocator interface.
|
||||
/// To support this, the macro can be called like `#[runtime_interface(wasm_only)]`. This instructs
|
||||
/// the macro to make two significant changes to the generated code:
|
||||
///
|
||||
/// 1. The generated functions are not callable from the native side.
|
||||
/// 2. The trait as shown above is not implemented for `Externalities` and is instead implemented
|
||||
/// for `FunctionExecutor` (from `sp-wasm-interface`).
|
||||
pub use sp_runtime_interface_proc_macro::runtime_interface;
|
||||
|
||||
#[doc(hidden)]
|
||||
|
||||
Reference in New Issue
Block a user