referrerpolicy=no-referrer-when-downgrade
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Substrate runtime interface
//!
//! This crate provides types, traits and macros around runtime interfaces. A runtime interface is
//! a fixed interface between a Substrate runtime and a Substrate node. For a native runtime the
//! interface maps to a direct function call of the implementation. For a wasm runtime the interface
//! maps to an external function call. These external functions are exported by the wasm executor
//! and they map to the same implementation as the native calls.
//!
//! # Using a type in a runtime interface
//!
//! Any type that should be used in a runtime interface as argument or return value needs to
//! implement [`RIType`]. The associated type
//! [`FFIType`](./trait.RIType.html#associatedtype.FFIType) is the type that is used in the FFI
//! function to represent the actual type. For example `[T]` is represented by an `u64`. The slice
//! pointer and the length will be mapped to an `u64` value. For more information see this
//! [table](#ffi-type-and-conversion). The FFI function definition is used when calling from the
//! wasm runtime into the node.
//!
//! Traits are used to convert from a type to the corresponding
//! [`RIType::FFIType`](./trait.RIType.html#associatedtype.FFIType).
//! Depending on where and how a type should be used in a function signature, a combination of the
//! following traits need to be implemented:
//! <!-- markdown-link-check-enable -->
//! 1. Pass as function argument: [`wasm::IntoFFIValue`] and [`host::FromFFIValue`]
//! 2. As function return value: [`wasm::FromFFIValue`] and [`host::IntoFFIValue`]
//! 3. Pass as mutable function argument: [`host::IntoPreallocatedFFIValue`]
//!
//! The traits are implemented for most of the common types like `[T]`, `Vec<T>`, arrays and
//! primitive types.
//!
//! For custom types, we provide the [`PassBy`](./pass_by#PassBy) trait and strategies that define
//! how a type is passed between the wasm runtime and the node. Each strategy also provides a derive
//! macro to simplify the implementation.
//!
//! # Performance
//!
//! To not waste any more performance when calling into the node, not all types are SCALE encoded
//! when being passed as arguments between the wasm runtime and the node. For most types that
//! are raw bytes like `Vec<u8>`, `[u8]` or `[u8; N]` we pass them directly, without SCALE encoding
//! them in front of. The implementation of [`RIType`] each type provides more information on how
//! the data is passed.
//!
//! # Declaring a runtime interface
//!
//! Declaring a runtime interface is similar to declaring a trait in Rust:
//!
//! ```
//! #[sp_runtime_interface::runtime_interface]
//! trait RuntimeInterface {
//!     fn some_function(value: &[u8]) -> bool {
//!         value.iter().all(|v| *v > 125)
//!     }
//! }
//! ```
//!
//! For more information on declaring a runtime interface, see
//! [`#[runtime_interface]`](./attr.runtime_interface.html).
//!
//! # FFI type and conversion
//!
//! The following table documents how values of types are passed between the wasm and
//! the host side and how they are converted into the corresponding type.
//!
//! | Type | FFI type | Conversion |
//! |----|----|----|
//! | `u8` | `u32` | zero-extended to 32-bits |
//! | `u16` | `u32` | zero-extended to 32-bits |
//! | `u32` | `u32` | `Identity` |
//! | `u64` | `u64` | `Identity` |
//! | `i128` | `u32` | `v.as_ptr()` (pointer to a 16 byte array) |
//! | `i8` | `i32` | sign-extended to 32-bits |
//! | `i16` | `i32` | sign-extended to 32-bits |
//! | `i32` | `i32` | `Identity` |
//! | `i64` | `i64` | `Identity` |
//! | `u128` | `u32` | `v.as_ptr()` (pointer to a 16 byte array) |
//! | `bool` | `u32` | `if v { 1 } else { 0 }` |
//! | `&str` | `u64` | <code>v.len() 32bit << 32 &#124; v.as_ptr() 32bit</code> |
//! | `&[u8]` | `u64` | <code>v.len() 32bit << 32 &#124; v.as_ptr() 32bit</code> |
//! | `Vec<u8>` | `u64` | <code>v.len() 32bit << 32 &#124; v.as_ptr() 32bit</code> |
//! | `Vec<T> where T: Encode` | `u64` | `let e = v.encode();`<br><br><code>e.len() 32bit << 32 &#124; e.as_ptr() 32bit</code> |
//! | `&[T] where T: Encode` | `u64` | `let e = v.encode();`<br><br><code>e.len() 32bit << 32 &#124; e.as_ptr() 32bit</code> |
//! | `[u8; N]` | `u32` | `v.as_ptr()` |
//! | `*const T` | `u32` | `Identity` |
//! | `Option<T>` | `u64` | `let e = v.encode();`<br><br><code>e.len() 32bit << 32 &#124; e.as_ptr() 32bit</code> |
//! | [`T where T: PassBy<PassBy=Inner>`](./pass_by#Inner) | Depends on inner | Depends on inner |
//! | [`T where T: PassBy<PassBy=Codec>`](./pass_by#Codec)|`u64`|<code>v.len() 32bit << 32 &#124;v.as_ptr() 32bit</code>|
//!
//! `Identity` means that the value is converted directly into the corresponding FFI type.

