Threshold signing with FROST
Bridges historically fail at the custody boundary — a multisig with five signers, three of whom share an office. FROST changes the shape of that risk. The ring generates a single group key through distributed key generation; no participant ever holds it, and no participant can reconstruct it. Signing takes two rounds and produces a signature that looks, on the Zcash side, exactly like an ordinary single-signer spend.
1use frost_redpallas as frost;2 3// Round 1 — every participant publishes a nonce commitment.4let (nonces, commitments) = frost::round1::commit(5 participant_secret.signing_share(),6 &mut rng,7);8 9// Round 2 — each share signs the same Zcash sighash.10let signing_package = frost::SigningPackage::new(commitment_map, &sighash);11let share = frost::round2::sign(&signing_package, &nonces, &key_package)?;12 13// Aggregation — t-of-n shares become one ordinary Schnorr signature.14let group_signature = frost::aggregate(15 &signing_package,16 &signature_shares,17 &public_key_package,18)?;19 20// On-chain, this is indistinguishable from a single-signer spend.21assert!(public_key_package22 .verifying_key()23 .verify(&sighash, &group_signature)24 .is_ok());Two properties matter here. First, the threshold is enforced cryptographically rather than procedurally — there is no contract to upgrade or admin to compromise. Second, the output leaks nothing about the ring: an observer cannot tell a 7-of-11 Z-Relay spend from any other Zcash transaction, which keeps Z-Relay users inside the chain's full anonymity set instead of a smaller Z-Relay-shaped one.
frost-redpallas rather than a generic Ed25519 FROST implementation means the threshold signature is native to the pool — no adapter, no wrapper, no second signature to verify.Proof compression
A shielded Zcash transaction carries a Halo 2 proof. Halo 2 is recursive and needs no trusted setup, which is excellent for Zcash and useless for the EVM: verifying one on-chain would cost more gas than a block contains.
The ring resolves this by moving the expensive verification off-chain and attesting to the result. A relayer verifies the Orchard bundle with librustzcash, then produces a small Groth16 proof over BN254 — the curve with precompiled pairing support at EIP-197 prices.
1// Off-chain: verify the real thing, then attest to it cheaply.2let orchard_bundle = tx.orchard_bundle().expect("shielded outputs");3orchard_bundle.verify_proof(&orchard::circuit::VerifyingKey::build())?;4 5let public_inputs = PublicInputs {6 zcash_block_root: anchor, // finalised block Merkle root7 nullifier, // proven unspent at this height8 claim_hash, // keccak(viewing-key decryption)9 min_balance, // the threshold being asserted10};11 12// Groth16 over BN254 — the only curve the EVM prices reasonably.13let proof = groth16::create_random_proof(14 AttestationCircuit { witness, public_inputs },15 &proving_key,16 &mut rng,17)?;- Native proof
- Halo 2 · Pallas / Vesta · no trusted setup
- Compressed proof
- Groth16 · BN254 · per-circuit setup
- Proof size
- 3 group elements (~192 bytes)
- On-chain cost
- ~180,000 gas
- Prover location
- Relayer, or the user's own browser
- Public inputs
- anchor · nullifier · claimHash · minBalance
Aggregation and batching
Attestations are queued and batched. Because each proof is only a few hundred bytes and verification dominates cost, the ring amortises submissions across a batch window — one calldata payload, many claims. Developers paying in $ZRL get priority placement in that queue, which is the practical meaning of “gas subsidy” in the token design.
What keeps the ring honest
- Stake. Signing requires bonded $ZRL. The bond is slashable and denominated in the asset whose value depends on the protocol continuing to work.
- Falsification is provable. A relayer that submits an attestation against a Zcash root that does not exist produces evidence anyone can replay. Slashing needs no vote.
- Withholding is unprofitable. Events are public and any node may serve any request, so declining to relay simply forwards the fee to a competitor.
- Liveness has a floor. Below the signing threshold the escrow refunds. The worst outcome of total ring failure is that nothing happens.