Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

contracts: Allow stack height metering to be disabled #10877

Merged
merged 5 commits into from
Feb 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 5 additions & 2 deletions frame/contracts/src/benchmarking/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,9 @@ fn inject_gas_metering<T: Config>(module: Module) -> Module {
}

fn inject_stack_metering<T: Config>(module: Module) -> Module {
let height = T::Schedule::get().limits.stack_height;
wasm_instrument::inject_stack_limiter(module, height).unwrap()
if let Some(height) = T::Schedule::get().limits.stack_height {
wasm_instrument::inject_stack_limiter(module, height).unwrap()
} else {
module
}
}
6 changes: 3 additions & 3 deletions frame/contracts/src/benchmarking/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2250,7 +2250,7 @@ benchmarks! {
// w_local_get = w_bench - 1 * w_param
instr_local_get {
let r in 0 .. INSTR_BENCHMARK_BATCHES;
let max_locals = T::Schedule::get().limits.stack_height;
let max_locals = T::Schedule::get().limits.stack_height.unwrap_or(512);
let mut call_body = body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
RandomGetLocal(0, max_locals),
Regular(Instruction::Drop),
Expand All @@ -2267,7 +2267,7 @@ benchmarks! {
// w_local_set = w_bench - 1 * w_param
instr_local_set {
let r in 0 .. INSTR_BENCHMARK_BATCHES;
let max_locals = T::Schedule::get().limits.stack_height;
let max_locals = T::Schedule::get().limits.stack_height.unwrap_or(512);
let mut call_body = body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
RandomI64Repeated(1),
RandomSetLocal(0, max_locals),
Expand All @@ -2284,7 +2284,7 @@ benchmarks! {
// w_local_tee = w_bench - 2 * w_param
instr_local_tee {
let r in 0 .. INSTR_BENCHMARK_BATCHES;
let max_locals = T::Schedule::get().limits.stack_height;
let max_locals = T::Schedule::get().limits.stack_height.unwrap_or(512);
let mut call_body = body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
RandomI64Repeated(1),
RandomTeeLocal(0, max_locals),
Expand Down
12 changes: 9 additions & 3 deletions frame/contracts/src/schedule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,13 @@ pub struct Limits {
/// See <https://wiki.parity.io/WebAssembly-StackHeight> to find out
/// how the stack frame cost is calculated. Each element can be of one of the
/// wasm value types. This means the maximum size per element is 64bit.
pub stack_height: u32,
///
/// # Note
///
/// It is safe to disable (pass `None`) the `stack_height` when the execution engine
/// is part of the runtime and hence there can be no indeterminism between different
/// client resident execution engines.
pub stack_height: Option<u32>,

/// Maximum number of globals a module is allowed to declare.
///
Expand Down Expand Up @@ -496,8 +502,8 @@ impl Default for Limits {
fn default() -> Self {
Self {
event_topics: 4,
// 512 * sizeof(i64) will give us a 4k stack.
stack_height: 512,
// No stack limit required because we use a runtime resident execution engine.
stack_height: None,
globals: 256,
parameters: 128,
memory_pages: 16,
Expand Down
8 changes: 7 additions & 1 deletion frame/contracts/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,13 @@ parameter_types! {
pub const MaxValueSize: u32 = 16_384;
pub const DeletionWeightLimit: Weight = 500_000_000_000;
pub const MaxCodeSize: u32 = 2 * 1024;
pub MySchedule: Schedule<Test> = <Schedule<Test>>::default();
pub MySchedule: Schedule<Test> = {
let mut schedule = <Schedule<Test>>::default();
// We want stack height to be always enabled for tests so that this
// instrumentation path is always tested implicitly.
schedule.limits.stack_height = Some(512);
schedule
};
pub const TransactionByteFee: u64 = 0;
pub static DepositPerByte: BalanceOf<Test> = 1;
pub const DepositPerItem: BalanceOf<Test> = 2;
Expand Down
9 changes: 6 additions & 3 deletions frame/contracts/src/wasm/prepare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,13 @@ impl<'a, T: Config> ContractModule<'a, T> {
}

fn inject_stack_height_metering(self) -> Result<Self, &'static str> {
let contract_module =
wasm_instrument::inject_stack_limiter(self.module, self.schedule.limits.stack_height)
if let Some(limit) = self.schedule.limits.stack_height {
let contract_module = wasm_instrument::inject_stack_limiter(self.module, limit)
.map_err(|_| "stack height instrumentation failed")?;
Ok(ContractModule { module: contract_module, schedule: self.schedule })
Ok(ContractModule { module: contract_module, schedule: self.schedule })
} else {
Ok(ContractModule { module: self.module, schedule: self.schedule })
}
}

/// Check that the module has required exported functions. For now
Expand Down
Loading