Skip to content

Commit 60aa1d7

Browse files
authored
contracts: switch from parity-wasm-based to wasmi-based module validation (paritytech#14449)
* upgrade to wasmi 0.29 * prepare cleanup * sync ref_time w engine from the stack frame * proc_macro: sync gas in host funcs save: compiles, only gas pushing left to macro WIP proc macro proc macro: done * clean benchmarks & schedule: w_base = w_i64const * scale gas values btw engine and gas meter * (re)instrumentation & code_cache removed * remove gas() host fn, continue clean-up save * address review comments * move from CodeStorage&PrefabWasmModule to PristineCode&WasmBlob * refactor: no reftime_limit&schedule passes, no CodeStorage * bugs fixing * fix tests: expected deposit amount * fix prepare::tests * update tests and fix bugs tests::run_out_of_gas_engine, need 2 more save: 2 bugs with gas syncs: 1 of 2 tests done gas_syncs_no_overcharge bug fixed, test passes! cleaned out debug prints second bug is not a bug disabled_chain_extension test fix (err msg) tests run_out_of_fuel_host, chain_extension pass all tests pass * update docs * bump wasmi 0.30.0 * benchmarks updated, tests pass * refactoring * s/OwnerInfo/CodeInfo/g; * migration: draft, compiles * migration: draft, runs * migration: draft, runs (fixing) * deposits repaid non pro rata * deposits repaid pro rata * better try-runtime output * even better try-runtime output * benchmark migration * fix merge leftover * add forgotten fixtures, fix docs * address review comments * ci fixes * cleanup * benchmarks::prepare to return DispatchError * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * store memory limits to CodeInfo * ci: roll back weights * ".git/.scripts/commands/bench-vm/bench-vm.sh" pallet dev pallet_contracts * drive-by: update Readme and pallet rustdoc * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * use wasmi 0.29 * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * use wasmi 0.30 again * query memory limits from wasmi * save: scan_exports ported, compiles * save (wip, not compiles) * query memory limits from wasmi * better migration types * ci: pull weights from master * refactoring * ".git/.scripts/commands/bench-vm/bench-vm.sh" pallet dev pallet_contracts * scan_imports ported * scan_export ported, other checks removed * tests fixed tests fixed * drop wasmparser and parity-wasm dependencies * typo fix * addressing review comments * refactor * address review comments * optimize migration * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * another review round comments addressed * ci fix one * clippy fix * ci fix two * allow stored modules to have no memory imports * rollback: allow stored modules to have no memory imports * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * address review comments --------- Co-authored-by: command-bot <>
1 parent dfd8286 commit 60aa1d7

File tree

14 files changed

+901
-1142
lines changed

14 files changed

+901
-1142
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frame/contracts/Cargo.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,15 @@ codec = { package = "parity-scale-codec", version = "3.6.1", default-features =
2121
] }
2222
scale-info = { version = "2.5.0", default-features = false, features = ["derive"] }
2323
log = { version = "0.4", default-features = false }
24-
wasm-instrument = { version = "0.4", default-features = false }
2524
serde = { version = "1", optional = true, features = ["derive"] }
2625
smallvec = { version = "1", default-features = false, features = [
2726
"const_generics",
2827
] }
2928
wasmi = { version = "0.30", default-features = false }
30-
wasmparser = { package = "wasmparser-nostd", version = "0.100", default-features = false }
3129
impl-trait-for-tuples = "0.2"
3230

33-
# Only used in benchmarking to generate random contract code
31+
# Only used in benchmarking to generate contract code
32+
wasm-instrument = { version = "0.4", optional = true, default-features = false }
3433
rand = { version = "0.8", optional = true, default-features = false }
3534
rand_pcg = { version = "0.3", optional = true }
3635

@@ -81,12 +80,12 @@ std = [
8180
"pallet-contracts-proc-macro/full",
8281
"log/std",
8382
"rand/std",
84-
"wasmparser/std",
8583
"environmental/std",
8684
]
8785
runtime-benchmarks = [
8886
"frame-benchmarking/runtime-benchmarks",
8987
"rand",
9088
"rand_pcg",
89+
"wasm-instrument",
9190
]
9291
try-runtime = ["frame-support/try-runtime"]

