Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Emit management canister idl during build when imported by Motoko canister #3329

Merged
merged 22 commits into from
Oct 1, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 22 additions & 16 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

# UNRELEASED

### 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: dfx deploy urls printed for asset canisters

### chore: --emulator parameter is deprecated and will be discontinued soon
Expand Down Expand Up @@ -264,7 +270,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.

Expand Down Expand Up @@ -319,7 +325,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.

Expand Down Expand Up @@ -409,7 +415,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.

Expand Down Expand Up @@ -508,20 +514,20 @@ When creating a canister on non-mainnet replica, you can now specify the caniste
`dfx deploy <CANISTER_NAME> --specified-id <PRINCIPAL>`

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.

`ic-cdk-timers` is included in the dependencies.

### 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
Expand Down Expand Up @@ -700,7 +706,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
Expand All @@ -718,12 +724,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)) })'
```
Expand All @@ -739,7 +745,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

Expand Down Expand Up @@ -850,7 +856,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
Expand All @@ -864,7 +870,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

Expand Down Expand Up @@ -1089,12 +1095,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) |
Expand All @@ -1111,7 +1117,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
},
]
```
Expand Down
7 changes: 7 additions & 0 deletions e2e/assets/motoko_management/main.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Management "ic:aaaaa-aa";

actor {
public func rand() : async Blob {
await Management.raw_rand();
};
};
1 change: 1 addition & 0 deletions e2e/assets/motoko_management/patch.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
jq '.canisters.e2e_project_backend.main="main.mo"' dfx.json | sponge dfx.json
9 changes: 9 additions & 0 deletions e2e/tests-dfx/build.bash
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,15 @@ 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 succeeds on default project" {
dfx_start
dfx canister create --all
Expand Down
36 changes: 26 additions & 10 deletions src/dfx/src/lib/builders/motoko.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -38,6 +39,20 @@ impl MotokoBuilder {
}
}

#[context("Failed to find imports for canister at '{}'.", file.to_string_lossy())]
kentosugama marked this conversation as resolved.
Show resolved Hide resolved
fn get_imports(cache: &dyn Cache, file: &Path) -> DfxResult<Vec<MotokoImport>> {
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))?;

String::from_utf8_lossy(&output.stdout)
.lines()
.map(|line| MotokoImport::try_from(line).context("Failed to create MotokoImport."))
.collect::<DfxResult<Vec<MotokoImport>>>()
}

impl CanisterBuilder for MotokoBuilder {
#[context("Failed to get dependencies for canister '{}'.", info.get_name())]
fn get_dependencies(
Expand All @@ -60,16 +75,7 @@ impl CanisterBuilder for MotokoBuilder {

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.")?;
for import in get_imports(cache, file)? {
match import {
MotokoImport::Canister(_) => {
result.insert(import);
Expand Down Expand Up @@ -132,6 +138,16 @@ 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(), input_path)?
kentosugama marked this conversation as resolved.
Show resolved Hide resolved
.contains(&MotokoImport::Ic("aaaaa-aa".to_string()))
{
let management_idl_path = idl_dir_path.join("aaaaa-aa.did");
std::fs::write(&management_idl_path, management_idl()?).with_context(|| {
format!("Failed to write {}.", management_idl_path.to_string_lossy())
})?;
kentosugama marked this conversation as resolved.
Show resolved Hide resolved
}

let package_arguments =
package_arguments::load(cache.as_ref(), motoko_info.get_packtool())?;

Expand Down
Loading