A desktop wallet and signing companion for threshold-controlled Zcash funds.
Cyze puts a graphical interface on ZF FROST threshold signatures, built on the Zcash Foundation's frost-tools. It lets a group of people jointly control a Zcash wallet where no single person ever holds the full private key — a configurable threshold (e.g. 2-of-3) must cooperate to authorize any spend.
Cyze is in beta and has not been security-audited. It targets the Ironwood (NU6.3) network upgrade and depends on some release-candidate Zcash libraries (
zcash_client_backend/zcash_client_sqlite). Do not use it to hold funds you cannot afford to lose. You are solely responsible for backing up your key shares and recovery code, and for any transaction you broadcast. No warranty is provided. Start on testnet, and if you use mainnet, use small amounts.
- Key ceremonies (DKG) — create or join a distributed key generation ceremony. The private key is split into shares across participants and never exists in one place.
- Threshold signing — coordinate a signing session (the coordinator can also be a signer), or participate through an inbox with an explicit review/approve step before your signature share is produced.
- Zcash wallet (Ironwood) — for RedPallas groups: sync from a lightwalletd server with a pipelined light-client scanner, view the group's Ironwood shielded balance, receive to a rotating group address (with QR), and send — each spend is authorized by a live FROST signing ceremony among the group. Sends build V6 transactions post-NU6.3. Any legacy Orchard funds are surfaced only when present, with a one-tap sweep into Ironwood. The app focuses on one active wallet at a time — selecting a group makes it the sole wallet the app syncs and acts on. Includes on-chain and local transaction/message history, and an in-app diagnostics log for troubleshooting.
- Coinholder voting — cast a Zcash coinholder-poll vote from a group: paste the poll's published ballot, answer, and the vote is delivered as a shielded memo (Vote Cast Memo v1) to the poll's reception address through the same FROST signing path. Vote weight is set by the poll's balance snapshot, not the wallet.
- ZcashNames (ZNS) — send to a human-readable
name.zcashin the recipient field: it is resolved to a unified address via the public ZNS indexer and shown for you to confirm before signing (the resolver is external, never an authorization). - Server hosting — run the
frostdcoordination server embedded (auto-generated, pinned self-signed TLS), and expose it to off-LAN peers either through a built-in Cloudflare tunnel (public HTTPS URL, no port-forwarding) or over Tailscale (a stable*.ts.nettailnet address with automatic, publicly-trusted TLS — tailnet-only, not public), or point at any externalfrostd. - Contacts & groups — a per-group view with public key material, named participants, receive addresses, and share-repair guidance.
Supports both frost-tools ciphersuites: Ed25519 (generic signing) and RedPallas (re-randomized FROST for Zcash shielded spend authorization).
- Key shares and contacts live in an envelope-encrypted keystore: a random
data key (XChaCha20-Poly1305) is wrapped under both your passphrase and a
one-time 12-word BIP-39 recovery code (Argon2id), so either can unlock, and
changing one doesn't invalidate the other. The plaintext is byte-compatible
with upstream
~/.config/frost/credentials.toml, so an existing frost-client config imports in one step. - The recovery code is shown once at setup behind an explicit acknowledgement and is never stored — it is your only way back in if you forget the passphrase. Back it up.
- All ceremony messages are end-to-end encrypted (Noise, via frost-client);
frostdis an untrusted relay. - Self-signed server certificates are pinned explicitly (trust-on-first-use with fingerprint display), never blanket-accepted. A Cloudflare tunnel presents a publicly valid certificate, so peers using its URL skip cert trust.
- Signers see the exact message (hex + UTF-8) and must approve before their round-2 signature share is computed. Round-1 commitments are message-independent, so nothing is at risk before approval.
On first launch you set a passphrase and a display name, and are shown a one-time recovery code to back up. A typical first run:
- Setup — start (or connect to) a
frostdserver, add contacts. - New DKG — run a key-generation ceremony with your group to create a shared wallet.
- Groups — open the group; for a RedPallas group, its Wallet page shows the receive address and balance.
- Send — enter a recipient and amount; the app runs a signing ceremony with the chosen threshold of members, then broadcasts the transaction.
📖 User Walkthrough & Testing Guide — a detailed, step-by-step guide covering security setup, contacts, hosting/joining a server, the DKG ceremony, building and approving transactions, and configuration. Follow it in order to fully test and vet the application.
Prerequisites:
- Rust (1.92+), Node 18+
- Tauri Linux system deps:
sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libdbus-1-dev librsvg2-dev libayatana-appindicator3-dev build-essential
npm install
./scripts/build-sidecar.sh # REQUIRED — see below
npm run tauri dev # development
npm run tauri build # native installers (AppImage/deb/…)build-sidecar.sh is not optional. The app bundles two sidecar binaries, and
Tauri refuses to build unless both are present for your host's target triple:
frostd— the coordination server, built fromfrost-toolsat the pinned revision (scripts/PINNED_REV). It must match thefrost-clientdependency insrc-tauri/Cargo.tomlor client and server disagree on the wire format.cloudflared— downloaded from Cloudflare's releases, so the optional public-tunnel feature needs no separate install or PATH entry.
The script fetches both. Skip it and the build fails late with
resource path 'binaries/cloudflared-<triple>' doesn't exist. The binaries land
in src-tauri/binaries/ (gitignored), so a fresh clone always needs this step.
Windows builds run natively (MSVC + Node) or via WSL2; build a Windows frostd
sidecar and target nsis/msi. To run two instances on one machine (e.g. to
play coordinator and participant), give the second its own data dir:
FROST_APP_DATA_DIR=/tmp/frost-app-2 npm run tauri devSee docs/RELEASE.md for packaging and sidecar details.
The core crate is Tauri-free and fully testable headlessly:
cd src-tauri && cargo test -p frost-app-coretests/ceremony_e2e.rs spawns a real frostd and runs complete 3-party DKG +
2-of-3 signing ceremonies over TLS for both ciphersuites, plus a rejection path;
keystore tests cover the envelope format and recovery code. A headless smoke test
drives the full Tauri command layer (cargo test -p frost-app --test smoke).
src-tauri/core—frost-app-core: keystore, frostd transport (pinned-cert TLS), DKG/signing ceremony engines, the Zcash wallet/PCZT send path (Ironwood, plus legacy Orchard) and pipelined sync driver, coinholder-poll voting (voting.rs), and ZcashNames resolution (zns.rs). No Tauri dependency.src-tauri/src— Tauri adapter: commands, event forwarding, sidecar lifecycle.src/— React + TypeScript frontend.scripts/PINNED_REV— the frost-tools revision used for both thefrost-clientlibrary dependency and thefrostdsidecar build (they must match for wire compatibility).
See repository headers. Third-party components (frostd, cloudflared) are
redistributed under their own licenses.