polkadot_node_core_pvf/
testing.rs1pub use crate::{
20 host::{EXECUTE_BINARY_NAME, PREPARE_BINARY_NAME},
21 worker_interface::{spawn_with_program_path, SpawnErr},
22};
23
24use crate::{artifacts::ArtifactId, get_worker_version};
25use is_executable::IsExecutable;
26use polkadot_node_core_pvf_common::pvf::PvfPrepData;
27use polkadot_node_primitives::NODE_VERSION;
28use polkadot_primitives::ExecutorParams;
29use std::{
30 path::PathBuf,
31 sync::{Mutex, OnceLock},
32};
33
34pub fn validate_candidate(
37 code: &[u8],
38 params: &[u8],
39) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
40 use polkadot_node_core_pvf_common::executor_interface::{prepare, prevalidate};
41 use polkadot_node_core_pvf_execute_worker::execute_artifact;
42
43 let code = sp_maybe_compressed_blob::decompress(code, 10 * 1024 * 1024)
44 .expect("Decompressing code failed");
45
46 let blob = prevalidate(&code)?;
47 let executor_params = ExecutorParams::default();
48 let compiled_artifact_blob = prepare(blob, &executor_params)?;
49
50 let result = unsafe {
51 execute_artifact(&compiled_artifact_blob, &executor_params, params)?
54 };
55
56 Ok(result)
57}
58
59pub fn build_workers_and_get_paths() -> (PathBuf, PathBuf) {
64 static WORKER_PATHS: OnceLock<Mutex<(PathBuf, PathBuf)>> = OnceLock::new();
66
67 fn build_workers() {
68 let mut build_args = vec![
69 "build",
70 "--package=polkadot",
71 "--bin=polkadot-prepare-worker",
72 "--bin=polkadot-execute-worker",
73 ];
74
75 if cfg!(build_profile = "release") {
76 build_args.push("--release");
77 }
78
79 let mut cargo = std::process::Command::new("cargo");
80 let cmd = cargo
81 .env("SKIP_WASM_BUILD", "1")
83 .args(build_args)
84 .stdout(std::process::Stdio::piped());
85
86 println!("INFO: calling `{cmd:?}`");
87 let exit_status = cmd.status().expect("Failed to run the build program");
88
89 if !exit_status.success() {
90 eprintln!("ERROR: Failed to build workers: {}", exit_status.code().unwrap());
91 std::process::exit(1);
92 }
93 }
94
95 let mutex = WORKER_PATHS.get_or_init(|| {
96 let mut workers_path = std::env::current_exe().unwrap();
97 workers_path.pop();
98 workers_path.pop();
99 let mut prepare_worker_path = workers_path.clone();
100 prepare_worker_path.push(PREPARE_BINARY_NAME);
101 let mut execute_worker_path = workers_path.clone();
102 execute_worker_path.push(EXECUTE_BINARY_NAME);
103
104 if !prepare_worker_path.is_executable() {
106 println!("WARN: Prepare worker does not exist or is not executable. Workers directory: {:?}", workers_path);
107 }
108 if !execute_worker_path.is_executable() {
109 println!("WARN: Execute worker does not exist or is not executable. Workers directory: {:?}", workers_path);
110 }
111 if let Ok(ver) = get_worker_version(&prepare_worker_path) {
112 if ver != NODE_VERSION {
113 println!("WARN: Prepare worker version {ver} does not match node version {NODE_VERSION}; worker path: {prepare_worker_path:?}");
114 }
115 }
116 if let Ok(ver) = get_worker_version(&execute_worker_path) {
117 if ver != NODE_VERSION {
118 println!("WARN: Execute worker version {ver} does not match node version {NODE_VERSION}; worker path: {execute_worker_path:?}");
119 }
120 }
121
122 build_workers();
123
124 Mutex::new((prepare_worker_path, execute_worker_path))
125 });
126
127 let guard = mutex.lock().unwrap();
128 (guard.0.clone(), guard.1.clone())
129}
130
131pub fn artifact_id(discriminator: u32) -> ArtifactId {
133 ArtifactId::from_pvf_prep_data(&PvfPrepData::from_discriminator(discriminator))
134}