sp_runtime_interface/
impls.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//! Provides implementations for the runtime interface traits.
19
20#[cfg(feature = "std")]
21use crate::host::*;
22#[cfg(not(feature = "std"))]
23use crate::wasm::*;
24use crate::{
25	pass_by::{Codec, Enum, Inner, PassBy, PassByInner},
26	util::{pack_ptr_and_len, unpack_ptr_and_len},
27	Pointer, RIType,
28};
29
30#[cfg(all(not(feature = "std"), not(feature = "disable_target_static_assertions")))]
31use static_assertions::assert_eq_size;
32
33#[cfg(feature = "std")]
34use sp_wasm_interface::{FunctionContext, Result};
35
36use codec::{Decode, Encode};
37
38use core::{any::TypeId, mem};
39
40use alloc::vec::Vec;
41
42#[cfg(feature = "std")]
43use alloc::borrow::Cow;
44
45// Make sure that our assumptions for storing a pointer + its size in `u64` is valid.
46#[cfg(all(not(feature = "std"), not(feature = "disable_target_static_assertions")))]
47assert_eq_size!(usize, u32);
48#[cfg(all(not(feature = "std"), not(feature = "disable_target_static_assertions")))]
49assert_eq_size!(*const u8, u32);
50
51/// Implement the traits for the given primitive traits.
52macro_rules! impl_traits_for_primitives {
53	(
54		$(
55			$rty:ty, $fty:ty,
56		)*
57	) => {
58		$(
59			/// The type is passed directly.
60			impl RIType for $rty {
61				type FFIType = $fty;
62			}
63
64			#[cfg(not(feature = "std"))]
65			impl IntoFFIValue for $rty {
66				type Owned = ();
67
68				fn into_ffi_value(&self) -> WrappedFFIValue<$fty> {
69					(*self as $fty).into()
70				}
71			}
72
73			#[cfg(not(feature = "std"))]
74			impl FromFFIValue for $rty {
75				fn from_ffi_value(arg: $fty) -> $rty {
76					arg as $rty
77				}
78			}
79
80			#[cfg(feature = "std")]
81			impl FromFFIValue for $rty {
82				type SelfInstance = $rty;
83
84				fn from_ffi_value(_: &mut dyn FunctionContext, arg: $fty) -> Result<$rty> {
85					Ok(arg as $rty)
86				}
87			}
88
89			#[cfg(feature = "std")]
90			impl IntoFFIValue for $rty {
91				fn into_ffi_value(self, _: &mut dyn FunctionContext) -> Result<$fty> {
92					Ok(self as $fty)
93				}
94			}
95		)*
96	}
97}
98
99impl_traits_for_primitives! {
100	u8, u32,
101	u16, u32,
102	u32, u32,
103	u64, u64,
104	i8, i32,
105	i16, i32,
106	i32, i32,
107	i64, i64,
108}
109
110/// `bool` is passed as `u32`.
111///
112/// - `1`: true
113/// - `0`: false
114impl RIType for bool {
115	type FFIType = u32;
116}
117
118#[cfg(not(feature = "std"))]
119impl IntoFFIValue for bool {
120	type Owned = ();
121
122	fn into_ffi_value(&self) -> WrappedFFIValue<u32> {
123		if *self { 1 } else { 0 }.into()
124	}
125}
126
127#[cfg(not(feature = "std"))]
128impl FromFFIValue for bool {
129	fn from_ffi_value(arg: u32) -> bool {
130		arg == 1
131	}
132}
133
134#[cfg(feature = "std")]
135impl FromFFIValue for bool {
136	type SelfInstance = bool;
137
138	fn from_ffi_value(_: &mut dyn FunctionContext, arg: u32) -> Result<bool> {
139		Ok(arg == 1)
140	}
141}
142
143#[cfg(feature = "std")]
144impl IntoFFIValue for bool {
145	fn into_ffi_value(self, _: &mut dyn FunctionContext) -> Result<u32> {
146		Ok(if self { 1 } else { 0 })
147	}
148}
149
150/// The type is passed as `u64`.
151///
152/// The `u64` value is build by `length 32bit << 32 | pointer 32bit`
153///
154/// If `T == u8` the length and the pointer are taken directly from `Self`.
155/// Otherwise `Self` is encoded and the length and the pointer are taken from the encoded vector.
156impl<T> RIType for Vec<T> {
157	type FFIType = u64;
158}
159
160#[cfg(feature = "std")]
161impl<T: 'static + Encode> IntoFFIValue for Vec<T> {
162	fn into_ffi_value(self, context: &mut dyn FunctionContext) -> Result<u64> {
163		let vec: Cow<'_, [u8]> = if TypeId::of::<T>() == TypeId::of::<u8>() {
164			unsafe { Cow::Borrowed(mem::transmute(&self[..])) }
165		} else {
166			Cow::Owned(self.encode())
167		};
168
169		let ptr = context.allocate_memory(vec.as_ref().len() as u32)?;
170		context.write_memory(ptr, &vec)?;
171
172		Ok(pack_ptr_and_len(ptr.into(), vec.len() as u32))
173	}
174}
175
176#[cfg(feature = "std")]
177impl<T: 'static + Decode> FromFFIValue for Vec<T> {
178	type SelfInstance = Vec<T>;
179
180	fn from_ffi_value(context: &mut dyn FunctionContext, arg: u64) -> Result<Vec<T>> {
181		<[T] as FromFFIValue>::from_ffi_value(context, arg)
182	}
183}
184
185#[cfg(not(feature = "std"))]
186impl<T: 'static + Encode> IntoFFIValue for Vec<T> {
187	type Owned = Vec<u8>;
188
189	fn into_ffi_value(&self) -> WrappedFFIValue<u64, Vec<u8>> {
190		self[..].into_ffi_value()
191	}
192}
193
194#[cfg(not(feature = "std"))]
195impl<T: 'static + Decode> FromFFIValue for Vec<T> {
196	fn from_ffi_value(arg: u64) -> Vec<T> {
197		let (ptr, len) = unpack_ptr_and_len(arg);
198		let len = len as usize;
199
200		if len == 0 {
201			return Vec::new()
202		}
203
204		let data = unsafe { Vec::from_raw_parts(ptr as *mut u8, len, len) };
205
206		if TypeId::of::<T>() == TypeId::of::<u8>() {
207			unsafe { mem::transmute(data) }
208		} else {
209			Self::decode(&mut &data[..]).expect("Host to wasm values are encoded correctly; qed")
210		}
211	}
212}
213
214/// The type is passed as `u64`.
215///
216/// The `u64` value is build by `length 32bit << 32 | pointer 32bit`
217///
218/// If `T == u8` the length and the pointer are taken directly from `Self`.
219/// Otherwise `Self` is encoded and the length and the pointer are taken from the encoded vector.
220impl<T> RIType for [T] {
221	type FFIType = u64;
222}
223
224#[cfg(feature = "std")]
225impl<T: 'static + Decode> FromFFIValue for [T] {
226	type SelfInstance = Vec<T>;
227
228	fn from_ffi_value(context: &mut dyn FunctionContext, arg: u64) -> Result<Vec<T>> {
229		let (ptr, len) = unpack_ptr_and_len(arg);
230
231		let vec = context.read_memory(Pointer::new(ptr), len)?;
232
233		if TypeId::of::<T>() == TypeId::of::<u8>() {
234			Ok(unsafe { mem::transmute(vec) })
235		} else {
236			Ok(Vec::<T>::decode(&mut &vec[..])
237				.expect("Wasm to host values are encoded correctly; qed"))
238		}
239	}
240}
241
242#[cfg(feature = "std")]
243impl IntoPreallocatedFFIValue for [u8] {
244	type SelfInstance = Vec<u8>;
245
246	fn into_preallocated_ffi_value(
247		self_instance: Self::SelfInstance,
248		context: &mut dyn FunctionContext,
249		allocated: u64,
250	) -> Result<()> {
251		let (ptr, len) = unpack_ptr_and_len(allocated);
252
253		if (len as usize) < self_instance.len() {
254			Err(format!(
255				"Preallocated buffer is not big enough (given {} vs needed {})!",
256				len,
257				self_instance.len()
258			))
259		} else {
260			context.write_memory(Pointer::new(ptr), &self_instance)
261		}
262	}
263}
264
265#[cfg(not(feature = "std"))]
266impl<T: 'static + Encode> IntoFFIValue for [T] {
267	type Owned = Vec<u8>;
268
269	fn into_ffi_value(&self) -> WrappedFFIValue<u64, Vec<u8>> {
270		if TypeId::of::<T>() == TypeId::of::<u8>() {
271			let slice = unsafe { mem::transmute::<&[T], &[u8]>(self) };
272			pack_ptr_and_len(slice.as_ptr() as u32, slice.len() as u32).into()
273		} else {
274			let data = self.encode();
275			let ffi_value = pack_ptr_and_len(data.as_ptr() as u32, data.len() as u32);
276			(ffi_value, data).into()
277		}
278	}
279}
280
281/// The type is passed as `u32`.
282///
283/// The `u32` is the pointer to the array.
284impl<const N: usize> RIType for [u8; N] {
285	type FFIType = u32;
286}
287
288#[cfg(not(feature = "std"))]
289impl<const N: usize> IntoFFIValue for [u8; N] {
290	type Owned = ();
291
292	fn into_ffi_value(&self) -> WrappedFFIValue<u32> {
293		(self.as_ptr() as u32).into()
294	}
295}
296
297#[cfg(not(feature = "std"))]
298impl<const N: usize> FromFFIValue for [u8; N] {
299	fn from_ffi_value(arg: u32) -> [u8; N] {
300		let mut res = [0u8; N];
301		let data = unsafe { Vec::from_raw_parts(arg as *mut u8, N, N) };
302
303		res.copy_from_slice(&data);
304
305		res
306	}
307}
308
309#[cfg(feature = "std")]
310impl<const N: usize> FromFFIValue for [u8; N] {
311	type SelfInstance = [u8; N];
312
313	fn from_ffi_value(context: &mut dyn FunctionContext, arg: u32) -> Result<[u8; N]> {
314		let mut res = [0u8; N];
315		context.read_memory_into(Pointer::new(arg), &mut res)?;
316		Ok(res)
317	}
318}
319
320#[cfg(feature = "std")]
321impl<const N: usize> IntoFFIValue for [u8; N] {
322	fn into_ffi_value(self, context: &mut dyn FunctionContext) -> Result<u32> {
323		let addr = context.allocate_memory(N as u32)?;
324		context.write_memory(addr, &self)?;
325		Ok(addr.into())
326	}
327}
328
329#[cfg(feature = "std")]
330impl<const N: usize> IntoPreallocatedFFIValue for [u8; N] {
331	type SelfInstance = [u8; N];
332
333	fn into_preallocated_ffi_value(
334		self_instance: Self::SelfInstance,
335		context: &mut dyn FunctionContext,
336		allocated: u32,
337	) -> Result<()> {
338		context.write_memory(Pointer::new(allocated), &self_instance)
339	}
340}
341
342impl<T: codec::Codec, E: codec::Codec> PassBy for core::result::Result<T, E> {
343	type PassBy = Codec<Self>;
344}
345
346impl<T: codec::Codec> PassBy for Option<T> {
347	type PassBy = Codec<Self>;
348}
349
350#[impl_trait_for_tuples::impl_for_tuples(30)]
351#[tuple_types_no_default_trait_bound]
352impl PassBy for Tuple
353where
354	Self: codec::Codec,
355{
356	type PassBy = Codec<Self>;
357}
358
359/// Implement `PassBy` with `Inner` for the given fixed sized hash types.
360macro_rules! for_primitive_types {
361	{ $( $hash:ident $n:expr ),* $(,)? } => {
362		$(
363			impl PassBy for primitive_types::$hash {
364				type PassBy = Inner<Self, [u8; $n]>;
365			}
366
367			impl PassByInner for primitive_types::$hash {
368				type Inner = [u8; $n];
369
370				fn inner(&self) -> &Self::Inner {
371					&self.0
372				}
373
374				fn into_inner(self) -> Self::Inner {
375					self.0
376				}
377
378				fn from_inner(inner: Self::Inner) -> Self {
379					Self(inner)
380				}
381			}
382		)*
383	}
384}
385
386for_primitive_types! {
387	H160 20,
388	H256 32,
389	H512 64,
390}
391
392/// The type is passed as `u64`.
393///
394/// The `u64` value is build by `length 32bit << 32 | pointer 32bit`
395///
396/// The length and the pointer are taken directly from `Self`.
397impl RIType for str {
398	type FFIType = u64;
399}
400
401#[cfg(feature = "std")]
402impl FromFFIValue for str {
403	type SelfInstance = String;
404
405	fn from_ffi_value(context: &mut dyn FunctionContext, arg: u64) -> Result<String> {
406		let (ptr, len) = unpack_ptr_and_len(arg);
407
408		let vec = context.read_memory(Pointer::new(ptr), len)?;
409
410		// The data is valid utf8, as it is stored as `&str` in wasm.
411		String::from_utf8(vec).map_err(|_| "Invalid utf8 data provided".into())
412	}
413}
414
415#[cfg(not(feature = "std"))]
416impl IntoFFIValue for str {
417	type Owned = ();
418
419	fn into_ffi_value(&self) -> WrappedFFIValue<u64, ()> {
420		let bytes = self.as_bytes();
421		pack_ptr_and_len(bytes.as_ptr() as u32, bytes.len() as u32).into()
422	}
423}
424
425#[cfg(feature = "std")]
426impl<T: sp_wasm_interface::PointerType> RIType for Pointer<T> {
427	type FFIType = u32;
428}
429
430/// The type is passed as `u32`.
431#[cfg(not(feature = "std"))]
432impl<T> RIType for Pointer<T> {
433	type FFIType = u32;
434}
435
436#[cfg(not(feature = "std"))]
437impl<T> IntoFFIValue for Pointer<T> {
438	type Owned = ();
439
440	fn into_ffi_value(&self) -> WrappedFFIValue<u32> {
441		(*self as u32).into()
442	}
443}
444
445#[cfg(not(feature = "std"))]
446impl<T> FromFFIValue for Pointer<T> {
447	fn from_ffi_value(arg: u32) -> Self {
448		arg as _
449	}
450}
451
452#[cfg(feature = "std")]
453impl<T: sp_wasm_interface::PointerType> FromFFIValue for Pointer<T> {
454	type SelfInstance = Self;
455
456	fn from_ffi_value(_: &mut dyn FunctionContext, arg: u32) -> Result<Self> {
457		Ok(Pointer::new(arg))
458	}
459}
460
461#[cfg(feature = "std")]
462impl<T: sp_wasm_interface::PointerType> IntoFFIValue for Pointer<T> {
463	fn into_ffi_value(self, _: &mut dyn FunctionContext) -> Result<u32> {
464		Ok(self.into())
465	}
466}
467
468/// Implement the traits for `u128`/`i128`
469macro_rules! for_u128_i128 {
470	($type:ty) => {
471		/// `u128`/`i128` is passed as `u32`.
472		///
473		/// The `u32` is a pointer to an `[u8; 16]` array.
474		impl RIType for $type {
475			type FFIType = u32;
476		}
477
478		#[cfg(not(feature = "std"))]
479		impl IntoFFIValue for $type {
480			type Owned = ();
481
482			fn into_ffi_value(&self) -> WrappedFFIValue<u32> {
483				unsafe { (mem::transmute::<&Self, *const u8>(self) as u32).into() }
484			}
485		}
486
487		#[cfg(not(feature = "std"))]
488		impl FromFFIValue for $type {
489			fn from_ffi_value(arg: u32) -> $type {
490				<$type>::from_le_bytes(<[u8; mem::size_of::<$type>()]>::from_ffi_value(arg))
491			}
492		}
493
494		#[cfg(feature = "std")]
495		impl FromFFIValue for $type {
496			type SelfInstance = $type;
497
498			fn from_ffi_value(context: &mut dyn FunctionContext, arg: u32) -> Result<$type> {
499				let mut res = [0u8; mem::size_of::<$type>()];
500				context.read_memory_into(Pointer::new(arg), &mut res)?;
501				Ok(<$type>::from_le_bytes(res))
502			}
503		}
504
505		#[cfg(feature = "std")]
506		impl IntoFFIValue for $type {
507			fn into_ffi_value(self, context: &mut dyn FunctionContext) -> Result<u32> {
508				let addr = context.allocate_memory(mem::size_of::<$type>() as u32)?;
509				context.write_memory(addr, &self.to_le_bytes())?;
510				Ok(addr.into())
511			}
512		}
513	};
514}
515
516for_u128_i128!(u128);
517for_u128_i128!(i128);
518
519impl PassBy for sp_wasm_interface::ValueType {
520	type PassBy = Enum<sp_wasm_interface::ValueType>;
521}
522
523impl PassBy for sp_wasm_interface::Value {
524	type PassBy = Codec<sp_wasm_interface::Value>;
525}
526
527impl PassBy for sp_storage::TrackedStorageKey {
528	type PassBy = Codec<Self>;
529}
530
531impl PassBy for sp_storage::StateVersion {
532	type PassBy = Enum<Self>;
533}
534
535impl PassBy for sp_externalities::MultiRemovalResults {
536	type PassBy = Codec<Self>;
537}