seal: Change prefix and module name from "ext_" to "seal_" for contract callable functions (#6798)

* seal: Change prefix "ext_" to "seal_" for contract callable functions

The word Ext is a overloaded term in the context of substrate. It usually
is a trait which abstracts away access to external resources usually in order
to mock them away for the purpose of tests. The contract module has its own
`Ext` trait in addition the the substrate `Ext` which makes things even more
confusing.

In order to differentiate the contract callable functions more clearly from
this `Ext` concept we rename them to use the "seal_" prefix instead.

This should change no behaviour at all. This is a pure renaming commit.

* seal: Rename import module from "env" to "seal0"

* seal: Fixup integration test

* seal: Add more tests for new import module names
This commit is contained in:
Alexander Theißen
2020-08-10 15:14:34 +02:00
committed by GitHub
parent f9f8262303
commit 04b185e3d4
29 changed files with 355 additions and 303 deletions
+81 -29
View File
@@ -28,6 +28,14 @@ use pwasm_utils::rules;
use sp_std::prelude::*;
use sp_runtime::traits::{SaturatedConversion};
/// Currently, all imported functions must be located inside this module. We might support
/// additional modules for versioning later.
pub const IMPORT_MODULE_FN: &str = "seal0";
/// Imported memory must be located inside this module. The reason for that is that current
/// compiler toolchains might not support specifying other modules than "env" for memory imports.
pub const IMPORT_MODULE_MEMORY: &str = "env";
struct ContractModule<'a> {
/// A deserialized module. The module is valid (this is Guaranteed by `new` method).
module: elements::Module,
@@ -146,8 +154,11 @@ impl<'a> ContractModule<'a> {
.with_grow_cost(self.schedule.grow_mem_cost.clone().saturated_into())
.with_forbidden_floats();
let contract_module = pwasm_utils::inject_gas_counter(self.module, &gas_rules)
.map_err(|_| "gas instrumentation failed")?;
let contract_module = pwasm_utils::inject_gas_counter(
self.module,
&gas_rules,
IMPORT_MODULE_FN
).map_err(|_| "gas instrumentation failed")?;
Ok(ContractModule {
module: contract_module,
schedule: self.schedule,
@@ -270,17 +281,19 @@ impl<'a> ContractModule<'a> {
let mut imported_mem_type = None;
for import in import_entries {
if import.module() != "env" {
// This import tries to import something from non-"env" module,
// but all imports are located in "env" at the moment.
return Err("module has imports from a non-'env' namespace");
}
let type_idx = match import.external() {
&External::Table(_) => return Err("Cannot import tables"),
&External::Global(_) => return Err("Cannot import globals"),
&External::Function(ref type_idx) => type_idx,
&External::Function(ref type_idx) => {
if import.module() != IMPORT_MODULE_FN {
return Err("Invalid module for imported function");
}
type_idx
},
&External::Memory(ref memory_type) => {
if import.module() != IMPORT_MODULE_MEMORY {
return Err("Invalid module for imported memory");
}
if import.field() != "memory" {
return Err("Memory import must have the field name 'memory'")
}
@@ -296,10 +309,10 @@ impl<'a> ContractModule<'a> {
.get(*type_idx as usize)
.ok_or_else(|| "validation: import entry points to a non-existent type")?;
// We disallow importing `ext_println` unless debug features are enabled,
// We disallow importing `seal_println` unless debug features are enabled,
// which should only be allowed on a dev chain
if !self.schedule.enable_println && import.field().as_bytes() == b"ext_println" {
return Err("module imports `ext_println` but debug features disabled");
if !self.schedule.enable_println && import.field().as_bytes() == b"seal_println" {
return Err("module imports `seal_println` but debug features disabled");
}
// We disallow importing `gas` function here since it is treated as implementation detail.
@@ -409,7 +422,7 @@ mod tests {
nop(_ctx, _unused: u64) => { unreachable!(); },
ext_println(_ctx, _ptr: u32, _len: u32) => { unreachable!(); },
seal_println(_ctx, _ptr: u32, _len: u32) => { unreachable!(); },
);
macro_rules! prepare_test {
@@ -548,7 +561,7 @@ mod tests {
prepare_test!(table_import,
r#"
(module
(import "env" "table" (table 1 anyfunc))
(import "seal0" "table" (table 1 anyfunc))
(func (export "call"))
(func (export "deploy"))
@@ -560,7 +573,7 @@ mod tests {
prepare_test!(global_import,
r#"
(module
(global $g (import "env" "global") i32)
(global $g (import "seal0" "global") i32)
(func (export "call"))
(func (export "deploy"))
)
@@ -618,7 +631,7 @@ mod tests {
prepare_test!(can_import_legit_function,
r#"
(module
(import "env" "nop" (func (param i64)))
(import "seal0" "nop" (func (param i64)))
(func (export "call"))
(func (export "deploy"))
@@ -632,7 +645,7 @@ mod tests {
prepare_test!(can_not_import_gas_function,
r#"
(module
(import "env" "gas" (func (param i32)))
(import "seal0" "gas" (func (param i32)))
(func (export "call"))
(func (export "deploy"))
@@ -641,24 +654,63 @@ mod tests {
Err("module imports a non-existent function")
);
// nothing can be imported from non-"env" module for now.
prepare_test!(non_env_import,
// memory is in "env" and not in "seal0"
prepare_test!(memory_not_in_seal0,
r#"
(module
(import "another_module" "memory" (memory 1 1))
(import "seal0" "memory" (memory 1 1))
(func (export "call"))
(func (export "deploy"))
)
"#,
Err("module has imports from a non-'env' namespace")
Err("Invalid module for imported memory")
);
// memory is in "env" and not in some arbitrary module
prepare_test!(memory_not_in_arbitrary_module,
r#"
(module
(import "any_module" "memory" (memory 1 1))
(func (export "call"))
(func (export "deploy"))
)
"#,
Err("Invalid module for imported memory")
);
// functions are in "env" and not in "seal0"
prepare_test!(function_not_in_env,
r#"
(module
(import "env" "nop" (func (param i64)))
(func (export "call"))
(func (export "deploy"))
)
"#,
Err("Invalid module for imported function")
);
// functions are in "seal0" and not in in some arbitrary module
prepare_test!(function_not_arbitrary_module,
r#"
(module
(import "any_module" "nop" (func (param i64)))
(func (export "call"))
(func (export "deploy"))
)
"#,
Err("Invalid module for imported function")
);
// wrong signature
prepare_test!(wrong_signature,
r#"
(module
(import "env" "gas" (func (param i64)))
(import "seal0" "gas" (func (param i64)))
(func (export "call"))
(func (export "deploy"))
@@ -670,7 +722,7 @@ mod tests {
prepare_test!(unknown_func_name,
r#"
(module
(import "env" "unknown_func" (func))
(import "seal0" "unknown_func" (func))
(func (export "call"))
(func (export "deploy"))
@@ -679,24 +731,24 @@ mod tests {
Err("module imports a non-existent function")
);
prepare_test!(ext_println_debug_disabled,
prepare_test!(seal_println_debug_disabled,
r#"
(module
(import "env" "ext_println" (func $ext_println (param i32 i32)))
(import "seal0" "seal_println" (func $seal_println (param i32 i32)))
(func (export "call"))
(func (export "deploy"))
)
"#,
Err("module imports `ext_println` but debug features disabled")
Err("module imports `seal_println` but debug features disabled")
);
#[test]
fn ext_println_debug_enabled() {
fn seal_println_debug_enabled() {
let wasm = wat::parse_str(
r#"
(module
(import "env" "ext_println" (func $ext_println (param i32 i32)))
(import "seal0" "seal_println" (func $seal_println (param i32 i32)))
(func (export "call"))
(func (export "deploy"))
@@ -745,7 +797,7 @@ mod tests {
prepare_test!(try_sneak_export_as_entrypoint,
r#"
(module
(import "env" "panic" (func))
(import "seal0" "panic" (func))
(func (export "deploy"))