Test Vectors and Cross-Implementation Checks
1. Why This Chapter Exists
zcash/orchard shares its consensus surface with zcashd,
zebra, and librustzcash. A divergence in any of the
cryptographic primitives is a fork-causing bug. The crate
defends against this with three layers of tests: external JSON
test vectors, a pinned proof binary, and an end-to-end
integration test. After this chapter the reader can locate the
test for any consensus-relevant claim and reproduce it.
2. Definitions
Definition 2.1 (Test Vector)
A tuple of inputs and expected outputs, generated by an
independent implementation, serialised as JSON, and consumed by
the crate's tests via
src/test_vectors.rs.
Definition 2.2 (Pinned Proof)
A serialised Halo 2 proof produced by the crate at a fixed
version. The pinned proof is checked into the repository at
src/circuit_proof_test_case.bin
and re-verified by a unit test on every build.
Definition 2.3 (Circuit Description)
A textual snapshot of the circuit shape (column counts, gates,
lookups, ), stored under
src/circuit_description/.
Any change to the shape must update both the description and the
pinned proof.
3. The Code
3.1 JSON Wiring
loading...
The module loads each JSON file and exposes typed accessors used
by the unit tests in src/keys.rs, src/note.rs,
src/note/nullifier.rs, src/note_encryption.rs, and
src/zip32.rs.
3.2 Source of the Vectors
The vectors are generated by the
zcash-hackworks/zcash-test-vectors
repository. A new test vector is added there first, then mirrored
into this crate via a PR. Open issue
#191 tracks the
gap for ZIP 32 derivation.
3.3 The Pinned Proof Test
The test in
src/circuit.rs
deserialises
src/circuit_proof_test_case.bin
and verifies it with SingleVerifier. The test catches any
change in the transcript byte layout (a common consequence of
bumping halo2_proofs).
3.4 The Integration Scenario
tests/builder.rs
runs the full happy path: build a bundle, prove, sign, verify,
trial-decrypt the output, advance the tree, and chain a second
bundle that spends the new note. It is the single best entry
point for end-to-end debugging.
4. Failure Modes
- Stale JSON vectors. A
librustzcashPR introduces a new vector; the Orchard crate must mirror it within the next release. The mirror is manual. - Pinned proof regeneration without review. Regenerating
the pinned proof bytes is sometimes necessary (a
halo2_proofsbump), but the PR must explain why and the reviewer must re-run a known-good prover. Silently regenerating defeats the purpose of the pin. - Circuit description drift. If the description changes but the proof does not (or vice versa), the test still passes but the audit-tracked shape no longer matches reality. The reviewer must update both.
5. Spec Pointers
zcash-hackworks/zcash-test-vectors: the canonical generator.librustzcash: the parallel client that consumes the same vectors.zebra: the independent Rust full node; divergences surface here first.
6. Exercises
- Run
cargo test --release --features circuitand identify the longest single test. State its name and its file. - Read the integration test in
tests/builder.rs. Which output of the first bundle is fed into the second bundle'sBuilder? Identify the line. - Code task. Flip one byte of
src/circuit_proof_test_case.binin your working copy (do not commit). Run the relevant test and observe the failure mode. Restore the file withgit checkout.
7. Further Reading
- The librustzcash
orchardtest suite: parallel coverage of the same primitives at the consensus boundary. - Zcash test vector RFC for the format conventions.