diff --git a/Cargo.lock b/Cargo.lock index 560a4edfb2..f81e6f5f8a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -326,6 +326,7 @@ dependencies = [ "primitives", "scale-info", "serde", + "smallvec", "sp-api", "sp-block-builder", "sp-consensus-aura", diff --git a/bin/node/src/main.rs b/bin/node/src/main.rs index 3572ffe641..77ac1e6edf 100644 --- a/bin/node/src/main.rs +++ b/bin/node/src/main.rs @@ -1,6 +1,7 @@ #[cfg(feature = "try-runtime")] use aleph_node::ExecutorDispatch; use aleph_node::{new_authority, new_full, new_partial, Cli, Subcommand}; +use aleph_primitives::HEAP_PAGES; #[cfg(feature = "try-runtime")] use aleph_runtime::Block; use log::warn; @@ -16,8 +17,6 @@ fn default_blocks_pruning() -> DatabasePruningMode { DatabasePruningMode::ArchiveCanonical } -const HEAP_PAGES: u64 = 4096; - fn pruning_changed(params: &PruningParams) -> bool { let state_pruning_changed = params.state_pruning != default_state_pruning(); @@ -26,8 +25,6 @@ fn pruning_changed(params: &PruningParams) -> bool { state_pruning_changed || blocks_pruning_changed } -// The default number of heap pages in substrate is 2048. Every heap page is 64KB, -// so value of 4096 gives 256MB memory for entire runtime. fn enforce_heap_pages(config: &mut Configuration) { config.default_heap_pages = Some(HEAP_PAGES); } diff --git a/bin/runtime/Cargo.toml b/bin/runtime/Cargo.toml index c4d070011c..acfc86bc12 100644 --- a/bin/runtime/Cargo.toml +++ b/bin/runtime/Cargo.toml @@ -64,6 +64,9 @@ pallet-elections = { path = "../../pallets/elections", default-features = false [build-dependencies] substrate-wasm-builder = { git = "https://github.com/Cardinal-Cryptography/substrate.git", branch = "aleph-v0.9.36" } +[dev-dependencies] +smallvec = { version = "1", default-features = false} + [features] default = ["std"] std = [ diff --git a/bin/runtime/src/lib.rs b/bin/runtime/src/lib.rs index 44ec9307c4..54c5ebf2c5 100644 --- a/bin/runtime/src/lib.rs +++ b/bin/runtime/src/lib.rs @@ -1017,10 +1017,38 @@ impl_runtime_apis! { #[cfg(test)] mod tests { - use crate::VERSION; + use frame_support::traits::Get; + use primitives::HEAP_PAGES; + use smallvec::Array; + + use super::*; #[test] fn state_version_must_be_zero() { assert_eq!(0, VERSION.state_version); } + + #[test] + fn check_contracts_memory_parameters() { + // Memory limit of one instance of a runtime + const MAX_RUNTIME_MEM: u32 = HEAP_PAGES as u32 * 64 * 1024; + // Max stack size defined by wasmi - 1MB + const MAX_STACK_SIZE: u32 = 1024 * 1024; + // Max heap size is 16 mempages of 64KB each - 1MB + let max_heap_size = ::Schedule::get() + .limits + .max_memory_size(); + // Max call depth is CallStack::size() + 1 + let max_call_depth = ::CallStack::size() as u32 + 1; + // Max code len + let max_code_len: u32 = ::MaxCodeLen::get(); + + // The factor comes from allocator, contracts representation, and wasmi + let lhs = max_call_depth * (72 * max_code_len + max_heap_size + MAX_STACK_SIZE); + // We allocate only 75% of all runtime memory to contracts execution. Important: it's not + // enforeced in wasmtime + let rhs = MAX_RUNTIME_MEM * 3 / 4; + + assert!(lhs < rhs); + } } diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 554677fffb..48a94559f8 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -38,6 +38,9 @@ pub type BlockNumber = u32; pub type SessionCount = u32; pub type BlockCount = u32; +// Default number of heap pages that gives limit of 256MB for a runtime instance since each page is 64KB +pub const HEAP_PAGES: u64 = 4096; + pub const MILLISECS_PER_BLOCK: u64 = 1000; // We agreed to 5MB as the block size limit. pub const MAX_BLOCK_SIZE: u32 = 5 * 1024 * 1024;