A zero-knowledge dApp starter template for Neo N3 blockchain developers. This project helps you:
- Write and test ZK circuits in Go
- Generate and verify proofs both on-chain and off-chain
- Deploy ZK-powered smart contracts to Neo N3
Credits to consensys/gnark
for making ZK tech accessible and nspcc-dev/neo-go
for bringing them to Neo developers. Code improvements, feature requests, and new circuit examples are welcomed and appreciated.
This repo includes several example circuits demonstrating common ZK patterns:
-
hash_commit
: Proves knowledge of a preimage for a hash commitment- Use case: Private voting, sealed bids
-
merkle_verify
: Verifies membership in a MiMC-Merkle tree without revealing the set- Use case: Private token transfers, allowlists
-
p256_verify
: Verifies ECDSA signatures on the P256 curve- Use case: Anonymous credentials, private identity verification, recursive proof verification
- Generate and verify a proof locally:
// Generate proof
result, err := api.HashCommitProof(42)
if err != nil {
log.Fatal(err)
}
// Verify locally
verified, err := api.VerifyProof(result.Proof, result.VerifyingKey, result.PublicWitness)
if err != nil {
log.Fatal(err)
}
log.Printf("Proof verified: %v", verified)
- Deploy a circuit-specific verifier contract and verify on-chain
# Generate verifier contract
go run . build -c hash_commit
go run . compile -c hash_commit
# Deploy to Neo N3 and call verify with proof args
verifyArgs := result.VerifyArgs # Contains formatted proof for Neo verification
# See internal/build/build_test.go for complete deployment and verification example
circuits/ # All ZK circuits live here
├── all/ # Imports and registers all circuits
├── hash_commit/ # Hash commitment circuit
├── merkle_verify/ # Merkle tree verification
└── p256_verify/ # P256 signature verification
internal/ # Internal packages
├── build/ # Build process utilities
├── setup/ # Trusted setup utilities
└── util/ # Common utilities
Build a circuit, generate proving/verifying keys:
go run . build -c <circuit_name>
Force rebuild:
go run . build -c <circuit_name> -r
Test a circuit with its ValidInput:
go run . prove -c <circuit_name>
Generate verifier contract:
go run . compile -c <circuit_name>
-
Create a new directory in
circuits/
(e.g.,my_circuit/
) -
Create circuit files:
circuit.go
: Circuit logiccircuit_test.go
: Circuit tests
-
Implement your circuit:
package my_circuit
import (
"neo_zk_starter/circuits"
"github.com/consensys/gnark/frontend"
)
type Circuit struct {
// Private inputs (known only to prover)
SecretInput frontend.Variable
// Public inputs (known to verifier)
PublicOutput frontend.Variable `gnark:",public"`
}
func (c *Circuit) Define(api frontend.API) error {
// Your circuit logic here
// Use api.AssertIsEqual() for constraints
return nil
}
func (c *Circuit) PrepareInput(input interface{}) (circuits.Circuit, []string) {
// Convert raw input to circuit input
// Return (assignment, additionalOutput)
}
func (c *Circuit) ValidInput() circuits.Circuit {
// Return valid test input
}
func init() {
circuits.Register("my_circuit", func() circuits.Circuit {
return &Circuit{}
})
}
- Add your circuit to
circuits/all/all.go
:
import (
// ... existing imports ...
_ "neo_zk_starter/circuits/my_circuit"
)
- Test your circuit:
go test ./circuits/my_circuit -v
- Build your circuit and generate keys:
go run . build -c my_circuit
- Generate the verifier contract:
go run . compile -c my_circuit
-
Deploy the contract to target network using your preferred method.
-
Generate and verify proofs:
// Generate proof
result, err := api.GenerateProof("my_circuit", input)
// Get verification args for smart contract
verifyArgs := result.VerifyArgs
// Use verifyArgs with your deployed contract
Run the test suite:
# Test all circuits
go test ./circuits/... -v
# Test Neo integration
go test ./internal/build -v
The development build uses a simplified setup. For production:
-
Proper Trusted Setup:
- Use a proper phase-1 response file for BLS12-381
- Ensure enough powers of tau for your constraints
- Consider using ZCash Sapling attestations
-
Phase-2 Setup: Replace dummy phase-2 with proper MPC process
-
Security:
- Conduct thorough security audits
- Test extensively with real-world inputs
- Consider circuit size and proof generation time
Remember that ZK proofs are cryptographic primitives - careful review and testing is essential.