Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Contracts: update wasmi to 0.32 #3679

Merged
merged 104 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
94fe749
Only load module once when validating
pgherveou Mar 22, 2024
a38c8a6
bump wasmi to 0.32
pgherveou Mar 22, 2024
bada63e
Merge branch 'master' into pg/wasmi-to-v0.32.0-beta.7
pgherveou Apr 10, 2024
0b96f38
fix lock
pgherveou Apr 10, 2024
88abfcf
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
Apr 10, 2024
21e5e33
Merge branch 'master' into pg/wasmi-to-v0.32.0-beta.7
pgherveou Apr 11, 2024
4503590
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
Apr 11, 2024
c275207
Use eager compilation mode when benchmarking a host fn
pgherveou Apr 11, 2024
3e835d0
tmp: Use eager compilation
pgherveou Apr 11, 2024
3892688
Merge branch 'master' of https://github.com/paritytech/polkadot-sdk i…
Apr 11, 2024
63d8663
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
Apr 11, 2024
59138ba
Disable unchecked compilation for now
pgherveou Apr 11, 2024
4d5b935
Merge branch 'master' of https://github.com/paritytech/polkadot-sdk i…
Apr 11, 2024
b1db093
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
Apr 11, 2024
213c84e
Merge branch 'master' into pg/wasmi-to-v0.32.0-beta.7
pgherveou Apr 16, 2024
1f6f926
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
Apr 16, 2024
4c84d87
Merge branch 'master' into pg/wasmi-to-v0.3t 2.0-beta.7
athei Apr 17, 2024
6b0acbd
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
Apr 17, 2024
829d590
Merge branch 'master' into pg/wasmi-to-v0.32.0-beta.7
pgherveou Apr 17, 2024
0de9713
wip
pgherveou Apr 22, 2024
d4ab2a8
wip
pgherveou Apr 22, 2024
ecedf8c
wip
pgherveou Apr 22, 2024
00fa306
Merge branch 'master' into pg/rework-host-benchs
pgherveou Apr 22, 2024
f2152fe
wip
pgherveou Apr 23, 2024
75f1c8c
wip
pgherveou Apr 25, 2024
d3921cd
Fixes
pgherveou Apr 26, 2024
c727dd2
Fixes
pgherveou Apr 26, 2024
cf3362f
Update
pgherveou Apr 26, 2024
aed88a9
fixes
pgherveou Apr 26, 2024
f20aed7
Merge branch 'master' of https://github.com/paritytech/polkadot-sdk i…
Apr 29, 2024
450ca08
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
Apr 29, 2024
c2cd365
Fixes
pgherveou Apr 29, 2024
19fb7bf
fix
pgherveou Apr 29, 2024
5edcd18
Rm unused
pgherveou Apr 29, 2024
837b2d6
Merge branch 'master' of https://github.com/paritytech/polkadot-sdk i…
Apr 29, 2024
b2eb314
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
Apr 29, 2024
41b5f3a
add ;
pgherveou Apr 29, 2024
f4d65f6
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
Apr 29, 2024
9ceb549
Undo
pgherveou May 3, 2024
c6df46a
Merge branch 'pg/rework-host-benchs' into pg/wasmi-to-v0.32.0-beta.7
pgherveou May 3, 2024
47b5291
restore unchecked & lazy compilation
pgherveou May 3, 2024
50c3b66
bump to latest beta
pgherveou May 3, 2024
92a27a1
Update fuel syncing.
pgherveou May 3, 2024
a75fa25
nit
pgherveou May 3, 2024
3466434
set_fuel can't error
pgherveou May 3, 2024
f398a9c
nit
pgherveou May 3, 2024
28acc56
Add PRdoc
pgherveou May 15, 2024
6d87585
Fix PRdoc
pgherveou May 15, 2024
8364456
Merge branch 'master' into pg/rework-host-benchs
athei May 16, 2024
0586b4a
benchmarks: whitelist account_id and contract_info for the root contract
pgherveou May 16, 2024
fbdc565
fix
pgherveou May 16, 2024
58517ee
PR review merge set_storage_per_new_byte & _old_bytes
pgherveou May 16, 2024
825a434
Merge branch 'master' of https://github.com/paritytech/polkadot-sdk i…
May 16, 2024
2cc19fb
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
May 16, 2024
a11e74b
Fix terminate
pgherveou May 17, 2024
da17374
Merge branch 'master' into pg/rework-host-benchs
pgherveou May 17, 2024
b806834
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
May 17, 2024
799134f
Merge branch 'pg/rework-host-benchs' into pg/wasmi-to-v0.32.0-beta.7
pgherveou May 17, 2024
ae17165
Bump beta version
pgherveou May 17, 2024
80dc606
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
May 17, 2024
87fa082
Merge branch 'master' into pg/rework-host-benchs
athei May 17, 2024
d235dfa
Remove internal events
pgherveou May 17, 2024
7ae8ac1
Add prdoc
pgherveou May 17, 2024
737e956
Fix tests
pgherveou May 17, 2024
2f34c0f
use whitelisted root contract origin for cross contract benchmarks
pgherveou May 17, 2024
8b24c9a
Merge branch 'pg/fix_legacy_bench' into pg/rework-host-benchs
pgherveou May 17, 2024
efd75a8
Merge branch 'pg/fix_legacy_bench' into pg/rework-host-benchs
pgherveou May 17, 2024
d5b08bb
Merge branch 'master' into pg/rework-host-benchs
pgherveou May 17, 2024
2926901
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
May 17, 2024
fb9355f
Merge branch 'master' of https://github.com/paritytech/polkadot-sdk i…
May 19, 2024
6b4eea3
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
May 19, 2024
2fa8edc
Simplify clone call
pgherveou May 20, 2024
46650ca
Fix weights
pgherveou May 20, 2024
d7ea304
Merge branch 'master' of https://github.com/paritytech/polkadot-sdk i…
May 20, 2024
8f15947
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
May 20, 2024
3532367
Bump wasmi beta
pgherveou May 23, 2024
1b186f6
Merge branch 'pg/rework-host-benchs' into pg/wasmi-to-v0.32.0-beta.7
pgherveou May 23, 2024
7ff3655
Update prdoc
pgherveou May 23, 2024
d054fcd
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
May 23, 2024
e2ec3cd
Add debug statement
pgherveou May 23, 2024
8e25cc9
Update to latest beta
pgherveou May 23, 2024
ca9da25
Merge branch 'master' into pg/wasmi-to-v0.32.0-beta.7
pgherveou May 23, 2024
d47a0d2
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
May 23, 2024
c116c66
Merge branch 'master' into pg/wasmi-to-v0.32.0-beta.7
pgherveou May 27, 2024
a058d38
Add assert
pgherveou May 27, 2024
ba61f59
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
May 27, 2024
8b7ca41
Merge branch 'master' of https://github.com/paritytech/polkadot-sdk i…
May 27, 2024
8fd1875
".git/.scripts/commands/bench-all/bench-all.sh" --pallet=pallet_contr…
May 27, 2024
2d40ddd
Update wasmi version
pgherveou May 29, 2024
49e3c78
Merge branch 'pg/wasmi-to-v0.32.0-beta.7' of https://github.com/parit…
pgherveou May 29, 2024
99fb78c
Update PR doc
pgherveou May 30, 2024
ca61d1b
Merge branch 'master' into pg/wasmi-to-v0.32.0-beta.7
pgherveou May 30, 2024
78abbea
test roll-back beta
pgherveou May 30, 2024
72de0b5
fix lock
pgherveou May 30, 2024
6eae263
fix lock
pgherveou May 30, 2024
cf02fd7
roll back 0.32
pgherveou May 30, 2024
acd6dfb
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
May 30, 2024
08ea90b
Bump wasmi
pgherveou Jun 3, 2024
ac9f81c
Remove transfer_surcharge from instantiate
pgherveou Jun 3, 2024
b960a6d
Merge branch 'master' of https://github.com/paritytech/polkadot-sdk i…
Jun 3, 2024
c2b7441
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
Jun 3, 2024
7efe1e7
Fix PR doc and bump wasmi one last time
pgherveou Jun 7, 2024
99cd79e
Merge branch 'master' into pg/wasmi-to-v0.32.0-beta.7
pgherveou Jun 7, 2024
ee1a7ca
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
Jun 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions substrate/frame/contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,6 @@ calls are reverted. Assuming correct error handling by contract A, A's other cal

