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

Commit b8d7dd5

Browse files
authored
wasm-builder: Enforce runtime_version wasm section (#14228)
* wasm-builder: Enforce `runtime_version` wasm section This pr changes the `wasm-builder` to enforce the `runtime_version` wasm section. This wasm section is being created by the `sp_version::runtime_version` attribute macro. This attribute macro now exists since quite some time and `runtime_version` also is the only way for parachains to support reading the `RuntimeVersion` from the runtime. \# Disabling the check By default the `WasmBuilder` will now check for this wasm section and if not found, exit with an error. However, there are situations where you may want to disable this check (like for tests). In this case there exists the `disable_runtime_version_section_check` function. ``` WasmBuilder::new() ... ... ... .disable_runtime_version_section_check() .build() ``` By using this method you get back the old behavior. * Review comment * Fix * Fix issue with `enum-as-inner`
1 parent eddd133 commit b8d7dd5

File tree

8 files changed

+62
-3
lines changed

8 files changed

+62
-3
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bin/node-template/node/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ node-template-runtime = { version = "4.0.0-dev", path = "../runtime" }
6666
# CLI-specific dependencies
6767
try-runtime-cli = { version = "0.10.0-dev", optional = true, path = "../../../utils/frame/try-runtime/cli" }
6868

69+
# Workaround until https://github.com/bluejekyll/enum-as-inner/issues/98 is fixed.
70+
enum-as-inner = "=0.5.1"
71+
6972
[build-dependencies]
7073
substrate-build-script-utils = { version = "3.0.0", path = "../../../utils/build-script-utils" }
7174

client/executor/runtime-test/build.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ fn main() {
2424
.with_current_project()
2525
.export_heap_base()
2626
.import_memory()
27+
.disable_runtime_version_section_check()
2728
.build();
2829
}
2930

@@ -36,6 +37,7 @@ fn main() {
3637
.import_memory()
3738
.set_file_name("wasm_binary_with_tracing.rs")
3839
.append_to_rust_flags(r#"--cfg feature="with-tracing""#)
40+
.disable_runtime_version_section_check()
3941
.build();
4042
}
4143
}

primitives/runtime-interface/test-wasm-deprecated/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ fn main() {
2222
.with_current_project()
2323
.export_heap_base()
2424
.import_memory()
25+
.disable_runtime_version_section_check()
2526
.build();
2627
}
2728
}

primitives/runtime-interface/test-wasm/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ fn main() {
2222
.with_current_project()
2323
.export_heap_base()
2424
.import_memory()
25+
.disable_runtime_version_section_check()
2526
.build();
2627
}
2728
}

utils/wasm-builder/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,5 @@ toml = "0.7.3"
2222
walkdir = "2.3.2"
2323
sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../primitives/maybe-compressed-blob" }
2424
filetime = "0.2.16"
25-
wasm-opt = "0.112"
25+
wasm-opt = "0.112"
26+
parity-wasm = "0.45"

utils/wasm-builder/src/builder.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ impl WasmBuilderSelectProject {
4848
file_name: None,
4949
project_cargo_toml: get_manifest_dir().join("Cargo.toml"),
5050
features_to_enable: Vec::new(),
51+
disable_runtime_version_section_check: false,
5152
}
5253
}
5354

