contracts: Upgrade to wasmi 0.28 (#13312)

* Upgrade to wasmi 0.28

* ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts

* Update stale comment

* Renamed variants of `Determinism`

* Compile fix

---------

Co-authored-by: command-bot <>
This commit is contained in:
Alexander Theißen
2023-03-21 00:09:22 +01:00
committed by GitHub
parent d5650ba07b
commit 82cb69922f
15 changed files with 1338 additions and 1393 deletions
+9 -13
View File
@@ -127,7 +127,7 @@ pub enum Determinism {
/// allowed.
///
/// Dispatchables always use this mode in order to make on-chain execution deterministic.
Deterministic,
Enforced,
/// Allow calling or uploading an indeterministic code.
///
/// This is only possible when calling into `pallet-contracts` directly via
@@ -136,7 +136,7 @@ pub enum Determinism {
/// # Note
///
/// **Never** use this mode for on-chain execution.
AllowIndeterminism,
Relaxed,
}
impl ExportedFunction {
@@ -225,7 +225,7 @@ impl<T: Config> PrefabWasmModule<T> {
let engine = Engine::new(&config);
let module = Module::new(&engine, code)?;
let mut store = Store::new(&engine, host_state);
let mut linker = Linker::new();
let mut linker = Linker::new(&engine);
E::define(
&mut store,
&mut linker,
@@ -329,7 +329,7 @@ impl<T: Config> Executable<T> for PrefabWasmModule<T> {
log::debug!(target: "runtime::contracts", "failed to instantiate code: {}", msg);
Error::<T>::CodeRejected
})?;
store.state_mut().set_memory(memory);
store.data_mut().set_memory(memory);
let exported_func = instance
.get_export(&store, function.identifier())
@@ -346,7 +346,7 @@ impl<T: Config> Executable<T> for PrefabWasmModule<T> {
let result = exported_func.call(&mut store, &[], &mut []);
store.into_state().to_execution_result(result)
store.into_data().to_execution_result(result)
}
fn code_hash(&self) -> &CodeHash<T> {
@@ -358,7 +358,7 @@ impl<T: Config> Executable<T> for PrefabWasmModule<T> {
}
fn is_deterministic(&self) -> bool {
matches!(self.determinism, Determinism::Deterministic)
matches!(self.determinism, Determinism::Enforced)
}
}
@@ -653,7 +653,7 @@ mod tests {
wasm,
&schedule,
ALICE,
Determinism::Deterministic,
Determinism::Enforced,
TryInstantiate::Instantiate,
)
.map_err(|err| err.0)?
@@ -3058,12 +3058,8 @@ mod tests {
let schedule = crate::Schedule::<Test>::default();
#[cfg(not(feature = "runtime-benchmarks"))]
assert_err!(execute(CODE_RANDOM, vec![], MockExt::default()), <Error<Test>>::CodeRejected);
self::prepare::reinstrument::<runtime::Env, Test>(
&wasm,
&schedule,
Determinism::Deterministic,
)
.unwrap();
self::prepare::reinstrument::<runtime::Env, Test>(&wasm, &schedule, Determinism::Enforced)
.unwrap();
}
/// This test check that an unstable interface cannot be deployed. In case of runtime
+10 -60
View File
@@ -155,52 +155,6 @@ impl<'a, T: Config> ContractModule<'a, T> {
Ok(())
}
/// Ensures that no floating point types are in use.
fn ensure_no_floating_types(&self) -> Result<(), &'static str> {
if let Some(global_section) = self.module.global_section() {
for global in global_section.entries() {
match global.global_type().content_type() {
ValueType::F32 | ValueType::F64 =>
return Err("use of floating point type in globals is forbidden"),
_ => {},
}
}
}
if let Some(code_section) = self.module.code_section() {
for func_body in code_section.bodies() {
for local in func_body.locals() {
match local.value_type() {
ValueType::F32 | ValueType::F64 =>
return Err("use of floating point type in locals is forbidden"),
_ => {},
}
}
}
}
if let Some(type_section) = self.module.type_section() {
for wasm_type in type_section.types() {
match wasm_type {
Type::Function(func_type) => {
let return_type = func_type.results().get(0);
for value_type in func_type.params().iter().chain(return_type) {
match value_type {
ValueType::F32 | ValueType::F64 =>
return Err(
"use of floating point type in function types is forbidden",
),
_ => {},
}
}
},
}
}
}
Ok(())
}
/// Ensure that no function exists that has more parameters than allowed.
fn ensure_parameter_limit(&self, limit: u32) -> Result<(), &'static str> {
let type_section = if let Some(type_section) = self.module.type_section() {
@@ -411,10 +365,9 @@ where
memory64: false,
extended_const: false,
component_model: false,
// This is not our only defense: We check for float types later in the preparation
// process. Additionally, all instructions explicitly need to have weights assigned
// This is not our only defense: All instructions explicitly need to have weights assigned
// or the deployment will fail. We have none assigned for float instructions.
deterministic_only: matches!(determinism, Determinism::Deterministic),
floats: matches!(determinism, Determinism::Relaxed),
mutable_global: false,
saturating_float_to_int: false,
sign_extension: false,
@@ -422,6 +375,7 @@ where
multi_value: false,
reference_types: false,
simd: false,
memory_control: false,
})
.validate_all(original_code)
.map_err(|err| {
@@ -439,10 +393,6 @@ where
contract_module.ensure_parameter_limit(schedule.limits.parameters)?;
contract_module.ensure_br_table_size_limit(schedule.limits.br_table_size)?;
if matches!(determinism, Determinism::Deterministic) {
contract_module.ensure_no_floating_types()?;
}
// We disallow importing `gas` function here since it is treated as implementation detail.
let disallowed_imports = [b"gas".as_ref()];
let memory_limits =
@@ -608,7 +558,7 @@ pub mod benchmarking {
deposit: Default::default(),
refcount: 0,
}),
determinism: Determinism::Deterministic,
determinism: Determinism::Enforced,
})
}
}
@@ -682,7 +632,7 @@ mod tests {
wasm,
&schedule,
ALICE,
Determinism::Deterministic,
Determinism::Enforced,
TryInstantiate::Instantiate,
);
assert_matches::assert_matches!(r.map_err(|(_, msg)| msg), $($expected)*);
@@ -704,7 +654,7 @@ mod tests {
)
(func (export "deploy"))
)"#,
Err("gas instrumentation failed")
Err("validation of new code failed")
);
mod functions {
@@ -1214,7 +1164,7 @@ mod tests {
(func (export "deploy"))
)
"#,
Err("use of floating point type in globals is forbidden")
Err("validation of new code failed")
);
prepare_test!(
@@ -1226,7 +1176,7 @@ mod tests {
(func (export "deploy"))
)
"#,
Err("use of floating point type in locals is forbidden")
Err("validation of new code failed")
);
prepare_test!(
@@ -1238,7 +1188,7 @@ mod tests {
(func (export "deploy"))
)
"#,
Err("use of floating point type in function types is forbidden")
Err("validation of new code failed")
);
prepare_test!(
@@ -1250,7 +1200,7 @@ mod tests {
(func (export "deploy"))
)
"#,
Err("use of floating point type in function types is forbidden")
Err("validation of new code failed")
);
}
}
@@ -482,11 +482,7 @@ impl<'a, E: Ext + 'a> Runtime<'a, E> {
Err(wasmi::Error::Trap(trap)) => {
// If we encoded a reason then it is some abort generated by a host function.
// Otherwise the trap came from the contract.
let reason: TrapReason = *trap
.into_host()
.ok_or(Error::<E::T>::ContractTrapped)?
.downcast()
.expect("`TrapReason` is the only type we use to encode host errors; qed");
let reason: TrapReason = trap.downcast().ok_or(Error::<E::T>::ContractTrapped)?;
match reason {
Return(ReturnData { flags, data }) => {
let flags =