Thank you for your interest in contributing to ZeroJ!
-
Install Java 25 (GraalVM recommended):
sdk install java 25.0.2-graal sdk use java 25.0.2-graal
-
Build the project:
./gradlew build
-
Run tests:
./gradlew test
The default build is pure Java. It needs no Go, Rust, Cargo, Node.js, WASM toolchain, or RocksDB JNI.
Everything below is outside the default build and never published (ADR-0044).
BLS/BBS WASM differential oracles (requires Rust stable + the wasm32-unknown-unknown target):
rustup target add wasm32-unknown-unknown
./gradlew -PincludeAssurance \
:zeroj-bls12381-wasm:test :zeroj-bbs-wasm:test :zeroj-bbs:test:zeroj-bbs:test is part of that command on purpose — it is what runs the official CFRG vectors through the WASM provider row. CI runs the same command in .github/workflows/assurance.yml.
gnark PlonK fixture oracle (requires Go 1.24+):
cd assurance/gnark-fixtures && make gen-scratchMPF/JMT load and benchmark tools (requires RocksDB JNI):
./gradlew -PincludeBenchmarks \
:zeroj-mpf-poseidon-load:build :zeroj-jmt-poseidon-load:buildCircuit development / interoperability tests (requires Node.js 18+):
cargo install circom
npm install -g snarkjssnarkjs is an independent prover oracle: ./gradlew :zeroj-integration-tests:e2eTest has snarkjs prove circuits ZeroJ compiled, then verifies them with ZeroJ's pure-Java verifier.
ZeroJ is a Gradle multi-module project. All module names use the zeroj- prefix and all packages start with org.zeroj.
Projects fall into four groups (ADR-0044):
- core product modules at the repository root, constrained by
zeroj-bom-core; - explicit opt-in product modules — also at the root and published, but declared by coordinate and version rather than through the stable BOM:
zeroj-verifier-plonk,zeroj-bbs,zeroj-mpf-poseidon,zeroj-jmt-poseidon; - support projects, never published:
zeroj-test-vectors,zeroj-integration-tests; - opt-in assurance and benchmark projects, outside the default build and never published:
assurance/,benchmarks/.
./gradlew verifyDefaultModuleSurface enforces those boundaries; it runs in CI, snapshot and release. If you add a dependency it rejects, that is the intended signal, not a bug in the check.
See docs/architecture-overview.md for the full module dependency graph and each module's README for details.
- Java 25 — use records, sealed interfaces, and pattern matching where appropriate
- All types in
zeroj-apimust be immutable - Fail fast on malformed input — no silent defaults
- GraalVM native-image compatible — avoid unnecessary reflection
- Include
META-INF/native-image/configs for any new module
- Write tests for new functionality using JUnit 5
- Use test vectors from
zeroj-test-vectorsfor proof-related tests - Run the full suite before submitting:
./gradlew test
- Fork the repository
- Create a feature branch from
main - Write tests for new functionality
- Ensure
./gradlew buildpasses - Submit a pull request
Significant design decisions are documented as ADRs in docs/adr/. Please read the relevant ADRs before making changes to the architecture.