referrerpolicy=no-referrer-when-downgrade

sp_runtime_interface/
lib.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Substrate runtime interface
19//!
20//! This crate provides types, traits and macros around runtime interfaces. A runtime interface is
21//! a fixed interface between a Substrate runtime (also called the "guest") and a Substrate node
22//! (also called the "host"). For a native runtime the interface maps to direct function calls of
23//! the implementation. For a non-native runtime the interface maps to an external function call.
24//! These external functions are exported by the runtime and they map to the same implementation
25//! as the native calls, just with some extra code to marshal them through the FFI boundary.
26//!
27//! # Using a type in a runtime interface
28//!
29//! Every argument type and return type must be wrapped in a marker newtype specifying the
30//! marshalling strategy used to pass the value through the FFI boundary between the host
31//! and the runtime. The only exceptions to this rule are a couple of basic, primitive types
32//! which can be passed directly through the FFI boundary and which don't require any special
33//! handling besides a straightforward, direct conversion.
34//!
35//! You can find the strategy wrapper types in the [`crate::pass_by`] module.
36//!
37//! The newtype wrappers are automatically stripped away when the function is called
38//! and applied when the function returns by the `runtime_interface` macro.
39//!
40//! # Declaring a runtime interface
41//!
42//! Declaring a runtime interface is similar to declaring a trait in Rust:
43//!
44//! ```
45//! # mod wrapper {
46//! # use sp_runtime_interface::pass_by::PassFatPointerAndRead;
47//!
48//! #[sp_runtime_interface::runtime_interface]
49//! trait RuntimeInterface {
50//!     fn some_function(value: PassFatPointerAndRead<&[u8]>) -> bool {
51//!         value.iter().all(|v| *v > 125)
52//!     }
53//! }
54//! # }
55//! ```
56//!
57//! For more information on declaring a runtime interface, see
58//! [`#[runtime_interface]`](./attr.runtime_interface.html).
59
60#![no_std]
61
62pub extern crate alloc;
63extern crate self as sp_runtime_interface;
64
65#[doc(hidden)]
66#[cfg(not(substrate_runtime))]
67pub use sp_wasm_interface;
68
69#[doc(hidden)]
70pub use sp_tracing;
71
72#[doc(hidden)]
73pub use sp_std;
74
75/// Attribute macro for transforming a trait declaration into a runtime interface.
76///
77/// A runtime interface is a fixed interface between a Substrate compatible runtime and the
78/// native node. This interface is callable from a native and a wasm runtime. The macro will
79/// generate the corresponding code for the native implementation and the code for calling from
80/// the wasm side to the native implementation.
81///
82/// The macro expects the runtime interface declaration as trait declaration:
83///
84/// ```
85/// # mod wrapper {
86/// # use sp_runtime_interface::runtime_interface;
87/// # use sp_runtime_interface::pass_by::{PassFatPointerAndDecode, PassFatPointerAndRead, AllocateAndReturnFatPointer};
88///
89/// #[runtime_interface]
90/// trait Interface {
91///     /// A function that can be called from native/wasm.
92///     ///
93///     /// The implementation given to this function is only compiled on native.
94///     fn call(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnFatPointer<Vec<u8>> {
95///         // Here you could call some rather complex code that only compiles on native or
96///         // is way faster in native than executing it in wasm.
97///         Vec::new()
98///     }
99///     /// Call function, but different version.
100///     ///
101///     /// For new runtimes, only function with latest version is reachable.
102///     /// But old version (above) is still accessible for old runtimes.
103///     /// Default version is 1.
104///     #[version(2)]
105///     fn call(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnFatPointer<Vec<u8>> {
106///         // Here you could call some rather complex code that only compiles on native or
107///         // is way faster in native than executing it in wasm.
108///         [17].to_vec()
109///     }
110///
111///     /// Call function, different version and only being registered.
112///     ///
113///     /// This `register_only` version is only being registered, aka exposed to the runtime,
114///     /// but the runtime will still use the version 2 of this function. This is useful for when
115///     /// new host functions should be introduced. Adding new host functions requires that all
116///     /// nodes have the host functions available, because otherwise they fail at instantiation
117///     /// of the runtime. With `register_only` the function will not be used when compiling the
118///     /// runtime, but it will already be there for a future version of the runtime that will
119///     /// switch to using these host function.
120///     #[version(3, register_only)]
121///     fn call(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnFatPointer<Vec<u8>> {
122///         // Here you could call some rather complex code that only compiles on native or
123///         // is way faster in native than executing it in wasm.
124///         [18].to_vec()
125///     }
126///
127///     /// A function can take a `&self` or `&mut self` argument to get access to the
128///     /// `Externalities`. (The generated method does not require
129///     /// this argument, so the function can be called just with the `optional` argument)
130///     fn set_or_clear(&mut self, optional: PassFatPointerAndDecode<Option<Vec<u8>>>) {
131///         match optional {
132///             Some(value) => self.set_storage([1, 2, 3, 4].to_vec(), value),
133///             None => self.clear_storage(&[1, 2, 3, 4]),
134///         }
135///     }
136///
137///     /// A function can be gated behind a configuration (`cfg`) attribute.
138///     /// To prevent ambiguity and confusion about what will be the final exposed host
139///     /// functions list, conditionally compiled functions can't be versioned.
140///     /// That is, conditionally compiled functions with `version`s greater than 1
141///     /// are not allowed.
142///     #[cfg(feature = "experimental-function")]
143///     fn gated_call(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnFatPointer<Vec<u8>> {
144///         [42].to_vec()
145///     }
146/// }
147/// # }
148/// ```
149///
150/// The given example will generate roughly the following code for native:
151///
152/// ```
153/// // The name of the trait is converted to snake case and used as mod name.
154/// //
155/// // Be aware that this module is not `public`, the visibility of the module is determined based
156/// // on the visibility of the trait declaration.
157/// mod interface {
158///     trait Interface {
159///         fn call_version_1(data: &[u8]) -> Vec<u8>;
160///         fn call_version_2(data: &[u8]) -> Vec<u8>;
161///         fn call_version_3(data: &[u8]) -> Vec<u8>;
162///         fn set_or_clear_version_1(&mut self, optional: Option<Vec<u8>>);
163///         #[cfg(feature = "experimental-function")]
164///         fn gated_call_version_1(data: &[u8]) -> Vec<u8>;
165///     }
166///
167///     impl Interface for &mut dyn sp_externalities::Externalities {
168///         fn call_version_1(data: &[u8]) -> Vec<u8> { Vec::new() }
169///         fn call_version_2(data: &[u8]) -> Vec<u8> { [17].to_vec() }
170///         fn call_version_3(data: &[u8]) -> Vec<u8> { [18].to_vec() }
171///         fn set_or_clear_version_1(&mut self, optional: Option<Vec<u8>>) {
172///             match optional {
173///                 Some(value) => self.set_storage([1, 2, 3, 4].to_vec(), value),
174///                 None => self.clear_storage(&[1, 2, 3, 4]),
175///             }
176///         }
177///         #[cfg(feature = "experimental-function")]
178///         fn gated_call_version_1(data: &[u8]) -> Vec<u8> { [42].to_vec() }
179///     }
180///
181///     pub fn call(data: &[u8]) -> Vec<u8> {
182///         // only latest version is exposed
183///         call_version_2(data)
184///     }
185///
186///     fn call_version_1(data: &[u8]) -> Vec<u8> {
187///         <&mut dyn sp_externalities::Externalities as Interface>::call_version_1(data)
188///     }
189///
190///     fn call_version_2(data: &[u8]) -> Vec<u8> {
191///         <&mut dyn sp_externalities::Externalities as Interface>::call_version_2(data)
192///     }
193///
194///     fn call_version_3(data: &[u8]) -> Vec<u8> {
195///         <&mut dyn sp_externalities::Externalities as Interface>::call_version_3(data)
196///     }
197///
198///     pub fn set_or_clear(optional: Option<Vec<u8>>) {
199///         set_or_clear_version_1(optional)
200///     }
201///
202///     fn set_or_clear_version_1(optional: Option<Vec<u8>>) {
203///         sp_externalities::with_externalities(|mut ext| Interface::set_or_clear_version_1(&mut ext, optional))
204///             .expect("`set_or_clear` called outside of an Externalities-provided environment.")
205///     }
206///
207///     #[cfg(feature = "experimental-function")]
208///     pub fn gated_call(data: &[u8]) -> Vec<u8> {
209///         gated_call_version_1(data)
210///     }
211///
212///     #[cfg(feature = "experimental-function")]
213///     fn gated_call_version_1(data: &[u8]) -> Vec<u8> {
214///         <&mut dyn sp_externalities::Externalities as Interface>::gated_call_version_1(data)
215///     }
216///
217///     /// This type implements the `HostFunctions` trait (from `sp-wasm-interface`) and
218///     /// provides the host implementation for the wasm side. The host implementation converts the
219///     /// arguments from wasm to native and calls the corresponding native function.
220///     ///
221///     /// This type needs to be passed to the wasm executor, so that the host functions will be
222///     /// registered in the executor.
223///     pub struct HostFunctions;
224/// }
225/// ```
226///
227/// The given example will generate roughly the following code for wasm:
228///
229/// ```
230/// mod interface {
231///     mod extern_host_functions_impls {
232///         /// Every function is exported by the native code as `ext_FUNCTION_NAME_version_VERSION`.
233///         ///
234///         /// The type for each argument of the exported function depends on
235///         /// `<ARGUMENT_TYPE as RIType>::FFIType`.
236///         ///
237///         /// `key` holds the pointer and the length to the `data` slice.
238///         pub fn call(data: &[u8]) -> Vec<u8> {
239///             extern "C" { pub fn ext_call_version_2(key: u64); }
240///             // Should call into external `ext_call_version_2(<[u8] as IntoFFIValue>::into_ffi_value(key))`
241///             // But this is too much to replicate in a doc test so here we just return a dummy vector.
242///             // Note that we jump into the latest version not marked as `register_only` (i.e. version 2).
243///             Vec::new()
244///         }
245///
246///         /// `key` holds the pointer and the length of the `option` value.
247///         pub fn set_or_clear(option: Option<Vec<u8>>) {
248///             extern "C" { pub fn ext_set_or_clear_version_1(key: u64); }
249///             // Same as above
250///         }
251///
252///         /// `key` holds the pointer and the length to the `data` slice.
253///         #[cfg(feature = "experimental-function")]
254///         pub fn gated_call(data: &[u8]) -> Vec<u8> {
255///             extern "C" { pub fn ext_gated_call_version_1(key: u64); }
256///             /// Same as above
257///             Vec::new()
258///         }
259///     }
260///
261///     /// The type is actually `ExchangeableFunction` (from `sp-runtime-interface`) and
262///     /// by default this is initialized to jump into the corresponding function in
263///     /// `extern_host_functions_impls`.
264///     ///
265///     /// This can be used to replace the implementation of the `call` function.
266///     /// Instead of calling into the host, the callee will automatically call the other
267///     /// implementation.
268///     ///
269///     /// To replace the implementation:
270///     ///
271///     /// `host_call.replace_implementation(some_other_impl)`
272///     pub static host_call: () = ();
273///     pub static host_set_or_clear: () = ();
274///     #[cfg(feature = "experimental-feature")]
275///     pub static gated_call: () = ();
276///
277///     pub fn call(data: &[u8]) -> Vec<u8> {
278///         // This is the actual call: `host_call.get()(data)`
279///         //
280///         // But that does not work for several reasons in this example, so we just return an
281///         // empty vector.
282///         Vec::new()
283///     }
284///
285///     pub fn set_or_clear(optional: Option<Vec<u8>>) {
286///         // Same as above
287///     }
288///
289///     #[cfg(feature = "experimental-feature")]
290///     pub fn gated_call(data: &[u8]) -> Vec<u8> {
291///         // Same as above
292///         Vec::new()
293///     }
294/// }
295/// ```
296///
297/// # Argument and return types
298///
299/// Every argument type and return type must be wrapped in a marker newtype specifying the
300/// marshalling strategy used to pass the value through the FFI boundary between the host
301/// and the runtime. The only exceptions to this rule are a couple of basic, primitive types
302/// which can be passed directly through the FFI boundary and which don't require any special
303/// handling besides a straightforward, direct conversion.
304///
305/// The following table documents those types which can be passed between the host and the
306/// runtime without a marshalling strategy wrapper:
307///
308/// | Type | FFI type | Conversion |
309/// |----|----|----|
310/// | `u8` | `u32` | zero-extended to 32-bits |
311/// | `u16` | `u32` | zero-extended to 32-bits |
312/// | `u32` | `u32` | `Identity` |
313/// | `u64` | `u64` | `Identity` |
314/// | `i8` | `i32` | sign-extended to 32-bits |
315/// | `i16` | `i32` | sign-extended to 32-bits |
316/// | `i32` | `i32` | `Identity` |
317/// | `i64` | `i64` | `Identity` |
318/// | `bool` | `u32` | `if v { 1 } else { 0 }` |
319/// | `*const T` | `u32` | `Identity` |
320///
321/// `Identity` means that the value is passed as-is directly in a bit-exact fashion.
322///
323/// You can find the strategy wrapper types in the [`crate::pass_by`] module.
324///
325/// The newtype wrappers are automatically stripped away when the function is called
326/// and applied when the function returns by the `runtime_interface` macro.
327///
328/// # Wasm only interfaces
329///
330/// Some interfaces are only required from within the wasm runtime e.g. the allocator
331/// interface. To support this, the macro can be called like `#[runtime_interface(wasm_only)]`.
332/// This instructs the macro to make two significant changes to the generated code:
333///
334/// 1. The generated functions are not callable from the native side.
335/// 2. The trait as shown above is not implemented for [`Externalities`] and is instead
336/// implemented for `FunctionContext` (from `sp-wasm-interface`).
337///
338/// # Disable tracing
339/// By adding `no_tracing` to the list of options you can prevent the wasm-side interface from
340/// generating the default `sp-tracing`-calls. Note that this is rarely needed but only meant
341/// for the case when that would create a circular dependency. You usually _do not_ want to add
342/// this flag, as tracing doesn't cost you anything by default anyways (it is added as a no-op)
343/// but is super useful for debugging later.
344pub use sp_runtime_interface_proc_macro::runtime_interface;
345
346#[doc(hidden)]
347#[cfg(not(substrate_runtime))]
348pub use sp_externalities::{
349	set_and_run_with_externalities, with_externalities, ExtensionStore, Externalities,
350	ExternalitiesExt,
351};
352
353#[doc(hidden)]
354pub use codec;
355
356#[cfg(all(any(target_arch = "riscv32", target_arch = "riscv64"), substrate_runtime))]
357pub mod polkavm;
358
359#[cfg(not(substrate_runtime))]
360pub mod host;
361pub(crate) mod impls;
362pub mod pass_by;
363#[cfg(any(substrate_runtime, doc))]
364pub mod wasm;
365
366mod util;
367
368pub use util::{pack_ptr_and_len, unpack_ptr_and_len};
369
370/// Something that can be used by the runtime interface as type to communicate between the runtime
371/// and the host.
372///
373/// Every type that should be used in a runtime interface function signature needs to implement
374/// this trait.
375pub trait RIType: Sized {
376	/// The raw FFI type that is used to pass `Self` through the host <-> runtime boundary.
377	#[cfg(not(substrate_runtime))]
378	type FFIType: sp_wasm_interface::IntoValue
379		+ sp_wasm_interface::TryFromValue
380		+ sp_wasm_interface::WasmTy;
381
382	#[cfg(substrate_runtime)]
383	type FFIType;
384
385	/// The inner type without any serialization strategy wrapper.
386	type Inner;
387}
388
389/// A raw pointer that can be used in a runtime interface function signature.
390#[cfg(substrate_runtime)]
391pub type Pointer<T> = *mut T;
392
393/// A raw pointer that can be used in a runtime interface function signature.
394#[cfg(not(substrate_runtime))]
395pub type Pointer<T> = sp_wasm_interface::Pointer<T>;