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