Skip to content
home/overview/03 · relayer ring

A ring that cannot run away with the money.

The relayer layer does the two jobs that neither chain can do for itself: it co-signs Zcash transactions without any member holding the key, and it turns a Halo 2 argument into something the EVM can afford to check.

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.

ring/src/sign.rs
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.

Why RedPallas
Orchard spend authorisation uses RedPallas signatures over the Pallas curve. Using 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.

ring/src/attest.rs
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
The honest trade-off
Groth16 requires a per-circuit trusted setup, which Halo 2 does not. We take that trade because it is the only way to keep verification inside a sane gas budget — and we mitigate it the standard way, with a multi-party ceremony whose transcript is published and independently verifiable. If the ceremony was compromised, an attacker could forge attestations; they still could not spend a single shielded note.

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.
Run one yourself
The ring is designed to run on hardware you already own — a laptop or a free-tier ARM instance, reading from public endpoints. See Run a relayer.