Skip to content

Commit

Permalink
feat: dfx canister status shows multiple controllers (dfinity#1782)
Browse files Browse the repository at this point in the history
- `dfx canister info` displays all controllers
- `dfx canister status` displays all controllers
- `dfx canister update-settings` now accepts multiple instances of the `--controller` parameter.  Note that update-settings forwards its call through the wallet to the management canister, so this works regardless of wallet version.
- `dfx canister create` now accepts multiple instances of the `--controller` parameter.  If the installed wallet does not support multiple controllers, displays an error message that mentions `dfx wallet upgrade`.
- update to ic-ref (ic-hs) 0.18.0

See also:
- dfinity/cycles-wallet#105
- dfinity/agent-rs#249
- dfinity/docs#575
  • Loading branch information
ericswanson-dfinity authored Sep 21, 2021
1 parent e4eb355 commit f5131a1
Show file tree
Hide file tree
Showing 25 changed files with 555 additions and 145 deletions.
23 changes: 23 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

== DFX

=== feat: dfx canister create now accepts multiple instances of --controller argument

It is now possible to create canisters with more than one controller by
passing multiple instances of the `--controller parameter to `dfx canister create`.

You will need to upgrade your wallet with `dfx wallet upgrade`, or `dfx wallet --network ic upgrade`

=== feat: dfx canister update-settings now accepts multiple instance of --controller argument

It is now possible to configure a canister to have more than one controller by
passing multiple instances of the `--controller parameter to `dfx canister update-settings`.

=== feat: dfx canister info and dfx canister status now display all controllers

=== feat!: dfx canister create --controller <controller> named parameter

Breaking change: The controller parameter for `dfx canister create` is now passed as a named parameter,
Expand All @@ -10,6 +24,15 @@ rather than optionally following the canister name.
Old: dfx canister create [canister name] [controller]
New: dfx canister create --controller <controller> [canister name]

== Cycles Wallet

- Module hash: 9183a38dd2eb1a4295f360990f87e67aa006f225910ab14880748e091248e086
- https://github.com/dfinity/cycles-wallet/commit/9ef38bb7cd0fe17cda749bf8e9bbec5723da0e95

=== Added support for multiple controllers

You will need to upgrade your wallet with `dfx wallet upgrade`, or `dfx wallet --network ic upgrade`

= 0.8.1

== DFX
Expand Down
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ members = [
[patch.crates-io.ic-agent]
version = "0.8.0"
git = "https://github.com/dfinity/agent-rs.git"
rev = "13a61995e0d112536c86e41cadf16201ffb7f29c"
rev = "5ab3aee0ad708254ea0c3fe7f61561f8a1cbb864"

[patch.crates-io.ic-asset]
version = "0.3.0"
git = "https://github.com/dfinity/agent-rs.git"
rev = "13a61995e0d112536c86e41cadf16201ffb7f29c"
rev = "5ab3aee0ad708254ea0c3fe7f61561f8a1cbb864"

[patch.crates-io.ic-identity-hsm]
version = "0.3.5"
git = "https://github.com/dfinity/agent-rs.git"
rev = "13a61995e0d112536c86e41cadf16201ffb7f29c"
rev = "5ab3aee0ad708254ea0c3fe7f61561f8a1cbb864"

[patch.crates-io.ic-utils]
version = "0.6.0"
git = "https://github.com/dfinity/agent-rs.git"
rev = "13a61995e0d112536c86e41cadf16201ffb7f29c"
rev = "5ab3aee0ad708254ea0c3fe7f61561f8a1cbb864"
169 changes: 169 additions & 0 deletions e2e/archive/wallet/0.8.2/wallet.did
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
type EventKind = variant {
CyclesSent: record {
to: principal;
amount: nat64;
refund: nat64;
};
CyclesReceived: record {
from: principal;
amount: nat64;
};
AddressAdded: record {
id: principal;
name: opt text;
role: Role;
};
AddressRemoved: record {
id: principal;
};
CanisterCreated: record {
canister: principal;
cycles: nat64;
};
CanisterCalled: record {
canister: principal;
method_name: text;
cycles: nat64;
};
WalletDeployed: record {
canister: principal;
}
};

type Event = record {
id: nat32;
timestamp: nat64;
kind: EventKind;
};

type Role = variant {
Contact;
Custodian;
Controller;
};

type Kind = variant {
Unknown;
User;
Canister;
};

// An entry in the address book. It must have an ID and a role.
type AddressEntry = record {
id: principal;
name: opt text;
kind: Kind;
role: Role;
};

type WalletResultCreate = variant {
Ok : record { canister_id: principal };
Err: text;
};

type WalletResult = variant {
Ok : null;
Err : text;
};

type WalletResultCall = variant {
Ok : record { return: blob };
Err : text;
};

type CanisterSettings = record {
controller: opt principal;
controllers: opt vec principal;
compute_allocation: opt nat;
memory_allocation: opt nat;
freezing_threshold: opt nat;
};

type CreateCanisterArgs = record {
cycles: nat64;
settings: CanisterSettings;
};


// Assets
type HeaderField = record { text; text; };

type HttpRequest = record {
method: text;
url: text;
headers: vec HeaderField;
body: blob;
};

type HttpResponse = record {
status_code: nat16;
headers: vec HeaderField;
body: blob;
streaming_strategy: opt StreamingStrategy;
};

type StreamingCallbackHttpResponse = record {
body: blob;
token: opt Token;
};

type Token = record {};

type StreamingStrategy = variant {
Callback: record {
callback: func (Token) -> (StreamingCallbackHttpResponse) query;
token: Token;
};
};

service : {
wallet_api_version: () -> (text) query;

// Wallet Name
name: () -> (opt text) query;
set_name: (text) -> ();

// Controller Management
get_controllers: () -> (vec principal) query;
add_controller: (principal) -> ();
remove_controller: (principal) -> (WalletResult);

// Custodian Management
get_custodians: () -> (vec principal) query;
authorize: (principal) -> ();
deauthorize: (principal) -> (WalletResult);

// Cycle Management
wallet_balance: () -> (record { amount: nat64 }) query;
wallet_send: (record { canister: principal; amount: nat64 }) -> (WalletResult);
wallet_receive: () -> (); // Endpoint for receiving cycles.

// Managing canister
wallet_create_canister: (CreateCanisterArgs) -> (WalletResultCreate);

wallet_create_wallet: (CreateCanisterArgs) -> (WalletResultCreate);

wallet_store_wallet_wasm: (record {
wasm_module: blob;
}) -> ();

// Call Forwarding
wallet_call: (record {
canister: principal;
method_name: text;
args: blob;
cycles: nat64;
}) -> (WalletResultCall);

// Address book
add_address: (address: AddressEntry) -> ();
list_addresses: () -> (vec AddressEntry) query;
remove_address: (address: principal) -> (WalletResult);

// Events
get_events: (opt record { from: opt nat32; to: opt nat32; }) -> (vec Event) query;
get_chart: (opt record { count: opt nat32; precision: opt nat64; } ) -> (vec record { nat64; nat64; }) query;

// Assets
http_request: (request: HttpRequest) -> (HttpResponse) query;
}
Binary file added e2e/archive/wallet/0.8.2/wallet.wasm
Binary file not shown.
4 changes: 2 additions & 2 deletions e2e/tests-dfx/certified_info.bash
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ teardown() {
dfx_start
dfx canister create hello
assert_command dfx canister info "$(dfx canister id hello)"
assert_match "Controller: $(dfx identity get-wallet) Module hash: None"
assert_match "Controllers: $(dfx identity get-wallet) Module hash: None"

dfx build hello
RESULT="$(openssl dgst -sha256 .dfx/local/canisters/hello/hello.wasm)"
Expand All @@ -25,5 +25,5 @@ teardown() {

dfx canister install hello
assert_command dfx canister info "$(dfx canister id hello)"
assert_match "Controller: $(dfx identity get-wallet) Module hash: $(HASH)"
assert_match "Controllers: $(dfx identity get-wallet) Module hash: $(HASH)"
}
56 changes: 50 additions & 6 deletions e2e/tests-dfx/create.bash
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ teardown() {
}



@test "create succeeds on default project" {
dfx_start
assert_command dfx canister create --all
Expand Down Expand Up @@ -93,7 +94,7 @@ teardown() {

assert_command dfx canister create --all --controller alice
assert_command dfx canister info e2e_project
assert_match "Controller: $ALICE_PRINCIPAL"
assert_match "Controllers: $ALICE_PRINCIPAL"

assert_command_fail dfx deploy --no-wallet
assert_command_fail dfx deploy
Expand All @@ -107,7 +108,7 @@ teardown() {

assert_command dfx canister create --all --controller "${ALICE_PRINCIPAL}"
assert_command dfx canister info e2e_project
assert_match "Controller: $ALICE_PRINCIPAL"
assert_match "Controllers: $ALICE_PRINCIPAL"

assert_command_fail dfx deploy --no-wallet
assert_command_fail dfx deploy
Expand All @@ -128,7 +129,7 @@ teardown() {

dfx identity use alice
assert_command dfx canister info e2e_project
assert_match "Controller: $BOB_PRINCIPAL"
assert_match "Controllers: $BOB_PRINCIPAL"

assert_command_fail dfx deploy --no-wallet
assert_command_fail dfx deploy
Expand All @@ -146,11 +147,10 @@ teardown() {
assert_command dfx canister create --controller bob e2e_project_assets

assert_command dfx canister info e2e_project
assert_match "Controller: $ALICE_PRINCIPAL"
assert_match "Controllers: $ALICE_PRINCIPAL"

assert_command dfx canister info e2e_project_assets
assert_match "Controller: $BOB_PRINCIPAL"

assert_match "Controllers: $BOB_PRINCIPAL"

assert_command_fail dfx --identity alice deploy e2e_project_assets
assert_command_fail dfx --identity bob deploy e2e_project
Expand All @@ -163,3 +163,47 @@ teardown() {
assert_command dfx --identity bob deploy --no-wallet e2e_project_assets
}

@test "create canister with multiple controllers" {
dfx_start
dfx identity new alice
dfx identity new bob
ALICE_PRINCIPAL=$(dfx --identity alice identity get-principal)
BOB_PRINCIPAL=$(dfx --identity bob identity get-principal)
# awk step is to avoid trailing space
WALLETS_SORTED=$(echo "$ALICE_PRINCIPAL" "$BOB_PRINCIPAL" | tr " " "\n" | sort | tr "\n" " " | awk '{printf "%s %s",$1,$2}' )

assert_command dfx --identity alice canister create --all --controller alice --controller bob
assert_command dfx canister info e2e_project
assert_match "Controllers: ${WALLETS_SORTED}"

assert_command dfx --identity alice deploy --no-wallet
assert_command_fail dfx --identity bob deploy --no-wallet

# The certified assets canister will have added alice as an authorized user, because she was the caller
# at initialization time. Bob has to be added separately. BUT, the canister has to be deployed first
# in order to call the authorize method.
assert_command dfx --identity alice canister call e2e_project_assets authorize "(principal \"$BOB_PRINCIPAL\")"

assert_command dfx --identity bob deploy --no-wallet
}

@test "reports wallet must be upgraded if attempting to create a canister with multiple controllers through an old wallet" {
use_wallet_wasm 0.7.2

dfx_start
dfx identity new alice
dfx identity new bob
ALICE_PRINCIPAL=$(dfx --identity alice identity get-principal)
BOB_PRINCIPAL=$(dfx --identity bob identity get-principal)
# awk step is to avoid trailing space
WALLETS_SORTED=$(echo "$ALICE_PRINCIPAL" "$BOB_PRINCIPAL" | tr " " "\n" | sort | tr "\n" " " | awk '{printf "%s %s",$1,$2}' )

assert_command_fail dfx --identity alice canister create --all --controller alice --controller bob
assert_match "The wallet canister must be upgraded: The installed wallet does not support multiple controllers."
assert_match "To upgrade, run dfx wallet upgrade"

use_wallet_wasm 0.8.2
assert_command dfx --identity alice wallet upgrade
assert_command dfx --identity alice canister create --all --controller alice --controller bob
}

1 change: 1 addition & 0 deletions e2e/tests-dfx/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ let
ln -s $utils utils
ln -s $assets assets
ln -s $archive archive
mkdir test
ln -s $test test/test.bash
Expand Down
Loading

0 comments on commit f5131a1

Please sign in to comment.