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
// Copyright 2017-2020 Parity Technologies (UK) Ltd.
// This file is part of Substrate.

// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Substrate.  If not, see <http://www.gnu.org/licenses/>.

//! A crate that provides means of executing/dispatching calls into the runtime.
//!
//! There are a few responsibilities of this crate at the moment:
//!
//! - It provides an implementation of a common entrypoint for calling into the runtime, both
//! wasm and compiled.
//! - It defines the environment for the wasm execution, namely the host functions that are to be
//! provided into the wasm runtime module.
//! - It also provides the required infrastructure for executing the current wasm runtime (specified
//! by the current value of `:code` in the provided externalities), i.e. interfacing with
//! wasm engine used, instance cache.

#![warn(missing_docs)]
#![recursion_limit="128"]

#[macro_use]
mod native_executor;
mod wasm_runtime;
#[cfg(test)]
mod integration_tests;

pub use wasmi;
pub use native_executor::{with_externalities_safe, NativeExecutor, NativeExecutionDispatch};
pub use sp_version::{RuntimeVersion, NativeVersion};
pub use codec::Codec;
#[doc(hidden)]
pub use sp_core::traits::Externalities;
#[doc(hidden)]
pub use sp_wasm_interface;
pub use wasm_runtime::WasmExecutionMethod;

pub use sc_executor_common::{error, sandbox};

/// Call the given `function` in the given wasm `code`.
///
/// The signature of `function` needs to follow the default Substrate function signature.
///
/// - `call_data`: Will be given as input parameters to `function`
/// - `execution_method`: The execution method to use.
/// - `ext`: The externalities that should be set while executing the wasm function.
///          If `None` is given, no externalities will be set.
/// - `heap_pages`: The number of heap pages to allocate.
///
/// Returns the `Vec<u8>` that contains the return value of the function.
pub fn call_in_wasm<HF: sp_wasm_interface::HostFunctions>(
	function: &str,
	call_data: &[u8],
	execution_method: WasmExecutionMethod,
	ext: &mut dyn Externalities,
	code: &[u8],
	heap_pages: u64,
	allow_missing_func_imports: bool,
) -> error::Result<Vec<u8>> {
	call_in_wasm_with_host_functions(
		function,
		call_data,
		execution_method,
		ext,
		code,
		heap_pages,
		HF::host_functions(),
		allow_missing_func_imports,
	)
}

/// Non-generic version of [`call_in_wasm`] that takes the `host_functions` as parameter.
/// For more information please see [`call_in_wasm`].
pub fn call_in_wasm_with_host_functions(
	function: &str,
	call_data: &[u8],
	execution_method: WasmExecutionMethod,
	ext: &mut dyn Externalities,
	code: &[u8],
	heap_pages: u64,
	host_functions: Vec<&'static dyn sp_wasm_interface::Function>,
	allow_missing_func_imports: bool,
) -> error::Result<Vec<u8>> {
	let instance = wasm_runtime::create_wasm_runtime_with_code(
		execution_method,
		heap_pages,
		code,
		host_functions,
		allow_missing_func_imports,
	)?;

	// It is safe, as we delete the instance afterwards.
	let mut instance = std::panic::AssertUnwindSafe(instance);

	with_externalities_safe(ext, move || instance.call(function, call_data)).and_then(|r| r)
}

/// Provides runtime information.
pub trait RuntimeInfo {
	/// Native runtime information.
	fn native_version(&self) -> &NativeVersion;

	/// Extract RuntimeVersion of given :code block
	fn runtime_version<E: Externalities> (&self, ext: &mut E) -> error::Result<RuntimeVersion>;
}

#[cfg(test)]
mod tests {
	use super::*;
	use sc_runtime_test::WASM_BINARY;
	use sp_io::TestExternalities;

	#[test]
	fn call_in_interpreted_wasm_works() {
		let mut ext = TestExternalities::default();
		let mut ext = ext.ext();
		let res = call_in_wasm::<sp_io::SubstrateHostFunctions>(
			"test_empty_return",
			&[],
			WasmExecutionMethod::Interpreted,
			&mut ext,
			&WASM_BINARY,
			8,
			true,
		).unwrap();
		assert_eq!(res, vec![0u8; 0]);
	}
}