frame/contracts/fixtures/dummy.wat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
;; A valid contract which does nothing at all
22
(module
3+
(import "env" "memory" (memory 1 1))
34
(func (export "deploy"))
45
(func (export "call"))
56
)

frame/contracts/fixtures/float_instruction.wat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
;; Module that contains a float instruction which is illegal in deterministic mode
22
(module
3+
(import "env" "memory" (memory 1 1))
34
(func (export "call")
45
f32.const 1
56
drop
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
;; Valid module but missing the call function
22
(module
3+
(import "env" "memory" (memory 1 1))
34
(func (export "deploy"))
45
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
;; A valid contract which does nothing at all
2+
(module
3+
(func (export "deploy"))
4+
(func (export "call"))
5+
)

frame/contracts/fixtures/run_out_of_gas.wat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
(module
2+
(import "env" "memory" (memory 1 1))
23
(func (export "call")
34
(loop $inf (br $inf)) ;; just run out of gas
45
(unreachable)

frame/contracts/src/benchmarking/code.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ impl<T: Config> From<ModuleDefinition> for WasmModule<T> {
122122
// internal functions start at that offset.
123123
let func_offset = u32::try_from(def.imported_functions.len()).unwrap();
124124

125-
// Every contract must export "deploy" and "call" functions
125+
// Every contract must export "deploy" and "call" functions.
126126
let mut contract = builder::module()
127127
// deploy function (first internal function)
128128
.function()
@@ -163,15 +163,16 @@ impl<T: Config> From<ModuleDefinition> for WasmModule<T> {
163163
}
164164

165165
// Grant access to linear memory.
166-
if let Some(memory) = &def.memory {
167-
contract = contract
168-
.import()
169-
.module("env")
170-
.field("memory")
171-
.external()
172-
.memory(memory.min_pages, Some(memory.max_pages))
173-
.build();
174-
}
166+
// Every contract module is required to have an imported memory.
167+
// If no memory is specified in the passed ModuleDefenition, then
168+
// default to (1, 1).
169+
let (init, max) = if let Some(memory) = &def.memory {
170+
(memory.min_pages, Some(memory.max_pages))
171+
} else {
172+
(1, Some(1))
173+
};
174+
175+
contract = contract.import().path("env", "memory").external().memory(init, max).build();
175176

176177
// Import supervisor functions. They start with idx 0.
177178
for func in def.imported_functions {

frame/contracts/src/benchmarking/sandbox.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
/// ! sandbox to execute the Wasm code. This is because we do not need the full
2020
/// ! environment that provides the seal interface as imported functions.
2121
use super::{code::WasmModule, Config};
22-
use crate::wasm::{AllowDeprecatedInterface, AllowUnstableInterface, Environment, WasmBlob};
22+
use crate::wasm::{
23+
AllowDeprecatedInterface, AllowUnstableInterface, Determinism, Environment, WasmBlob,
24+
};
2325
use sp_core::Get;
2426
use wasmi::{errors::LinkerError, Func, Linker, StackLimits, Store};
2527

@@ -44,6 +46,7 @@ impl<T: Config> From<&WasmModule<T>> for Sandbox {
4446
&module.code,
4547
(),
4648
&<T>::Schedule::get(),
49+
Determinism::Relaxed,
4750
StackLimits::default(),
4851
// We are testing with an empty environment anyways
4952
AllowDeprecatedInterface::No,

frame/contracts/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,8 @@ pub mod pallet {
885885
CodeTooLarge,
886886
/// No code could be found at the supplied code hash.
887887
CodeNotFound,
888+
/// No code info could be found at the supplied code hash.
889+
CodeInfoNotFound,
888890
/// A buffer outside of sandbox memory was passed to a contract API function.
889891
OutOfBounds,
890892
/// Input passed to a contract API function failed to decode as expected type.

0 commit comments

Comments
 (0)