diff --git a/Cargo.lock b/Cargo.lock index 8ac27c4b..c9308368 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1445,38 +1445,6 @@ dependencies = [ name = "c-kzg" version = "2.99.99" -[[package]] -name = "camino" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" -dependencies = [ - "serde_core", -] - -[[package]] -name = "cargo-platform" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", - "thiserror 2.0.17", -] - [[package]] name = "cc" version = "1.2.48" @@ -7080,15 +7048,6 @@ dependencies = [ "bytemuck", ] -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - [[package]] name = "sc-allocator" version = "34.0.0" @@ -8096,10 +8055,6 @@ name = "semver" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" -dependencies = [ - "serde", - "serde_core", -] [[package]] name = "serai-abi" @@ -9033,7 +8988,6 @@ dependencies = [ "sp-timestamp", "sp-transaction-pool", "sp-version", - "substrate-wasm-builder", ] [[package]] @@ -10117,22 +10071,6 @@ dependencies = [ "thiserror 2.0.17", ] -[[package]] -name = "substrate-wasm-builder" -version = "29.0.0" -source = "git+https://github.com/serai-dex/patch-polkadot-sdk#0cd66846e58f167b09b48a77c3f70bf7b2b67000" -dependencies = [ - "cargo_metadata", - "console", - "jobserver", - "parity-wasm", - "shlex", - "strum 0.27.2", - "tempfile", - "toml 0.9.8", - "walkdir", -] - [[package]] name = "subtle" version = "2.6.1" @@ -10874,16 +10812,6 @@ dependencies = [ "libc", ] -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - [[package]] name = "want" version = "0.3.1" diff --git a/orchestration/runtime/Dockerfile b/orchestration/runtime/Dockerfile index 084b55ba..a1aae19d 100644 --- a/orchestration/runtime/Dockerfile +++ b/orchestration/runtime/Dockerfile @@ -37,6 +37,6 @@ COPY --from=builder /bin/busybox /bin/ ENV LD_LIBRARY_PATH=/lib/ ENV PATH=/bin # Copy the artifact itself -COPY --from=builder /serai/target/release/wbuild/serai-runtime/serai_runtime.wasm /serai.wasm +COPY --from=builder /serai/target/release/serai_runtime.wasm /serai.wasm # By default, copy the artifact to `/volume`, presumably a provided volume CMD ["busybox", "cp", "/serai.wasm", "/volume/serai.wasm"] diff --git a/substrate/node/src/chain_spec.rs b/substrate/node/src/chain_spec.rs index 9506b4ad..216d92ab 100644 --- a/substrate/node/src/chain_spec.rs +++ b/substrate/node/src/chain_spec.rs @@ -74,7 +74,7 @@ fn wasm_binary(dev: bool) -> Vec { } log::info!("using built-in wasm"); - serai_runtime::WASM_BINARY.ok_or("compiled in wasm not available").unwrap().to_vec() + serai_runtime::WASM.to_vec() } fn devnet_genesis(validators: &[&'static str], endowed_accounts: Vec) -> GenesisConfig { diff --git a/substrate/node/src/service/mod.rs b/substrate/node/src/service/mod.rs index 38288074..b3b22c07 100644 --- a/substrate/node/src/service/mod.rs +++ b/substrate/node/src/service/mod.rs @@ -6,7 +6,7 @@ use sp_timestamp::InherentDataProvider as TimestampInherent; use sp_consensus_babe::{SlotDuration, inherents::InherentDataProvider as BabeInherent}; use sp_io::SubstrateHostFunctions; -use sc_executor::{sp_wasm_interface::ExtendedHostFunctions, WasmExecutor}; +use sc_executor::{sp_wasm_interface::ExtendedHostFunctions, HeapAllocStrategy, WasmExecutor}; use sc_network::{Event, NetworkEventStream, NetworkBackend}; use sc_service::{error::Error as ServiceError, Configuration, TaskManager, TFullClient}; @@ -99,14 +99,13 @@ pub fn new_partial( }) .transpose()?; - #[allow(deprecated)] - let executor = Executor::new( - config.executor.wasm_method, - config.executor.default_heap_pages, - config.executor.max_runtime_instances, - None, - config.executor.runtime_cache_size, - ); + let executor = Executor::builder() + .with_execution_method(config.executor.wasm_method) + .with_onchain_heap_alloc_strategy(HeapAllocStrategy::Dynamic { maximum_pages: None }) + .with_offchain_heap_alloc_strategy(HeapAllocStrategy::Dynamic { maximum_pages: None }) + .with_max_runtime_instances(config.executor.max_runtime_instances) + .with_runtime_cache_size(config.executor.runtime_cache_size) + .build(); let (client, backend, keystore_container, task_manager) = { let telemetry = telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()); diff --git a/substrate/runtime/Cargo.toml b/substrate/runtime/Cargo.toml index d404f3c4..0b10a0a8 100644 --- a/substrate/runtime/Cargo.toml +++ b/substrate/runtime/Cargo.toml @@ -70,9 +70,6 @@ serai-dex-pallet = { path = "../dex", default-features = false } serai-genesis-liquidity-pallet = { path = "../genesis-liquidity", default-features = false } serai-in-instructions-pallet = { path = "../in-instructions", default-features = false } -[build-dependencies] -substrate-wasm-builder = { git = "https://github.com/serai-dex/patch-polkadot-sdk" } - [features] std = [ "scale/std", diff --git a/substrate/runtime/build.rs b/substrate/runtime/build.rs index 71bee10e..f1f72c9b 100644 --- a/substrate/runtime/build.rs +++ b/substrate/runtime/build.rs @@ -1,4 +1,90 @@ fn main() { - #[cfg(not(target_family = "wasm"))] - substrate_wasm_builder::WasmBuilder::build_using_defaults(); + use std::{path::PathBuf, fs, env, process::Command}; + + // Prevent recursing infinitely + if env::var("TARGET").unwrap() == "wasm32v1-none" { + return; + } + + // https://github.com/rust-lang/rust/issues/145491 + const ONE_45491: &str = "-C link-arg=--mllvm=-mcpu=mvp,--mllvm=-mattr=+mutable-globals"; + const WASM: &str = "-C link-arg=--export-table"; + const REQUIRED_BY_SUBSTRATE: &str = "--cfg substrate_runtime -C link-arg=--import-memory"; + const SAFETY: &str = "-C overflow-checks=true -C panic=abort"; + const COMPILATION: &str = + "-C symbol-mangling-version=v0 -C embed-bitcode=false -C linker-plugin-lto=true"; + + let profile = env::var("PROFILE").unwrap(); + let release = profile == "release"; + let rustflags = format!("{ONE_45491} {WASM} {REQUIRED_BY_SUBSTRATE} {SAFETY} {COMPILATION}"); + let rustflags = if release { + format!("{rustflags} -C codegen-units=1 -C strip=symbols -C debug-assertions=false") + } else { + rustflags + }; + + let target_dir = PathBuf::from(env::var("OUT_DIR").unwrap()).join("target"); + + let cargo_command = || { + let cargo = env::var("CARGO").unwrap(); + let mut command = Command::new(&cargo); + command + .current_dir(env::var("CARGO_MANIFEST_DIR").unwrap()) + .env_clear() + .env("PATH", env::var("PATH").unwrap()) + .env("CARGO", cargo) + .env("RUSTC", env::var("RUSTC").unwrap()) + .env("RUSTFLAGS", &rustflags) + .env("CARGO_TARGET_DIR", &target_dir); + command + }; + + let workspace = { + let workspace = cargo_command() + .arg("locate-project") + .arg("--workspace") + .arg("--message-format") + .arg("plain") + .output() + .unwrap(); + assert!(workspace.status.success()); + let mut workspace = PathBuf::from(String::from_utf8(workspace.stdout).unwrap().trim()); + assert_eq!(workspace.file_name().unwrap(), "Cargo.toml"); + assert!(workspace.pop()); + workspace + }; + + // Re-run anytime the workspace changes + // TODO: Re-run anytime `Cargo.lock` or specifically the `src` folders change + println!("cargo::rerun-if-changed={}", workspace.display()); + + let mut command = cargo_command(); + command + .arg("rustc") + .arg("--package") + .arg(env::var("CARGO_PKG_NAME").unwrap()) + .arg("--target") + .arg("wasm32v1-none") + .arg("--crate-type") + .arg("cdylib") + .arg("--no-default-features"); + if release { + command.arg("--release"); + } + assert!(command.status().unwrap().success()); + + // Place the resulting WASM blob into the parent `target` directory + { + let wasm_file = env::var("CARGO_PKG_NAME").unwrap().replace('-', "_") + ".wasm"; + let src_file = target_dir.join("wasm32v1-none").join(&profile).join(&wasm_file); + let dst_file = { + let mut dst_dir = workspace.clone(); + // e.g. workspace/target/debug + dst_dir.extend(["target", &profile]); + let _ = fs::create_dir_all(&dst_dir); + // e.g. workspace/target/debug/serai_runtime.wasm + dst_dir.join(&wasm_file) + }; + fs::copy(&src_file, &dst_file).unwrap(); + } } diff --git a/substrate/runtime/src/lib.rs b/substrate/runtime/src/lib.rs index 37aa3e4c..fd828405 100644 --- a/substrate/runtime/src/lib.rs +++ b/substrate/runtime/src/lib.rs @@ -20,5 +20,9 @@ mod std_runtime_api; pub use std_runtime_api::RuntimeApi; // If this isn't WASM, regardless of what it is, we include the WASM blob from the build script -#[cfg(not(target_family = "wasm"))] -include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +#[cfg(all(not(target_family = "wasm"), debug_assertions))] +pub const WASM: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/target/wasm32v1-none/debug/serai_runtime.wasm")); +#[cfg(all(not(target_family = "wasm"), not(debug_assertions)))] +pub const WASM: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/target/wasm32v1-none/release/serai_runtime.wasm"));