Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

== DFX

=== feat: add --no-wallet flag and --wallet option to allow Users to bypass Wallet or specify a Wallet to use for calls (#1476)

Added `--no-wallet` flag to `dfx canister` and `dfx deploy`. This allows users to call canister management functionality with their Identity as the Sender (bypassing their Wallet canister.)
Added `--wallet` option to `dfx canister` and `dfx deploy`. This allows users to specify a wallet canister id to use as the Sender for calls.
`--wallet` and `--no-wallet` conflict with each other. Omitting both will invoke the selected Identity's wallet canister to perform calls.

=== feat: implement the HTTP Request proposal in dfx' bootstrap webserver. +
And add support for http requests in the base storage canister (with a default to `/index.html`).

Expand Down
7 changes: 7 additions & 0 deletions e2e/assets/initializer/initializer.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Error "mo:base/Error";

shared ({caller = initializer}) actor class() {
public shared (message) func test(): async Bool {
message.caller == initializer
}
}
1 change: 1 addition & 0 deletions e2e/assets/initializer/patch.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dfx config canisters/e2e_project/main initializer.mo
19 changes: 17 additions & 2 deletions e2e/tests-dfx/basic-project.bash
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,19 @@ teardown() {
assert_eq '("Hello, Bongalo!")'

# Using call --async and request-status.
assert_command dfx canister call --async hello greet Blueberry
# Call with user Identity as Sender
assert_command dfx canister --no-wallet call --async hello greet Blueberry
# At this point $output is the request ID.
# shellcheck disable=SC2154
assert_command dfx canister request-status "$stdout"
assert_eq '("Hello, Blueberry!")'

# Call using the wallet's call forwarding
assert_command dfx canister call --async hello greet Blueberry
# At this point $output is the request ID.
# shellcheck disable=SC2154
assert_command dfx canister request-status "$stdout"
assert_eq '(record { 153_986_224 = blob "DIDL\00\01q\11Hello, Blueberry!" })'
}

@test "build + install + call + request-status -- counter_mo" {
Expand Down Expand Up @@ -79,9 +87,16 @@ teardown() {
assert_eq "()"

# Write has no return value. But we can _call_ read too.
assert_command dfx canister call hello read --async
# Call with user Identity as Sender
assert_command dfx canister --no-wallet call hello read --async
assert_command dfx canister request-status "$stdout"
assert_eq "(1_337)"

# Call using the wallet's call forwarding
assert_command dfx canister call hello read --async
assert_command dfx canister request-status "$stdout"
assert_eq '(record { 153_986_224 = blob "DIDL\00\01}\b9\0a" })'

}

@test "build + install + call -- counter_idl_mo" {
Expand Down
5 changes: 4 additions & 1 deletion e2e/tests-dfx/certificate.bash
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ teardown() {
}

@test "mitm attack - query: attack succeeds because there is no certificate to verify" {
assert_command dfx canister call certificate hello_query '("Buckaroo")'
# 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
assert_command dfx canister --no-wallet call certificate hello_query '("Buckaroo")'
assert_eq '("Hullo, Buckaroo!")'
}
27 changes: 16 additions & 11 deletions e2e/tests-dfx/identity.bash
Original file line number Diff line number Diff line change
Expand Up @@ -88,27 +88,32 @@ teardown() {
assert_command dfx --identity alice build
assert_command dfx --identity alice canister install --all

# The wallet is the initializer
assert_command dfx --identity alice canister call e2e_project amInitializer
assert_eq '(true)'

# The user Identity's principal is not the initializer
assert_command dfx --identity alice canister --no-wallet call e2e_project amInitializer
assert_eq '(false)'

assert_command dfx --identity alice canister call \
assert_command dfx --identity alice canister --no-wallet call \
"$(dfx --identity alice identity get-wallet)" wallet_call \
"(record { canister = principal \"$(dfx canister id e2e_project)\"; method_name = \"amInitializer\"; args = blob \"DIDL\00\00\"; cycles = (0:nat64)})"
assert_eq '(record { 153_986_224 = blob "DIDL\00\01~\01" })' # True in DIDL.

assert_command dfx --identity bob canister call e2e_project amInitializer
assert_command dfx --identity bob canister --no-wallet call e2e_project amInitializer
assert_eq '(false)'

# these all fail (other identities are not initializer; cannot store assets):
assert_command_fail dfx --identity bob canister call e2e_project_assets store '("B", vec { 88; 87; 86 })'
assert_command_fail dfx --identity default canister call e2e_project_assets store '("B", vec { 88; 87; 86 })'
assert_command_fail dfx canister call e2e_project_assets store '("B", vec { 88; 87; 86 })'
assert_command_fail dfx canister call e2e_project_assets retrieve '("B")'
assert_command_fail dfx --identity bob canister --no-wallet call e2e_project_assets store '("B", vec { 88; 87; 86 })'
assert_command_fail dfx --identity default canister --no-wallet call e2e_project_assets store '("B", vec { 88; 87; 86 })'
assert_command_fail dfx canister --no-wallet call e2e_project_assets store '("B", vec { 88; 87; 86 })'
assert_command_fail dfx canister --no-wallet call e2e_project_assets retrieve '("B")'

# but alice, the initializer, can store assets:
assert_command dfx --identity alice canister call e2e_project_assets store '("B", vec { 88; 87; 86 })'
assert_eq '()'
assert_command dfx canister call --output idl e2e_project_assets retrieve '("B")'
assert_command dfx canister --no-wallet call --output idl e2e_project_assets retrieve '("B")'
assert_eq '(blob "XWV")'
}

Expand All @@ -120,24 +125,24 @@ teardown() {
dfx --identity alice canister create --all
assert_command dfx --identity alice build
assert_command dfx --identity alice canister install --all
assert_command dfx --identity alice canister call \
assert_command dfx --identity alice canister --no-wallet call \
"$(dfx --identity alice identity get-wallet)" wallet_call \
"(record { canister = principal \"$(dfx canister id e2e_project)\"; method_name = \"amInitializer\"; args = blob \"DIDL\00\00\"; cycles = (0:nat64)})"
assert_eq '(record { 153_986_224 = blob "DIDL\00\01~\01" })' # True in DIDL.
assert_command dfx canister call e2e_project amInitializer
assert_command dfx canister --no-wallet call e2e_project amInitializer
assert_eq '(false)'

assert_command dfx identity rename alice bob

assert_command dfx identity whoami
assert_eq 'default'
assert_command dfx --identity bob canister call \
assert_command dfx --identity bob canister --no-wallet call \
"$(dfx --identity bob identity get-wallet)" wallet_call \
"(record { canister = principal \"$(dfx canister id e2e_project)\"; method_name = \"amInitializer\"; args = blob \"DIDL\00\00\"; cycles = (0:nat64)})"
assert_eq '(record { 153_986_224 = blob "DIDL\00\01~\01" })' # True in DIDL.

assert_command dfx --identity bob canister call e2e_project_assets store '("B", blob "hello")'
assert_eq '()'
assert_command dfx canister call --output idl e2e_project_assets retrieve '("B")'
assert_command dfx canister --no-wallet call --output idl e2e_project_assets retrieve '("B")'
assert_eq '(blob "hello")'
}
40 changes: 40 additions & 0 deletions e2e/tests-dfx/initializer.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env bats

load ../utils/_

setup() {
# We want to work from a temporary directory, different for every test.
cd "$(mktemp -d -t dfx-e2e-XXXXXXXX)" || exit

# Each test gets its own home directory in order to have its own identities.
x=$(pwd)/home-for-test
mkdir "$x"
export HOME="$x"

dfx_new
}

teardown() {
dfx_stop
x=$(pwd)/home-for-test
rm -rf "$x"
}

@test "test access control flow via dfx call" {
install_asset initializer
dfx_start
assert_command dfx identity new alice
assert_command dfx identity use alice

dfx canister create --all
assert_command dfx build
assert_command dfx canister install --all

# The wallet is the initializer
assert_command dfx canister call e2e_project test
assert_eq '(true)'

# The user Identity's principal is not the initializer
assert_command dfx canister --no-wallet call e2e_project test
assert_eq '(false)'
}
36 changes: 34 additions & 2 deletions e2e/tests-dfx/wallet.bash
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ setup() {
x=$(pwd)/home-for-test
mkdir "$x"
export HOME="$x"

dfx_new
}

teardown() {
Expand All @@ -21,6 +19,7 @@ teardown() {
}

@test "deploy wallet" {
dfx_new hello
dfx_start
setup_actuallylocal_network

Expand All @@ -45,3 +44,36 @@ teardown() {
assert_command dfx identity --network actuallylocal deploy-wallet "${ID_TWO}"
assert_match "The wallet canister \"${ID}\"\ already exists for user \"default\" on \"actuallylocal\" network."
}

@test "bypass wallet call as user" {
dfx_new
install_asset identity
dfx_start
assert_command dfx canister --no-wallet create --all
assert_command dfx build
assert_command dfx canister --no-wallet install --all

CALL_RES=$(dfx canister --no-wallet call e2e_project fromCall)
CALLER=$(echo "${CALL_RES}" | cut -d'"' -f 2)
ID=$(dfx identity get-principal)
assert_eq "$CALLER" "$ID"

assert_command dfx canister --no-wallet call e2e_project amInitializer
assert_eq '(true)'
}

@test "bypass wallet call as user: deploy" {
dfx_new
install_asset identity
dfx_start
assert_command dfx deploy --no-wallet

CALL_RES=$(dfx canister --no-wallet call e2e_project fromCall)
CALLER=$(echo "${CALL_RES}" | cut -d'"' -f 2)
ID=$(dfx identity get-principal)
assert_eq "$CALLER" "$ID"

assert_command dfx canister --no-wallet call e2e_project amInitializer
assert_eq '(true)'
}

Loading