Native Rust Groth16 verification for Solidity on Polkadot Hub, shipped with a live private-voting app.
ZKNative demonstrates the part of Polkadot’s PVM that other EVM-compatible environments do not expose: a Solidity contract can delegate heavy proof verification work to native Rust through PolkaVM FFI.
This repository now includes:
- A live, chain-backed private voting console
- A live proposal dashboard with create and finalize actions
- Browser-side Groth16 proof generation using synced circuit assets
- A Rust verifier for PolkaVM plus a Solidity fallback verifier
- Checked-in trusted setup artifacts for the current voting circuit
The current application focus is private governance: a voter proves eligibility against a Merkle root, commits to a proposal and vote choice, and submits a nullifier-protected ballot without revealing the qualifying wallet on-chain.
| Feature | Ethereum | Solana | Polkadot Hub |
|---|---|---|---|
| Solidity can call native Rust | ❌ | ❌ | ✅ |
| User-deployed Rust verifier path | ❌ | ✅ | |
| EVM app + native verifier in one flow | ❌ | ❌ | ✅ |
| Reusable verifier for multiple privacy apps | ✅ |
With PolkaVM, the verifier logic does not need to be permanently embedded as a protocol precompile. The app contract stays in Solidity, while the heavy cryptography can live in Rust.
- Frontend:
https://zknative.vercel.app - Explorer:
https://westend-asset-hub.blockscout.com - Chain: Polkadot Hub Testnet
- Chain ID:
420420417 - PVM verifier entrypoint:
0x0000000000000000000000000000000000000900
These addresses come from contracts/broadcast/addresses.json.
| Contract | Address |
|---|---|
| ZKNToken | 0xA1D135E125e1C1B5713478266E18d85d66273a48 |
| TimelockController | 0x7c0b03Db2a95bd3352788e236bc8cc1e8fD449A5 |
| VotingGovernor | 0xf7E7080A077ae14eCf13389DC1Fa068aD87e6B76 |
| ZKNativeVerifier | 0x79a8979b0ed0F57CD840e2BBC3CA7071E37913d0 |
| PrivateVoting | 0x4eA0e6Bc7e76ed28CF39381e58fBC6193f5a8b43 |
The repo now contains refreshed verifier constants generated from the checked-in circuit artifacts. If you want the public testnet deployment to match the latest contract source byte-for-byte, redeploy from the current repo state.
- Reads proposal data and the live Merkle root from the deployed
PrivateVotingcontract - Generates Groth16 proofs in the browser using
snarkjs - Checks nullifier reuse before submission
- Submits private votes to the deployed contract through a connected EVM wallet
- Reads
proposalCountand proposal structs directly from chain - Shows real aggregate tallies instead of hard-coded demo data
- Allows authorized operators to create new proposals
- Allows ended proposals to be finalized on-chain
- Circuit assets are synced into
frontend/public/circuitsautomatically duringnpm run devandnpm run build - Deployment metadata is synced into
frontend/public/deployments - The app now ships with a usable
frontend/.env.example
To cast a valid private vote, a voter still needs a correct eligibility bundle:
secretnullifierpathElements[20]pathIndices[20]- The eligible address used in the Merkle leaf
Those values must match the current on-chain Merkle root.
Frontend (Next.js)
└─ snarkjs + synced WASM/zkey assets
↓ castVote(proof, publicSignals)
PrivateVoting.sol
└─ validates proposal window, Merkle root, nullifier, and vote choice
↓ verifyProof(proof, publicSignals)
ZKNativeVerifier.sol
└─ dispatches to PVM native verifier or Solidity fallback
↓ staticcall(0x...0900, abi.encode(...))
PVM Rust verifier
└─ arkworks Groth16 verification on BN254
Current benchmark target for Groth16 verification with 4 public signals:
| Backend | Gas Used | Relative Cost |
|---|---|---|
| PVM Rust on Polkadot | ~180,000 |
1x |
| Solidity verifier on EVM | ~1,850,000 |
~10.3x |
| Solidity verifier on Polkadot Hub | ~1,820,000 |
~10.1x |
The practical point of the project is not just “ZK works on-chain”; it is “ZK verification can be moved into native Rust while keeping the application interface in Solidity”.
git clone https://github.com/RippleOrg/ZKNative.git
cd ZKNative
bash scripts/setup.shbash scripts/compile-circuits.shThis updates:
circuits/build/contracts/src/GeneratedVerifier.solpvm-verifier/keys/voting_vk_placeholder.bin
cp frontend/.env.example frontend/.env.local
cd frontend
npm run devThe frontend automatically copies the latest proving assets into frontend/public/circuits before dev and production builds.
cd contracts
anvil
forge script script/Deploy.s.sol \
--rpc-url http://127.0.0.1:8545 \
--private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
--broadcastnpm run generate-proof -- 1 1The current repo state was checked with:
npm run --prefix frontend lintnpm run --prefix frontend type-checknpm run --prefix frontend buildnpm run test:rustcd contracts && forge build
forge test currently crashes in this macOS environment because of an upstream Foundry/system proxy bug inside system-configuration rather than a Solidity compile failure. The contracts do compile successfully with forge build.
contracts/ Solidity contracts, tests, scripts, broadcast metadata
circuits/ circom circuit, proving assets, verification key output
pvm-verifier/ Rust verifier compiled for the PVM path
frontend/ Next.js application with live vote and results pages
scripts/ setup, benchmarking, proof generation, asset sync
docs/ architecture, deployment notes, roadmap
ZKNative is meant to become a reusable privacy and high-performance verification layer for Polkadot applications.
The voting app is the first product surface, but the larger idea is broader:
- Let Solidity teams keep their app logic and tooling
- Let Rust handle cryptography-heavy or performance-sensitive verification work
- Make privacy-preserving UX normal for governance, claims, credentials, and gated access
- Turn PolkaVM FFI into a general pattern for bringing native libraries into smart-contract apps
- Ship Merkle tree generation and eligibility bundle tooling
- Add a first-class operator flow for allowlist management
- Redeploy the public verifier stack from the latest source state
- Add richer transaction and proof diagnostics in the UI
- Cross-parachain voting and eligibility sources
- Additional privacy app templates beyond governance
- PLONK or universal-setup variants
- Generalize
ZKNativeVerifierfor arbitrary circuit families - Publish SDK tooling for Rust-backed verifier deployment on Polkadot
- Expand from voting into a broader ZK co-processor and privacy infrastructure layer
See docs/roadmap.md for the evolving roadmap.
- OpenGuild Discord:
https://discord.gg/WWgzkDfPQF - Polkadot developer support:
https://t.me/substratedevs
MIT