-
Notifications
You must be signed in to change notification settings - Fork 72
Description
Issue description
To locate the produced WASM runtime artifact, the custom build.rs recursively scans the target directory and picks the last filename matching the <pkg_name>.wasm format (link). This approach is non deterministic as stale build artifacts could be picked. Furthermore, fs::read_dir order can change between calls, causing different results over multiple runs.
Risk
This issue could result in different runtimes to be run by Serai nodes, potentially causing behavioral differences.
Mitigation
Determine the exact output path of the produced WASM runtime. We would recommend the second approach mentioned in the comments above the code. Pass --message-format=json to the build command and then parse the output, even if this would require a JSON parser build dependency.
Example code of how to deterministically find the WASM artifact:
let file = cargo_env("CARGO_PKG_NAME").replace('-', "_") + ".wasm";
let mut artifacts = HashSet::<PathBuf>::new();
for line in stdout.lines() {
let line = line.expect("failed to read line from `cargo` JSON stdout");
let Ok(json) = serde_json::from_str::<serde_json::Value>(&line) else {
continue;
};
if json.get("reason").and_then(|r| r.as_str()) != Some("compiler-artifact") {
continue;
}
let Some(filenames) = json.get("filenames").and_then(|f| f.as_array()) else {
continue;
};
for filename in filenames {
let Some(filename) = filename.as_str() else { continue };
let path = PathBuf::from(filename);
if path.file_name().and_then(|n| n.to_str()) == Some(file.as_str()) {
artifacts.insert(path);
}
}
}
assert!(!artifacts.is_empty(), "nested build succeeded but did not emit a `{file}` artifact");
assert_eq!(
artifacts.len(),
1,
"nested build emitted multiple `{file}` artifacts: {artifacts:?}"
);
let artifact = artifacts.into_iter().next().unwrap();