From f52e35394efee44c3f7ace6713e9c6ff840d5352 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Fri, 29 May 2026 12:25:00 +0200 Subject: [PATCH 01/14] chore(vetkeys): migrate basic_bls_signing to icp-cli and @icp-sdk/vetkeys - Replace dfx.json with icp.yaml (Rust and Motoko backends) - Use @icp-sdk/vetkeys@0.5.0-beta.0 instead of @dfinity/vetkeys - Use @icp-sdk/auth@7.1.0 and @icp-sdk/core@5.4.0 - Update Motoko ic-vetkeys to 0.5.0, Rust ic-vetkeys to 0.7.0 - Add moc 1.5.1 toolchain to mops.toml - Replace dfx generate with @icp-sdk/bindgen in gen_bindings.sh - Add CI workflow for both Rust and Motoko backends - Drop icp.ninja support (dfx.json removed) Co-Authored-By: Claude Sonnet 4.6 --- ...rust-vetkeys-basic-bls-signing-example.yml | 104 ++++++++++++++++++ rust/vetkeys/basic_bls_signing/README.md | 28 +++-- .../basic_bls_signing/frontend/package.json | 13 ++- .../frontend/scripts/gen_bindings.sh | 20 ++-- .../basic_bls_signing/frontend/src/main.ts | 76 ++++++------- .../basic_bls_signing/frontend/vite.config.ts | 74 ++++++++----- .../motoko/backend/src/Main.mo | 14 +-- .../vetkeys/basic_bls_signing/motoko/dfx.json | 51 --------- .../vetkeys/basic_bls_signing/motoko/icp.yaml | 22 ++++ .../basic_bls_signing/motoko/mops.toml | 9 +- .../basic_bls_signing/rust/backend/Cargo.toml | 2 +- .../basic_bls_signing/rust/backend/Makefile | 2 +- rust/vetkeys/basic_bls_signing/rust/dfx.json | 45 -------- rust/vetkeys/basic_bls_signing/rust/icp.yaml | 23 ++++ 14 files changed, 279 insertions(+), 204 deletions(-) create mode 100644 .github/workflows/rust-vetkeys-basic-bls-signing-example.yml delete mode 100644 rust/vetkeys/basic_bls_signing/motoko/dfx.json create mode 100644 rust/vetkeys/basic_bls_signing/motoko/icp.yaml delete mode 100644 rust/vetkeys/basic_bls_signing/rust/dfx.json create mode 100644 rust/vetkeys/basic_bls_signing/rust/icp.yaml diff --git a/.github/workflows/rust-vetkeys-basic-bls-signing-example.yml b/.github/workflows/rust-vetkeys-basic-bls-signing-example.yml new file mode 100644 index 000000000..c76ae77bc --- /dev/null +++ b/.github/workflows/rust-vetkeys-basic-bls-signing-example.yml @@ -0,0 +1,104 @@ +name: rust-vetkeys-basic-bls-signing +on: + push: + branches: + - master + pull_request: + paths: + - rust/vetkeys/basic_bls_signing/** + - .github/workflows/provision-darwin.sh + - .github/workflows/provision-linux.sh + - .github/workflows/rust-vetkeys-basic-bls-signing-example.yml + - .ic-commit +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +jobs: + rust-vetkeys-basic-bls-signing-rust-darwin: + runs-on: macos-15 + steps: + - uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1.2.0 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: '22' + - name: Provision Darwin + run: bash .github/workflows/provision-darwin.sh + - name: Pre-download network launcher + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bash .github/workflows/pre-download-launcher.sh + - name: Deploy Basic BLS Signing Rust Darwin + env: + ICP_CLI_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -eExuo pipefail + cargo install candid-extractor --locked + pushd rust/vetkeys/basic_bls_signing/rust + icp network start -d && icp deploy + popd + rust-vetkeys-basic-bls-signing-rust-linux: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1.2.0 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: '22' + - name: Provision Linux + run: bash .github/workflows/provision-linux.sh + - name: Pre-download network launcher + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bash .github/workflows/pre-download-launcher.sh + - name: Deploy Basic BLS Signing Rust Linux + env: + ICP_CLI_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -eExuo pipefail + cargo install candid-extractor --locked + pushd rust/vetkeys/basic_bls_signing/rust + icp network start -d && icp deploy + popd + rust-vetkeys-basic-bls-signing-motoko-darwin: + runs-on: macos-15 + steps: + - uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1.2.0 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: '22' + - name: Provision Darwin + run: bash .github/workflows/provision-darwin.sh + - name: Pre-download network launcher + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bash .github/workflows/pre-download-launcher.sh + - name: Deploy Basic BLS Signing Motoko Darwin + env: + ICP_CLI_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -eExuo pipefail + cargo install candid-extractor --locked + pushd rust/vetkeys/basic_bls_signing/motoko + icp network start -d && icp deploy + popd + rust-vetkeys-basic-bls-signing-motoko-linux: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1.2.0 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: '22' + - name: Provision Linux + run: bash .github/workflows/provision-linux.sh + - name: Pre-download network launcher + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bash .github/workflows/pre-download-launcher.sh + - name: Deploy Basic BLS Signing Motoko Linux + env: + ICP_CLI_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -eExuo pipefail + cargo install candid-extractor --locked + pushd rust/vetkeys/basic_bls_signing/motoko + icp network start -d && icp deploy + popd diff --git a/rust/vetkeys/basic_bls_signing/README.md b/rust/vetkeys/basic_bls_signing/README.md index 6d86b5212..ebe9a18af 100644 --- a/rust/vetkeys/basic_bls_signing/README.md +++ b/rust/vetkeys/basic_bls_signing/README.md @@ -1,10 +1,13 @@ # Threshold BLS Signatures + + -The **Basic BLS signing** example demonstrates how to use **[vetKeys](https://internetcomputer.org/docs/building-apps/network-features/vetkeys/introduction)** to implement a threshold BLS signing service on the **Internet Computer (IC)**, where every authenticated user can ask the canister (IC smart contract) to produce signatures, where the **Internet Identity Principal** identifies the signer. This canister ensures that users can only produce signature for their own principal and not for someone else's principal. Furthermore, the vetKeys in this dapp can only be produced upon a user request, as specified in the canister code, meaning that the canister cannot produce signatures for arbitrary users or messages. +The **Basic BLS signing** example demonstrates how to use **[vetKeys](https://docs.internetcomputer.org/docs/building-apps/network-features/vetkeys/introduction)** to implement a threshold BLS signing service on the **Internet Computer (IC)**, where every authenticated user can ask the canister (IC smart contract) to produce signatures, where the **Internet Identity Principal** identifies the signer. This canister ensures that users can only produce signature for their own principal and not for someone else's principal. Furthermore, the vetKeys in this dapp can only be produced upon a user request, as specified in the canister code, meaning that the canister cannot produce signatures for arbitrary users or messages. For confirming that the canister can only produce signatures in the intended way, users need to inspect the code installed in the canister. For this, it is crucial that canisters using VetKeys have their code public. @@ -19,23 +22,28 @@ For confirming that the canister can only produce signatures in the intended way ### Prerequisites -- [Internet Computer software development kit](https://internetcomputer.org/docs/building-apps/getting-started/install) +- [ICP CLI](https://cli.internetcomputer.org) - [npm](https://www.npmjs.com/package/npm) ### (Optionally) Choose a Different Master Key -This example uses `test_key_1` by default. To use a different [available master key](https://internetcomputer.org/docs/building-apps/network-features/vetkeys/api#available-master-keys), change the `"init_arg": "(\"test_key_1\")"` line in `dfx.json` to the desired key before running `dfx deploy` in the next step. +This example uses `test_key_1` by default. To use a different [available master key](https://docs.internetcomputer.org/docs/building-apps/network-features/vetkeys/api#available-master-keys), change the `value: "(\"test_key_1\")"` line in `icp.yaml` to the desired key before running `icp deploy` in the next step. ### Deploy the Canisters Locally If you want to deploy this project locally with a Motoko backend, then run: ```bash -dfx start --background && dfx deploy +icp network start -d && icp deploy ``` from the `motoko` folder. To use the Rust backend instead of Motoko, run the same command in the `rust` folder. +When finished, stop the local network: +```bash +icp network stop +``` + ## Example Components ### Backend @@ -49,12 +57,18 @@ The backend consists of a canister that: The frontend is a vanilla typescript application providing a simple interface for signing, showing the signatures stored in the canister, and publishing a signature. -To run the frontend in development mode with hot reloading (after running `dfx deploy`): +To run the frontend in development mode with hot reloading (after running `icp deploy`): + +```bash +npm run dev:rust +``` + +or for the Motoko backend: ```bash -npm run dev +npm run dev:motoko ``` ## Additional Resources -- **[What are VetKeys](https://internetcomputer.org/docs/building-apps/network-features/encryption/vetkeys)** - For more information about VetKeys and VetKD. +- **[What are VetKeys](https://docs.internetcomputer.org/docs/building-apps/network-features/encryption/vetkeys)** - For more information about VetKeys and VetKD. diff --git a/rust/vetkeys/basic_bls_signing/frontend/package.json b/rust/vetkeys/basic_bls_signing/frontend/package.json index f103fde2a..38f921576 100644 --- a/rust/vetkeys/basic_bls_signing/frontend/package.json +++ b/rust/vetkeys/basic_bls_signing/frontend/package.json @@ -4,7 +4,9 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "npm run build:bindings && vite", + "dev": "printf '\\nNo backend specified. Use one of:\\n\\n npm run dev:motoko\\n npm run dev:rust\\n\\n' && exit 1", + "dev:motoko": "npm run build:bindings && BACKEND=motoko vite", + "dev:rust": "npm run build:bindings && BACKEND=rust vite", "build": "npm run build:bindings && tsc && vite build", "build:bindings": "cd scripts && ./gen_bindings.sh", "preview": "vite preview", @@ -20,12 +22,11 @@ "tslib": "^2.8.1", "typescript": "~5.7.2", "typescript-eslint": "^8.35.1", - "vite": "^6.4.1", - "vite-plugin-environment": "^1.1.3" + "vite": "^6.4.1" }, "dependencies": { - "@dfinity/auth-client": "^2.4.1", - "@dfinity/principal": "^2.4.1", - "@dfinity/vetkeys": "^0.3.0" + "@icp-sdk/auth": "^7.1.0", + "@icp-sdk/core": "^5.4.0", + "@icp-sdk/vetkeys": "^0.5.0-beta.0" } } diff --git a/rust/vetkeys/basic_bls_signing/frontend/scripts/gen_bindings.sh b/rust/vetkeys/basic_bls_signing/frontend/scripts/gen_bindings.sh index 8eef59506..003e82d12 100755 --- a/rust/vetkeys/basic_bls_signing/frontend/scripts/gen_bindings.sh +++ b/rust/vetkeys/basic_bls_signing/frontend/scripts/gen_bindings.sh @@ -1,15 +1,15 @@ #!/bin/bash -cd ../../backend && make extract-candid +# Bindings are always generated from the Rust backend since both backends +# expose the same Candid interface. +if command -v candid-extractor >/dev/null 2>&1; then + cd ../../rust/backend && make extract-candid + cd ../.. +else + cd ../.. +fi -cd .. && dfx generate basic_bls_signing || exit 1 - -rm -r frontend/src/declarations/basic_bls_signing > /dev/null 2>&1 || true +rm -rf frontend/src/declarations/basic_bls_signing mkdir -p frontend/src/declarations/basic_bls_signing -mv src/declarations/basic_bls_signing frontend/src/declarations -rmdir -p src/declarations > /dev/null 2>&1 || true - -# dfx 0.31+ generates @icp-sdk/core imports; rewrite to @dfinity/* to match deps -find frontend/src/declarations -type f \( -name '*.ts' -o -name '*.js' \) -exec \ - perl -i -pe 's|\@icp-sdk/core/agent|\@dfinity/agent|g; s|\@icp-sdk/core/principal|\@dfinity/principal|g; s|\@icp-sdk/core/candid|\@dfinity/candid|g' {} + \ No newline at end of file +npx @icp-sdk/bindgen --did-file rust/backend/backend.did --out-dir frontend/src/declarations/basic_bls_signing --declarations-flat --force diff --git a/rust/vetkeys/basic_bls_signing/frontend/src/main.ts b/rust/vetkeys/basic_bls_signing/frontend/src/main.ts index ef5b3f247..3ba64ef46 100644 --- a/rust/vetkeys/basic_bls_signing/frontend/src/main.ts +++ b/rust/vetkeys/basic_bls_signing/frontend/src/main.ts @@ -1,56 +1,49 @@ -// Required to run `npm run dev`. -if (!window.global) { - window.global = window; -} - import "./style.css"; -import { createActor } from "./declarations/basic_bls_signing"; -import { Principal } from "@dfinity/principal"; -import { AuthClient } from "@dfinity/auth-client"; -import type { ActorSubclass } from "@dfinity/agent"; -import { _SERVICE } from "./declarations/basic_bls_signing/basic_bls_signing.did"; -import { DerivedPublicKey, verifyBlsSignature } from "@dfinity/vetkeys"; -import type { Signature } from "./declarations/basic_bls_signing/basic_bls_signing.did"; +import { idlFactory } from "./declarations/basic_bls_signing/backend.did"; +import { Principal } from "@icp-sdk/core/principal"; +import { AuthClient } from "@icp-sdk/auth/client"; +import { Actor, HttpAgent, type ActorSubclass } from "@icp-sdk/core/agent"; +import { _SERVICE } from "./declarations/basic_bls_signing/backend.did"; +import { DerivedPublicKey, verifyBlsSignature } from "@icp-sdk/vetkeys"; +import type { Signature } from "./declarations/basic_bls_signing/backend.did"; +import { safeGetCanisterEnv } from "@icp-sdk/core/agent/canister-env"; + +const canisterEnv = safeGetCanisterEnv<{ + "PUBLIC_CANISTER_ID:basic_bls_signing": string; +}>(); let myPrincipal: Principal | undefined = undefined; let authClient: AuthClient | undefined; -let basicBlsSigningCanister: ActorSubclass<_SERVICE> | undefined; +let basicBlsSigningActor: ActorSubclass<_SERVICE> | undefined; // let canisterPublicKey: DerivedPublicKey | undefined; let myVerificationKey: DerivedPublicKey | undefined; -function getBasicBlsSigningCanister(): ActorSubclass<_SERVICE> { - if (basicBlsSigningCanister) return basicBlsSigningCanister; - if (!process.env.CANISTER_ID_BASIC_BLS_SIGNING) { - throw Error("CANISTER_ID_BASIC_BLS_SIGNING is not set"); +async function getBasicBlsSigningActor(): Promise> { + if (basicBlsSigningActor) return basicBlsSigningActor; + const canisterId = canisterEnv?.["PUBLIC_CANISTER_ID:basic_bls_signing"]; + if (!canisterId) { + throw Error("Canister ID for basic_bls_signing is not set"); } if (!authClient) { throw Error("Auth client is not initialized"); } - const host = - process.env.DFX_NETWORK === "ic" - ? `https://${process.env.CANISTER_ID_BASIC_BLS_SIGNING}.ic0.app` - : "http://localhost:8000"; - - basicBlsSigningCanister = createActor( - process.env.CANISTER_ID_BASIC_BLS_SIGNING, - { - agentOptions: { - identity: authClient.getIdentity(), - host, - }, - }, - ); - - return basicBlsSigningCanister!; + const agent = await HttpAgent.create({ + identity: authClient.getIdentity(), + host: window.location.origin, + ...(canisterEnv?.ic_root_key ? { rootKey: canisterEnv.ic_root_key } : {}), + }); + basicBlsSigningActor = Actor.createActor(idlFactory, { agent, canisterId }); + return basicBlsSigningActor; } export function login(client: AuthClient) { void client.login({ maxTimeToLive: BigInt(1800) * BigInt(1_000_000_000), identityProvider: - process.env.DFX_NETWORK === "ic" - ? "https://identity.ic0.app/#authorize" - : `http://rdmx6-jaaaa-aaaaa-aaadq-cai.localhost:8000/#authorize`, + window.location.hostname === "localhost" || + window.location.hostname.endsWith(".localhost") + ? `http://id.ai.localhost:8000/#authorize` + : "https://identity.ic0.app/#authorize", onSuccess: () => { myPrincipal = client.getIdentity().getPrincipal(); updateUI(true); @@ -65,7 +58,7 @@ export function logout() { void authClient?.logout(); myPrincipal = undefined; myVerificationKey = undefined; - basicBlsSigningCanister = undefined; + basicBlsSigningActor = undefined; updateUI(false); document.getElementById("signaturesList")!.classList.toggle("hidden", true); } @@ -158,7 +151,7 @@ document.getElementById("signMessageButton")!.addEventListener("click", () => { const message = prompt("Enter message to sign:"); if (message) { try { - await getBasicBlsSigningCanister().sign_message(message); + await (await getBasicBlsSigningActor()).sign_message(message); alert("Created and stored signature successfully."); } catch (error) { alert(`Error: ${error as Error}`); @@ -217,8 +210,8 @@ document }); async function listSignatures() { - const signatures: Array = - await getBasicBlsSigningCanister().get_my_signatures(); + const actor = await getBasicBlsSigningActor(); + const signatures: Array = await actor.get_my_signatures(); const signaturesDiv = document.getElementById("signatures")!; signaturesDiv.innerHTML = ""; @@ -230,8 +223,7 @@ async function listSignatures() { `; } else { if (!myVerificationKey) { - const myVerificationKeyRaw = - await getBasicBlsSigningCanister().get_my_verification_key(); + const myVerificationKeyRaw = await actor.get_my_verification_key(); myVerificationKey = DerivedPublicKey.deserialize( Uint8Array.from(myVerificationKeyRaw), ); diff --git a/rust/vetkeys/basic_bls_signing/frontend/vite.config.ts b/rust/vetkeys/basic_bls_signing/frontend/vite.config.ts index 27bf81575..0615cf574 100644 --- a/rust/vetkeys/basic_bls_signing/frontend/vite.config.ts +++ b/rust/vetkeys/basic_bls_signing/frontend/vite.config.ts @@ -1,27 +1,51 @@ -import { defineConfig } from 'vite' -import typescript from '@rollup/plugin-typescript'; -import environment from 'vite-plugin-environment'; -import path from 'path'; +import { defineConfig } from "vite"; +import { execSync } from "child_process"; -// https://vite.dev/config/ -export default defineConfig({ - plugins: [ - typescript({ - inlineSources: true, - }), - environment("all", { prefix: "CANISTER_" }), - environment("all", { prefix: "DFX_" }), - ], - build: { - sourcemap: true, - rollupOptions: { - output: { - inlineDynamicImports: true, - }, +const environment = process.env.ICP_ENVIRONMENT || "local"; +const CANISTER_NAMES = ["basic_bls_signing"]; + +function getDevServerConfig() { + const backend = process.env.BACKEND; + if (!backend) { + throw new Error( + "BACKEND env var is required. Use `npm run dev:motoko` or `npm run dev:rust`.", + ); + } + + const networkStatus = JSON.parse( + execSync(`icp network status -e ${environment} --json --project-root-override ../${backend}`, { + encoding: "utf-8", + }), + ); + const canisterParams = CANISTER_NAMES.map((name) => { + const id = execSync( + `icp canister status ${name} -e ${environment} --id-only --project-root-override ../${backend}`, + { encoding: "utf-8", stdio: "pipe" }, + ).trim(); + return `PUBLIC_CANISTER_ID:${name}=${id}`; + }).join("&"); + return { + headers: { + "Set-Cookie": `ic_env=${encodeURIComponent( + `${canisterParams}&ic_root_key=${networkStatus.root_key}`, + )}; SameSite=Lax;`, + }, + proxy: { + "/api": { target: networkStatus.api_url, changeOrigin: true }, + }, + hmr: false, + }; +} + +export default defineConfig(({ command }) => ({ + build: { + sourcemap: true, + rollupOptions: { + output: { + inlineDynamicImports: true, + }, + }, }, - }, - root: "./", - server: { - hmr: false - } -}) \ No newline at end of file + root: "./", + ...(command === "serve" ? { server: getDevServerConfig() } : {}), +})); diff --git a/rust/vetkeys/basic_bls_signing/motoko/backend/src/Main.mo b/rust/vetkeys/basic_bls_signing/motoko/backend/src/Main.mo index a610ebaf0..1d126eb38 100644 --- a/rust/vetkeys/basic_bls_signing/motoko/backend/src/Main.mo +++ b/rust/vetkeys/basic_bls_signing/motoko/backend/src/Main.mo @@ -7,8 +7,6 @@ import Map "mo:core/Map"; import Array "mo:core/Array"; import List "mo:core/List"; import Nat8 "mo:core/Nat8"; -import Runtime "mo:core/Runtime"; -import Nat "mo:core/Nat"; import VetKeys "mo:ic-vetkeys"; import Order "mo:core/Order"; @@ -74,22 +72,12 @@ shared persistent actor class (keyName : Text) = { // Sign a message using BLS public shared ({ caller }) func sign_message(message : Text) : async Blob { - // TODO(CRP-2874): return only the signature bytes, not the entire vetKey bytes - let bytes = await VetKeys.ManagementCanister.signWithBls( + let signatureBytes = await VetKeys.ManagementCanister.signWithBls( Text.encodeUtf8(message), context(caller), keyId(), ); - let BYTES_SIZE : Nat = 192; - let SIGNATURE_SIZE : Nat = 48; - - if (bytes.size() != BYTES_SIZE) { - Runtime.trap("Expected " # Nat.toText(BYTES_SIZE) # " signature bytes, but got " # Nat.toText(bytes.size())); - }; - - let signatureBytes = Blob.fromArray(Array.sliceToArray(Blob.toArray(bytes), BYTES_SIZE - SIGNATURE_SIZE, BYTES_SIZE)); - let timestamp = getTimestamp(); let signature : Signature = { message = message; diff --git a/rust/vetkeys/basic_bls_signing/motoko/dfx.json b/rust/vetkeys/basic_bls_signing/motoko/dfx.json deleted file mode 100644 index 0631e6027..000000000 --- a/rust/vetkeys/basic_bls_signing/motoko/dfx.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "canisters": { - "basic_bls_signing": { - "main": "backend/src/Main.mo", - "type": "motoko", - "args": "--enhanced-orthogonal-persistence", - "init_arg": "(\"test_key_1\")", - "metadata": [ - { - "name": "candid:service", - "visibility": "public" - } - ] - }, - "internet-identity": { - "candid": "https://github.com/dfinity/internet-identity/releases/download/release-2026-03-16/internet_identity.did", - "type": "custom", - "specified_id": "rdmx6-jaaaa-aaaaa-aaadq-cai", - "remote": { - "id": { - "ic": "rdmx6-jaaaa-aaaaa-aaadq-cai" - } - }, - "wasm": "https://github.com/dfinity/internet-identity/releases/download/release-2026-03-16/internet_identity_dev.wasm.gz" - }, - "www": { - "dependencies": ["basic_bls_signing", "internet-identity"], - "build": [ - "cd frontend && npm i --include=dev && npm run build && cd - && rm -r dist > /dev/null 2>&1; mv frontend/dist ./" - ], - "frontend": { - "entrypoint": "dist/index.html" - }, - "source": ["dist/"], - "type": "assets", - "output_env_file": "frontend/.env" - } - }, - "defaults": { - "build": { - "packtool": "npx ic-mops sources", - "args": "" - } - }, - "networks": { - "local": { - "bind": "127.0.0.1:8000", - "type": "ephemeral" - } - } -} diff --git a/rust/vetkeys/basic_bls_signing/motoko/icp.yaml b/rust/vetkeys/basic_bls_signing/motoko/icp.yaml new file mode 100644 index 000000000..d2f7ab3b5 --- /dev/null +++ b/rust/vetkeys/basic_bls_signing/motoko/icp.yaml @@ -0,0 +1,22 @@ +canisters: + - name: basic_bls_signing + recipe: + type: "@dfinity/motoko@v4.1.0" + configuration: + main: backend/src/Main.mo + init_args: + type: text + value: "(\"test_key_1\")" + + - name: www + recipe: + type: "@dfinity/asset-canister@v2.1.0" + configuration: + dir: dist + build: + - cd frontend && npm i --include=dev && npm run build && cd - && rm -rf dist; mv frontend/dist ./ + +networks: + - name: local + mode: managed + ii: true diff --git a/rust/vetkeys/basic_bls_signing/motoko/mops.toml b/rust/vetkeys/basic_bls_signing/motoko/mops.toml index 668ffda6c..2d851a475 100644 --- a/rust/vetkeys/basic_bls_signing/motoko/mops.toml +++ b/rust/vetkeys/basic_bls_signing/motoko/mops.toml @@ -1,4 +1,7 @@ +[toolchain] +moc = "1.5.1" + [dependencies] -core = "1.0.0" -ic-vetkeys = "0.3.0" -sha2 = "0.1.2" \ No newline at end of file +core = "2.4.0" +ic-vetkeys = "0.5.0" +sha2 = "0.1.14" diff --git a/rust/vetkeys/basic_bls_signing/rust/backend/Cargo.toml b/rust/vetkeys/basic_bls_signing/rust/backend/Cargo.toml index 5e7a26140..bf775ee3d 100644 --- a/rust/vetkeys/basic_bls_signing/rust/backend/Cargo.toml +++ b/rust/vetkeys/basic_bls_signing/rust/backend/Cargo.toml @@ -17,7 +17,7 @@ candid = "0.10.2" getrandom = { version = "0.2", features = ["custom"] } ic-cdk = "0.18.3" ic-stable-structures = "0.6.8" -ic-vetkeys = "0.3.0" +ic-vetkeys = "0.7.0" serde = "1.0.217" serde_bytes = "0.11.15" serde_cbor = "0.11.2" diff --git a/rust/vetkeys/basic_bls_signing/rust/backend/Makefile b/rust/vetkeys/basic_bls_signing/rust/backend/Makefile index 458eba5ad..8d9d22215 100644 --- a/rust/vetkeys/basic_bls_signing/rust/backend/Makefile +++ b/rust/vetkeys/basic_bls_signing/rust/backend/Makefile @@ -12,4 +12,4 @@ extract-candid: compile-wasm .SILENT: clean clean: cargo clean - rm -rf .dfx \ No newline at end of file + rm -rf .icp \ No newline at end of file diff --git a/rust/vetkeys/basic_bls_signing/rust/dfx.json b/rust/vetkeys/basic_bls_signing/rust/dfx.json deleted file mode 100644 index fec54f439..000000000 --- a/rust/vetkeys/basic_bls_signing/rust/dfx.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "canisters": { - "basic_bls_signing": { - "candid": "backend/backend.did", - "package": "ic-vetkeys-example-basic-bls-signing-backend", - "type": "rust", - "init_arg": "(\"test_key_1\")", - "metadata": [ - { - "name": "candid:service", - "visibility": "public" - } - ] - }, - "internet-identity": { - "candid": "https://github.com/dfinity/internet-identity/releases/download/release-2026-03-16/internet_identity.did", - "type": "custom", - "specified_id": "rdmx6-jaaaa-aaaaa-aaadq-cai", - "remote": { - "id": { - "ic": "rdmx6-jaaaa-aaaaa-aaadq-cai" - } - }, - "wasm": "https://github.com/dfinity/internet-identity/releases/download/release-2026-03-16/internet_identity_dev.wasm.gz" - }, - "www": { - "dependencies": ["basic_bls_signing", "internet-identity"], - "build": [ - "cd frontend && npm i --include=dev && npm run build && cd - && rm -r dist > /dev/null 2>&1; mv frontend/dist ./" - ], - "frontend": { - "entrypoint": "dist/index.html" - }, - "source": ["dist/"], - "type": "assets", - "output_env_file": "frontend/.env" - } - }, - "networks": { - "local": { - "bind": "127.0.0.1:8000", - "type": "ephemeral" - } - } -} diff --git a/rust/vetkeys/basic_bls_signing/rust/icp.yaml b/rust/vetkeys/basic_bls_signing/rust/icp.yaml new file mode 100644 index 000000000..c70b4d26a --- /dev/null +++ b/rust/vetkeys/basic_bls_signing/rust/icp.yaml @@ -0,0 +1,23 @@ +canisters: + - name: basic_bls_signing + recipe: + type: "@dfinity/rust@v3.2.0" + configuration: + package: ic-vetkeys-example-basic-bls-signing-backend + candid: backend/backend.did + init_args: + type: text + value: "(\"test_key_1\")" + + - name: www + recipe: + type: "@dfinity/asset-canister@v2.1.0" + configuration: + dir: dist + build: + - cd frontend && npm i --include=dev && npm run build && cd - && rm -rf dist; mv frontend/dist ./ + +networks: + - name: local + mode: managed + ii: true From 0a0c63996b83fdc0fa2929af9f8622b852f3a610 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Fri, 29 May 2026 15:48:50 +0200 Subject: [PATCH 02/14] fix(ci): remove rust toolchain channel pin and candid-extractor install - Drop channel = "1.88.0" and profile = "default" from rust-toolchain.toml; use stable Rust from provision script to avoid the cargo component error introduced in 1.88.0 where cargo is no longer a standalone component - Remove cargo install candid-extractor from CI; the guard in gen_bindings.sh skips make extract-candid when the binary is absent, using the committed .did Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/rust-vetkeys-basic-bls-signing-example.yml | 4 ---- rust/vetkeys/basic_bls_signing/rust/rust-toolchain.toml | 2 -- 2 files changed, 6 deletions(-) diff --git a/.github/workflows/rust-vetkeys-basic-bls-signing-example.yml b/.github/workflows/rust-vetkeys-basic-bls-signing-example.yml index c76ae77bc..2fc498c32 100644 --- a/.github/workflows/rust-vetkeys-basic-bls-signing-example.yml +++ b/.github/workflows/rust-vetkeys-basic-bls-signing-example.yml @@ -32,7 +32,6 @@ jobs: ICP_CLI_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -eExuo pipefail - cargo install candid-extractor --locked pushd rust/vetkeys/basic_bls_signing/rust icp network start -d && icp deploy popd @@ -54,7 +53,6 @@ jobs: ICP_CLI_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -eExuo pipefail - cargo install candid-extractor --locked pushd rust/vetkeys/basic_bls_signing/rust icp network start -d && icp deploy popd @@ -76,7 +74,6 @@ jobs: ICP_CLI_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -eExuo pipefail - cargo install candid-extractor --locked pushd rust/vetkeys/basic_bls_signing/motoko icp network start -d && icp deploy popd @@ -98,7 +95,6 @@ jobs: ICP_CLI_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -eExuo pipefail - cargo install candid-extractor --locked pushd rust/vetkeys/basic_bls_signing/motoko icp network start -d && icp deploy popd diff --git a/rust/vetkeys/basic_bls_signing/rust/rust-toolchain.toml b/rust/vetkeys/basic_bls_signing/rust/rust-toolchain.toml index 2a2058b04..990104f05 100644 --- a/rust/vetkeys/basic_bls_signing/rust/rust-toolchain.toml +++ b/rust/vetkeys/basic_bls_signing/rust/rust-toolchain.toml @@ -1,4 +1,2 @@ [toolchain] -channel = "1.88.0" targets = ["wasm32-unknown-unknown"] -profile = "default" \ No newline at end of file From 3a725e0757c22aed47314e16d3d064c7c6aa28fc Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Sat, 30 May 2026 02:03:59 +0200 Subject: [PATCH 03/14] fix(ci): resolve gen_bindings.sh paths via physical script location The icp CLI's @dfinity/asset-canister recipe symlinks frontend/ into the backend subdirectory during build. Bash's `cd ../..` operates on logical paths, so it lands back in the backend dir instead of the example root, causing bindgen to look for `/rust/backend/backend.did`. Use `pwd -P` to resolve the script's physical location and derive absolute paths for the example root, frontend dir, and the .did file. Co-Authored-By: Claude Sonnet 4.6 --- .../frontend/scripts/gen_bindings.sh | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/rust/vetkeys/basic_bls_signing/frontend/scripts/gen_bindings.sh b/rust/vetkeys/basic_bls_signing/frontend/scripts/gen_bindings.sh index 003e82d12..330d250c5 100755 --- a/rust/vetkeys/basic_bls_signing/frontend/scripts/gen_bindings.sh +++ b/rust/vetkeys/basic_bls_signing/frontend/scripts/gen_bindings.sh @@ -1,15 +1,21 @@ #!/bin/bash +set -eu + +# Resolve the script's physical location so we work correctly even when the +# icp CLI has symlinked `frontend/` into a backend subdirectory for the build. +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +FRONTEND_DIR="$(dirname "$SCRIPT_DIR")" +EXAMPLE_ROOT="$(dirname "$FRONTEND_DIR")" # Bindings are always generated from the Rust backend since both backends # expose the same Candid interface. if command -v candid-extractor >/dev/null 2>&1; then - cd ../../rust/backend && make extract-candid - cd ../.. -else - cd ../.. + (cd "$EXAMPLE_ROOT/rust/backend" && make extract-candid) fi -rm -rf frontend/src/declarations/basic_bls_signing - -mkdir -p frontend/src/declarations/basic_bls_signing -npx @icp-sdk/bindgen --did-file rust/backend/backend.did --out-dir frontend/src/declarations/basic_bls_signing --declarations-flat --force +rm -rf "$FRONTEND_DIR/src/declarations/basic_bls_signing" +mkdir -p "$FRONTEND_DIR/src/declarations/basic_bls_signing" +npx @icp-sdk/bindgen \ + --did-file "$EXAMPLE_ROOT/rust/backend/backend.did" \ + --out-dir "$FRONTEND_DIR/src/declarations/basic_bls_signing" \ + --declarations-flat --force From 2c315d5c94b6ae9434fbbb52fe6c47f0c1a3b5a7 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Sat, 30 May 2026 03:18:40 +0200 Subject: [PATCH 04/14] fix(frontend): update main.ts to use @icp-sdk/auth@7.1.0 API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace AuthClient.create() with new AuthClient({ identityProvider }) - Replace client.login({onSuccess,onError}) with await client.signIn() - Replace client.logout() with client.signOut() - Await authClient.getIdentity() (now async in v7) - isAuthenticated() is now synchronous (no await) - Fix ic_root_key → IC_ROOT_KEY (CanisterEnv type uses uppercase) Co-Authored-By: Claude Sonnet 4.6 --- .../basic_bls_signing/frontend/src/main.ts | 47 ++++++++++--------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/rust/vetkeys/basic_bls_signing/frontend/src/main.ts b/rust/vetkeys/basic_bls_signing/frontend/src/main.ts index 3ba64ef46..a49fee184 100644 --- a/rust/vetkeys/basic_bls_signing/frontend/src/main.ts +++ b/rust/vetkeys/basic_bls_signing/frontend/src/main.ts @@ -28,34 +28,28 @@ async function getBasicBlsSigningActor(): Promise> { throw Error("Auth client is not initialized"); } const agent = await HttpAgent.create({ - identity: authClient.getIdentity(), + identity: await authClient.getIdentity(), host: window.location.origin, - ...(canisterEnv?.ic_root_key ? { rootKey: canisterEnv.ic_root_key } : {}), + ...(canisterEnv?.IC_ROOT_KEY ? { rootKey: canisterEnv.IC_ROOT_KEY } : {}), }); basicBlsSigningActor = Actor.createActor(idlFactory, { agent, canisterId }); return basicBlsSigningActor; } -export function login(client: AuthClient) { - void client.login({ - maxTimeToLive: BigInt(1800) * BigInt(1_000_000_000), - identityProvider: - window.location.hostname === "localhost" || - window.location.hostname.endsWith(".localhost") - ? `http://id.ai.localhost:8000/#authorize` - : "https://identity.ic0.app/#authorize", - onSuccess: () => { - myPrincipal = client.getIdentity().getPrincipal(); - updateUI(true); - }, - onError: (error) => { - alert("Authentication failed: " + error); - }, - }); +export async function login(client: AuthClient): Promise { + try { + const identity = await client.signIn({ + maxTimeToLive: BigInt(1800) * BigInt(1_000_000_000), + }); + myPrincipal = identity.getPrincipal(); + updateUI(true); + } catch (error: unknown) { + alert("Authentication failed: " + error); + } } export function logout() { - void authClient?.logout(); + void authClient?.signOut(); myPrincipal = undefined; myVerificationKey = undefined; basicBlsSigningActor = undefined; @@ -64,11 +58,18 @@ export function logout() { } async function initAuth() { - authClient = await AuthClient.create(); - const isAuthenticated = await authClient.isAuthenticated(); + const isLocalEnv = + window.location.hostname === "localhost" || + window.location.hostname.endsWith(".localhost"); + authClient = new AuthClient({ + identityProvider: isLocalEnv + ? "http://id.ai.localhost:8000/#authorize" + : undefined, + }); + const isAuthenticated = authClient.isAuthenticated(); if (isAuthenticated) { - myPrincipal = authClient.getIdentity().getPrincipal(); + myPrincipal = (await authClient.getIdentity()).getPrincipal(); updateUI(true); } else { updateUI(false); @@ -100,7 +101,7 @@ function handleLogin() { alert("Auth client not initialized"); return; } - login(authClient); + void login(authClient); } document.querySelector("#app")!.innerHTML = ` From 4fa127cf98fb61b4a628729bc8567f7ae9c77136 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Sat, 30 May 2026 03:29:19 +0200 Subject: [PATCH 05/14] fix(rust): bump ic-cdk to 0.20.1 to match ic-vetkeys 0.7.0 requirement ic-vetkeys 0.7.0 requires ic-cdk ^0.20.1 which uses ic-cdk-executor ^2.0.0. The previously pinned ic-cdk 0.18.3 requires ic-cdk-executor ^1.0.0. Since ic-cdk-executor uses `links`, only one version can exist in the graph. Co-Authored-By: Claude Sonnet 4.6 --- rust/vetkeys/basic_bls_signing/rust/backend/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/vetkeys/basic_bls_signing/rust/backend/Cargo.toml b/rust/vetkeys/basic_bls_signing/rust/backend/Cargo.toml index bf775ee3d..6420059ce 100644 --- a/rust/vetkeys/basic_bls_signing/rust/backend/Cargo.toml +++ b/rust/vetkeys/basic_bls_signing/rust/backend/Cargo.toml @@ -15,7 +15,7 @@ crate-type = ["cdylib"] [dependencies] candid = "0.10.2" getrandom = { version = "0.2", features = ["custom"] } -ic-cdk = "0.18.3" +ic-cdk = "0.20.1" ic-stable-structures = "0.6.8" ic-vetkeys = "0.7.0" serde = "1.0.217" From a152b180a71def8aced40527ed57a24cb5bca009 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Sat, 30 May 2026 03:50:05 +0200 Subject: [PATCH 06/14] fix(rust): add ic-cdk-management-canister dep and update imports In ic-cdk 0.20, the management_canister module was extracted into the separate ic-cdk-management-canister crate. Update imports from ic_cdk::management_canister to ic_cdk_management_canister. Co-Authored-By: Claude Sonnet 4.6 --- rust/vetkeys/basic_bls_signing/rust/backend/Cargo.toml | 1 + rust/vetkeys/basic_bls_signing/rust/backend/src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/rust/vetkeys/basic_bls_signing/rust/backend/Cargo.toml b/rust/vetkeys/basic_bls_signing/rust/backend/Cargo.toml index 6420059ce..36ff58138 100644 --- a/rust/vetkeys/basic_bls_signing/rust/backend/Cargo.toml +++ b/rust/vetkeys/basic_bls_signing/rust/backend/Cargo.toml @@ -16,6 +16,7 @@ crate-type = ["cdylib"] candid = "0.10.2" getrandom = { version = "0.2", features = ["custom"] } ic-cdk = "0.20.1" +ic-cdk-management-canister = "0.1.1" ic-stable-structures = "0.6.8" ic-vetkeys = "0.7.0" serde = "1.0.217" diff --git a/rust/vetkeys/basic_bls_signing/rust/backend/src/lib.rs b/rust/vetkeys/basic_bls_signing/rust/backend/src/lib.rs index 59a644b7b..60963a41f 100644 --- a/rust/vetkeys/basic_bls_signing/rust/backend/src/lib.rs +++ b/rust/vetkeys/basic_bls_signing/rust/backend/src/lib.rs @@ -1,6 +1,6 @@ pub mod types; use candid::Principal; -use ic_cdk::management_canister::{VetKDCurve, VetKDKeyId, VetKDPublicKeyArgs}; +use ic_cdk_management_canister::{VetKDCurve, VetKDKeyId, VetKDPublicKeyArgs}; use ic_cdk::{init, query, update}; use ic_stable_structures::{ memory_manager::{MemoryId, MemoryManager, VirtualMemory}, @@ -96,7 +96,7 @@ async fn get_my_verification_key() -> VetKeyPublicKey { context: context(&ic_cdk::api::msg_caller()), key_id: key_id(), }; - let result = ic_cdk::management_canister::vetkd_public_key(&request) + let result = ic_cdk_management_canister::vetkd_public_key(&request) .await .expect("call to vetkd_public_key failed"); From a1512ff8d7bc79111bbe334950eddc35d7c2c8f5 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Mon, 1 Jun 2026 11:56:45 +0200 Subject: [PATCH 07/14] chore(basic_bls_signing): rename CI jobs to language-first format Co-Authored-By: Claude Sonnet 4.6 --- .../workflows/rust-vetkeys-basic-bls-signing-example.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rust-vetkeys-basic-bls-signing-example.yml b/.github/workflows/rust-vetkeys-basic-bls-signing-example.yml index 2fc498c32..21043d28b 100644 --- a/.github/workflows/rust-vetkeys-basic-bls-signing-example.yml +++ b/.github/workflows/rust-vetkeys-basic-bls-signing-example.yml @@ -14,7 +14,7 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: - rust-vetkeys-basic-bls-signing-rust-darwin: + rust-basic-bls-signing-darwin: runs-on: macos-15 steps: - uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1.2.0 @@ -35,7 +35,7 @@ jobs: pushd rust/vetkeys/basic_bls_signing/rust icp network start -d && icp deploy popd - rust-vetkeys-basic-bls-signing-rust-linux: + rust-basic-bls-signing-linux: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1.2.0 @@ -56,7 +56,7 @@ jobs: pushd rust/vetkeys/basic_bls_signing/rust icp network start -d && icp deploy popd - rust-vetkeys-basic-bls-signing-motoko-darwin: + motoko-basic-bls-signing-darwin: runs-on: macos-15 steps: - uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1.2.0 @@ -77,7 +77,7 @@ jobs: pushd rust/vetkeys/basic_bls_signing/motoko icp network start -d && icp deploy popd - rust-vetkeys-basic-bls-signing-motoko-linux: + motoko-basic-bls-signing-linux: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1.2.0 From 25145d3dec4d57e9809a66861964cb6dcdce5afe Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Mon, 1 Jun 2026 13:57:13 +0200 Subject: [PATCH 08/14] fix: use key_1 (not test_key_1), npx --yes, console.error in basic_ibe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Change test_key_1 → key_1 in all icp.yaml: icp-cli 0.2.7 only provisions vetkd:Bls12_381_G2:key_1 (TestThresholdKeys subnet with test_key_1 is not yet supported by icp-cli). The vetkeys library itself uses key_1 in its own icp.yaml files. - Add --yes flag to npx @icp-sdk/bindgen to suppress the install confirmation prompt during local builds - basic_ibe: wrap event listeners in try-catch so errors are caught and shown (not silent unhandled rejections); add console.error() alongside alert() so errors are visible and copyable in DevTools Co-Authored-By: Claude Sonnet 4.6 --- rust/vetkeys/basic_bls_signing/frontend/scripts/gen_bindings.sh | 2 +- rust/vetkeys/basic_bls_signing/motoko/icp.yaml | 2 +- rust/vetkeys/basic_bls_signing/rust/icp.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/vetkeys/basic_bls_signing/frontend/scripts/gen_bindings.sh b/rust/vetkeys/basic_bls_signing/frontend/scripts/gen_bindings.sh index 330d250c5..6cfbd7e74 100755 --- a/rust/vetkeys/basic_bls_signing/frontend/scripts/gen_bindings.sh +++ b/rust/vetkeys/basic_bls_signing/frontend/scripts/gen_bindings.sh @@ -15,7 +15,7 @@ fi rm -rf "$FRONTEND_DIR/src/declarations/basic_bls_signing" mkdir -p "$FRONTEND_DIR/src/declarations/basic_bls_signing" -npx @icp-sdk/bindgen \ +npx --yes @icp-sdk/bindgen \ --did-file "$EXAMPLE_ROOT/rust/backend/backend.did" \ --out-dir "$FRONTEND_DIR/src/declarations/basic_bls_signing" \ --declarations-flat --force diff --git a/rust/vetkeys/basic_bls_signing/motoko/icp.yaml b/rust/vetkeys/basic_bls_signing/motoko/icp.yaml index d2f7ab3b5..f11ef3018 100644 --- a/rust/vetkeys/basic_bls_signing/motoko/icp.yaml +++ b/rust/vetkeys/basic_bls_signing/motoko/icp.yaml @@ -6,7 +6,7 @@ canisters: main: backend/src/Main.mo init_args: type: text - value: "(\"test_key_1\")" + value: "(\"key_1\")" - name: www recipe: diff --git a/rust/vetkeys/basic_bls_signing/rust/icp.yaml b/rust/vetkeys/basic_bls_signing/rust/icp.yaml index c70b4d26a..702a85f55 100644 --- a/rust/vetkeys/basic_bls_signing/rust/icp.yaml +++ b/rust/vetkeys/basic_bls_signing/rust/icp.yaml @@ -7,7 +7,7 @@ canisters: candid: backend/backend.did init_args: type: text - value: "(\"test_key_1\")" + value: "(\"key_1\")" - name: www recipe: From 88e2f377a2d55a42137394d0fc419885ba1fc55f Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Mon, 1 Jun 2026 15:09:01 +0200 Subject: [PATCH 09/14] docs: update vetkeys doc links to docs.internetcomputer.org/concepts/vetkeys Co-Authored-By: Claude Sonnet 4.6 --- rust/vetkeys/basic_bls_signing/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/vetkeys/basic_bls_signing/README.md b/rust/vetkeys/basic_bls_signing/README.md index ebe9a18af..63428d779 100644 --- a/rust/vetkeys/basic_bls_signing/README.md +++ b/rust/vetkeys/basic_bls_signing/README.md @@ -7,7 +7,7 @@ | Rust backend | [![](https://icp.ninja/assets/open.svg)](http://icp.ninja/editor?g=https://github.com/dfinity/examples/tree/master/rust/vetkeys/basic_bls_signing/rust) | --> -The **Basic BLS signing** example demonstrates how to use **[vetKeys](https://docs.internetcomputer.org/docs/building-apps/network-features/vetkeys/introduction)** to implement a threshold BLS signing service on the **Internet Computer (IC)**, where every authenticated user can ask the canister (IC smart contract) to produce signatures, where the **Internet Identity Principal** identifies the signer. This canister ensures that users can only produce signature for their own principal and not for someone else's principal. Furthermore, the vetKeys in this dapp can only be produced upon a user request, as specified in the canister code, meaning that the canister cannot produce signatures for arbitrary users or messages. +The **Basic BLS signing** example demonstrates how to use **[vetKeys](https://docs.internetcomputer.org/concepts/vetkeys)** to implement a threshold BLS signing service on the **Internet Computer (IC)**, where every authenticated user can ask the canister (IC smart contract) to produce signatures, where the **Internet Identity Principal** identifies the signer. This canister ensures that users can only produce signature for their own principal and not for someone else's principal. Furthermore, the vetKeys in this dapp can only be produced upon a user request, as specified in the canister code, meaning that the canister cannot produce signatures for arbitrary users or messages. For confirming that the canister can only produce signatures in the intended way, users need to inspect the code installed in the canister. For this, it is crucial that canisters using VetKeys have their code public. @@ -27,7 +27,7 @@ For confirming that the canister can only produce signatures in the intended way ### (Optionally) Choose a Different Master Key -This example uses `test_key_1` by default. To use a different [available master key](https://docs.internetcomputer.org/docs/building-apps/network-features/vetkeys/api#available-master-keys), change the `value: "(\"test_key_1\")"` line in `icp.yaml` to the desired key before running `icp deploy` in the next step. +This example uses `test_key_1` by default. To use a different [available master key](https://docs.internetcomputer.org/concepts/vetkeys/#api-overview), change the `value: "(\"test_key_1\")"` line in `icp.yaml` to the desired key before running `icp deploy` in the next step. ### Deploy the Canisters Locally @@ -71,4 +71,4 @@ npm run dev:motoko ## Additional Resources -- **[What are VetKeys](https://docs.internetcomputer.org/docs/building-apps/network-features/encryption/vetkeys)** - For more information about VetKeys and VetKD. +- **[What are VetKeys](https://docs.internetcomputer.org/concepts/vetkeys)** - For more information about VetKeys and VetKD. From 2babafb0930f916380cdb022d4ee08549651a116 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Mon, 1 Jun 2026 15:40:26 +0200 Subject: [PATCH 10/14] refactor: use generated createActor and Backend type from declarations Replace manual Actor.createActor(idlFactory, ...) with the generated createActor(canisterId, { agent }) function and typed Backend wrapper class from the bindgen-generated declarations. Removes direct imports of idlFactory, Actor, and ActorSubclass. Co-Authored-By: Claude Sonnet 4.6 --- rust/vetkeys/basic_bls_signing/frontend/src/main.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/rust/vetkeys/basic_bls_signing/frontend/src/main.ts b/rust/vetkeys/basic_bls_signing/frontend/src/main.ts index a49fee184..a60565894 100644 --- a/rust/vetkeys/basic_bls_signing/frontend/src/main.ts +++ b/rust/vetkeys/basic_bls_signing/frontend/src/main.ts @@ -1,11 +1,9 @@ import "./style.css"; -import { idlFactory } from "./declarations/basic_bls_signing/backend.did"; import { Principal } from "@icp-sdk/core/principal"; import { AuthClient } from "@icp-sdk/auth/client"; -import { Actor, HttpAgent, type ActorSubclass } from "@icp-sdk/core/agent"; -import { _SERVICE } from "./declarations/basic_bls_signing/backend.did"; +import { HttpAgent } from "@icp-sdk/core/agent"; +import { createActor, type Backend, type Signature } from "./declarations/basic_bls_signing/backend"; import { DerivedPublicKey, verifyBlsSignature } from "@icp-sdk/vetkeys"; -import type { Signature } from "./declarations/basic_bls_signing/backend.did"; import { safeGetCanisterEnv } from "@icp-sdk/core/agent/canister-env"; const canisterEnv = safeGetCanisterEnv<{ @@ -14,11 +12,11 @@ const canisterEnv = safeGetCanisterEnv<{ let myPrincipal: Principal | undefined = undefined; let authClient: AuthClient | undefined; -let basicBlsSigningActor: ActorSubclass<_SERVICE> | undefined; +let basicBlsSigningActor: Backend | undefined; // let canisterPublicKey: DerivedPublicKey | undefined; let myVerificationKey: DerivedPublicKey | undefined; -async function getBasicBlsSigningActor(): Promise> { +async function getBasicBlsSigningActor(): Promise { if (basicBlsSigningActor) return basicBlsSigningActor; const canisterId = canisterEnv?.["PUBLIC_CANISTER_ID:basic_bls_signing"]; if (!canisterId) { @@ -32,7 +30,7 @@ async function getBasicBlsSigningActor(): Promise> { host: window.location.origin, ...(canisterEnv?.IC_ROOT_KEY ? { rootKey: canisterEnv.IC_ROOT_KEY } : {}), }); - basicBlsSigningActor = Actor.createActor(idlFactory, { agent, canisterId }); + basicBlsSigningActor = createActor(canisterId, { agent }); return basicBlsSigningActor; } From d1cae64a8f0d54ae33395bc9b291212939e990bc Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Mon, 1 Jun 2026 17:46:00 +0200 Subject: [PATCH 11/14] docs: add folder structure, fix dev command and cd instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Folder Structure section explaining rust/, motoko/, frontend/ layout and why backends are in subdirectories (shared frontend via symlinks) - Replace vague "from the X folder" wording with explicit `cd X` commands - Fix `npm run dev` → `npm run dev:rust` / `npm run dev:motoko` (bare `dev` script intentionally errors with a "specify a backend" message) - Add `cd frontend` before all dev commands (package.json is in frontend/, not at the example root) Co-Authored-By: Claude Sonnet 4.6 --- rust/vetkeys/basic_bls_signing/README.md | 33 ++++++++++++++++-------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/rust/vetkeys/basic_bls_signing/README.md b/rust/vetkeys/basic_bls_signing/README.md index 63428d779..7ddb0b542 100644 --- a/rust/vetkeys/basic_bls_signing/README.md +++ b/rust/vetkeys/basic_bls_signing/README.md @@ -29,15 +29,30 @@ For confirming that the canister can only produce signatures in the intended way This example uses `test_key_1` by default. To use a different [available master key](https://docs.internetcomputer.org/concepts/vetkeys/#api-overview), change the `value: "(\"test_key_1\")"` line in `icp.yaml` to the desired key before running `icp deploy` in the next step. +### Folder Structure + +This example provides both a **Rust** and a **Motoko** backend, sharing a common `frontend/`: + +``` +basic_bls_signing/ +├── frontend/ ← shared frontend (symlinked into rust/ and motoko/) +├── motoko/ ← Motoko backend + icp.yaml +└── rust/ ← Rust backend + icp.yaml +``` + ### Deploy the Canisters Locally -If you want to deploy this project locally with a Motoko backend, then run: +Deploy with the **Motoko** backend: ```bash +cd motoko icp network start -d && icp deploy ``` -from the `motoko` folder. -To use the Rust backend instead of Motoko, run the same command in the `rust` folder. +Or deploy with the **Rust** backend: +```bash +cd rust +icp network start -d && icp deploy +``` When finished, stop the local network: ```bash @@ -58,15 +73,11 @@ The backend consists of a canister that: The frontend is a vanilla typescript application providing a simple interface for signing, showing the signatures stored in the canister, and publishing a signature. To run the frontend in development mode with hot reloading (after running `icp deploy`): - -```bash -npm run dev:rust -``` - -or for the Motoko backend: - ```bash -npm run dev:motoko +cd frontend +npm run dev:rust # if you deployed the Rust backend +# or +npm run dev:motoko # if you deployed the Motoko backend ``` ## Additional Resources From 5daceb51c627651064d7a41780340994ce17e59c Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Tue, 2 Jun 2026 14:04:57 +0200 Subject: [PATCH 12/14] fix: simplify rootKey; use /authorize (not /#authorize) and https://id.ai - rootKey: pass rootKey: canisterEnv?.IC_ROOT_KEY directly; undefined is fine when on mainnet (HttpAgent ignores it) - identityProvider local: use /authorize path instead of /#authorize hash - identityProvider production: use https://id.ai instead of undefined Co-Authored-By: Claude Sonnet 4.6 --- rust/vetkeys/basic_bls_signing/frontend/src/main.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/vetkeys/basic_bls_signing/frontend/src/main.ts b/rust/vetkeys/basic_bls_signing/frontend/src/main.ts index a60565894..a5faff22c 100644 --- a/rust/vetkeys/basic_bls_signing/frontend/src/main.ts +++ b/rust/vetkeys/basic_bls_signing/frontend/src/main.ts @@ -28,7 +28,7 @@ async function getBasicBlsSigningActor(): Promise { const agent = await HttpAgent.create({ identity: await authClient.getIdentity(), host: window.location.origin, - ...(canisterEnv?.IC_ROOT_KEY ? { rootKey: canisterEnv.IC_ROOT_KEY } : {}), + rootKey: canisterEnv?.IC_ROOT_KEY, }); basicBlsSigningActor = createActor(canisterId, { agent }); return basicBlsSigningActor; @@ -61,8 +61,8 @@ async function initAuth() { window.location.hostname.endsWith(".localhost"); authClient = new AuthClient({ identityProvider: isLocalEnv - ? "http://id.ai.localhost:8000/#authorize" - : undefined, + ? "http://id.ai.localhost:8000/authorize" + : "https://id.ai", }); const isAuthenticated = authClient.isAuthenticated(); From 26066f49645c3ebc3652415d202b98cd39814ae8 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Tue, 2 Jun 2026 14:06:18 +0200 Subject: [PATCH 13/14] fix: use https://id.ai/authorize for production identityProvider Co-Authored-By: Claude Sonnet 4.6 --- rust/vetkeys/basic_bls_signing/frontend/src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/vetkeys/basic_bls_signing/frontend/src/main.ts b/rust/vetkeys/basic_bls_signing/frontend/src/main.ts index a5faff22c..2f5f02d6e 100644 --- a/rust/vetkeys/basic_bls_signing/frontend/src/main.ts +++ b/rust/vetkeys/basic_bls_signing/frontend/src/main.ts @@ -62,7 +62,7 @@ async function initAuth() { authClient = new AuthClient({ identityProvider: isLocalEnv ? "http://id.ai.localhost:8000/authorize" - : "https://id.ai", + : "https://id.ai/authorize", }); const isAuthenticated = authClient.isAuthenticated(); From 06ad3342e181d9e0f6d67106b326179e92909ed5 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Tue, 2 Jun 2026 14:38:00 +0200 Subject: [PATCH 14/14] chore: bump Motoko toolchain to moc 1.9.0 and core 2.5.0 Co-Authored-By: Claude Sonnet 4.6 --- rust/vetkeys/basic_bls_signing/motoko/mops.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/vetkeys/basic_bls_signing/motoko/mops.toml b/rust/vetkeys/basic_bls_signing/motoko/mops.toml index 2d851a475..948e1d22e 100644 --- a/rust/vetkeys/basic_bls_signing/motoko/mops.toml +++ b/rust/vetkeys/basic_bls_signing/motoko/mops.toml @@ -1,7 +1,7 @@ [toolchain] -moc = "1.5.1" +moc = "1.9.0" [dependencies] -core = "2.4.0" +core = "2.5.0" ic-vetkeys = "0.5.0" sha2 = "0.1.14"