diff --git a/Cargo.lock b/Cargo.lock index 4fedf32835187..b0ec498ce3b99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5427,6 +5427,7 @@ name = "node-template" version = "4.0.0-dev" dependencies = [ "clap 4.2.7", + "enum-as-inner", "frame-benchmarking", "frame-benchmarking-cli", "frame-system", @@ -11881,6 +11882,7 @@ dependencies = [ "build-helper", "cargo_metadata", "filetime", + "parity-wasm", "sp-maybe-compressed-blob", "strum", "tempfile", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 1801caad676ab..ceac4fa8db1cd 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -66,6 +66,9 @@ node-template-runtime = { version = "4.0.0-dev", path = "../runtime" } # CLI-specific dependencies try-runtime-cli = { version = "0.10.0-dev", optional = true, path = "../../../utils/frame/try-runtime/cli" } +# Workaround until https://github.com/bluejekyll/enum-as-inner/issues/98 is fixed. +enum-as-inner = "=0.5.1" + [build-dependencies] substrate-build-script-utils = { version = "3.0.0", path = "../../../utils/build-script-utils" } diff --git a/client/executor/runtime-test/build.rs b/client/executor/runtime-test/build.rs index 745742123a8f6..088c93110d855 100644 --- a/client/executor/runtime-test/build.rs +++ b/client/executor/runtime-test/build.rs @@ -24,6 +24,7 @@ fn main() { .with_current_project() .export_heap_base() .import_memory() + .disable_runtime_version_section_check() .build(); } @@ -36,6 +37,7 @@ fn main() { .import_memory() .set_file_name("wasm_binary_with_tracing.rs") .append_to_rust_flags(r#"--cfg feature="with-tracing""#) + .disable_runtime_version_section_check() .build(); } } diff --git a/primitives/runtime-interface/test-wasm-deprecated/build.rs b/primitives/runtime-interface/test-wasm-deprecated/build.rs index b7676a70dfe84..651f57388e0d0 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/build.rs +++ b/primitives/runtime-interface/test-wasm-deprecated/build.rs @@ -22,6 +22,7 @@ fn main() { .with_current_project() .export_heap_base() .import_memory() + .disable_runtime_version_section_check() .build(); } } diff --git a/primitives/runtime-interface/test-wasm/build.rs b/primitives/runtime-interface/test-wasm/build.rs index b7676a70dfe84..651f57388e0d0 100644 --- a/primitives/runtime-interface/test-wasm/build.rs +++ b/primitives/runtime-interface/test-wasm/build.rs @@ -22,6 +22,7 @@ fn main() { .with_current_project() .export_heap_base() .import_memory() + .disable_runtime_version_section_check() .build(); } } diff --git a/utils/wasm-builder/Cargo.toml b/utils/wasm-builder/Cargo.toml index 5228f26d57c6d..79ff4d19ac675 100644 --- a/utils/wasm-builder/Cargo.toml +++ b/utils/wasm-builder/Cargo.toml @@ -22,4 +22,5 @@ toml = "0.7.3" walkdir = "2.3.2" sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../primitives/maybe-compressed-blob" } filetime = "0.2.16" -wasm-opt = "0.112" \ No newline at end of file +wasm-opt = "0.112" +parity-wasm = "0.45" diff --git a/utils/wasm-builder/src/builder.rs b/utils/wasm-builder/src/builder.rs index 72d32445e8da5..d0bed8d22a036 100644 --- a/utils/wasm-builder/src/builder.rs +++ b/utils/wasm-builder/src/builder.rs @@ -48,6 +48,7 @@ impl WasmBuilderSelectProject { file_name: None, project_cargo_toml: get_manifest_dir().join("Cargo.toml"), features_to_enable: Vec::new(), + disable_runtime_version_section_check: false, } } @@ -63,6 +64,7 @@ impl WasmBuilderSelectProject { file_name: None, project_cargo_toml: path, features_to_enable: Vec::new(), + disable_runtime_version_section_check: false, }) } else { Err("Project path must point to the `Cargo.toml` of the project") @@ -93,6 +95,8 @@ pub struct WasmBuilder { project_cargo_toml: PathBuf, /// Features that should be enabled when building the wasm binary. features_to_enable: Vec, + /// Should the builder not check that the `runtime_version` section exists in the wasm binary? + disable_runtime_version_section_check: bool, } impl WasmBuilder { @@ -143,6 +147,17 @@ impl WasmBuilder { self } + /// Disable the check for the `runtime_version` wasm section. + /// + /// By default the `wasm-builder` will ensure that the `runtime_version` section will + /// exists in the build wasm binary. This `runtime_version` section is used to get the + /// `RuntimeVersion` without needing to call into the wasm binary. However, for some + /// use cases (like tests) you may want to disable this check. + pub fn disable_runtime_version_section_check(mut self) -> Self { + self.disable_runtime_version_section_check = true; + self + } + /// Build the WASM binary. pub fn build(self) { let out_dir = PathBuf::from(env::var("OUT_DIR").expect("`OUT_DIR` is set by cargo!")); @@ -165,6 +180,7 @@ impl WasmBuilder { self.rust_flags.into_iter().map(|f| format!("{} ", f)).collect(), self.features_to_enable, self.file_name, + !self.disable_runtime_version_section_check, ); // As last step we need to generate our `rerun-if-changed` stuff. If a build fails, we don't @@ -215,7 +231,7 @@ fn generate_rerun_if_changed_instructions() { /// The current project is determined by using the `CARGO_MANIFEST_DIR` environment variable. /// /// `file_name` - The name + path of the file being generated. The file contains the -/// constant `WASM_BINARY`, which contains the built WASM binary. +/// constant `WASM_BINARY`, which contains the built wasm binary. /// /// `project_cargo_toml` - The path to the `Cargo.toml` of the project that should be built. /// @@ -224,14 +240,17 @@ fn generate_rerun_if_changed_instructions() { /// `features_to_enable` - Features that should be enabled for the project. /// /// `wasm_binary_name` - The optional wasm binary name that is extended with -/// /// `.compact.compressed.wasm`. If `None`, the project name will be used. +/// +/// `check_for_runtime_version_section` - Should the wasm binary be checked for the +/// `runtime_version` section? fn build_project( file_name: PathBuf, project_cargo_toml: PathBuf, default_rustflags: String, features_to_enable: Vec, wasm_binary_name: Option, + check_for_runtime_version_section: bool, ) { let cargo_cmd = match crate::prerequisites::check() { Ok(cmd) => cmd, @@ -247,6 +266,7 @@ fn build_project( cargo_cmd, features_to_enable, wasm_binary_name, + check_for_runtime_version_section, ); let (wasm_binary, wasm_binary_bloaty) = if let Some(wasm_binary) = wasm_binary { diff --git a/utils/wasm-builder/src/wasm_project.rs b/utils/wasm-builder/src/wasm_project.rs index c45a40a6b9202..849af853c6da4 100644 --- a/utils/wasm-builder/src/wasm_project.rs +++ b/utils/wasm-builder/src/wasm_project.rs @@ -19,6 +19,7 @@ use crate::{write_file_if_changed, CargoCommandVersioned, OFFLINE}; use build_helper::rerun_if_changed; use cargo_metadata::{CargoOpt, Metadata, MetadataCommand}; +use parity_wasm::elements::{deserialize_buffer, Module}; use std::{ borrow::ToOwned, collections::HashSet, @@ -116,6 +117,7 @@ pub(crate) fn create_and_compile( cargo_cmd: CargoCommandVersioned, features_to_enable: Vec, wasm_binary_name: Option, + check_for_runtime_version_section: bool, ) -> (Option, WasmBinaryBloaty) { let wasm_workspace_root = get_wasm_workspace_root(); let wasm_workspace = wasm_workspace_root.join("wbuild"); @@ -134,6 +136,10 @@ pub(crate) fn create_and_compile( let (wasm_binary, wasm_binary_compressed, bloaty) = compact_wasm_file(&project, profile, project_cargo_toml, wasm_binary_name); + if check_for_runtime_version_section { + ensure_runtime_version_wasm_section_exists(bloaty.wasm_binary_bloaty_path()); + } + wasm_binary .as_ref() .map(|wasm_binary| copy_wasm_to_target_directory(project_cargo_toml, wasm_binary)); @@ -159,6 +165,29 @@ pub(crate) fn create_and_compile( (final_wasm_binary, bloaty) } +/// Ensures that the `runtime_version` wasm section exists in the given wasm file. +/// +/// If the section can not be found, it will print an error and exit the builder. +fn ensure_runtime_version_wasm_section_exists(wasm: &Path) { + let wasm_blob = fs::read(wasm).expect("`{wasm}` was just written and should exist; qed"); + + let module: Module = match deserialize_buffer(&wasm_blob) { + Ok(m) => m, + Err(e) => { + println!("Failed to deserialize `{}`: {e:?}", wasm.display()); + process::exit(1); + }, + }; + + if !module.custom_sections().any(|cs| cs.name() == "runtime_version") { + println!( + "Couldn't find the `runtime_version` wasm section. \ + Please ensure that you are using the `sp_version::runtime_version` attribute macro!" + ); + process::exit(1); + } +} + /// Adjust the mtime of the bloaty and compressed/compact wasm files. /// /// We add the bloaty and the compressed/compact wasm file to the `rerun-if-changed` files.