Skip to content

Commit

Permalink
Ckbtc install (#121)
Browse files Browse the repository at this point in the history
# Motivation
We would like to have e2e tests for ckbtc functionality in the nns-dapp
repo.

# Changes
- Add a CKBTC deployment script
- This is the script from the nns-dapp repo, with variables such as
network taken from command line flags.
- Include ckbtc canisters in the stock snapshot

# Tests
* The ckbtc deployment contains a self-test. Additionally, there is a
set of tests for the self-test itself.

---------

Co-authored-by: Max Murphy-Skvorzov <[email protected]>
Co-authored-by: Formatting Committer <[email protected]>
  • Loading branch information
3 people authored Apr 20, 2023
1 parent f18cd26 commit 6b204fd
Show file tree
Hide file tree
Showing 5 changed files with 260 additions and 5 deletions.
33 changes: 28 additions & 5 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,35 @@ jobs:
uses: ludeeus/action-shellcheck@master
env:
SHELLCHECK_OPTS: -e SC1090 -e SC2119 -e SC1091 -e SC2121 -e SC2155 -e SC2094 -e SC2015
clap-checks:
needs: formatting
name: Clap checks
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Clap works
run: ./bin/clap.test
ckbtc-checks:
needs: formatting
name: CKBTC tools
runs-on: ubuntu-20.04
steps:
- name: Install apt-dependencies
run: sudo apt-get update && sudo apt-get install moreutils -yy && command -v more
- uses: actions/checkout@v3
- name: Install dfx
run: ./bin/dfx-software-dfx-install --version "$(jq -r .dfx dfx.json)"
- name: Import ckbtc works
run: |
set -euxo pipefail
echo "This modifies files, so make sure the state is clean before and after"
git clean -dfx
bin/dfx-ckbtc-import.test
git clean -dfx
set -euxo pipefail
echo "This modifies files, so make sure the state is clean before and after"
git clean -dfx
bin/dfx-ckbtc-import.test
git clean -dfx
- name: Deploy ckbtc works
run: |
set -euxo pipefail
echo "This modifies files, so make sure the state is clean before and after"
git clean -dfx
bin/dfx-ckbtc-deploy.test
git clean -dfx
44 changes: 44 additions & 0 deletions bin/dfx-canister-check-wasm-hash
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env bash
set -euo pipefail
SOURCE_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
PATH="$SOURCE_DIR:$PATH"

print_help() {
cat <<-EOF
Checks that a deployed canister's hash matches a local WASM.
If a deployment succeeded, the wasms must match.
This will not detect whether the canister arguments were as expected.
EOF
}

# Source the clap.bash file ---------------------------------------------------
source "$SOURCE_DIR/clap.bash"
# Define options
clap.define short=n long=network desc="The dfx network to use" variable=DFX_NETWORK default="local"
clap.define short=c long=canister desc="The canister name or ID" variable=DFX_CANISTER
clap.define short=w long=wasm desc="The path to the local wasm file" variable=DFX_WASM
# Source the output file ----------------------------------------------------------
source "$(clap.build)"

# If the location of the wasm was not supplied, get the default location specified in dfx.json
DFX_WASM="${DFX_WASM:-$(n="$DFX_CANISTER" jq -r '.canisters[env.n].wasm' dfx.json)}"
test -e "${DFX_WASM:-}" || {
echo "ERROR: Wasm not found at '${DFX_WASM:-}'"
echo " Please check and specify the correct path."
exit 1
} >&2

build_hash="$(sha256sum "$DFX_WASM" | awk '{print $1}')"
deployed_hash="$(dfx canister info "$DFX_CANISTER" --network "$DFX_NETWORK" | awk '/Module hash/{print $3}')"
if [[ "0x$build_hash" == "$deployed_hash" ]]; then
echo "Check passed: Installed $DFX_CANISTER matches local wasm."
else
{
echo "ERROR: Deployed $DFX_CANISTER hash does not match."
echo "Local build: 0x$build_hash"
echo "Deployed: $deployed_hash"
exit 1
} >&2
fi
111 changes: 111 additions & 0 deletions bin/dfx-ckbtc-deploy
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/usr/bin/env bash
# Original source: https://github.com/dfinity/ckBTC-Minter-Frontend/blob/master/local_deploy.sh
# Via: https://github.com/dfinity/nns-dapp/blob/main/scripts/ckbtc/deploy-ckbtc
set -euo pipefail
SOURCE_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
PATH="$SOURCE_DIR:$PATH"
. "$SOURCE_DIR/versions.bash"

print_help() {
cat <<-EOF
Installs ckbtc canisters.
EOF
}

# Source the clap.bash file ---------------------------------------------------
source "$SOURCE_DIR/clap.bash"
# Define options
clap.define short=n long=network desc="The dfx network to use" variable=DFX_NETWORK default="local"
clap.define short=p long=prefix desc="Prefix for the local canister names" variable=LOCAL_PREFIX default="ckbtc_"
clap.define short=y long=yes desc="Deploy even if there are existing ckbtc canisters." variable=DFX_YES nargs=0
clap.define short=c long=check desc="Check that the canisters are present and correct." variable=DFX_CHECK nargs=0
clap.define short=m long=mode desc="Canister install mode." variable=DFX_MODE default="reinstall"
# Source the output file ----------------------------------------------------------
source "$(clap.build)"

: Check preconditions. This is always run.
"${SOURCE_DIR}/dfx-ckbtc-import" --check --prefix "$LOCAL_PREFIX" || {
echo "ERROR: ckbtc canister data and files are not all present and correct."
echo " Please run:"
echo " dfx-ckbtc-import --prefix '$LOCAL_PREFIX'"
echo
exit 1
} >&2

deploy_ckbtc() {
dfx canister create "${LOCAL_PREFIX}ledger" --network "$DFX_NETWORK" || echo "${LOCAL_PREFIX}ledger canister already exists"
dfx canister create "${LOCAL_PREFIX}minter" --network "$DFX_NETWORK" || echo "${LOCAL_PREFIX}minter canister already exists"

MINTERID="$(dfx canister id "${LOCAL_PREFIX}minter" --network "$DFX_NETWORK")"
echo "$MINTERID"
LEDGERID="$(dfx canister id "${LOCAL_PREFIX}ledger" --network "$DFX_NETWORK")"
echo "$LEDGERID"

# echo "Step 2: deploying minter canister..."
dfx deploy "${LOCAL_PREFIX}minter" --network "$DFX_NETWORK" --argument "(variant {
Init = record {
btc_network = variant { Regtest };
ledger_id = principal \"$LEDGERID\";
ecdsa_key_name = \"dfx_test_key\";
retrieve_btc_min_amount = 0;
max_time_in_queue_nanos = 420_000_000_000;
min_confirmations = opt 12;
mode = variant { GeneralAvailability };
kyt_fee = opt 13_333;
kyt_principal = null;
}
})" --mode="${DFX_MODE}" ${DFX_YES:+--yes} --upgrade-unchanged