@@ -63,6 +64,7 @@ impl WasmBuilderSelectProject {
6364
file_name: None,
6465
project_cargo_toml: path,
6566
features_to_enable: Vec::new(),
67+
disable_runtime_version_section_check: false,
6668
})
6769
} else {
6870
Err("Project path must point to the `Cargo.toml` of the project")
@@ -93,6 +95,8 @@ pub struct WasmBuilder {
9395
project_cargo_toml: PathBuf,
9496
/// Features that should be enabled when building the wasm binary.
9597
features_to_enable: Vec<String>,
98+
/// Should the builder not check that the `runtime_version` section exists in the wasm binary?
99+
disable_runtime_version_section_check: bool,
96100
}
97101

98102
impl WasmBuilder {
@@ -143,6 +147,17 @@ impl WasmBuilder {
143147
self
144148
}
145149

150+
/// Disable the check for the `runtime_version` wasm section.
151+
///
152+
/// By default the `wasm-builder` will ensure that the `runtime_version` section will
153+
/// exists in the build wasm binary. This `runtime_version` section is used to get the
154+
/// `RuntimeVersion` without needing to call into the wasm binary. However, for some
155+
/// use cases (like tests) you may want to disable this check.
156+
pub fn disable_runtime_version_section_check(mut self) -> Self {
157+
self.disable_runtime_version_section_check = true;
158+
self
159+
}
160+
146161
/// Build the WASM binary.
147162
pub fn build(self) {
148163
let out_dir = PathBuf::from(env::var("OUT_DIR").expect("`OUT_DIR` is set by cargo!"));
@@ -165,6 +180,7 @@ impl WasmBuilder {
165180
self.rust_flags.into_iter().map(|f| format!("{} ", f)).collect(),
166181
self.features_to_enable,
167182
self.file_name,
183+
!self.disable_runtime_version_section_check,
168184
);
169185

170186
// 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() {
215231
/// The current project is determined by using the `CARGO_MANIFEST_DIR` environment variable.
216232
///
217233
/// `file_name` - The name + path of the file being generated. The file contains the
218-
/// constant `WASM_BINARY`, which contains the built WASM binary.
234+
/// constant `WASM_BINARY`, which contains the built wasm binary.
219235
///
220236
/// `project_cargo_toml` - The path to the `Cargo.toml` of the project that should be built.
221237
///
@@ -224,14 +240,17 @@ fn generate_rerun_if_changed_instructions() {
224240
/// `features_to_enable` - Features that should be enabled for the project.
225241
///
226242
/// `wasm_binary_name` - The optional wasm binary name that is extended with
227-
///
228243
/// `.compact.compressed.wasm`. If `None`, the project name will be used.
244+
///
245+
/// `check_for_runtime_version_section` - Should the wasm binary be checked for the
246+
/// `runtime_version` section?
229247
fn build_project(
230248
file_name: PathBuf,
231249
project_cargo_toml: PathBuf,
232250
default_rustflags: String,
233251
features_to_enable: Vec<String>,
234252
wasm_binary_name: Option<String>,
253+
check_for_runtime_version_section: bool,
235254
) {
236255
let cargo_cmd = match crate::prerequisites::check() {
237256
Ok(cmd) => cmd,
@@ -247,6 +266,7 @@ fn build_project(
247266
cargo_cmd,
248267
features_to_enable,
249268
wasm_binary_name,
269+
check_for_runtime_version_section,
250270
);
251271

252272
let (wasm_binary, wasm_binary_bloaty) = if let Some(wasm_binary) = wasm_binary {

utils/wasm-builder/src/wasm_project.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::{write_file_if_changed, CargoCommandVersioned, OFFLINE};
1919

2020
use build_helper::rerun_if_changed;
2121
use cargo_metadata::{CargoOpt, Metadata, MetadataCommand};
22+
use parity_wasm::elements::{deserialize_buffer, Module};
2223
use std::{
2324
borrow::ToOwned,
2425
collections::HashSet,
@@ -116,6 +117,7 @@ pub(crate) fn create_and_compile(
116117
cargo_cmd: CargoCommandVersioned,
117118
features_to_enable: Vec<String>,
118119
wasm_binary_name: Option<String>,
120+
check_for_runtime_version_section: bool,
119121
) -> (Option<WasmBinary>, WasmBinaryBloaty) {
120122
let wasm_workspace_root = get_wasm_workspace_root();
121123
let wasm_workspace = wasm_workspace_root.join("wbuild");
@@ -134,6 +136,10 @@ pub(crate) fn create_and_compile(
134136
let (wasm_binary, wasm_binary_compressed, bloaty) =
135137
compact_wasm_file(&project, profile, project_cargo_toml, wasm_binary_name);
136138

139+
if check_for_runtime_version_section {
140+
ensure_runtime_version_wasm_section_exists(bloaty.wasm_binary_bloaty_path());
141+
}
142+
137143
wasm_binary
138144
.as_ref()
139145
.map(|wasm_binary| copy_wasm_to_target_directory(project_cargo_toml, wasm_binary));
@@ -159,6 +165,29 @@ pub(crate) fn create_and_compile(
159165
(final_wasm_binary, bloaty)
160166
}
161167

168+
/// Ensures that the `runtime_version` wasm section exists in the given wasm file.
169+
///
170+
/// If the section can not be found, it will print an error and exit the builder.
171+
fn ensure_runtime_version_wasm_section_exists(wasm: &Path) {
172+
let wasm_blob = fs::read(wasm).expect("`{wasm}` was just written and should exist; qed");
173+
174+
let module: Module = match deserialize_buffer(&wasm_blob) {
175+
Ok(m) => m,
176+
Err(e) => {
177+
println!("Failed to deserialize `{}`: {e:?}", wasm.display());
178+
process::exit(1);
179+
},
180+
};
181+
182+
if !module.custom_sections().any(|cs| cs.name() == "runtime_version") {
183+
println!(
184+
"Couldn't find the `runtime_version` wasm section. \
185+
Please ensure that you are using the `sp_version::runtime_version` attribute macro!"
186+
);
187+
process::exit(1);
188+
}
189+
}
190+
162191
/// Adjust the mtime of the bloaty and compressed/compact wasm files.
163192
///
164193
/// We add the bloaty and the compressed/compact wasm file to the `rerun-if-changed` files.

0 commit comments

Comments
 (0)