mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 12:17:58 +00:00
Wasm executor should provide stubs for unknown externs (wasmi) (#4550)
Related to #4456
This commit is contained in:
@@ -32,6 +32,49 @@ use crate::WasmExecutionMethod;
|
||||
|
||||
pub type TestExternalities = CoreTestExternalities<Blake2Hasher, u64>;
|
||||
|
||||
#[cfg(feature = "wasmtime")]
|
||||
mod wasmtime_missing_externals {
|
||||
use sp_wasm_interface::{Function, FunctionContext, HostFunctions, Result, Signature, Value};
|
||||
|
||||
pub struct WasmtimeHostFunctions;
|
||||
|
||||
impl HostFunctions for WasmtimeHostFunctions {
|
||||
fn host_functions() -> Vec<&'static dyn Function> {
|
||||
vec![MISSING_EXTERNAL_FUNCTION, YET_ANOTHER_MISSING_EXTERNAL_FUNCTION]
|
||||
}
|
||||
}
|
||||
|
||||
struct MissingExternalFunction(&'static str);
|
||||
|
||||
impl Function for MissingExternalFunction {
|
||||
fn name(&self) -> &str { self.0 }
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::new(vec![], None)
|
||||
}
|
||||
|
||||
fn execute(
|
||||
&self,
|
||||
_context: &mut dyn FunctionContext,
|
||||
_args: &mut dyn Iterator<Item = Value>,
|
||||
) -> Result<Option<Value>> {
|
||||
panic!("should not be called");
|
||||
}
|
||||
}
|
||||
|
||||
static MISSING_EXTERNAL_FUNCTION: &'static MissingExternalFunction =
|
||||
&MissingExternalFunction("missing_external");
|
||||
static YET_ANOTHER_MISSING_EXTERNAL_FUNCTION: &'static MissingExternalFunction =
|
||||
&MissingExternalFunction("yet_another_missing_external");
|
||||
}
|
||||
|
||||
#[cfg(feature = "wasmtime")]
|
||||
type HostFunctions =
|
||||
(wasmtime_missing_externals::WasmtimeHostFunctions, sp_io::SubstrateHostFunctions);
|
||||
|
||||
#[cfg(not(feature = "wasmtime"))]
|
||||
type HostFunctions = sp_io::SubstrateHostFunctions;
|
||||
|
||||
fn call_in_wasm<E: Externalities>(
|
||||
function: &str,
|
||||
call_data: &[u8],
|
||||
@@ -40,13 +83,14 @@ fn call_in_wasm<E: Externalities>(
|
||||
code: &[u8],
|
||||
heap_pages: u64,
|
||||
) -> crate::error::Result<Vec<u8>> {
|
||||
crate::call_in_wasm::<E, sp_io::SubstrateHostFunctions>(
|
||||
crate::call_in_wasm::<E, HostFunctions>(
|
||||
function,
|
||||
call_data,
|
||||
execution_method,
|
||||
ext,
|
||||
code,
|
||||
heap_pages,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -68,6 +112,44 @@ fn returning_should_work(wasm_method: WasmExecutionMethod) {
|
||||
assert_eq!(output, vec![0u8; 0]);
|
||||
}
|
||||
|
||||
#[test_case(WasmExecutionMethod::Interpreted)]
|
||||
#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))]
|
||||
#[should_panic(expected = "Function `missing_external` is only a stub. Calling a stub is not allowed.")]
|
||||
#[cfg(not(feature = "wasmtime"))]
|
||||
fn call_not_existing_function(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
let test_code = WASM_BINARY;
|
||||
|
||||
call_in_wasm(
|
||||
"test_calling_missing_external",
|
||||
&[],
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
&test_code[..],
|
||||
8,
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
#[test_case(WasmExecutionMethod::Interpreted)]
|
||||
#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))]
|
||||
#[should_panic(expected = "Function `yet_another_missing_external` is only a stub. Calling a stub is not allowed.")]
|
||||
#[cfg(not(feature = "wasmtime"))]
|
||||
fn call_yet_another_not_existing_function(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
let test_code = WASM_BINARY;
|
||||
|
||||
call_in_wasm(
|
||||
"test_calling_yet_another_missing_external",
|
||||
&[],
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
&test_code[..],
|
||||
8,
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
#[test_case(WasmExecutionMethod::Interpreted)]
|
||||
#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))]
|
||||
fn panicking_should_work(wasm_method: WasmExecutionMethod) {
|
||||
|
||||
@@ -67,12 +67,14 @@ pub fn call_in_wasm<E: Externalities, HF: sp_wasm_interface::HostFunctions>(
|
||||
ext: &mut E,
|
||||
code: &[u8],
|
||||
heap_pages: u64,
|
||||
allow_missing_imports: bool,
|
||||
) -> error::Result<Vec<u8>> {
|
||||
let mut instance = wasm_runtime::create_wasm_runtime_with_code(
|
||||
execution_method,
|
||||
heap_pages,
|
||||
code,
|
||||
HF::host_functions(),
|
||||
allow_missing_imports,
|
||||
)?;
|
||||
instance.call(ext, function, call_data)
|
||||
}
|
||||
@@ -103,6 +105,7 @@ mod tests {
|
||||
&mut ext,
|
||||
&WASM_BINARY,
|
||||
8,
|
||||
true,
|
||||
).unwrap();
|
||||
assert_eq!(res, vec![0u8; 0]);
|
||||
}
|
||||
|
||||
@@ -191,10 +191,11 @@ pub fn create_wasm_runtime_with_code(
|
||||
heap_pages: u64,
|
||||
code: &[u8],
|
||||
host_functions: Vec<&'static dyn Function>,
|
||||
allow_missing_imports: bool,
|
||||
) -> Result<Box<dyn WasmRuntime>, WasmError> {
|
||||
match wasm_method {
|
||||
WasmExecutionMethod::Interpreted =>
|
||||
sc_executor_wasmi::create_instance(code, heap_pages, host_functions)
|
||||
sc_executor_wasmi::create_instance(code, heap_pages, host_functions, allow_missing_imports)
|
||||
.map(|runtime| -> Box<dyn WasmRuntime> { Box::new(runtime) }),
|
||||
#[cfg(feature = "wasmtime")]
|
||||
WasmExecutionMethod::Compiled =>
|
||||
@@ -212,7 +213,7 @@ fn create_versioned_wasm_runtime<E: Externalities>(
|
||||
let code = ext
|
||||
.original_storage(well_known_keys::CODE)
|
||||
.ok_or(WasmError::CodeNotFound)?;
|
||||
let mut runtime = create_wasm_runtime_with_code(wasm_method, heap_pages, &code, host_functions)?;
|
||||
let mut runtime = create_wasm_runtime_with_code(wasm_method, heap_pages, &code, host_functions, false)?;
|
||||
|
||||
// Call to determine runtime version.
|
||||
let version_result = {
|
||||
|
||||
Reference in New Issue
Block a user