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..b3fc7470fd 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -82,7 +82,6 @@ jobs: strategy: fail-fast: false matrix: - backend: ["ic-ref", "replica"] # macos-latest is currently macos-11, ubuntu-latest is currently ubuntu-20.04 # ubuntu-18.04 not supported due to: # /home/runner/.cache/dfinity/versions/0.8.3-34-g36e39809/ic-starter: @@ -97,17 +96,17 @@ 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 time dfx cache install time dfx new smoke cd smoke - if [ "${{ matrix.backend}}" = "ic-ref" ]; then - time dfx start --emulator --background - else - time dfx start --background - fi + time dfx start --background time dfx deploy time dfx canister call smoke_backend greet '("fire")' time curl --fail http://localhost:"$(dfx info webserver-port)"/sample-asset.txt?canisterId=$(dfx canister id smoke_frontend) @@ -153,10 +152,50 @@ jobs: - name: Run e2e test run: timeout 2400 bats "e2e/$E2E_TEST" + ui_test: + runs-on: ${{ matrix.os }} + needs: [build_dfx] + strategy: + matrix: + os: [macos-12, ubuntu-20.04, ubuntu-22.04] + steps: + - name: Checking out repo + uses: actions/checkout@v4 + - name: Setting up Python + uses: actions/setup-python@v4 + with: + python-version: '3.9' + - name: Installing playwright + run: | + pip install playwright==1.40.0 + playwright install + playwright install-deps + - name: Download dfx binary + uses: actions/download-artifact@v3 + with: + name: dfx-${{ matrix.os }}-rs-${{ hashFiles('rust-toolchain.toml') }} + path: /usr/local/bin + - name: Setup dfx binary + run: chmod +x /usr/local/bin/dfx + - name: Deploy default dfx project + run: | + dfx new e2e_project + cd e2e_project + dfx start --background --clean + dfx deploy 2>&1 | tee deploy.log + echo FRONTEND_URL=$(grep "_frontend:" deploy.log | grep -Eo "(http|https)://[a-zA-Z0-9./?=_&%:-]*") >> $GITHUB_ENV + echo CANDID_URL=$(grep "_backend:" deploy.log | grep -Eo "(http|https)://[a-zA-Z0-9./?=_&%:-]*") >> $GITHUB_ENV + - name: Running the Python script + run: | + python scripts/test-uis.py \ + --frontend_url "$FRONTEND_URL" \ + --candid_url "$CANDID_URL" \ + --browser chromium firefox webkit + aggregate: name: e2e:required if: ${{ always() }} - needs: [test, smoke] + needs: [test, smoke, ui_test] runs-on: ubuntu-latest steps: - name: check smoke test result diff --git a/.github/workflows/publish-dfxvm-install-script.yml b/.github/workflows/publish-dfxvm-install-script.yml new file mode 100644 index 0000000000..14ca33c04b --- /dev/null +++ b/.github/workflows/publish-dfxvm-install-script.yml @@ -0,0 +1,47 @@ +name: Publish dfxvm install script + +on: + push: + branches: + - sdk-1278-dfxvm-install-script + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + # When getting Rust dependencies, retry on network error: + CARGO_NET_RETRY: 10 + # Use the local .curlrc + CURL_HOME: . + +jobs: + publish-manifest: + name: dfxvm-install-script-shellcheck + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install shfmt + run: go install mvdan.cc/sh/v3/cmd/shfmt@latest + - name: Generate + run: | + shellcheck --shell=sh public/install/*.sh --exclude SC2154,SC2034,SC3003,SC3014,SC3043 + ~/go/bin/shfmt -d -p -i 4 -ci -bn -s public/install/*.sh + sed -i "s/@revision@/${GITHUB_SHA}/" public/install/999_footer.sh + mkdir _out + cat public/install/*.sh > _out/install.sh + sed -i " + /#!.*/p + /##.*/p + /^ *$/d + /^ *#/d + s/ *#.*// + " _out/install.sh + - name: Upload Artifacts + if: github.event_name == 'push' + uses: JamesIves/github-pages-deploy-action@releases/v3 + with: + single_commit: yes + branch: dfxvm-install-script + folder: _out/ diff --git a/.github/workflows/publish-manifest.yml b/.github/workflows/publish-manifest.yml index a6fa2840e4..da3dea0c11 100644 --- a/.github/workflows/publish-manifest.yml +++ b/.github/workflows/publish-manifest.yml @@ -4,6 +4,7 @@ on: push: branches: - master + pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -17,6 +18,7 @@ env: jobs: publish-manifest: + name: install-script-shellcheck:required runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -38,6 +40,7 @@ jobs: " _out/install.sh cp public/manifest.json _out/manifest.json - name: Upload Artifacts + if: github.event_name == 'push' uses: JamesIves/github-pages-deploy-action@releases/v3 with: single_commit: yes diff --git a/CHANGELOG.md b/CHANGELOG.md index c9b5597e64..622a1a4fd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,165 @@ ### fix: frontend code crashing when there is no canister ID +### feat: `dfx ledger top-up` also accepts canister names + +Previously, `dfx ledger top-up` only accepted canister principals. Now it accepts both principals and canister names. + +### fix: installer once again detects if curl supports tlsv1.2 + +A change to `curl --help` output made it so the install script did not detect +that the `--proto` and `--tlsv1.2` options are available. + +### feat: Added support for icx-proxy `--domain` parameter + +In order to access a local replica through a domain name or domain names, +it's necessary to pass the `--domain` parameter to icx-proxy. dfx now supports +this in configuration and as a parameter to dfx start. You can specify a single +domain or a list of domains in any of the following ways: + +- in networks.json, in `..proxy.domain` +- in dfx.json, in `.networks..proxy.domain` +- in dfx.json, in `.defaults.proxy.domain` +- to dfx start, as `dfx start --domain --domain ...` + +## Dependencies + +### Candid UI + +- Module hash: d172df265a14397a460b752ff07598380bc7ebd9c43ece1e82495ae478a88719c +- Internet identity integration in Candid UI. Thanks to @Samer! + + You can customize the II url and derivationOrigin via URL parameter `ii` and `origin` respectively. +- Update with the new profiling API + + +# 0.15.2 + +### 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 +call it as a query call. This resolves a potential security risk. + +### fix: `dfx ledger transfer` now logs to stderr messages about duplicates rather than printing them to stdout + +The message "transaction is a duplicate of another transaction in block ...", previously printed to stdout, is now logged to stderr. This means that the output of `dfx ledger transfer` to stdout will contain only "Transfer sent at block height ". + +### feat: accept more ways to specify cycle and e8s amounts + +Underscores (`_`) can now be used to make large numbers more readable. For example: `dfx canister deposit-cycles 1_234_567 mycanister` + +Certain suffixes that replace a number of zeros are now supported. The (case-insensitive) suffixes are: +- `k` for `000`, e.g. `500k` +- `m` for `000_000`, e.g. `5m` +- `b` for `000_000_000`, e.g. `50B` +- `t` for `000_000_000_000`, e.g. `0.3T` + +For cycles an additional `c` or `C` is also acceptable. For example: `dfx canister deposit-cycles 3TC mycanister` + +### feat: added `dfx cycles` command + +This won't work on mainnet yet, but can work locally after installing the cycles ledger. + +Added the following subcommands: + - `dfx cycles balance` + - `dfx cycles transfer ` (transfer cycles from one account to another account) + - `dfx cycles top-up ` (send cycles from an account to a canister) + +## Dependencies + +### Motoko + +Updated Motoko to [0.10.2](https://github.com/dfinity/motoko/releases/tag/0.10.2) + +### Frontend canister + +Defining a custom `etag` header no longer breaks certification. + +Fixed a certification issue where under certain conditions the fallback file (`/index.html`) was served with an incomplete certificate tree, not proving sufficiently that the fallback file may be used as a replacement. + +Add the option to (re)set all permissions using upgrade arguments. This is especially useful for SNSes that cannot make calls as the canister's controller. + +- Module hash: 657938477f1dee46db70b5a9f0bd167ec5ffcd2f930a1d96593c17dcddef61b3 +- https://github.com/dfinity/sdk/pull/3443 +- https://github.com/dfinity/sdk/pull/3451 +- https://github.com/dfinity/sdk/pull/3429 +- https://github.com/dfinity/sdk/pull/3428 +- https://github.com/dfinity/sdk/pull/3421 + +### Replica + +Updated replica to elected commit 69e1408347723dbaa7a6cd2faa9b65c42abbe861. +This incorporates the following executed proposals: + +- [126095](https://dashboard.internetcomputer.org/proposal/126095) +- [126000](https://dashboard.internetcomputer.org/proposal/126000) +- [125592](https://dashboard.internetcomputer.org/proposal/125592) +- [125591](https://dashboard.internetcomputer.org/proposal/125591) +- [125504](https://dashboard.internetcomputer.org/proposal/125504) +- [125503](https://dashboard.internetcomputer.org/proposal/125503) +- [125343](https://dashboard.internetcomputer.org/proposal/125343) +- [125342](https://dashboard.internetcomputer.org/proposal/125342) +- [125321](https://dashboard.internetcomputer.org/proposal/125321) +- [125320](https://dashboard.internetcomputer.org/proposal/125320) +- [125002](https://dashboard.internetcomputer.org/proposal/125002) +- [125001](https://dashboard.internetcomputer.org/proposal/125001) +- [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 + +`dfx canister status` will now display the reserved cycles balance and reserved cycles limit for a canister. + +Added command-line options: + - `dfx canister create --reserved-cycles-limit ` + - `dfx canister update-settings --reserved-cycles-limit ` + +In addition, `dfx deploy` will set `reserved_cycles_limit` when creating canisters if specified in `canisters..initialization_values.reserved_cycles_limit` in dfx.json. + +### feat: emit management canister idl when imported by Motoko canister + +`import management "ic:aaaaa-aa;` + +This will automatically produce the idl in the `.dfx` folder. + ### fix: Include remote canisters in canisters_to_generate Generate frontend declarations for remote canisters too because frontend JS code may want to call them. +### feat: dfx extension install --version + +Install a specific version of an extension, bypassing version checks. + ### feat: Updated handling of missing values in state tree certificates The `Unknown` lookup of a path in a certificate results in an `AgentError` (the IC returns `Absent` for non-existing paths). @@ -99,6 +254,8 @@ The verifying side can then unzip the response and will have a valid certificate - https://github.com/dfinity/sdk/pull/3298 - https://github.com/dfinity/sdk/pull/3281 +### Replica + Updated replica to elected commit 91bf38ff3cb927cb94027d9da513cd15f91a5b04. This incorporates the following executed proposals: @@ -328,7 +485,7 @@ Previously, it would only retry when waiting for the request to complete. ### fix: now considers fewer error types to be retryable -Previously, errors were assumed to be retryable, except for a few specific error messages and 403/unauthorized responses. This could cause deployment to appear to hang until timeout. +Previously, errors were assumed to be retryable, except for a few specific error messages and 403/unauthorized responses. This could cause deployment to appear to hang until timeout. Now, only transport errors and timeout errors are considered retryable. @@ -383,7 +540,7 @@ When running `dfx canister delete` on a canister that has not been stopped, dfx ### feat: gzip option in dfx.json -`dfx` can gzip wasm module as the final step in building canisters. +`dfx` can gzip wasm module as the final step in building canisters. This behavior is disabled by default. @@ -473,7 +630,7 @@ Previously, it would only retry when waiting for the request to complete. ### fix: now considers fewer error types to be retryable -Previously, errors were assumed to be retryable, except for a few specific error messages and 403/unauthorized responses. This could cause deployment to appear to hang until timeout. +Previously, errors were assumed to be retryable, except for a few specific error messages and 403/unauthorized responses. This could cause deployment to appear to hang until timeout. Now, only transport errors and timeout errors are considered retryable. @@ -572,12 +729,12 @@ When creating a canister on non-mainnet replica, you can now specify the caniste `dfx deploy --specified-id ` You can specify the ID in the range of `[0, u64::MAX / 2]`. -If not specify the ID, the canister will be created in the range of `[u64::MAX / 2 + 1, u64::MAX]`. +If not specify the ID, the canister will be created in the range of `[u64::MAX / 2 + 1, u64::MAX]`. This canister ID allocation behavior only applies to the replica, not the emulator (ic-ref). ### feat: dfx nns install --ledger-accounts -`dfx nns install` now takes an option `--ledger-accounts` to initialize the ledger canister with these accounts. +`dfx nns install` now takes an option `--ledger-accounts` to initialize the ledger canister with these accounts. ### fix: update Rust canister template. @@ -585,7 +742,7 @@ This canister ID allocation behavior only applies to the replica, not the emulat ### chore: change the default Internet Computer gateway domain to `icp0.io` -By default, DFX now uses the `icp0.io` domain to connect to Internet Computer as opposed to using `ic0.app`. +By default, DFX now uses the `icp0.io` domain to connect to Internet Computer as opposed to using `ic0.app`. Canisters communicating with `ic0.app` will continue to function nominally. ### feat: --no-asset-upgrade @@ -764,7 +921,7 @@ This is no longer the case. See rules above for grant_permission and revoke_per ### feat(frontend-canister)!: default secure configuration for assets in frontend project template -- Secure HTTP headers, preventing several typical security vulnerabilities (e.g. XSS, clickjacking, and many more). For more details, see comments in `headers` section in [default `.ic-assets.json5`](https://raw.githubusercontent.com/dfinity/sdk/master/src/dfx/assets/new_project_node_files/src/__project_name___frontend/src/.ic-assets.json5). +- Secure HTTP headers, preventing several typical security vulnerabilities (e.g. XSS, clickjacking, and many more). For more details, see comments in `headers` section in [default `.ic-assets.json5`](https://raw.githubusercontent.com/dfinity/sdk/master/src/dfx/assets/new_project_node_files/src/__project_name___frontend/src/.ic-assets.json5). - Configures `allow_raw_access` option in starter `.ic-assets.json5` config files, with the value set to its default value (which is `false`). We are showing that configuration in the default starter projects for the sake of easier discoverability, even though its value is set to the default. ### feat(frontend-canister)!: add `allow_raw_access` config option @@ -782,12 +939,12 @@ By default, the frontend canister will now restrict the access of traffic to the **Important**: Note that any assets already uploaded to an asset canister will be protected by this redirection, because at present the asset synchronization process does not update the `allow_raw_access` property, or any other properties, after creating an asset. This also applies to assets that are deployed without any configuration, and later configured to allow raw access. At the present time, there are two ways to reconfigure an existing asset: 1. re-create the asset - 1. delete the asset in your project's directory + 1. delete the asset in your project's directory 1. execute `dfx deploy` 1. re-create the asset in your project's directory - 1. modify `.ic-assets.json` acordingly + 1. modify `.ic-assets.json` acordingly 1. execute `dfx deploy` -2. via manual candid call +2. via manual candid call ``` dfx canister call PROJECT_NAME_frontend set_asset_properties '( record { key="/robots.txt"; allow_raw_access=opt(opt(true)) })' ``` @@ -803,7 +960,7 @@ Callable only by a controller. Clears list of authorized principals and adds th ### feat(frontend-canister): add `get_asset_properties` and `set_asset_properties` to frontend canister -As part of creating the support for future work, it's now possible to get and set AssetProperties for assets in frontend canister. +As part of creating the support for future work, it's now possible to get and set AssetProperties for assets in frontend canister. ### feat: add `--argument-file` argument to the `dfx canister sign` command @@ -914,7 +1071,7 @@ This incorporates the following executed proposals: ### feat(frontend-canister): add warning if config is provided in `.ic-assets.json` but not used -### fix(frontend-canister): Allow overwriting default HTTP Headers for assets in frontend canister +### fix(frontend-canister): Allow overwriting default HTTP Headers for assets in frontend canister Allows to overwrite `Content-Type`, `Content-Encoding`, and `Cache-Control` HTTP headers with custom values via `.ic-assets.json5` config file. Example `.ic-assets.json5` file: ```json5 @@ -928,7 +1085,7 @@ Allows to overwrite `Content-Type`, `Content-Encoding`, and `Cache-Control` HTTP } ] ``` -This change will trigger the update process for frontend canister (new module hash: `2ff0513123f11c57716d889ca487083fac7d94a4c9434d5879f8d0342ad9d759`). +This change will trigger the update process for frontend canister (new module hash: `2ff0513123f11c57716d889ca487083fac7d94a4c9434d5879f8d0342ad9d759`). ### feat: warn if an unencrypted identity is used on mainnet @@ -1153,12 +1310,12 @@ The running replica port and url are generally useful information. Previously th Instead, the build process relies on `ic-wasm` to provide candid metadata for the canister, and shrinking the canister size by stripping debug symbols and unused fuctions. -Additionally, after build step, the `.wasm` file is archived with `gzip`. +Additionally, after build step, the `.wasm` file is archived with `gzip`. ### chore: Move all `frontend canister`-related code into the SDK repo | from (`repository` `path`) | to (path in `dfinity/sdk` repository) | summary | -|:--------------------------------------------|:-----------------------------------------------|:--------------------------------------------------------------------------------------------| +| :------------------------------------------ | :--------------------------------------------- | :------------------------------------------------------------------------------------------ | | `dfinity/cdk-rs` `/src/ic-certified-assets` | `/src/canisters/frontend/ic-certified-asset` | the core of the frontend canister | | `dfinity/certified-assets` `/` | `/src/canisters/frontend/ic-frontend-canister` | wraps `ic-certified-assets` to build the canister wasm | | `dfinity/agent-rs` `/ic-asset` | `/src/canisters/frontend/ic-asset` | library facilitating interactions with frontend canister (e.g. uploading or listing assets) | @@ -1175,7 +1332,7 @@ as if they were [JSON5](https://json5.org/) format. Example content of the `.ic- "match": "*", // comment /* keys below not wrapped in quotes -*/ cache: { max_age: 999 }, // trailing comma +*/ cache: { max_age: 999 }, // trailing comma }, ] ``` diff --git a/Cargo.lock b/Cargo.lock index cae09245f4..86b31e3f8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,13 +35,14 @@ dependencies = [ [[package]] name = "actix" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f728064aca1c318585bf4bb04ffcfac9e75e508ab4e8b1bd9ba5dfe04e2cbed5" +checksum = "cba56612922b907719d4a01cf11c8d5b458e7d3dba946d0435f20f58d6795ed2" dependencies = [ + "actix-macros", "actix-rt", "actix_derive", - "bitflags 1.3.2", + "bitflags 2.4.1", "bytes", "crossbeam-channel", "futures-core", @@ -57,11 +58,21 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "actix-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" +dependencies = [ + "quote", + "syn 2.0.38", +] + [[package]] name = "actix-rt" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15265b6b8e2347670eb363c47fc8c75208b4a4994b27192f345fcbe707804f3e" +checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d" dependencies = [ "futures-core", "tokio", @@ -69,22 +80,22 @@ dependencies = [ [[package]] name = "actix_derive" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d44b8fee1ced9671ba043476deddef739dd0959bf77030b26b738cc591737a7" +checksum = "7c7db3d5a9718568e4cf4a537cfd7070e6e6ff7481510d0237fb529ac850f6d3" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] name = "addr2line" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ - "gimli 0.27.3", + "gimli 0.28.0", ] [[package]] @@ -136,9 +147,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" dependencies = [ "getrandom", "once_cell", @@ -147,24 +158,31 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if 1.0.0", "once_cell", "version_check", + "zerocopy", ] [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" 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" @@ -182,39 +200,38 @@ dependencies = [ [[package]] name = "annotate-snippets" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3b9d411ecbaf79885c6df4d75fff75858d5995ff25385657a28af47e82f9c36" +checksum = "ccaf7e9dfbb6ab22c82e473cd1a8a7bd313c19a5b7e40970f3d89ef5a5c9e81e" dependencies = [ "unicode-width", ] [[package]] name = "anstream" -version = "0.3.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" dependencies = [ "utf8parse", ] @@ -230,9 +247,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", "windows-sys 0.48.0", @@ -240,9 +257,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "apply-patch" @@ -254,9 +271,9 @@ dependencies = [ [[package]] name = "arbitrary" -version = "1.3.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" [[package]] name = "argon2" @@ -314,30 +331,30 @@ dependencies = [ "log", "parking", "polling", - "rustix 0.37.23", + "rustix 0.37.27", "slab", - "socket2", + "socket2 0.4.10", "waker-fn", ] [[package]] name = "async-lock" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ "event-listener", ] [[package]] name = "async-trait" -version = "0.1.71" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] @@ -373,9 +390,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", @@ -418,9 +435,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "base64ct" @@ -479,7 +496,7 @@ dependencies = [ "pbkdf2", "rand_core", "ripemd", - "sha2 0.10.7", + "sha2 0.10.8", "subtle", "zeroize", ] @@ -507,9 +524,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "bitvec" @@ -636,9 +653,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" +checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019" dependencies = [ "memchr", "serde", @@ -646,9 +663,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "byte-unit" @@ -684,21 +701,21 @@ dependencies = [ [[package]] name = "bytecount" -version = "0.6.3" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" +checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cached" @@ -712,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" @@ -730,28 +760,28 @@ dependencies = [ "lalrpop-util 0.19.12", "leb128", "logos 0.12.1", - "num-bigint 0.4.3", + "num-bigint 0.4.4", "num-traits", "num_enum 0.5.11", "paste", "pretty 0.10.0", "serde", "serde_bytes", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", ] [[package]] name = "candid" -version = "0.9.6" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88f6eec0ae850e006ef0fe306f362884d370624094ec55a6a26de18b251774be" +checksum = "465c1ce01d8089ee5b49ba20d3a9da15a28bba64c35cdff2aa256d37e319625d" dependencies = [ "anyhow", "arbitrary", "binread", "byteorder", - "candid_derive 0.6.3", + "candid_derive 0.6.4", "codespan-reporting", "convert_case 0.6.0", "crc32fast", @@ -762,16 +792,16 @@ dependencies = [ "lalrpop-util 0.20.0", "leb128", "logos 0.13.0", - "num-bigint 0.4.3", + "num-bigint 0.4.4", "num-traits", "num_enum 0.6.1", "paste", - "pretty 0.12.1", + "pretty 0.12.3", "rand", "serde", "serde_bytes", "serde_dhall", - "sha2 0.10.7", + "sha2 0.10.8", "stacker", "thiserror", ] @@ -790,23 +820,24 @@ dependencies = [ [[package]] name = "candid_derive" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "158403ea38fab5904ae47a5d67eb7047650a91681407f5ccbcbcabc4f4ffb489" +checksum = "201ea498d901add0822653ac94cb0f8a92f9b1758a5273f4dafbb6673c9a5020" dependencies = [ "lazy_static", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", + "libc", ] [[package]] @@ -823,24 +854,23 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", - "time 0.1.45", "wasm-bindgen", - "winapi", + "windows-targets 0.48.5", ] [[package]] name = "ci_info" -version = "0.14.11" +version = "0.14.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eb8c8d139abf8673b1805f52f6ad398825e24c397dc9ac8283fe588dd6c80d9" +checksum = "e32051a4c1d4548018ac9bfbb648e3a03e09fe72439d5d1ce8b46dcdeb955a92" dependencies = [ "envmnt", ] @@ -856,46 +886,44 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.11" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1640e5cc7fb47dbb8338fd471b105e7ed6c3cb2aeb00c2e067127ffd3764a05d" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" dependencies = [ "clap_builder", "clap_derive", - "once_cell", ] [[package]] name = "clap_builder" -version = "4.3.11" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c59138d527eeaf9b53f35a77fcc1fad9d883116070c63d5de1c7dc7b00c72b" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" dependencies = [ "anstream", "anstyle", "clap_lex", - "once_cell", "strsim", "terminal_size", ] [[package]] name = "clap_derive" -version = "4.3.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "cmake" @@ -971,9 +999,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" dependencies = [ "crossbeam-utils", ] @@ -993,9 +1021,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" [[package]] name = "convert_case" @@ -1030,9 +1058,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -1133,9 +1161,9 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15" +checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" dependencies = [ "generic-array", "rand_core", @@ -1174,14 +1202,27 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a011bbe2c35ce9c1f143b7af6f94f29a167beb4cd1d29e6740ce836f723120e" +checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf" dependencies = [ - "nix 0.26.2", + "nix 0.27.1", "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" @@ -1193,9 +1234,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.100" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e928d50d5858b744d1ea920b790641129c347a770d1530c3a85b77705a5ee031" +checksum = "7129e341034ecb940c9072817cd9007974ea696844fc4dd582dc1653a7fbe2e8" dependencies = [ "cc", "cxxbridge-flags", @@ -1205,9 +1246,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.100" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8332ba63f8a8040ca479de693150129067304a3496674477fff6d0c372cc34ae" +checksum = "a2a24f3f5f8eed71936f21e570436f024f5c2e25628f7496aa7ccd03b90109d5" dependencies = [ "cc", "codespan-reporting", @@ -1215,24 +1256,24 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] name = "cxxbridge-flags" -version = "1.0.100" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5966a5a87b6e9bb342f5fab7170a93c77096efe199872afffc4b477cfeb86957" +checksum = "06fdd177fc61050d63f67f5bd6351fac6ab5526694ea8e359cd9cd3b75857f44" [[package]] name = "cxxbridge-macro" -version = "1.0.100" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b2dab6991c7ab1572fea8cb049db819b1aeea1e2dac74c0869f244d9f21a7c" +checksum = "587663dd5fb3d10932c8aecfe7c844db1bcf0aee93eeab08fac13dc1212c2e7f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] @@ -1295,15 +1336,25 @@ dependencies = [ [[package]] name = "der" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" dependencies = [ "const-oid", "pem-rfc7468 0.7.0", "zeroize", ] +[[package]] +name = "deranged" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", + "serde", +] + [[package]] name = "derivative" version = "2.2.0" @@ -1325,9 +1376,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "deunicode" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a1abaf4d861455be59f64fd2b55606cb151fce304ede7165f410243ce96bde6" + [[package]] name = "dfx" -version = "0.14.3" +version = "0.15.1" dependencies = [ "actix", "aes-gcm", @@ -1340,7 +1397,7 @@ dependencies = [ "base64 0.13.1", "byte-unit", "bytes", - "candid 0.9.6", + "candid 0.9.11", "ci_info", "clap", "console", @@ -1361,9 +1418,11 @@ dependencies = [ "hyper-rustls", "ic-agent", "ic-asset", + "ic-cdk", "ic-identity-hsm", - "ic-utils 0.28.0", + "ic-utils 0.30.2", "ic-wasm", + "icrc-ledger-types", "indicatif", "itertools 0.10.5", "json-patch", @@ -1383,9 +1442,9 @@ dependencies = [ "rand", "regex", "reqwest", - "ring", + "ring 0.16.20", "rust_decimal", - "rustls-webpki 0.101.4", + "rustls-webpki", "schemars", "sec1 0.3.0", "semver", @@ -1393,7 +1452,7 @@ dependencies = [ "serde_bytes", "serde_cbor", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "shell-words", "slog", "slog-async", @@ -1404,9 +1463,9 @@ dependencies = [ "tempfile", "term", "thiserror", - "time 0.3.23", + "time", "tokio", - "toml 0.7.6", + "toml 0.7.8", "url", "walkdir", "walrus", @@ -1422,7 +1481,7 @@ dependencies = [ "bip32", "byte-unit", "bytes", - "candid 0.9.6", + "candid 0.9.11", "clap", "dialoguer", "directories-next", @@ -1431,13 +1490,13 @@ dependencies = [ "humantime-serde", "ic-agent", "ic-identity-hsm", - "ic-utils 0.28.0", + "ic-utils 0.30.2", "k256 0.11.6", "keyring", "lazy_static", "proptest", "reqwest", - "ring", + "ring 0.16.20", "schemars", "sec1 0.3.0", "semver", @@ -1447,7 +1506,7 @@ dependencies = [ "tar", "tempfile", "thiserror", - "time 0.3.23", + "time", "tiny-bip39", "url", ] @@ -1572,9 +1631,9 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "dyn-clone" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" +checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" [[package]] name = "ecdsa" @@ -1590,23 +1649,38 @@ dependencies = [ [[package]] name = "ecdsa" -version = "0.16.7" +version = "0.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" +checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" dependencies = [ - "der 0.7.7", + "der 0.7.8", "digest 0.10.7", - "elliptic-curve 0.13.5", + "elliptic-curve 0.13.6", "rfc6979 0.4.0", "signature 2.1.0", "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.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "elliptic-curve" @@ -1631,12 +1705,12 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.13.5" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +checksum = "d97ca172ae9dc9f9b779a6e3a65d308f2af74e5b8c921299075bdb4a0370e914" dependencies = [ "base16ct 0.2.0", - "crypto-bigint 0.5.2", + "crypto-bigint 0.5.3", "digest 0.10.7", "ff 0.13.0", "generic-array", @@ -1644,16 +1718,16 @@ dependencies = [ "pem-rfc7468 0.7.0", "pkcs8 0.10.2", "rand_core", - "sec1 0.7.2", + "sec1 0.7.3", "subtle", "zeroize", ] [[package]] name = "elsa" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e0aca8dce8856e420195bd13b6a64de3334235ccc9214e824b86b12bf26283" +checksum = "714f766f3556b44e7e4776ad133fcc3445a489517c25c704ace411bb14790194" dependencies = [ "stable_deref_trait", ] @@ -1675,9 +1749,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if 1.0.0", ] @@ -1734,34 +1808,23 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "erased-serde" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da96524cc884f6558f1769b6c46686af2fe8e8b4cd253bd5a3cdba8181b8e070" +checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c" dependencies = [ "serde", ] [[package]] name = "errno" -version = "0.3.1" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" dependencies = [ - "errno-dragonfly", "libc", "windows-sys 0.48.0", ] -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "event-listener" version = "2.5.3" @@ -1770,12 +1833,12 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fake" -version = "2.6.1" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a44c765350db469b774425ff1c833890b16ceb9612fb5d7c4bbdf4a1b55f876" +checksum = "26221445034074d46b276e13eb97a265ebdb8ed8da705c4dddd3dd20b66b45d2" dependencies = [ + "deunicode", "rand", - "unidecode", ] [[package]] @@ -1793,6 +1856,12 @@ dependencies = [ "instant", ] +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + [[package]] name = "features" version = "0.10.0" @@ -1824,13 +1893,13 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.21" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.2.16", + "redox_syscall 0.3.5", "windows-sys 0.48.0", ] @@ -1842,9 +1911,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "libz-ng-sys", @@ -1868,7 +1937,7 @@ checksum = "2cd66269887534af4b0c3e3337404591daa8dc8b9b2b3db71f9523beb4bafb41" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] @@ -1918,9 +1987,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ "futures-channel", "futures-core", @@ -1933,9 +2002,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", "futures-sink", @@ -1943,15 +2012,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" dependencies = [ "futures-core", "futures-task", @@ -1971,9 +2040,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-lite" @@ -1981,7 +2050,7 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ - "fastrand", + "fastrand 1.9.0", "futures-core", "futures-io", "memchr", @@ -1992,32 +2061,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-channel", "futures-core", @@ -2051,7 +2120,7 @@ dependencies = [ "cfg-if 1.0.0", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] @@ -2078,15 +2147,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "globset" -version = "0.4.11" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" +checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" dependencies = [ "aho-corasick", "bstr", @@ -2119,9 +2188,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" dependencies = [ "bytes", "fnv", @@ -2144,9 +2213,9 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "handlebars" -version = "4.3.7" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c3372087601b532857d332f5957cbae686da52bb7810bf038c3e3c3cc2fa0d" +checksum = "c39b3bc2a8f715298032cf5087e58573809374b08160aa7d750582bdb82d2683" dependencies = [ "log", "pest", @@ -2162,7 +2231,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash 0.7.6", + "ahash 0.7.7", ] [[package]] @@ -2171,14 +2240,18 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.6", ] [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +dependencies = [ + "ahash 0.8.6", + "allocator-api2", +] [[package]] name = "heck" @@ -2206,9 +2279,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "hex" @@ -2287,9 +2360,9 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" @@ -2324,7 +2397,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -2333,9 +2406,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http", @@ -2345,7 +2418,7 @@ dependencies = [ "rustls-native-certs", "tokio", "tokio-rustls", - "webpki-roots 0.23.1", + "webpki-roots", ] [[package]] @@ -2363,16 +2436,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -2386,16 +2459,18 @@ dependencies = [ [[package]] name = "ic-agent" -version = "0.28.0" -source = "git+https://github.com/dfinity/agent-rs.git?rev=9c4db330d96938d95eda69bbf5878db91aae0aa1#9c4db330d96938d95eda69bbf5878db91aae0aa1" +version = "0.30.2" +source = "git+https://github.com/dfinity/agent-rs.git?rev=ed0862a45d5973ff123cbabc4ac40a89821b18c6#ed0862a45d5973ff123cbabc4ac40a89821b18c6" dependencies = [ "backoff", - "candid 0.9.6", + "cached 0.46.1", + "candid 0.9.11", + "ed25519-consensus", "futures-util", "hex", "http", "http-body", - "ic-certification 0.27.0", + "ic-certification 1.3.0", "ic-transport-types", "ic-verify-bls-signature", "k256 0.13.1", @@ -2403,18 +2478,19 @@ dependencies = [ "pem 2.0.1", "pkcs8 0.10.2", "rand", + "rangemap", "reqwest", - "ring", - "rustls-webpki 0.101.4", - "sec1 0.7.2", + "ring 0.16.20", + "rustls-webpki", + "sec1 0.7.3", "serde", "serde_bytes", "serde_cbor", "serde_repr", - "sha2 0.10.7", + "sha2 0.10.8", "simple_asn1", "thiserror", - "time 0.3.23", + "time", "tokio", "url", ] @@ -2424,7 +2500,7 @@ name = "ic-asset" version = "0.20.0" dependencies = [ "backoff", - "candid 0.9.6", + "candid 0.9.11", "derivative", "dfx-core", "flate2", @@ -2433,7 +2509,7 @@ dependencies = [ "globset", "hex", "ic-agent", - "ic-utils 0.28.0", + "ic-utils 0.30.2", "itertools 0.10.5", "json5", "mime", @@ -2443,7 +2519,7 @@ dependencies = [ "serde", "serde_bytes", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "slog", "tempfile", "thiserror", @@ -2499,7 +2575,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d4c0b932bf454d5d60e61e13c3c944972fcfd74dc82b9ed5c8b0a75979cf50" dependencies = [ - "candid 0.9.6", + "candid 0.9.11", "ic-cdk-macros", "ic0", "serde", @@ -2508,11 +2584,11 @@ dependencies = [ [[package]] name = "ic-cdk-macros" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4587624e64b8db56224033ee74e5c246d39be15375d03d3df7c117d49d18487" +checksum = "411c0dd4c149132b68e679274d397053332ee29996c6a541075895881916333b" dependencies = [ - "candid 0.9.6", + "candid 0.9.11", "proc-macro2", "quote", "serde", @@ -2527,19 +2603,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "beb68e0ea2fe6b533ddab6ae2142274f9669acacbacd83ac64bb1cd268d33104" dependencies = [ "hex", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] name = "ic-certification" -version = "0.27.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1120544357d4d2f7540dd5290b952c6305afe24c9620d423e2239560adca2535" +checksum = "e8c04340437a32c8b9c80d36f09715909c1e0a755327503a2e2906dcd662ba4e" dependencies = [ "hex", "serde", "serde_bytes", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -2547,10 +2623,10 @@ name = "ic-certified-assets" version = "0.2.5" dependencies = [ "base64 0.13.1", - "candid 0.9.6", + "candid 0.9.11", "hex", "ic-cdk", - "ic-certified-map", + "ic-certification 1.3.0", "ic-crypto-tree-hash", "ic-representation-independent-hash", "ic-response-verification", @@ -2560,7 +2636,7 @@ dependencies = [ "serde", "serde_bytes", "serde_cbor", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -2571,7 +2647,7 @@ checksum = "6adc65afeffc619a7cd19553c66c79820908c12f42191af90cfb39e2e93c4431" dependencies = [ "serde", "serde_bytes", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -2635,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", @@ -2752,13 +2828,13 @@ dependencies = [ [[package]] name = "ic-identity-hsm" -version = "0.28.0" -source = "git+https://github.com/dfinity/agent-rs.git?rev=9c4db330d96938d95eda69bbf5878db91aae0aa1#9c4db330d96938d95eda69bbf5878db91aae0aa1" +version = "0.30.2" +source = "git+https://github.com/dfinity/agent-rs.git?rev=ed0862a45d5973ff123cbabc4ac40a89821b18c6#ed0862a45d5973ff123cbabc4ac40a89821b18c6" dependencies = [ "hex", "ic-agent", "pkcs11", - "sha2 0.10.7", + "sha2 0.10.8", "simple_asn1", "thiserror", ] @@ -2785,7 +2861,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f5790ff4b3752ce648d83554b3b0df1039a94bea24119d29a0f9874d796075e" dependencies = [ "leb128", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -2804,7 +2880,7 @@ dependencies = [ "log", "miracl_core_bls12381", "nom", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", ] @@ -2813,7 +2889,7 @@ name = "ic-response-verification-test-utils" version = "0.3.0" source = "git+https://github.com/dfinity/response-verification.git?rev=4686895c6070ac36109a01f4bd642caf2369b97b#4686895c6070ac36109a01f4bd642caf2369b97b" dependencies = [ - "base64 0.21.2", + "base64 0.21.5", "flate2", "getrandom", "hex", @@ -2848,17 +2924,17 @@ dependencies = [ [[package]] name = "ic-transport-types" -version = "0.28.0" -source = "git+https://github.com/dfinity/agent-rs.git?rev=9c4db330d96938d95eda69bbf5878db91aae0aa1#9c4db330d96938d95eda69bbf5878db91aae0aa1" +version = "0.30.2" +source = "git+https://github.com/dfinity/agent-rs.git?rev=ed0862a45d5973ff123cbabc4ac40a89821b18c6#ed0862a45d5973ff123cbabc4ac40a89821b18c6" dependencies = [ - "candid 0.9.6", + "candid 0.9.11", "hex", - "ic-certification 0.27.0", + "ic-certification 1.3.0", "leb128", "serde", "serde_bytes", "serde_repr", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", ] @@ -2923,11 +2999,11 @@ dependencies = [ [[package]] name = "ic-utils" -version = "0.28.0" -source = "git+https://github.com/dfinity/agent-rs.git?rev=9c4db330d96938d95eda69bbf5878db91aae0aa1#9c4db330d96938d95eda69bbf5878db91aae0aa1" +version = "0.30.2" +source = "git+https://github.com/dfinity/agent-rs.git?rev=ed0862a45d5973ff123cbabc4ac40a89821b18c6#ed0862a45d5973ff123cbabc4ac40a89821b18c6" dependencies = [ "async-trait", - "candid 0.9.6", + "candid 0.9.11", "ic-agent", "once_cell", "semver", @@ -2936,7 +3012,7 @@ dependencies = [ "strum 0.24.1", "strum_macros 0.24.3", "thiserror", - "time 0.3.23", + "time", ] [[package]] @@ -2958,7 +3034,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e360e45c2bf406a867c35ec5daee433f2c3bbbaf013469e6a386a322a9713885" dependencies = [ "anyhow", - "candid 0.9.6", + "candid 0.9.11", "clap", "rustc-demangle", "tempfile", @@ -2988,19 +3064,36 @@ dependencies = [ "zeroize", ] +[[package]] +name = "icrc-ledger-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ad46da2124f4d7bf5c079eca568786b87bd60fc962bef404ff44207077961c" +dependencies = [ + "base32", + "candid 0.9.11", + "crc32fast", + "hex", + "num-bigint 0.4.4", + "num-traits", + "serde", + "serde_bytes", + "sha2 0.10.8", +] + [[package]] name = "icx-asset" version = "0.20.0" dependencies = [ "anstyle", "anyhow", - "candid 0.9.6", + "candid 0.9.11", "clap", "delay", "humantime", "ic-agent", "ic-asset", - "ic-utils 0.28.0", + "ic-utils 0.30.2", "libflate", "num-traits", "pem 1.1.1", @@ -3011,7 +3104,7 @@ dependencies = [ "slog-async", "slog-term", "thiserror", - "time 0.3.23", + "time", "tokio", "walkdir", ] @@ -3050,12 +3143,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.2", ] [[package]] @@ -3085,16 +3178,16 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi 0.3.3", "libc", "windows-sys 0.48.0", ] [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" @@ -3102,8 +3195,8 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.2", - "rustix 0.38.4", + "hermit-abi 0.3.3", + "rustix 0.38.21", "windows-sys 0.48.0", ] @@ -3133,33 +3226,33 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" dependencies = [ "wasm-bindgen", ] [[package]] name = "json-patch" -version = "1.0.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f54898088ccb91df1b492cc80029a6fdf1c48ca0db7c6822a8babad69c94658" +checksum = "55ff1e1486799e3f64129f8ccad108b38290df9cd7015cd31bed17239f0789d6" dependencies = [ "serde", "serde_json", @@ -3197,7 +3290,7 @@ dependencies = [ "cfg-if 1.0.0", "ecdsa 0.14.8", "elliptic-curve 0.12.3", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", ] @@ -3208,10 +3301,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" dependencies = [ "cfg-if 1.0.0", - "ecdsa 0.16.7", - "elliptic-curve 0.13.5", + "ecdsa 0.16.8", + "elliptic-curve 0.13.6", "once_cell", - "sha2 0.10.7", + "sha2 0.10.8", "signature 2.1.0", ] @@ -3274,7 +3367,7 @@ dependencies = [ "petgraph", "pico-args", "regex", - "regex-syntax 0.7.4", + "regex-syntax 0.7.5", "string_cache", "term", "tiny-keccak", @@ -3313,9 +3406,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "libflate" @@ -3349,15 +3442,15 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libz-ng-sys" -version = "1.1.9" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2468756f34903b582fe7154dc1ffdebd89d0562c4a43b53c621bb0f1b1043ccb" +checksum = "3dd9f43e75536a46ee0f92b758f6b63846e594e86638c61a9251338a65baea63" dependencies = [ "cmake", "libc", @@ -3380,15 +3473,15 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.3" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -3396,9 +3489,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "logos" @@ -3429,7 +3522,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax 0.6.29", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] @@ -3463,9 +3556,9 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" @@ -3518,12 +3611,12 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.48.0", ] @@ -3576,7 +3669,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1bb540dc6ef51cfe1916ec038ce7a620daf3a111e2502d745197cd53d6bca15" dependencies = [ "libc", - "socket2", + "socket2 0.4.10", ] [[package]] @@ -3624,14 +3717,13 @@ dependencies = [ [[package]] name = "nix" -version = "0.26.2" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.1", "cfg-if 1.0.0", "libc", - "static_assertions", ] [[package]] @@ -3646,9 +3738,9 @@ dependencies = [ [[package]] name = "nom_locate" -version = "4.1.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e299bf5ea7b212e811e71174c5d1a5d065c4c0ad0c8691ecb1f97e3e66025e" +checksum = "1e3c83c053b0713da60c5b8de47fe8e494fe3ece5267b2f23090a07a053ba8f3" dependencies = [ "bytecount", "memchr", @@ -3670,7 +3762,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" dependencies = [ - "num-bigint 0.4.3", + "num-bigint 0.4.4", "num-complex", "num-integer", "num-iter", @@ -3691,9 +3783,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ "autocfg", "num-integer", @@ -3703,9 +3795,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" +checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" dependencies = [ "num-traits", ] @@ -3738,16 +3830,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg", - "num-bigint 0.4.3", + "num-bigint 0.4.4", "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", "libm", @@ -3759,7 +3851,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi 0.3.3", "libc", ] @@ -3802,7 +3894,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] @@ -3822,9 +3914,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.31.1" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] @@ -3843,11 +3935,11 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.55" +version = "0.10.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.1", "cfg-if 1.0.0", "foreign-types", "libc", @@ -3864,7 +3956,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] @@ -3875,18 +3967,18 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "111.26.0+1.1.1u" +version = "300.1.6+3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efc62c9f12b22b8f5208c23a7200a442b2e5999f8bdf80233852122b5a4f6f37" +checksum = "439fac53e092cd7442a3660c85dde4643ab3b5bd39040912388dcdabf6b88085" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.90" +version = "0.9.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" +checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" dependencies = [ "cc", "libc", @@ -3897,9 +3989,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.5.1" +version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" dependencies = [ "memchr", ] @@ -3915,9 +4007,9 @@ dependencies = [ [[package]] name = "parking" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" @@ -3937,7 +4029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.8", + "parking_lot_core 0.9.9", ] [[package]] @@ -3956,15 +4048,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "smallvec", - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] @@ -3980,9 +4072,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b27ab7be369122c218afc2079489cdcb4b517c0a3fc386ff11e1fedfcc2b35" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "patch" @@ -4019,7 +4111,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b13fe415cdf3c8e44518e18a7c95a13431d9bdf6d15367d82b23c377fdd441a" dependencies = [ - "base64 0.21.2", + "base64 0.21.5", "serde", ] @@ -4049,10 +4141,11 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.7.0" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73935e4d55e2abf7f130186537b19e7a4abc886a0252380b59248af473a3fc9" +checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" dependencies = [ + "memchr", "thiserror", "ucd-trie", ] @@ -4081,9 +4174,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.0" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef623c9bbfa0eedf5a0efba11a5ee83209c326653ca31ff019bec3a95bfff2b" +checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" dependencies = [ "pest", "pest_generator", @@ -4091,36 +4184,36 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.0" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e8cba4ec22bada7fc55ffe51e2deb6a0e0db2d0b7ab0b103acc80d2510c190" +checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] name = "pest_meta" -version = "2.7.0" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01f71cb40bd8bb94232df14b946909e14660e33fc05db3e50ae2a82d7ea0ca0" +checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" dependencies = [ "once_cell", "pest", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] name = "petgraph" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 1.9.3", + "indexmap 2.1.0", ] [[package]] @@ -4150,9 +4243,9 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "pin-project-lite" -version = "0.2.10" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -4186,7 +4279,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.7", + "der 0.7.8", "spki 0.7.2", ] @@ -4224,6 +4317,12 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -4260,13 +4359,13 @@ dependencies = [ [[package]] name = "pretty" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "563c9d701c3a31dfffaaf9ce23507ba09cbe0b9125ba176d15e629b0235e9acc" +checksum = "b55c4d17d994b637e2f4daf6e5dc5d660d209d5642377d675d7a1c3ab69fa579" dependencies = [ "arrayvec 0.5.2", "typed-arena", - "unicode-segmentation", + "unicode-width", ] [[package]] @@ -4300,28 +4399,28 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" +checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e" dependencies = [ "bit-set", - "bitflags 1.3.2", - "byteorder", + "bit-vec", + "bitflags 2.4.1", "lazy_static", "num-traits", "rand", "rand_chacha", "rand_xorshift", - "regex-syntax 0.6.29", + "regex-syntax 0.7.5", "rusty-fork", "tempfile", "unarray", @@ -4387,9 +4486,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.29" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -4439,11 +4538,17 @@ 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.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ "either", "rayon-core", @@ -4451,14 +4556,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -4479,6 +4582,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_users" version = "0.4.3" @@ -4492,25 +4604,25 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax 0.7.4", + "regex-syntax 0.8.2", ] [[package]] name = "regex-automata" -version = "0.3.3" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.4", + "regex-syntax 0.8.2", ] [[package]] @@ -4521,26 +4633,32 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rend" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581008d2099240d37fb08d77ad713bcaec2c4d89d50b5b21a8bb1996bbab68ab" +checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" dependencies = [ "bytecheck", ] [[package]] name = "reqwest" -version = "0.11.19" +version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20b9b67e2ca7dd9e9f9285b759de30ff538aab981abaaf7bc9bd90b84a0126c3" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64 0.21.2", + "base64 0.21.5", "bytes", "encoding_rs", "futures-core", @@ -4564,6 +4682,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "system-configuration", "tokio", "tokio-native-tls", "tokio-rustls", @@ -4574,7 +4693,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 0.25.2", + "webpki-roots", "winreg", ] @@ -4608,12 +4727,26 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", - "untrusted", + "spin 0.5.2", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" +dependencies = [ + "cc", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.48.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -4659,14 +4792,12 @@ checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" [[package]] name = "rust_decimal" -version = "1.30.0" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0446843641c69436765a35a5a77088e28c2e6a12da93e84aa3ab1cd4aa5a042" +checksum = "a4c4216490d5a413bc6d10fa4742bd7d4955941d062c0ef873141d6b0e7b30fd" dependencies = [ "arrayvec 0.7.4", "borsh", - "bytecheck", - "byteorder", "bytes", "num-traits", "rand", @@ -4689,9 +4820,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.37.23" +version = "0.37.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" dependencies = [ "bitflags 1.3.2", "errno", @@ -4703,26 +4834,26 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.4" +version = "0.38.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.1", "errno", "libc", - "linux-raw-sys 0.4.3", + "linux-raw-sys 0.4.10", "windows-sys 0.48.0", ] [[package]] name = "rustls" -version = "0.21.6" +version = "0.21.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb" +checksum = "446e14c5cda4f3f30fe71863c34ec70f5ac79d6087097ad0bb433e1be5edf04c" dependencies = [ "log", - "ring", - "rustls-webpki 0.101.4", + "ring 0.17.5", + "rustls-webpki", "sct", ] @@ -4744,34 +4875,24 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64 0.21.2", + "base64 0.21.5", ] [[package]] name = "rustls-webpki" -version = "0.100.2" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e98ff011474fa39949b7e5c0428f9b4937eda7da7848bbb947786b7be0b27dab" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" -dependencies = [ - "ring", - "untrusted", + "ring 0.17.5", + "untrusted 0.9.0", ] [[package]] name = "rustversion" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc31bd9b61a32c31f9650d18add92aa83a49ba979c143eefd27fe7177b05bd5f" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "rusty-fork" @@ -4787,9 +4908,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "same-file" @@ -4811,9 +4932,9 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.12" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c613288622e5f0c3fdc5dbd4db1c5fbe752746b1d1a56a0630b78fd00de44f" +checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c" dependencies = [ "dyn-clone", "schemars_derive", @@ -4823,9 +4944,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.12" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109da1e6b197438deb6db99952990c7f959572794b80ff93707d55a232545e7c" +checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c" dependencies = [ "proc-macro2", "quote", @@ -4847,24 +4968,24 @@ checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "scratch" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "764cad9e7e1ca5fe15b552859ff5d96a314e6ed2934f2260168cd5dfa5891409" +checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring", - "untrusted", + "ring 0.17.5", + "untrusted 0.9.0", ] [[package]] @@ -4889,12 +5010,12 @@ dependencies = [ [[package]] name = "sec1" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct 0.2.0", - "der 0.7.7", + "der 0.7.8", "generic-array", "pkcs8 0.10.2", "subtle", @@ -4923,9 +5044,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -4936,9 +5057,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -4946,27 +5067,27 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.171" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" +checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.11" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a16be4fe5320ade08736447e3198294a5ea9a6d44dde6f35f0a5e06859c427a" +checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" dependencies = [ "serde", ] @@ -4983,13 +5104,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.171" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" +checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] @@ -5018,9 +5139,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.102" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -5029,20 +5150,20 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.14" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d89a8107374290037607734c0b73a85db7ed80cae314b3c5791f192a496e731" +checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" dependencies = [ "serde", ] @@ -5107,9 +5228,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -5118,14 +5239,14 @@ dependencies = [ [[package]] name = "sha256" -version = "1.2.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b11f1548fd635c4b698ffdc817d44dfb725700392b1082bbc241167579bee0c8" +checksum = "7895c8ae88588ccead14ff438b939b0c569cd619116f14b4d13fdff7b8333386" dependencies = [ "async-trait", "bytes", "hex", - "sha2 0.10.7", + "sha2 0.10.8", "tokio", ] @@ -5182,9 +5303,9 @@ checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" [[package]] name = "similar" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" +checksum = "2aeaf503862c419d66959f5d7ca015337d864e9c49485d771b732e2a20453597" [[package]] name = "simple_asn1" @@ -5192,23 +5313,23 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" dependencies = [ - "num-bigint 0.4.3", + "num-bigint 0.4.4", "num-traits", "thiserror", - "time 0.3.23", + "time", ] [[package]] name = "siphasher" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] @@ -5224,9 +5345,9 @@ dependencies = [ [[package]] name = "slog-async" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "766c59b252e62a34651412870ff55d8c4e6d04df19b43eecb2703e417b097ffe" +checksum = "72c8038f898a2c79507940990f05386455b3a317d8f18d4caea7cbc3d5096b84" dependencies = [ "crossbeam-channel", "slog", @@ -5244,31 +5365,47 @@ dependencies = [ "slog", "term", "thread_local", - "time 0.3.23", + "time", ] [[package]] name = "smallvec" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", ] +[[package]] +name = "socket2" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "spki" version = "0.6.0" @@ -5286,7 +5423,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" dependencies = [ "base64ct", - "der 0.7.7", + "der 0.7.8", ] [[package]] @@ -5377,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" @@ -5400,9 +5543,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.25" +version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ "proc-macro2", "quote", @@ -5424,6 +5567,27 @@ dependencies = [ "winapi", ] +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "take_mut" version = "0.2.2" @@ -5438,9 +5602,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.38" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" +checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" dependencies = [ "filetime", "libc", @@ -5449,15 +5613,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.6.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ - "autocfg", "cfg-if 1.0.0", - "fastrand", - "redox_syscall 0.3.5", - "rustix 0.37.23", + "fastrand 2.0.1", + "redox_syscall 0.4.1", + "rustix 0.38.21", "windows-sys 0.48.0", ] @@ -5474,41 +5637,41 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ "winapi-util", ] [[package]] name = "terminal_size" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" +checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ - "rustix 0.37.23", + "rustix 0.38.21", "windows-sys 0.48.0", ] [[package]] name = "thiserror" -version = "1.0.43" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.43" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] @@ -5529,24 +5692,15 @@ dependencies = [ [[package]] name = "time" -version = "0.1.45" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "time" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" dependencies = [ + "deranged", "itoa", "libc", "num_threads", + "powerfmt", "serde", "time-core", "time-macros", @@ -5554,15 +5708,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.10" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" dependencies = [ "time-core", ] @@ -5579,7 +5733,7 @@ dependencies = [ "pbkdf2", "rand", "rustc-hash", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", "unicode-normalization", "wasm-bindgen", @@ -5612,11 +5766,10 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", @@ -5625,7 +5778,7 @@ dependencies = [ "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.5.5", "tokio-macros", "windows-sys 0.48.0", ] @@ -5638,7 +5791,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] @@ -5663,9 +5816,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -5686,9 +5839,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" dependencies = [ "serde", "serde_spanned", @@ -5698,20 +5851,20 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.12" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.1.0", "serde", "serde_spanned", "toml_datetime", @@ -5726,20 +5879,19 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if 1.0.0", "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", ] @@ -5767,9 +5919,9 @@ checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" @@ -5785,9 +5937,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] @@ -5800,9 +5952,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -5821,9 +5973,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unicode-xid" @@ -5831,12 +5983,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" -[[package]] -name = "unidecode" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402bb19d8e03f1d1a7450e2bd613980869438e0666331be3e073089124aa1adc" - [[package]] name = "universal-hash" version = "0.4.1" @@ -5853,11 +5999,17 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", "idna", @@ -5879,9 +6031,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d023da39d1fde5a8a3fe1f3e01ca9632ada0a63e9797de55a879d6e2236277be" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" [[package]] name = "vcpkg" @@ -5906,15 +6058,15 @@ dependencies = [ [[package]] name = "waker-fn" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" [[package]] name = "walkdir" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", @@ -5957,12 +6109,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -5971,9 +6117,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -5981,24 +6127,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -6008,9 +6154,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6018,22 +6164,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" [[package]] name = "wasm-encoder" @@ -6105,23 +6251,14 @@ checksum = "449167e2832691a1bff24cde28d2804e90e09586a448c8e76984792c44334a6b" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" dependencies = [ "js-sys", "wasm-bindgen", ] -[[package]] -name = "webpki-roots" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" -dependencies = [ - "rustls-webpki 0.100.2", -] - [[package]] name = "webpki-roots" version = "0.25.2" @@ -6130,13 +6267,14 @@ checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" [[package]] name = "which" -version = "4.4.0" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ "either", - "libc", + "home", "once_cell", + "rustix 0.38.21", ] [[package]] @@ -6157,9 +6295,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -6171,12 +6309,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] @@ -6194,7 +6332,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] @@ -6214,17 +6352,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -6235,9 +6373,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" @@ -6247,9 +6385,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" @@ -6259,9 +6397,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" @@ -6271,9 +6409,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" @@ -6283,9 +6421,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" @@ -6295,9 +6433,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" @@ -6307,15 +6445,15 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.4.9" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a2094c43cc94775293eaa0e499fbc30048a6d824ac82c0351a8c0bf9112529" +checksum = "176b6138793677221d420fd2f0aeeced263f197688b36484660da767bca2fa32" dependencies = [ "memchr", ] @@ -6347,9 +6485,9 @@ dependencies = [ [[package]] name = "xattr" -version = "0.2.3" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" +checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" dependencies = [ "libc", ] @@ -6370,7 +6508,7 @@ dependencies = [ "byteorder", "derivative", "enumflags2", - "fastrand", + "fastrand 1.9.0", "futures", "nb-connect", "nix 0.22.3", @@ -6395,6 +6533,26 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "zerocopy" +version = "0.7.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686b7e407015242119c33dab17b8f61ba6843534de936d94368856528eae4dcc" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020f3dfe25dfc38dfea49ce62d5d45ecdd7f0d8a724fa63eb36b6eba4ec76806" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "zeroize" version = "1.6.0" @@ -6412,7 +6570,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index e0bff1eb37..8a42a64df0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,18 +18,18 @@ rust-version = "1.71.1" license = "Apache-2.0" [workspace.dependencies] -candid = "0.9.0" -ic-agent = "0.28.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.28.0" -ic-utils = "0.28.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 = "0.4.0" +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.28.0" +version = "0.30.2" git = "https://github.com/dfinity/agent-rs.git" -rev = "9c4db330d96938d95eda69bbf5878db91aae0aa1" +rev = "ed0862a45d5973ff123cbabc4ac40a89821b18c6" [patch.crates-io.ic-identity-hsm] -version = "0.28.0" +version = "0.30.2" git = "https://github.com/dfinity/agent-rs.git" -rev = "9c4db330d96938d95eda69bbf5878db91aae0aa1" +rev = "ed0862a45d5973ff123cbabc4ac40a89821b18c6" [patch.crates-io.ic-utils] -version = "0.28.0" +version = "0.30.2" git = "https://github.com/dfinity/agent-rs.git" -rev = "9c4db330d96938d95eda69bbf5878db91aae0aa1" +rev = "ed0862a45d5973ff123cbabc4ac40a89821b18c6" [profile.release] panic = 'abort' diff --git a/README.md b/README.md index 87e136081f..592765880b 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,14 @@ This command will install a binary compatible with your operating system, and ad Find a release for your architecture [here](https://github.com/dfinity/sdk/releases). +#### in GitHub Action, using [`dfinity/setup-dfx`](https://github.com/dfinity/setup-dfx) + +```yml + steps: + - name: Install dfx + uses: dfinity/setup-dfx@main +``` + ### Getting Help Once the `IC SDK` is installed, get acquainted with its capabilities by entering. diff --git a/docs/cli-reference/dfx-build.md b/docs/cli-reference/dfx-build.md index 0531cb914d..f10f411db8 100644 --- a/docs/cli-reference/dfx-build.md +++ b/docs/cli-reference/dfx-build.md @@ -16,16 +16,16 @@ dfx build [flag] [option] [--all | canister_name] You can use the following optional flags with the `dfx build` command. -| Flag | Description | -|-------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `--check` | Builds canisters using a temporary, hard-coded, locally-defined canister identifier for testing that your program compiles without connecting to the IC. | +| Flag | Description | +| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `--check` | Builds canisters using a temporary, hard-coded, locally-defined canister identifier for testing that your program compiles without connecting to the IC. | ## Options You can specify the following options for the `dfx build` command. | Option | Description | -|-----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------| +| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | `--network ` | Specifies the network alias or URL you want to connect to. You can use this option to override the network specified in the `dfx.json` configuration file. | | `--output-env-file` | Writes dfx environment variables to a provided path. Overrides the `output_env_file` configuration from `dfx.json` if passed. | @@ -34,7 +34,7 @@ You can specify the following options for the `dfx build` command. You can specify the following arguments for the `dfx build` command. | Argument | Description | -|-----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `--all` | Builds all of the canisters configured in the project’s `dfx.json` file. | | `canister_name` | Specifies the name of the canister you want to build. If you are not using the `--all` option, you can continue to use `dfx build` or provide a canister name as an argument (the canister name must match at least one name that you have configured in the `canisters` section of the `dfx.json` configuration file for your project.) | @@ -57,3 +57,7 @@ To test whether a canister compiles without connecting to the IC or the local ca ``` bash dfx build --check ``` + +## Management Canister + +If `dfx` detects that your Motoko project is importing the Management Canister (e.g. `import Management "ic:aaaaa-aa";`) it will automatically provide the Candid interface for the Management Canister during the build. \ No newline at end of file diff --git a/docs/cli-reference/dfx-canister.md b/docs/cli-reference/dfx-canister.md index 559ef2549f..ffc06eed56 100644 --- a/docs/cli-reference/dfx-canister.md +++ b/docs/cli-reference/dfx-canister.md @@ -216,6 +216,7 @@ You can use the following options with the `dfx canister create` command. | `-c`, `--compute-allocation ` | Specifies the canister's compute allocation. This should be a percent in the range [0..100]. | | `--controller ` | Specifies the identity name or the principal of the new controller. | | `--memory-allocation ` | Specifies how much memory the canister is allowed to use in total. This should be a value in the range [0..12 GiB]. A setting of 0 means the canister will have access to memory on a “best-effort” basis: It will only be charged for the memory it uses, but at any point in time may stop running if it tries to allocate more memory when there isn’t space available on the subnet. | +| `--reserved-cycles-limit ` | Specifies the upper limit for the canister's reserved cycles. | | `--no-wallet` | Performs the call with the user Identity as the Sender of messages. Bypasses the Wallet canister. Enabled by default. | | `--with-cycles ` | Specifies the initial cycle balance to deposit into the newly created canister. The specified amount needs to take the canister create fee into account. This amount is deducted from the wallet's cycle balance. | | `--specified-id ` | Attempts to create the canister with this Canister ID | @@ -437,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. | @@ -921,6 +923,7 @@ You can specify the following options for the `dfx canister update-settings` com | `-c`, `--compute-allocation ` | Specifies the canister's compute allocation. This should be a percent in the range [0..100]. | | `--set-controller ` | Specifies the identity name or the principal of the new controller. Can be specified more than once, indicating the canister will have multiple controllers. If any controllers are set with this parameter, any other controllers will be removed. | | `--memory-allocation ` | Specifies how much memory the canister is allowed to use in total. This should be a value in the range [0..12 GiB]. A setting of 0 means the canister will have access to memory on a “best-effort” basis: It will only be charged for the memory it uses, but at any point in time may stop running if it tries to allocate more memory when there isn’t space available on the subnet. | +| `--reserved-cycles-limit ` | Specifies the upper limit of the canister's reserved cycles. | | `--remove-controller ` | Removes a principal from the list of controllers of the canister. | | `--freezing-threshold ` | Set the [freezing threshold](https://internetcomputer.org/docs/current/references/ic-interface-spec/#ic-create_canister) in seconds for a canister. This should be a value in the range [0..2^64^-1]. Very long thresholds require the `--confirm-very-long-freezing-threshold` flag. | | `-y`, `--yes` | Skips yes/no checks by answering 'yes'. Such checks can result in loss of control, so this is not recommended outside of CI. | diff --git a/docs/cli-reference/dfx-cycles.md b/docs/cli-reference/dfx-cycles.md new file mode 100644 index 0000000000..936abdc986 --- /dev/null +++ b/docs/cli-reference/dfx-cycles.md @@ -0,0 +1,153 @@ +# dfx cycles + +> **NOTE**: The cycles ledger is in development and the dfx cycles command is not expected to work on mainnet at this time. + +Use the `dfx cycles` command to manage cycles associated with an identity's principal. + +The basic syntax for running `dfx cycles` commands is: + +``` bash +dfx cycles [subcommand] [options] +``` + +The following subcommands are available: + +| Command | Description | +|---------------------------------------|--------------------------------------------------------------------------------------| +| [`balance`](#dfx-cycles-balance) | Prints the account balance of the user. | +| [`transfer`](#dfx-cycles-transfer) | Send cycles to another account. | +| `help` | Displays usage information message for a specified subcommand. | + +To view usage information for a specific subcommand, specify the subcommand and the `--help` flag. For example, to see usage information for `dfx cycles balance`, you can run the following command: + +`dfx cycles balance --help` + +## dfx cycles balance + +Use the `dfx cycles balance` command to print your account balance or that of another user. + +### Basic usage + +``` bash +dfx cycles balance [flag] --network ic +``` + +### Options + +You can specify the following arguments for the `dfx cycles balance` command. + +| Option | Description | +|---------------------------------------------|---------------------------------------------------------------------| +| `--owner ` | Display the balance of this principal | +| `--subaccount ` | Display the balance of this subaccount | +| `--precise` | Displays the exact balance, without scaling to trillions of cycles. | +| `--cycles-ledger-canister-id ` | Specify the ID of the cycles ledger canister. | + +### Examples + +> **NOTE**: None of the examples below specify the `--cycles-ledger-canister-id` option, but it is required until the cycles ledger canister ID is known. + +Check the cycles balance of the selected identity. + +``` +$ dfx cycles balance --network ic +89.000 TC (trillion cycles). +``` + +To see the exact amount of cycles, you can use the `--precise` option: +``` +$ dfx cycles balance --network ic --precise +89000000000000 cycles. +``` + +You can use the `dfx cycles balance` command to check the balance of another principal: + +``` bash +dfx cycles balance --owner raxcz-bidhr-evrzj-qyivt-nht5a-eltcc-24qfc-o6cvi-hfw7j-dcecz-kae --network ic +``` + +## dfx cycles transfer + +Use the `dfx cycles transfer` command to transfer cycles from your account to another account. + +### Basic usage + +``` bash +dfx cycles transfer [options] +``` + +### Arguments + +You must specify the following arguments for the `dfx cycles transfer` command. + +| Argument | Description | +|------------|-----------------------------------| +| `` | The principal of the account to which you want to transfer cycles. | +| `` | The number of cycles to transfer. | + +### Options + +You can specify the following options for the `dfx cycles transfer` command. + +| Option | Description | +|----------------------------------|----------------------------------------------------------------------------------------| +| `--to-subaccount ` | The subaccount to which you want to transfer cycles. | +| `--from-subaccount ` | The subaccount from which you want to transfer cycles. | +| `--memo ` | Specifies a numeric memo for this transaction. | +| `--created-at-time ` | Specify the timestamp-nanoseconds for the `created_at_time` field on the transfer request. Useful for controlling transaction-de-duplication. https://internetcomputer.org/docs/current/developer-docs/integrations/icrc-1/#transaction-deduplication- | + +### Examples + +Transfer 1 billion cycles to another account: + +``` bash +dfx cycles transfer raxcz-bidhr-evrzj-qyivt-nht5a-eltcc-24qfc-o6cvi-hfw7j-dcecz-kae 1000000000 --network ic +``` + +Transfer from a subaccount: + +``` bash +dfx cycles transfer raxcz-bidhr-evrzj-qyivt-nht5a-eltcc-24qfc-o6cvi-hfw7j-dcecz-kae 1000000000 --from-subaccount 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f --network ic +``` + +## dfx cycles top-up + +Use the `dfx cycles top-up` command to send cycles from your account to a canister. + +### Basic usage + +``` bash +dfx cycles top-up [options] +``` + +### Arguments + +You must specify the following arguments for the `dfx cycles transfer` command. + +| Argument | Description | +|------------|-------------------------------------------------------------------------| +| `` | The name of a canister in the current project, or a canister principal. | +| `` | The number of cycles to transfer. | + +### Options + +You can specify the following options for the `dfx cycles top-up` command. + +| Option | Description | +|----------------------------------|----------------------------------------------------------------------------------------| +| `--from-subaccount ` | The subaccount from which you want to transfer cycles. | +| `--created-at-time ` | Specify the timestamp-nanoseconds for the `created_at_time` field on the transfer request. Useful for controlling transaction deduplication. https://internetcomputer.org/docs/current/developer-docs/integrations/icrc-1/#transaction-deduplication- | + +### Examples + +Send cycles to a canister in your project: + +``` bash +dfx cycles top-up my_backend 1000000000 --network ic +``` + +Send cycles to a canister by principal: + +``` bash +dfx cycles top-up bkyz2-fmaaa-aaaaa-qaaaq-cai 1000000000 --network ic +``` diff --git a/docs/cli-reference/dfx-ledger.md b/docs/cli-reference/dfx-ledger.md index 25906e3a07..20f64b56a6 100644 --- a/docs/cli-reference/dfx-ledger.md +++ b/docs/cli-reference/dfx-ledger.md @@ -276,9 +276,9 @@ dfx ledger top-up [options] canister [flag] --network ic You can specify the following argument for the `dfx ledger top-up` command. -| Argument | Description | -|------------|------------------------------------------------------------------| -| `canister` | Specifies the canister identifier that you would like to top up. | +| Argument | Description | +|------------|--------------------------------------------------------------------------| +| `canister` | Specifies the canister identifier or name that you would like to top up. | ### Options diff --git a/docs/cli-reference/dfx-start.md b/docs/cli-reference/dfx-start.md index 83a399d66c..3621c67bc2 100644 --- a/docs/cli-reference/dfx-start.md +++ b/docs/cli-reference/dfx-start.md @@ -32,6 +32,7 @@ You can use the following option with the `dfx start` command. | `--host host` | Specifies the host interface IP address and port number to bind the frontend to. The default for the local shared network is `127.0.0.1:4943`, while the default for a project-specific network is '127.0.0.1:8000'. | | `--bitcoin-node host:port` | Specifies the address of a bitcoind node. Implies `--enable-bitcoin`. | | `--artificial-delay milliseconds` | Specifies the delay that an update call should incur. Default: 600ms | +| `--domain domain` | A domain that can be served. Can be specified more than once. These are used for canister resolution [default: localhost] | ## Examples diff --git a/docs/cli-reference/index.md b/docs/cli-reference/index.md index c4290ce2cd..d05b68d23a 100644 --- a/docs/cli-reference/index.md +++ b/docs/cli-reference/index.md @@ -24,6 +24,8 @@ When you have the SDK installed, you can use the following commands to specify t - [dfx canister](./dfx-canister.md) +- [dfx cycles](./dfx-cycles.md) + - [dfx deploy](./dfx-deploy.md) - [dfx deps](./dfx-deps.md) diff --git a/docs/design/asset-canister-interface.md b/docs/design/asset-canister-interface.md index 3f30ac48fe..ffc36bffe6 100644 --- a/docs/design/asset-canister-interface.md +++ b/docs/design/asset-canister-interface.md @@ -159,6 +159,29 @@ The size of any chunk cannot exceed the message ingress limit. ## Method Reference +### Method: `init` and `post_upgrade` + +```candid +service: (asset_canister_args: variant { + Init: record {}; + Upgrade: record { + set_permissions: opt record { + prepare: vec principal; + commit: vec principal; + manage_permissions: vec principal; + }; + }; +}) +``` + +The methods `init` and `post_upgrade` are called automatically by the system after new code is installed in the canister. + +Both methods take the same argument type by definition. Therefore, to be able to have different arguments for the two cases, an enum is used to make the distinction. +If `init` is called with the `Upgrade` variant or if `post_upgrade` is called with the `Init` variant the asset canister traps and thereby reverts the code changes. + +In `Upgrade`, the field `set_permissions` can be used to (re)set the list of principals with the listed permissions. +If `set_permissions` that is not `null`, then all permissions are set to the newly provided list of principals and the previous lists of principals are discarded. + ### Method: `get` ```candid diff --git a/docs/dfx-json-schema.json b/docs/dfx-json-schema.json index 8d38220a0a..40f4e890ac 100644 --- a/docs/dfx-json-schema.json +++ b/docs/dfx-json-schema.json @@ -372,7 +372,8 @@ "default": { "compute_allocation": null, "freezing_threshold": null, - "memory_allocation": null + "memory_allocation": null, + "reserved_cycles_limit": null }, "allOf": [ { @@ -526,6 +527,16 @@ } ] }, + "proxy": { + "anyOf": [ + { + "$ref": "#/definitions/ConfigDefaultsProxy" + }, + { + "type": "null" + } + ] + }, "replica": { "anyOf": [ { @@ -645,6 +656,23 @@ } } }, + "ConfigDefaultsProxy": { + "description": "Configuration for icx-proxy.", + "type": "object", + "required": [ + "domain" + ], + "properties": { + "domain": { + "description": "A list of domains that can be served. These are used for canister resolution [default: localhost]", + "allOf": [ + { + "$ref": "#/definitions/SerdeVec_for_String" + } + ] + } + } + }, "ConfigDefaultsReplica": { "title": "Local Replica Configuration", "type": "object", @@ -734,6 +762,16 @@ } ] }, + "proxy": { + "anyOf": [ + { + "$ref": "#/definitions/ConfigDefaultsProxy" + }, + { + "type": "null" + } + ] + }, "replica": { "anyOf": [ { @@ -848,6 +886,17 @@ ], "format": "uint64", "minimum": 0.0 + }, + "reserved_cycles_limit": { + "title": "Reserved Cycles Limit", + "description": "Specifies the upper limit of the canister's reserved cycles balance.\n\nReserved cycles are cycles that the system sets aside for future use by the canister. If a subnet's storage exceeds 450 GiB, then every time a canister allocates new storage bytes, the system sets aside some amount of cycles from the main balance of the canister. These reserved cycles will be used to cover future payments for the newly allocated bytes. The reserved cycles are not transferable and the amount of reserved cycles depends on how full the subnet is.\n\nA setting of 0 means that the canister will trap if it tries to allocate new storage while the subnet's memory usage exceeds 450 GiB.", + "default": null, + "type": [ + "integer", + "null" + ], + "format": "uint128", + "minimum": 0.0 } } }, diff --git a/docs/networks-json-schema.json b/docs/networks-json-schema.json index c5d7ef47c7..dd7a239ef3 100644 --- a/docs/networks-json-schema.json +++ b/docs/networks-json-schema.json @@ -105,6 +105,23 @@ } } }, + "ConfigDefaultsProxy": { + "description": "Configuration for icx-proxy.", + "type": "object", + "required": [ + "domain" + ], + "properties": { + "domain": { + "description": "A list of domains that can be served. These are used for canister resolution [default: localhost]", + "allOf": [ + { + "$ref": "#/definitions/SerdeVec_for_String" + } + ] + } + } + }, "ConfigDefaultsReplica": { "title": "Local Replica Configuration", "type": "object", @@ -194,6 +211,16 @@ } ] }, + "proxy": { + "anyOf": [ + { + "$ref": "#/definitions/ConfigDefaultsProxy" + }, + { + "type": "null" + } + ] + }, "replica": { "anyOf": [ { @@ -319,6 +346,19 @@ "application", "verifiedapplication" ] + }, + "SerdeVec_for_String": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] } } } \ No newline at end of file diff --git a/docs/process/release.adoc b/docs/process/release.adoc deleted file mode 100644 index 6c61af5f0e..0000000000 --- a/docs/process/release.adoc +++ /dev/null @@ -1,501 +0,0 @@ -= Release process - -This document describes the release process for `dfx`, with step-by-step instructions, information about automation, and a checklist. - -== Overview - -Before starting the release process, the team should conduct a brief Go/No-Go release review to evaluate the current state of fixes and features ready to be included in a release candidate. -After reviewing the list of fixes and features, the team will decide whether to proceed with staging a build. - -For now, our release process is driven by the DFINITY foundation SDK team. Future work needs to be done to separate the build and release process to run fully on open systems. - -If the new release is given the Go green light, two people who are familiar with the process—a *driver* and a *validator*—use the steps in this document to stage or promote a release candidate. - -The *validator* should be the person most familiar with the process and be able to assist with debugging or resolving issues if the *driver* building the release runs into trouble. - -A successful release is the result of coordination between automation, manual steps performed by team members, and a validation process. -Our goal is to update this document with the latest information as we iterate to improve the release process. - -=== Participants -- Driver / Primary -- Validator / Secondary - -=== Prerequisites - -Before you begin, verify the following prerequisites for the release process *driver*: - -- You must have a GitHub account and access to the `+dfinity+` organization and core repositories like the `sdk` repository -+ -For information about setting up a GitHub account, see link:https://docs.github.com/en/github/getting-started-with-github/signing-up-for-a-new-github-account[Signin up for a GitHub account] -To get permission for your account to access `+dfinity-lab+` and `+dfinity+` repositories, see link:https://www.notion.so/How-to-Get-Github-Access-68c9ad72b5974fa9bbec003592677d02[How to get GitHub access). -If you run into any issues accessing repositories, you can contact IT using the `#help-it` Slack channel and sending a message to `@firstresponder`. - -- You must have VPN access to the DFINITY VPN. -+ -If you don't have a VPN connection set up for your computer, you'll need to follow the instructions in link:https://www.notion.so/How-to-get-VPN-access-to-our-data-center-services-1c9b123152d740508eec25e7ac982259[How to get VPN access to our data center services]. - -- You must have link:https://github.com/dfinity-lab/dfinity/blob/master/CONTRIBUTING.adoc#install-and-configure-nix[Nix installed and configured]. -+ -NOTE: If you are installing Nix for the first time, building the cache can take hours and might timeout depending on the reliability of your network connection. - -- You must have a registered NPM account and `npm` installed on your system. -+ -If you don't have an account, you can go to the link:https://www.npmjs.com/[NPMJS] website and click *Sign Up* to create one using your `firstname.lastname@dfinity.org` email address. -+ -You will need to verify your email address to complete the registration process. -For your account to be added to the `dfinity` organization, contact IT - -=== Preliminary validation - -Verify the general stability of the master branch before attempting to create a release candidate. - -. Use this link:https://github.com/dfinity-lab/sdk/commits/master[link] -to verify: -.. Is `master` green? -.. Was `master` red recently or flaky? -+ - -image:is-master-green.png[] - -=== Preparation - -. Connect to VPN. -. Open a terminal and `cd` into your local copy of the `sdk` repo. - -=== Creating a New Release Branch - -. Check out the `master` branch and pull merged commits from the remote in your working directory by running the following command: -+ -[source, bash] ----- -git checkout master && git pull ----- - -. Create the release branch. Note that the branch name never includes alpha, beta, and so forth. All of these will be released on the same release branch. -+ -[source, bash] ----- -git switch -c release- && git push ----- -+ -For example, if creating the release branch for 0.7.0, you would run the following command: -+ -[source, bash] ----- -git switch -c release-0.7.0 && git push ----- - -. Edit CHANGELOG.md to remove the "UNRELEASED" note from the version to be released. Commit this to change to the release branch. - -=== Resuming on an Existing Release Branch - -. Check out the `master` branch and pull merged commits from the remote in your working directory by running the following command: -+ -[source, bash] ----- -git checkout release- && git pull ----- - -=== Ready - -At this point, you are ready to build a release candidate. -There are two ways you can build a release candidate: - -- Using the <> to automate the build process and skip manual testing. -- Using the <> to build and test the release. - -[[script]] -== SCRIPT-BASED release process - -To use the release script to automate building the release candidate: - -. Run the following command and substitute `` with the version number for this release candidate: -+ -[source, bash] ----- -./scripts/release.sh ----- -+ -For example, if releasing 0.7.0, you would run the following command: -+ -.... -./scripts/release.sh 0.7.0 -.... -. Follow the prompts displayed to complete the release process. - -After running this command to build the release candidate, follow the steps in <> to complete the release process. - -[[manual]] -== MANUAL STEPS release process - -The manual release process provides full instructions for building and testing the release candidate binaries to ensure everything is working before making a release available to internal or external developers. - -=== Build DFX - -Verify that you can build DFX from the `+master+` branch without errors. - -. Verify you're connected to VPN, if necessary. -. Build the `dfx` binary by running the following command: -+ -[source, bash] ----- -cargo clean --release -cargo build --release --locked -export dfx_rc="$(pwd)/target/release/dfx" ----- -+ -The `nix-build` command can take a while to complete. -Wait for it to be done. -These commands create the binary then stores the binary in a shell variable. -. Make sure the `$dfx_rc` variable points to a real file by running the following command: -+ -``` -test -x $dfx_rc \ - && echo 'Please proceed.' \ - || echo 'Cant find executable $dfx_rc'="$dfx_rc" -``` -+ -You should see 'Please proceed' returned. -. Delete the existing `dfx` cache to ensure you're not using a stale binary. -+ -[source, bash] ----- -$dfx_rc cache delete ----- -. Ensure `dfx` and `replica` are not running in the background by running the following command: -+ -[source, bash] ----- -ps -ef | grep -E 'replica|dfx' | grep -v grep ----- -+ -If there are any `replica` or `dfx` processes running, use the `kill` command to terminate them. - -=== Validate the default project - -Verify that you can build, deploy, and call the default `hello_world` project without errors. - -. Generate a default new project and change to the project directory by running the following commands: -+ -[source, bash] ----- -$dfx_rc new hello_world -cd hello_world ----- -. Start the local `replica` as a background process by running the following command: -+ -[source, bash] ----- -$dfx_rc start --clean --background ----- -. Create, build, and install canisters by running the following command: -+ -[source, bash] ----- -$dfx_rc deploy ----- -. Call the canister and verify the result by running the following command: -+ -[source, bash] ----- -$dfx_rc canister call hello_world greet everyone ----- -. Save the canister URLs as shell variables, then print them by running the following commands: -+ -[source, bash] ----- -export hello_world_backend_candid_url="http://localhost:4943/candid?canisterId=$($dfx_rc canister id hello_world_backend)" -export hello_world_frontend_url="http://localhost:4943/?canisterId=$($dfx_rc canister id hello_world_frontend)" ----- -. Open a web browser and clear your cache or switch to Private Browsing/Incognito mode. -. Open the following URL in your web browser: -+ -[source,bash] ----- -echo "$hello_world_frontend_url" ----- -+ -. Verify that you are prompted to type a greeting in a prompt window. -.. Type a greeting, then click *OK* to return the greeting in an alert window. -.. Verify there are no errors in the console by opening the Developer Tools. -+ -For example, in the browser, right-click, then click Inspect and select Console to check for errors and warnings. -Warnings can be ignored. - -. Verify the Candid UI by opening the following URL in your web browser: -+ -[source, bash] ----- -echo "$hello_world_backend_candid_url" ----- -+ -.. Verify UI loads, then test the greet function by entering text and clicking *Call* or clicking *Lucky*, -.. Verify there are no errors in the console by opening the Developer Tools. -+ -For example, in the browser, right-click, then click Inspect and select Console to check for errors and warnings. -Warnings can be ignored. -. Stop the replica by running the following command: -+ -[source, bash] ----- -$dfx_rc stop ----- -. Delete the test project by running the following commands: -+ -[source, bash] ----- -cd .. -rm -rf hello_world ----- - - -=== Whitelist asset canister in Motoko Playground - -If the release includes a new version of the asset canister, then the Motoko Playground needs to have the new asset canister WASM whitelisted. -Otherwise `dfx deploy --playground` will not work for asset canisters. - -Find the new asset canister module hash. It will be listed in `CHANGELOG.md` under `` - `Dependencies` - `Frontend canister`. - -Head over to the link:https://github.com/dfinity/motoko-playground[Motoko Playground repo] and create a PR that adds the asset canister module hash to the whitelist in `service/wasm-utils/lib.rs`. -You can use link:https://github.com/dfinity/motoko-playground/pull/175/files#diff-c8a035da9dcede5539deb0e81164ea50730e3177f56aef747d157406b1ba648dR15-R17[this change] as an example. - -==== Update the version - -. Set the new version in a temporary environment variable. -+ -For example, replace `` with a specific version number: -+ -[source, nix-shell] ----- -export NEW_DFX_VERSION= ----- -. If you're not already there, navigate back to the top-level of the `sdk` repo. -. Enter the sdk `nix` development environment by running the following command: -+ -[source, bash] ----- -nix-shell --option extra-binary-caches https://cache.dfinity.systems ----- -. Create a new branch for your changes by running the following command: -+ -[source, nix-shell] ----- -git switch -c $USER/release-$NEW_DFX_VERSION ----- -. Update the first `version` field in `src/dfx/Cargo.toml` to be equal to `$NEW_DFX_VERSION` -. Apply these changes to `Cargo.lock` by running the following command: -+ -[source, nix-shell] ----- -cargo build ----- -. Append the new version to `public/manifest.json` by appending it to the `versions` list. -+ -For example: -+ -[source, json] ----- -{ - "tags": { - "latest": "0.6.0" - }, - "versions": [ - "0.5.15", - "0.6.0", - "n.n.n" - ] -} ----- -+ -*Ensure* `tags.latest` remains the same. -. Exit `nix-shell` to continue. - -==== Create a pull request and tag - -. Create a pull request with the above changes by running the following commands: -+ -[source, bash] ----- -git add --all -git commit --signoff --message "chore: Release $NEW_DFX_VERSION" -git push origin $USER/release-$NEW_DFX_VERSION ----- -. After pushing, click the link in the console to go to your new branch in GitHub, then click *Create Pull Request*. Change the base branch to `release-`. -. Have the validator review and approve the PR. -. Merge the PR manually (the automerge-squash label only works for PRs to the master branch). -+ -NOTE: Depending on the number of jobs queued up, this step can take 45 to 60 minutes to complete. - -. Switch to the release branch by running the following command: -+ -[source, bash] ----- -git switch release-$NEW_DFX_VERSION ----- -. Set the upstream tracking information for the release branch: -+ -[source, bash] ----- -git branch --set-upstream-to=origin/$NEW_DFX_VERSION $NEW_DFX_VERSION ----- -. Update the release branch: -+ -[source, bash] ----- -git pull ----- -. Create a new tag by running the following command: -+ -[source, bash] ----- -git tag --annotate $NEW_DFX_VERSION --message "Release: $NEW_DFX_VERSION" ----- -. Verify the tag points to the correct version and includes annotation by running the following commands: -+ -[source, bash] ----- -git log -git describe --always ----- -. Push the tag by running the following command: -+ -[source, bash] ----- -git push origin $NEW_DFX_VERSION ----- -+ -The link:../../.github/workflows/publish.yml[publish.yml GitHub workflow] will build the release -and upload to GitHub releases after you push the tag. - -==== Add new frontend canister hash to list of WHITELISTED_WASMS in dfinity/motoko-playground repo -You can do it either by using GitHub UI (https://github.com/dfinity/sdk/actions/workflows/broadcast-frontend-hash.yml) or by running the following command: -[source, bash] ----- -gh workflow run "broadcast-frontend-hash.yml" -f dfx_version= ----- - -[[post-build]] -== Notification and post-build validation - -. Wait for the publish workflow to complete. -. Install the build using the `DFX_VERSION=` environment variable. -. Run through the link:https://sdk.dfinity.org/docs/quickstart/local-quickstart.html[_Quick start - Local development_] steps. -. Run through link:https://sdk.dfinity.org/docs/quickstart/network-quickstart.html#ping-the-network[Check the connection to the network] and link:https://sdk.dfinity.org/docs/quickstart/network-quickstart.html#net-deploy[Register, build, and deploy the application] steps to deploy to the network. -. Notify link:https://app.slack.com/client/T43F9UHS5/CGA566TPV[#eng-sdk] team members that the new build is ready for manual installation and testing. -+ -Remind the SDK and Apps teams to add information about _features and fixes_ for release notes to their issues or PRs and to apply the changelog label to have the information included in the release notes. -. Notify the link:https://forum.dfinity.org[Developer Forum] community if there are breaking changes. -+ -If a release is known to have changes that are not backward-compatible, create a forum post to describe the change and any instructions for migrating to the new release. -+ -Depending on the change, the notification might need to be posted in more than one topic channel. -For example, changes to the external network for onboarded developers are currently posted in link:https://forum.dfinity.org/t/network-status-updates/928[Network status and updates] on the link:https://forum.dfinity.org[DFINITY Developer Forum]. - -== Promote a release candidate to production - -. Verify that release notes and documentation are ready for public consumption. -. Open the `public/manifest.json` file in a text editor. -. Verify that `dfx deploy --playground` works with an asset canister by e.g. deploying the default project created by `dfx new`. -.. If it doesn't work, make sure the PR created on the Motoko Playground repo is merged and deployed. -. Under the `tags` key, change the version number associated with the `latest` key. -+ -For example: -+ -[source,json] ----- -{ - "tags": { - "latest": "n.n.n" - } -} ----- -. Prepare a PR for the manifest by running the following commands: -+ -[source, bash] ----- -git switch -c /update-n.n.n-latest -git add --all -git commit --message "chore: Update the manifest latest to n.n.n " -git push origin /update-n.n.n-latest ----- -. After pushing, click the link in the console to go to your new branch in GitHub, then click *Create Pull Request*. -. Have the validator review and approve the PR, then merge to `master`. -. Verify the Linux and Darwin (macOS) builds are available for download from \https://download.dfinity.systems/sdk/dfx/n.n.n/architecture/dfx-n.n.n.tar.gz. -+ -Linux—Replace _n.n.n_ with the new version number and _architecture_ with `x86_64-linux`. For example, the following link would download version 0.6.1 for Linux: -+ -\https://download.dfinity.systems/sdk/dfx/0.6.1/x86_64-linux/dfx-0.6.1.tar.gz[] -+ -Darwin (macOS)—Replace _n.n.n_ with the new version number and _architecture_ with `x86_64-darwin`. For example, the following link would download version 0.6.1 for macOS: -+ -\https://download.dfinity.systems/sdk/dfx/0.6.1/x86_64-darwin/dfx-0.6.1.tar.gz[] -+ -CI Hydra: -+ -link:https://hydra.dfinity.systems/jobset/dfinity-ci-build/sdk-release[] - -Add a description and publish the tag for the latest release -https://github.com/dfinity-lab/sdk/releases/new?tag=${NEW_DFX_VERSION} - -== Release documentation - -link:https://github.com/dfinity/docs[Documentation repo] - -. Tag the documentation using `git tag -a -m `. -. Publish the tag on the remote server using `git push origin `. -. Deploy updated documentation using Netlify. - -== Requirements and properties - - - Semi-automation - - Consistent delivery - - Validation - - Rollback - - Guardrails - - Flexibility - -== Build mechanism - -Our build process is described in the `release.nix` derivation. -The `release.nix` derivation mainly invokes the `dfx-release` derivation passing the annotated tag on HEAD (which happens right now to be the stable branch). -The `dfx-release` derivation builds the release binaries and files for each platform and generates a manifest for S3 that includes the tag name. -The release tag allows us to keep a directory structure with all past and upcoming releases in S3. - -== CI - -CI release-related operation is split into two jobsets: - - - Generation and publishing of 'install.sh' and 'manifest.json'. - - Tagging of a commit to release, building and publishing the necessary executables and files for supported platforms. - -== Manifest - -We utilize a manifest to indicate to users (and in particular to our installer and dfx executable) available and supported versions for download. -The manifest allows us to rollback a release or remove a release from the list of supported releases. -See link:../specification/version_management{outfilesuffix}[Version Management] for details on the format of the manifest. - -The manifest is generated when a patch is applied on master by the CI. - -== Installer - -The installer is generated when a patch is applied on the `master` branch by the CI. - -== Changelog - -A candidate changelog is generated automatically using the respective tool (under scripts directory). -Currently, the release notes are updated manually in github. - -== Publishing of artifacts - -We now summarize the release process. -Our first step is to ensure the proper and valid state of the `master` branch. -Next, we update `cargo` and the manifest accordingly. -We then create and push an annotated tag on the `stable` branch, generate the changelog. -The product and SDK team members can then inspect, clarify, and develop the changelog to ensure it is appropriate for public -consumption. -After ensuring the proper artifacts are available in S3, we can now publish them by updating the manifest. - -== TODOs and improvements -. version from the tag -. release stress tests -. valid json test for the manifest diff --git a/docs/process/release.md b/docs/process/release.md new file mode 100644 index 0000000000..2f99161f23 --- /dev/null +++ b/docs/process/release.md @@ -0,0 +1,119 @@ +# IC SDK Release Process + +## Overview + +1. Update the replica version +1. Create the release branch +1. Update the changelog on master +1. Create beta releases +1. Open a PR to update the Portal +1. Create the final release +1. Open a PR to promote the release +1. Open a PR to update the Motoko Playground allow-list +1. Promote the release +1. Post to the forum + +## Details + +### Update the Replica Version + +Before making a new release, try to update the replica to the latest version +by running the [update-replica] workflow. + +### Create the Release Branch + +Create a release branch from `master`, for example `release-0.15.3`. + +This branch will be used to create beta releases as well as the final release. + +### Update the changelog + +Open a PR to master. Roll the changelog by adding a new header for the +new dfx version underneath the "# Unreleased" header. Further changes to dfx +should be added under the "#Unreleased" header, unless they are ported to +the release branch. + +### Create Beta Releases + +1. Check out the release branch. +1. Run the release script, for example `./scripts/release.sh 0.15.3-beta.1` +1. Open a PR from the branch pushed by the previous to the release branch, +obtain CR approval, and merge the PR. + - The release script will wait for you to do this + - It will then create and push a tag + - This triggers the [publish][publish-workflow] workflow +1. Wait for the [publish][publish-workflow] workflow to create the GitHub release +from the last commit on the release branch. +1. Update the GitHub release + - Copy/paste the changelog section for the new version into the release notes + - Set the "Prerelease" flag +1. Announce the release to #eng-sdk + - Post a message like this, linking to the GitHub release notes: + > dfx 0.15.3-beta.1 is available for manual installation and testing. + > + > ```bash + > DFX_VERSION=0.15.3-beta.1 sh -ci "$(curl -fsSL https://internetcomputer.org/install.sh)" + > ``` + > + > See also release notes. +1. Repeat the above steps until ready to promote the latest beta. + +### Open a Draft PR to update the Portal + +You can do this step while the beta releases are being tested. + +- Add a link to the [release-notes-table] +- Update the sdk submodule + +Obtain approval, but do not merge the PR yet. + +This PR is a draft in order to help remind the reviewer not to merge it. + +### Create the Final Release + +Once the beta releases are ready to be promoted: + +1. Check out the release branch +2. Run the release script, for example `./scripts/release.sh 0.15.3` +3. Follow the same steps as for the beta releases + +### Open a PR to promote the release + +1. Create a new branch from the release branch, for example `release-0.15.3-promote`. +1. Update the [version manifest][public-manifest]: + - Set `.tags.latest` to the new dfx version + - Remove the beta releases from the `versions` array +1. Open a PR from this branch to master + +Obtain approval, but do not merge this PR yet. + +### Open a PR to Update the Motoko Playground allow-list + +You can do it either by using GitHub UI ([broadcast-frontend-hash-workflow]) +or by running the following command: + +```bash +gh workflow run "broadcast-frontend-hash.yml" -f dfx_version= +``` + +Obtain approval, but do not merge this PR yet. + +### Promote the release + +You should now have three open, approved PRs: + +- Update the portal +- Promote the release +- Update the Motoko Playground allow-list + +Merge all three PRs. + +### Post to the forum + +Post a message to the forum, linking to the GitHub release notes. + +[broadcast-frontend-hash-workflow]: https://github.com/dfinity/sdk/actions/workflows/broadcast-frontend-hash.yml +[public-manifest]: https://github.com/dfinity/sdk/blob/master/public/manifest.json +[publish-workflow]: https://github.com/dfinity/sdk/blob/master/.github/workflows/publish.yml +[release-notes-table]: https://github.com/dfinity/portal/blob/master/docs/other/updates/release-notes/release-notes.md +[update-replica]: https://github.com/dfinity/sdk/actions/workflows/update-replica-version.yml diff --git a/e2e/assets/cycles-ledger/dfx.json b/e2e/assets/cycles-ledger/dfx.json new file mode 100644 index 0000000000..8b092b0d7b --- /dev/null +++ b/e2e/assets/cycles-ledger/dfx.json @@ -0,0 +1,14 @@ +{ + "canisters": { + "cycles-ledger": { + "type": "custom", + "wasm": "cycles-ledger.wasm.gz", + "candid": "cycles-ledger.did" + }, + "cycles-depositor": { + "type": "custom", + "wasm": "cycles-depositor.wasm.gz", + "candid": "cycles-depositor.did" + } + } +} diff --git a/e2e/assets/motoko_management/main.mo b/e2e/assets/motoko_management/main.mo new file mode 100644 index 0000000000..2fd2f8e820 --- /dev/null +++ b/e2e/assets/motoko_management/main.mo @@ -0,0 +1,7 @@ +import Management "ic:aaaaa-aa"; + +actor { + public func rand() : async Blob { + await Management.raw_rand(); + }; +}; diff --git a/e2e/assets/motoko_management/patch.bash b/e2e/assets/motoko_management/patch.bash new file mode 100644 index 0000000000..da753f124a --- /dev/null +++ b/e2e/assets/motoko_management/patch.bash @@ -0,0 +1 @@ +jq '.canisters.e2e_project_backend.main="main.mo"' dfx.json | sponge dfx.json diff --git a/e2e/assets/motoko_management_recursive/dependency.mo b/e2e/assets/motoko_management_recursive/dependency.mo new file mode 100644 index 0000000000..28cf8aece7 --- /dev/null +++ b/e2e/assets/motoko_management_recursive/dependency.mo @@ -0,0 +1,7 @@ +import Management "ic:aaaaa-aa"; + +module Rand { + public func rand() : async Blob { + await Management.raw_rand(); + }; +}; diff --git a/e2e/assets/motoko_management_recursive/main.mo b/e2e/assets/motoko_management_recursive/main.mo new file mode 100644 index 0000000000..8fcf9f9bde --- /dev/null +++ b/e2e/assets/motoko_management_recursive/main.mo @@ -0,0 +1,7 @@ +import Rand "dependency"; + +actor { + public func rand() : async Blob { + await Rand.rand(); + }; +}; diff --git a/e2e/assets/motoko_management_recursive/patch.bash b/e2e/assets/motoko_management_recursive/patch.bash new file mode 100644 index 0000000000..da753f124a --- /dev/null +++ b/e2e/assets/motoko_management_recursive/patch.bash @@ -0,0 +1 @@ +jq '.canisters.e2e_project_backend.main="main.mo"' dfx.json | sponge dfx.json diff --git a/e2e/tests-dfx/assetscanister.bash b/e2e/tests-dfx/assetscanister.bash index a95795fa33..2a5aaf6083 100644 --- a/e2e/tests-dfx/assetscanister.bash +++ b/e2e/tests-dfx/assetscanister.bash @@ -1228,40 +1228,6 @@ CHERRIES" "$stdout" assert_match "404 Not Found" } -@test "asset configuration via .ic-assets.json5 - overwriting etag breaks certification" { - # this is observed behavior, not expected behavior - # https://dfinity.atlassian.net/browse/SDK-1245 - install_asset assetscanister - - dfx_start - - touch src/e2e_project_frontend/assets/thing.json - - dfx deploy - - ID=$(dfx canister id e2e_project_frontend) - PORT=$(get_webserver_port) - - dfx canister call --query e2e_project_frontend http_request '(record{url="/thing.json";headers=vec{};method="GET";body=vec{}})' - assert_command curl --fail --head "http://localhost:$PORT/thing.json?canisterId=$ID" - - echo '[ - { - "match": "thing.json", - "headers": { - "etag": "my-etag" - } - } - ]' > src/e2e_project_frontend/assets/.ic-assets.json5 - - dfx deploy - - dfx canister call --query e2e_project_frontend http_request '(record{url="/thing.json";headers=vec{};method="GET";body=vec{}})' - - assert_command_fail curl --fail --head "http://localhost:$PORT/thing.json?canisterId=$ID" - assert_contains "500 Internal Server Error" -} - @test "asset configuration via .ic-assets.json5 - overwriting default headers" { install_asset assetscanister @@ -1269,8 +1235,6 @@ CHERRIES" "$stdout" touch src/e2e_project_frontend/assets/thing.json - # this test used to also set etag, but that breaks certification - # see https://dfinity.atlassian.net/browse/SDK-1245 echo '[ { "match": "thing.json", @@ -1278,7 +1242,8 @@ CHERRIES" "$stdout" "headers": { "Content-Encoding": "my-encoding", "Content-Type": "x-type", - "Cache-Control": "custom" + "Cache-Control": "custom", + "etag": "my-custom-etag" } } ]' > src/e2e_project_frontend/assets/.ic-assets.json5 @@ -1294,8 +1259,7 @@ CHERRIES" "$stdout" assert_match "cache-control: custom" assert_match "content-encoding: my-encoding" assert_match "content-type: x-type" - # https://dfinity.atlassian.net/browse/SDK-1245 assert_not_match "etag: my-etag" - assert_match "etag: \"[a-z0-9]{64}\"" + assert_match "etag: my-custom-etag" } @test "aliasing rules: to .html or /index.html" { @@ -1768,3 +1732,42 @@ WARN: { assert_command dfx canister call e2e_project_frontend configure '(record { max_chunks=opt opt 3; max_bytes = opt opt 5500 })' assert_command dfx deploy } + +@test "set permissions through upgrade argument" { + dfx_start + dfx deploy + + assert_command dfx canister call e2e_project_frontend list_permitted '(record { permission = variant { Prepare }; })' + assert_eq "(vec {})" + assert_command dfx canister call e2e_project_frontend list_permitted '(record { permission = variant { Commit }; })' + assert_match "$(dfx identity get-principal)" + assert_command dfx canister call e2e_project_frontend list_permitted '(record { permission = variant { ManagePermissions }; })' + assert_eq "(vec {})" + + dfx identity new alice --storage-mode plaintext + ALICE="$(dfx --identity alice identity get-principal)" + + dfx canister install e2e_project_frontend --upgrade-unchanged --mode upgrade --argument "(opt variant { + Upgrade = record { + set_permissions = opt record { + prepare = vec { + principal \"${ALICE}\"; + }; + commit = vec { + principal \"$(dfx identity get-principal)\"; + principal \"aaaaa-aa\"; + }; + manage_permissions = vec { + principal \"$(dfx identity get-principal)\"; + }; + } + } + })" + assert_command dfx canister call e2e_project_frontend list_permitted '(record { permission = variant { Prepare }; })' + assert_match "${ALICE}" + assert_command dfx canister call e2e_project_frontend list_permitted '(record { permission = variant { Commit }; })' + assert_match "$(dfx identity get-principal)" + assert_match '"aaaaa-aa"' + assert_command dfx canister call e2e_project_frontend list_permitted '(record { permission = variant { ManagePermissions }; })' + assert_match "$(dfx identity get-principal)" +} diff --git a/e2e/tests-dfx/build.bash b/e2e/tests-dfx/build.bash index 898e003d0a..2be504a37d 100644 --- a/e2e/tests-dfx/build.bash +++ b/e2e/tests-dfx/build.bash @@ -106,6 +106,24 @@ teardown() { assert_match "10World" } +@test "build supports auto-generated idl for management canister imports in motoko" { + install_asset motoko_management + dfx_start + dfx canister create --all + assert_command dfx build + dfx deploy + assert_command dfx canister call e2e_project_backend rand +} + +@test "build supports auto-generated idl for recursive management canister imports in motoko" { + install_asset motoko_management_recursive + dfx_start + dfx canister create --all + assert_command dfx build + dfx deploy + assert_command dfx canister call e2e_project_backend rand +} + @test "build succeeds on default project" { dfx_start dfx canister create --all diff --git a/e2e/tests-dfx/build_granular.bash b/e2e/tests-dfx/build_granular.bash index 04101028c8..d60b824b53 100644 --- a/e2e/tests-dfx/build_granular.bash +++ b/e2e/tests-dfx/build_granular.bash @@ -47,7 +47,7 @@ teardown() { dfx build e2e_project_backend # validate assets canister wasn't built and can't be installed assert_command_fail dfx canister install e2e_project_frontend - assert_match "No such file or directory" + assert_match "The canister must be built before install. Please run \`dfx build\`." } 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/create.bash b/e2e/tests-dfx/create.bash index a7f04b3ed4..bd16462e84 100644 --- a/e2e/tests-dfx/create.bash +++ b/e2e/tests-dfx/create.bash @@ -14,6 +14,21 @@ teardown() { standard_teardown } +@test "create with reserved cycles limit" { + dfx_start + + assert_command_fail dfx canister create e2e_project_backend --reserved-cycles-limit 470000 + assert_contains "Cannot create a canister using a wallet if the reserved_cycles_limit is set. Please create with --no-wallet or use dfx canister update-settings instead." + + assert_command dfx canister create e2e_project_frontend --no-wallet + assert_command dfx canister status e2e_project_frontend + assert_contains "Reserved Cycles Limit: 5_000_000_000_000 Cycles" + + assert_command dfx canister create e2e_project_backend --reserved-cycles-limit 470000 --no-wallet + assert_command dfx canister status e2e_project_backend + assert_contains "Reserved Cycles Limit: 470_000 Cycles" +} + @test "create succeeds on default project" { dfx_start assert_command dfx canister create --all diff --git a/e2e/tests-dfx/cycles-ledger.bash b/e2e/tests-dfx/cycles-ledger.bash new file mode 100644 index 0000000000..a878e8cc60 --- /dev/null +++ b/e2e/tests-dfx/cycles-ledger.bash @@ -0,0 +1,418 @@ +#!/usr/bin/env bats + +load ../utils/_ +load ../utils/cycles-ledger + +setup() { + standard_setup + install_asset cycles-ledger + install_shared_asset subnet_type/shared_network_settings/system + install_cycles_ledger_canisters + + dfx identity new --storage-mode plaintext cycle-giver + dfx identity new --storage-mode plaintext alice + dfx identity new --storage-mode plaintext bob + + dfx_start_for_nns_install + + dfx extension install nns --version 0.2.1 || true + dfx nns install --ledger-accounts "$(dfx ledger account-id --identity cycle-giver)" +} + +teardown() { + dfx_stop + + standard_teardown +} + +add_cycles_ledger_canisters_to_project() { + jq -s '.[0] * .[1]' ../dfx.json dfx.json | sponge dfx.json +} + +current_time_nanoseconds() { + echo "$(date +%s)"000000000 +} + +@test "balance" { + ALICE=$(dfx identity get-principal --identity alice) + ALICE_SUBACCT1="000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + ALICE_SUBACCT1_CANDID="\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" + ALICE_SUBACCT2="9C9B9A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + ALICE_SUBACCT2_CANDID="\9C\9B\9A\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" + BOB=$(dfx identity get-principal --identity bob) + + assert_command dfx deploy cycles-ledger + assert_command dfx deploy cycles-depositor --argument "(record {ledger_id = principal \"$(dfx canister id cycles-ledger)\"})" --with-cycles 10000000000000 + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --precise + assert_eq "0 cycles." + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice + assert_eq "0.000 TC (trillion cycles)." + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob --precise + assert_eq "0 cycles." + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob + assert_eq "0.000 TC (trillion cycles)." + + + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\";};cycles = 1_700_400_200_150;})" --identity cycle-giver + assert_eq "(record { balance = 1_700_400_200_150 : nat; txid = 0 : nat })" + + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\"; subaccount = opt blob \"$ALICE_SUBACCT1_CANDID\"};cycles = 3_750_000_000_000;})" --identity cycle-giver + assert_eq "(record { balance = 3_750_000_000_000 : nat; txid = 1 : nat })" + + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\"; subaccount = opt blob \"$ALICE_SUBACCT2_CANDID\"};cycles = 760_500_000_000;})" --identity cycle-giver + assert_eq "(record { balance = 760_500_000_000 : nat; txid = 2 : nat })" + + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\";};cycles = 2_900_000_000_000;})" --identity cycle-giver + assert_eq "(record { balance = 2_900_000_000_000 : nat; txid = 3 : nat })" + + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice + assert_eq "1700400200150 cycles." + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT1" + assert_eq "3750000000000 cycles." + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT2" + assert_eq "760500000000 cycles." + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "2900000000000 cycles." + + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice + assert_eq "1.700 TC (trillion cycles)." + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --subaccount "$ALICE_SUBACCT1" + assert_eq "3.750 TC (trillion cycles)." + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --subaccount "$ALICE_SUBACCT2" + assert_eq "0.760 TC (trillion cycles)." + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob + assert_eq "2.900 TC (trillion cycles)." + + + # can see cycles balance of other accounts + assert_command dfx cycles balance --owner "$ALICE" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob + assert_eq "1.700 TC (trillion cycles)." + + assert_command dfx cycles balance --owner "$ALICE" --subaccount "$ALICE_SUBACCT1" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob + assert_eq "3.750 TC (trillion cycles)." + + assert_command dfx cycles balance --owner "$BOB" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity anonymous + assert_eq "2.900 TC (trillion cycles)." +} + +@test "transfer" { + ALICE=$(dfx identity get-principal --identity alice) + ALICE_SUBACCT1="000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + ALICE_SUBACCT1_CANDID="\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" + ALICE_SUBACCT2="9C9B9A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + ALICE_SUBACCT2_CANDID="\9C\9B\9A\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" + BOB=$(dfx identity get-principal --identity bob) + BOB_SUBACCT1="7C7B7A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + + assert_command dfx deploy cycles-ledger + assert_command dfx deploy cycles-depositor --argument "(record {ledger_id = principal \"$(dfx canister id cycles-ledger)\"})" --with-cycles 10000000000000 + + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\";};cycles = 3_000_000_000_000;})" --identity cycle-giver + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\"; subaccount = opt blob \"$ALICE_SUBACCT1_CANDID\"};cycles = 2_000_000_000_000;})" --identity cycle-giver + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\"; subaccount = opt blob \"$ALICE_SUBACCT2_CANDID\"};cycles = 1_000_000_000_000;})" --identity cycle-giver + + # account to account + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice + assert_eq "3000000000000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "0 cycles." + + assert_command dfx cycles transfer "$BOB" 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice + assert_eq "Transfer sent at block index 3" + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice + assert_eq "2999899900000 cycles." + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "100000 cycles." + + # account to subaccount + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice + assert_eq "2999899900000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" + assert_eq "0 cycles." + + assert_command dfx cycles transfer "$BOB" 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --to-subaccount "$BOB_SUBACCT1" + assert_eq "Transfer sent at block index 4" + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice + assert_eq "2999799800000 cycles." + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" + assert_eq "100000 cycles." + + + # subaccount to account + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT2" + assert_eq "1000000000000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "100000 cycles." + + assert_command dfx cycles transfer "$BOB" 700000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --from-subaccount "$ALICE_SUBACCT2" + assert_eq "Transfer sent at block index 5" + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT2" + assert_eq "999899300000 cycles." + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "800000 cycles." + + + # subaccount to subaccount + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT2" + assert_eq "999899300000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" + assert_eq "100000 cycles." + + assert_command dfx cycles transfer "$BOB" 400000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --to-subaccount "$BOB_SUBACCT1" --from-subaccount "$ALICE_SUBACCT2" + assert_eq "Transfer sent at block index 6" + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT2" + assert_eq "999798900000 cycles." + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" + assert_eq "500000 cycles." +} + +@test "transfer deduplication" { + ALICE=$(dfx identity get-principal --identity alice) + BOB=$(dfx identity get-principal --identity bob) + + assert_command dfx deploy cycles-ledger + assert_command dfx deploy cycles-depositor --argument "(record {ledger_id = principal \"$(dfx canister id cycles-ledger)\"})" --with-cycles 10000000000000 + + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\";};cycles = 3_000_000_000_000;})" --identity cycle-giver + + assert_command dfx cycles balance --precise --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "3000000000000 cycles." + + assert_command dfx cycles balance --precise --identity bob --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "0 cycles." + + t=$(current_time_nanoseconds) + + assert_command dfx cycles transfer "$BOB" 100000 --created-at-time "$t" --memo 1 --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "Transfer sent at block index 1" + + assert_command dfx cycles balance --precise --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "2999899900000 cycles." + + assert_command dfx cycles balance --precise --identity bob --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "100000 cycles." + + # same memo and created-at-time: dupe + assert_command dfx cycles transfer "$BOB" 100000 --created-at-time "$t" --memo 1 --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + # shellcheck disable=SC2154 + assert_contains "transaction is a duplicate of another transaction in block 1" "$stderr" + # shellcheck disable=SC2154 + assert_eq "Transfer sent at block index 1" "$stdout" + + assert_command dfx cycles balance --precise --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "2999899900000 cycles." + + assert_command dfx cycles balance --precise --identity bob --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "100000 cycles." + + # different memo and same created-at-time same: not dupe + assert_command dfx cycles transfer "$BOB" 100000 --created-at-time "$t" --memo 2 --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_contains "Transfer sent at block index 2" + + assert_command dfx cycles balance --precise --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "2999799800000 cycles." + + assert_command dfx cycles balance --precise --identity bob --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "200000 cycles." + + # same memo and different created-at-time same: not dupe + assert_command dfx cycles transfer "$BOB" 100000 --created-at-time $((t+1)) --memo 1 --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_contains "Transfer sent at block index 3" + + assert_command dfx cycles balance --precise --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "2999699700000 cycles." + + assert_command dfx cycles balance --precise --identity bob --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "300000 cycles." +} + +@test "top up canister principal check" { + BOB=$(dfx identity get-principal --identity bob) + + assert_command dfx deploy cycles-ledger + + assert_command_fail dfx cycles top-up "$BOB" 600000 --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_contains "Invalid receiver: $BOB. Make sure the receiver is a canister." +} + +@test "top-up" { + dfx_new + add_cycles_ledger_canisters_to_project + install_cycles_ledger_canisters + + BOB=$(dfx identity get-principal --identity bob) + BOB_SUBACCT1="7C7B7A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + BOB_SUBACCT1_CANDID="\7C\7B\7A\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" + BOB_SUBACCT2="6C6B6A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + BOB_SUBACCT2_CANDID="\6C\6B\6A\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" + + assert_command dfx deploy cycles-ledger + assert_command dfx deploy cycles-depositor --argument "(record {ledger_id = principal \"$(dfx canister id cycles-ledger)\"})" --with-cycles 10000000000000 + + assert_command dfx deploy + + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\";};cycles = 2_400_000_000_000;})" --identity cycle-giver + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\"; subaccount = opt blob \"$BOB_SUBACCT1_CANDID\"};cycles = 2_600_000_000_000;})" --identity cycle-giver + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\"; subaccount = opt blob \"$BOB_SUBACCT2_CANDID\"};cycles = 2_700_000_000_000;})" --identity cycle-giver + + # account to canister + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "2400000000000 cycles." + assert_command dfx canister status e2e_project_backend + assert_contains "Balance: 3_100_000_000_000 Cycles" + + assert_command dfx cycles top-up e2e_project_backend 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "2399899900000 cycles." + assert_command dfx canister status e2e_project_backend + assert_contains "Balance: 3_100_000_100_000 Cycles" + + # subaccount to canister + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" + assert_eq "2600000000000 cycles." + assert_command dfx canister status e2e_project_backend + assert_contains "Balance: 3_100_000_100_000 Cycles" + + assert_command dfx cycles top-up e2e_project_backend 300000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob --from-subaccount "$BOB_SUBACCT1" + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" + assert_eq "2599899700000 cycles." + assert_command dfx canister status e2e_project_backend + assert_contains "Balance: 3_100_000_400_000 Cycles" + + # subaccount to canister - by canister id + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT2" + assert_eq "2700000000000 cycles." + assert_command dfx canister status e2e_project_backend + assert_contains "Balance: 3_100_000_400_000 Cycles" + + assert_command dfx cycles top-up "$(dfx canister id e2e_project_backend)" 600000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob --from-subaccount "$BOB_SUBACCT2" + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT2" + assert_eq "2699899400000 cycles." + assert_command dfx canister status e2e_project_backend + assert_contains "Balance: 3_100_001_000_000 Cycles" +} + +@test "top-up deduplication" { + dfx_new + add_cycles_ledger_canisters_to_project + install_cycles_ledger_canisters + + BOB=$(dfx identity get-principal --identity bob) + BOB_SUBACCT1="7C7B7A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + BOB_SUBACCT1_CANDID="\7C\7B\7A\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" + BOB_SUBACCT2="6C6B6A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + BOB_SUBACCT2_CANDID="\6C\6B\6A\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" + + assert_command dfx deploy cycles-ledger + assert_command dfx deploy cycles-depositor --argument "(record {ledger_id = principal \"$(dfx canister id cycles-ledger)\"})" --with-cycles 10000000000000 + + assert_command dfx deploy + + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\";};cycles = 2_400_000_000_000;})" --identity cycle-giver + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\"; subaccount = opt blob \"$BOB_SUBACCT1_CANDID\"};cycles = 2_600_000_000_000;})" --identity cycle-giver + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\"; subaccount = opt blob \"$BOB_SUBACCT2_CANDID\"};cycles = 2_700_000_000_000;})" --identity cycle-giver + + # account to canister + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "2400000000000 cycles." + assert_command dfx canister status e2e_project_backend + assert_contains "Balance: 3_100_000_000_000 Cycles" + + t=$(current_time_nanoseconds) + assert_command dfx cycles top-up "$(dfx canister id e2e_project_backend)" --created-at-time "$t" 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob + assert_eq "Transfer sent at block index 3" + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "2399899900000 cycles." + assert_command dfx canister status e2e_project_backend + assert_contains "Balance: 3_100_000_100_000 Cycles" + + # same created-at-time: dupe + assert_command dfx cycles top-up "$(dfx canister id e2e_project_backend)" --created-at-time "$t" 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob + # shellcheck disable=SC2154 + assert_contains "transaction is a duplicate of another transaction in block 3" "$stderr" + # shellcheck disable=SC2154 + assert_contains "Transfer sent at block index 3" "$stdout" + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "2399899900000 cycles." + + # different created-at-time: not dupe + assert_command dfx cycles top-up "$(dfx canister id e2e_project_backend)" --created-at-time $((t+1)) 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob + assert_eq "Transfer sent at block index 4" + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "2399799800000 cycles." +} + +@test "howto" { + # This is the equivalent of https://www.notion.so/dfinityorg/How-to-install-and-test-the-cycles-ledger-521c9f3c410f4a438514a03e35464299 + ALICE=$(dfx identity get-principal --identity alice) + BOB=$(dfx identity get-principal --identity bob) + + assert_command dfx deploy cycles-ledger + assert_command dfx deploy cycles-depositor --argument "(record {ledger_id = principal \"$(dfx canister id cycles-ledger)\"})" --with-cycles 10000000000000 + + assert_command dfx ledger balance --identity cycle-giver + assert_eq "1000000000.00000000 ICP" + + assert_command dfx canister status cycles-depositor + assert_contains "Balance: 10_000_000_000_000 Cycles" + + dfx canister status cycles-depositor + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --precise + assert_eq "0 cycles." + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob --precise + assert_eq "0 cycles." + + + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\";};cycles = 500_000_000;})" --identity cycle-giver + assert_eq "(record { balance = 500_000_000 : nat; txid = 0 : nat })" + + assert_command dfx canister status cycles-depositor + assert_contains "Balance: 9_999_500_000_000 Cycles" + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --precise + assert_eq "500000000 cycles." + + assert_command dfx cycles transfer "$BOB" 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice + assert_eq "Transfer sent at block index 1" + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --precise + assert_eq "399900000 cycles." + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob --precise + assert_eq "100000 cycles." + + assert_command dfx cycles top-up cycles-depositor 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice + assert_eq "Transfer sent at block index 2" + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --precise + assert_eq "299800000 cycles." + + assert_command dfx canister status cycles-depositor + assert_contains "Balance: 9_999_500_100_000 Cycles" +} 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/deploy.bash b/e2e/tests-dfx/deploy.bash index 88aa5f05fe..87a69c4a32 100644 --- a/e2e/tests-dfx/deploy.bash +++ b/e2e/tests-dfx/deploy.bash @@ -14,6 +14,19 @@ teardown() { standard_teardown } +@test "deploy with reserved cycles limit" { + dfx_start + cat dfx.json + jq '.canisters.hello_backend.initialization_values.reserved_cycles_limit=860000' dfx.json | sponge dfx.json + assert_command_fail dfx deploy + assert_contains "Cannot create a canister using a wallet if the reserved_cycles_limit is set. Please create with --no-wallet or use dfx canister update-settings instead." + + assert_command dfx deploy --no-wallet + + assert_command dfx canister status hello_backend + assert_contains "Reserved Cycles Limit: 860_000 Cycles" +} + @test "deploy --upgrade-unchanged upgrades even if the .wasm did not change" { dfx_start assert_command dfx deploy 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 dd22e5b5b0..bf2c627940 100644 --- a/e2e/tests-dfx/extension.bash +++ b/e2e/tests-dfx/extension.bash @@ -13,13 +13,19 @@ 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 assert_command dfx extension list assert_match 'No extensions installed' - assert_command dfx extension install sns --install-as snsx + assert_command dfx extension install sns --install-as snsx --version 0.2.1 # TODO: how to capture spinner message? # assert_match 'Successfully installed extension' diff --git a/e2e/tests-dfx/install.bash b/e2e/tests-dfx/install.bash index 04fcb84fa9..bd4a4f3d02 100644 --- a/e2e/tests-dfx/install.bash +++ b/e2e/tests-dfx/install.bash @@ -182,7 +182,39 @@ 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 '" } + +@test "remind to build before install" { + dfx_start + dfx canister create --all + assert_command_fail dfx canister install e2e_project_backend + assert_contains "The canister must be built before install. Please run \`dfx build\`." +} diff --git a/e2e/tests-dfx/ledger.bash b/e2e/tests-dfx/ledger.bash index 6c5590fa9c..b22c6f0c99 100644 --- a/e2e/tests-dfx/ledger.bash +++ b/e2e/tests-dfx/ledger.bash @@ -12,7 +12,7 @@ setup() { dfx_start_for_nns_install - dfx extension install nns || true + dfx extension install nns --version 0.2.1 || true dfx nns install --ledger-accounts 345f723e9e619934daac6ae0f4be13a7b0ba57d6a608e511a00fd0ded5866752 22ca7edac648b814e81d7946e8bacea99280e07c5f51a04ba7a38009d8ad8e89 5a94fe181e9d411c58726cb87cbf2d016241b6c350bc3330e4869ca76e54ecbc } @@ -43,32 +43,32 @@ current_time_nanoseconds() { @test "ledger balance & transfer" { dfx identity use alice assert_command dfx ledger account-id - assert_match 345f723e9e619934daac6ae0f4be13a7b0ba57d6a608e511a00fd0ded5866752 + assert_eq 345f723e9e619934daac6ae0f4be13a7b0ba57d6a608e511a00fd0ded5866752 assert_command dfx ledger balance - assert_match "1000000000.00000000 ICP" + assert_eq "1000000000.00000000 ICP" assert_command dfx ledger transfer --amount 100 --memo 1 22ca7edac648b814e81d7946e8bacea99280e07c5f51a04ba7a38009d8ad8e89 # to bob - assert_match "Transfer sent at block height" + assert_contains "Transfer sent at block height" # The sender(alice) paid transaction fee which is 0.0001 ICP assert_command dfx ledger balance - assert_match "999999899.99990000 ICP" + assert_eq "999999899.99990000 ICP" dfx identity use bob assert_command dfx ledger account-id - assert_match 22ca7edac648b814e81d7946e8bacea99280e07c5f51a04ba7a38009d8ad8e89 + assert_eq 22ca7edac648b814e81d7946e8bacea99280e07c5f51a04ba7a38009d8ad8e89 assert_command dfx ledger balance - assert_match "1000000100.00000000 ICP" + assert_eq "1000000100.00000000 ICP" assert_command dfx ledger transfer --icp 100 --e8s 1 --memo 2 345f723e9e619934daac6ae0f4be13a7b0ba57d6a608e511a00fd0ded5866752 # to alice - assert_match "Transfer sent at block height" + assert_contains "Transfer sent at block height" # The sender(bob) paid transaction fee which is 0.0001 ICP # 10100 - 100 - 0.0001 - 0.00000001 = 9999.99989999 assert_command dfx ledger balance - assert_match "999999999.99989999 ICP" + assert_eq "999999999.99989999 ICP" # Transaction Deduplication t=$(current_time_nanoseconds) @@ -77,25 +77,24 @@ current_time_nanoseconds() { # shellcheck disable=SC2154 block_height=$(echo "$stdout" | sed '1q' | sed 's/Transfer sent at block height //') # shellcheck disable=SC2154 - assert_match "Transfer sent at block height $block_height" "$stdout" + assert_eq "Transfer sent at block height $block_height" "$stdout" assert_command dfx ledger transfer --icp 1 --memo 1 --created-at-time $((t+1)) 345f723e9e619934daac6ae0f4be13a7b0ba57d6a608e511a00fd0ded5866752 # shellcheck disable=SC2154 - assert_match "Transfer sent at block height" "$stdout" + assert_contains "Transfer sent at block height" "$stdout" # shellcheck disable=SC2154 - assert_not_match "Transfer sent at block height $block_height" "$stdout" + assert_not_contains "Transfer sent at block height $block_height" "$stdout" assert_command dfx ledger transfer --icp 1 --memo 1 --created-at-time "$t" 345f723e9e619934daac6ae0f4be13a7b0ba57d6a608e511a00fd0ded5866752 # shellcheck disable=SC2154 - assert_match "transaction is a duplicate of another transaction in block $block_height" "$stdout" - # shellcheck disable=SC2154 - assert_match "Transfer sent at block height $block_height" "$stdout" + assert_eq "transaction is a duplicate of another transaction in block $block_height" "$stderr" + assert_eq "Transfer sent at block height $block_height" "$stdout" assert_command dfx ledger transfer --icp 1 --memo 2 --created-at-time "$t" 345f723e9e619934daac6ae0f4be13a7b0ba57d6a608e511a00fd0ded5866752 # shellcheck disable=SC2154 - assert_match "Transfer sent at block height" "$stdout" + assert_contains "Transfer sent at block height" "$stdout" # shellcheck disable=SC2154 - assert_not_match "Transfer sent at block height $block_height" "$stdout" + assert_not_contains "Transfer sent at block height $block_height" "$stdout" } @@ -178,13 +177,19 @@ tc_to_num() { assert_command dfx ledger top-up "$wallet" --icp 5 --created-at-time "$t" # shellcheck disable=SC2154 - assert_match "transaction is a duplicate of another transaction in block $block_height" "$stdout" + assert_contains "transaction is a duplicate of another transaction in block $block_height" "$stderr" # shellcheck disable=SC2154 - assert_match "Transfer sent at block height $block_height" "$stdout" + assert_contains "Transfer sent at block height $block_height" "$stdout" # shellcheck disable=SC2154 - assert_match "Using transfer at block height $block_height" "$stdout" + assert_contains "Using transfer at block height $block_height" "$stdout" # shellcheck disable=SC2154 - assert_match "Canister was topped up with" "$stdout" + assert_contains "Canister was topped up with" "$stdout" + + # Top up canister by name instead of principal + dfx_new + assert_command dfx canister create e2e_project_backend + assert_command dfx ledger top-up e2e_project_backend --amount 5 + assert_contains "Canister was topped up with 617283500000000 cycles" } @test "ledger create-canister" { @@ -226,13 +231,13 @@ tc_to_num() { assert_command dfx ledger create-canister --amount=100 --created-at-time "$t" "$(dfx identity get-principal)" # shellcheck disable=SC2154 - assert_match "transaction is a duplicate of another transaction in block $block_height" "$stdout" + assert_contains "transaction is a duplicate of another transaction in block $block_height" "$stderr" # shellcheck disable=SC2154 - assert_match "Transfer sent at block height $block_height" "$stdout" + assert_contains "Transfer sent at block height $block_height" "$stdout" # shellcheck disable=SC2154 - assert_match "Using transfer at block height $block_height" "$stdout" + assert_contains "Using transfer at block height $block_height" "$stdout" # shellcheck disable=SC2154 - assert_match "Canister created with id: $created_canister_id" "$stdout" + assert_contains "Canister created with id: $created_canister_id" "$stdout" } diff --git a/e2e/tests-dfx/start.bash b/e2e/tests-dfx/start.bash index 2ba61ab7b7..52a735bda6 100644 --- a/e2e/tests-dfx/start.bash +++ b/e2e/tests-dfx/start.bash @@ -12,6 +12,48 @@ teardown() { standard_teardown } +@test "icx-proxy domain configuration in string form" { + create_networks_json + jq '.local.proxy.domain="xyz.domain"' "$E2E_NETWORKS_JSON" | sponge "$E2E_NETWORKS_JSON" + + dfx_start + + assert_command ps aux + assert_match "icx-proxy.*--domain xyz.domain" +} + +@test "icx-proxy domain configuration in vector form" { + create_networks_json + jq '.local.proxy.domain=["xyz.domain", "abc.something"]' "$E2E_NETWORKS_JSON" | sponge "$E2E_NETWORKS_JSON" + + dfx_start + + assert_command ps aux + assert_match "icx-proxy.*--domain xyz.domain" + assert_match "icx-proxy.*--domain abc.something" +} + +@test "icx-proxy domain configuration from project defaults" { + dfx_new + define_project_network + + jq '.defaults.proxy.domain=["xyz.domain", "abc.something"]' dfx.json | sponge dfx.json + + dfx_start + + assert_command ps aux + assert_match "icx-proxy.*--domain xyz.domain" + assert_match "icx-proxy.*--domain abc.something" +} + +@test "icx-proxy domain configuration from command-line" { + dfx_start --domain xyz.domain --domain def.somewhere + + assert_command ps aux + assert_match "icx-proxy.*--domain xyz.domain" + assert_match "icx-proxy.*--domain def.somewhere" +} + @test "dfx restarts the replica" { dfx_new hello dfx_start diff --git a/e2e/tests-dfx/update_settings.bash b/e2e/tests-dfx/update_settings.bash index 8ad100f00b..54f529948d 100644 --- a/e2e/tests-dfx/update_settings.bash +++ b/e2e/tests-dfx/update_settings.bash @@ -14,6 +14,17 @@ teardown() { standard_teardown } +@test "set reserved cycles limit" { + dfx_start + assert_command dfx deploy hello_backend + assert_command dfx canister status hello_backend + assert_contains "Reserved Cycles Limit: 5_000_000_000_000 Cycles" + + assert_command dfx canister update-settings hello_backend --reserved-cycles-limit 650000 + assert_command dfx canister status hello_backend + assert_contains "Reserved Cycles Limit: 650_000 Cycles" +} + @test "set freezing threshold" { dfx_start assert_command dfx deploy hello_backend diff --git a/e2e/utils/cycles-ledger.bash b/e2e/utils/cycles-ledger.bash new file mode 100644 index 0000000000..0409faa0e4 --- /dev/null +++ b/e2e/utils/cycles-ledger.bash @@ -0,0 +1,36 @@ +CYCLES_LEDGER_VERSION="0.2.1" + +build_artifact_url() { + echo "https://github.com/dfinity/cycles-ledger/releases/download/cycles-ledger-v$CYCLES_LEDGER_VERSION/${1}" +} + +downloaded_cycles_ledger_canisters_dir() { + echo "$DFX_CACHE_ROOT/canisters/cycles-ledger/$CYCLES_LEDGER_VERSION" +} + +download_cycles_ledger_canisters() { + DOWNLOAD_DIR="$DFX_CACHE_ROOT/.download" + DEST_DIR="$(downloaded_cycles_ledger_canisters_dir)" + + if test -d "$DEST_DIR"; then + return + fi + + rm -rf "$DOWNLOAD_DIR" + mkdir -p "$DOWNLOAD_DIR" "$(dirname "$DEST_DIR")" + + for name in cycles-ledger cycles-depositor; do + for ext in wasm.gz wasm.gz.sha256 did; do + URL=$(build_artifact_url "${name}.${ext}") + curl -v -L --fail -o "$DOWNLOAD_DIR/${name}.${ext}" "$URL" + done + done + + ( cd "$DOWNLOAD_DIR" && shasum -c cycles-ledger.wasm.gz.sha256 && shasum -c cycles-depositor.wasm.gz.sha256 ) + mv "$DOWNLOAD_DIR" "$DEST_DIR" +} + +install_cycles_ledger_canisters() { + download_cycles_ledger_canisters + cp "$(downloaded_cycles_ledger_canisters_dir)"/* . +} diff --git a/nix/sources.json b/nix/sources.json index 14c77ab188..5793f4efa5 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -6,104 +6,104 @@ "homepage": "https://rustsec.org", "owner": "RustSec", "repo": "advisory-db", - "rev": "9b6403d856f71291aabb91511b53fa79c2758745", - "sha256": "1b839a6bja6x1660737yfv7b7qfldcjd36g2s3a1v74q3f6zv5nw", + "rev": "3338fcfb59cea5fcd7d2a4e7fe24cbc7cb778003", + "sha256": "0fw5xrzafv061jj3lzrnqarbjcm1irzvl338yhkzw1k8firmki7d", "type": "tarball", - "url": "https://github.com/RustSec/advisory-db/archive/9b6403d856f71291aabb91511b53fa79c2758745.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": { "builtin": false, "description": "The canister_sandbox binary. It must be updated together with the replica binary.", - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "06dqva0my0hqraxwj5nqql58j3yry0vnjb8a37syjkz1fvjg78yg", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "049hfmpi7njn439hry1z5qb3k45z300jvrvcgycbxrdiz5nd9kaa", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/canister_sandbox.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/canister_sandbox.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-darwin/canister_sandbox.gz" }, "canister_sandbox-x86_64-linux": { "builtin": false, "description": "The canister_sandbox binary. It must be updated together with the replica binary.", - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "0n7axa0ymsj0nkd9iy3vj93b08q682f3r7i2bzg2bc4y96pvqjkv", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "04r9rs47ky6715jwia5qzpj5983y2xyg246wncjhybqn79a9m10i", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/canister_sandbox.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/canister_sandbox.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-linux/canister_sandbox.gz" }, "ic-admin-x86_64-darwin": { "builtin": false, "description": "The ic-admin binary.", - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "1l0xh0f8pw8qmvqdcbssps71i6qinpmicva5yw24dw6ycl66rnlw", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "15r1ymcrhb1z859cpjhg3y9nswskh94sxr8l1gqbw5lsf6y8ygsb", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/ic-admin.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/ic-admin.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-darwin/ic-admin.gz" }, "ic-admin-x86_64-linux": { "builtin": false, "description": "The ic-admin binary.", - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "0dh9w6h9cv6ygqxv1b14vlpw32c0mlvf9x1kjihfd449xcbf4rpm", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "00hry4mjramd8dwx88v8crrzjj0rzkvd23ckqig3bglvaisnsspf", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/ic-admin.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/ic-admin.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-linux/ic-admin.gz" }, "ic-btc-adapter-x86_64-darwin": { "builtin": false, - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "1hd1vlgca2sy37gcafna9l4a1jmv9ndvdzk63084wsf0d8g8agx6", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "0y79j7rzi12896808sai0nhfzslmgrg1gvm7kfprf89jrikh1v9w", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/ic-btc-adapter.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/ic-btc-adapter.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-darwin/ic-btc-adapter.gz" }, "ic-btc-adapter-x86_64-linux": { "builtin": false, - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "1k0vq2nbm3zjpnhm175h733aidgk7rm34zs8v2cw4f35h4x9n9n6", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "1silh7jx2i6ln7r1k49ndgddm4fm10f9f3f822lyz90vz7dml6yk", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/ic-btc-adapter.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/ic-btc-adapter.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-linux/ic-btc-adapter.gz" }, "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, - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "1h0s6gw81f50kr93vnrgpylfq4nzm7ini6f90pbmbfh4r50iawyb", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "14nivx59ww4y0phpwxfcisc4an2sny5r4f3qrmalqk4vi445mszy", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/ic-https-outcalls-adapter.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/ic-https-outcalls-adapter.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-darwin/ic-https-outcalls-adapter.gz" }, "ic-https-outcalls-adapter-x86_64-linux": { "builtin": false, - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "1cbjimj3jiy1y427mznwzasv019a68igki0c3nwq7crlm48xbn6n", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "0qgxzfzym8gh91bsg5krmlrh39anlcgnff330w4jgiwql95ayvr7", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/ic-https-outcalls-adapter.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/ic-https-outcalls-adapter.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-linux/ic-https-outcalls-adapter.gz" }, "ic-nns-init-x86_64-darwin": { "builtin": false, "description": "The ic-nns-init binary.", - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "0r7dy3wa96nf1f1r7dcsp1bhk1si0az6b6mvgj7icni213mf23ag", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "0c59dsi9gwxzj9l2d94k48yk2vdz0gb1yjfh58ky1sx4w28hxzc5", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/ic-nns-init.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/ic-nns-init.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-darwin/ic-nns-init.gz" }, "ic-nns-init-x86_64-linux": { "builtin": false, "description": "The ic-nns-init binary.", - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "1zh39j3mlqgk0axkpppjzfqb406gmfb5yxi0jvn5xps01cfvsy5i", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "15v8a6d71rg7xgl3nvy5l839qxyvkig1mlldpdr4bmmwp3yqx3nm", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/ic-nns-init.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/ic-nns-init.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-linux/ic-nns-init.gz" }, "ic-ref-x86_64-darwin": { @@ -126,114 +126,114 @@ }, "ic-starter-x86_64-darwin": { "builtin": false, - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "0vf29dznkba48xjpacanrniqz03aj805k6kgc73inagkn2flmz9n", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "1ar30xi3vnrwpyl0cir3m4dvdzdwm09xji33w25krj5n9503acqz", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/ic-starter.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/ic-starter.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-darwin/ic-starter.gz" }, "ic-starter-x86_64-linux": { "builtin": false, - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "0dnhb3hgncn9m4430g78pz2yblqmhpnq2z2piqlkjrcb68ssm7b6", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "1ddgxd9pnybnjiqhgggxlkbq8ml99ca4iq54kh221kdj7h1m334d", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/ic-starter.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/ic-starter.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-linux/ic-starter.gz" }, "icx-proxy-x86_64-darwin": { "builtin": false, - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "09y3q0ri294qkfp5bywpm37f7c7gd44xq8a2fx5lafzfd98xb6v1", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "1p9gmlz85j514s6da189hwaghg18p62pbknkn3q59jyxmf22fzxh", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/icx-proxy-dev.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/icx-proxy-dev.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-darwin/icx-proxy-dev.gz" }, "icx-proxy-x86_64-linux": { "builtin": false, - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "0h8k4hf42grjhhs6nnl8gcb9k02cs4dm1a25mjlkf6vi3f6sx307", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "105jm3px6ky88jc86am8dkxz1vnhzcxy0p7skzs98baylr96kzrb", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/icx-proxy-dev.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/icx-proxy-dev.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-linux/icx-proxy-dev.gz" }, "motoko-base": { "builtin": false, "description": "The Motoko base library", "owner": "dfinity", - "sha256": "18qp0d8mr6hcnbym81a4hgvj036vm0qdbjb833w1rqqhibv1083s", + "sha256": "12z4mr3r63nnncjqxrsxjhr1z2p8adg7zp48wbacb42jhs0mkfvl", "type": "tarball", - "url": "https://github.com/dfinity/motoko/releases/download/0.9.8/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.9.8" + "version": "0.10.2" }, "motoko-x86_64-darwin": { "builtin": false, - "sha256": "153lnpkdna9dv76zvmy44farsy8r4ixv4yi8bf5qnkr9dmkmrdr7", + "sha256": "1x49qwzrxc6dj5gik2hpi8l3xdnggqj2v9yvb6sfb7ff6gx3avc6", "type": "file", - "url": "https://github.com/dfinity/motoko/releases/download/0.9.8/motoko-Darwin-x86_64-0.9.8.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.9.8" + "version": "0.10.2" }, "motoko-x86_64-linux": { "builtin": false, - "sha256": "11yaciq3fq6fckqrw9gh5wb23cz5wxk9fij0z107nsiys9z46g2i", + "sha256": "1a1yv2awrd053qk3h9a34y887j2vfhb0ckrk25kjjx4ifdygp8ys", "type": "file", - "url": "https://github.com/dfinity/motoko/releases/download/0.9.8/motoko-Linux-x86_64-0.9.8.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.9.8" + "version": "0.10.2" }, "replica-x86_64-darwin": { "builtin": false, "description": "The replica binary. It must be updated together with the canister_sandbox binary.", - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "08sh0rfj8ykmvr74a4hzm3j4kbhrz5d7c3vachsm2jla9dhvd6rl", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "12z1lvhv257ywf1b4gknywdimh5yqnfx20yxn37f30iifg2zw87k", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/replica.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/replica.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-darwin/replica.gz" }, "replica-x86_64-linux": { "builtin": false, "description": "The replica binary. It must be updated together with the canister_sandbox binary.", - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "0sbzdp9ydmv8lv055gw04gvr6lz3li7ibfnz7f1833qvcqwjacjv", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "120iinjcybvc346wf1iq6r964a3w5dhhif6rnf2ngf0q3350rlrc", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/replica.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/replica.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-linux/replica.gz" }, "sandbox_launcher-x86_64-darwin": { "builtin": false, "description": "The sandbox_launcher binary. It must be updated together with the replica binary.", - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "19ma4n918bq7z9avlaazfdrq94xvsdl153kwmaysxw19gz4f01a0", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "12pz2i2yhfl2saab3rc5sf0dr24l6siirpsx8z414818mzpc42zd", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/sandbox_launcher.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/sandbox_launcher.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-darwin/sandbox_launcher.gz" }, "sandbox_launcher-x86_64-linux": { "builtin": false, "description": "The sandbox_launcher binary. It must be updated together with the replica binary.", - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "10qq77zwbyas65y2msa55pjhiz24pi9ghhmg6gqldx96hf6z6xkn", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "0zzpr02vc14ibx1qzd31a9jzh1zhb7ahcg85fazs6jkjk2zidi4n", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/sandbox_launcher.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/sandbox_launcher.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-linux/sandbox_launcher.gz" }, "sns-x86_64-darwin": { "builtin": false, "description": "The sns binary.", - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "0pm8ihnf4hyn9jsnb299lxlv2w8nix2zy7ax93z4wvzi2ngksfi4", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "12xkvxp3jprxw0205ml4ad3gdksi0x5c3kf7skcmkvqk744nml04", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/sns.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/sns.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-darwin/sns.gz" }, "sns-x86_64-linux": { "builtin": false, "description": "The sns binary.", - "rev": "91bf38ff3cb927cb94027d9da513cd15f91a5b04", - "sha256": "151342zhm4hn9v1h4c9h6hdirjsx5g9ghnqf6k0zlxg6cxl2l1ky", + "rev": "69e1408347723dbaa7a6cd2faa9b65c42abbe861", + "sha256": "02aqj9qcpvk216sdvkz25q1pf32bwb6wnf8v704rw133wpqq8sln", "type": "file", - "url": "https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/sns.gz", + "url": "https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/sns.gz", "url_template": "https://download.dfinity.systems/ic//openssl-static-binaries/x86_64-linux/sns.gz" } } diff --git a/public/install/200_downloader.sh b/public/install/200_downloader.sh index 4916e4a216..db2a8b7f8e 100644 --- a/public/install/200_downloader.sh +++ b/public/install/200_downloader.sh @@ -26,7 +26,7 @@ check_help_for() { fi for _arg in "$@"; do - if ! "$_cmd" --help | grep -q -- "$_arg"; then + if ! "$_cmd" --help all | grep -q -- "$_arg"; then _ok="n" fi done diff --git a/public/manifest.json b/public/manifest.json index 861b203a03..d302e1a0e0 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,6 +1,6 @@ { "tags": { - "latest": "0.15.0" + "latest": "0.15.2" }, "versions": [ "0.5.0", @@ -57,6 +57,9 @@ "0.14.1", "0.14.2", "0.14.3", - "0.14.4" + "0.14.4", + "0.15.0", + "0.15.1", + "0.15.2" ] } diff --git a/scripts/test-uis.py b/scripts/test-uis.py new file mode 100644 index 0000000000..5752936c29 --- /dev/null +++ b/scripts/test-uis.py @@ -0,0 +1,341 @@ +""" +Automate frontend tests by using Playwright. +The script tests the following UIs: + +1. Frontend UI. +2. Candid UI. + +Examples: + +$ python3 test-uis.py --frontend_url '...' --browser chromium firefox webkit # Only test the frontend UI +$ python3 test-uis.py --candid_url '...' --browser chromium firefox webkit # Only test the Candid UI +$ python3 test-uis.py --frontend_url '...' --candid_url '...' --browser chromium firefox webkit # Test both UIs +""" +import argparse +import logging +import re +import sys +import time +from enum import Enum + +from playwright.sync_api import sync_playwright + +_CHROMIUM_BROWSER = "chromium" +_FIREFOX_BROWSER = "firefox" +_WEBKIT_BROWSER = "webkit" +_SUPPORTED_BROWSERS = { + _CHROMIUM_BROWSER, + _FIREFOX_BROWSER, + _WEBKIT_BROWSER, +} +_CANDID_UI_WARNINGS_TO_IGNORE = [ + ("Error", "/index.js"), + ("Invalid asm.js: Unexpected token", "/index.js"), + ("Expected to find result for path [object Object], but instead found nothing.", "/index.js"), + ( + """ +Error: Server returned an error: + Code: 404 (Not Found) + Body: Custom section name not found. + + at j.readState (http://localhost:4943/index.js:2:11709) + at async http://localhost:4943/index.js:2:97683 + at async Promise.all (index 0) + at async Module.UA (http://localhost:4943/index.js:2:98732) + at async Object.getNames (http://localhost:4943/index.js:2:266156) + at async http://localhost:4943/index.js:2:275479""".strip(), + "/index.js", + ), + ( + """ +Error: Server returned an error: + Code: 404 (Not Found) + Body: Custom section name not found.""".strip(), + "/index.js", + ), +] +_CANDID_UI_ERRORS_TO_IGNORE = [ + ("Failed to load resource: the server responded with a status of 404 (Not Found)", "/read_state"), +] +# `page.route` does not support additional function parameters +_FRONTEND_URL = None + + +class _UI(Enum): + CANDID = 1 + FRONTEND = 2 + + +def _validate_browsers(browser): + if browser not in _SUPPORTED_BROWSERS: + logging.error(f"Browser {browser} not supported") + sys.exit(1) + + return browser + + +def _get_argument_parser(): + parser = argparse.ArgumentParser(description="Test the Frontend and Candid UIs") + + parser.add_argument("--frontend_url", help="Frontend UI url") + parser.add_argument("--candid_url", help="Candid UI url") + + parser.add_argument( + "--browsers", + nargs="+", + type=_validate_browsers, + help=f"Test against the specified browsers ({_SUPPORTED_BROWSERS})", + ) + + return parser + + +def _validate_args(args): + has_err = False + + if not args.frontend_url and not args.candid_url: + logging.error('Either "--frontend_url" or "--candid_url" must be specified to start the tests') + has_err = True + + if not args.browsers: + logging.error("At least one browser must be specified") + logging.error(f"Possible browsers: {_SUPPORTED_BROWSERS}") + has_err = True + + if has_err: + sys.exit(1) + + +def _get_browser_obj(playwright, browser_name): + if browser_name == _CHROMIUM_BROWSER: + return playwright.chromium + if browser_name == _FIREFOX_BROWSER: + return playwright.firefox + if browser_name == _WEBKIT_BROWSER: + return playwright.webkit + + return None + + +def _check_console_logs(console_logs): + logging.info("Checking console logs") + + has_err = False + for log in console_logs: + if log.type not in {"warning", "error"}: + continue + + # Skip all `Error with Permissions-Policy header: Unrecognized feature` warnings + perm_policy_warn = "Error with Permissions-Policy header:" + if perm_policy_warn in log.text: + logging.warning(f'Skipping Permissions-Policy warning. log.text="{log.text}"') + continue + + url = log.location.get("url") + if not url: + raise RuntimeError( + f'Cannot find "url" during log parsing (log.type={log.type}, log.text="{log.text}", log.location="{log.location}")' + ) + + for actual_text, endpoint in ( + _CANDID_UI_ERRORS_TO_IGNORE if log.type == "error" else _CANDID_UI_WARNINGS_TO_IGNORE + ): + if actual_text == log.text.strip() and endpoint in url: + logging.warning( + f'Found {log.type}, but it was expected (log.type="{actual_text}", endpoint="{endpoint}")' + ) + break + else: + logging.error(f'Found unexpected console log {log.type}. Text: "{log.text}", url: {url}') + + has_err = True + + if has_err: + raise RuntimeError("Console has unexpected warnings and/or errors. Check previous logs") + + logging.info("Console logs are ok") + + +def _click_button(page, button): + logging.info(f'Clicking button "{button}"') + page.get_by_role("button", name=button).click() + + +def _set_text(page, text, value): + logging.info(f'Setting text to "{value}"') + page.get_by_role("textbox", name=text).fill(value) + + +def _test_frontend_ui_handler(page): + # Set the name & Click the button + name = "my name" + logging.info(f'Setting name "{name}"') + page.get_by_label("Enter your name:").fill(name) + _click_button(page, "Click Me!") + + # Check if `#greeting` is populated correctly + greeting_id = "#greeting" + timeout_ms = 60000 + greeting_obj = page.wait_for_selector(greeting_id, timeout=timeout_ms) + if greeting_obj: + actual_value = greeting_obj.inner_text() + expected_value = f"Hello, {name}!" + if actual_value == expected_value: + logging.info(f'"{actual_value}" found in "{greeting_id}"') + else: + raise RuntimeError(f'Expected greeting message is "{expected_value}", but found "{actual_value}"') + else: + raise RuntimeError(f"Cannot find {greeting_id} selector") + + +def _test_candid_ui_handler(page): + # Set the text & Click the "Query" button + text = "hello, world" + _set_text(page, "text", text) + _click_button(page, "Query") + + # Check if `#output-list` is populated correctly (after the first click) + output_list_id = "#output-list" + timeout_ms = 60000 + _ = page.wait_for_selector(output_list_id, timeout=timeout_ms) + + # Reset the text & Click the "Random" button + _set_text(page, "text", "") + _click_button(page, "Random") + # ~ + + # Check if `#output-list` is populated correctly (after the second click) + # + # NOTE: `#output-list` already exists, so `wait_for_selector` won't work as expected. + # We noticed that, especially for `Ubuntu 20.04` and `Webkit`, the two additional lines + # created once the `Random` button was clicked, were not created properly. + # + # For this reason there is this simple fallback logic that tries to look at the selector + # for more than once by sleeping for some time. + fallback_retries = 10 + fallback_sleep_sec = 5 + last_err = None + for _ in range(fallback_retries): + try: + output_list_obj = page.wait_for_selector(output_list_id, timeout=timeout_ms) + if not output_list_obj: + raise RuntimeError(f"Cannot find {output_list_id} selector") + + output_list_lines = output_list_obj.inner_text().split("\n") + actual_num_lines, expected_num_lines = len(output_list_lines), 4 + if actual_num_lines != expected_num_lines: + err = [f"Expected {expected_num_lines} lines of text but found {actual_num_lines}"] + err.append("Lines:") + err.extend(output_list_lines) + raise RuntimeError("\n".join(err)) + + # Extract random text from third line + random_text = re.search(r'"([^"]*)"', output_list_lines[2]) + if not random_text: + raise RuntimeError(f"Cannot extract the random text from the third line: {output_list_lines[2]}") + random_text = random_text.group(1) + + for i, text_str in enumerate([text, random_text]): + line1, line2 = (i * 2), (i * 2 + 1) + + # First output line + actual_line, expected_line = output_list_lines[line1], f'› greet("{text_str}")' + if actual_line != expected_line: + raise RuntimeError(f"Expected {expected_line} line, but found {actual_line} (line {line1})") + logging.info(f'"{actual_line}" found in {output_list_id} at position {line1}') + + # Second output line + actual_line, expected_line = output_list_lines[line2], f'("Hello, {text_str}!")' + if actual_line != expected_line: + raise RuntimeError(f"Expected {expected_line} line, but found {actual_line} (line {line2})") + logging.info(f'"{actual_line}" found in {output_list_id} at position {line2}') + + # All good! + last_err = None + logging.info(f"{output_list_id} lines are defined correctly") + break + except RuntimeError as run_err: + last_err = str(run_err) + logging.warning(f"Fallback hit! Sleeping for {fallback_sleep_sec} before continuing") + time.sleep(fallback_sleep_sec) + + if last_err: + raise RuntimeError(last_err) + + +def _handle_route_for_webkit(route): + url = route.request.url.replace("https://", "http://") + + headers = None + if any(map(url.endswith, [".css", ".js", ".svg"])): + global _FRONTEND_URL + assert _FRONTEND_URL + headers = { + "referer": _FRONTEND_URL, + } + + response = route.fetch(url=url, headers=headers) + assert response.status == 200, f"Expected 200 status code, but got {response.status}. Url: {url}" + route.fulfill(response=response) + + +def _test_ui(ui, url, handler, browsers): + logging.info(f'Testing "{str(ui)}" at "{url}"') + + has_err = False + with sync_playwright() as playwright: + for browser_name in browsers: + logging.info(f'Checking "{browser_name}" browser') + browser = _get_browser_obj(playwright, browser_name) + if not browser: + raise RuntimeError(f"Cannot determine browser object for browser {browser_name}") + + try: + browser = browser.launch(headless=True) + context = browser.new_context() + page = context.new_page() + + # Attach a listener to the page's console events + console_logs = [] + page.on("console", lambda msg: console_logs.append(msg)) + + # Webkit forces HTTPS: + # - https://github.com/microsoft/playwright/issues/12975 + # - https://stackoverflow.com/questions/46394682/safari-keeps-forcing-https-on-localhost + if ui == _UI.FRONTEND and browser_name == _WEBKIT_BROWSER: + global _FRONTEND_URL + _FRONTEND_URL = url + page.route("**/*", _handle_route_for_webkit) + + page.goto(url) + + handler(page) + _check_console_logs(console_logs) + except Exception as e: + logging.error(f"Error: {str(e)}") + has_err = True + finally: + if context: + context.close() + if browser: + browser.close() + + if has_err: + sys.exit(1) + + +def _main(): + args = _get_argument_parser().parse_args() + _validate_args(args) + + if args.frontend_url: + _test_ui(_UI.FRONTEND, args.frontend_url, _test_frontend_ui_handler, args.browsers) + if args.candid_url: + _test_ui(_UI.CANDID, args.candid_url, _test_candid_ui_handler, args.browsers) + + logging.info("DONE!") + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") + _main() 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/canister_api/methods/api_version.rs b/src/canisters/frontend/ic-asset/src/canister_api/methods/api_version.rs index 235a221787..b882c1e255 100644 --- a/src/canisters/frontend/ic-asset/src/canister_api/methods/api_version.rs +++ b/src/canisters/frontend/ic-asset/src/canister_api/methods/api_version.rs @@ -4,7 +4,7 @@ use ic_utils::Canister; pub(crate) async fn api_version(canister: &Canister<'_>) -> u16 { canister - .query_(API_VERSION) + .query(API_VERSION) .build() .call() .await diff --git a/src/canisters/frontend/ic-asset/src/canister_api/methods/asset_properties.rs b/src/canisters/frontend/ic-asset/src/canister_api/methods/asset_properties.rs index a0fda24559..4efdd1c8da 100644 --- a/src/canisters/frontend/ic-asset/src/canister_api/methods/asset_properties.rs +++ b/src/canisters/frontend/ic-asset/src/canister_api/methods/asset_properties.rs @@ -49,7 +49,7 @@ pub(crate) async fn get_asset_properties( asset_id: &str, ) -> Result { let (asset_properties,): (AssetProperties,) = canister - .query_(GET_ASSET_PROPERTIES) + .query(GET_ASSET_PROPERTIES) .with_arg(GetAssetPropertiesArgument(asset_id.to_string())) .build() .call() diff --git a/src/canisters/frontend/ic-asset/src/canister_api/methods/batch.rs b/src/canisters/frontend/ic-asset/src/canister_api/methods/batch.rs index db4ad8d6f5..db0296f75a 100644 --- a/src/canisters/frontend/ic-asset/src/canister_api/methods/batch.rs +++ b/src/canisters/frontend/ic-asset/src/canister_api/methods/batch.rs @@ -24,7 +24,7 @@ pub(crate) async fn create_batch(canister: &Canister<'_>) -> Result( loop { match canister - .update_(method_name) + .update(method_name) .with_arg(&arg) .build() .call_and_wait() @@ -103,7 +103,7 @@ pub(crate) async fn compute_evidence( loop { match canister - .update_(COMPUTE_EVIDENCE) + .update(COMPUTE_EVIDENCE) .with_arg(arg) .build() .map(|result: (Option,)| (result.0,)) diff --git a/src/canisters/frontend/ic-asset/src/canister_api/methods/chunk.rs b/src/canisters/frontend/ic-asset/src/canister_api/methods/chunk.rs index 8fab2c9045..ad55aab8eb 100644 --- a/src/canisters/frontend/ic-asset/src/canister_api/methods/chunk.rs +++ b/src/canisters/frontend/ic-asset/src/canister_api/methods/chunk.rs @@ -26,7 +26,7 @@ pub(crate) async fn create_chunk( .build(); loop { - let builder = canister.update_(CREATE_CHUNK); + let builder = canister.update(CREATE_CHUNK); let builder = builder.with_arg(&args); let request_id_result = { let _releaser = semaphores.create_chunk_call.acquire(1).await; diff --git a/src/canisters/frontend/ic-asset/src/canister_api/methods/list.rs b/src/canisters/frontend/ic-asset/src/canister_api/methods/list.rs index 1d7734e35b..321e30b34c 100644 --- a/src/canisters/frontend/ic-asset/src/canister_api/methods/list.rs +++ b/src/canisters/frontend/ic-asset/src/canister_api/methods/list.rs @@ -9,7 +9,7 @@ pub(crate) async fn list_assets( canister: &Canister<'_>, ) -> Result, AgentError> { let (entries,): (Vec,) = canister - .query_(LIST) + .query(LIST) .with_arg(ListAssetsRequest {}) .build() .call() 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/ic-certified-assets/Cargo.toml b/src/canisters/frontend/ic-certified-assets/Cargo.toml index 6c2ef2b88d..0aa6639bbc 100644 --- a/src/canisters/frontend/ic-certified-assets/Cargo.toml +++ b/src/canisters/frontend/ic-certified-assets/Cargo.toml @@ -16,7 +16,7 @@ base64.workspace = true candid.workspace = true hex.workspace = true ic-cdk.workspace = true -ic-certified-map = "0.3.2" +ic-certification = "1.3.0" ic-response-verification = "0.3.0" ic-representation-independent-hash = "0.3.0" itertools.workspace = true diff --git a/src/canisters/frontend/ic-certified-assets/assets.did b/src/canisters/frontend/ic-certified-assets/assets.did index c4f659eb88..51bb1a235b 100644 --- a/src/canisters/frontend/ic-certified-assets/assets.did +++ b/src/canisters/frontend/ic-certified-assets/assets.did @@ -139,7 +139,25 @@ type ListPermitted = record { permission: Permission }; type ValidationResult = variant { Ok : text; Err : text }; -service: { +type AssetCanisterArgs = variant { + Init: InitArgs; + Upgrade: UpgradeArgs; +}; + +type InitArgs = record {}; + +type UpgradeArgs = record { + set_permissions: opt SetPermissions; +}; + +/// Sets the list of principals granted each permission. +type SetPermissions = record { + prepare: vec principal; + commit: vec principal; + manage_permissions: vec principal; +}; + +service: (asset_canister_args: opt AssetCanisterArgs) -> { api_version: () -> (nat16) query; get: (record { @@ -220,10 +238,10 @@ service: { authorize: (principal) -> (); deauthorize: (principal) -> (); - list_authorized: () -> (vec principal) query; + list_authorized: () -> (vec principal); grant_permission: (GrantPermission) -> (); revoke_permission: (RevokePermission) -> (); - list_permitted: (ListPermitted) -> (vec principal) query; + list_permitted: (ListPermitted) -> (vec principal); take_ownership: () -> (); get_asset_properties : (key: Key) -> (record { diff --git a/src/canisters/frontend/ic-certified-assets/src/asset_certification/mod.rs b/src/canisters/frontend/ic-certified-assets/src/asset_certification/mod.rs index 42b731fd05..b69e5d2233 100644 --- a/src/canisters/frontend/ic-certified-assets/src/asset_certification/mod.rs +++ b/src/canisters/frontend/ic-certified-assets/src/asset_certification/mod.rs @@ -1,5 +1,5 @@ use self::{ - tree::{merge_hash_trees, NestedTree}, + tree::NestedTree, types::{ certification::{AssetPath, HashTreePath, NestedTreeKey, RequestHash, WitnessResult}, http::{ @@ -8,13 +8,14 @@ use self::{ }, }; use crate::asset_certification::types::http::build_ic_certificate_expression_header; +use ic_certification::merge_hash_trees; use ic_representation_independent_hash::Value; use serde::Serialize; use sha2::Digest; pub mod tree; pub mod types; -pub use ic_certified_map::HashTree; +pub use ic_certification::HashTree; pub type CertifiedResponses = NestedTree>; @@ -184,25 +185,18 @@ impl CertifiedResponses { WitnessResult::PathFound, ) } else { - let fallback_path = HashTreePath::not_found_base_path_v2(); - let absence_proof = self.witness(hash_tree_path_root.as_vec()); - let fallback_trailing_slash_path = HashTreePath::not_found_trailing_slash_path_v2(); - let not_found_trailing_slash_proof = - self.witness(fallback_trailing_slash_path.as_vec()); - let mut combined_proof = - merge_hash_trees(absence_proof, not_found_trailing_slash_proof); - - let mut partial_path = hash_tree_path_root.0; - while partial_path.pop().is_some() && !partial_path.is_empty() { - partial_path.push(NestedTreeKey::String("<*>".into())); + let fallback_paths = hash_tree_path_root.fallback_paths_v2(); - let proof = self.witness(HashTreePath::from(partial_path.clone()).as_vec()); - combined_proof = merge_hash_trees(combined_proof, proof); - - partial_path.pop(); // remove <*> - } + let combined_proof = + fallback_paths + .into_iter() + .fold(absence_proof, |accumulator, path| { + let new_proof = self.witness(path.as_vec()); + merge_hash_trees(accumulator, new_proof) + }); + let fallback_path = HashTreePath::not_found_base_path_v2(); if self.contains_path(fallback_path.as_vec()) { (combined_proof, WitnessResult::FallbackFound) } else { diff --git a/src/canisters/frontend/ic-certified-assets/src/asset_certification/tree.rs b/src/canisters/frontend/ic-certified-assets/src/asset_certification/tree.rs index 89b292f2ab..d46c4dfec9 100644 --- a/src/canisters/frontend/ic-certified-assets/src/asset_certification/tree.rs +++ b/src/canisters/frontend/ic-certified-assets/src/asset_certification/tree.rs @@ -1,4 +1,4 @@ -use ic_certified_map::{AsHashTree, HashTree, RbTree}; +use ic_certification::{AsHashTree, HashTree, RbTree}; pub trait NestedTreeKeyRequirements: Clone + AsRef<[u8]> + 'static {} pub trait NestedTreeValueRequirements: AsHashTree + 'static {} @@ -18,14 +18,14 @@ impl Default for N } impl AsHashTree for NestedTree { - fn root_hash(&self) -> ic_certified_map::Hash { + fn root_hash(&self) -> ic_certification::Hash { match self { NestedTree::Leaf(a) => a.root_hash(), NestedTree::Nested(tree) => tree.root_hash(), } } - fn as_hash_tree(&self) -> HashTree<'_> { + fn as_hash_tree(&self) -> HashTree { match self { NestedTree::Leaf(a) => a.as_hash_tree(), NestedTree::Nested(tree) => tree.as_hash_tree(), @@ -129,41 +129,6 @@ impl NestedTree(lhs: HashTree<'a>, rhs: HashTree<'a>) -> HashTree<'a> { - use HashTree::{Empty, Fork, Labeled, Leaf, Pruned}; - - match (lhs, rhs) { - (Pruned(l), Pruned(r)) => { - if l != r { - panic!("merge_hash_trees: inconsistent hashes"); - } - Pruned(l) - } - (Pruned(_), r) => r, - (l, Pruned(_)) => l, - (Fork(l), Fork(r)) => Fork(Box::new(( - merge_hash_trees(l.0, r.0), - merge_hash_trees(l.1, r.1), - ))), - (Labeled(l_label, l), Labeled(r_label, r)) => { - if l_label != r_label { - panic!("merge_hash_trees: inconsistent hash tree labels"); - } - Labeled(l_label, Box::new(merge_hash_trees(*l, *r))) - } - (Empty, Empty) => Empty, - (Leaf(l), Leaf(r)) => { - if l != r { - panic!("merge_hash_trees: inconsistent leaves"); - } - Leaf(l) - } - (_l, _r) => { - panic!("merge_hash_trees: inconsistent tree structure"); - } - } -} - #[test] fn nested_tree_operation() { let mut tree: NestedTree<&str, Vec> = NestedTree::default(); diff --git a/src/canisters/frontend/ic-certified-assets/src/asset_certification/types/certification.rs b/src/canisters/frontend/ic-certified-assets/src/asset_certification/types/certification.rs index 807f7a5e0b..209dee8b74 100644 --- a/src/canisters/frontend/ic-certified-assets/src/asset_certification/types/certification.rs +++ b/src/canisters/frontend/ic-certified-assets/src/asset_certification/types/certification.rs @@ -145,6 +145,28 @@ impl HashTreePath { base64::encode(cbor) } + /// Produces all `HashTreePath`s required to prove + /// - whether or not fallback file exists and + /// - that there is no fallback file with higher priority + /// in the hash tree. + pub fn fallback_paths_v2(&self) -> Vec { + let mut paths = Vec::new(); + + // starting at 1 because "http_expr" is always the starting element + for i in 1..self.0.len() { + let mut without_trailing_slash: Vec = self.0.as_slice()[0..i].into(); + let mut with_trailing_slash = without_trailing_slash.clone(); + without_trailing_slash.push("<*>".into()); + with_trailing_slash.push("".into()); + with_trailing_slash.push("<*>".into()); + + paths.push(without_trailing_slash.into()); + paths.push(with_trailing_slash.into()); + } + + paths + } + pub fn new( asset: &str, status_code: u16, @@ -182,14 +204,6 @@ impl HashTreePath { ])) } - pub fn not_found_trailing_slash_path_v2() -> Self { - HashTreePath::from(Vec::from([ - NestedTreeKey::String("http_expr".into()), - NestedTreeKey::String("".into()), - NestedTreeKey::String("<*>".into()), - ])) - } - pub fn not_found_base_path_v1() -> Self { let not_found_path = AssetPath::from(FALLBACK_FILE); not_found_path.asset_hash_path_v1() diff --git a/src/canisters/frontend/ic-certified-assets/src/asset_certification/types/http.rs b/src/canisters/frontend/ic-certified-assets/src/asset_certification/types/http.rs index 1fd6e0157d..1e176c9549 100644 --- a/src/canisters/frontend/ic-certified-assets/src/asset_certification/types/http.rs +++ b/src/canisters/frontend/ic-certified-assets/src/asset_certification/types/http.rs @@ -4,7 +4,7 @@ use crate::{ state_machine::{encoding_certification_order, Asset, AssetEncoding}, }; use candid::{define_function, CandidType, Deserialize, Nat}; -use ic_certified_map::Hash; +use ic_certification::Hash; use ic_representation_independent_hash::{representation_independent_hash, Value}; use serde_bytes::ByteBuf; use sha2::Digest; @@ -182,10 +182,15 @@ impl HttpResponse { let (status_code, body) = if etags.contains(&enc.sha256) { (304, RcBytes::default()) } else { - headers.insert( - "etag".to_string(), - format!("\"{}\"", hex::encode(enc.sha256)), - ); + if !headers + .iter() + .any(|(header_name, _)| header_name.eq_ignore_ascii_case("etag")) + { + headers.insert( + "etag".to_string(), + format!("\"{}\"", hex::encode(enc.sha256)), + ); + } (200, enc.content_chunks[chunk_index].clone()) }; diff --git a/src/canisters/frontend/ic-certified-assets/src/lib.rs b/src/canisters/frontend/ic-certified-assets/src/lib.rs index 827fa05b99..336a0106a9 100644 --- a/src/canisters/frontend/ic-certified-assets/src/lib.rs +++ b/src/canisters/frontend/ic-certified-assets/src/lib.rs @@ -104,14 +104,14 @@ async fn validate_revoke_permission(arg: RevokePermissionArguments) -> Result ManualReply> { STATE.with(|s| ManualReply::one(s.borrow().list_permitted(&Permission::Commit))) } -#[query(manual_reply = true)] -#[candid_method(query)] +#[update(manual_reply = true)] +#[candid_method(update)] fn list_permitted(arg: ListPermittedArguments) -> ManualReply> { STATE.with(|s| ManualReply::one(s.borrow().list_permitted(&arg.permission))) } @@ -413,7 +413,10 @@ fn is_controller() -> Result<(), String> { } } -pub fn init() { +pub fn init(args: Option) { + if let Some(upgrade_arg) = args { + let AssetCanisterArgs::Init(InitArgs {}) = upgrade_arg else { ic_cdk::trap("Cannot initialize the canister with an Upgrade argument. Please provide an Init argument.")}; + } STATE.with(|s| { let mut s = s.borrow_mut(); s.clear(); @@ -425,10 +428,18 @@ pub fn pre_upgrade() -> StableState { STATE.with(|s| s.take().into()) } -pub fn post_upgrade(stable_state: StableState) { +pub fn post_upgrade(stable_state: StableState, args: Option) { + let set_permissions = args.and_then(|args| { + let AssetCanisterArgs::Upgrade(UpgradeArgs { set_permissions }) = args else {ic_cdk::trap("Cannot upgrade the canister with an Init argument. Please provide an Upgrade argument.")}; + set_permissions + }); + STATE.with(|s| { *s.borrow_mut() = State::from(stable_state); set_certified_data(&s.borrow().root_hash()); + if let Some(set_permissions) = set_permissions { + s.borrow_mut().set_permissions(set_permissions); + } }); } diff --git a/src/canisters/frontend/ic-certified-assets/src/state_machine.rs b/src/canisters/frontend/ic-certified-assets/src/state_machine.rs index 4bcc82b90a..3a41f358a6 100644 --- a/src/canisters/frontend/ic-certified-assets/src/state_machine.rs +++ b/src/canisters/frontend/ic-certified-assets/src/state_machine.rs @@ -24,7 +24,7 @@ use crate::{ url_decode::url_decode, }; use candid::{CandidType, Deserialize, Int, Nat, Principal}; -use ic_certified_map::{AsHashTree, Hash}; +use ic_certification::{AsHashTree, Hash}; use ic_representation_independent_hash::Value; use num_traits::ToPrimitive; use serde::Serialize; @@ -320,6 +320,20 @@ impl State { .ok_or_else(|| "asset not found".to_string()) } + pub fn set_permissions( + &mut self, + SetPermissions { + prepare, + commit, + manage_permissions, + }: SetPermissions, + ) { + *self.get_mut_permission_list(&Permission::Prepare) = prepare.into_iter().collect(); + *self.get_mut_permission_list(&Permission::Commit) = commit.into_iter().collect(); + *self.get_mut_permission_list(&Permission::ManagePermissions) = + manage_permissions.into_iter().collect(); + } + pub fn grant_permission(&mut self, principal: Principal, permission: &Permission) { let permitted = self.get_mut_permission_list(permission); permitted.insert(principal); diff --git a/src/canisters/frontend/ic-certified-assets/src/tests.rs b/src/canisters/frontend/ic-certified-assets/src/tests.rs index 3afe42767f..88fb797277 100644 --- a/src/canisters/frontend/ic-certified-assets/src/tests.rs +++ b/src/canisters/frontend/ic-certified-assets/src/tests.rs @@ -84,7 +84,17 @@ pub fn verify_response( fn certified_http_request(state: &State, request: HttpRequest) -> HttpResponse { let response = state.http_request(request.clone(), &[], unused_callback()); - assert!(verify_response(state, &request, &response).expect("Certificate validation failed.")); + match verify_response(state, &request, &response) { + Err(err) => panic!( + "Response verification failed with error {:?}. Response: {:#?}", + err, response + ), + Ok(success) => { + if !success { + panic!("Response verification failed. Response: {:?}", response) + } + } + } response } @@ -510,6 +520,8 @@ fn serve_fallback_v2() { vec![ AssetBuilder::new("/index.html", "text/html") .with_encoding("identity", vec![INDEX_BODY]), + AssetBuilder::new("/deep/nested/folder/index.html", "text/html") + .with_encoding("identity", vec![OTHER_BODY]), AssetBuilder::new("/deep/nested/folder/a_file.html", "text/html") .with_encoding("identity", vec![OTHER_BODY]), AssetBuilder::new("/deep/nested/sibling/another_file.html", "text/html") @@ -1875,6 +1887,49 @@ mod certification_v2 { assert!(lookup_header(&response, "ic-certificate").is_some()); } + + #[test] + fn etag() { + // For now only checks that defining a custom etag doesn't break certification. + // Serving HTTP 304 responses if the etag matches is part of https://dfinity.atlassian.net/browse/SDK-191 + + let mut state = State::default(); + let time_now = 100_000_000_000; + + const BODY: &[u8] = b""; + + create_assets( + &mut state, + time_now, + vec![AssetBuilder::new("/contents.html", "text/html") + .with_encoding("identity", vec![BODY]) + .with_header("etag", "my-etag")], + ); + + let response = certified_http_request( + &state, + RequestBuilder::get("/contents.html") + .with_header("Accept-Encoding", "gzip,identity") + .with_certificate_version(1) + .build(), + ); + assert_eq!( + lookup_header(&response, "etag").expect("ic-certificate header missing"), + "my-etag" + ); + + let response = certified_http_request( + &state, + RequestBuilder::get("/contents.html") + .with_header("Accept-Encoding", "gzip,identity") + .with_certificate_version(2) + .build(), + ); + assert_eq!( + lookup_header(&response, "etag").expect("ic-certificate header missing"), + "my-etag" + ); + } } #[cfg(test)] diff --git a/src/canisters/frontend/ic-certified-assets/src/types.rs b/src/canisters/frontend/ic-certified-assets/src/types.rs index 0373146bb6..d72ccdf92d 100644 --- a/src/canisters/frontend/ic-certified-assets/src/types.rs +++ b/src/canisters/frontend/ic-certified-assets/src/types.rs @@ -184,3 +184,27 @@ pub struct RevokePermissionArguments { pub struct ListPermittedArguments { pub permission: Permission, } + +/// The argument to `init` and `post_upgrade` needs to have the same argument type by definition. +/// `AssetCanisterArgs` is there so that the two functions can take different argument types. +#[derive(Clone, Debug, CandidType, Deserialize)] +pub enum AssetCanisterArgs { + Init(InitArgs), + Upgrade(UpgradeArgs), +} + +#[derive(Clone, Debug, CandidType, Deserialize)] +pub struct InitArgs {} + +#[derive(Clone, Debug, CandidType, Deserialize)] +pub struct UpgradeArgs { + pub set_permissions: Option, +} + +/// Sets the list of principals with a certain permission for every permission that is `Some`. +#[derive(Clone, Debug, CandidType, Deserialize)] +pub struct SetPermissions { + pub prepare: Vec, + pub commit: Vec, + pub manage_permissions: Vec, +} diff --git a/src/canisters/frontend/ic-frontend-canister/src/lib.rs b/src/canisters/frontend/ic-frontend-canister/src/lib.rs index ac0cd9d0c7..ccb562c56d 100644 --- a/src/canisters/frontend/ic-frontend-canister/src/lib.rs +++ b/src/canisters/frontend/ic-frontend-canister/src/lib.rs @@ -1,8 +1,9 @@ use ic_cdk::{init, post_upgrade, pre_upgrade}; +use ic_certified_assets::types::AssetCanisterArgs; #[init] -fn init() { - ic_certified_assets::init(); +fn init(args: Option) { + ic_certified_assets::init(args); } #[pre_upgrade] @@ -12,8 +13,8 @@ fn pre_upgrade() { } #[post_upgrade] -fn post_upgrade() { +fn post_upgrade(args: Option) { let (stable_state,): (ic_certified_assets::StableState,) = ic_cdk::storage::stable_restore().expect("failed to restore stable state"); - ic_certified_assets::post_upgrade(stable_state); + ic_certified_assets::post_upgrade(stable_state, args); } diff --git a/src/canisters/frontend/icx-asset/src/commands/list.rs b/src/canisters/frontend/icx-asset/src/commands/list.rs index 50ee387c86..5bbddd014b 100644 --- a/src/canisters/frontend/icx-asset/src/commands/list.rs +++ b/src/canisters/frontend/icx-asset/src/commands/list.rs @@ -26,7 +26,7 @@ pub async fn list(canister: &Canister<'_>, logger: &Logger) -> anyhow::Result<() struct EmptyRecord {} let (entries,): (Vec,) = canister - .query_("list") + .query("list") .with_arg(EmptyRecord {}) .build() .call() 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 5e233544f5..f4ffd78cc6 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; @@ -10,10 +11,11 @@ use crate::error::dfx_config::GetFreezingThresholdError::GetFreezingThresholdFai use crate::error::dfx_config::GetMemoryAllocationError::GetMemoryAllocationFailed; use crate::error::dfx_config::GetPullCanistersError::PullCanistersSameId; use crate::error::dfx_config::GetRemoteCanisterIdError::GetRemoteCanisterIdFailed; +use crate::error::dfx_config::GetReservedCyclesLimitError::GetReservedCyclesLimitFailed; use crate::error::dfx_config::{ AddDependenciesError, GetCanisterConfigError, GetCanisterNamesWithDependenciesError, GetComputeAllocationError, GetFreezingThresholdError, GetMemoryAllocationError, - GetPullCanistersError, GetRemoteCanisterIdError, + GetPullCanistersError, GetRemoteCanisterIdError, GetReservedCyclesLimitError, }; use crate::error::load_dfx_config::LoadDfxConfigError; use crate::error::load_dfx_config::LoadDfxConfigError::{ @@ -55,6 +57,7 @@ const EMPTY_CONFIG_DEFAULTS: ConfigDefaults = ConfigDefaults { bootstrap: None, build: None, canister_http: None, + proxy: None, replica: None, }; @@ -347,6 +350,19 @@ pub struct InitializationValues { #[serde(with = "humantime_serde")] #[schemars(with = "Option")] pub freezing_threshold: Option, + + /// # Reserved Cycles Limit + /// Specifies the upper limit of the canister's reserved cycles balance. + /// + /// Reserved cycles are cycles that the system sets aside for future use by the canister. + /// If a subnet's storage exceeds 450 GiB, then every time a canister allocates new storage bytes, + /// the system sets aside some amount of cycles from the main balance of the canister. + /// These reserved cycles will be used to cover future payments for the newly allocated bytes. + /// The reserved cycles are not transferable and the amount of reserved cycles depends on how full the subnet is. + /// + /// A setting of 0 means that the canister will trap if it tries to allocate new storage while the subnet's memory usage exceeds 450 GiB. + #[schemars(with = "Option")] + pub reserved_cycles_limit: Option, } /// # Declarations Configuration @@ -540,6 +556,13 @@ pub struct ConfigDefaultsReplica { pub log_level: Option, } +/// Configuration for icx-proxy. +#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub struct ConfigDefaultsProxy { + /// A list of domains that can be served. These are used for canister resolution [default: localhost] + pub domain: SerdeVec, +} + // Schemars doesn't add the enum value's docstrings. Therefore the explanations have to be up here. /// # Network Type /// Type 'ephemeral' is used for networks that are regularly reset. @@ -628,6 +651,7 @@ pub struct ConfigLocalProvider { pub canister_http: Option, pub replica: Option, pub playground: Option, + pub proxy: Option, } #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, JsonSchema)] @@ -652,6 +676,7 @@ pub struct ConfigDefaults { pub bootstrap: Option, pub build: Option, pub canister_http: Option, + pub proxy: Option, pub replica: Option, } @@ -836,6 +861,17 @@ impl ConfigInterface { .freezing_threshold) } + pub fn get_reserved_cycles_limit( + &self, + canister_name: &str, + ) -> Result, GetReservedCyclesLimitError> { + Ok(self + .get_canister_config(canister_name) + .map_err(|e| GetReservedCyclesLimitFailed(canister_name.to_string(), e))? + .initialization_values + .reserved_cycles_limit) + } + fn get_canister_config( &self, canister_name: &str, @@ -988,6 +1024,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/config/model/local_server_descriptor.rs b/src/dfx-core/src/config/model/local_server_descriptor.rs index ff4403247c..6d59829cfa 100644 --- a/src/dfx-core/src/config/model/local_server_descriptor.rs +++ b/src/dfx-core/src/config/model/local_server_descriptor.rs @@ -1,12 +1,14 @@ use crate::config::model::bitcoin_adapter; use crate::config::model::canister_http_adapter::HttpAdapterLogLevel; use crate::config::model::dfinity::{ - to_socket_addr, ConfigDefaultsBitcoin, ConfigDefaultsCanisterHttp, ConfigDefaultsReplica, - ReplicaLogLevel, ReplicaSubnetType, DEFAULT_PROJECT_LOCAL_BIND, DEFAULT_SHARED_LOCAL_BIND, + to_socket_addr, ConfigDefaultsBitcoin, ConfigDefaultsCanisterHttp, ConfigDefaultsProxy, + ConfigDefaultsReplica, ReplicaLogLevel, ReplicaSubnetType, DEFAULT_PROJECT_LOCAL_BIND, + DEFAULT_SHARED_LOCAL_BIND, }; use crate::error::network_config::{ NetworkConfigError, NetworkConfigError::ParseBindAddressFailed, }; +use crate::json::structure::SerdeVec; use slog::{debug, info, Logger}; use std::net::SocketAddr; use std::path::{Path, PathBuf}; @@ -30,6 +32,7 @@ pub struct LocalServerDescriptor { pub bitcoin: ConfigDefaultsBitcoin, pub canister_http: ConfigDefaultsCanisterHttp, + pub proxy: ConfigDefaultsProxy, pub replica: ConfigDefaultsReplica, pub scope: LocalNetworkScopeDescriptor, @@ -51,6 +54,7 @@ impl LocalServerDescriptor { bind: String, bitcoin: ConfigDefaultsBitcoin, canister_http: ConfigDefaultsCanisterHttp, + proxy: ConfigDefaultsProxy, replica: ConfigDefaultsReplica, scope: LocalNetworkScopeDescriptor, legacy_pid_path: Option, @@ -61,6 +65,7 @@ impl LocalServerDescriptor { bind_address, bitcoin, canister_http, + proxy, replica, scope, legacy_pid_path, @@ -199,6 +204,13 @@ impl LocalServerDescriptor { }; Self { bitcoin, ..self } } + + pub fn with_proxy_domains(self, domains: Vec) -> LocalServerDescriptor { + let proxy = ConfigDefaultsProxy { + domain: SerdeVec::Many(domains), + }; + Self { proxy, ..self } + } } impl LocalServerDescriptor { 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/error/dfx_config.rs b/src/dfx-core/src/error/dfx_config.rs index 062ff19a1c..943484f11b 100644 --- a/src/dfx-core/src/error/dfx_config.rs +++ b/src/dfx-core/src/error/dfx_config.rs @@ -40,6 +40,12 @@ pub enum GetFreezingThresholdError { GetFreezingThresholdFailed(String, GetCanisterConfigError), } +#[derive(Error, Debug)] +pub enum GetReservedCyclesLimitError { + #[error("Failed to get reserved cycles limit for canister '{0}': {1}")] + GetReservedCyclesLimitFailed(String, GetCanisterConfigError), +} + #[derive(Error, Debug)] pub enum GetMemoryAllocationError { #[error("Failed to get memory allocation for canister '{0}': {1}")] diff --git a/src/dfx-core/src/extension/manager/install.rs b/src/dfx-core/src/extension/manager/install.rs index 11d48c1716..f25b550d2d 100644 --- a/src/dfx-core/src/extension/manager/install.rs +++ b/src/dfx-core/src/extension/manager/install.rs @@ -17,6 +17,7 @@ impl ExtensionManager { &self, extension_name: &str, install_as: Option<&str>, + version: Option<&Version>, ) -> Result<(), ExtensionError> { let effective_extension_name = install_as.unwrap_or(extension_name); @@ -29,7 +30,10 @@ impl ExtensionManager { )); } - let extension_version = self.get_extension_compatible_version(extension_name)?; + let extension_version = match version { + Some(version) => version.clone(), + None => self.get_extension_compatible_version(extension_name)?, + }; let github_release_tag = get_git_release_tag(extension_name, &extension_version); let extension_archive = get_extension_archive_name(extension_name)?; let url = get_extension_download_url(&github_release_tag, &extension_archive)?; diff --git a/src/dfx-core/src/json/structure.rs b/src/dfx-core/src/json/structure.rs index 8bfbd71e62..c838f0eacc 100644 --- a/src/dfx-core/src/json/structure.rs +++ b/src/dfx-core/src/json/structure.rs @@ -4,7 +4,7 @@ use serde::Serialize; use std::fmt::Display; use std::str::FromStr; -#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)] +#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema, PartialEq, Eq)] #[serde(untagged)] pub enum SerdeVec { One(T), diff --git a/src/dfx-core/src/network/provider.rs b/src/dfx-core/src/network/provider.rs index dcc67b2cd6..6c12ec4efd 100644 --- a/src/dfx-core/src/network/provider.rs +++ b/src/dfx-core/src/network/provider.rs @@ -96,6 +96,11 @@ fn config_network_to_network_descriptor( .clone() .or_else(|| project_defaults.and_then(|x| x.canister_http.clone())) .unwrap_or_default(); + let proxy = local_provider + .proxy + .clone() + .or_else(|| project_defaults.and_then(|x| x.proxy.clone())) + .unwrap_or_default(); let replica = local_provider .replica .clone() @@ -121,6 +126,7 @@ fn config_network_to_network_descriptor( bind_address, bitcoin, canister_http, + proxy, replica, local_scope, legacy_pid_path, @@ -237,6 +243,7 @@ fn create_shared_network_descriptor( canister_http: None, replica: None, playground: None, + proxy: None, })) } (network_name, None) => { @@ -474,7 +481,7 @@ mod tests { ReplicaLogLevel, }; use std::fs; - use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + use std::net::SocketAddr; use std::str::FromStr; #[test] 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/.gitignore b/src/dfx/.gitignore deleted file mode 100644 index 8e97362b93..0000000000 --- a/src/dfx/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -# Created by https://www.gitignore.io/api/rust -# Edit at https://www.gitignore.io/?templates=rust - -### Rust ### -# Generated by Cargo -# will have compiled files and executables -target/ - -# The following is commented out since we need to guarantee all engineers and CI -# are using the same crates. -# # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -# **/Cargo.lock - -# These are backup files generated by rustfmt -**/*.rs.bk - -# End of https://www.gitignore.io/api/rust - -### ASCIIDOC ### - -/docs/**/*.png -/docs/**/*.svg -!/docs/assets/*.png -!/docs/assets/*.svg -/docs/**/*.html -/docs/**/.asciidoctor - -README.html - -### Working files ### -.* -!.gitignore -!.cargo -,* -*~ -*.bak diff --git a/src/dfx/Cargo.toml b/src/dfx/Cargo.toml index 4f6f1ae8a2..518531bc3f 100644 --- a/src/dfx/Cargo.toml +++ b/src/dfx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dfx" -version = "0.14.3" +version = "0.15.1" authors.workspace = true edition.workspace = true repository.workspace = true @@ -63,9 +63,11 @@ humantime.workspace = true hyper-rustls = { version = "0.24.1", features = ["webpki-roots", "http2"] } ic-agent = { workspace = true, features = ["reqwest"] } ic-asset.workspace = true +ic-cdk.workspace = true ic-identity-hsm = { workspace = true } ic-utils = { workspace = true } ic-wasm = "0.4.0" +icrc-ledger-types = "0.1.1" indicatif = "0.16.0" itertools.workspace = true json-patch = "1.0.0" @@ -75,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 2ab11fd4f1..41c18e690d 100644 --- a/src/dfx/assets/dfx-asset-sources.toml +++ b/src/dfx/assets/dfx-asset-sources.toml @@ -1,118 +1,118 @@ # generated by write-dfx-asset-sources.sh -replica-rev = '91bf38ff3cb927cb94027d9da513cd15f91a5b04' +replica-rev = '69e1408347723dbaa7a6cd2faa9b65c42abbe861' [x86_64-darwin.ic-ref] url = 'https://download.dfinity.systems/ic-ref/ic-ref-0.0.1-a9f73dba-x86_64-darwin.tar.gz' sha256 = 'e1c1694579f46d544aa87f6387d7e5a4b096fe65015b1609a459efcbaf15890f' [x86_64-darwin.icx-proxy] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/icx-proxy-dev.gz' -sha256 = '619bd5516aee3b454b774221dc0969efb0e3cea897fb55ae9b98241133c0c327' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/icx-proxy-dev.gz' +sha256 = 'b07f2784abddcb54f0b0d3ce7585b9283cf814870905d58c26a1c8823ead2fdd' [x86_64-darwin.ic-admin] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/ic-admin.gz' -sha256 = '9cda6c0c65def04604f7456d16ebb5119b188ebe5a2fd6f0ae18f18b1c801dd0' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/ic-admin.gz' +sha256 = '4b3f8fbc719a16bef00b14e5ae498253736d931f0fcacb52413f2c9859f52197' [x86_64-darwin.ic-btc-adapter] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/ic-btc-adapter.gz' -sha256 = 'a63f851e6ac0694e101866feb69b4dbbcaa0084dca3ac5de195e0bc51edda1c1' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/ic-btc-adapter.gz' +sha256 = '3ced0067cc322197af9ba7ee175e7e95eaefa00551690490494884f8f391e978' [x86_64-darwin.ic-https-outcalls-adapter] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/ic-https-outcalls-adapter.gz' -sha256 = 'cb731541c904ba55d705c99968e3a9df12eca8bf2fdb3d529ea0b880f8331ac0' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/ic-https-outcalls-adapter.gz' +sha256 = 'feeb5a08899b4c4c55cd7838928bb75a5845988ecc757ee1059e709e4adfd192' [x86_64-darwin.ic-nns-init] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/ic-nns-init.gz' -sha256 = '4f0de1ea08225a168f7cbb9a65be0251870957b89ab593830bce9aa4f8f0ed64' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/ic-nns-init.gz' +sha256 = '85fd0e91e0a4ebe0272ad0491fd603bf6d313d2293a4266892bff397a26ea930' [x86_64-darwin.ic-starter] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/ic-starter.gz' -sha256 = '36fd4a9db0f3291bc7616f9a5900926a808fa3cd563175654744ad697f4bc26d' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/ic-starter.gz' +sha256 = '1f33354049b6c83c8be06344d913a8bcfdb61ba9234706a8bf3cdb3d620723ab' [x86_64-darwin.motoko] -url = 'https://github.com/dfinity/motoko/releases/download/0.9.8/motoko-Darwin-x86_64-0.9.8.tar.gz' -sha256 = '27b75c676d294f8b8b5b287ab27b2419799d9523c4d7fdcdd92d29dbe6b57494' +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] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/replica.gz' -sha256 = '349bb6614b8a4a5135646a0f765af919ae49e4a81f12454ede757a245d065023' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/replica.gz' +sha256 = 'f320fec5733182e1ceb0dd03d19dc5bec01a1bf7763eb282e3fe14b1e1a6e18b' # The replica and canister_sandbox binaries must have the same revision. [x86_64-darwin.canister_sandbox] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/canister_sandbox.gz' -sha256 = 'cfa3f3e476e14fe9f5190a2d6937f0d90f890ac5d816c9bbca18025f81dab819' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/canister_sandbox.gz' +sha256 = '4acdd46cf9b1e5be987f6ce72d0118bf9039162e3ff80cd32056da136f753011' [x86_64-darwin.sandbox_launcher] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/sandbox_launcher.gz' -sha256 = '4005e0c87f29f0aebdaa7c8e1268d3bb938473735f29ba55fa072f149225aaa6' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/sandbox_launcher.gz' +sha256 = 'ed0bc2eeaf282012c8475ddf1ca3369488dc80d385e5b194d2823ae84514ff8a' [x86_64-darwin.sns] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-darwin/sns.gz' -sha256 = '243a3d9f15f16f4efe485d1dff458f1671b169a7298965b54cd643e22c8ca85e' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/sns.gz' +sha256 = '04d06a093913ef59d9d4c7cdc14a0751cff6465384d60204e03d5f396edfb38b' [x86_64-darwin.motoko-base] -url = 'https://github.com/dfinity/motoko/releases/download/0.9.8/motoko-base-library.tar.gz' -sha256 = 'cd8213878fc1663e5c343eeee9f72d10e31e0ea40ae3d1ac24936deb9ca617f4' +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' sha256 = '5c4967764e87d1b2945b1db027422633b48f08cd01d96ba2f622753fcb62c2a4' [x86_64-linux.icx-proxy] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/icx-proxy-dev.gz' -sha256 = '078cae8d1b711b37a9ac45a8501bd14c8099167b885a6b3484323f411c241341' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/icx-proxy-dev.gz' +sha256 = '2bff6952a65e2d94f49ffa5ce03bfbd0eef0fb6ca82a839844c84fd3efa8b280' [x86_64-linux.ic-admin] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/ic-admin.gz' -sha256 = 'f566e216eb8990e6609433f4e436ad8089c12fdd24acb03b7ede6c96a0e10936' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/ic-admin.gz' +sha256 = 'ee6a6d75549bbe355ec4930dd1f6fc1948f973666823d47943adaa2c2bf11902' [x86_64-linux.ic-btc-adapter] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/ic-btc-adapter.gz' -sha256 = 'c6269b3a816538c299d8487f326a3ef3b5a8c638b09c50a1bdf28fbaacc01bcc' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/ic-btc-adapter.gz' +sha256 = 'd31b5adbf91ba4efa910c80d971c08d591dada6b369119f2b1d444d1e58134ea' [x86_64-linux.ic-https-outcalls-adapter] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/ic-https-outcalls-adapter.gz' -sha256 = 'd6d8d511a934b383b91d0cc4f922322a05b0b5fadcfe7a04f1c14739648d72b1' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/ic-https-outcalls-adapter.gz' +sha256 = '276faf4aa298c72709076338671fa356a50133ad7996a75748f0a1eabffbfd61' [x86_64-linux.ic-nns-init] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/ic-nns-init.gz' -sha256 = 'b178bd1d0b40df5eec9620765f96abcf00b2b0fbf2de3bbb02f3615a874c03fe' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/ic-nns-init.gz' +sha256 = 'd58e8efdb8bcd64572bb8dd21a5e9cdb779c06a2c56f3be8ebe7e5709a516897' [x86_64-linux.ic-starter] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/ic-starter.gz' -sha256 = '669daa35328b6539298e577c81ed8515d3e5c5bfe83c3008a9c932fbe058d036' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/ic-starter.gz' +sha256 = '8d8c51033cb2cd20049ca4e048144b895684d7a4fdbd07719476797b53ebafb5' [x86_64-linux.motoko] -url = 'https://github.com/dfinity/motoko/releases/download/0.9.8/motoko-Linux-x86_64-0.9.8.tar.gz' -sha256 = '513c437ed23e6a7b40f840469766e7e5b321162ff0259ef164ce60377064ca87' +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] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/replica.gz' -sha256 = '5b322539661b8f81823bdfba154fa4e35393f72380bf52c0a668d7e6d36d7f69' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/replica.gz' +sha256 = '2cd30cca1818b86785b3d9b808612b7c286252363806c70d196c2fcfa48d1188' # The replica and canister_sandbox binaries must have the same revision. [x86_64-linux.canister_sandbox] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/canister_sandbox.gz' -sha256 = '7b4abcaf499eb025de5f229e3c9c400623b046927bf898dab440eaea81eaea58' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/canister_sandbox.gz' +sha256 = '11849a543a162f0f25b3dc10f17c177ea054e4fdb8a8c86509c7f87988ce2913' [x86_64-linux.sandbox_launcher] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/sandbox_launcher.gz' -sha256 = '7676f38d8326f546f133af42f852bc44fc08e52d45e92a7c315af9c5ff391883' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/sandbox_launcher.gz' +sha256 = '96c416bf98724aa3bf72053d06d559f007f8655261b48f435f9104b605c8f77f' [x86_64-linux.sns] -url = 'https://download.dfinity.systems/ic/91bf38ff3cb927cb94027d9da513cd15f91a5b04/openssl-static-binaries/x86_64-linux/sns.gz' -sha256 = '7e062a6867e675fac1340e5bf8d22b5dcb1c1b34303102c34e16920abf202394' +url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-linux/sns.gz' +sha256 = '966a84f1e563049e09381b39cbcde24b0c77032ee2cfddb40962eecb70925809' [x86_64-linux.motoko-base] -url = 'https://github.com/dfinity/motoko/releases/download/0.9.8/motoko-base-library.tar.gz' -sha256 = 'cd8213878fc1663e5c343eeee9f72d10e31e0ea40ae3d1ac24936deb9ca617f4' +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/actors/icx_proxy.rs b/src/dfx/src/actors/icx_proxy.rs index 74e6aa2ba7..916577767d 100644 --- a/src/dfx/src/actors/icx_proxy.rs +++ b/src/dfx/src/actors/icx_proxy.rs @@ -42,6 +42,9 @@ pub struct IcxProxyConfig { /// run icx-proxy in non-quiet mode pub verbose: bool, + + /// list of domains that can be served (localhost if none specified) + pub domains: Vec, } /// The configuration for the icx_proxy actor. @@ -96,6 +99,7 @@ impl IcxProxy { receiver, fetch_root_key, config.verbose, + config.domains.clone(), ), "Failed to start ICX proxy thread.", )?; @@ -189,6 +193,7 @@ fn icx_proxy_start_thread( receiver: Receiver<()>, fetch_root_key: bool, verbose: bool, + domains: Vec, ) -> DfxResult> { let thread_handler = move || { // Start the process, then wait for the file. @@ -205,6 +210,9 @@ fn icx_proxy_start_thread( let s = format!("{}", url); cmd.args(["--replica", &s]); } + for domain in domains { + cmd.args(["--domain", &domain]); + } if !verbose { cmd.arg("-q"); } 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/call.rs b/src/dfx/src/commands/canister/call.rs index 9f8eb53418..eb034120f6 100644 --- a/src/dfx/src/commands/canister/call.rs +++ b/src/dfx/src/commands/canister/call.rs @@ -94,7 +94,7 @@ struct CallIn { async fn do_wallet_call(wallet: &WalletCanister<'_>, args: &CallIn) -> DfxResult> { // todo change to wallet.call when IDLValue implements ArgumentDecoder let builder = if wallet.version_supports_u128_cycles() { - wallet.update_("wallet_call128").with_arg(args) + wallet.update("wallet_call128").with_arg(args) } else { let CallIn { canister, @@ -108,7 +108,7 @@ async fn do_wallet_call(wallet: &WalletCanister<'_>, args: &CallIn) -> DfxResult args, cycles: cycles as u64, }; - wallet.update_("wallet_call").with_arg(args64) + wallet.update("wallet_call").with_arg(args64) }; let (result,): (Result,) = builder .build() @@ -263,9 +263,7 @@ pub async fn exec( // Get the argument, get the type, convert the argument to the type and return // an error if any of it doesn't work. let arg_value = blob_from_arguments(arguments, opts.random.as_deref(), arg_type, &method_type)?; - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); fetch_root_key_if_needed(env).await?; diff --git a/src/dfx/src/commands/canister/create.rs b/src/dfx/src/commands/canister/create.rs index ee152f6aac..7793120e69 100644 --- a/src/dfx/src/commands/canister/create.rs +++ b/src/dfx/src/commands/canister/create.rs @@ -2,7 +2,8 @@ use crate::lib::deps::get_pull_canisters_in_config; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; use crate::lib::ic_attributes::{ - get_compute_allocation, get_freezing_threshold, get_memory_allocation, CanisterSettings, + get_compute_allocation, get_freezing_threshold, get_memory_allocation, + get_reserved_cycles_limit, CanisterSettings, }; use crate::lib::identity::wallet::get_or_create_wallet_canister; use crate::lib::operations::canister::create_canister; @@ -10,6 +11,7 @@ use crate::lib::root_key::fetch_root_key_if_needed; use crate::util::clap::parsers::cycle_amount_parser; use crate::util::clap::parsers::{ compute_allocation_parser, freezing_threshold_parser, memory_allocation_parser, + reserved_cycles_limit_parser, }; use anyhow::{bail, Context}; use byte_unit::Byte; @@ -62,6 +64,18 @@ pub struct CanisterCreateOpts { #[arg(long, value_parser = freezing_threshold_parser, hide = true)] freezing_threshold: Option, + /// Specifies the upper limit of the canister's reserved cycles balance. + /// + /// Reserved cycles are cycles that the system sets aside for future use by the canister. + /// If a subnet's storage exceeds 450 GiB, then every time a canister allocates new storage bytes, + /// the system sets aside some amount of cycles from the main balance of the canister. + /// These reserved cycles will be used to cover future payments for the newly allocated bytes. + /// The reserved cycles are not transferable and the amount of reserved cycles depends on how full the subnet is. + /// + /// A setting of 0 means that the canister will trap if it tries to allocate new storage while the subnet's memory usage exceeds 450 GiB. + #[arg(long, value_parser = reserved_cycles_limit_parser, hide = true)] + reserved_cycles_limit: Option, + /// Performs the call with the user Identity as the Sender of messages. /// Bypasses the Wallet canister. #[arg(long)] @@ -160,6 +174,12 @@ pub async fn exec( Some(canister_name), ) .with_context(|| format!("Failed to read freezing threshold of {}.", canister_name))?; + let reserved_cycles_limit = get_reserved_cycles_limit( + opts.reserved_cycles_limit, + Some(config_interface), + Some(canister_name), + ) + .with_context(|| format!("Failed to read reserved cycles limit of {}.", canister_name))?; create_canister( env, canister_name, @@ -171,6 +191,7 @@ pub async fn exec( compute_allocation, memory_allocation, freezing_threshold, + reserved_cycles_limit, }, ) .await?; @@ -219,6 +240,14 @@ pub async fn exec( .with_context(|| { format!("Failed to read freezing threshold of {}.", canister_name) })?; + let reserved_cycles_limit = get_reserved_cycles_limit( + opts.reserved_cycles_limit, + Some(config_interface), + Some(canister_name), + ) + .with_context(|| { + format!("Failed to read reserved cycles limit of {}.", canister_name) + })?; create_canister( env, canister_name, @@ -230,6 +259,7 @@ pub async fn exec( compute_allocation, memory_allocation, freezing_threshold, + reserved_cycles_limit, }, ) .await?; diff --git a/src/dfx/src/commands/canister/delete.rs b/src/dfx/src/commands/canister/delete.rs index 1f4e5eff29..db20159dab 100644 --- a/src/dfx/src/commands/canister/delete.rs +++ b/src/dfx/src/commands/canister/delete.rs @@ -10,7 +10,7 @@ use crate::lib::operations::canister::{ use crate::lib::root_key::fetch_root_key_if_needed; use crate::util::assets::wallet_wasm; use crate::util::blob_from_arguments; -use anyhow::{anyhow, Context}; +use anyhow::Context; use candid::Principal; use clap::Parser; use dfx_core::canister::build_wallet_canister; @@ -19,7 +19,7 @@ use dfx_core::identity::CallSender; use fn_error_context::context; use ic_utils::call::AsyncCall; use ic_utils::interfaces::management_canister::attributes::{ - ComputeAllocation, FreezingThreshold, MemoryAllocation, + ComputeAllocation, FreezingThreshold, MemoryAllocation, ReservedCyclesLimit, }; use ic_utils::interfaces::management_canister::builders::InstallMode; use ic_utils::interfaces::management_canister::CanisterStatus; @@ -36,6 +36,7 @@ const DANK_PRINCIPAL: Principal = // "Couldn't send message" when deleting a canister: increase WITHDRAWAL_COST const WITHDRAWAL_COST: u128 = 10_606_030_000; // 5% higher than a value observed ok locally const MAX_MEMORY_ALLOCATION: u64 = 8589934592; +const DEFAULT_RESERVED_CYCLES_LIMIT: u128 = 5_000_000_000_000; /// Deletes a currently stopped canister. #[derive(Parser)] @@ -90,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(); @@ -148,9 +154,7 @@ async fn delete_canister( "Canister {canister} has not been stopped. Delete anyway?" ))?; } - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); let mgr = ManagementCanister::create(agent); let canister_id = Principal::from_text(canister).or_else(|_| canister_id_store.get(canister))?; @@ -161,6 +165,9 @@ async fn delete_canister( compute_allocation: Some(ComputeAllocation::try_from(0u8).unwrap()), memory_allocation: Some(MemoryAllocation::try_from(MAX_MEMORY_ALLOCATION).unwrap()), freezing_threshold: Some(FreezingThreshold::try_from(0u8).unwrap()), + reserved_cycles_limit: Some( + ReservedCyclesLimit::try_from(DEFAULT_RESERVED_CYCLES_LIMIT).unwrap(), + ), }; info!(log, "Setting the controller to identity principal."); update_settings(env, canister_id, settings, call_sender).await?; @@ -266,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/info.rs b/src/dfx/src/commands/canister/info.rs index 8139698cec..3e352fe71f 100644 --- a/src/dfx/src/commands/canister/info.rs +++ b/src/dfx/src/commands/canister/info.rs @@ -17,9 +17,7 @@ pub struct InfoOpts { } pub async fn exec(env: &dyn Environment, opts: InfoOpts) -> DfxResult { - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); let callee_canister = opts.canister.as_str(); let canister_id_store = env.get_canister_id_store()?; diff --git a/src/dfx/src/commands/canister/install.rs b/src/dfx/src/commands/canister/install.rs index 2985cbb347..4a00c18d48 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) { @@ -188,7 +203,9 @@ pub async fn exec( Principal::from_text(canister).or_else(|_| canister_id_store.get(canister))?; let canister_info = CanisterInfo::load(&config, canister, Some(canister_id))?; - let install_args = || Ok(vec![]); + let idl_path = canister_info.get_constructor_idl_path(); + let init_type = get_candid_init_type(&idl_path); + let install_args = || blob_from_arguments(None, None, None, &init_type); install_canister( env, diff --git a/src/dfx/src/commands/canister/metadata.rs b/src/dfx/src/commands/canister/metadata.rs index 86f9fbcb4e..2c4ea1337a 100644 --- a/src/dfx/src/commands/canister/metadata.rs +++ b/src/dfx/src/commands/canister/metadata.rs @@ -1,7 +1,7 @@ use crate::lib::error::DfxResult; use crate::lib::root_key::fetch_root_key_if_needed; use crate::Environment; -use anyhow::{anyhow, Context}; +use anyhow::Context; use candid::Principal; use clap::Parser; use std::io::{stdout, Write}; @@ -17,9 +17,7 @@ pub struct CanisterMetadataOpts { } pub async fn exec(env: &dyn Environment, opts: CanisterMetadataOpts) -> DfxResult { - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); let callee_canister = opts.canister_name.as_str(); let canister_id_store = env.get_canister_id_store()?; diff --git a/src/dfx/src/commands/canister/request_status.rs b/src/dfx/src/commands/canister/request_status.rs index ba20dcccc6..12dcd352a8 100644 --- a/src/dfx/src/commands/canister/request_status.rs +++ b/src/dfx/src/commands/canister/request_status.rs @@ -3,7 +3,7 @@ use crate::lib::error::{DfxError, DfxResult}; use crate::lib::root_key::fetch_root_key_if_needed; use crate::util::clap::parsers; use crate::util::print_idl_blob; -use anyhow::{anyhow, Context}; +use anyhow::Context; use backoff::backoff::Backoff; use backoff::ExponentialBackoff; use candid::Principal; @@ -36,9 +36,7 @@ pub struct RequestStatusOpts { pub async fn exec(env: &dyn Environment, opts: RequestStatusOpts) -> DfxResult { let request_id = RequestId::from_str(&opts.request_id[2..]).context("Invalid argument: request_id")?; - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); fetch_root_key_if_needed(env).await?; 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/canister/sign.rs b/src/dfx/src/commands/canister/sign.rs index d8c317ca84..69515733de 100644 --- a/src/dfx/src/commands/canister/sign.rs +++ b/src/dfx/src/commands/canister/sign.rs @@ -125,9 +125,7 @@ pub async fn exec( // Get the argument, get the type, convert the argument to the type and return // an error if any of it doesn't work. let arg_value = blob_from_arguments(arguments, opts.random.as_deref(), arg_type, &method_type)?; - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); let network = env .get_network_descriptor() diff --git a/src/dfx/src/commands/canister/status.rs b/src/dfx/src/commands/canister/status.rs index 0d08ac04c9..bfa2a4787d 100644 --- a/src/dfx/src/commands/canister/status.rs +++ b/src/dfx/src/commands/canister/status.rs @@ -41,7 +41,13 @@ async fn canister_status( .collect(); controllers.sort(); - info!(log, "Canister status call result for {}.\nStatus: {}\nControllers: {}\nMemory allocation: {}\nCompute allocation: {}\nFreezing threshold: {}\nMemory Size: {:?}\nBalance: {} Cycles\nModule hash: {}", + let reserved_cycles_limit = if let Some(limit) = status.settings.reserved_cycles_limit { + format!("{} Cycles", limit) + } else { + "Not Set".to_string() + }; + + info!(log, "Canister status call result for {}.\nStatus: {}\nControllers: {}\nMemory allocation: {}\nCompute allocation: {}\nFreezing threshold: {}\nMemory Size: {:?}\nBalance: {} Cycles\nReserved: {} Cycles\nReserved Cycles Limit: {}\nModule hash: {}", canister, status.status, controllers.join(" "), @@ -50,6 +56,8 @@ async fn canister_status( status.settings.freezing_threshold, status.memory_size, status.cycles, + status.reserved_cycles, + reserved_cycles_limit, status.module_hash.map_or_else(|| "None".to_string(), |v| format!("0x{}", hex::encode(v))) ); Ok(()) diff --git a/src/dfx/src/commands/canister/update_settings.rs b/src/dfx/src/commands/canister/update_settings.rs index b19f846991..b06fae6ae9 100644 --- a/src/dfx/src/commands/canister/update_settings.rs +++ b/src/dfx/src/commands/canister/update_settings.rs @@ -2,12 +2,14 @@ use crate::lib::diagnosis::DiagnosedError; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; use crate::lib::ic_attributes::{ - get_compute_allocation, get_freezing_threshold, get_memory_allocation, CanisterSettings, + get_compute_allocation, get_freezing_threshold, get_memory_allocation, + get_reserved_cycles_limit, CanisterSettings, }; use crate::lib::operations::canister::{get_canister_status, update_settings}; use crate::lib::root_key::fetch_root_key_if_needed; use crate::util::clap::parsers::{ compute_allocation_parser, freezing_threshold_parser, memory_allocation_parser, + reserved_cycles_limit_parser, }; use anyhow::{bail, Context}; use byte_unit::Byte; @@ -62,6 +64,18 @@ pub struct UpdateSettingsOpts { #[arg(long, value_parser = freezing_threshold_parser)] freezing_threshold: Option, + /// Sets the upper limit of the canister's reserved cycles balance. + /// + /// Reserved cycles are cycles that the system sets aside for future use by the canister. + /// If a subnet's storage exceeds 450 GiB, then every time a canister allocates new storage bytes, + /// the system sets aside some amount of cycles from the main balance of the canister. + /// These reserved cycles will be used to cover future payments for the newly allocated bytes. + /// The reserved cycles are not transferable and the amount of reserved cycles depends on how full the subnet is. + /// + /// A setting of 0 means that the canister will trap if it tries to allocate new storage while the subnet's memory usage exceeds 450 GiB. + #[arg(long, value_parser = reserved_cycles_limit_parser)] + reserved_cycles_limit: Option, + /// Freezing thresholds above ~1.5 years require this flag as confirmation. #[arg(long)] confirm_very_long_freezing_threshold: bool, @@ -122,6 +136,8 @@ pub async fn exec( get_memory_allocation(opts.memory_allocation, config_interface, canister_name)?; let freezing_threshold = get_freezing_threshold(opts.freezing_threshold, config_interface, canister_name)?; + let reserved_cycles_limit = + get_reserved_cycles_limit(opts.reserved_cycles_limit, config_interface, canister_name)?; if let Some(added) = &opts.add_controller { let status = get_canister_status(env, canister_id, call_sender).await?; let mut existing_controllers = status.settings.controllers; @@ -153,6 +169,7 @@ pub async fn exec( compute_allocation, memory_allocation, freezing_threshold, + reserved_cycles_limit, }; update_settings(env, canister_id, settings, call_sender).await?; display_controller_update(&opts, canister_name_or_id); @@ -188,6 +205,14 @@ pub async fn exec( .with_context(|| { format!("Failed to get freezing threshold for {}.", canister_name) })?; + let reserved_cycles_limit = get_reserved_cycles_limit( + opts.reserved_cycles_limit, + Some(config_interface), + Some(canister_name), + ) + .with_context(|| { + format!("Failed to get reserved cycles limit for {}.", canister_name) + })?; if let Some(added) = &opts.add_controller { let status = get_canister_status(env, canister_id, call_sender).await?; let mut existing_controllers = status.settings.controllers; @@ -219,6 +244,7 @@ pub async fn exec( compute_allocation, memory_allocation, freezing_threshold, + reserved_cycles_limit, }; update_settings(env, canister_id, settings, call_sender).await?; display_controller_update(&opts, canister_name); diff --git a/src/dfx/src/commands/cycles/balance.rs b/src/dfx/src/commands/cycles/balance.rs new file mode 100644 index 0000000000..bfddfd64b7 --- /dev/null +++ b/src/dfx/src/commands/cycles/balance.rs @@ -0,0 +1,57 @@ +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; + +/// Get the cycle balance of the selected Identity's cycles wallet. +#[derive(Parser)] +pub struct CyclesBalanceOpts { + /// Specifies a Principal to get the balance of + #[arg(long)] + owner: Option, + + /// Subaccount of the selected identity to get the balance of + #[arg(long)] + subaccount: Option, + + /// Get balance raw value (without upscaling to trillions of cycles). + #[arg(long)] + precise: bool, + + /// Canister ID of the cycles ledger canister. + /// If not specified, the default cycles ledger canister ID will be used. + // todo: remove this. See https://dfinity.atlassian.net/browse/SDK-1262 + #[arg(long)] + cycles_ledger_canister_id: Principal, +} + +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(|| { + env.get_selected_identity_principal() + .expect("Selected identity not instantiated.") + }); + + let subaccount = opts.subaccount.map(|x| x.0); + + let balance = + cycles_ledger::balance(agent, owner, subaccount, opts.cycles_ledger_canister_id).await?; + + if opts.precise { + println!("{} cycles.", balance); + } else { + println!( + "{} TC (trillion cycles).", + pretty_thousand_separators(format_as_trillions(balance)) + ); + } + + Ok(()) +} diff --git a/src/dfx/src/commands/cycles/mod.rs b/src/dfx/src/commands/cycles/mod.rs new file mode 100644 index 0000000000..8e1b14228a --- /dev/null +++ b/src/dfx/src/commands/cycles/mod.rs @@ -0,0 +1,40 @@ +use crate::lib::agent::create_agent_environment; +use crate::lib::environment::Environment; +use crate::lib::error::DfxResult; +use crate::lib::network::network_opt::NetworkOpt; +use clap::Parser; +use tokio::runtime::Runtime; + +mod balance; +pub mod top_up; +mod transfer; + +/// Helper commands to manage the user's cycles. +#[derive(Parser)] +#[command(name = "wallet")] +pub struct CyclesOpts { + #[command(flatten)] + network: NetworkOpt, + + #[command(subcommand)] + subcmd: SubCommand, +} + +#[derive(Parser)] +enum SubCommand { + Balance(balance::CyclesBalanceOpts), + TopUp(top_up::TopUpOpts), + Transfer(transfer::TransferOpts), +} + +pub fn exec(env: &dyn Environment, opts: CyclesOpts) -> DfxResult { + let agent_env = create_agent_environment(env, opts.network.to_network_name())?; + let runtime = Runtime::new().expect("Unable to create a runtime"); + runtime.block_on(async { + match opts.subcmd { + SubCommand::Balance(v) => balance::exec(&agent_env, v).await, + SubCommand::TopUp(v) => top_up::exec(&agent_env, v).await, + SubCommand::Transfer(v) => transfer::exec(&agent_env, v).await, + } + }) +} diff --git a/src/dfx/src/commands/cycles/top_up.rs b/src/dfx/src/commands/cycles/top_up.rs new file mode 100644 index 0000000000..70e49bcc4f --- /dev/null +++ b/src/dfx/src/commands/cycles/top_up.rs @@ -0,0 +1,83 @@ +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::clap::parsers::cycle_amount_parser; +use candid::Principal; +use clap::Parser; +use slog::warn; +use std::time::{SystemTime, UNIX_EPOCH}; + +/// Send cycles to a canister. +#[derive(Parser)] +pub struct TopUpOpts { + /// Send cycles to this canister. + to: String, + + /// The number of cycles to send. + #[arg(value_parser = cycle_amount_parser)] + amount: u128, + + /// Transfer cycles from this subaccount. + #[arg(long)] + from_subaccount: Option, + + /// Transaction timestamp, in nanoseconds, for use in controlling transaction deduplication, default is system time. + /// https://internetcomputer.org/docs/current/developer-docs/integrations/icrc-1/#transaction-deduplication- + #[arg(long)] + created_at_time: Option, + + /// Canister ID of the cycles ledger canister. + /// If not specified, the default cycles ledger canister ID will be used. + // todo: remove this. See https://dfinity.atlassian.net/browse/SDK-1262 + #[arg(long)] + cycles_ledger_canister_id: Principal, +} + +pub async fn exec(env: &dyn Environment, opts: TopUpOpts) -> DfxResult { + let agent = env.get_agent(); + + let amount = opts.amount; + + fetch_root_key_if_needed(env).await?; + + let created_at_time = opts.created_at_time.unwrap_or( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_nanos() as u64, + ); + + let to = get_canister_id(env, &opts.to)?; + let from_subaccount = opts.from_subaccount.map(|x| x.0); + let result = cycles_ledger::send( + agent, + env.get_logger(), + to, + amount, + created_at_time, + from_subaccount, + opts.cycles_ledger_canister_id, + ) + .await; + if result.is_err() && opts.created_at_time.is_none() { + warn!( + env.get_logger(), + "If you retry this operation, use --created-at-time {}", created_at_time + ); + } + let block_index = result?; + + println!("Transfer sent at block index {block_index}"); + + Ok(()) +} + +fn get_canister_id(env: &dyn Environment, s: &str) -> DfxResult { + let principal = Principal::from_text(s).or_else(|_| { + env.get_canister_id_store() + .and_then(|canister_id_store| canister_id_store.get(s)) + })?; + Ok(principal) +} diff --git a/src/dfx/src/commands/cycles/transfer.rs b/src/dfx/src/commands/cycles/transfer.rs new file mode 100644 index 0000000000..97c1cf9d01 --- /dev/null +++ b/src/dfx/src/commands/cycles/transfer.rs @@ -0,0 +1,85 @@ +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::clap::parsers::cycle_amount_parser; +use candid::Principal; +use clap::Parser; +use slog::warn; +use std::time::{SystemTime, UNIX_EPOCH}; + +/// Transfer cycles to another principal. +#[derive(Parser)] +pub struct TransferOpts { + /// Transfer cycles to this principal. + to: Principal, + + /// The number of cycles to send. + #[arg(value_parser = cycle_amount_parser)] + amount: u128, + + /// Transfer cycles from this subaccount. + #[arg(long)] + from_subaccount: Option, + + /// Transfer cycles to this subaccount. + #[arg(long)] + to_subaccount: Option, + + /// Transaction timestamp, in nanoseconds, for use in controlling transaction-deduplication, default is system-time. + /// https://internetcomputer.org/docs/current/developer-docs/integrations/icrc-1/#transaction-deduplication- + #[arg(long)] + created_at_time: Option, + + /// Memo. + #[arg(long)] + memo: Option, + + /// Canister ID of the cycles ledger canister. + /// If not specified, the default cycles ledger canister ID will be used. + // todo: remove this. See https://dfinity.atlassian.net/browse/SDK-1262 + #[arg(long)] + cycles_ledger_canister_id: Principal, +} + +pub async fn exec(env: &dyn Environment, opts: TransferOpts) -> DfxResult { + let agent = env.get_agent(); + + let amount = opts.amount; + + fetch_root_key_if_needed(env).await?; + + let created_at_time = opts.created_at_time.unwrap_or( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_nanos() as u64, + ); + + let from_subaccount = opts.from_subaccount.map(|x| x.0); + let to_subaccount = opts.to_subaccount.map(|x| x.0); + let result = cycles_ledger::transfer( + agent, + env.get_logger(), + amount, + from_subaccount, + opts.to, + to_subaccount, + created_at_time, + opts.memo, + opts.cycles_ledger_canister_id, + ) + .await; + if result.is_err() && opts.created_at_time.is_none() { + warn!( + env.get_logger(), + "If you retry this operation, use --created-at-time {}", created_at_time + ); + } + let block_index = result?; + + println!("Transfer sent at block index {block_index}"); + + Ok(()) +} 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/deps/deploy.rs b/src/dfx/src/commands/deps/deploy.rs index 9aef0e7328..d4685f0f3a 100644 --- a/src/dfx/src/commands/deps/deploy.rs +++ b/src/dfx/src/commands/deps/deploy.rs @@ -7,7 +7,7 @@ use crate::lib::deps::{ use crate::lib::environment::Environment; use crate::lib::error::DfxResult; use crate::lib::root_key::fetch_root_key_if_needed; -use anyhow::anyhow; + use candid::Principal; use clap::Parser; use fn_error_context::context; @@ -38,9 +38,7 @@ pub async fn exec(env: &dyn Environment, opts: DepsDeployOpts) -> DfxResult { let init_json = load_init_json(&project_root)?; fetch_root_key_if_needed(env).await?; - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); let canister_ids = match &opts.canister { Some(canister) => { diff --git a/src/dfx/src/commands/deps/pull.rs b/src/dfx/src/commands/deps/pull.rs index 8edeaa7e71..1f53471207 100644 --- a/src/dfx/src/commands/deps/pull.rs +++ b/src/dfx/src/commands/deps/pull.rs @@ -53,9 +53,7 @@ pub async fn exec(env: &dyn Environment, opts: DepsPullOpts) -> DfxResult { fetch_root_key_if_needed(&env).await?; - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); let all_dependencies = resolve_all_dependencies(agent, logger, &pull_canisters_in_config).await?; diff --git a/src/dfx/src/commands/extension/install.rs b/src/dfx/src/commands/extension/install.rs index db2abd9c95..58e6b472d7 100644 --- a/src/dfx/src/commands/extension/install.rs +++ b/src/dfx/src/commands/extension/install.rs @@ -1,9 +1,11 @@ use crate::commands::DfxCommand; +use crate::config::cache::DiskBasedCache; use crate::lib::environment::Environment; use crate::lib::error::DfxResult; use clap::Parser; use clap::Subcommand; use dfx_core::error::extension::ExtensionError; +use semver::Version; #[derive(Parser)] pub struct InstallOpts { @@ -12,9 +14,15 @@ pub struct InstallOpts { /// Installs the extension under different name. Useful when installing an extension with the same name as: already installed extension, or a built-in command. #[clap(long)] install_as: Option, + /// Installs a specific version of the extension, bypassing version checks + #[clap(long)] + version: Option, } 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()); @@ -22,7 +30,11 @@ pub fn exec(env: &dyn Environment, opts: InstallOpts) -> DfxResult<()> { return Err(ExtensionError::CommandAlreadyExists(opts.name).into()); } - mgr.install_extension(&opts.name, opts.install_as.as_deref())?; + mgr.install_extension( + &opts.name, + opts.install_as.as_deref(), + opts.version.as_ref(), + )?; spinner.finish_with_message( format!( "Extension '{}' installed successfully{}", diff --git a/src/dfx/src/commands/identity/set_wallet.rs b/src/dfx/src/commands/identity/set_wallet.rs index 1b3fe3cfbe..74cd6b58a7 100644 --- a/src/dfx/src/commands/identity/set_wallet.rs +++ b/src/dfx/src/commands/identity/set_wallet.rs @@ -57,9 +57,7 @@ pub fn exec(env: &dyn Environment, opts: SetWalletOpts, network: NetworkOpt) -> "Skipping verification of availability of the canister on the network due to --force..." ); } else { - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); runtime .block_on(async { diff --git a/src/dfx/src/commands/ledger/balance.rs b/src/dfx/src/commands/ledger/balance.rs index 5ee77a5922..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."); @@ -34,9 +36,7 @@ pub async fn exec(env: &dyn Environment, opts: BalanceOpts) -> DfxResult { |v| AccountIdentifier::from_str(&v), ) .map_err(|err| anyhow!(err))?; - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); let balance = ledger::balance(agent, &acc_id, opts.ledger_canister_id).await?; diff --git a/src/dfx/src/commands/ledger/create_canister.rs b/src/dfx/src/commands/ledger/create_canister.rs index 8d0fc6606d..0f1bd2fdec 100644 --- a/src/dfx/src/commands/ledger/create_canister.rs +++ b/src/dfx/src/commands/ledger/create_canister.rs @@ -9,7 +9,7 @@ use crate::lib::nns_types::icpts::{ICPTs, TRANSACTION_FEE}; use crate::lib::operations::cmc::{notify_create, transfer_cmc}; use crate::lib::root_key::fetch_root_key_if_needed; use crate::util::clap::parsers::e8s_parser; -use anyhow::{anyhow, bail, Context}; +use anyhow::{bail, Context}; use candid::Principal; use clap::Parser; @@ -71,14 +71,13 @@ pub async fn exec(env: &dyn Environment, opts: CreateCanisterOpts) -> DfxResult ) })?; - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); fetch_root_key_if_needed(env).await?; let height = transfer_cmc( agent, + env.get_logger(), memo, amount, fee, diff --git a/src/dfx/src/commands/ledger/notify/create_canister.rs b/src/dfx/src/commands/ledger/notify/create_canister.rs index a588cafa92..a9e2f53e65 100644 --- a/src/dfx/src/commands/ledger/notify/create_canister.rs +++ b/src/dfx/src/commands/ledger/notify/create_canister.rs @@ -3,7 +3,7 @@ use crate::lib::ledger_types::NotifyError::Refunded; use crate::lib::operations::cmc::notify_create; use crate::lib::root_key::fetch_root_key_if_needed; use crate::lib::{environment::Environment, error::DfxResult}; -use anyhow::{anyhow, bail}; +use anyhow::bail; use candid::Principal; use clap::Parser; @@ -27,9 +27,7 @@ pub async fn exec(env: &dyn Environment, opts: NotifyCreateOpts) -> DfxResult { let block_height = opts.block_height; let controller = opts.controller; - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); fetch_root_key_if_needed(env).await?; diff --git a/src/dfx/src/commands/ledger/notify/top_up.rs b/src/dfx/src/commands/ledger/notify/top_up.rs index a64578c29a..ae7885a018 100644 --- a/src/dfx/src/commands/ledger/notify/top_up.rs +++ b/src/dfx/src/commands/ledger/notify/top_up.rs @@ -3,7 +3,7 @@ use crate::lib::ledger_types::NotifyError::Refunded; use crate::lib::operations::cmc::notify_top_up; use crate::lib::root_key::fetch_root_key_if_needed; use crate::lib::{environment::Environment, error::DfxResult}; -use anyhow::{anyhow, bail}; +use anyhow::bail; use candid::Principal; use clap::Parser; @@ -21,9 +21,7 @@ pub async fn exec(env: &dyn Environment, opts: NotifyTopUpOpts) -> DfxResult { let block_height = opts.block_height; let canister = opts.canister; - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); fetch_root_key_if_needed(env).await?; diff --git a/src/dfx/src/commands/ledger/show_subnet_types.rs b/src/dfx/src/commands/ledger/show_subnet_types.rs index 30ea9e0850..305f164c85 100644 --- a/src/dfx/src/commands/ledger/show_subnet_types.rs +++ b/src/dfx/src/commands/ledger/show_subnet_types.rs @@ -2,7 +2,7 @@ use crate::lib::environment::Environment; use crate::lib::error::DfxResult; use crate::lib::ledger_types::{GetSubnetTypesToSubnetsResult, MAINNET_CYCLE_MINTER_CANISTER_ID}; use crate::lib::root_key::fetch_root_key_if_needed; -use anyhow::{anyhow, Context}; +use anyhow::Context; use candid::{Decode, Encode, Principal}; use clap::Parser; @@ -17,9 +17,7 @@ pub struct ShowSubnetTypesOpts { } pub async fn exec(env: &dyn Environment, opts: ShowSubnetTypesOpts) -> DfxResult { - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); fetch_root_key_if_needed(env).await?; diff --git a/src/dfx/src/commands/ledger/top_up.rs b/src/dfx/src/commands/ledger/top_up.rs index 414efe946b..2c3defd80a 100644 --- a/src/dfx/src/commands/ledger/top_up.rs +++ b/src/dfx/src/commands/ledger/top_up.rs @@ -8,7 +8,7 @@ use crate::lib::nns_types::icpts::{ICPTs, TRANSACTION_FEE}; use crate::lib::operations::cmc::{notify_top_up, transfer_cmc}; use crate::lib::root_key::fetch_root_key_if_needed; use crate::util::clap::parsers::e8s_parser; -use anyhow::{anyhow, bail, Context}; +use anyhow::{bail, Context}; use candid::Principal; use clap::Parser; @@ -17,7 +17,7 @@ const MEMO_TOP_UP_CANISTER: u64 = 1347768404_u64; /// Top up a canister with cycles minted from ICP #[derive(Parser)] pub struct TopUpOpts { - /// Specify the canister id to top up + /// Specify the canister id or name to top up canister: String, /// Subaccount to withdraw from @@ -58,21 +58,22 @@ pub async fn exec(env: &dyn Environment, opts: TopUpOpts) -> DfxResult { let memo = Memo(MEMO_TOP_UP_CANISTER); - let to = Principal::from_text(&opts.canister).with_context(|| { - format!( - "Failed to parse {:?} as target canister principal.", - &opts.canister - ) - })?; + let to = Principal::from_text(&opts.canister) + .or_else(|_| env.get_canister_id_store()?.get(&opts.canister)) + .with_context(|| { + format!( + "Failed to parse {:?} as target canister principal or name.", + &opts.canister + ) + })?; - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); fetch_root_key_if_needed(env).await?; let height = transfer_cmc( agent, + env.get_logger(), memo, amount, fee, diff --git a/src/dfx/src/commands/ledger/transfer.rs b/src/dfx/src/commands/ledger/transfer.rs index cd1c58925d..256f5df953 100644 --- a/src/dfx/src/commands/ledger/transfer.rs +++ b/src/dfx/src/commands/ledger/transfer.rs @@ -70,9 +70,7 @@ pub async fn exec(env: &dyn Environment, opts: TransferOpts) -> DfxResult { })? .to_address(); - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); fetch_root_key_if_needed(env).await?; @@ -82,6 +80,7 @@ pub async fn exec(env: &dyn Environment, opts: TransferOpts) -> DfxResult { let _block_height = transfer( agent, + env.get_logger(), &canister_id, memo, amount, diff --git a/src/dfx/src/commands/mod.rs b/src/dfx/src/commands/mod.rs index 2a402902d5..139ac8ae6c 100644 --- a/src/dfx/src/commands/mod.rs +++ b/src/dfx/src/commands/mod.rs @@ -7,6 +7,7 @@ mod beta; mod build; mod cache; mod canister; +mod cycles; mod deploy; mod deps; mod diagnose; @@ -35,6 +36,8 @@ pub enum DfxCommand { Build(build::CanisterBuildOpts), Cache(cache::CacheOpts), Canister(canister::CanisterOpts), + #[command(hide = true)] + Cycles(cycles::CyclesOpts), Deploy(deploy::DeployOpts), Deps(deps::DepsOpts), Diagnose(diagnose::DiagnoseOpts), @@ -64,6 +67,7 @@ pub fn exec(env: &dyn Environment, cmd: DfxCommand) -> DfxResult { DfxCommand::Build(v) => build::exec(env, v), DfxCommand::Cache(v) => cache::exec(env, v), DfxCommand::Canister(v) => canister::exec(env, v), + DfxCommand::Cycles(v) => cycles::exec(env, v), DfxCommand::Deploy(v) => deploy::exec(env, v), DfxCommand::Deps(v) => deps::exec(env, v), DfxCommand::Diagnose(v) => diagnose::exec(env, v), diff --git a/src/dfx/src/commands/quickstart.rs b/src/dfx/src/commands/quickstart.rs index 2059cb0713..dce97ef9b8 100644 --- a/src/dfx/src/commands/quickstart.rs +++ b/src/dfx/src/commands/quickstart.rs @@ -31,6 +31,7 @@ use ic_utils::interfaces::{ use indicatif::ProgressBar; use num_traits::Inv; use rust_decimal::Decimal; +use slog::Logger; use tokio::runtime::Runtime; /// Use the `dfx quickstart` command to perform initial one time setup for your identity and/or wallet. This command @@ -45,7 +46,7 @@ pub struct QuickstartOpts; pub fn exec(env: &dyn Environment, _: QuickstartOpts) -> DfxResult { let env = create_agent_environment(env, Some("ic".to_string()))?; - let agent = env.get_agent().expect("Unable to create agent"); + let agent = env.get_agent(); let ident = env.get_selected_identity().unwrap(); let principal = env.get_selected_identity_principal().unwrap(); eprintln!("Your DFX user principal: {principal}"); @@ -151,13 +152,14 @@ async fn step_deploy_wallet( eprintln!("Run this command again at any time to continue from here."); return Ok(()); } - let wallet = step_interact_ledger(agent, ident_principal, rounded).await?; + let wallet = step_interact_ledger(agent, env.get_logger(), ident_principal, rounded).await?; step_finish_wallet(env, agent, wallet, ident).await?; Ok(()) } async fn step_interact_ledger( agent: &Agent, + logger: &Logger, ident_principal: Principal, to_spend: Decimal, ) -> DfxResult { @@ -169,6 +171,7 @@ async fn step_interact_ledger( let icpts = ICPTs::from_decimal(to_spend)?; let height = transfer_cmc( agent, + logger, Memo(MEMO_CREATE_CANISTER /* 👽 */), icpts, TRANSACTION_FEE, diff --git a/src/dfx/src/commands/start.rs b/src/dfx/src/commands/start.rs index 03515f5740..1fdcd36230 100644 --- a/src/dfx/src/commands/start.rs +++ b/src/dfx/src/commands/start.rs @@ -80,6 +80,10 @@ pub struct StartOpts { /// Use old metering. #[arg(long)] use_old_metering: bool, + + /// A list of domains that can be served. These are used for canister resolution [default: localhost] + #[arg(long)] + domain: Vec, } // The frontend webserver is brought up by the bg process; thus, the fg process @@ -146,6 +150,7 @@ pub fn exec( enable_canister_http, artificial_delay, use_old_metering, + domain, }: StartOpts, ) -> DfxResult { if !background { @@ -179,6 +184,7 @@ pub fn exec( bitcoin_node, enable_canister_http, emulator, + domain, )?; let local_server_descriptor = network_descriptor.local_server_descriptor()?; @@ -292,6 +298,8 @@ pub fn exec( .log_level .unwrap_or_default(); + let proxy_domains = local_server_descriptor.proxy.domain.clone().into_vec(); + let replica_config = { let replica_config = ReplicaConfig::new( &state_root, @@ -388,6 +396,7 @@ pub fn exec( bind: address_and_port, replica_urls: vec![], // will be determined after replica starts fetch_root_key: !network_descriptor.is_ic, + domains: proxy_domains, verbose: env.get_verbose_level() > 0, }; @@ -453,6 +462,7 @@ pub fn apply_command_line_parameters( bitcoin_nodes: Vec, enable_canister_http: bool, emulator: bool, + domain: Vec, ) -> DfxResult { if enable_canister_http { warn!( @@ -492,6 +502,10 @@ pub fn apply_command_line_parameters( local_server_descriptor = local_server_descriptor.with_bitcoin_nodes(bitcoin_nodes) } + if !domain.is_empty() { + local_server_descriptor = local_server_descriptor.with_proxy_domains(domain) + } + Ok(NetworkDescriptor { local_server_descriptor: Some(local_server_descriptor), ..network_descriptor diff --git a/src/dfx/src/commands/wallet/mod.rs b/src/dfx/src/commands/wallet/mod.rs index 0eb1a95564..bbc2538f4f 100644 --- a/src/dfx/src/commands/wallet/mod.rs +++ b/src/dfx/src/commands/wallet/mod.rs @@ -92,7 +92,7 @@ where let wallet = get_or_create_wallet_canister(env, network, &identity_name).await?; let out: O = wallet - .query_(method) + .query(method) .with_arg(arg) .build() .call() @@ -109,7 +109,7 @@ where { let wallet = get_wallet(env).await?; let out: O = wallet - .update_(method) + .update(method) .with_arg(arg) .build() .call_and_wait() diff --git a/src/dfx/src/commands/wallet/redeem_faucet_coupon.rs b/src/dfx/src/commands/wallet/redeem_faucet_coupon.rs index 45c790ae6a..93568c4f0c 100644 --- a/src/dfx/src/commands/wallet/redeem_faucet_coupon.rs +++ b/src/dfx/src/commands/wallet/redeem_faucet_coupon.rs @@ -33,9 +33,7 @@ pub async fn exec(env: &dyn Environment, opts: RedeemFaucetCouponOpts) -> DfxRes } else { Principal::from_text(DEFAULT_FAUCET_PRINCIPAL).unwrap() }; - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); if fetch_root_key_if_needed(env).await.is_err() { bail!("Failed to connect to the local replica. Did you forget to use '--network ic'?"); } else if !env.get_network_descriptor().is_ic { diff --git a/src/dfx/src/commands/wallet/upgrade.rs b/src/dfx/src/commands/wallet/upgrade.rs index 4828f0bc10..a0d36b3076 100644 --- a/src/dfx/src/commands/wallet/upgrade.rs +++ b/src/dfx/src/commands/wallet/upgrade.rs @@ -4,7 +4,7 @@ use crate::lib::identity::wallet::wallet_canister_id; use crate::lib::operations::canister::install_canister::install_wallet; use crate::lib::root_key::fetch_root_key_if_needed; use crate::lib::state_tree::canister_info::read_state_tree_canister_module_hash; -use anyhow::{anyhow, bail}; +use anyhow::bail; use clap::Parser; use ic_utils::interfaces::management_canister::builders::InstallMode; @@ -31,9 +31,7 @@ pub async fn exec(env: &dyn Environment, _opts: UpgradeOpts) -> DfxResult { ); }; - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); fetch_root_key_if_needed(env).await?; if read_state_tree_canister_module_hash(agent, canister_id) @@ -43,9 +41,7 @@ pub async fn exec(env: &dyn Environment, _opts: UpgradeOpts) -> DfxResult { bail!("The cycles wallet canister is empty. Try running `dfx identity deploy-wallet` to install code for the cycles wallet in this canister.") } - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); install_wallet(env, agent, canister_id, InstallMode::Upgrade).await?; diff --git a/src/dfx/src/lib/builders/mod.rs b/src/dfx/src/lib/builders/mod.rs index d689b2d6db..231192b513 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/builders/motoko.rs b/src/dfx/src/lib/builders/motoko.rs index 0f2fcb8219..3b3f526d38 100644 --- a/src/dfx/src/lib/builders/motoko.rs +++ b/src/dfx/src/lib/builders/motoko.rs @@ -8,6 +8,7 @@ use crate::lib::error::{BuildError, DfxError, DfxResult}; use crate::lib::metadata::names::{CANDID_ARGS, CANDID_SERVICE}; use crate::lib::models::canister::CanisterPool; use crate::lib::package_arguments::{self, PackageArguments}; +use crate::util::assets::management_idl; use anyhow::Context; use candid::Principal as CanisterId; use dfx_core::config::cache::Cache; @@ -38,6 +39,48 @@ impl MotokoBuilder { } } +#[context("Failed to find imports for canister at '{}'.", info.get_main_path().display())] +fn get_imports(cache: &dyn Cache, info: &MotokoCanisterInfo) -> DfxResult> { + #[context("Failed recursive dependency detection at {}.", file.display())] + fn get_imports_recursive( + cache: &dyn Cache, + file: &Path, + result: &mut BTreeSet, + ) -> DfxResult { + if result.contains(&MotokoImport::Relative(file.to_path_buf())) { + return Ok(()); + } + + result.insert(MotokoImport::Relative(file.to_path_buf())); + + let mut command = cache.get_binary_command("moc")?; + let command = command.arg("--print-deps").arg(file); + let output = command + .output() + .with_context(|| format!("Error executing {:#?}", command))?; + let output = String::from_utf8_lossy(&output.stdout); + + for line in output.lines() { + let import = MotokoImport::try_from(line).context("Failed to create MotokoImport.")?; + match import { + MotokoImport::Relative(path) => { + get_imports_recursive(cache, path.as_path(), result)?; + } + _ => { + result.insert(import); + } + } + } + + Ok(()) + } + + let mut result = BTreeSet::new(); + get_imports_recursive(cache, info.get_main_path(), &mut result)?; + + Ok(result) +} + impl CanisterBuilder for MotokoBuilder { #[context("Failed to get dependencies for canister '{}'.", info.get_name())] fn get_dependencies( @@ -45,52 +88,10 @@ impl CanisterBuilder for MotokoBuilder { pool: &CanisterPool, info: &CanisterInfo, ) -> DfxResult> { - let mut result = BTreeSet::new(); let motoko_info = info.as_info::()?; + let imports = get_imports(self.cache.as_ref(), &motoko_info)?; - #[context("Failed recursive dependency detection at {}.", file.to_string_lossy())] - fn find_deps_recursive( - cache: &dyn Cache, - file: &Path, - result: &mut BTreeSet, - ) -> DfxResult { - if result.contains(&MotokoImport::Relative(file.to_path_buf())) { - return Ok(()); - } - - result.insert(MotokoImport::Relative(file.to_path_buf())); - - let mut command = cache.get_binary_command("moc")?; - let command = command.arg("--print-deps").arg(file); - let output = command - .output() - .with_context(|| format!("Error executing {:#?}", command))?; - - let output = String::from_utf8_lossy(&output.stdout); - for line in output.lines() { - let import = - MotokoImport::try_from(line).context("Failed to create MotokoImport.")?; - match import { - MotokoImport::Canister(_) => { - result.insert(import); - } - MotokoImport::Relative(path) => { - find_deps_recursive(cache, path.as_path(), result)?; - } - MotokoImport::Lib(_) => (), - MotokoImport::Ic(_) => (), - } - } - - Ok(()) - } - find_deps_recursive( - self.cache.as_ref(), - motoko_info.get_main_path(), - &mut result, - )?; - - Ok(result + Ok(imports .iter() .filter_map(|import| { if let MotokoImport::Canister(name) = import { @@ -132,6 +133,14 @@ impl CanisterBuilder for MotokoBuilder { std::fs::create_dir_all(idl_dir_path) .with_context(|| format!("Failed to create {}.", idl_dir_path.to_string_lossy()))?; + // If the management canister is being imported, emit the candid file. + if get_imports(cache.as_ref(), &motoko_info)? + .contains(&MotokoImport::Ic("aaaaa-aa".to_string())) + { + let management_idl_path = idl_dir_path.join("aaaaa-aa.did"); + dfx_core::fs::write(management_idl_path, management_idl()?)?; + } + let package_arguments = package_arguments::load(cache.as_ref(), motoko_info.get_packtool())?; diff --git a/src/dfx/src/lib/cycles_ledger_types/mod.rs b/src/dfx/src/lib/cycles_ledger_types/mod.rs new file mode 100644 index 0000000000..5c9ff69435 --- /dev/null +++ b/src/dfx/src/lib/cycles_ledger_types/mod.rs @@ -0,0 +1 @@ +pub mod send; diff --git a/src/dfx/src/lib/cycles_ledger_types/send.rs b/src/dfx/src/lib/cycles_ledger_types/send.rs new file mode 100644 index 0000000000..20b51228f0 --- /dev/null +++ b/src/dfx/src/lib/cycles_ledger_types/send.rs @@ -0,0 +1,48 @@ +// Copied from https://github.com/dfinity/cycles-ledger/blob/main/cycles-ledger/src/endpoints.rs +use candid::{CandidType, Nat, Principal}; +use ic_cdk::api::call::RejectionCode; +use icrc_ledger_types::icrc1::account::Subaccount; +use icrc_ledger_types::icrc1::transfer::BlockIndex; +use serde::Deserialize; + +pub type NumCycles = Nat; + +#[derive(CandidType, Deserialize, Clone, Debug, PartialEq, Eq)] +pub struct SendArgs { + #[serde(default)] + pub from_subaccount: Option, + pub to: Principal, + #[serde(default)] + pub created_at_time: Option, + pub amount: NumCycles, +} + +#[derive(CandidType, Deserialize, Clone, Debug, PartialEq, Eq)] +pub enum SendError { + BadFee { + expected_fee: NumCycles, + }, + InsufficientFunds { + balance: NumCycles, + }, + TooOld, + CreatedInFuture { + ledger_time: u64, + }, + TemporarilyUnavailable, + Duplicate { + duplicate_of: BlockIndex, + }, + FailedToSend { + fee_block: Option, + rejection_code: RejectionCode, + rejection_reason: String, + }, + GenericError { + error_code: Nat, + message: String, + }, + InvalidReceiver { + receiver: Principal, + }, +} diff --git a/src/dfx/src/lib/environment.rs b/src/dfx/src/lib/environment.rs index 917cdd30fd..e77b2ab090 100644 --- a/src/dfx/src/lib/environment.rs +++ b/src/dfx/src/lib/environment.rs @@ -43,7 +43,7 @@ pub trait Environment { // Explicit lifetimes are actually needed for mockall to work properly. #[allow(clippy::needless_lifetimes)] - fn get_agent<'a>(&'a self) -> Option<&'a Agent>; + fn get_agent<'a>(&'a self) -> &'a Agent; #[allow(clippy::needless_lifetimes)] fn get_network_descriptor<'a>(&'a self) -> &'a NetworkDescriptor; @@ -210,10 +210,8 @@ impl Environment for EnvironmentImpl { &self.identity_override } - fn get_agent(&self) -> Option<&Agent> { - // create an AgentEnvironment explicitly, in order to specify network and agent. - // See install, build for examples. - None + fn get_agent(&self) -> &Agent { + unreachable!("Agent only available from an AgentEnvironment"); } fn get_network_descriptor(&self) -> &NetworkDescriptor { @@ -337,8 +335,8 @@ impl<'a> Environment for AgentEnvironment<'a> { self.backend.get_identity_override() } - fn get_agent(&self) -> Option<&Agent> { - Some(&self.agent) + fn get_agent(&self) -> &Agent { + &self.agent } fn get_network_descriptor(&self) -> &NetworkDescriptor { @@ -385,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/ic_attributes/mod.rs b/src/dfx/src/lib/ic_attributes/mod.rs index 77e0cea05f..09d495338e 100644 --- a/src/dfx/src/lib/ic_attributes/mod.rs +++ b/src/dfx/src/lib/ic_attributes/mod.rs @@ -5,7 +5,7 @@ use candid::Principal; use dfx_core::config::model::dfinity::ConfigInterface; use fn_error_context::context; use ic_utils::interfaces::management_canister::attributes::{ - ComputeAllocation, FreezingThreshold, MemoryAllocation, + ComputeAllocation, FreezingThreshold, MemoryAllocation, ReservedCyclesLimit, }; use std::convert::TryFrom; @@ -15,6 +15,7 @@ pub struct CanisterSettings { pub compute_allocation: Option, pub memory_allocation: Option, pub freezing_threshold: Option, + pub reserved_cycles_limit: Option, } #[context("Failed to get compute allocation.")] @@ -80,3 +81,24 @@ pub fn get_freezing_threshold( }) .transpose() } + +#[context("Failed to get reserved cycles limit")] +pub fn get_reserved_cycles_limit( + reserved_cycles_limit: Option, + config_interface: Option<&ConfigInterface>, + canister_name: Option<&str>, +) -> DfxResult> { + let reserved_cycles_limit = match (reserved_cycles_limit, config_interface, canister_name) { + (Some(reserved_cycles_limit), _, _) => Some(reserved_cycles_limit), + (None, Some(config_interface), Some(canister_name)) => { + config_interface.get_reserved_cycles_limit(canister_name)? + } + _ => None, + }; + reserved_cycles_limit + .map(|arg| { + ReservedCyclesLimit::try_from(arg) + .context("Must be a limit between 0 and 2^128-1 inclusive.") + }) + .transpose() +} diff --git a/src/dfx/src/lib/identity/wallet.rs b/src/dfx/src/lib/identity/wallet.rs index 93b0c0b907..d0b3abb454 100644 --- a/src/dfx/src/lib/identity/wallet.rs +++ b/src/dfx/src/lib/identity/wallet.rs @@ -3,7 +3,7 @@ use crate::lib::error::DfxResult; use crate::lib::root_key::fetch_root_key_if_needed; use crate::util::assets::wallet_wasm; use crate::Environment; -use anyhow::{anyhow, bail, Context}; +use anyhow::{bail, Context}; use candid::Principal; use dfx_core::canister::build_wallet_canister; use dfx_core::config::directories::get_user_dfx_config_dir; @@ -83,9 +83,7 @@ pub async fn create_wallet( some_canister_id: Option, ) -> DfxResult { fetch_root_key_if_needed(env).await?; - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); let mgr = ManagementCanister::create(agent); info!( env.get_logger(), @@ -161,9 +159,7 @@ pub async fn get_or_create_wallet_canister<'env>( // without this async block, #[context] gives a spurious error async { let wallet_canister_id = get_or_create_wallet(env, network, name).await?; - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); build_wallet_canister(wallet_canister_id, agent) .await .map_err(Into::into) diff --git a/src/dfx/src/lib/migrate.rs b/src/dfx/src/lib/migrate.rs index 62845ab4e0..16642be28a 100644 --- a/src/dfx/src/lib/migrate.rs +++ b/src/dfx/src/lib/migrate.rs @@ -19,9 +19,7 @@ pub async fn migrate(env: &dyn Environment, network: &NetworkDescriptor, fix: bo fetch_root_key_if_needed(env).await?; let config = env.get_config_or_anyhow()?; let config = config.get_config(); - let agent = env - .get_agent() - .expect("Could not get agent from environment"); + let agent = env.get_agent(); let mut mgr = env.new_identity_manager()?; let ident = mgr.instantiate_selected_identity(env.get_logger())?; let mut did_migrate = false; @@ -114,6 +112,7 @@ async fn migrate_canister( compute_allocation: None, freezing_threshold: None, memory_allocation: None, + reserved_cycles_limit: None, }, },)), 0, diff --git a/src/dfx/src/lib/mod.rs b/src/dfx/src/lib/mod.rs index 221cd6999d..2de6df22db 100644 --- a/src/dfx/src/lib/mod.rs +++ b/src/dfx/src/lib/mod.rs @@ -1,6 +1,7 @@ pub mod agent; pub mod builders; pub mod canister_info; +pub mod cycles_ledger_types; pub mod deps; pub mod diagnosis; pub mod dist; @@ -27,6 +28,7 @@ pub mod progress_bar; pub mod project; pub mod replica; pub mod replica_config; +pub mod retryable; pub mod root_key; pub mod sign; pub mod state_tree; diff --git a/src/dfx/src/lib/named_canister.rs b/src/dfx/src/lib/named_canister.rs index 1484b74fc7..c3afd7bdb3 100644 --- a/src/dfx/src/lib/named_canister.rs +++ b/src/dfx/src/lib/named_canister.rs @@ -30,10 +30,7 @@ pub async fn install_ui_canister( )); } fetch_root_key_if_needed(env).await?; - let mgr = ManagementCanister::create( - env.get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?, - ); + let mgr = ManagementCanister::create(env.get_agent()); info!( env.get_logger(), "Creating UI canister on the {} network.", network.name diff --git a/src/dfx/src/lib/operations/canister/create_canister.rs b/src/dfx/src/lib/operations/canister/create_canister.rs index 1d6ee09171..1880100739 100644 --- a/src/dfx/src/lib/operations/canister/create_canister.rs +++ b/src/dfx/src/lib/operations/canister/create_canister.rs @@ -73,9 +73,7 @@ pub async fn create_canister( return reserve_canister_with_playground(env, canister_name).await; } - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); let cid = match call_sender { CallSender::SelectedId => { create_with_management_canister(env, agent, with_cycles, specified_id, settings).await @@ -121,6 +119,7 @@ async fn create_with_management_canister( .with_optional_compute_allocation(settings.compute_allocation) .with_optional_memory_allocation(settings.memory_allocation) .with_optional_freezing_threshold(settings.freezing_threshold) + .with_optional_reserved_cycles_limit(settings.reserved_cycles_limit) .call_and_wait() .await; const NEEDS_WALLET: &str = "In order to create a canister on this network, you must use a wallet in order to allocate cycles to the new canister. \ @@ -152,6 +151,10 @@ async fn create_with_wallet( ) -> DfxResult { let wallet = build_wallet_canister(*wallet_id, agent).await?; let cycles = with_cycles.unwrap_or(CANISTER_CREATE_FEE + CANISTER_INITIAL_CYCLE_BALANCE); + if settings.reserved_cycles_limit.is_some() { + bail!( + "Cannot create a canister using a wallet if the reserved_cycles_limit is set. Please create with --no-wallet or use dfx canister update-settings instead.") + } match wallet .wallet_create_canister( cycles, diff --git a/src/dfx/src/lib/operations/canister/deploy_canisters.rs b/src/dfx/src/lib/operations/canister/deploy_canisters.rs index 7984f6cb76..b8d4cf65c8 100644 --- a/src/dfx/src/lib/operations/canister/deploy_canisters.rs +++ b/src/dfx/src/lib/operations/canister/deploy_canisters.rs @@ -20,7 +20,7 @@ use dfx_core::config::model::dfinity::Config; use dfx_core::identity::CallSender; use fn_error_context::context; use ic_utils::interfaces::management_canister::attributes::{ - ComputeAllocation, FreezingThreshold, MemoryAllocation, + ComputeAllocation, FreezingThreshold, MemoryAllocation, ReservedCyclesLimit, }; use ic_utils::interfaces::management_canister::builders::InstallMode; use slog::info; @@ -242,6 +242,12 @@ async fn register_canisters( FreezingThreshold::try_from(arg.as_secs()) .expect("Freezing threshold must be between 0 and 2^64-1, inclusively.") }); + let reserved_cycles_limit = config_interface + .get_reserved_cycles_limit(canister_name)? + .map(|arg| { + ReservedCyclesLimit::try_from(arg) + .expect("Reserved cycles limit must be between 0 and 2^128-1, inclusively.") + }); let controllers = None; create_canister( env, @@ -254,6 +260,7 @@ async fn register_canisters( compute_allocation, memory_allocation, freezing_threshold, + reserved_cycles_limit, }, ) .await?; @@ -358,9 +365,7 @@ async fn prepare_assets_for_commit( ); } - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); prepare_assets_for_proposal(&canister_info, agent, env.get_logger()).await?; @@ -384,9 +389,7 @@ async fn compute_evidence( ); } - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); let assets_canister_info = canister_info.as_info::()?; let source_paths = assets_canister_info.get_source_paths(); diff --git a/src/dfx/src/lib/operations/canister/install_canister.rs b/src/dfx/src/lib/operations/canister/install_canister.rs index a53375493f..1bd13cd42b 100644 --- a/src/dfx/src/lib/operations/canister/install_canister.rs +++ b/src/dfx/src/lib/operations/canister/install_canister.rs @@ -50,9 +50,7 @@ pub async fn install_canister( no_asset_upgrade: bool, ) -> DfxResult { let log = env.get_logger(); - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); let network = env.get_network_descriptor(); if !network.is_ic && named_canister::get_ui_canister_id(canister_id_store).is_none() { named_canister::install_ui_canister(env, canister_id_store, None).await?; @@ -109,9 +107,13 @@ pub async fn install_canister( let wasm_path: PathBuf = if let Some(wasm_override) = wasm_path_override { wasm_override.into() } else { - canister_info + let build_wasm_path = canister_info .map(|info| info.get_build_wasm_path()) - .context("Failed to find wasm")? + .context("Failed to find wasm")?; + if !build_wasm_path.exists() { + bail!("The canister must be built before install. Please run `dfx build`."); + } + build_wasm_path }; let wasm_module = std::fs::read(&wasm_path) .with_context(|| format!("Failed to read {}.", &wasm_path.display()))?; diff --git a/src/dfx/src/lib/operations/canister/mod.rs b/src/dfx/src/lib/operations/canister/mod.rs index 1107c293b3..0d7595690e 100644 --- a/src/dfx/src/lib/operations/canister/mod.rs +++ b/src/dfx/src/lib/operations/canister/mod.rs @@ -7,7 +7,7 @@ use crate::lib::canister_info::CanisterInfo; use crate::lib::environment::Environment; use crate::lib::error::DfxResult; use crate::lib::ic_attributes::CanisterSettings as DfxCanisterSettings; -use anyhow::{anyhow, bail, Context}; +use anyhow::{bail, Context}; use candid::utils::ArgumentDecoder; use candid::CandidType; use candid::Principal as CanisterId; @@ -44,14 +44,12 @@ where A: CandidType + Sync + Send, O: for<'de> ArgumentDecoder<'de> + Sync + Send, { - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); let out = match call_sender { CallSender::SelectedId => { let mgr = ManagementCanister::create(agent); - mgr.update_(method) + mgr.update(method) .with_arg(arg) .with_effective_canister_id(destination_canister) .build() @@ -183,6 +181,10 @@ pub async fn update_settings( .freezing_threshold .map(u64::from) .map(candid::Nat::from), + reserved_cycles_limit: settings + .reserved_cycles_limit + .map(u128::from) + .map(candid::Nat::from), }, }, call_sender, diff --git a/src/dfx/src/lib/operations/canister/motoko_playground.rs b/src/dfx/src/lib/operations/canister/motoko_playground.rs index b53293582c..e9f4d33dd4 100644 --- a/src/dfx/src/lib/operations/canister/motoko_playground.rs +++ b/src/dfx/src/lib/operations/canister/motoko_playground.rs @@ -76,7 +76,7 @@ pub async fn reserve_canister_with_playground( env: &dyn Environment, canister_name: &str, ) -> DfxResult { - let agent = env.get_agent().context("Failed to get HTTP agent")?; + let agent = env.get_agent(); let log = env.get_logger(); let playground_canister = if let NetworkTypeDescriptor::Playground { playground_canister, @@ -125,7 +125,7 @@ pub async fn authorize_asset_uploader( canister_timestamp: &SystemTime, principal_to_authorize: &Principal, ) -> DfxResult { - let agent = env.get_agent().context("Failed to get HTTP agent")?; + let agent = env.get_agent(); let playground_canister = if let NetworkTypeDescriptor::Playground { playground_canister, .. @@ -159,7 +159,7 @@ pub async fn playground_install_code( is_asset_canister: bool, ) -> DfxResult { let canister_info = CanisterInfo::from(canister_id, canister_timestamp)?; - let agent = env.get_agent().context("Failed to get HTTP agent")?; + let agent = env.get_agent(); let playground_canister = match env.get_network_descriptor().r#type { NetworkTypeDescriptor::Playground { playground_canister, diff --git a/src/dfx/src/lib/operations/cmc.rs b/src/dfx/src/lib/operations/cmc.rs index 5db9b608ae..695ee3c65d 100644 --- a/src/dfx/src/lib/operations/cmc.rs +++ b/src/dfx/src/lib/operations/cmc.rs @@ -8,12 +8,14 @@ use crate::lib::nns_types::icpts::ICPTs; use crate::lib::operations::ledger::transfer; use candid::{Decode, Encode, Principal}; use ic_agent::Agent; +use slog::Logger; const NOTIFY_CREATE_CANISTER_METHOD: &str = "notify_create_canister"; const NOTIFY_TOP_UP_METHOD: &str = "notify_top_up"; pub async fn transfer_cmc( agent: &Agent, + logger: &Logger, memo: Memo, amount: ICPTs, fee: ICPTs, @@ -26,6 +28,7 @@ pub async fn transfer_cmc( AccountIdentifier::new(MAINNET_CYCLE_MINTER_CANISTER_ID, Some(to_subaccount)).to_address(); transfer( agent, + logger, &MAINNET_LEDGER_CANISTER_ID, memo, amount, diff --git a/src/dfx/src/lib/operations/cycles_ledger.rs b/src/dfx/src/lib/operations/cycles_ledger.rs new file mode 100644 index 0000000000..c82a561760 --- /dev/null +++ b/src/dfx/src/lib/operations/cycles_ledger.rs @@ -0,0 +1,172 @@ +use crate::lib::cycles_ledger_types; +use crate::lib::cycles_ledger_types::send::SendError; +use crate::lib::error::DfxResult; +use crate::lib::retryable::retryable; +use anyhow::anyhow; +use backoff::future::retry; +use backoff::ExponentialBackoff; +use candid::{Nat, Principal}; +use ic_agent::Agent; +use ic_utils::call::SyncCall; +use ic_utils::Canister; +use icrc_ledger_types::icrc1; +use icrc_ledger_types::icrc1::transfer::{BlockIndex, TransferError}; +use slog::{info, Logger}; + +const ICRC1_BALANCE_OF_METHOD: &str = "icrc1_balance_of"; +const ICRC1_TRANSFER_METHOD: &str = "icrc1_transfer"; +const SEND_METHOD: &str = "send"; + +pub async fn balance( + agent: &Agent, + owner: Principal, + subaccount: Option, + cycles_ledger_canister_id: Principal, +) -> DfxResult { + let canister = Canister::builder() + .with_agent(agent) + .with_canister_id(cycles_ledger_canister_id) + .build()?; + let arg = icrc1::account::Account { owner, subaccount }; + + let retry_policy = ExponentialBackoff::default(); + + retry(retry_policy, || async { + let result = canister + .query(ICRC1_BALANCE_OF_METHOD) + .with_arg(arg) + .build() + .call() + .await; + match result { + Ok((balance,)) => Ok(balance), + Err(agent_err) if retryable(&agent_err) => { + Err(backoff::Error::transient(anyhow!(agent_err))) + } + Err(agent_err) => Err(backoff::Error::permanent(anyhow!(agent_err))), + } + }) + .await +} + +pub async fn transfer( + agent: &Agent, + logger: &Logger, + amount: u128, + from_subaccount: Option, + owner: Principal, + to_subaccount: Option, + created_at_time: u64, + memo: Option, + cycles_ledger_canister_id: Principal, +) -> DfxResult { + let canister = Canister::builder() + .with_agent(agent) + .with_canister_id(cycles_ledger_canister_id) + .build()?; + + let retry_policy = ExponentialBackoff::default(); + + let block_index = retry(retry_policy, || async { + let arg = icrc1::transfer::TransferArg { + from_subaccount, + to: icrc1::account::Account { + owner, + subaccount: to_subaccount, + }, + fee: None, + created_at_time: Some(created_at_time), + memo: memo.map(|v| v.into()), + amount: Nat::from(amount), + }; + match canister + .update(ICRC1_TRANSFER_METHOD) + .with_arg(arg) + .build() + .map(|result: (Result,)| (result.0,)) + .call_and_wait() + .await + .map(|(result,)| result) + { + Ok(Ok(block_index)) => Ok(block_index), + Ok(Err(TransferError::Duplicate { duplicate_of })) => { + info!( + logger, + "{}", + TransferError::Duplicate { + duplicate_of: duplicate_of.clone() + } + ); + Ok(duplicate_of) + } + Ok(Err(transfer_err)) => Err(backoff::Error::permanent(anyhow!(transfer_err))), + Err(agent_err) if retryable(&agent_err) => { + Err(backoff::Error::transient(anyhow!(agent_err))) + } + Err(agent_err) => Err(backoff::Error::permanent(anyhow!(agent_err))), + } + }) + .await?; + + Ok(block_index) +} + +pub async fn send( + agent: &Agent, + logger: &Logger, + to: Principal, + amount: u128, + created_at_time: u64, + from_subaccount: Option, + cycles_ledger_canister_id: Principal, +) -> DfxResult { + let canister = Canister::builder() + .with_agent(agent) + .with_canister_id(cycles_ledger_canister_id) + .build()?; + + let retry_policy = ExponentialBackoff::default(); + let block_index: BlockIndex = retry(retry_policy, || async { + let arg = cycles_ledger_types::send::SendArgs { + from_subaccount, + to, + created_at_time: Some(created_at_time), + amount: Nat::from(amount), + }; + match canister + .update(SEND_METHOD) + .with_arg(arg) + .build() + .map(|result: (Result,)| (result.0,)) + .call_and_wait() + .await + .map(|(result,)| result) + { + Ok(Ok(block_index)) => Ok(block_index), + Ok(Err(SendError::Duplicate { duplicate_of })) => { + info!( + logger, + "transaction is a duplicate of another transaction in block {}", duplicate_of + ); + Ok(duplicate_of) + } + Ok(Err(SendError::InvalidReceiver { receiver })) => { + Err(backoff::Error::permanent(anyhow!( + "Invalid receiver: {}. Make sure the receiver is a canister.", + receiver + ))) + } + Ok(Err(send_err)) => Err(backoff::Error::permanent(anyhow!( + "send error: {:?}", + send_err + ))), + Err(agent_err) if retryable(&agent_err) => { + Err(backoff::Error::transient(anyhow!(agent_err))) + } + Err(agent_err) => Err(backoff::Error::permanent(anyhow!(agent_err))), + } + }) + .await?; + + Ok(block_index) +} diff --git a/src/dfx/src/lib/operations/ledger.rs b/src/dfx/src/lib/operations/ledger.rs index f3f360d740..6f5c45b7c8 100644 --- a/src/dfx/src/lib/operations/ledger.rs +++ b/src/dfx/src/lib/operations/ledger.rs @@ -20,6 +20,7 @@ use ic_agent::{ lookup_value, Agent, AgentError, }; use ic_utils::{call::SyncCall, Canister}; +use slog::{info, Logger}; use std::time::{SystemTime, UNIX_EPOCH}; const ACCOUNT_BALANCE_METHOD: &str = "account_balance_dfx"; @@ -36,7 +37,7 @@ pub async fn balance( .with_canister_id(canister_id) .build()?; let (result,) = canister - .query_(ACCOUNT_BALANCE_METHOD) + .query(ACCOUNT_BALANCE_METHOD) .with_arg(AccountBalanceArgs { account: acct.to_string(), }) @@ -53,7 +54,7 @@ pub async fn xdr_permyriad_per_icp(agent: &Agent) -> DfxResult { .with_canister_id(MAINNET_CYCLE_MINTER_CANISTER_ID) .build()?; let (certified_rate,): (IcpXdrConversionRateCertifiedResponse,) = canister - .query_("get_icp_xdr_conversion_rate") + .query("get_icp_xdr_conversion_rate") .build() .call() .await?; @@ -98,6 +99,7 @@ pub async fn xdr_permyriad_per_icp(agent: &Agent) -> DfxResult { #[context("Failed to transfer funds.")] pub async fn transfer( agent: &Agent, + logger: &Logger, canister_id: &Principal, memo: Memo, amount: ICPTs, @@ -138,7 +140,7 @@ pub async fn transfer( match result { Ok(block_height) => break block_height, Err(TransferError::TxDuplicate { duplicate_of }) => { - println!("{}", TransferError::TxDuplicate { duplicate_of }); + info!(logger, "{}", TransferError::TxDuplicate { duplicate_of }); break duplicate_of; } Err(transfer_err) => bail!(transfer_err), diff --git a/src/dfx/src/lib/operations/mod.rs b/src/dfx/src/lib/operations/mod.rs index bbe6390dd4..d7d7b006f5 100644 --- a/src/dfx/src/lib/operations/mod.rs +++ b/src/dfx/src/lib/operations/mod.rs @@ -1,3 +1,4 @@ pub mod canister; pub mod cmc; +pub mod cycles_ledger; pub mod ledger; 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/retryable.rs b/src/dfx/src/lib/retryable.rs new file mode 100644 index 0000000000..edc76f241f --- /dev/null +++ b/src/dfx/src/lib/retryable.rs @@ -0,0 +1,8 @@ +use ic_agent::AgentError; + +pub fn retryable(agent_error: &AgentError) -> bool { + matches!( + agent_error, + AgentError::TimeoutWaitingForResponse() | AgentError::TransportError(_) + ) +} diff --git a/src/dfx/src/lib/root_key.rs b/src/dfx/src/lib/root_key.rs index d39f0f029b..5b7cd486cd 100644 --- a/src/dfx/src/lib/root_key.rs +++ b/src/dfx/src/lib/root_key.rs @@ -1,11 +1,9 @@ use crate::{lib::error::DfxResult, Environment}; -use anyhow::anyhow; + use dfx_core::network::root_key; pub async fn fetch_root_key_if_needed(env: &dyn Environment) -> DfxResult { - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); let network = env.get_network_descriptor(); root_key::fetch_root_key_when_local(agent, network).await?; Ok(()) @@ -14,9 +12,7 @@ pub async fn fetch_root_key_if_needed(env: &dyn Environment) -> DfxResult { /// Fetches the root key of the local network. /// Returns an error if attempted to run on the real IC. pub async fn fetch_root_key_or_anyhow(env: &dyn Environment) -> DfxResult { - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot get HTTP client from environment."))?; + let agent = env.get_agent(); let network = env.get_network_descriptor(); root_key::fetch_root_key_when_local_or_error(agent, network).await?; Ok(()) 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/assets.rs b/src/dfx/src/util/assets.rs index 9500024f54..d4a417368a 100644 --- a/src/dfx/src/util/assets.rs +++ b/src/dfx/src/util/assets.rs @@ -107,3 +107,206 @@ pub fn bitcoin_wasm(logger: &slog::Logger) -> DfxResult> { bail!("Failed to find bitcoin canister archive entry"); } } + +pub fn management_idl() -> DfxResult { + // FIXME get idl from replica when it's available + // Pulled from https://github.com/dfinity/interface-spec/blob/master/spec/_attachments/ic.did + Ok(r##" +type canister_id = principal; +type wasm_module = blob; + +type canister_settings = record { + controllers : opt vec principal; + compute_allocation : opt nat; + memory_allocation : opt nat; + freezing_threshold : opt nat; +}; + +type definite_canister_settings = record { + controllers : vec principal; + compute_allocation : nat; + memory_allocation : nat; + freezing_threshold : nat; +}; + +type change_origin = variant { + from_user : record { + user_id : principal; + }; + from_canister : record { + canister_id : principal; + canister_version : opt nat64; + }; +}; + +type change_details = variant { + creation : record { + controllers : vec principal; + }; + code_uninstall; + code_deployment : record { + mode : variant {install; reinstall; upgrade}; + module_hash : blob; + }; + controllers_change : record { + controllers : vec principal; + }; +}; + +type change = record { + timestamp_nanos : nat64; + canister_version : nat64; + origin : change_origin; + details : change_details; +}; + +type http_header = record { name: text; value: text }; + +type http_response = record { + status: nat; + headers: vec http_header; + body: blob; +}; + +type ecdsa_curve = variant { secp256k1; }; + +type satoshi = nat64; + +type bitcoin_network = variant { + mainnet; + testnet; +}; + +type bitcoin_address = text; + +type block_hash = blob; + +type outpoint = record { + txid : blob; + vout : nat32 +}; + +type utxo = record { + outpoint: outpoint; + value: satoshi; + height: nat32; +}; + +type get_utxos_request = record { + address : bitcoin_address; + network: bitcoin_network; + filter: opt variant { + min_confirmations: nat32; + page: blob; + }; +}; + +type get_current_fee_percentiles_request = record { + network: bitcoin_network; +}; + +type get_utxos_response = record { + utxos: vec utxo; + tip_block_hash: block_hash; + tip_height: nat32; + next_page: opt blob; +}; + +type get_balance_request = record { + address : bitcoin_address; + network: bitcoin_network; + min_confirmations: opt nat32; +}; + +type send_transaction_request = record { + transaction: blob; + network: bitcoin_network; +}; + +type millisatoshi_per_byte = nat64; + +service ic : { + create_canister : (record { + settings : opt canister_settings; + sender_canister_version : opt nat64; + }) -> (record {canister_id : canister_id}); + update_settings : (record { + canister_id : principal; + settings : canister_settings; + sender_canister_version : opt nat64; + }) -> (); + install_code : (record { + mode : variant {install; reinstall; upgrade}; + canister_id : canister_id; + wasm_module : wasm_module; + arg : blob; + sender_canister_version : opt nat64; + }) -> (); + uninstall_code : (record { + canister_id : canister_id; + sender_canister_version : opt nat64; + }) -> (); + start_canister : (record {canister_id : canister_id}) -> (); + stop_canister : (record {canister_id : canister_id}) -> (); + canister_status : (record {canister_id : canister_id}) -> (record { + status : variant { running; stopping; stopped }; + settings: definite_canister_settings; + module_hash: opt blob; + memory_size: nat; + cycles: nat; + idle_cycles_burned_per_day: nat; + }); + canister_info : (record { + canister_id : canister_id; + num_requested_changes : opt nat64; + }) -> (record { + total_num_changes : nat64; + recent_changes : vec change; + module_hash : opt blob; + controllers : vec principal; + }); + delete_canister : (record {canister_id : canister_id}) -> (); + deposit_cycles : (record {canister_id : canister_id}) -> (); + raw_rand : () -> (blob); + http_request : (record { + url : text; + max_response_bytes: opt nat64; + method : variant { get; head; post }; + headers: vec http_header; + body : opt blob; + transform : opt record { + function : func (record {response : http_response; context : blob}) -> (http_response) query; + context : blob + }; + }) -> (http_response); + + // Threshold ECDSA signature + ecdsa_public_key : (record { + canister_id : opt canister_id; + derivation_path : vec blob; + key_id : record { curve: ecdsa_curve; name: text }; + }) -> (record { public_key : blob; chain_code : blob; }); + sign_with_ecdsa : (record { + message_hash : blob; + derivation_path : vec blob; + key_id : record { curve: ecdsa_curve; name: text }; + }) -> (record { signature : blob }); + + // bitcoin interface + bitcoin_get_balance: (get_balance_request) -> (satoshi); + bitcoin_get_utxos: (get_utxos_request) -> (get_utxos_response); + bitcoin_send_transaction: (send_transaction_request) -> (); + bitcoin_get_current_fee_percentiles: (get_current_fee_percentiles_request) -> (vec millisatoshi_per_byte); + + // provisional interfaces for the pre-ledger world + provisional_create_canister_with_cycles : (record { + amount: opt nat; + settings : opt canister_settings; + specified_id: opt canister_id; + sender_canister_version : opt nat64; + }) -> (record {canister_id : canister_id}); + provisional_top_up_canister : + (record { canister_id: canister_id; amount: nat }) -> (); +} +"##.to_string()) +} diff --git a/src/dfx/src/util/clap/parsers.rs b/src/dfx/src/util/clap/parsers.rs index e8b5f8360c..9b7184dffc 100644 --- a/src/dfx/src/util/clap/parsers.rs +++ b/src/dfx/src/util/clap/parsers.rs @@ -1,5 +1,33 @@ use byte_unit::{Byte, ByteUnit}; -use std::path::PathBuf; +use rust_decimal::Decimal; +use std::{path::PathBuf, str::FromStr}; + +/// Removes `_`, interprets `k`, `m`, `b`, `t` suffix (case-insensitive) +fn decimal_with_suffix_parser(input: &str) -> Result { + let input = input.replace('_', "").to_lowercase(); + let (number, suffix) = if input + .chars() + .last() + .map(|char| char.is_alphabetic()) + .unwrap_or(false) + { + input.split_at(input.len() - 1) + } else { + (input.as_str(), "") + }; + let multiplier: u64 = match suffix { + "" => Ok(1), + "k" => Ok(1_000), + "m" => Ok(1_000_000), + "b" => Ok(1_000_000_000), + "t" => Ok(1_000_000_000_000), + other => Err(format!("Unknown amount specifier: '{}'", other)), + }?; + let number = Decimal::from_str(number).map_err(|err| err.to_string())?; + Decimal::from(multiplier) + .checked_mul(number) + .ok_or_else(|| "Amount too large.".to_string()) +} pub fn request_id_parser(v: &str) -> Result { // A valid Request Id starts with `0x` and is a series of 64 hexadecimals. @@ -18,9 +46,10 @@ pub fn request_id_parser(v: &str) -> Result { } } -pub fn e8s_parser(e8s: &str) -> Result { - e8s.parse::() - .map_err(|_| "Must specify a non negative whole number.".to_string()) +pub fn e8s_parser(input: &str) -> Result { + decimal_with_suffix_parser(input)? + .try_into() + .map_err(|_| "Must specify a non-negative whole number.".to_string()) } pub fn memo_parser(memo: &str) -> Result { @@ -28,10 +57,14 @@ pub fn memo_parser(memo: &str) -> Result { .map_err(|_| "Must specify a non negative whole number.".to_string()) } -pub fn cycle_amount_parser(cycles: &str) -> Result { - cycles - .parse::() - .map_err(|_| "Must be a non negative amount.".to_string()) +pub fn cycle_amount_parser(input: &str) -> Result { + let removed_cycle_suffix = if input.to_lowercase().ends_with('c') { + &input[..input.len() - 1] + } else { + input + }; + + decimal_with_suffix_parser(removed_cycle_suffix)?.try_into().map_err(|_| "Failed to parse amount. Please use digits only or something like 3.5TC, 2t, or 5_000_000.".to_string()) } pub fn file_parser(path: &str) -> Result { @@ -52,9 +85,15 @@ pub fn file_or_stdin_parser(path: &str) -> Result { } } -pub fn trillion_cycle_amount_parser(cycles: &str) -> Result { - format!("{}000000000000", cycles).parse::() - .map_err(|_| "Must be a non negative amount. Currently only accepts whole numbers. Use --cycles otherwise.".to_string()) +pub fn trillion_cycle_amount_parser(input: &str) -> Result { + if let Ok(cycles) = format!("{}000000000000", input.replace('_', "")).parse::() { + Ok(cycles) + } else { + decimal_with_suffix_parser(input)? + .checked_mul(1_000_000_000_000_u64.into()) + .and_then(|total| total.try_into().ok()) + .ok_or_else(|| "Amount too large.".to_string()) + } } pub fn compute_allocation_parser(compute_allocation: &str) -> Result { @@ -84,6 +123,12 @@ pub fn freezing_threshold_parser(freezing_threshold: &str) -> Result Result { + reserved_cycles_limit + .parse::() + .map_err(|_| "Must be a value between 0 and 2^128-1 inclusive".to_string()) +} + /// Validate a String can be a valid project name. /// A project name is valid if it starts with a letter, and is alphanumeric (with hyphens). /// It cannot end with a dash. @@ -124,3 +169,42 @@ pub fn hsm_key_id_parser(key_id: &str) -> Result { Ok(key_id.to_string()) } } + +#[test] +fn test_cycle_amount_parser() { + assert_eq!(cycle_amount_parser("900c"), Ok(900)); + assert_eq!(cycle_amount_parser("9_887K"), Ok(9_887_000)); + assert_eq!(cycle_amount_parser("0.1M"), Ok(100_000)); + assert_eq!(cycle_amount_parser("0.01b"), Ok(10_000_000)); + assert_eq!(cycle_amount_parser("10T"), Ok(10_000_000_000_000)); + assert_eq!(cycle_amount_parser("10TC"), Ok(10_000_000_000_000)); + assert_eq!(cycle_amount_parser("1.23t"), Ok(1_230_000_000_000)); + + assert!(cycle_amount_parser("1ffff").is_err()); + assert!(cycle_amount_parser("1MT").is_err()); + assert!(cycle_amount_parser("-0.1m").is_err()); + assert!(cycle_amount_parser("T100").is_err()); + assert!(cycle_amount_parser("1.1k0").is_err()); + assert!(cycle_amount_parser(&format!("{}0", u128::MAX)).is_err()); +} + +#[test] +fn test_trillion_cycle_amount_parser() { + const TRILLION: u128 = 1_000_000_000_000; + assert_eq!(trillion_cycle_amount_parser("3"), Ok(3 * TRILLION)); + assert_eq!(trillion_cycle_amount_parser("5_555"), Ok(5_555 * TRILLION)); + assert_eq!(trillion_cycle_amount_parser("1k"), Ok(1_000 * TRILLION)); + assert_eq!(trillion_cycle_amount_parser("0.3"), Ok(300_000_000_000)); + assert_eq!(trillion_cycle_amount_parser("0.3k"), Ok(300 * TRILLION)); + + assert!(trillion_cycle_amount_parser("-0.1m").is_err()); + assert!(trillion_cycle_amount_parser("1TC").is_err()); // ambiguous in combination with --t +} + +#[test] +fn test_e8s_parser() { + assert_eq!(e8s_parser("1"), Ok(1)); + assert_eq!(e8s_parser("1_000"), Ok(1_000)); + assert_eq!(e8s_parser("1k"), Ok(1_000)); + assert_eq!(e8s_parser("1M"), Ok(1_000_000)); +} 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() diff --git a/src/distributed/assetstorage.did b/src/distributed/assetstorage.did index c4f659eb88..51bb1a235b 100644 --- a/src/distributed/assetstorage.did +++ b/src/distributed/assetstorage.did @@ -139,7 +139,25 @@ type ListPermitted = record { permission: Permission }; type ValidationResult = variant { Ok : text; Err : text }; -service: { +type AssetCanisterArgs = variant { + Init: InitArgs; + Upgrade: UpgradeArgs; +}; + +type InitArgs = record {}; + +type UpgradeArgs = record { + set_permissions: opt SetPermissions; +}; + +/// Sets the list of principals granted each permission. +type SetPermissions = record { + prepare: vec principal; + commit: vec principal; + manage_permissions: vec principal; +}; + +service: (asset_canister_args: opt AssetCanisterArgs) -> { api_version: () -> (nat16) query; get: (record { @@ -220,10 +238,10 @@ service: { authorize: (principal) -> (); deauthorize: (principal) -> (); - list_authorized: () -> (vec principal) query; + list_authorized: () -> (vec principal); grant_permission: (GrantPermission) -> (); revoke_permission: (RevokePermission) -> (); - list_permitted: (ListPermitted) -> (vec principal) query; + list_permitted: (ListPermitted) -> (vec principal); take_ownership: () -> (); get_asset_properties : (key: Key) -> (record { diff --git a/src/distributed/assetstorage.wasm.gz b/src/distributed/assetstorage.wasm.gz index db405979dd..eb402f7605 100755 Binary files a/src/distributed/assetstorage.wasm.gz and b/src/distributed/assetstorage.wasm.gz differ diff --git a/src/distributed/ui.wasm b/src/distributed/ui.wasm index 9458baa7fa..673188b3e5 100644 Binary files a/src/distributed/ui.wasm and b/src/distributed/ui.wasm differ