#![cfg_attr(not(feature = "std"), no_std)]

extern crate self as sp_runtime_interface;

extern crate alloc;

#[doc(hidden)]
#[cfg(feature = "std")]
pub use sp_wasm_interface;

#[doc(hidden)]
pub use sp_tracing;

#[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(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()
///     }
///     /// Call function, but different version.
///     ///
///     /// For new runtimes, only function with latest version is reachable.
///     /// But old version (above) is still accessible for old runtimes.
///     /// Default version is 1.
///     #[version(2)]
///     fn call(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.
///         [17].to_vec()
///     }
///
///     /// Call function, different version and only being registered.
///     ///
///     /// This `register_only` version is only being registered, aka exposed to the runtime,
///     /// but the runtime will still use the version 2 of this function. This is useful for when
///     /// new host functions should be introduced. Adding new host functions requires that all
///     /// nodes have the host functions available, because otherwise they fail at instantiation
///     /// of the runtime. With `register_only` the function will not be used when compiling the
///     /// runtime, but it will already be there for a future version of the runtime that will
///     /// switch to using these host function.
///     #[version(3, register_only)]
///     fn call(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.
///         [18].to_vec()
///     }
///
///     /// 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]),
///         }
///     }
///
///     /// A function can be gated behind a configuration (`cfg`) attribute.
///     /// To prevent ambiguity and confusion about what will be the final exposed host
///     /// functions list, conditionally compiled functions can't be versioned.
///     /// That is, conditionally compiled functions with `version`s greater than 1
///     /// are not allowed.
///     #[cfg(feature = "experimental-function")]
///     fn gated_call(data: &[u8]) -> Vec<u8> {
///         [42].to_vec()
///     }
/// }
/// ```
///
/// 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_version_1(data: &[u8]) -> Vec<u8>;
///         fn call_version_2(data: &[u8]) -> Vec<u8>;
///         fn call_version_3(data: &[u8]) -> Vec<u8>;
///         fn set_or_clear_version_1(&mut self, optional: Option<Vec<u8>>);
///         #[cfg(feature = "experimental-function")]
///         fn gated_call_version_1(data: &[u8]) -> Vec<u8>;
///     }
///
///     impl Interface for &mut dyn sp_externalities::Externalities {
///         fn call_version_1(data: &[u8]) -> Vec<u8> { Vec::new() }
///         fn call_version_2(data: &[u8]) -> Vec<u8> { [17].to_vec() }
///         fn call_version_3(data: &[u8]) -> Vec<u8> { [18].to_vec() }
///         fn set_or_clear_version_1(&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]),
///             }
///         }
///         #[cfg(feature = "experimental-function")]
///         fn gated_call_version_1(data: &[u8]) -> Vec<u8> { [42].to_vec() }
///     }
///
///     pub fn call(data: &[u8]) -> Vec<u8> {
///         // only latest version is exposed
///         call_version_2(data)
///     }
///
///     fn call_version_1(data: &[u8]) -> Vec<u8> {
///         <&mut dyn sp_externalities::Externalities as Interface>::call_version_1(data)
///     }
///
///     fn call_version_2(data: &[u8]) -> Vec<u8> {
///         <&mut dyn sp_externalities::Externalities as Interface>::call_version_2(data)
///     }
///
///     fn call_version_3(data: &[u8]) -> Vec<u8> {
///         <&mut dyn sp_externalities::Externalities as Interface>::call_version_3(data)
///     }
///
///     pub fn set_or_clear(optional: Option<Vec<u8>>) {
///         set_or_clear_version_1(optional)
///     }
///
///     fn set_or_clear_version_1(optional: Option<Vec<u8>>) {
///         sp_externalities::with_externalities(|mut ext| Interface::set_or_clear_version_1(&mut ext, optional))
///             .expect("`set_or_clear` called outside of an Externalities-provided environment.")
///     }
///
///     #[cfg(feature = "experimental-function")]
///     pub fn gated_call(data: &[u8]) -> Vec<u8> {
///         gated_call_version_1(data)
///     }
///
///     #[cfg(feature = "experimental-function")]
///     fn gated_call_version_1(data: &[u8]) -> Vec<u8> {
///         <&mut dyn sp_externalities::Externalities as Interface>::gated_call_version_1(data)
///     }
///
///     /// 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 {
///         /// Every function is exported by the native code as `ext_FUNCTION_NAME_version_VERSION`.
///         ///
///         /// The type for each argument of the exported function depends on
///         /// `<ARGUMENT_TYPE as RIType>::FFIType`.
///         ///
///         /// `key` holds the pointer and the length to the `data` slice.
///         pub fn call(data: &[u8]) -> Vec<u8> {
///             extern "C" { pub fn ext_call_version_2(key: u64); }
///             // Should call into external `ext_call_version_2(<[u8] as IntoFFIValue>::into_ffi_value(key))`
///             // But this is too much to replicate in a doc test so here we just return a dummy vector.
///             // Note that we jump into the latest version not marked as `register_only` (i.e. version 2).
///             Vec::new()
///         }
///
///         /// `key` holds the pointer and the length of the `option` value.
///         pub fn set_or_clear(option: Option<Vec<u8>>) {
///             extern "C" { pub fn ext_set_or_clear_version_1(key: u64); }
///             // Same as above
///         }
///
///         /// `key` holds the pointer and the length to the `data` slice.
///         #[cfg(feature = "experimental-function")]
///         pub fn gated_call(data: &[u8]) -> Vec<u8> {
///             extern "C" { pub fn ext_gated_call_version_1(key: u64); }
///             /// Same as above
///             Vec::new()
///         }
///     }
///
///     /// The type is actually `ExchangeableFunction` (from `sp-runtime-interface`) and
///     /// by default this is initialized to jump into the corresponding function in
///     /// `extern_host_functions_impls`.
///     ///
///     /// This can be used to replace the implementation of the `call` function.
///     /// Instead of calling into the host, the callee will automatically call the other
///     /// implementation.
///     ///
///     /// To replace the implementation:
///     ///
///     /// `host_call.replace_implementation(some_other_impl)`
///     pub static host_call: () = ();
///     pub static host_set_or_clear: () = ();
///     #[cfg(feature = "experimental-feature")]
///     pub static gated_call: () = ();
///
///     pub fn call(data: &[u8]) -> Vec<u8> {
///         // This is the actual call: `host_call.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
///     }
///
///     #[cfg(feature = "experimental-feature")]
///     pub fn gated_call(data: &[u8]) -> Vec<u8> {
///         // Same as above
///         Vec::new()
///     }
/// }
/// ```
///
/// # 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 `FunctionContext` (from `sp-wasm-interface`).
///
/// # Disable tracing
/// By adding `no_tracing` to the list of options you can prevent the wasm-side interface from
/// generating the default `sp-tracing`-calls. Note that this is rarely needed but only meant
/// for the case when that would create a circular dependency. You usually _do not_ want to add
/// this flag, as tracing doesn't cost you anything by default anyways (it is added as a no-op)
/// but is super useful for debugging later.
pub use sp_runtime_interface_proc_macro::runtime_interface;

#[doc(hidden)]
#[cfg(feature = "std")]
pub use sp_externalities::{
	set_and_run_with_externalities, with_externalities, ExtensionStore, Externalities,
	ExternalitiesExt,
};

#[doc(hidden)]
pub use codec;

#[cfg(all(any(target_arch = "riscv32", target_arch = "riscv64"), substrate_runtime))]
pub mod polkavm;

#[cfg(feature = "std")]
pub mod host;
pub(crate) mod impls;
pub mod pass_by;
#[cfg(any(not(feature = "std"), doc))]
pub mod wasm;

mod util;

pub use util::{pack_ptr_and_len, unpack_ptr_and_len};

/// Something that can be used by the runtime interface as type to communicate between wasm and the
/// host.
///
/// Every type that should be used in a runtime interface function signature needs to implement
/// this trait.
pub trait RIType {
	/// The ffi type that is used to represent `Self`.
	#[cfg(feature = "std")]
	type FFIType: sp_wasm_interface::IntoValue
		+ sp_wasm_interface::TryFromValue
		+ sp_wasm_interface::WasmTy;
	#[cfg(not(feature = "std"))]
	type FFIType;
}

/// A pointer that can be used in a runtime interface function signature.
#[cfg(not(feature = "std"))]
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>;