Skip to content

Commit

Permalink
Merge pull request #934 from dfinity/alex/rm-mock-from-schnorr-canister
Browse files Browse the repository at this point in the history
CRP-2532 remove mock API from Schnorr example since dfx now supports Schnorr
  • Loading branch information
altkdf authored Jul 23, 2024
2 parents c7cbd1c + 2a18064 commit 37e2e3b
Show file tree
Hide file tree
Showing 15 changed files with 107 additions and 383 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/motoko-threshold-schnorr-example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
16 changes: 10 additions & 6 deletions .github/workflows/rust-threshold-schnorr-example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
11 changes: 1 addition & 10 deletions motoko/threshold-schnorr/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
55 changes: 34 additions & 21 deletions motoko/threshold-schnorr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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.
Expand All @@ -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

Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
5 changes: 0 additions & 5 deletions motoko/threshold-schnorr/dfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
}
8 changes: 0 additions & 8 deletions motoko/threshold-schnorr/src/schnorr_example_motoko/main.mo
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
44 changes: 23 additions & 21 deletions motoko/threshold-schnorr/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 <<END
import('@noble/curves/ed25519').then((ed25519) => { 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 <<END
# import('@noble/curves/ed25519').then((ed25519) => { 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)"
Expand All @@ -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
Loading

0 comments on commit 37e2e3b

Please sign in to comment.