One `ref_time` `Weight` is defined as one picosecond of execution time on the runtime's reference machine.

#### Schedule

The `Schedule` is where, among other things, the cost of every action a contract can do is defined. These costs are derived
from the benchmarks of this pallet. Instead of looking at the raw benchmark results it is advised to look at the `Schedule`
if one wants to manually inspect the performance characteristics. The `Schedule` can be printed like this:

```sh
RUST_LOG=runtime::contracts=info cargo run --features runtime-benchmarks --bin substrate-node -- benchmark pallet --extra -p pallet_contracts -e print_schedule
```

Please note that the `Schedule` will be printed multiple times. This is because we are (ab)using a benchmark to print
the struct.

### Revert Behaviour

Contract call failures are not cascading. When failures occur in a sub-call, they do not "bubble up", and the call will
Expand Down
178 changes: 127 additions & 51 deletions substrate/frame/contracts/proc-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ struct HostFn {
alias_to: Option<String>,
/// Formulating the predicate inverted makes the expression using it simpler.
not_deprecated: bool,
cfg: Option<syn::Attribute>,
}

enum HostFnReturn {
Expand Down Expand Up @@ -163,20 +164,21 @@ impl ToTokens for HostFn {
impl HostFn {
pub fn try_from(mut item: syn::ItemFn) -> syn::Result<Self> {
let err = |span, msg| {
let msg = format!("Invalid host function definition. {}", msg);
let msg = format!("Invalid host function definition.\n{}", msg);
syn::Error::new(span, msg)
};

// process attributes
let msg =
"only #[version(<u8>)], #[unstable], #[prefixed_alias] and #[deprecated] attributes are allowed.";
"Only #[version(<u8>)], #[unstable], #[prefixed_alias], #[cfg] and #[deprecated] attributes are allowed.";
let span = item.span();
let mut attrs = item.attrs.clone();
attrs.retain(|a| !a.path().is_ident("doc"));
let mut maybe_version = None;
let mut is_stable = true;
let mut alias_to = None;
let mut not_deprecated = true;
let mut cfg = None;
while let Some(attr) = attrs.pop() {
let ident = attr.path().get_ident().ok_or(err(span, msg))?.to_string();
match ident.as_str() {
Expand Down Expand Up @@ -206,7 +208,13 @@ impl HostFn {
}
not_deprecated = false;
},
_ => return Err(err(span, msg)),
"cfg" => {
if cfg.is_some() {
return Err(err(span, "#[cfg] can only be specified once"))
}
cfg = Some(attr);
},
id => return Err(err(span, &format!("Unsupported attribute \"{id}\". {msg}"))),
}
}
let name = item.sig.ident.to_string();
Expand Down Expand Up @@ -311,6 +319,7 @@ impl HostFn {
is_stable,
alias_to,
not_deprecated,
cfg,
})
},
_ => Err(err(span, &msg)),
Expand Down Expand Up @@ -528,8 +537,9 @@ fn expand_env(def: &EnvDef, docs: bool) -> TokenStream2 {
/// - real implementation, to register it in the contract execution environment;
/// - dummy implementation, to be used as mocks for contract validation step.
fn expand_impls(def: &EnvDef) -> TokenStream2 {
let impls = expand_functions(def, true, quote! { crate::wasm::Runtime<E> });
let dummy_impls = expand_functions(def, false, quote! { () });
let impls = expand_functions(def, ExpandMode::Impl);
let dummy_impls = expand_functions(def, ExpandMode::MockImpl);
let bench_impls = expand_functions(def, ExpandMode::BenchImpl);

quote! {
impl<'a, E: Ext> crate::wasm::Environment<crate::wasm::runtime::Runtime<'a, E>> for Env
Expand All @@ -545,6 +555,14 @@ fn expand_impls(def: &EnvDef) -> TokenStream2 {
}
}

#[cfg(feature = "runtime-benchmarks")]
pub struct BenchEnv<E>(::core::marker::PhantomData<E>);

#[cfg(feature = "runtime-benchmarks")]
impl<E: Ext> BenchEnv<E> {
#bench_impls
}

impl crate::wasm::Environment<()> for Env
{
fn define(
Expand All @@ -560,18 +578,38 @@ fn expand_impls(def: &EnvDef) -> TokenStream2 {
}
}

fn expand_functions(def: &EnvDef, expand_blocks: bool, host_state: TokenStream2) -> TokenStream2 {
enum ExpandMode {
Impl,
BenchImpl,
MockImpl,
}

impl ExpandMode {
fn expand_blocks(&self) -> bool {
match *self {
ExpandMode::Impl | ExpandMode::BenchImpl => true,
ExpandMode::MockImpl => false,
}
}

fn host_state(&self) -> TokenStream2 {
match *self {
ExpandMode::Impl | ExpandMode::BenchImpl => quote! { crate::wasm::runtime::Runtime<E> },
ExpandMode::MockImpl => quote! { () },
}
}
}

fn expand_functions(def: &EnvDef, expand_mode: ExpandMode) -> TokenStream2 {
let impls = def.host_funcs.iter().map(|f| {
// skip the context and memory argument
let params = f.item.sig.inputs.iter().skip(2);

let (module, name, body, wasm_output, output) = (
f.module(),
&f.name,
&f.item.block,
f.returns.to_wasm_sig(),
&f.item.sig.output
);
let module = f.module();
let cfg = &f.cfg;
let name = &f.name;
let body = &f.item.block;
let wasm_output = f.returns.to_wasm_sig();
let output = &f.item.sig.output;
let is_stable = f.is_stable;
let not_deprecated = f.not_deprecated;

Expand Down Expand Up @@ -608,23 +646,34 @@ fn expand_functions(def: &EnvDef, expand_blocks: bool, host_state: TokenStream2)
// - We replace any code by unreachable!
// - Allow unused variables as the code that uses is not expanded
// - We don't need to map the error as we simply panic if they code would ever be executed
let inner = if expand_blocks {
quote! { || #output {
let (memory, ctx) = __caller__
.data()
.memory()
.expect("Memory must be set when setting up host data; qed")
.data_and_store_mut(&mut __caller__);
#wrapped_body_with_trace
} }
} else {
quote! { || -> #wasm_output {
// This is part of the implementation for `Environment<()>` which is not
// meant to be actually executed. It is only for validation which will
// never call host functions.
::core::unreachable!()
} }
let expand_blocks = expand_mode.expand_blocks();
let inner = match expand_mode {
ExpandMode::Impl => {
quote! { || #output {
let (memory, ctx) = __caller__
.data()
.memory()
.expect("Memory must be set when setting up host data; qed")
.data_and_store_mut(&mut __caller__);
#wrapped_body_with_trace
} }
},
ExpandMode::BenchImpl => {
let body = &body.stmts;
quote!{
#(#body)*
}
},
ExpandMode::MockImpl => {
quote! { || -> #wasm_output {
// This is part of the implementation for `Environment<()>` which is not
// meant to be actually executed. It is only for validation which will
// never call host functions.
::core::unreachable!()
} }
},
};

let into_host = if expand_blocks {
quote! {
|reason| {
Expand Down Expand Up @@ -655,6 +704,11 @@ fn expand_functions(def: &EnvDef, expand_blocks: bool, host_state: TokenStream2)
.map_err(TrapReason::from)
.map_err(#into_host)?
};

// Charge gas for host function execution.
__caller__.data_mut().charge_gas(crate::wasm::RuntimeCosts::HostFn)
.map_err(TrapReason::from)
.map_err(#into_host)?;
}
} else {
quote! { }
Expand All @@ -679,29 +733,51 @@ fn expand_functions(def: &EnvDef, expand_blocks: bool, host_state: TokenStream2)
quote! { }
};

quote! {
// We need to allow all interfaces when runtime benchmarks are performed because
// we generate the weights even when those interfaces are not enabled. This
// is necessary as the decision whether we allow unstable or deprecated functions
// is a decision made at runtime. Generation of the weights happens statically.
if ::core::cfg!(feature = "runtime-benchmarks") ||
((#is_stable || __allow_unstable__) && (#not_deprecated || __allow_deprecated__))
{
#allow_unused
linker.define(#module, #name, ::wasmi::Func::wrap(&mut*store, |mut __caller__: ::wasmi::Caller<#host_state>, #( #params, )*| -> #wasm_output {
#sync_gas_before
let mut func = #inner;
let result = func().map_err(#into_host).map(::core::convert::Into::into);
#sync_gas_after
result
}))?;
}
match expand_mode {
ExpandMode::BenchImpl => {
let name = Ident::new(&format!("{module}_{name}"), Span::call_site());
quote! {
pub fn #name(ctx: &mut crate::wasm::Runtime<E>, memory: &mut [u8], #(#params),*) #output {
#inner
}
}
},
_ => {
let host_state = expand_mode.host_state();
quote! {
// We need to allow all interfaces when runtime benchmarks are performed because
// we generate the weights even when those interfaces are not enabled. This
// is necessary as the decision whether we allow unstable or deprecated functions
// is a decision made at runtime. Generation of the weights happens statically.
#cfg
if ::core::cfg!(feature = "runtime-benchmarks") ||
((#is_stable || __allow_unstable__) && (#not_deprecated || __allow_deprecated__))
{
#allow_unused
linker.define(#module, #name, ::wasmi::Func::wrap(&mut*store, |mut __caller__: ::wasmi::Caller<#host_state>, #( #params, )*| -> #wasm_output {
#sync_gas_before
let mut func = #inner;
let result = func().map_err(#into_host).map(::core::convert::Into::into);
#sync_gas_after
result
}))?;
}
}
},
}
});
quote! {
let __allow_unstable__ = matches!(allow_unstable, AllowUnstableInterface::Yes);
let __allow_deprecated__ = matches!(allow_deprecated, AllowDeprecatedInterface::Yes);
#( #impls )*

match expand_mode {
ExpandMode::BenchImpl => {
quote! {
#( #impls )*
}
},
_ => quote! {
let __allow_unstable__ = matches!(allow_unstable, AllowUnstableInterface::Yes);
let __allow_deprecated__ = matches!(allow_deprecated, AllowDeprecatedInterface::Yes);
#( #impls )*
},
}
}

Expand Down
44 changes: 31 additions & 13 deletions substrate/frame/contracts/src/benchmarking/call_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ pub struct CallSetup<T: Config> {
data: Vec<u8>,
}

impl<T> Default for CallSetup<T>
where
T: Config + pallet_balances::Config,
<BalanceOf<T> as HasCompact>::Type: Clone + Eq + PartialEq + Debug + TypeInfo + Encode,
{
fn default() -> Self {
Self::new(WasmModule::dummy())
}
}

impl<T> CallSetup<T>
where
T: Config + pallet_balances::Config,
Expand Down Expand Up @@ -150,21 +160,29 @@ where
}

#[macro_export]
macro_rules! call_builder(
($func: ident, $module:expr) => {
$crate::call_builder!($func, _contract, $module);
macro_rules! memory(
($($bytes:expr,)*) => {
vec![]
.into_iter()
$(.chain($bytes))*
.collect::<Vec<_>>()
};
($func: ident, $contract: ident, $module:expr) => {
let mut setup = CallSetup::<T>::new($module);
$crate::call_builder!($func, $contract, setup: setup);
);

#[macro_export]
macro_rules! build_runtime(
($runtime:ident, $memory:ident: [$($segment:expr,)*]) => {
$crate::build_runtime!($runtime, _contract, $memory: [$($segment,)*]);
};
($func:ident, setup: $setup: ident) => {
$crate::call_builder!($func, _contract, setup: $setup);
($runtime:ident, $contract:ident, $memory:ident: [$($bytes:expr,)*]) => {
$crate::build_runtime!($runtime, $contract);
let mut $memory = $crate::memory!($($bytes,)*);
};
($func:ident, $contract: ident, setup: $setup: ident) => {
let data = $setup.data();
let $contract = $setup.contract();
let (mut ext, module) = $setup.ext();
let $func = CallSetup::<T>::prepare_call(&mut ext, module, data);
($runtime:ident, $contract:ident) => {
let mut setup = CallSetup::<T>::default();
let $contract = setup.contract();
let input = setup.data();
let (mut ext, _) = setup.ext();
let mut $runtime = crate::wasm::Runtime::new(&mut ext, input);
};
);
Loading
Loading