diff --git a/.changelog/unreleased/improvements/3598-remove-wasm-loader.md b/.changelog/unreleased/improvements/3598-remove-wasm-loader.md new file mode 100644 index 0000000000..62db0b06d8 --- /dev/null +++ b/.changelog/unreleased/improvements/3598-remove-wasm-loader.md @@ -0,0 +1,2 @@ +- Do not try to download wasms artifacts from an untrusted source. + ([\#3598](https://github.com/anoma/namada/pull/3598)) \ No newline at end of file diff --git a/crates/apps_lib/src/cli.rs b/crates/apps_lib/src/cli.rs index cc7c51844c..35997dec7c 100644 --- a/crates/apps_lib/src/cli.rs +++ b/crates/apps_lib/src/cli.rs @@ -3267,7 +3267,6 @@ pub mod args { arg("destination-validator"); pub const DISCORD_OPT: ArgOpt = arg_opt("discord-handle"); pub const DO_IT: ArgFlag = flag("do-it"); - pub const DONT_PREFETCH_WASM: ArgFlag = flag("dont-prefetch-wasm"); pub const DRY_RUN_TX: ArgFlag = flag("dry-run"); pub const DRY_RUN_WRAPPER_TX: ArgFlag = flag("dry-run-wrapper"); pub const DUMP_TX: ArgFlag = flag("dump-tx"); @@ -7767,7 +7766,6 @@ pub mod args { pub chain_id: ChainId, pub genesis_validator: Option, pub pre_genesis_path: Option, - pub dont_prefetch_wasm: bool, pub allow_duplicate_ip: bool, pub add_persistent_peers: bool, } @@ -7777,14 +7775,12 @@ pub mod args { let chain_id = CHAIN_ID.parse(matches); let genesis_validator = GENESIS_VALIDATOR.parse(matches); let pre_genesis_path = PRE_GENESIS_PATH.parse(matches); - let dont_prefetch_wasm = DONT_PREFETCH_WASM.parse(matches); let allow_duplicate_ip = ALLOW_DUPLICATE_IP.parse(matches); let add_persistent_peers = ADD_PERSISTENT_PEERS.parse(matches); Self { chain_id, genesis_validator, pre_genesis_path, - dont_prefetch_wasm, allow_duplicate_ip, add_persistent_peers, } @@ -7795,9 +7791,6 @@ pub mod args { https://github.com/heliaxdev/anoma-network-config"))) .arg(GENESIS_VALIDATOR.def().help(wrap!("The alias of the genesis validator that you want to set up as, if any."))) .arg(PRE_GENESIS_PATH.def().help(wrap!("The path to the pre-genesis directory for genesis validator, if any. Defaults to \"{base-dir}/pre-genesis/{genesis-validator}\"."))) - .arg(DONT_PREFETCH_WASM.def().help(wrap!( - "Do not pre-fetch WASM.") - )) .arg(ALLOW_DUPLICATE_IP.def().help(wrap!( "Toggle to disable guard against peers connecting from the \ same IP. This option shouldn't be used in mainnet.") diff --git a/crates/apps_lib/src/client/utils.rs b/crates/apps_lib/src/client/utils.rs index 0d88cd54d5..2776493700 100644 --- a/crates/apps_lib/src/client/utils.rs +++ b/crates/apps_lib/src/client/utils.rs @@ -54,7 +54,6 @@ pub async fn join_network( chain_id, genesis_validator, pre_genesis_path, - dont_prefetch_wasm, allow_duplicate_ip, add_persistent_peers, }: args::JoinNetwork, @@ -250,9 +249,8 @@ pub async fn join_network( config.wasm_dir = wasm_dir_full; } - if !dont_prefetch_wasm { - fetch_wasms_aux(&chain_id, &config.wasm_dir).await; - } + // Validate the wasm artifacts checksums + validate_wasm_artifacts_aux(&chain_id, &config.wasm_dir).await; // Save the config and the wallet config.write(&base_dir, &chain_id, true).unwrap(); @@ -261,9 +259,9 @@ pub async fn join_network( println!("Successfully configured for chain ID {chain_id}"); } -async fn fetch_wasms_aux(chain_id: &ChainId, wasm_dir: &Path) { - println!("Fetching missing wasms for chain ID {chain_id}..."); - wasm_loader::pre_fetch_wasm(wasm_dir).await; +async fn validate_wasm_artifacts_aux(chain_id: &ChainId, wasm_dir: &Path) { + println!("Validating wasms artifacts for chain ID {chain_id}..."); + wasm_loader::validate_wasm_artifacts(wasm_dir).await; } pub fn validate_wasm(args::ValidateWasm { code_path }: args::ValidateWasm) { diff --git a/crates/apps_lib/src/wasm_loader/mod.rs b/crates/apps_lib/src/wasm_loader/mod.rs index f9f9be70f4..a5de01a6a4 100644 --- a/crates/apps_lib/src/wasm_loader/mod.rs +++ b/crates/apps_lib/src/wasm_loader/mod.rs @@ -1,5 +1,4 @@ //! A module for loading WASM files and downloading pre-built WASMs. -use core::borrow::Borrow; use std::fs; use std::path::Path; @@ -35,10 +34,6 @@ pub enum Error { #[serde(transparent)] pub struct Checksums(pub HashMap); -/// Github URL prefix of released Namada network configs -pub const ENV_VAR_WASM_SERVER: &str = "NAMADA_NETWORK_WASM_SERVER"; -const DEFAULT_WASM_SERVER: &str = "https://artifacts.heliax.click/namada-wasm"; - impl Checksums { /// Read WASM checksums from the given path pub fn read_checksums_file( @@ -115,12 +110,6 @@ impl Checksums { } } -fn wasm_url(wasm_name: &str) -> String { - let prefix_url = std::env::var(ENV_VAR_WASM_SERVER) - .unwrap_or_else(|_| DEFAULT_WASM_SERVER.to_string()); - format!("{}/{}", prefix_url, wasm_name) -} - fn valid_wasm_checksum( wasm_payload: &[u8], name: &str, @@ -141,9 +130,8 @@ fn valid_wasm_checksum( } } -/// Download all the pre-built wasms, or if they're already downloaded, verify -/// their checksums. -pub async fn pre_fetch_wasm(wasm_directory: impl AsRef) { +/// Validate wasm artifacts +pub async fn validate_wasm_artifacts(wasm_directory: impl AsRef) { // load json with wasm hashes let checksums = Checksums::read_checksums_async(&wasm_directory).await; @@ -154,69 +142,29 @@ pub async fn pre_fetch_wasm(wasm_directory: impl AsRef) { tokio::spawn(async move { let wasm_path = wasm_directory.join(&full_name); match tokio::fs::read(&wasm_path).await { - // if the file exist, first check the hash. If not matching - // download it again. + // if the file exist, check the hash Ok(bytes) => { if let Err(derived_name) = valid_wasm_checksum(&bytes, &name, &full_name) { tracing::info!( "WASM checksum mismatch: Got {}, expected {}. \ - Fetching new version...", + Check your wasms artifacts.", derived_name, full_name ); - } else { - return; - } - - match download_wasm(&name, &full_name).await { - Ok(bytes) => { - if let Err(e) = - tokio::fs::write(wasm_path, &bytes).await - { - eprintln!( - "Error while creating file for {}: {}", - &name, e - ); - safe_exit(1); - } - } - Err(e) => { - eprintln!("Error downloading wasm: {}", e); - safe_exit(1); - } + safe_exit(1); } } // if the doesn't file exist, download it. - Err(err) => match err.kind() { - std::io::ErrorKind::NotFound => { - match download_wasm(&name, &full_name).await { - Ok(bytes) => { - if let Err(e) = - tokio::fs::write(wasm_path, &bytes).await - { - eprintln!( - "Error while creating file for {}: {}", - &name, e - ); - safe_exit(1); - } - } - Err(e) => { - eprintln!("Error downloading wasm: {}", e); - safe_exit(1); - } - } - } - _ => { - eprintln!( - "Can't read {}.", - wasm_path.as_os_str().to_string_lossy() - ); - safe_exit(1); - } - }, + Err(err) => { + eprintln!( + "Can't read {}: {}", + wasm_path.as_os_str().to_string_lossy(), + err + ); + safe_exit(1); + } } }) })) @@ -270,33 +218,3 @@ pub fn read_wasm_or_exit( } } } - -async fn download_wasm(name: &str, full_name: &str) -> Result, Error> { - let url = wasm_url(full_name); - - tracing::info!("Downloading WASM {url}..."); - - let response = reqwest::get(&url).await; - - match response { - Ok(body) => { - let status = body.status(); - if status.is_success() { - let bytes = body.bytes().await.unwrap(); - let bytes: &[u8] = bytes.borrow(); - - valid_wasm_checksum(bytes, name, full_name) - .map_err(Error::ChecksumMismatch)?; - - let bytes: Vec = bytes.to_owned(); - - Ok(bytes) - } else if status.is_server_error() { - Err(Error::WasmNotFound(url)) - } else { - Err(Error::ServerError(url, status.to_string())) - } - } - Err(e) => Err(Error::Download(url, e)), - } -} diff --git a/crates/node/src/lib.rs b/crates/node/src/lib.rs index c90b803a04..ff756f5fa3 100644 --- a/crates/node/src/lib.rs +++ b/crates/node/src/lib.rs @@ -522,8 +522,7 @@ async fn run_aux_setup( wasm_dir: &PathBuf, scheduled_migration: Option, ) -> RunAuxSetup { - // Prefetch needed wasm artifacts - wasm_loader::pre_fetch_wasm(wasm_dir).await; + wasm_loader::validate_wasm_artifacts(wasm_dir).await; // Find the system available memory let available_memory_bytes = Lazy::new(|| { diff --git a/crates/tests/src/e2e/ledger_tests.rs b/crates/tests/src/e2e/ledger_tests.rs index f2fb82dd99..1f6aa42fba 100644 --- a/crates/tests/src/e2e/ledger_tests.rs +++ b/crates/tests/src/e2e/ledger_tests.rs @@ -2143,13 +2143,7 @@ fn test_sync_chain() -> Result<()> { // Setup the chain let mut join_network = setup::run_cmd( Bin::Client, - [ - "utils", - "join-network", - "--chain-id", - chain_id_raw.as_str(), - "--dont-prefetch-wasm", - ], + ["utils", "join-network", "--chain-id", chain_id_raw.as_str()], Some(60), &test.working_dir, base_dir, diff --git a/crates/tests/src/e2e/setup.rs b/crates/tests/src/e2e/setup.rs index d845125367..a2fdab0e31 100644 --- a/crates/tests/src/e2e/setup.rs +++ b/crates/tests/src/e2e/setup.rs @@ -530,7 +530,6 @@ pub fn network( net.chain_id.as_str(), "--genesis-validator", &alias, - "--dont-prefetch-wasm", ], Some(5), &working_dir, @@ -561,7 +560,6 @@ pub fn network( "--add-persistent-peers", "--chain-id", net.chain_id.as_str(), - "--dont-prefetch-wasm", ], Some(5), &working_dir, diff --git a/scripts/gen_localnet.py b/scripts/gen_localnet.py index 3cfe1facac..e9323bec64 100755 --- a/scripts/gen_localnet.py +++ b/scripts/gen_localnet.py @@ -160,7 +160,6 @@ def join_network( genesis_validator, "--pre-genesis-path", genesis_validator_path, - "--dont-prefetch-wasm", ) info(f"Validator {genesis_validator} joined {chain_id}")