diff --git a/substrate/core/cli/src/params.rs b/substrate/core/cli/src/params.rs index 0f0617f859..c1135afb2e 100644 --- a/substrate/core/cli/src/params.rs +++ b/substrate/core/cli/src/params.rs @@ -263,9 +263,9 @@ pub struct ImportBlocksCmd { )] pub api_execution: ExecutionStrategy, - /// The maximum number of 64KB pages to ever allocate for Wasm execution. Don't alter this unless you know what you're doing. - #[structopt(long = "max-heap-pages", value_name = "COUNT")] - pub max_heap_pages: Option, + /// The default number of 64KB pages to allocate for Wasm execution. Don't alter this unless you know what you're doing. + #[structopt(long = "default-heap-pages", value_name = "COUNT")] + pub default_heap_pages: Option, #[allow(missing_docs)] #[structopt(flatten)] diff --git a/substrate/core/client/src/genesis.rs b/substrate/core/client/src/genesis.rs index 468d7137db..83f295ecc0 100644 --- a/substrate/core/client/src/genesis.rs +++ b/substrate/core/client/src/genesis.rs @@ -54,7 +54,7 @@ mod tests { native_executor_instance!(Executor, test_client::runtime::api::dispatch, test_client::runtime::native_version, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm")); fn executor() -> executor::NativeExecutor { - NativeExecutionDispatch::new() + NativeExecutionDispatch::new(None) } fn construct_block( @@ -207,7 +207,7 @@ mod tests { &backend, Some(&InMemoryChangesTrieStorage::new()), &mut overlay, - &Executor::new(), + &Executor::new(None), "Core_execute_block", &b1data, ExecutionStrategy::NativeWhenPossible, diff --git a/substrate/core/client/src/light/call_executor.rs b/substrate/core/client/src/light/call_executor.rs index 601cb0732f..f6ea6b32f2 100644 --- a/substrate/core/client/src/light/call_executor.rs +++ b/substrate/core/client/src/light/call_executor.rs @@ -450,7 +450,7 @@ mod tests { ).unwrap(); // check remote execution proof locally - let local_executor = test_client::LocalExecutor::new(); + let local_executor = test_client::LocalExecutor::new(None); let local_result = check_execution_proof(&local_executor, &RemoteCallRequest { block: test_client::runtime::Hash::default(), header: test_client::runtime::Header { diff --git a/substrate/core/client/src/light/fetcher.rs b/substrate/core/client/src/light/fetcher.rs index 49c7a5a5f2..1c1697eb34 100644 --- a/substrate/core/client/src/light/fetcher.rs +++ b/substrate/core/client/src/light/fetcher.rs @@ -456,7 +456,7 @@ pub mod tests { None, crate::backend::NewBlockState::Final, ).unwrap(); - let local_executor = test_client::LocalExecutor::new(); + let local_executor = test_client::LocalExecutor::new(None); let local_checker = LightDataChecker::new(Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor); (local_checker, remote_block_header, remote_read_proof, authorities_len) } @@ -482,7 +482,7 @@ pub mod tests { if insert_cht { local_storage.insert_cht_root(1, local_cht_root); } - let local_executor = test_client::LocalExecutor::new(); + let local_executor = test_client::LocalExecutor::new(None); let local_checker = LightDataChecker::new(Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor); (local_checker, local_cht_root, remote_block_header, remote_header_proof) } @@ -535,7 +535,7 @@ pub mod tests { let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes(); let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), - test_client::LocalExecutor::new() + test_client::LocalExecutor::new(None) ); let local_checker = &local_checker as &FetchChecker; let max = remote_client.info().unwrap().chain.best_number; @@ -603,7 +603,7 @@ pub mod tests { local_storage.changes_tries_cht_roots.insert(0, local_cht_root); let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(local_storage)), - test_client::LocalExecutor::new() + test_client::LocalExecutor::new(None) ); // check proof on local client @@ -631,7 +631,7 @@ pub mod tests { let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes(); let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), - test_client::LocalExecutor::new() + test_client::LocalExecutor::new(None) ); let local_checker = &local_checker as &FetchChecker; let max = remote_client.info().unwrap().chain.best_number; @@ -712,7 +712,7 @@ pub mod tests { // fails when changes trie CHT is missing from the local db let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), - test_client::LocalExecutor::new() + test_client::LocalExecutor::new(None) ); assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots, remote_proof.roots_proof.clone()).is_err()); @@ -722,7 +722,7 @@ pub mod tests { local_storage.changes_tries_cht_roots.insert(0, local_cht_root); let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(local_storage)), - test_client::LocalExecutor::new() + test_client::LocalExecutor::new(None) ); assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots, vec![]).is_err()); } diff --git a/substrate/core/executor/src/native_executor.rs b/substrate/core/executor/src/native_executor.rs index 2c2021179a..4ee58e4493 100644 --- a/substrate/core/executor/src/native_executor.rs +++ b/substrate/core/executor/src/native_executor.rs @@ -51,6 +51,7 @@ fn fetch_cached_runtime_version<'a, E: Externalities>( wasm_executor: &WasmExecutor, cache: &'a mut RefMut, ext: &mut E, + default_heap_pages: Option, ) -> Result<(&'a WasmModuleInstanceRef, &'a Option)> { let code_hash = match ext.storage_hash(well_known_keys::CODE) { @@ -63,10 +64,10 @@ fn fetch_cached_runtime_version<'a, E: Externalities>( Some(code) => code, None => return RuntimePreproc::InvalidCode, }; - let heap_pages = match ext.storage(well_known_keys::HEAP_PAGES) { - Some(pages) => u64::decode(&mut &pages[..]).unwrap_or(DEFAULT_HEAP_PAGES), - None => DEFAULT_HEAP_PAGES, - }; + let heap_pages = ext.storage(well_known_keys::HEAP_PAGES) + .and_then(|pages| u64::decode(&mut &pages[..])) + .or(default_heap_pages) + .unwrap_or(DEFAULT_HEAP_PAGES); match WasmModule::from_buffer(code) .map_err(|_| ErrorKind::InvalidCode(vec![]).into()) .and_then(|module| wasm_executor.prepare_module(ext, heap_pages as usize, &module)) @@ -125,7 +126,7 @@ pub trait NativeExecutionDispatch: Send + Sync { fn native_version() -> NativeVersion; /// Construct corresponding `NativeExecutor` - fn new() -> NativeExecutor where Self: Sized; + fn new(default_heap_pages: Option) -> NativeExecutor where Self: Sized; } /// A generic `CodeExecutor` implementation that uses a delegate to determine wasm code equivalence @@ -138,15 +139,18 @@ pub struct NativeExecutor { fallback: WasmExecutor, /// Native runtime version info. native_version: NativeVersion, + /// The default number of 64KB pages to allocate for Wasm execution. + default_heap_pages: Option, } impl NativeExecutor { /// Create new instance. - pub fn new() -> Self { + pub fn new(default_heap_pages: Option) -> Self { NativeExecutor { _dummy: Default::default(), fallback: WasmExecutor::new(), native_version: D::native_version(), + default_heap_pages, } } } @@ -157,6 +161,7 @@ impl Clone for NativeExecutor { _dummy: Default::default(), fallback: self.fallback.clone(), native_version: D::native_version(), + default_heap_pages: self.default_heap_pages, } } } @@ -171,7 +176,8 @@ impl RuntimeInfo for NativeExecutor { ext: &mut E, ) -> Option { RUNTIMES_CACHE.with(|c| - fetch_cached_runtime_version(&self.fallback, &mut c.borrow_mut(), ext).ok()?.1.clone() + fetch_cached_runtime_version(&self.fallback, &mut c.borrow_mut(), ext, self.default_heap_pages) + .ok()?.1.clone() ) } } @@ -194,9 +200,10 @@ impl CodeExecutor for NativeExecutor (Result>, bool) { RUNTIMES_CACHE.with(|c| { let mut c = c.borrow_mut(); - let (module, onchain_version) = match fetch_cached_runtime_version(&self.fallback, &mut c, ext) { - Ok((module, onchain_version)) => (module, onchain_version), - Err(e) => return (Err(e), false), + let (module, onchain_version) = match fetch_cached_runtime_version( + &self.fallback, &mut c, ext, self.default_heap_pages) { + Ok((module, onchain_version)) => (module, onchain_version), + Err(e) => return (Err(e), false), }; match ( use_native, @@ -281,8 +288,8 @@ macro_rules! native_executor_instance { $version() } - fn new() -> $crate::NativeExecutor<$name> { - $crate::NativeExecutor::new() + fn new(default_heap_pages: Option) -> $crate::NativeExecutor<$name> { + $crate::NativeExecutor::new(default_heap_pages) } } } diff --git a/substrate/core/service/src/config.rs b/substrate/core/service/src/config.rs index 636b555617..fa02561dfe 100644 --- a/substrate/core/service/src/config.rs +++ b/substrate/core/service/src/config.rs @@ -67,6 +67,8 @@ pub struct Configuration { pub rpc_ws: Option, /// Telemetry service URL. `None` if disabled. pub telemetry_url: Option, + /// The default number of 64KB pages to allocate for Wasm execution + pub default_heap_pages: Option, } impl Configuration { @@ -92,6 +94,7 @@ impl Configuration { pub fn new_client(config: &FactoryFullConfiguration) -> Result>>, error::Error> { - let executor = NativeExecutor::new(); + let executor = NativeExecutor::new(config.default_heap_pages); let (client, _) = components::FullComponents::::build_client( config, executor, @@ -132,7 +132,7 @@ impl Service { let (signal, exit) = ::exit_future::signal(); // Create client - let executor = NativeExecutor::new(); + let executor = NativeExecutor::new(config.default_heap_pages); let mut keystore = Keystore::open(config.keystore_path.as_str().into())?; diff --git a/substrate/core/service/test/src/lib.rs b/substrate/core/service/test/src/lib.rs index 97ad89bcdb..db38fa142d 100644 --- a/substrate/core/service/test/src/lib.rs +++ b/substrate/core/service/test/src/lib.rs @@ -135,6 +135,7 @@ fn node_config ( rpc_http: None, rpc_ws: None, telemetry_url: None, + default_heap_pages: None, } } diff --git a/substrate/core/test-client/src/lib.rs b/substrate/core/test-client/src/lib.rs index eec5770fc1..fe5f8d4478 100644 --- a/substrate/core/test-client/src/lib.rs +++ b/substrate/core/test-client/src/lib.rs @@ -76,7 +76,7 @@ pub fn new_with_api_execution_strat( api_execution_strategy: ExecutionStrategy ) -> client::Client { let backend = Arc::new(Backend::new()); - let executor = NativeExecutor::new(); + let executor = NativeExecutor::new(None); let executor = LocalCallExecutor::new(backend.clone(), executor); client::Client::new( @@ -95,7 +95,7 @@ pub fn new_with_changes_trie() new_with_backend(Arc::new(Backend::new()), true) } -/// Creates new client instance used for tests with an explicitely provided backend. +/// Creates new client instance used for tests with an explicitly provided backend. /// This is useful for testing backend implementations. pub fn new_with_backend( backend: Arc, @@ -107,7 +107,7 @@ pub fn new_with_backend( runtime::RuntimeApi > where B: backend::LocalBackend { - let executor = NativeExecutor::new(); + let executor = NativeExecutor::new(None); client::new_with_backend(backend, executor, genesis_storage(support_changes_trie)).unwrap() } diff --git a/substrate/node/executor/src/lib.rs b/substrate/node/executor/src/lib.rs index d98a8f32cc..44fd6efa68 100644 --- a/substrate/node/executor/src/lib.rs +++ b/substrate/node/executor/src/lib.rs @@ -101,7 +101,7 @@ mod tests { } fn executor() -> ::substrate_executor::NativeExecutor { - ::substrate_executor::NativeExecutor::new() + ::substrate_executor::NativeExecutor::new(None) } #[test] @@ -729,7 +729,7 @@ mod tests { fn native_big_block_import_succeeds() { let mut t = new_test_ext(COMPACT_CODE, false); - Executor::new().call::<_, NeverNativeValue, fn() -> _>( + Executor::new(None).call::<_, NeverNativeValue, fn() -> _>( &mut t, "Core_execute_block", &block1big().0, @@ -743,7 +743,7 @@ mod tests { let mut t = new_test_ext(COMPACT_CODE, false); assert!( - Executor::new().call::<_, NeverNativeValue, fn() -> _>( + Executor::new(None).call::<_, NeverNativeValue, fn() -> _>( &mut t, "Core_execute_block", &block1big().0, @@ -805,7 +805,7 @@ mod tests { #[test] fn full_native_block_import_works_with_changes_trie() { let mut t = new_test_ext(COMPACT_CODE, true); - Executor::new().call::<_, NeverNativeValue, fn() -> _>( + Executor::new(None).call::<_, NeverNativeValue, fn() -> _>( &mut t, "Core_execute_block", &block1(true).0,