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")]
21
use crate::host::*;
22
#[cfg(not(feature = "std"))]
23
use crate::wasm::*;
24
use 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")))]
31
use static_assertions::assert_eq_size;
32

            
33
#[cfg(feature = "std")]
34
use sp_wasm_interface::{FunctionContext, Result};
35

            
36
use codec::{Decode, Encode};
37

            
38
use core::{any::TypeId, mem};
39

            
40
use alloc::vec::Vec;
41

            
42
#[cfg(feature = "std")]
43
use 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")))]
47
assert_eq_size!(usize, u32);
48
#[cfg(all(not(feature = "std"), not(feature = "disable_target_static_assertions")))]
49
assert_eq_size!(*const u8, u32);
50

            
51
/// Implement the traits for the given primitive traits.
52
macro_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

            
99
impl_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
114
impl RIType for bool {
115
	type FFIType = u32;
116
}
117

            
118
#[cfg(not(feature = "std"))]
119
impl 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"))]
128
impl FromFFIValue for bool {
129
	fn from_ffi_value(arg: u32) -> bool {
130
		arg == 1
131
	}
132
}
133

            
134
#[cfg(feature = "std")]
135
impl 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")]
144
impl 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.
156
impl<T> RIType for Vec<T> {
157
	type FFIType = u64;
158
}
159

            
160
#[cfg(feature = "std")]
161
impl<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")]
177
impl<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"))]
186
impl<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"))]
195
impl<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.
220
impl<T> RIType for [T] {
221
	type FFIType = u64;
222
}
223

            
224
#[cfg(feature = "std")]
225
impl<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")]
243
impl 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"))]
266
impl<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.
284
impl<const N: usize> RIType for [u8; N] {
285
	type FFIType = u32;
286
}
287

            
288
#[cfg(not(feature = "std"))]
289
impl<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"))]
298
impl<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")]
310
impl<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")]
321
impl<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")]
330
impl<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

            
342
impl<T: codec::Codec, E: codec::Codec> PassBy for core::result::Result<T, E> {
343
	type PassBy = Codec<Self>;
344
}
345

            
346
impl<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]
352
impl PassBy for Tuple
353
where
354
	Self: codec::Codec,
355
{
356
	type PassBy = Codec<Self>;
357
}
358

            
359
/// Implement `PassBy` with `Inner` for the given fixed sized hash types.
360
macro_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

            
386
for_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`.
397
impl RIType for str {
398
	type FFIType = u64;
399
}
400

            
401
#[cfg(feature = "std")]
402
impl 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"))]
416
impl 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")]
426
impl<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"))]
432
impl<T> RIType for Pointer<T> {
433
	type FFIType = u32;
434
}
435

            
436
#[cfg(not(feature = "std"))]
437
impl<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"))]
446
impl<T> FromFFIValue for Pointer<T> {
447
	fn from_ffi_value(arg: u32) -> Self {
448
		arg as _
449
	}
450
}
451

            
452
#[cfg(feature = "std")]
453
impl<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")]
462
impl<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`
469
macro_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

            
516
for_u128_i128!(u128);
517
for_u128_i128!(i128);
518

            
519
impl PassBy for sp_wasm_interface::ValueType {
520
	type PassBy = Enum<sp_wasm_interface::ValueType>;
521
}
522

            
523
impl PassBy for sp_wasm_interface::Value {
524
	type PassBy = Codec<sp_wasm_interface::Value>;
525
}
526

            
527
impl PassBy for sp_storage::TrackedStorageKey {
528
	type PassBy = Codec<Self>;
529
}
530

            
531
impl PassBy for sp_storage::StateVersion {
532
	type PassBy = Enum<Self>;
533
}
534

            
535
impl PassBy for sp_externalities::MultiRemovalResults {
536
	type PassBy = Codec<Self>;
537
}