diff --git a/.github/workflows/motoko-threshold-schnorr-example.yaml b/.github/workflows/motoko-threshold-schnorr-example.yaml index b5602a821..68e774f0d 100644 --- a/.github/workflows/motoko-threshold-schnorr-example.yaml +++ b/.github/workflows/motoko-threshold-schnorr-example.yaml @@ -21,9 +21,10 @@ jobs: run: bash .github/workflows/provision-darwin.sh - name: Motoko Threshold Schnorr Darwin run: | + dfxvm default 0.22.0-beta.0 dfx start --background + npm install @noble/curves pushd motoko/threshold-schnorr - make mock make test motoko-threshold-schnorr-linux: runs-on: ubuntu-20.04 @@ -33,7 +34,8 @@ jobs: run: bash .github/workflows/provision-linux.sh - name: Motoko Threshold Schnorr Linux run: | + dfxvm default 0.22.0-beta.0 dfx start --background + npm install @noble/curves pushd motoko/threshold-schnorr - make mock make test diff --git a/.github/workflows/rust-threshold-schnorr-example.yml b/.github/workflows/rust-threshold-schnorr-example.yml index 21697e62a..aed7e1eff 100644 --- a/.github/workflows/rust-threshold-schnorr-example.yml +++ b/.github/workflows/rust-threshold-schnorr-example.yml @@ -25,11 +25,13 @@ jobs: run: bash .github/workflows/provision-pocket-ic-server.sh - name: Rust Threshold Schnorr Darwin run: | + dfxvm default 0.22.0-beta.0 dfx start --background pushd rust/threshold-schnorr - make mock - sleep 10 - make test + make deploy +# This should be re-enabled when Pocket IC supports threshold Schnorr +# sleep 10 +# make test rust-threshold-schnorr-linux: runs-on: ubuntu-20.04 steps: @@ -40,8 +42,10 @@ jobs: run: bash .github/workflows/provision-pocket-ic-server.sh - name: Rust Threshold Schnorr Linux run: | + dfxvm default 0.22.0-beta.0 dfx start --background pushd rust/threshold-schnorr - make mock - sleep 10 - make test + make deploy +# This should be re-enabled when Pocket IC supports threshold Schnorr +# sleep 10 +# make test diff --git a/motoko/threshold-schnorr/Makefile b/motoko/threshold-schnorr/Makefile index d32e82059..3db31fe09 100644 --- a/motoko/threshold-schnorr/Makefile +++ b/motoko/threshold-schnorr/Makefile @@ -6,18 +6,9 @@ all: deploy deploy: dfx deploy -.PHONY: mock -.SILENT: mock -mock: deploy - SCHNORR_MOCK_CANISTER_ID=$(shell dfx canister id schnorr_canister); \ - SCHNORR_EXAMPLE_CANISTER_ID=$(shell dfx canister id schnorr_example_motoko); \ - echo "Changing to using mock canister instead of management canister for signing"; \ - CMD="dfx canister call "$${SCHNORR_EXAMPLE_CANISTER_ID}" for_test_only_change_management_canister_id '("\"$${SCHNORR_MOCK_CANISTER_ID}\"")'"; \ - eval "$${CMD}" - .PHONY: test .SILENT: test -test: mock +test: deploy bash test.sh hello .PHONY: clean diff --git a/motoko/threshold-schnorr/README.md b/motoko/threshold-schnorr/README.md index 78c0e13a7..8d90ca162 100644 --- a/motoko/threshold-schnorr/README.md +++ b/motoko/threshold-schnorr/README.md @@ -13,13 +13,6 @@ We present a minimal example canister smart contract for showcasing the Schnorr](https://org5p-7iaaa-aaaak-qckna-cai.icp0.io/docs#ic-sign_with_schnorr) API. -WARNING: the current version of this canister calls not the management canister -but a custom canister, which produces Schnorr signatures in an INSECURE way. -This is done for testing purposes ONLY and MUST NOT be done in production. In -production, ONLY the management canister API MUST be used. The reason is that -the management canister API is not yet fully implemented and instead of the -management canister we use a mock canister that provides Schnorr signatures. - The example canister is a signing oracle that creates Schnorr signatures with keys derived based on the canister ID and the chosen algorithm, either BIP340 or Ed25519. @@ -36,13 +29,16 @@ More specifically: This tutorial gives a complete overview of the development, starting with downloading [`dfx`](https://internetcomputer.org/docs/current/developer-docs/setup/index.md), up to the deployment and trying out the code on the mainnet. This walkthrough focuses on the version of the sample canister code written in -Motoko programming language.. There is also a +Motoko programming language. There is also a [Rust](https://github.com/dfinity/examples/tree/master/rust/threshold-schnorr) version available in the same repo and follows the same commands for deploying. ## Prerequisites -- [x] Download and [install the IC SDK](https://internetcomputer.org/docs/current/developer-docs/setup/index.md) if you do not already have it. +- [x] Download and [install the IC + SDK](https://internetcomputer.org/docs/current/developer-docs/setup/index.md) + if you do not already have it. For local testing, `dfx >= 0.22.0-beta.0` is + required. - [x] Clone the example dapp project: `git clone https://github.com/dfinity/examples` ## Getting started @@ -51,22 +47,30 @@ Sample code for `threshold-schnorr-example` is provided in the [examples reposit ### Deploy and test the canister locally -This tutorial will use the Motoko version of the canister: +This tutorial will use the Motoko version of the canister. + +To deploy: +```bash +cd examples/motoko/threshold-schnorr +dfx start --background +make deploy +``` +To test (includes deploying): ```bash cd examples/motoko/threshold-schnorr dfx start --background -npm install -make mock +npm install @noble/curves +make test ``` #### What this does - `dfx start --background` starts a local instance of the IC via the IC SDK -- `make mock` deploys the canister code on the local version of the IC and - updates the canister ID that produces Schnorr signatures (see the WARNING at - the beginning of this document) +- `make deploy` deploys the canister code on the local version of the IC +- `npm install @noble/curves` installs a test javascript dependency +- `make test` deploys and tests the canister code on the local version of the IC -If successful, you should see something like this: +If deployment was successful, you should see something like this: ```bash Deployed canisters. @@ -76,8 +80,8 @@ URLs: ``` If you open the URL in a web browser, you will see a web UI that shows the -public methods the canister exposes. Since the canister exposes `public_key`, -`sign`, and `verify` methods, those are rendered in the web UI. +public methods the canister exposes. Since the canister exposes `public_key` and +`sign`, those are rendered in the web UI. ### Deploying the canister on the mainnet @@ -116,7 +120,6 @@ key ID in `src/schnorr_example_motoko/src/main.mo` must be consistent. To [deploy via the mainnet](https://internetcomputer.org/docs/current/developer-docs/setup/deploy-mainnet.md), run the following commands: ```bash -npm install dfx deploy --network ic ``` If successful, you should see something like this: @@ -125,9 +128,15 @@ If successful, you should see something like this: Deployed canisters. URLs: Backend canister via Candid interface: - schnorr_example_motoko: https://a3gq9-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=736w4-cyaaa-aaaal-qb3wq-cai + schnorr_example_motoko: https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=enb64-iaaaa-aaaap-ahnkq-cai ``` +The implementation of this canister in Rust is (`schnorr_example_rust`) is +deployed on mainnet. It has the URL +https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=enb64-iaaaa-aaaap-ahnkq-cai +and serves up the Candid web UI for this particular canister deployed on +mainnet. + ## Obtaining public keys ### Using the Candid Web UI @@ -215,7 +224,11 @@ Computing threshold Schnorr signatures is the core functionality of this feature ## Signature verification -For completeness of the example, we show that the created signatures can be verified with the public key corresponding to the same canister and derivation path. +For completeness of the example, we show that the created signatures can be +verified with the public key corresponding to the same canister and derivation +path in javascript. Note that in contrast to the Rust implementation of this +example, the signature verification is not part of the canister API and happens +externally. Ed25519 can be verified as follows: ```javascript diff --git a/motoko/threshold-schnorr/dfx.json b/motoko/threshold-schnorr/dfx.json index 294bb4e48..831308eb8 100644 --- a/motoko/threshold-schnorr/dfx.json +++ b/motoko/threshold-schnorr/dfx.json @@ -5,11 +5,6 @@ "package": "schnorr_example_motoko", "main": "src/schnorr_example_motoko/main.mo", "type": "motoko" - }, - "schnorr_canister": { - "type": "custom", - "candid": "https://github.com/domwoe/schnorr_canister/releases/download/v0.4.0//schnorr_canister.did", - "wasm": "https://github.com/domwoe/schnorr_canister/releases/download/v0.4.0/schnorr_canister.wasm.gz" } } } diff --git a/motoko/threshold-schnorr/src/schnorr_example_motoko/main.mo b/motoko/threshold-schnorr/src/schnorr_example_motoko/main.mo index 6361c8812..b89b415d9 100644 --- a/motoko/threshold-schnorr/src/schnorr_example_motoko/main.mo +++ b/motoko/threshold-schnorr/src/schnorr_example_motoko/main.mo @@ -29,14 +29,6 @@ actor { var ic : IC = actor ("aaaaa-aa"); - public func for_test_only_change_management_canister_id(mock_id : Text) : async { - #Ok : (); - #Err : Text; - } { - ic := actor (mock_id); - #Ok(()); - }; - public shared ({ caller }) func public_key(algorithm_arg : SchnorrAlgorithm) : async { #Ok : { public_key_hex : Text }; #Err : Text; diff --git a/motoko/threshold-schnorr/test.sh b/motoko/threshold-schnorr/test.sh index eef7d7dca..4e110b2fa 100755 --- a/motoko/threshold-schnorr/test.sh +++ b/motoko/threshold-schnorr/test.sh @@ -10,27 +10,29 @@ function test_impl() { message="$1" echo message="$message" - ed25519_sign_cmd="dfx canister call schnorr_example_motoko sign '(\"${message}\" ,(variant { ed25519 }))'" - ed25519_sig_raw_output="$(eval ${ed25519_sign_cmd} | grep signature_hex)" - ed25519_sig_hex="$(get_text_in_double_quotes "${ed25519_sig_raw_output}")" - echo ed25519_signature_hex="$ed25519_sig_hex" +# This should be uncommented when dfx deploys an Ed25519 key - ed25519_public_key_raw_output="$(dfx canister call schnorr_example_motoko public_key '(variant { ed25519 })' | grep public_key_hex)" - ed25519_public_key_hex="$(get_text_in_double_quotes "${ed25519_public_key_raw_output}")" - echo ed25519_public_key_hex="$ed25519_public_key_hex" +# ed25519_sign_cmd="dfx canister call schnorr_example_motoko sign '(\"${message}\" ,(variant { ed25519 }))'" +# ed25519_sig_raw_output="$(eval ${ed25519_sign_cmd} | grep signature_hex)" +# ed25519_sig_hex="$(get_text_in_double_quotes "${ed25519_sig_raw_output}")" +# echo ed25519_signature_hex="$ed25519_sig_hex" - node < { verify(ed25519.ed25519); }) - .catch((err) => { console.log(err) }); +# ed25519_public_key_raw_output="$(dfx canister call schnorr_example_motoko public_key '(variant { ed25519 })' | grep public_key_hex)" +# ed25519_public_key_hex="$(get_text_in_double_quotes "${ed25519_public_key_raw_output}")" +# echo ed25519_public_key_hex="$ed25519_public_key_hex" - function verify(ed25519) { - const sig = '${ed25519_sig_hex}'; - const pubkey = '${ed25519_public_key_hex}'; - const msg = Uint8Array.from(Buffer.from("${message}", 'utf8')); +# node < { verify(ed25519.ed25519); }) +# .catch((err) => { console.log(err) }); - console.log(ed25519.verify(sig, msg, pubkey)); - } -END +# function verify(ed25519) { +# const sig = '${ed25519_sig_hex}'; +# const pubkey = '${ed25519_public_key_hex}'; +# const msg = Uint8Array.from(Buffer.from("${message}", 'utf8')); + +# console.log(ed25519.verify(sig, msg, pubkey)); +# } +# END bip340_sign_cmd="dfx canister call schnorr_example_motoko sign '(\"${message}\" ,(variant { bip340secp256k1 }))'" bip340_sig_raw_output="$(eval ${bip340_sign_cmd} | grep signature_hex)" @@ -57,10 +59,10 @@ END test_output=$(test_impl "$1") echo $test_output -if echo $test_output | grep "false"; then - echo "failed to validate signatures" - exit 1 -else +if echo $test_output | grep "true"; then echo "successfully validated signatures" exit 0 +else + echo "failed to validate signatures" + exit 1 fi diff --git a/rust/threshold-schnorr/Cargo.lock b/rust/threshold-schnorr/Cargo.lock index 0bc8a0ee2..acde75390 100644 --- a/rust/threshold-schnorr/Cargo.lock +++ b/rust/threshold-schnorr/Cargo.lock @@ -40,9 +40,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", @@ -123,12 +123,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.5.0" @@ -422,37 +416,12 @@ dependencies = [ "zeroize", ] -[[package]] -name = "encoding_rs" -version = "0.8.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" -dependencies = [ - "cfg-if", -] - [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "fastrand" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" - [[package]] name = "ff" version = "0.13.0" @@ -485,21 +454,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -736,22 +690,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.5" @@ -890,12 +828,6 @@ version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - [[package]] name = "log" version = "0.4.21" @@ -943,23 +875,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "native-tls" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1032,50 +947,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "openssl-probe" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -1136,12 +1013,6 @@ dependencies = [ "spki", ] -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - [[package]] name = "pocket-ic" version = "3.1.0" @@ -1262,13 +1133,12 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" -version = "0.12.4" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +checksum = "3e6cc1e89e689536eb5aeede61520e874df5a4707df811cd5da4aa5fbb2aae19" dependencies = [ "base64 0.22.1", "bytes", - "encoding_rs", "futures-channel", "futures-core", "futures-util", @@ -1278,13 +1148,11 @@ dependencies = [ "http-body-util", "hyper", "hyper-rustls", - "hyper-tls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -1296,9 +1164,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper", - "system-configuration", "tokio", - "tokio-native-tls", "tokio-rustls", "tokio-socks", "tokio-util", @@ -1352,19 +1218,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.38.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" -dependencies = [ - "bitflags 2.5.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - [[package]] name = "rustls" version = "0.22.4" @@ -1476,7 +1329,6 @@ dependencies = [ "ic-cdk", "k256", "pocket-ic", - "reqwest", "serde", "serde_bytes", "sha2", @@ -1502,7 +1354,7 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 2.5.0", + "bitflags", "core-foundation", "core-foundation-sys", "libc", @@ -1527,9 +1379,9 @@ checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] @@ -1545,9 +1397,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", @@ -1567,9 +1419,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -1717,39 +1569,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" -[[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 = "tempfile" -version = "3.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" -dependencies = [ - "cfg-if", - "fastrand", - "rustix", - "windows-sys 0.52.0", -] - [[package]] name = "thiserror" version = "1.0.56" @@ -1828,9 +1647,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", @@ -1842,16 +1661,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.25.0" @@ -2070,12 +1879,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.4" diff --git a/rust/threshold-schnorr/Makefile b/rust/threshold-schnorr/Makefile index d8a8df96d..07fd3fbfb 100644 --- a/rust/threshold-schnorr/Makefile +++ b/rust/threshold-schnorr/Makefile @@ -6,18 +6,9 @@ all: build deploy: dfx deploy -.PHONY: mock -.SILENT: mock -mock: deploy - SCHNORR_MOCK_CANISTER_ID=$(shell dfx canister id schnorr_canister); \ - SCHNORR_EXAMPLE_CANISTER_ID=$(shell dfx canister id schnorr_example_rust); \ - echo "Changing to using mock canister instead of management canister for signing"; \ - CMD="dfx canister call "$${SCHNORR_EXAMPLE_CANISTER_ID}" for_test_only_change_management_canister_id '("\"$${SCHNORR_MOCK_CANISTER_ID}\"")'"; \ - eval "$${CMD}" - .PHONY: test .SILENT: test -test: mock +test: cargo test .PHONY: clean diff --git a/rust/threshold-schnorr/README.md b/rust/threshold-schnorr/README.md index 34ee7c3b8..6e39c33fe 100644 --- a/rust/threshold-schnorr/README.md +++ b/rust/threshold-schnorr/README.md @@ -13,13 +13,6 @@ We present a minimal example canister smart contract for showcasing the Schnorr](https://org5p-7iaaa-aaaak-qckna-cai.icp0.io/docs#ic-sign_with_schnorr) API. -WARNING: the current version of this canister calls not the management canister -but a custom canister, which produces Schnorr signatures in an INSECURE way. -This is done for testing purposes ONLY and MUST NOT be done in production. In -production, ONLY the management canister API MUST be used. The reason is that -the management canister API is not yet fully implemented and instead of the -management canister we use a mock canister that provides Schnorr signatures. - The example canister is a signing oracle that creates Schnorr signatures with keys derived based on the canister ID and the chosen algorithm, either BIP340 or Ed25519. @@ -42,29 +35,29 @@ version available in the same repo and follows the same commands for deploying. ## Prerequisites -- [x] Download and [install the IC SDK](https://internetcomputer.org/docs/current/developer-docs/setup/index.md) if you do not already have it. +- [x] Download and [install the IC + SDK](https://internetcomputer.org/docs/current/developer-docs/setup/index.md) + if you do not already have it. For local testing, `dfx >= 0.22.0-beta.0` is + required. - [x] Clone the example dapp project: `git clone https://github.com/dfinity/examples` ## Getting started Sample code for `threshold-schnorr-example` is provided in the [examples repository](https://github.com/dfinity/examples), under either [`/motoko`](https://github.com/dfinity/examples/tree/master/motoko/threshold-schnorr) or [`/rust`](https://github.com/dfinity/examples/tree/master/rust/threshold-schnorr) sub-directories. -### Deploy and test the canister locally +### Deploy the canister locally This tutorial will use the Rust version of the canister: ```bash cd examples/rust/threshold-schnorr dfx start --background -npm install -make mock +make deploy ``` #### What this does - `dfx start --background` starts a local instance of the IC via the IC SDK -- `make mock` deploys the canister code on the local version of the IC and - updates the canister ID that produces Schnorr signatures (see the WARNING at - the beginning of this document) +- `make deploy` deploys the canister code on the local version of the IC If successful, you should see something like this: @@ -117,7 +110,6 @@ Both uses of key ID in `src/schnorr_example_rust/src/lib.rs` must be consistent. To [deploy via the mainnet](https://internetcomputer.org/docs/current/developer-docs/setup/deploy-mainnet.md), run the following commands: ```bash -npm install dfx deploy --network ic ``` If successful, you should see something like this: @@ -126,10 +118,10 @@ If successful, you should see something like this: Deployed canisters. URLs: Backend canister via Candid interface: - schnorr_example_rust: https://a3gq9-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=736w4-cyaaa-aaaal-qb3wq-cai + schnorr_example_rust: https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=enb64-iaaaa-aaaap-ahnkq-cai ``` -# In the example above, `schnorr_example_rust` has the URL https://a3gq9-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=736w4-cyaaa-aaaal-qb3wq-cai and serves up the Candid web UI for this particular canister deployed on mainnet. +In the example above, `schnorr_example_rust` has the URL https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=enb64-iaaaa-aaaap-ahnkq-cai and serves up the Candid web UI for this particular canister deployed on mainnet. ## Obtaining public keys @@ -165,7 +157,7 @@ async fn public_key(algorithm: SchnorrAlgorithm) -> Result Result (variant { Ok: null; Err: text }); public_key : (SchnorrAlgorithm) -> (variant { Ok: record { public_key_hex: text; }; Err: text }); sign : (text, SchnorrAlgorithm) -> (variant { Ok: record { signature_hex: text; }; Err: text }); verify : (text, text, text, SchnorrAlgorithm) -> (variant { Ok: record { is_signature_valid: bool; }; Err: text }); diff --git a/rust/threshold-schnorr/src/schnorr_example_rust/src/wasm_only.rs b/rust/threshold-schnorr/src/schnorr_example_rust/src/wasm_only.rs index 576a2bee2..1aa02d4db 100644 --- a/rust/threshold-schnorr/src/schnorr_example_rust/src/wasm_only.rs +++ b/rust/threshold-schnorr/src/schnorr_example_rust/src/wasm_only.rs @@ -1,10 +1,8 @@ +use super::{PublicKeyReply, SchnorrAlgorithm, SignatureReply, SignatureVerificationReply}; use candid::{CandidType, Principal}; use ic_cdk::{query, update}; use serde::{Deserialize, Serialize}; -use std::cell::RefCell; -use std::convert::TryFrom; -use std::convert::TryInto; -use super::{PublicKeyReply, SchnorrAlgorithm, SignatureReply, SignatureVerificationReply}; +use std::convert::{TryFrom, TryInto}; type CanisterId = Principal; @@ -39,23 +37,6 @@ struct ManagementCanisterSignatureReply { pub signature: Vec, } -thread_local! { - static STATE: RefCell = RefCell::new("aaaaa-aa".to_string()); -} - -#[update] -async fn for_test_only_change_management_canister_id(id: String) -> Result<(), String> { - let _ = CanisterId::from_text(&id).map_err(|e| panic!("invalid canister id: {}: {}", id, e)); - STATE.with_borrow_mut(move |current_id| { - println!( - "Changing management canister id from {} to {id}", - *current_id - ); - *current_id = id; - }); - Ok(()) -} - #[update] async fn public_key(algorithm: SchnorrAlgorithm) -> Result { let request = ManagementCanisterSchnorrPublicKeyRequest { @@ -64,10 +45,13 @@ async fn public_key(algorithm: SchnorrAlgorithm) -> Result Result CanisterId { - STATE.with_borrow(|state| CanisterId::from_text(&state).unwrap()) -} - enum SchnorrKeyIds { #[allow(unused)] TestKeyLocalDevelopment, diff --git a/rust/threshold-schnorr/src/schnorr_example_rust/tests/tests.rs b/rust/threshold-schnorr/src/schnorr_example_rust/tests/tests.rs index cace153d4..5600b14af 100644 --- a/rust/threshold-schnorr/src/schnorr_example_rust/tests/tests.rs +++ b/rust/threshold-schnorr/src/schnorr_example_rust/tests/tests.rs @@ -23,18 +23,6 @@ fn signing_and_verification_should_work_correctly() { fn test_impl(pic: &PocketIc, algorithm: SchnorrAlgorithm) { let my_principal = Principal::anonymous(); - // Create an empty canister as the anonymous principal and add cycles. - let schnorr_mock_canister_id = pic.create_canister(); - pic.add_cycles(schnorr_mock_canister_id, 2_000_000_000_000); - - let schnorr_mock_wasm_bytes = load_schnorr_mock_canister_wasm(); - pic.install_canister( - schnorr_mock_canister_id, - schnorr_mock_wasm_bytes, - vec![], - None, - ); - // Create an empty example canister as the anonymous principal and add cycles. let example_canister_id = pic.create_canister(); pic.add_cycles(example_canister_id, 2_000_000_000_000); @@ -45,19 +33,6 @@ fn test_impl(pic: &PocketIc, algorithm: SchnorrAlgorithm) { // Make sure the canister is properly initialized fast_forward(&pic, 5); - let _dummy_reply: () = update( - &pic, - my_principal, - example_canister_id, - "for_test_only_change_management_canister_id", - encode_one(schnorr_mock_canister_id.to_text()).unwrap(), - ) - .expect("failed to update management canister id"); - - // Make sure the example canister uses mock schnorr canister instead of - // the management canister - fast_forward(&pic, 5); - let message_hex = hex::encode("Test message"); let sig_reply: Result = update( @@ -201,15 +176,6 @@ fn load_schnorr_example_canister_wasm() -> Vec { zipped_bytes } -fn load_schnorr_mock_canister_wasm() -> Vec { - let wasm_url = "https://github.com/domwoe/schnorr_canister/releases/download/v0.4.0/schnorr_canister.wasm.gz"; - reqwest::blocking::get(wasm_url) - .unwrap() - .bytes() - .unwrap() - .to_vec() -} - pub fn update Deserialize<'de>>( ic: &PocketIc, sender: Principal,