Cross-Chain Privacy: Midnight + Cardano Zero-Knowledge Integration
Cardano provides strong settlement guarantees, but all state is public. For applications that need private computation (secret ballots, hidden hands, confidential business logic), that's a real limitation. By integrating Midnight's ZK-native design with Cardano, EffectStream applications can have public settlement on Cardano with private state via Midnight's zero-knowledge proofs.
The privacy gap on Cardano
Cardano's UTxO model is transparent by design: every transaction, every datum, every output is visible on the public ledger. That's great for financial transparency, but it's a problem for applications that need private state:
- Voting: ballots should stay private until the vote closes
- Games: hidden hands, fog-of-war, and secret strategies need private state
- Business logic: competitive information shouldn't be visible to rivals
Midnight is a privacy-focused blockchain with native zero-knowledge proof support. Combining Cardano's settlement with Midnight's private computation gives applications the best of both worlds.
Private Delegation Voting template
To show this cross-chain privacy pattern in practice, we built a Private Delegation Voting template that combines Cardano stake pool delegation data with Midnight's ZK proofs for private ballot casting.
Here's the concept: a governance vote where voting power comes from your Cardano stake pool delegation, but your actual vote stays private. The system proves via zero-knowledge that:
- The voter has a valid Cardano delegation (verified on-chain)
- The vote was cast correctly (the ballot is well-formed)
- The voter hasn't voted twice (nullifier prevents double-voting)
...without revealing which pool the voter delegates to or how they voted. The delegation data comes from Cardano via EffectStream's PoolDelegation primitive, and the privacy layer runs on Midnight.

The full ZK-Cardano template is available in the monorepo alongside five new Cardano primitives.
How it works
EffectStream uses a "funnel" abstraction to read data from multiple blockchains through a unified interface. Adding a new chain means implementing a new funnel; the developer's state machine receives events from all configured chains without needing to know each chain's data format.
For the Midnight + Cardano integration:
- Cardano funnel reads delegation state via Dolos/UTxORPC (who delegates to which pool, how much stake)
- Midnight funnel reads ZK proof submissions and private state transitions
- EffectStream state machine combines both data sources, verifying delegation eligibility from Cardano while preserving vote privacy from Midnight
The batcher system supports Midnight wallets via @effectstream/wallets, which provides unified wallet support across EVM, Cardano, Midnight, Polkadot, Algorand, and Mina. Users can sign transactions with Midnight wallets, making it a first-class chain in the framework.
Beyond voting: the privacy pattern
Private Delegation Voting is one application of the Cardano + ZK pattern, but the architecture generalizes. Any scenario where public chain data needs private processing fits:
- Private governance - vote with your Cardano stake without revealing your position
- Hidden-hand games - use Cardano NFTs as game pieces with hidden state on Midnight
- Confidential analytics - prove facts about on-chain data without revealing the underlying data
- Anonymous credentials - prove you meet criteria (delegation amount, token holdings) without identifying yourself
Each follows the same template: read public state from Cardano, process it privately on Midnight, publish only the ZK proof.
Local ZK proof generation
Beyond chain-integrated ZK, EffectStream also supports computing zero-knowledge proofs locally, without settling to any ZK chain. This removes the network dependency while keeping the privacy guarantees:
- Lower latency (no network round-trip)
- Lower cost (no on-chain fees for proof verification)
- Offline capability (proofs can be generated without network access)
The trade-off is in verification: chain-verified proofs inherit the chain's security guarantees, while locally-verified proofs need the application to validate them. For many use cases (anti-cheat in games, client-side validation), local proofs are sufficient and quite a bit faster.
Template: Werewolf (multiplayer ZK with browser proofs)
The clearest worked example of local proofs is Werewolf — a multiplayer Mafia-style template where every player's role, night action, and vote stays private behind a ZK proof. The Compact contract tracks alive players in a Merkle tree and uses nullifiers to prevent double-voting; each player-side proof is generated in the browser before the input reaches the game server.

The night/day loop is structured around two ZK actions:
- Night action — werewolves submit an encrypted target with a ZK proof that they hold the werewolf role. The role itself never appears in any log.
- Vote — any alive player votes to eliminate, attaching a ZK inclusion proof against the alive-player Merkle root plus a nullifier so the same player can't vote twice.
The full stack runs locally with no external dependency: Midnight node, indexer, proof server, game server, and frontend all spin up from the template's README. Template source: effectstream/werewolf-game.
A second template, Go Fish, uses the same local-proof pattern for ZK Mental Poker — trustless card games without a dealer, with all card commitments and reveals proved client-side.