echo "Step 3: deploying ledger canister..."
PRINCIPAL="$(dfx identity get-principal)"
dfx deploy "${LOCAL_PREFIX}ledger" --network "$DFX_NETWORK" --argument "(variant {
Init = record {
token_symbol = \"ckBTC\";
token_name = \"Token ckBTC\";
minting_account = record { owner = principal \"$MINTERID\" };
transfer_fee = 11_500;
metadata = vec {};
initial_balances = vec { record { record { owner = principal \"$PRINCIPAL\"; }; 10_000_000; }; };
archive_options = record {
num_blocks_to_archive = 10_000;
trigger_threshold = 20_000;
controller_id = principal \"$PRINCIPAL\";
cycles_for_archive_creation = opt 4_000_000_000_000;
};
}
})" --mode="$DFX_MODE" ${DFX_YES:+--yes} --upgrade-unchanged

echo "Step 4: deploying index canister..."
dfx deploy "${LOCAL_PREFIX}index" --network "$DFX_NETWORK" --argument "(record { ledger_id = principal \"$LEDGERID\" })" --mode="${DFX_MODE}" ${DFX_YES:+--yes} --upgrade-unchanged

# Example to mint ckBTC

# BTCADDRESS="$(dfx canister call "${LOCAL_PREFIX}minter" get_btc_address '(record {subaccount=null;})')"
# dfx canister call "${LOCAL_PREFIX}minter" update_balance '(record {subaccount=null;})'
# WITHDRAWALADDRESS="$(dfx canister call "${LOCAL_PREFIX}minter" get_withdrawal_account)"
# echo $BTCADDRESS
# echo $WITHDRAWALADDRESS
#
# cleaned_output=$(echo $WITHDRAWALADDRESS | sed -re 's/^\(|, \)$//g')
#
# dfx canister call "${LOCAL_PREFIX}ledger" icrc1_transfer "(record {from=null; to=$cleaned_output; amount=1000000; fee=null; memo=null; created_at_time=null;})"
#
# Execute the command to get the input string and save the result
# dfx canister call "${LOCAL_PREFIX}minter" retrieve_btc '(record {fee = null; address="bcrt1qu9za0uzzd3kjjecgv7waqq0ynn8dl8l538q0xl"; amount=10000})'

echo "Step 5: transfer ckBTC to principal..."
# record { owner= principal “”;}
dfx canister call "${LOCAL_PREFIX}ledger" --network "$DFX_NETWORK" icrc1_transfer "(record {from=null; to=record { owner= principal \"73avq-yvrvj-kuzxq-kttlj-nkaz4-tecy6-biuud-3ymeg-guvci-naire-uqe\";}; amount=1000000; fee=null; memo=null; created_at_time=null;})"
}

check_ckbtc_deployment() {
for canister in "${LOCAL_PREFIX}ledger" "${LOCAL_PREFIX}minter"; do
: "Verify that the deployed canister matches the local wasm"
dfx-canister-check-wasm-hash --canister "$canister"
done
}

[[ "${DFX_CHECK:-}" == "true" ]] || deploy_ckbtc
check_ckbtc_deployment
73 changes: 73 additions & 0 deletions bin/dfx-ckbtc-deploy.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env bash
set -euo pipefail
SOURCE_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
PATH="$SOURCE_DIR:$PATH"

(
printf "\n\n===================================\n"
echo "Should fail if ckbtc canisters have not been imported"
git checkout dfx.json
error_log="$(mktemp ,test_log.XXXXXXXX)"
if dfx-ckbtc-deploy --check 2>"$error_log"; then
echo "ERROR: Should fail if ckbtc canisters are not in dfx.json"
exit 1
fi
grep 'ckbtc canister data and files are not all present and correct' "$error_log" || {
echo "The check should complain about ckbtc canisters missing in dfx.json"
exit 1
}
rm "$error_log"
)
(
printf "\n\n===================================\n"
echo "Should fail if ckbtc canisters have not been created"
dfx-network-stop
dfx start --clean --background
git checkout dfx.json
dfx-ckbtc-import
error_log="$(mktemp ,test_log.XXXXXXXX)"
if dfx-ckbtc-deploy --check 2>"$error_log"; then
echo "ERROR: Should fail if ckbtc canisters are not in dfx.json"
fi
grep 'Failed to determine id for canister' "$error_log" || {
echo "The check should complain about missing canisters"
exit 1
}
rm "$error_log"
dfx-network-stop
)
(
printf "\n\n===================================\n"
echo "Should fail if ckbtc canisters have not been populated"
dfx-network-stop
dfx start --clean --background
git checkout dfx.json
dfx-ckbtc-import
dfx canister create "ckbtc_ledger" --no-wallet
dfx canister create "ckbtc_minter" --no-wallet
error_log="$(mktemp ,test_log.XXXXXXXX)"
if dfx-ckbtc-deploy --check 2>"$error_log"; then
echo "ERROR: Should fail if ckbtc canisters have the incorrect or no hash"
fi
grep 'ERROR: Deployed ckbtc_ledger hash does not match.' "$error_log" || {
echo "ERROR: The check should complain about missing canisters."
echo "Actual error output:"
sed 's/^/ /g' "$error_log"
exit 1
}
rm "$error_log"
dfx-network-stop
)
(
printf "\n\n===================================\n"
echo "Should succeed if canisters have been deployed"
dfx-network-stop
dfx start --clean --background
git checkout dfx.json
dfx-ckbtc-import
dfx-ckbtc-deploy --yes
dfx-ckbtc-deploy --check
dfx-network-stop
)

printf "\n\n\nckbtc tests passed.\n"
4 changes: 4 additions & 0 deletions bin/dfx-snapshot-stock-make
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ source "$(clap.build)"
: Set up SNS state and create one finalized SNS
dfx-sns-demo

: Set up ckbtc canisters
dfx-ckbtc-import --prefix ckbtc_
dfx-ckbtc-deploy --prefix ckbtc_ --yes

: "Wait for a checkpoint"
dfx-network-wait-for-checkpoint --timeout 600

Expand Down

0 comments on commit 6b204fd

Please sign in to comment.