opencircom
v0.2.0
Published
Reusable Circom ZK circuit templates — hashing, comparators, Merkle trees, and more. No dependency on circomlib.
Maintainers
Readme
opencircom

Reusable Circom ZK circuit templates: hashing, comparators, Merkle trees, nullifiers, and utilities. No dependency on circomlib.
Use in your project
Add the circuits folder to your include path and include templates:
include "opencircom/circuits/hashing/poseidon.circom";
include "opencircom/circuits/comparators.circom";
include "opencircom/circuits/merkle/merkle_inclusion.circom";
template MyCircuit(levels) {
signal input secret;
signal input pathElements[levels];
signal input pathIndices[levels];
signal output root;
component hasher = Poseidon(1);
hasher.inputs[0] <== secret;
component tree = MerkleInclusionProof(levels);
tree.leaf <== hasher.out;
for (var i = 0; i < levels; i++) {
tree.pathElements[i] <== pathElements[i];
tree.pathIndices[i] <== pathIndices[i];
}
root <== tree.root;
}If you clone or link this repo as opencircom in your project root, compile with:
circom your.circom --r1cs --wasm -o build -l opencircom/circuitsInclude in Hardhat or Foundry
Install
From npm:
npm install opencircomOr add to your package.json: "opencircom": "^0.2.0".
Hardhat
Add
opencircomas a dependency (see Install).In your Circom build step (e.g. Hardhat plugin or script), pass the package circuits as the include path:
circom circuits/YourCircuit.circom --r1cs --wasm -o build -l node_modules/opencircom/circuitsUse snarkjs (or your flow) to generate the verifier contract; deploy or import it in your Hardhat tests.
Foundry
- Add
opencircomvia npm (npm install opencircom) or as a Git submodule:git submodule add https://github.com/jose-blockchain/opencircom.git lib/opencircom - In a script, run
circomwith the opencircom circuits on the include path:- npm:
-l node_modules/opencircom/circuits - submodule:
-l lib/opencircom/circuits
- npm:
- Use snarkjs (or circom) to generate the Solidity verifier; put the generated
.solinsrc/. - Run
forge buildandforge test; your Solidity code calls the verifier contract as usual.
Circuits
| Category | Template | Description |
|-----------|--------------------------|-------------|
| Hashing | Poseidon(nInputs) | Hades Poseidon (configurable width). |
| Hashing | MiMC7(nrounds), MultiMiMC7(nInputs, nRounds) | MiMC-7. |
| Hashing | Sha256(nBits) | SHA-256 (FIPS 180-4). Input length in bits; padding is applied. |
| Comparators | LessThan(n), GreaterThan(n), IsEqual(), IsZero() | Range and equality. |
| Comparators | StrictNum2Bits(n) | Num2Bits with in ∈ [0, 2^n−1] enforced. |
| Comparators | RangeProof(n) | Prove a ≤ x ≤ b (inputs x, a, b; n-bit range). |
| Bitify | Num2Bits(n), Bits2Num(n) | Bit decomposition (see also compconstant.circom, aliascheck.circom). |
| Gates | AND, OR, NOT, XOR, MultiAND(n) | Boolean gates. |
| Utils | Mux1, Mux2, Switcher | Multiplexer and conditional swap. |
| Merkle | MerkleInclusionProof(levels) | Binary Merkle inclusion. |
| Merkle | SparseMerkleInclusion(levels), SparseMerkleExclusion(levels) | Sparse Merkle: prove leaf at key equals value, or is empty. |
| Merkle | IncrementalMerkleInclusion(levels) | Append-only tree: prove leaf at numeric index. |
| Merkle | MerkleUpdateProof(levels) | Prove old root → new root by changing one leaf on the same path. |
| Identity | Nullifier(domainSize) | Nullifier hash for double-spend prevention. |
| Voting | VoteCommit(numChoices), VoteReveal() | Commit-reveal (commit phase + reveal with ZK), anonymous 1-of-N vote, tally verification, double-vote prevention (nullifier-based). |
Potential circuits to add (roadmap)
Planned or community-requested templates (not yet implemented):
- Hashing: Pedersen (Baby Jubjub), Keccak-256.
- Signatures: EdDSA verify (Baby JubJub), ECDSA verify (secp256k1).
- Merkle: (Sparse inclusion/exclusion, incremental, update proof are implemented.)
- Comparators & range: (Range proof and StrictNum2Bits are implemented.)
- Arithmetic: Safe division with remainder, modular exponentiation, sum/inner product, aliasing-safe field checks.
- Encryption: ElGamal encrypt/decrypt, ECDH shared secret, symmetric (Poseidon-based).
- Identity & credentials: Semaphore-style identity commitment, selective attribute disclosure, age/threshold proof (attribute > N without revealing).
- Set membership: Merkle-based allowlist, non-membership proof (sparse Merkle), accumulator-based membership.
- Payments & finance: Balance proof (balance ≥ amount without revealing), confidential transfer, mixer (deposit/withdraw).
- String & data: Regex matching (in-circuit), JSON field extraction, UTF-8 validation, substring search.
- Utilities: MuxN, array contains / index of, padding (PKCS, zero-pad).
Contributions welcome; open an issue to propose or prioritize.
Security
- Range checks: Use
LessThan(n)withnlarge enough for your values; combine withNum2Bitswhen you need strict field bounds. - Merkle: Enforce
pathIndices[i]binary (circuit does this). - Nullifier: Use a unique
externalNullifierper action to avoid cross-action replay. - Hashing: Poseidon uses standard Hades parameters (same as circomlib spec); constants are in
circuits/hashing/poseidon_constants.circom.
See SECURITY.md for more.
Tests
Tests use real ZK where applicable: circuits are compiled with Circom, then a small Powers of Tau and zkey are generated, and a Groth16 proof is created and verified with snarkjs (no mocks).
Coverage (79+ tests): Poseidon, SHA-256, Comparators (incl. StrictNum2Bits, RangeProof), Gates, Bitify, Merkle (inclusion, sparse, incremental, update), MiMC, Mux1/Mux2, Switcher, Nullifier, Voting, and one full Groth16 prove/verify.
npm install
npm testThe first run runs setup:zk (ptau + zkey generation) and can take about a minute.
License
MIT
