From d9f2c986ba6a1e7d87a2276694b602971721c629 Mon Sep 17 00:00:00 2001 From: Marcin Nowak-Liebiediew Date: Fri, 17 Nov 2023 17:23:57 +0100 Subject: [PATCH] chore: release 0.15.2 beta.2 (#3449) * feat: Read install arg from file (#3431) # Description This PR adds support for providing install arguments from a file. This is motivated by these issues: * It is impossible to pass a large canister init arg as the length of shell arguments is limited by the terminal (which in turn may be limited by the operating system). * For shorter arguments, it is more convenient to write `--argument-file somefile.hex` than `--argument "$(cat somefile.hex)"`. * The `dfx canister call` method supports `--argument-file` for similar reasons. It would be nice to be consistent. * fix: output .env file is now relative to project root, not cwd (#3435) dfx.json can specify `output_env_file` (the default for new projects is `".env"`), and some commands accept `--output-env-file .env` on the command line. If `dfx deploy`, `dfx build`, or `dfx canister install` were executed in a subdirectory of a project, they would create/read this file in that subdirectory, rather than the same directory as dfx.json (the project root). With this change, the location of the env file is taken to be relative to the project root, and furthermore must be contained within the project directory. Also fixed three places that could output "No such file or directory (OS error 2)" without telling which path wasn't found. Fixes: https://dfinity.atlassian.net/browse/SDK-1028 * fix: dfx extension install will no longer create a corrupt cache directory (#3436) Running `dfx extension install ` immediately after installing a new dfx version, or after `dfx cache delete`, would result in a cache directory that contained only an `extensions` subdirectory. Later, dfx would see that the cache directory exists and therefore not install it. Then, commands like `dfx start` or `dfx build` would fail due to missing files. Fixes: https://dfinity.atlassian.net/browse/SDK-1240 * ci: add workflow to update bitcoin canister sources (#3438) * chore: Update Bitcoin Canister to release/2023-10-13 (#3439) Co-authored-by: github-actions * chore: update Motoko version to 0.10.2 (#3441) ## Suggested [CHANGELOG.md](https://github.com/dfinity/sdk/edit/chore-update-motoko-0.10.2/CHANGELOG.md) changes ``` ## Dependencies ### Motoko Updated Motoko to [0.10.2](https://github.com/dfinity/motoko/releases/tag/0.10.2) * fix: deleting project canister by id will clean up canister id store. (#3442) `dfx canister delete ` would leave entries (canister name -> canister id) in the canister id store. A subsequent `dfx deploy` would then fail because it would try to install to the deleted canister rather than creating a new one. Fixes https://dfinity.atlassian.net/browse/SDK-1143 * chore: Update to new ic-agent version (#3445) * Update to new ic-agent version * . * fix some tests, add env var for disabling query cert * per command * fix other tests * 0.30.2 * chore: Release 0.15.2-beta.2 Signed-off-by: Marcin Nowak-Liebiediew --------- Signed-off-by: Marcin Nowak-Liebiediew Co-authored-by: Max Co-authored-by: Eric Swanson <64809312+ericswanson-dfinity@users.noreply.github.com> Co-authored-by: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Co-authored-by: github-actions Co-authored-by: Adam Spofford <93943719+adamspofford-dfinity@users.noreply.github.com> --- .github/workflows/bitcoin-canister-update.yml | 69 ++++++++++++++ .github/workflows/e2e.yml | 4 + CHANGELOG.md | 31 +++++- Cargo.lock | 94 ++++++++++++++++--- Cargo.toml | 22 ++--- docs/cli-reference/dfx-canister.md | 1 + e2e/tests-dfx/certificate.bash | 1 + e2e/tests-dfx/delete.bash | 13 +++ e2e/tests-dfx/dotenv.bash | 37 ++++++++ e2e/tests-dfx/extension.bash | 6 ++ e2e/tests-dfx/install.bash | 27 +++++- nix/sources.json | 30 +++--- public/manifest.json | 3 +- scripts/workflows/provision-darwin.sh | 3 +- scripts/workflows/provision-linux.sh | 3 +- src/canisters/frontend/ic-asset/src/lib.rs | 4 +- src/canisters/frontend/icx-asset/src/main.rs | 6 +- .../src/config/model/canister_id_store.rs | 6 +- src/dfx-core/src/config/model/dfinity.rs | 30 ++++++ src/dfx-core/src/error/config.rs | 16 ++++ src/dfx-core/src/util/mod.rs | 3 +- src/dfx/Cargo.toml | 4 +- src/dfx/assets/dfx-asset-sources.toml | 24 ++--- src/dfx/src/commands/build.rs | 4 +- src/dfx/src/commands/canister/delete.rs | 14 ++- .../src/commands/canister/deposit_cycles.rs | 4 +- src/dfx/src/commands/canister/install.rs | 31 ++++-- src/dfx/src/commands/canister/send.rs | 6 +- src/dfx/src/commands/cycles/balance.rs | 3 + src/dfx/src/commands/deploy.rs | 4 +- src/dfx/src/commands/extension/install.rs | 4 + src/dfx/src/commands/ledger/balance.rs | 2 + src/dfx/src/lib/builders/mod.rs | 8 +- src/dfx/src/lib/environment.rs | 3 + src/dfx/src/lib/replica/status.rs | 4 +- src/dfx/src/lib/sign/sign_transport.rs | 13 +++ src/dfx/src/util/currency_conversion.rs | 4 +- 37 files changed, 445 insertions(+), 96 deletions(-) create mode 100644 .github/workflows/bitcoin-canister-update.yml diff --git a/.github/workflows/bitcoin-canister-update.yml b/.github/workflows/bitcoin-canister-update.yml new file mode 100644 index 0000000000..55dad64246 --- /dev/null +++ b/.github/workflows/bitcoin-canister-update.yml @@ -0,0 +1,69 @@ +name: Check Bitcoin Canister Release Update + +on: + workflow_dispatch: + schedule: + - cron: '0 0 * * *' # Runs at UTC midnight every day + +jobs: + check-update: + runs-on: ubuntu-latest + + steps: + - name: Checkout dfx repository + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Fetch Bitcoin Canister latest release tag + env: + GH_TOKEN: "${{ secrets.NIV_UPDATER_TOKEN }}" + run: | + LATEST_TAG=$(gh release view --repo dfinity/bitcoin-canister --json tagName -q .tagName) + echo "Latest tag is $LATEST_TAG" + echo "LATEST_TAG=$LATEST_TAG" >> $GITHUB_ENV + + - name: Check if the latest release tag has been updated + run: | + URL_ENCODED_CURRENT_TAG=$(jq -r '.["ic-btc-canister"].version' nix/sources.json) + CURRENT_TAG=$(python -c "import sys, urllib.parse as ul; print(ul.unquote_plus(sys.argv[1]))" "$URL_ENCODED_CURRENT_TAG") + echo "Current tag is $CURRENT_TAG" + if [[ "$CURRENT_TAG" == "$LATEST_TAG" ]]; then + echo "No update is required." + exit 1 + else + echo "An update is required." + fi + + + - name: install Nix + uses: cachix/install-nix-action@v21 + with: + nix_path: nixpkgs=channel:nixos-unstable + + - name: install niv (dependency manager for Nix projects) + run: nix-env -i niv -f '' + + - name: install packages from nix/sources.json + run: niv update + + - name: update sources + run: | + URL_ENCODED_LATEST_TAG=$(echo -n "$LATEST_TAG" | python -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip(), safe=""))') + niv update ic-btc-canister -a version=$URL_ENCODED_LATEST_TAG + ./scripts/write-dfx-asset-sources.sh + + - name: Update dfx to use the latest Bitcoin Canister version + env: + GH_TOKEN: "${{ secrets.NIV_UPDATER_TOKEN }}" + run: | + git config user.name github-actions + git config user.email github-actions@github.com + git checkout -b bot/update-bitcoin-canister/$LATEST_TAG + git add . + git commit -m "Update Bitcoin Canister to $LATEST_TAG" + git push --set-upstream origin bot/update-bitcoin-canister/$LATEST_TAG + PR_TITLE="chore: Update Bitcoin Canister Version to $LATEST_TAG" + PR_BODY="This PR updates the Bitcoin Canister version to the latest tag: $LATEST_TAG" + gh pr create --title "$PR_TITLE" --body "$PR_BODY" --base master --head $(git branch --show-current) + diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 9b468bffef..41bed9aa7e 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -97,6 +97,10 @@ jobs: path: /usr/local/bin - name: Setup dfx binary run: chmod +x /usr/local/bin/dfx + - name: Disable query verification in ic-ref + if: ${{ matrix.backend == 'ic-ref' }} + run: | + echo DFX_DISABLE_QUERY_VERIFICATION=1 >> $GITHUB_ENV - name: start and deploy run: | pwd diff --git a/CHANGELOG.md b/CHANGELOG.md index a496863420..e4d6102937 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,31 @@ # UNRELEASED +=== fix: `dfx canister delete ` removes the related entry from the canister id store + +Previously, deleting a canister in the project by id rather than by name +would leave the canister id in the canister id store. This would cause +`dfx deploy` to fail. + +=== fix: dfx extension install can no longer create a corrupt cache directory + +Running `dfx cache delete && dfx extension install nns` would previously +create a cache directory containing only an `extensions` subdirectory. +dfx only looks for the existence of a cache version subdirectory to +determine whether it has been installed. The end result was that later +commands would fail when the cache did not contain expected files. + +=== fix: output_env_file is now considered relative to project root + +The .env file location, whether specified as `output_env_file` in dfx.json +or `--output-env-file ` on the commandline, is now considered relative +to the project root, rather than relative to the current working directory. + +=== feat: Read dfx canister install argument from a file + +Enables passing large arguments that cannot be passed directly in the command line using the `--argument-file` flag. For example `dfx canister install --argument-file ./my/argument/file.txt my_canister_name`. + + ### feat: change `list_permitted` and `list_authorized` to an update call. This requires the `list_authorized` and `list_permitted` methods to be called as an update and disables the ability to @@ -24,7 +49,7 @@ Added the following subcommands: ### Motoko -Updated Motoko to [0.10.1](https://github.com/dfinity/motoko/releases/tag/0.10.1) +Updated Motoko to [0.10.2](https://github.com/dfinity/motoko/releases/tag/0.10.2) ### Frontend canister @@ -51,6 +76,10 @@ This incorporates the following executed proposals: - [124858](https://dashboard.internetcomputer.org/proposal/124858) - [124857](https://dashboard.internetcomputer.org/proposal/124857) +### Bitcoin canister + +Updated Bitcoin canister to [release/2023-10-13](https://github.com/dfinity/bitcoin-canister/releases/tag/release%2F2023-10-13) + # 0.15.1 ### feat: Added support for reserved_cycles and reserved_cycles_limit diff --git a/Cargo.lock b/Cargo.lock index 7a5695181b..f62c4bec0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -177,6 +177,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -723,6 +729,19 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cached" +version = "0.46.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c8c50262271cdf5abc979a5f76515c234e764fa025d1ba4862c0f0bcda0e95" +dependencies = [ + "ahash 0.8.6", + "hashbrown 0.14.2", + "instant", + "once_cell", + "thiserror", +] + [[package]] name = "candid" version = "0.8.4" @@ -1191,6 +1210,19 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "curve25519-dalek-ng" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core", + "subtle-ng", + "zeroize", +] + [[package]] name = "cvt" version = "0.1.2" @@ -1352,7 +1384,7 @@ checksum = "6a1abaf4d861455be59f64fd2b55606cb151fce304ede7165f410243ce96bde6" [[package]] name = "dfx" -version = "0.15.2-beta.1" +version = "0.15.2-beta.2" dependencies = [ "actix", "aes-gcm", @@ -1388,7 +1420,7 @@ dependencies = [ "ic-asset", "ic-cdk", "ic-identity-hsm", - "ic-utils 0.29.0", + "ic-utils 0.30.2", "ic-wasm", "icrc-ledger-types", "indicatif", @@ -1458,7 +1490,7 @@ dependencies = [ "humantime-serde", "ic-agent", "ic-identity-hsm", - "ic-utils 0.29.0", + "ic-utils 0.30.2", "k256 0.11.6", "keyring", "lazy_static", @@ -1629,6 +1661,21 @@ dependencies = [ "spki 0.7.2", ] +[[package]] +name = "ed25519-consensus" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c8465edc8ee7436ffea81d21a019b16676ee3db267aa8d5a8d729581ecf998b" +dependencies = [ + "curve25519-dalek-ng", + "hex", + "rand_core", + "serde", + "sha2 0.9.9", + "thiserror", + "zeroize", +] + [[package]] name = "either" version = "1.9.0" @@ -2201,6 +2248,10 @@ name = "hashbrown" version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +dependencies = [ + "ahash 0.8.6", + "allocator-api2", +] [[package]] name = "heck" @@ -2408,11 +2459,13 @@ dependencies = [ [[package]] name = "ic-agent" -version = "0.29.0" -source = "git+https://github.com/dfinity/agent-rs.git?rev=b91b85b7b6ba6bfaf9dfd616b7c7c8f966bf8f68#b91b85b7b6ba6bfaf9dfd616b7c7c8f966bf8f68" +version = "0.30.2" +source = "git+https://github.com/dfinity/agent-rs.git?rev=ed0862a45d5973ff123cbabc4ac40a89821b18c6#ed0862a45d5973ff123cbabc4ac40a89821b18c6" dependencies = [ "backoff", + "cached 0.46.1", "candid 0.9.11", + "ed25519-consensus", "futures-util", "hex", "http", @@ -2425,6 +2478,7 @@ dependencies = [ "pem 2.0.1", "pkcs8 0.10.2", "rand", + "rangemap", "reqwest", "ring 0.16.20", "rustls-webpki", @@ -2455,7 +2509,7 @@ dependencies = [ "globset", "hex", "ic-agent", - "ic-utils 0.29.0", + "ic-utils 0.30.2", "itertools 0.10.5", "json5", "mime", @@ -2657,7 +2711,7 @@ source = "git+https://github.com/dfinity/ic.git?rev=a533346f63f4091eb64692891de0 dependencies = [ "arrayvec 0.5.2", "base64 0.11.0", - "cached", + "cached 0.41.0", "hex", "ic-crypto-internal-bls12-381-type", "ic-crypto-internal-seed", @@ -2774,8 +2828,8 @@ dependencies = [ [[package]] name = "ic-identity-hsm" -version = "0.29.0" -source = "git+https://github.com/dfinity/agent-rs.git?rev=b91b85b7b6ba6bfaf9dfd616b7c7c8f966bf8f68#b91b85b7b6ba6bfaf9dfd616b7c7c8f966bf8f68" +version = "0.30.2" +source = "git+https://github.com/dfinity/agent-rs.git?rev=ed0862a45d5973ff123cbabc4ac40a89821b18c6#ed0862a45d5973ff123cbabc4ac40a89821b18c6" dependencies = [ "hex", "ic-agent", @@ -2870,8 +2924,8 @@ dependencies = [ [[package]] name = "ic-transport-types" -version = "0.29.0" -source = "git+https://github.com/dfinity/agent-rs.git?rev=b91b85b7b6ba6bfaf9dfd616b7c7c8f966bf8f68#b91b85b7b6ba6bfaf9dfd616b7c7c8f966bf8f68" +version = "0.30.2" +source = "git+https://github.com/dfinity/agent-rs.git?rev=ed0862a45d5973ff123cbabc4ac40a89821b18c6#ed0862a45d5973ff123cbabc4ac40a89821b18c6" dependencies = [ "candid 0.9.11", "hex", @@ -2945,8 +2999,8 @@ dependencies = [ [[package]] name = "ic-utils" -version = "0.29.0" -source = "git+https://github.com/dfinity/agent-rs.git?rev=b91b85b7b6ba6bfaf9dfd616b7c7c8f966bf8f68#b91b85b7b6ba6bfaf9dfd616b7c7c8f966bf8f68" +version = "0.30.2" +source = "git+https://github.com/dfinity/agent-rs.git?rev=ed0862a45d5973ff123cbabc4ac40a89821b18c6#ed0862a45d5973ff123cbabc4ac40a89821b18c6" dependencies = [ "async-trait", "candid 0.9.11", @@ -3039,7 +3093,7 @@ dependencies = [ "humantime", "ic-agent", "ic-asset", - "ic-utils 0.29.0", + "ic-utils 0.30.2", "libflate", "num-traits", "pem 1.1.1", @@ -4484,6 +4538,12 @@ dependencies = [ "rand_core", ] +[[package]] +name = "rangemap" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "977b1e897f9d764566891689e642653e5ed90c6895106acd005eb4c1d0203991" + [[package]] name = "rayon" version = "1.8.0" @@ -5454,6 +5514,12 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +[[package]] +name = "subtle-ng" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" + [[package]] name = "supports-color" version = "1.3.1" diff --git a/Cargo.toml b/Cargo.toml index 869e4773e3..8a42a64df0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,18 +18,18 @@ rust-version = "1.71.1" license = "Apache-2.0" [workspace.dependencies] -candid = { version = "0.9.0", features = [ "parser" ] } -ic-agent = "0.29.0" +candid = { version = "0.9.0", features = ["parser"] } +ic-agent = "0.30.2" ic-asset = { path = "src/canisters/frontend/ic-asset" } ic-cdk = "0.10.0" -ic-identity-hsm = "0.29.0" -ic-utils = "0.29.0" +ic-identity-hsm = "0.30.2" +ic-utils = "0.30.2" aes-gcm = "0.9.4" anyhow = "1.0.56" anstyle = "1.0.0" argon2 = "0.4.0" -backoff = { version = "0.4.0", features = [ "futures", "tokio" ] } +backoff = { version = "0.4.0", features = ["futures", "tokio"] } base64 = "0.13.0" byte-unit = "4.0.14" bytes = "1.2.1" @@ -69,19 +69,19 @@ url = "2.1.0" walkdir = "2.3.2" [patch.crates-io.ic-agent] -version = "0.29.0" +version = "0.30.2" git = "https://github.com/dfinity/agent-rs.git" -rev = "b91b85b7b6ba6bfaf9dfd616b7c7c8f966bf8f68" +rev = "ed0862a45d5973ff123cbabc4ac40a89821b18c6" [patch.crates-io.ic-identity-hsm] -version = "0.29.0" +version = "0.30.2" git = "https://github.com/dfinity/agent-rs.git" -rev = "b91b85b7b6ba6bfaf9dfd616b7c7c8f966bf8f68" +rev = "ed0862a45d5973ff123cbabc4ac40a89821b18c6" [patch.crates-io.ic-utils] -version = "0.29.0" +version = "0.30.2" git = "https://github.com/dfinity/agent-rs.git" -rev = "b91b85b7b6ba6bfaf9dfd616b7c7c8f966bf8f68" +rev = "ed0862a45d5973ff123cbabc4ac40a89821b18c6" [profile.release] panic = 'abort' diff --git a/docs/cli-reference/dfx-canister.md b/docs/cli-reference/dfx-canister.md index 555b83df78..ffc06eed56 100644 --- a/docs/cli-reference/dfx-canister.md +++ b/docs/cli-reference/dfx-canister.md @@ -438,6 +438,7 @@ You can use the following optional flags with the `dfx canister install` command | Flag | Description | |-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `--argument-file` | Specifies the file from which to read the argument to pass to the init method. Stdin may be referred to as `-`. | | `--async-call` | Enables you to continue without waiting for the result of the installation to be returned by polling the Internet Computer or the local canister execution environment. | | `--upgrade-unchanged` | Upgrade the canister even if the .wasm did not change. | diff --git a/e2e/tests-dfx/certificate.bash b/e2e/tests-dfx/certificate.bash index 1fe5d66269..a86a2baeeb 100644 --- a/e2e/tests-dfx/certificate.bash +++ b/e2e/tests-dfx/certificate.bash @@ -73,6 +73,7 @@ teardown() { # The wallet does not have a query call forward method (currently calls forward from wallet's update method) # So call with users Identity as sender here # There may need to be a query version of wallet_call + declare -x DFX_DISABLE_QUERY_VERIFICATION=1 assert_command dfx canister call certificate_backend hello_query '("Buckaroo")' assert_eq '("Hullo, Buckaroo!")' } diff --git a/e2e/tests-dfx/delete.bash b/e2e/tests-dfx/delete.bash index d87e08bcfd..5aa7b3e610 100755 --- a/e2e/tests-dfx/delete.bash +++ b/e2e/tests-dfx/delete.bash @@ -14,6 +14,19 @@ teardown() { standard_teardown } +@test "delete by canister id cleans up canister id store" { + dfx_start + dfx deploy e2e_project_backend + id=$(dfx canister id e2e_project_backend) + dfx canister stop e2e_project_backend + assert_command dfx canister delete "$id" + assert_command_fail dfx canister info e2e_project_backend + assert_contains "Cannot find canister id. Please issue 'dfx canister create e2e_project_backend'." + assert_command_fail dfx canister status "$id" + assert_contains "Canister $id not found" + assert_command dfx deploy +} + @test "delete can be used to delete a canister" { dfx_start dfx deploy e2e_project_backend diff --git a/e2e/tests-dfx/dotenv.bash b/e2e/tests-dfx/dotenv.bash index 1f6f2ab755..2f92e07d0e 100644 --- a/e2e/tests-dfx/dotenv.bash +++ b/e2e/tests-dfx/dotenv.bash @@ -14,6 +14,43 @@ teardown() { standard_teardown } + +@test "puts .env in project root" { + dfx_start + jq '.canisters["e2e_project_backend"].post_install="echo post install backend"' dfx.json | sponge dfx.json + jq '.canisters["e2e_project_frontend"].post_install="echo post install frontend"' dfx.json | sponge dfx.json + + mkdir subdir + mkdir subdir/canister-install-all subdir/canister-install-single + mkdir subdir/build-all subdir/build-single + mkdir subdir/deploy-single subdir/deploy-all + dfx canister create --all + ( cd subdir/build-single && dfx build e2e_project_frontend ) + ( cd subdir/build-all && dfx build --all ) + ( cd subdir/canister-install-single && dfx canister install e2e_project_backend ) + dfx canister uninstall-code e2e_project_backend + ( cd subdir/canister-install-all && dfx canister install --all ) + rm -rf .dfx + ( cd subdir/deploy-single && dfx deploy e2e_project_backend) + ( cd subdir/deploy-all && dfx deploy ) + + assert_command find . -name .env + assert_eq "./.env" +} + +@test "the output_env_file must be contained within project" { + dfx_start + mkdir ../outside + + assert_command_fail dfx deploy --output-env-file nonexistent/.env + assert_contains "failed to canonicalize output_env_file" + assert_contains "working-dir/e2e_project/nonexistent: No such file or directory" + assert_command_fail dfx deploy --output-env-file /etc/passwd + assert_contains "The output_env_file must be a relative path, but is /etc/passwd" + assert_command_fail dfx deploy --output-env-file ../outside/.env + assert_match "The output_env_file must be within the project root, but is .*/working-dir/e2e_project/../outside/.env" +} + @test "writes environment variables to .env" { dfx_start dfx canister create --all diff --git a/e2e/tests-dfx/extension.bash b/e2e/tests-dfx/extension.bash index f5688d51ef..bf2c627940 100644 --- a/e2e/tests-dfx/extension.bash +++ b/e2e/tests-dfx/extension.bash @@ -13,6 +13,12 @@ teardown() { standard_teardown } +@test "extension install with an empty cache does not create a corrupt cache" { + dfx cache delete + dfx extension install nns --version 0.2.1 + dfx_start +} + @test "install extension from official registry" { assert_command_fail dfx snsx diff --git a/e2e/tests-dfx/install.bash b/e2e/tests-dfx/install.bash index 04fcb84fa9..5511205a07 100644 --- a/e2e/tests-dfx/install.bash +++ b/e2e/tests-dfx/install.bash @@ -182,7 +182,32 @@ teardown() { assert_contains db07e7e24f6f8ddf53c33a610713259a7c1eb71c270b819ebd311e2d223267f0 } +@test "installing one canister with an argument succeeds" { + dfx_start + assert_command dfx canister create e2e_project_backend + assert_command dfx build e2e_project_backend + assert_command dfx canister install e2e_project_backend --argument '()' +} + +@test "installing with an argument in a file succeeds" { + dfx_start + assert_command dfx canister create e2e_project_backend + assert_command dfx build e2e_project_backend + TMPFILE="$(mktemp)" + echo '()' >"$TMPFILE" + assert_command dfx canister install e2e_project_backend --argument-file "$TMPFILE" +} + +@test "installing with an argument on stdin succeeds" { + dfx_start + assert_command dfx canister create e2e_project_backend + assert_command dfx build e2e_project_backend + TMPFILE="$(mktemp)" + echo '()' >"$TMPFILE" + assert_command dfx canister install e2e_project_backend --argument-file - <"$TMPFILE" +} + @test "installing multiple canisters with arguments fails" { - assert_command_fail dfx canister install --all --argument hello + assert_command_fail dfx canister install --all --argument '()' assert_contains "error: the argument '--all' cannot be used with '--argument '" } diff --git a/nix/sources.json b/nix/sources.json index 72e8ea5b82..e73f22befb 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -6,10 +6,10 @@ "homepage": "https://rustsec.org", "owner": "RustSec", "repo": "advisory-db", - "rev": "0c251c3c9a1b08e08ef5946d4c2d133fe1bc213e", - "sha256": "1nqzy1ky570zdkkdc9q7cpi5ys9cxnkyjhzvic1fzfcrrlz92kzd", + "rev": "3338fcfb59cea5fcd7d2a4e7fe24cbc7cb778003", + "sha256": "0fw5xrzafv061jj3lzrnqarbjcm1irzvl338yhkzw1k8firmki7d", "type": "tarball", - "url": "https://github.com/RustSec/advisory-db/archive/0c251c3c9a1b08e08ef5946d4c2d133fe1bc213e.tar.gz", + "url": "https://github.com/RustSec/advisory-db/archive/3338fcfb59cea5fcd7d2a4e7fe24cbc7cb778003.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "canister_sandbox-x86_64-darwin": { @@ -66,11 +66,11 @@ }, "ic-btc-canister": { "owner": "dfinity", - "sha256": "0izvazr0cpdwjga12zim2cwp3rgm5n3w7ag5yplfl8rxrhwk65f4", + "sha256": "1b34jpxkk72h07ls0fspwrgmndmj7xhlivdhn82msvgz8mx69x89", "type": "file", - "url": "https://github.com/dfinity/bitcoin-canister/releases/download/release%2F2023-03-31/ic-btc-canister.wasm.gz", + "url": "https://github.com/dfinity/bitcoin-canister/releases/download/release%2F2023-10-13/ic-btc-canister.wasm.gz", "url_template": "https://github.com/dfinity/bitcoin-canister/releases/download//ic-btc-canister.wasm.gz", - "version": "release%2F2023-03-31" + "version": "release%2F2023-10-13" }, "ic-https-outcalls-adapter-x86_64-darwin": { "builtin": false, @@ -160,27 +160,27 @@ "builtin": false, "description": "The Motoko base library", "owner": "dfinity", - "sha256": "0b8lsxb3j7qj6kzb32fbkf0a018jkisapcb8szwl8ad023lv3xv3", + "sha256": "12z4mr3r63nnncjqxrsxjhr1z2p8adg7zp48wbacb42jhs0mkfvl", "type": "tarball", - "url": "https://github.com/dfinity/motoko/releases/download/0.10.1/motoko-base-library.tar.gz", + "url": "https://github.com/dfinity/motoko/releases/download/0.10.2/motoko-base-library.tar.gz", "url_template": "https://github.com/dfinity/motoko/releases/download//motoko-base-library.tar.gz", - "version": "0.10.1" + "version": "0.10.2" }, "motoko-x86_64-darwin": { "builtin": false, - "sha256": "1inc2x9misqazgswfz7irvsjp4dkvab87j66yklnvy51w6pi3r7b", + "sha256": "1x49qwzrxc6dj5gik2hpi8l3xdnggqj2v9yvb6sfb7ff6gx3avc6", "type": "file", - "url": "https://github.com/dfinity/motoko/releases/download/0.10.1/motoko-Darwin-x86_64-0.10.1.tar.gz", + "url": "https://github.com/dfinity/motoko/releases/download/0.10.2/motoko-Darwin-x86_64-0.10.2.tar.gz", "url_template": "https://github.com/dfinity/motoko/releases/download//motoko-Darwin-x86_64-.tar.gz", - "version": "0.10.1" + "version": "0.10.2" }, "motoko-x86_64-linux": { "builtin": false, - "sha256": "11jx3r0lw41x7xqajqqc7s9wvkr9kfpg5h38vr9bcvwfndg49flc", + "sha256": "1a1yv2awrd053qk3h9a34y887j2vfhb0ckrk25kjjx4ifdygp8ys", "type": "file", - "url": "https://github.com/dfinity/motoko/releases/download/0.10.1/motoko-Linux-x86_64-0.10.1.tar.gz", + "url": "https://github.com/dfinity/motoko/releases/download/0.10.2/motoko-Linux-x86_64-0.10.2.tar.gz", "url_template": "https://github.com/dfinity/motoko/releases/download//motoko-Linux-x86_64-.tar.gz", - "version": "0.10.1" + "version": "0.10.2" }, "replica-x86_64-darwin": { "builtin": false, diff --git a/public/manifest.json b/public/manifest.json index d6fc9f5a0d..9e0bf6b9ae 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -60,6 +60,7 @@ "0.14.4", "0.15.0", "0.15.1", - "0.15.2-beta.1" + "0.15.2-beta.1", + "0.15.2-beta.2" ] } diff --git a/scripts/workflows/provision-darwin.sh b/scripts/workflows/provision-darwin.sh index 38fb86c9ab..73df981f86 100755 --- a/scripts/workflows/provision-darwin.sh +++ b/scripts/workflows/provision-darwin.sh @@ -27,7 +27,8 @@ if [ "$E2E_TEST" = "tests-dfx/certificate.bash" ]; then brew install mitmproxy fi if [ "$E2E_TEST" = "tests-dfx/deps.bash" ]; then - cargo install ic-wasm + cargo install cargo-binstall + cargo binstall -y ic-wasm fi # Exit temporary directory. diff --git a/scripts/workflows/provision-linux.sh b/scripts/workflows/provision-linux.sh index 9e2b26f111..f00de0f386 100755 --- a/scripts/workflows/provision-linux.sh +++ b/scripts/workflows/provision-linux.sh @@ -36,7 +36,8 @@ if [ "$E2E_TEST" = "tests-dfx/identity_encryption.bash" ] || [ "$E2E_TEST" = "te sudo apt-get install --yes expect fi if [ "$E2E_TEST" = "tests-dfx/deps.bash" ]; then - cargo install ic-wasm + cargo install cargo-binstall + cargo binstall -y ic-wasm fi # Set environment variables. diff --git a/src/canisters/frontend/ic-asset/src/lib.rs b/src/canisters/frontend/ic-asset/src/lib.rs index 8059916760..9e9fa6f454 100644 --- a/src/canisters/frontend/ic-asset/src/lib.rs +++ b/src/canisters/frontend/ic-asset/src/lib.rs @@ -3,7 +3,7 @@ //! # Example //! //! ```rust,no_run -//! use ic_agent::agent::{Agent, http_transport::ReqwestHttpReplicaV2Transport}; +//! use ic_agent::agent::{Agent, http_transport::ReqwestTransport}; //! use ic_agent::identity::BasicIdentity; //! use ic_utils::Canister; //! use std::time::Duration; @@ -12,7 +12,7 @@ //! # let pemfile = ""; //! # let canister_id = ""; //! let agent = Agent::builder() -//! .with_transport(ReqwestHttpReplicaV2Transport::create(replica_url)?) +//! .with_transport(ReqwestTransport::create(replica_url)?) //! .with_identity(BasicIdentity::from_pem_file(pemfile)?) //! .build()?; //! let canister = Canister::builder() diff --git a/src/canisters/frontend/icx-asset/src/main.rs b/src/canisters/frontend/icx-asset/src/main.rs index 490ed4f36c..818180c6dd 100644 --- a/src/canisters/frontend/icx-asset/src/main.rs +++ b/src/canisters/frontend/icx-asset/src/main.rs @@ -110,9 +110,9 @@ async fn main() -> anyhow::Result<()> { let logger = support::new_logger(); let agent = Agent::builder() - .with_transport( - agent::http_transport::ReqwestHttpReplicaV2Transport::create(opts.replica.clone())?, - ) + .with_transport(agent::http_transport::ReqwestTransport::create( + opts.replica.clone(), + )?) .with_boxed_identity(create_identity(opts.pem)) .build()?; diff --git a/src/dfx-core/src/config/model/canister_id_store.rs b/src/dfx-core/src/config/model/canister_id_store.rs index 150c7906eb..76485bef5a 100644 --- a/src/dfx-core/src/config/model/canister_id_store.rs +++ b/src/dfx-core/src/config/model/canister_id_store.rs @@ -188,10 +188,14 @@ impl CanisterIdStore { self.remote_ids .as_ref() .and_then(|remote_ids| self.get_name_in(canister_id, remote_ids)) - .or_else(|| self.get_name_in(canister_id, &self.ids)) + .or_else(|| self.get_name_in_project(canister_id)) .or_else(|| self.get_name_in_pull_ids(canister_id)) } + pub fn get_name_in_project(&self, canister_id: &str) -> Option<&String> { + self.get_name_in(canister_id, &self.ids) + } + pub fn get_name_in<'a>( &'a self, canister_id: &str, diff --git a/src/dfx-core/src/config/model/dfinity.rs b/src/dfx-core/src/config/model/dfinity.rs index e67d9a7c38..17c8b1d8a7 100644 --- a/src/dfx-core/src/config/model/dfinity.rs +++ b/src/dfx-core/src/config/model/dfinity.rs @@ -3,6 +3,7 @@ use crate::config::directories::get_user_dfx_config_dir; use crate::config::model::bitcoin_adapter::BitcoinAdapterLogLevel; use crate::config::model::canister_http_adapter::HttpAdapterLogLevel; +use crate::error::config::GetOutputEnvFileError; use crate::error::dfx_config::AddDependenciesError::CanisterCircularDependency; use crate::error::dfx_config::GetCanisterNamesWithDependenciesError::AddDependenciesFailed; use crate::error::dfx_config::GetComputeAllocationError::GetComputeAllocationFailed; @@ -1013,6 +1014,35 @@ impl Config { ) } + // returns the path to the output env file if any, guaranteed to be + // a child relative to the project root + pub fn get_output_env_file( + &self, + from_cmdline: Option, + ) -> Result, GetOutputEnvFileError> { + from_cmdline + .or(self.config.output_env_file.clone()) + .map(|p| { + if p.is_relative() { + let p = self.get_project_root().join(p); + + // cannot canonicalize a path that doesn't exist, but the parent should exist + let env_parent = + crate::fs::parent(&p).map_err(GetOutputEnvFileError::Parent)?; + let env_parent = crate::fs::canonicalize(&env_parent) + .map_err(GetOutputEnvFileError::Canonicalize)?; + if !env_parent.starts_with(self.get_project_root()) { + Err(GetOutputEnvFileError::OutputEnvFileMustBeInProjectRoot(p)) + } else { + Ok(self.get_project_root().join(p)) + } + } else { + Err(GetOutputEnvFileError::OutputEnvFileMustBeRelative(p)) + } + }) + .transpose() + } + pub fn save(&self) -> Result<(), StructuredFileError> { save_json_file(&self.path, &self.json) } diff --git a/src/dfx-core/src/error/config.rs b/src/dfx-core/src/error/config.rs index 1121332e42..1658ba575e 100644 --- a/src/dfx-core/src/error/config.rs +++ b/src/dfx-core/src/error/config.rs @@ -1,5 +1,6 @@ use crate::error::fs::FsError; use crate::error::get_user_home::GetUserHomeError; +use std::path::PathBuf; use thiserror::Error; #[derive(Error, Debug)] @@ -13,3 +14,18 @@ pub enum ConfigError { #[error("Failed to determine shared network data directory: {0}")] DetermineSharedNetworkDirectoryFailed(GetUserHomeError), } + +#[derive(Error, Debug)] +pub enum GetOutputEnvFileError { + #[error("failed to canonicalize output_env_file")] + Canonicalize(#[source] FsError), + + #[error("The output_env_file must be within the project root, but is {}", .0.display())] + OutputEnvFileMustBeInProjectRoot(PathBuf), + + #[error("The output_env_file must be a relative path, but is {}", .0.display())] + OutputEnvFileMustBeRelative(PathBuf), + + #[error(transparent)] + Parent(FsError), +} diff --git a/src/dfx-core/src/util/mod.rs b/src/dfx-core/src/util/mod.rs index 64a9d30f9f..efb41ba088 100644 --- a/src/dfx-core/src/util/mod.rs +++ b/src/dfx-core/src/util/mod.rs @@ -6,5 +6,6 @@ pub fn network_to_pathcompat(network_name: &str) -> String { pub fn expiry_duration() -> Duration { // 5 minutes is max ingress timeout - Duration::from_secs(60 * 5) + // 4 minutes accounts for possible replica drift + Duration::from_secs(60 * 4) } diff --git a/src/dfx/Cargo.toml b/src/dfx/Cargo.toml index 535aa84ba8..049cadf038 100644 --- a/src/dfx/Cargo.toml +++ b/src/dfx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dfx" -version = "0.15.2-beta.1" +version = "0.15.2-beta.2" authors.workspace = true edition.workspace = true repository.workspace = true @@ -77,7 +77,7 @@ mime.workspace = true mime_guess.workspace = true net2 = "0.2.34" num-traits.workspace = true -os_str_bytes = "6.3.0" +os_str_bytes = { version = "6.3.0", features = ["conversions"] } patch = "0.7.0" pem.workspace = true petgraph = "0.6.0" diff --git a/src/dfx/assets/dfx-asset-sources.toml b/src/dfx/assets/dfx-asset-sources.toml index a44888a10e..5cd20632b0 100644 --- a/src/dfx/assets/dfx-asset-sources.toml +++ b/src/dfx/assets/dfx-asset-sources.toml @@ -30,8 +30,8 @@ url = 'https://download.dfinity.systems/ic/80a6745673a28ee53d257b3fe19dcd6b7efa9 sha256 = 'd42213aea42f1ae55623e7e437ef683e99c0a3a98c1bae7dc24db7c1577005e9' [x86_64-darwin.motoko] -url = 'https://github.com/dfinity/motoko/releases/download/0.10.1/motoko-Darwin-x86_64-0.10.1.tar.gz' -sha256 = 'ebe411afe1a1f86de9f4c6c88396dab3912bf5cef17cc7f5fb0aeb585317ccc6' +url = 'https://github.com/dfinity/motoko/releases/download/0.10.2/motoko-Darwin-x86_64-0.10.2.tar.gz' +sha256 = '866d35fa33ce9de5b459dba72d247ecfb63e288a178a195f91cdb09e3fc789f4' # The replica and canister_sandbox binaries must have the same revision. [x86_64-darwin.replica] @@ -52,12 +52,12 @@ url = 'https://download.dfinity.systems/ic/80a6745673a28ee53d257b3fe19dcd6b7efa9 sha256 = '73a6d72d82025abb58c28d6ada411ac40ed5b482017f409133f7ac5562899990' [x86_64-darwin.motoko-base] -url = 'https://github.com/dfinity/motoko/releases/download/0.10.1/motoko-base-library.tar.gz' -sha256 = '27563ee89ad2b6c24642ccd9b569836cef2a0316d33bc3d2b4cc61ed7ec1017e' +url = 'https://github.com/dfinity/motoko/releases/download/0.10.2/motoko-base-library.tar.gz' +sha256 = 'cfa7950a3f452b0d8f42320061be09176a7aecee5a7851d913a1517a8116fd46' [x86_64-darwin.ic-btc-canister] -url = 'https://github.com/dfinity/bitcoin-canister/releases/download/release%2F2023-03-31/ic-btc-canister.wasm.gz' -sha256 = 'c4153339cc3d23eae8f5e5a9c3872df5e5713913357e11d493bc5d06f257fb47' +url = 'https://github.com/dfinity/bitcoin-canister/releases/download/release%2F2023-10-13/ic-btc-canister.wasm.gz' +sha256 = '09f5647a45ff6d5d05b2b0ed48613fb2365b5fe6573ba0e901509c39fb9564ac' [x86_64-linux.ic-ref] url = 'https://download.dfinity.systems/ic-ref/ic-ref-0.0.1-a9f73dba-x86_64-linux.tar.gz' @@ -88,8 +88,8 @@ url = 'https://download.dfinity.systems/ic/80a6745673a28ee53d257b3fe19dcd6b7efa9 sha256 = 'eb5ea6cd768fda12d00f370665db132d66c262b35f1a513c2807f78881c1cb7a' [x86_64-linux.motoko] -url = 'https://github.com/dfinity/motoko/releases/download/0.10.1/motoko-Linux-x86_64-0.10.1.tar.gz' -sha256 = '8cba445eb38e6fb652de68c0f2ae9b29cfcd933e0c63a9703f3d104e411e5d86' +url = 'https://github.com/dfinity/motoko/releases/download/0.10.2/motoko-Linux-x86_64-0.10.2.tar.gz' +sha256 = 'daa3fb7c739174296711334f0616745bc8839027432538261e05b4cc95d83ea8' # The replica and canister_sandbox binaries must have the same revision. [x86_64-linux.replica] @@ -110,9 +110,9 @@ url = 'https://download.dfinity.systems/ic/80a6745673a28ee53d257b3fe19dcd6b7efa9 sha256 = 'a9e30c500fb108ab5247db0827868fb74914939a04519d08943440f12b020db8' [x86_64-linux.motoko-base] -url = 'https://github.com/dfinity/motoko/releases/download/0.10.1/motoko-base-library.tar.gz' -sha256 = '27563ee89ad2b6c24642ccd9b569836cef2a0316d33bc3d2b4cc61ed7ec1017e' +url = 'https://github.com/dfinity/motoko/releases/download/0.10.2/motoko-base-library.tar.gz' +sha256 = 'cfa7950a3f452b0d8f42320061be09176a7aecee5a7851d913a1517a8116fd46' [x86_64-linux.ic-btc-canister] -url = 'https://github.com/dfinity/bitcoin-canister/releases/download/release%2F2023-03-31/ic-btc-canister.wasm.gz' -sha256 = 'c4153339cc3d23eae8f5e5a9c3872df5e5713913357e11d493bc5d06f257fb47' +url = 'https://github.com/dfinity/bitcoin-canister/releases/download/release%2F2023-10-13/ic-btc-canister.wasm.gz' +sha256 = '09f5647a45ff6d5d05b2b0ed48613fb2365b5fe6573ba0e901509c39fb9564ac' diff --git a/src/dfx/src/commands/build.rs b/src/dfx/src/commands/build.rs index d9abf3412b..22d58f3dcf 100644 --- a/src/dfx/src/commands/build.rs +++ b/src/dfx/src/commands/build.rs @@ -40,9 +40,7 @@ pub fn exec(env: &dyn Environment, opts: CanisterBuildOpts) -> DfxResult { // Read the config. let config = env.get_config_or_anyhow()?; - let env_file = opts - .output_env_file - .or_else(|| config.get_config().output_env_file.clone()); + let env_file = config.get_output_env_file(opts.output_env_file)?; // Check the cache. This will only install the cache if there isn't one installed // already. diff --git a/src/dfx/src/commands/canister/delete.rs b/src/dfx/src/commands/canister/delete.rs index 09f906c96b..db20159dab 100644 --- a/src/dfx/src/commands/canister/delete.rs +++ b/src/dfx/src/commands/canister/delete.rs @@ -91,10 +91,15 @@ async fn delete_canister( ) -> DfxResult { let log = env.get_logger(); let mut canister_id_store = env.get_canister_id_store()?; + let (canister_id, canister_name_to_delete) = match Principal::from_text(canister) { + Ok(canister_id) => ( + canister_id, + canister_id_store.get_name_in_project(canister).cloned(), + ), + Err(_) => (canister_id_store.get(canister)?, Some(canister.to_string())), + }; if !env.get_network_descriptor().is_playground() { - let canister_id = - Principal::from_text(canister).or_else(|_| canister_id_store.get(canister))?; let mut call_sender = call_sender; let to_dank = withdraw_cycles_to_dank || withdraw_cycles_to_dank_principal.is_some(); @@ -268,7 +273,10 @@ async fn delete_canister( canister::delete_canister(env, canister_id, call_sender).await?; } - canister_id_store.remove(canister)?; + + if let Some(canister_name) = canister_name_to_delete { + canister_id_store.remove(&canister_name)?; + } Ok(()) } diff --git a/src/dfx/src/commands/canister/deposit_cycles.rs b/src/dfx/src/commands/canister/deposit_cycles.rs index d68d975b01..1db9ed67f2 100644 --- a/src/dfx/src/commands/canister/deposit_cycles.rs +++ b/src/dfx/src/commands/canister/deposit_cycles.rs @@ -60,6 +60,8 @@ pub async fn exec( opts: DepositCyclesOpts, mut call_sender: &CallSender, ) -> DfxResult { + fetch_root_key_if_needed(env).await?; + let proxy_sender; // choose default wallet if no wallet is specified @@ -79,8 +81,6 @@ pub async fn exec( let config = env.get_config_or_anyhow()?; - fetch_root_key_if_needed(env).await?; - if let Some(canister) = opts.canister.as_deref() { deposit_cycles(env, canister, call_sender, cycles).await } else if opts.all { diff --git a/src/dfx/src/commands/canister/install.rs b/src/dfx/src/commands/canister/install.rs index 2985cbb347..0b01dd243d 100644 --- a/src/dfx/src/commands/canister/install.rs +++ b/src/dfx/src/commands/canister/install.rs @@ -3,8 +3,12 @@ use crate::lib::environment::Environment; use crate::lib::error::DfxResult; use crate::lib::operations::canister::install_canister::install_canister; use crate::lib::root_key::fetch_root_key_if_needed; +use crate::util::clap::parsers::file_or_stdin_parser; use crate::util::get_candid_init_type; -use crate::{lib::canister_info::CanisterInfo, util::blob_from_arguments}; +use crate::{ + lib::canister_info::CanisterInfo, + util::{arguments_from_file, blob_from_arguments}, +}; use dfx_core::identity::CallSender; use anyhow::{anyhow, bail, Context}; @@ -40,9 +44,17 @@ pub struct CanisterInstallOpts { upgrade_unchanged: bool, /// Specifies the argument to pass to the method. - #[arg(long)] + #[arg(long, conflicts_with("argument_file"))] argument: Option, + /// Specifies the file from which to read the argument to pass to the method. + #[arg( + long, + value_parser = file_or_stdin_parser, + conflicts_with("argument") + )] + argument_file: Option, + /// Specifies the data type for the argument when making the call using an argument. #[arg(long, requires("argument"), value_parser = ["idl", "raw"])] argument_type: Option, @@ -107,7 +119,14 @@ pub async fn exec( let canister_id = Principal::from_text(canister).or_else(|_| canister_id_store.get(canister))?; + + let arguments_from_file = opts + .argument_file + .map(|v| arguments_from_file(&v)) + .transpose()?; let arguments = opts.argument.as_deref(); + let arguments = arguments_from_file.as_deref().or(arguments); + let arg_type = opts.argument_type.as_deref(); let canister_info = config.as_ref() .ok_or_else(|| anyhow!("Cannot find dfx configuration file in the current working directory. Did you forget to create one?")) @@ -136,9 +155,7 @@ pub async fn exec( } else { let canister_info = canister_info?; let config = config.unwrap(); - let env_file = opts - .output_env_file - .or_else(|| config.get_config().output_env_file.clone()); + let env_file = config.get_output_env_file(opts.output_env_file)?; let idl_path = canister_info.get_constructor_idl_path(); let init_type = get_candid_init_type(&idl_path); let install_args = || blob_from_arguments(arguments, None, arg_type, &init_type); @@ -163,9 +180,7 @@ pub async fn exec( } else if opts.all { // Install all canisters. let config = env.get_config_or_anyhow()?; - let env_file = opts - .output_env_file - .or_else(|| config.get_config().output_env_file.clone()); + let env_file = config.get_output_env_file(opts.output_env_file)?; if let Some(canisters) = &config.get_config().canisters { for canister in canisters.keys() { if pull_canisters_in_config.contains_key(canister) { diff --git a/src/dfx/src/commands/canister/send.rs b/src/dfx/src/commands/canister/send.rs index 2aced0088b..17e14789dc 100644 --- a/src/dfx/src/commands/canister/send.rs +++ b/src/dfx/src/commands/canister/send.rs @@ -6,7 +6,7 @@ use candid::Principal; use clap::Parser; use dfx_core::identity::CallSender; use ic_agent::agent::Transport; -use ic_agent::{agent::http_transport::ReqwestHttpReplicaV2Transport, RequestId}; +use ic_agent::{agent::http_transport::ReqwestTransport, RequestId}; use std::{fs::File, path::Path}; use std::{io::Read, str::FromStr}; @@ -40,8 +40,8 @@ pub async fn exec( message.validate()?; let network = message.network.clone(); - let transport = ReqwestHttpReplicaV2Transport::create(network) - .context("Failed to create transport object.")?; + let transport = + ReqwestTransport::create(network).context("Failed to create transport object.")?; let content = hex::decode(&message.content).context("Failed to decode message content.")?; let canister_id = Principal::from_text(message.canister_id.clone()) .with_context(|| format!("Failed to parse canister id {:?}.", message.canister_id))?; diff --git a/src/dfx/src/commands/cycles/balance.rs b/src/dfx/src/commands/cycles/balance.rs index 1cdbe78e1b..bfddfd64b7 100644 --- a/src/dfx/src/commands/cycles/balance.rs +++ b/src/dfx/src/commands/cycles/balance.rs @@ -2,6 +2,7 @@ use crate::lib::environment::Environment; use crate::lib::error::DfxResult; use crate::lib::nns_types::account_identifier::Subaccount; use crate::lib::operations::cycles_ledger; +use crate::lib::root_key::fetch_root_key_if_needed; use crate::util::{format_as_trillions, pretty_thousand_separators}; use candid::Principal; use clap::Parser; @@ -29,6 +30,8 @@ pub struct CyclesBalanceOpts { } pub async fn exec(env: &dyn Environment, opts: CyclesBalanceOpts) -> DfxResult { + fetch_root_key_if_needed(env).await?; + let agent = env.get_agent(); let owner = opts.owner.unwrap_or_else(|| { diff --git a/src/dfx/src/commands/deploy.rs b/src/dfx/src/commands/deploy.rs index 7a429dcd85..5058ecb88f 100644 --- a/src/dfx/src/commands/deploy.rs +++ b/src/dfx/src/commands/deploy.rs @@ -115,9 +115,7 @@ pub fn exec(env: &dyn Environment, opts: DeployOpts) -> DfxResult { .map_err(|err| anyhow!(err)) .context("Failed to parse InstallMode.")?; let config = env.get_config_or_anyhow()?; - let env_file = opts - .output_env_file - .or_else(|| config.get_config().output_env_file.clone()); + let env_file = config.get_output_env_file(opts.output_env_file)?; let with_cycles = opts.with_cycles; diff --git a/src/dfx/src/commands/extension/install.rs b/src/dfx/src/commands/extension/install.rs index 6435915951..58e6b472d7 100644 --- a/src/dfx/src/commands/extension/install.rs +++ b/src/dfx/src/commands/extension/install.rs @@ -1,4 +1,5 @@ use crate::commands::DfxCommand; +use crate::config::cache::DiskBasedCache; use crate::lib::environment::Environment; use crate::lib::error::DfxResult; use clap::Parser; @@ -19,6 +20,9 @@ pub struct InstallOpts { } pub fn exec(env: &dyn Environment, opts: InstallOpts) -> DfxResult<()> { + // creating an `extensions` directory in an otherwise empty cache directory would + // cause the cache to be considered "installed" and later commands would fail + DiskBasedCache::install(&env.get_cache().version_str())?; let spinner = env.new_spinner(format!("Installing extension: {}", opts.name).into()); let mgr = env.new_extension_manager()?; let effective_extension_name = opts.install_as.clone().unwrap_or_else(|| opts.name.clone()); diff --git a/src/dfx/src/commands/ledger/balance.rs b/src/dfx/src/commands/ledger/balance.rs index f02fd0657c..6d397ea02d 100644 --- a/src/dfx/src/commands/ledger/balance.rs +++ b/src/dfx/src/commands/ledger/balance.rs @@ -2,6 +2,7 @@ use crate::lib::environment::Environment; use crate::lib::error::DfxResult; use crate::lib::nns_types::account_identifier::{AccountIdentifier, Subaccount}; use crate::lib::operations::ledger; +use crate::lib::root_key::fetch_root_key_if_needed; use anyhow::anyhow; use candid::Principal; use clap::Parser; @@ -23,6 +24,7 @@ pub struct BalanceOpts { } pub async fn exec(env: &dyn Environment, opts: BalanceOpts) -> DfxResult { + fetch_root_key_if_needed(env).await?; let sender = env .get_selected_identity_principal() .expect("Selected identity not instantiated."); diff --git a/src/dfx/src/lib/builders/mod.rs b/src/dfx/src/lib/builders/mod.rs index cfa2934da2..0a553ef1ff 100644 --- a/src/dfx/src/lib/builders/mod.rs +++ b/src/dfx/src/lib/builders/mod.rs @@ -448,7 +448,7 @@ fn write_environment_variables(vars: &[Env<'_>], write_path: &Path) -> DfxResult // the section is correctly formed let end_pos = end_pos + END_TAG.len() + start_pos + START_TAG.len(); existing_file.replace_range(start_pos..end_pos, &write_string); - fs::write(write_path, existing_file)?; + dfx_core::fs::write(write_path, existing_file)?; return Ok(()); } else { // the file has been edited, so we don't know how much to delete, so we append instead @@ -456,10 +456,10 @@ fn write_environment_variables(vars: &[Env<'_>], write_path: &Path) -> DfxResult } // append to the existing file existing_file.push_str(&write_string); - fs::write(write_path, existing_file)?; + dfx_core::fs::write(write_path, existing_file)?; } else { // no existing file, okay to clobber - fs::write(write_path, write_string)?; + dfx_core::fs::write(write_path, write_string)?; } Ok(()) } @@ -501,7 +501,7 @@ impl BuildConfig { idl_root: canister_root.join("idl/"), // TODO: possibly move to `network_root.join("idl/")` lsp_root: network_root.join("lsp/"), canisters_to_build: None, - env_file: config_intf.output_env_file.clone(), + env_file: config.get_output_env_file(None)?, }) } diff --git a/src/dfx/src/lib/environment.rs b/src/dfx/src/lib/environment.rs index f1056a72ee..e77b2ab090 100644 --- a/src/dfx/src/lib/environment.rs +++ b/src/dfx/src/lib/environment.rs @@ -383,11 +383,14 @@ pub fn create_agent( identity: Box, timeout: Duration, ) -> DfxResult { + let disable_query_verification = + std::env::var("DFX_DISABLE_QUERY_VERIFICATION").is_ok_and(|x| !x.trim().is_empty()); let agent = Agent::builder() .with_transport(ic_agent::agent::http_transport::ReqwestTransport::create( url, )?) .with_boxed_identity(identity) + .with_verify_query_signatures(!disable_query_verification) .with_ingress_expiry(Some(timeout)) .build()?; Ok(agent) diff --git a/src/dfx/src/lib/replica/status.rs b/src/dfx/src/lib/replica/status.rs index 8851ff78bf..3efc7ee84f 100644 --- a/src/dfx/src/lib/replica/status.rs +++ b/src/dfx/src/lib/replica/status.rs @@ -1,13 +1,13 @@ use crate::lib::error::DfxResult; use anyhow::{bail, Context}; -use ic_agent::agent::http_transport::ReqwestHttpReplicaV2Transport; +use ic_agent::agent::http_transport::ReqwestTransport; use ic_agent::Agent; use std::time::Duration; pub async fn ping_and_wait(url: &str) -> DfxResult { let agent = Agent::builder() .with_transport( - ReqwestHttpReplicaV2Transport::create(url) + ReqwestTransport::create(url) .with_context(|| format!("Failed to create replica transport from url {url}.",))?, ) .build() diff --git a/src/dfx/src/lib/sign/sign_transport.rs b/src/dfx/src/lib/sign/sign_transport.rs index 217b9ab9a6..768af94107 100644 --- a/src/dfx/src/lib/sign/sign_transport.rs +++ b/src/dfx/src/lib/sign/sign_transport.rs @@ -65,6 +65,19 @@ impl Transport for SignTransport { Box::pin(run(self, envelope)) } + fn read_subnet_state( + &self, + _: Principal, + _: Vec, + ) -> Pin, AgentError>> + Send + '_>> { + async fn run() -> Result, AgentError> { + Err(AgentError::MessageError( + "read_subnet_state calls not supported".to_string(), + )) + } + Box::pin(run()) + } + fn call<'a>( &'a self, _effective_canister_id: Principal, diff --git a/src/dfx/src/util/currency_conversion.rs b/src/dfx/src/util/currency_conversion.rs index 1980e091b1..ad312582f9 100644 --- a/src/dfx/src/util/currency_conversion.rs +++ b/src/dfx/src/util/currency_conversion.rs @@ -4,7 +4,7 @@ use crate::lib::{ use anyhow::Context; use dfx_core::config::model::dfinity::DEFAULT_IC_GATEWAY; use fn_error_context::context; -use ic_agent::{agent::http_transport::ReqwestHttpReplicaV2Transport, Agent}; +use ic_agent::{agent::http_transport::ReqwestTransport, Agent}; use rust_decimal::Decimal; /// How many cycles you get per XDR when converting ICP to cycles @@ -16,7 +16,7 @@ const CYCLES_PER_XDR: u128 = 1_000_000_000_000; pub async fn as_cycles_with_current_exchange_rate(icpts: &ICPTs) -> DfxResult { let agent = Agent::builder() .with_transport( - ReqwestHttpReplicaV2Transport::create(DEFAULT_IC_GATEWAY) + ReqwestTransport::create(DEFAULT_IC_GATEWAY) .context("Failed to create transport object to default ic gateway.")?, ) .build()