Skip to content

Commit e7b3333

Browse files
authored
feat: Lazy download (#2599)
# Description Some but not all nns-wasms are downloaded only if they do not already exist. With this change all NNS wasm downloads occur only if the wasm is not already present. This should help testing when one has a slow internet connection.
1 parent 06a1deb commit e7b3333

File tree

3 files changed

+28
-16
lines changed

3 files changed

+28
-16
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
### fix: Only kill main process on `dfx stop`
88
Removes misleading panics when running `dfx stop`.
99

10+
### feat: `dfx nns install` works offline if all assets have been cached.
11+
1012
### feat: Initialise the nns with an account controlled by a secp256k1 key
1113

1214
This enables easy access to toy ICP using command line tools and this key:

e2e/tests-dfx/nns.bash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ assert_nns_canister_id_matches() {
125125
dfx canister info "$(nns_canister_id "$1")" | awk '/Module hash/{print $3; exit 0}END{exit 1}'
126126
}
127127
downloaded_wasm_hash() {
128-
sha256sum ".dfx/wasms/nns/$(dfx --version | awk '{printf "%s-%s", $1, $2}')/$1" | awk '{print "0x" $1}'
128+
sha256sum "$DFX_CACHE_ROOT/.cache/dfinity/versions/$(dfx --version | awk '{printf "%s", $2}')/wasms/$1" | awk '{print "0x" $1}'
129129
}
130130
wasm_matches() {
131131
echo "Comparing $* ..."

src/dfx/src/lib/nns/install_nns.rs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#![warn(missing_docs)]
77
#![warn(clippy::missing_docs_in_private_items)]
88

9+
use crate::config::cache::get_bin_cache;
910
use crate::config::dfinity::ReplicaSubnetType;
1011
use crate::lib::environment::Environment;
1112
use crate::lib::identity::identity_utils::CallSender;
@@ -74,7 +75,7 @@ pub async fn install_nns(
7475
eprintln!("Installing the core backend wasm canisters...");
7576
download_nns_wasms(env).await?;
7677
let ic_nns_init_opts = IcNnsInitOpts {
77-
wasm_dir: nns_wasm_dir(env),
78+
wasm_dir: nns_wasm_dir(env)?,
7879
nns_url: nns_url.to_string(),
7980
test_accounts: vec![
8081
canisters::ED25519_TEST_ACCOUNT.to_string(),
@@ -95,7 +96,7 @@ pub async fn install_nns(
9596
canister_id,
9697
} in NNS_FRONTEND
9798
{
98-
let local_wasm_path = nns_wasm_dir(env).join(wasm_name);
99+
let local_wasm_path = nns_wasm_dir(env)?.join(wasm_name);
99100
let parsed_wasm_url = Url::parse(wasm_url)
100101
.with_context(|| format!("Could not parse url for {canister_name} wasm: {wasm_url}"))?;
101102
download(&parsed_wasm_url, &local_wasm_path).await?;
@@ -326,6 +327,15 @@ pub fn verify_local_replica_type_is_system(env: &dyn Environment) -> anyhow::Res
326327
/// Downloads a file
327328
#[context("Failed to download '{:?}' to '{:?}'.", source, target)]
328329
pub async fn download(source: &Url, target: &Path) -> anyhow::Result<()> {
330+
if target.exists() {
331+
println!("Already downloaded: {}", target.to_string_lossy());
332+
return Ok(());
333+
}
334+
println!(
335+
"Downloading {}\n from: {}",
336+
target.to_string_lossy(),
337+
source.as_str()
338+
);
329339
let buffer = reqwest::get(source.clone())
330340
.await
331341
.with_context(|| "Failed to connect")?
@@ -358,6 +368,15 @@ pub async fn download(source: &Url, target: &Path) -> anyhow::Result<()> {
358368
/// Downloads and unzips a file
359369
#[context("Failed to download and unzip '{:?}' from '{:?}'.", target, source.as_str())]
360370
pub async fn download_gz(source: &Url, target: &Path) -> anyhow::Result<()> {
371+
if target.exists() {
372+
println!("Already downloaded: {}", target.to_string_lossy());
373+
return Ok(());
374+
}
375+
println!(
376+
"Downloading {}\n from .gz: {}",
377+
target.to_string_lossy(),
378+
source.as_str()
379+
);
361380
let response = reqwest::get(source.clone())
362381
.await
363382
.with_context(|| "Failed to connect")?
@@ -403,27 +422,18 @@ pub async fn download_ic_repo_wasm(
403422
fs::create_dir_all(wasm_dir)
404423
.with_context(|| format!("Failed to create wasm directory: '{}'", wasm_dir.display()))?;
405424
let final_path = wasm_dir.join(&wasm_name);
406-
if final_path.exists() {
407-
return Ok(());
408-
}
409-
410425
let url_str =
411426
format!("https://download.dfinity.systems/ic/{ic_commit}/canisters/{wasm_name}.gz");
412427
let url = Url::parse(&url_str)
413428
.with_context(|| format!("Could not determine download URL. Are ic_commit '{ic_commit}' and wasm_name '{wasm_name}' valid?"))?;
414-
println!(
415-
"Downloading {}\n from {}",
416-
final_path.to_string_lossy(),
417-
url_str
418-
);
419429
download_gz(&url, &final_path).await
420430
}
421431

422432
/// Downloads all the core NNS wasms, excluding only the front-end wasms II and NNS-dapp.
423433
#[context("Failed to download NNS wasm files.")]
424434
pub async fn download_nns_wasms(env: &dyn Environment) -> anyhow::Result<()> {
425435
let ic_commit = std::env::var("DFX_IC_COMMIT").unwrap_or_else(|_| replica_rev().to_string());
426-
let wasm_dir = &nns_wasm_dir(env);
436+
let wasm_dir = &nns_wasm_dir(env)?;
427437
for IcNnsInitCanister {
428438
wasm_name,
429439
test_wasm_name,
@@ -570,7 +580,7 @@ pub fn upload_nns_sns_wasms_canister_wasms(env: &dyn Environment) -> anyhow::Res
570580
} in SNS_CANISTERS
571581
{
572582
let sns_cli = bundled_binary(env, "sns")?;
573-
let wasm_path = nns_wasm_dir(env).join(wasm_name);
583+
let wasm_path = nns_wasm_dir(env)?.join(wasm_name);
574584
let mut command = Command::new(sns_cli);
575585
command
576586
.arg("add-sns-wasm-for-tests")
@@ -656,8 +666,8 @@ pub async fn install_canister(
656666
}
657667

658668
/// The local directory where NNS wasm files are cached. The directory is typically created on demand.
659-
fn nns_wasm_dir(env: &dyn Environment) -> PathBuf {
660-
Path::new(&format!(".dfx/wasms/nns/dfx-{}/", env.get_version())).to_path_buf()
669+
fn nns_wasm_dir(env: &dyn Environment) -> anyhow::Result<PathBuf> {
670+
Ok(get_bin_cache(&env.get_version().to_string())?.join("wasms"))
661671
}
662672

663673
/// Get the path to a bundled command line binary

0 commit comments

Comments
 (0)