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

Add cli option --wasmtime-precompiled and subcommand precompile-wasm #1641

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d7b3887
add command PrecompileWasmCmd
librelois Sep 19, 2023
0616813
fmt
librelois Sep 20, 2023
f7705b6
Merge branch 'master' into elois-wasmtime-precompiled
librelois Sep 20, 2023
68e7765
fix tests & benches build
librelois Sep 20, 2023
6b122c3
fix rust compilation
librelois Sep 20, 2023
c56bffd
typo and rm unused import
librelois Sep 20, 2023
e0b1111
fix rust test
librelois Sep 21, 2023
50eac51
Merge branch 'master' into elois-wasmtime-precompiled
librelois Sep 21, 2023
2755221
enable wasm-precompiled feature in node-template
librelois Sep 27, 2023
0b26c2e
improve precompile-wasm subcommand: load the bytecode from chain spec
librelois Sep 27, 2023
5c038e0
Fix allow_missing_func_imports
crystalin Sep 28, 2023
85d5570
Changes genesis to use blake2hash for wasm hash
crystalin Sep 28, 2023
3bedb37
fmt
crystalin Sep 28, 2023
582c404
fmt
crystalin Sep 28, 2023
9f92b3c
more fmt
crystalin Sep 28, 2023
ac73de9
Merge branch 'master' into elois-wasmtime-precompiled
crystalin Sep 28, 2023
2da154a
Update substrate/client/executor/src/wasm_runtime.rs
RomarQ Nov 26, 2024
9e4abc7
Update substrate/client/executor/src/wasm_runtime.rs
RomarQ Nov 26, 2024
8061c87
fix: 🩹 Amend wasmtime precompiled PR review (#13)
ffarall Dec 4, 2024
fe0b4db
feat: 🔀 Merge upstream into wasmtime-precompile PR (#14)
ffarall Dec 5, 2024
635219c
Revert "feat: 🔀 Merge upstream into wasmtime-precompile PR (#14)"
RomarQ Dec 5, 2024
e3405e0
Merge branch 'master' into pr/1641
ffarall Dec 11, 2024
d420424
fix: :rotating_light: Compiler fixes after merge
ffarall Dec 12, 2024
d844373
feat: :sparkles: Add value parser to `output_dir` parameter in `preco…
ffarall Dec 12, 2024
9dbee39
feat: :sparkles: Add `precompile-wasm` subcommand to parachain template
ffarall Dec 12, 2024
11ede5c
style: :art: Apply `cargo fmt`
ffarall Dec 12, 2024
8e5f8ba
Merge branch 'master' into pr/1641
ffarall Dec 12, 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
6 changes: 6 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 8 additions & 3 deletions cumulus/parachain-template/node/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,18 @@ pub fn new_partial(
.default_heap_pages
.map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static { extra_pages: h as _ });

let wasm = WasmExecutor::builder()
let mut wasm_builder = WasmExecutor::builder()
.with_execution_method(config.wasm_method)
.with_onchain_heap_alloc_strategy(heap_pages)
.with_offchain_heap_alloc_strategy(heap_pages)
.with_max_runtime_instances(config.max_runtime_instances)
.with_runtime_cache_size(config.runtime_cache_size)
.build();
.with_runtime_cache_size(config.runtime_cache_size);

if let Some(ref wasmtime_precompiled_path) = config.wasmtime_precompiled {
wasm_builder = wasm_builder.with_wasmtime_precompiled_path(wasmtime_precompiled_path);
}

let wasm = wasm_builder.build();

let executor = ParachainExecutor::new_with_wasm_executor(wasm);

Expand Down
1 change: 1 addition & 0 deletions cumulus/test/service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,7 @@ pub fn node_config(
base_path,
informant_output_format: Default::default(),
wasm_runtime_overrides: None,
wasmtime_precompiled: None,
runtime_cache_size: 2,
})
}
Expand Down
2 changes: 1 addition & 1 deletion polkadot/node/core/pvf/prepare-worker/src/executor_intf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,5 @@ pub fn prepare(
) -> Result<Vec<u8>, sc_executor_common::error::WasmError> {
let semantics = params_to_wasmtime_semantics(executor_params)
.map_err(|e| sc_executor_common::error::WasmError::Other(e))?;
sc_executor_wasmtime::prepare_runtime_artifact(blob, &semantics)
sc_executor_wasmtime::prepare_runtime_artifact(blob, Default::default(), &semantics)
}
1 change: 1 addition & 0 deletions polkadot/node/test/service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ pub fn node_config(
instantiation_strategy: WasmtimeInstantiationStrategy::PoolingCopyOnWrite,
},
wasm_runtime_overrides: Default::default(),
wasmtime_precompiled: Default::default(),
rpc_addr: Default::default(),
rpc_max_request_size: Default::default(),
rpc_max_response_size: Default::default(),
Expand Down
3 changes: 3 additions & 0 deletions substrate/bin/node-template/node/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,7 @@ pub enum Subcommand {

/// Db meta columns information.
ChainInfo(sc_cli::ChainInfoCmd),

/// Precompile the WASM runtime into native code
PrecompileWasm(sc_cli::PrecompileWasmCmd),
}
8 changes: 8 additions & 0 deletions substrate/bin/node-template/node/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,14 @@ pub fn run() -> sc_cli::Result<()> {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run::<Block>(&config))
},
Some(Subcommand::PrecompileWasm(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { task_manager, backend, .. } =
service::new_partial(&config)?;
Ok((cmd.run(backend, config.chain_spec), task_manager))
})
},
None => {
let runner = cli.create_runner(&cli.run)?;
runner.run_node_until_exit(|config| async move {
Expand Down
1 change: 1 addition & 0 deletions substrate/bin/node/cli/benches/block_production.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase {
data_path: base_path.path().into(),
base_path,
informant_output_format: Default::default(),
wasmtime_precompiled: None,
wasm_runtime_overrides: None,
};

Expand Down
1 change: 1 addition & 0 deletions substrate/bin/node/cli/benches/transaction_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase {
data_path: base_path.path().into(),
base_path,
informant_output_format: Default::default(),
wasmtime_precompiled: None,
wasm_runtime_overrides: None,
};

Expand Down
3 changes: 3 additions & 0 deletions substrate/bin/node/cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,7 @@ pub enum Subcommand {

/// Db meta columns information.
ChainInfo(sc_cli::ChainInfoCmd),

/// Precompile the WASM runtime into native code
PrecompileWasm(sc_cli::PrecompileWasmCmd),
}
8 changes: 8 additions & 0 deletions substrate/bin/node/cli/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,5 +230,13 @@ pub fn run() -> Result<()> {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run::<Block>(&config))
},
Some(Subcommand::PrecompileWasm(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { task_manager, backend, .. } =
service::new_partial(&config)?;
Ok((cmd.run(backend), task_manager))
})
},
}
}
14 changes: 8 additions & 6 deletions substrate/client/chain-spec/src/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@

//! Tool for creating the genesis block.

use std::{collections::hash_map::DefaultHasher, marker::PhantomData, sync::Arc};
use std::{marker::PhantomData, sync::Arc};

use sc_client_api::{backend::Backend, BlockImportOperation};
use sc_executor::RuntimeVersionOf;
use sp_core::storage::{well_known_keys, StateVersion, Storage};
use sp_core::{
storage::{well_known_keys, StateVersion, Storage},
Blake2Hasher,
};

use sp_runtime::{
traits::{Block as BlockT, Hash as HashT, Header as HeaderT, Zero},
BuildStorage,
Expand All @@ -44,10 +48,8 @@ where
code_fetcher: &code_fetcher,
heap_pages: None,
hash: {
use std::hash::{Hash, Hasher};
let mut state = DefaultHasher::new();
wasm.hash(&mut state);
state.finish().to_le_bytes().to_vec()
use sp_core::Hasher;
Blake2Hasher::hash(&wasm.to_vec()).as_ref().to_vec()
},
};
let runtime_version = RuntimeVersionOf::runtime_version(executor, &mut ext, &runtime_code)
Expand Down
3 changes: 3 additions & 0 deletions substrate/client/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ tiny-bip39 = "1.0.0"
tokio = { version = "1.22.0", features = ["signal", "rt-multi-thread", "parking_lot"] }
sc-client-api = { path = "../api" }
sc-client-db = { path = "../db", default-features = false}
sc-executor = { path = "../executor" }
sc-keystore = { path = "../keystore" }
sc-network = { path = "../network" }
sc-service = { path = "../service", default-features = false}
Expand All @@ -44,6 +45,8 @@ sp-keyring = { path = "../../primitives/keyring" }
sp-keystore = { path = "../../primitives/keystore" }
sp-panic-handler = { path = "../../primitives/panic-handler" }
sp-runtime = { path = "../../primitives/runtime" }
sp-state-machine = { path = "../../primitives/state-machine" }
sp-storage = { path = "../../primitives/storage" }
sp-version = { path = "../../primitives/version" }

[dev-dependencies]
Expand Down
5 changes: 3 additions & 2 deletions substrate/client/cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ mod insert_key;
mod inspect_key;
mod inspect_node_key;
mod key;
mod precompile_wasm_cmd;
mod purge_chain_cmd;
mod revert_cmd;
mod run_cmd;
Expand All @@ -44,6 +45,6 @@ pub use self::{
export_blocks_cmd::ExportBlocksCmd, export_state_cmd::ExportStateCmd, generate::GenerateCmd,
generate_node_key::GenerateNodeKeyCmd, import_blocks_cmd::ImportBlocksCmd,
insert_key::InsertKeyCmd, inspect_key::InspectKeyCmd, inspect_node_key::InspectNodeKeyCmd,
key::KeySubcommand, purge_chain_cmd::PurgeChainCmd, revert_cmd::RevertCmd, run_cmd::RunCmd,
sign::SignCmd, vanity::VanityCmd, verify::VerifyCmd,
key::KeySubcommand, precompile_wasm_cmd::PrecompileWasmCmd, purge_chain_cmd::PurgeChainCmd,
revert_cmd::RevertCmd, run_cmd::RunCmd, sign::SignCmd, vanity::VanityCmd, verify::VerifyCmd,
};
145 changes: 145 additions & 0 deletions substrate/client/cli/src/commands/precompile_wasm_cmd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::{
arg_enums::{
execution_method_from_cli, WasmExecutionMethod, WasmtimeInstantiationStrategy,
DEFAULT_WASMTIME_INSTANTIATION_STRATEGY,
},
error::{self, Error},
params::{DatabaseParams, PruningParams, SharedParams},
CliConfiguration,
};

use clap::Parser;
use sc_client_api::{Backend, HeaderBackend};
use sc_executor::{
precompile_and_serialize_versioned_wasm_runtime, HeapAllocStrategy, DEFAULT_HEAP_ALLOC_PAGES,
};
use sc_service::ChainSpec;
use sp_core::traits::RuntimeCode;
use sp_runtime::traits::Block as BlockT;
use sp_state_machine::backend::BackendRuntimeCode;
use std::{fmt::Debug, path::PathBuf, sync::Arc};

/// The `precompile-wasm` command used to serialize a precompiled WASM module.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also mention which WASM is actually pre-compiled.

#[derive(Debug, Parser)]
pub struct PrecompileWasmCmd {
#[allow(missing_docs)]
#[clap(flatten)]
pub database_params: DatabaseParams,

/// The default number of 64KB pages to ever allocate for Wasm execution.
/// Don't alter this unless you know what you're doing.
#[arg(long, value_name = "COUNT")]
pub default_heap_pages: Option<u32>,

/// path to the directory where precompiled artifact will be written
#[arg()]
pub output_dir: PathBuf,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// The default number of 64KB pages to ever allocate for Wasm execution.
/// Don't alter this unless you know what you're doing.
#[arg(long, value_name = "COUNT")]
pub default_heap_pages: Option<u32>,
/// path to the directory where precompiled artifact will be written
#[arg()]
pub output_dir: PathBuf,
/// The default number of 64KB pages to ever allocate for Wasm execution.
///
/// Don't alter this unless you know what you're doing.
#[arg(long, value_name = "COUNT")]
pub default_heap_pages: Option<u32>,
/// Path to the directory where precompiled artifact will be written
#[arg()]
pub output_dir: PathBuf,


#[allow(missing_docs)]
#[clap(flatten)]
pub pruning_params: PruningParams,

#[allow(missing_docs)]
#[clap(flatten)]
pub shared_params: SharedParams,

/// The WASM instantiation method to use.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// The WASM instantiation method to use.
/// The WASM instantiation method to use.
///

/// Only has an effect when `wasm-execution` is set to `compiled`.
/// The copy-on-write strategies are only supported on Linux.
/// If the copy-on-write variant of a strategy is unsupported
/// the executor will fall back to the non-CoW equivalent.
/// The fastest (and the default) strategy available is `pooling-copy-on-write`.
/// The `legacy-instance-reuse` strategy is deprecated and will
/// be removed in the future. It should only be used in case of
/// issues with the default instantiation strategy.
#[arg(
long,
value_name = "STRATEGY",
default_value_t = DEFAULT_WASMTIME_INSTANTIATION_STRATEGY,
value_enum,
)]
pub wasmtime_instantiation_strategy: WasmtimeInstantiationStrategy,
}

impl PrecompileWasmCmd {
/// Run the precompile-wasm command
pub async fn run<B, BA>(&self, backend: Arc<BA>, spec: Box<dyn ChainSpec>) -> error::Result<()>
where
B: BlockT,
BA: Backend<B>,
{
let heap_pages = self.default_heap_pages.unwrap_or(DEFAULT_HEAP_ALLOC_PAGES);

let blockchain_info = backend.blockchain().info();

if backend.have_state_at(blockchain_info.finalized_hash, blockchain_info.finalized_number) {
let state = backend.state_at(backend.blockchain().info().finalized_hash)?;

precompile_and_serialize_versioned_wasm_runtime(
HeapAllocStrategy::Static { extra_pages: heap_pages },
&BackendRuntimeCode::new(&state).runtime_code()?,
execution_method_from_cli(
WasmExecutionMethod::Compiled,
self.wasmtime_instantiation_strategy,
),
&self.output_dir,
)
.map_err(|e| Error::Application(Box::new(e)))?;
} else {
let storage = spec.as_storage_builder().build_storage()?;
if let Some(wasm_bytecode) = storage.top.get(sp_storage::well_known_keys::CODE) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If CODE does not exist, there should be an error.

let runtime_code = RuntimeCode {
code_fetcher: &sp_core::traits::WrappedRuntimeCode(
wasm_bytecode.as_slice().into(),
),
hash: sp_core::blake2_256(&wasm_bytecode).to_vec(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
hash: sp_core::blake2_256(&wasm_bytecode).to_vec(),
hash: B::Hasher::hash(&wasm_bytecode).to_vec(),

The hash depends on the configured hasher.

heap_pages: Some(heap_pages as u64),
};
precompile_and_serialize_versioned_wasm_runtime(
HeapAllocStrategy::Static { extra_pages: heap_pages },
&runtime_code,
execution_method_from_cli(
WasmExecutionMethod::Compiled,
self.wasmtime_instantiation_strategy,
),
&self.output_dir,
)
.map_err(|e| Error::Application(Box::new(e)))?;
}
}

Ok(())
}
}

impl CliConfiguration for PrecompileWasmCmd {
fn shared_params(&self) -> &SharedParams {
&self.shared_params
}

fn pruning_params(&self) -> Option<&PruningParams> {
Some(&self.pruning_params)
}

fn database_params(&self) -> Option<&DatabaseParams> {
Some(&self.database_params)
}
}
8 changes: 8 additions & 0 deletions substrate/client/cli/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,13 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
Ok(self.import_params().map(|x| x.wasm_method()).unwrap_or_default())
}

/// Get the path where WASM precompiled artifacts live.
///
/// By default this is `None`.
fn wasmtime_precompiled(&self) -> Option<PathBuf> {
self.import_params().map(|x| x.wasmtime_precompiled()).unwrap_or_default()
}

/// Get the path where WASM overrides live.
///
/// By default this is `None`.
Expand Down Expand Up @@ -491,6 +498,7 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
state_pruning: self.state_pruning()?,
blocks_pruning: self.blocks_pruning()?,
wasm_method: self.wasm_method()?,
wasmtime_precompiled: self.wasmtime_precompiled(),
wasm_runtime_overrides: self.wasm_runtime_overrides(),
rpc_addr: self.rpc_addr(DCV::rpc_listen_port())?,
rpc_methods: self.rpc_methods()?,
Expand Down
Loading
Loading