Crate and Module Map
1. Why This Chapter Exists
The orchard crate is small (about eight thousand lines of Rust),
but it touches every layer of a shielded protocol: curves,
proof system, key tree, encryption, Merkle tree, builder API, and
PCZT. A contributor must know which file owns which concern before
they can change anything; otherwise they will either duplicate
work in the wrong module or break a cross-module invariant. By the
end of the chapter the reader will be able to point at a feature
("a new flag in the Action description", "a different note
plaintext encoding") and name the file they would touch.
2. Definitions
The crate is a single Rust library (no workspace). Its public
surface is declared by pub use and pub mod in
src/lib.rs.
The build is controlled by Cargo features in
Cargo.toml:
default = ["circuit", "multicore", "std"]. The default build includes the Halo 2 Action circuit, multicore IPA, andstd.circuitactivates the Halo 2 prover and verifier and adds dependencies onhalo2_proofsandhalo2_gadgets.unstable-voting-circuitswidens visibility of internal modules (spec,constants) for the voting-circuit work.unstable-frostreserves API surface for FROST multi-party spend authorisation.dev-graphenables circuit visualisation via theplotterscrate.
The crate is #![no_std] (with alloc) and #![forbid(unsafe_code)].
Module Tiers
The modules form four tiers. Lower tiers are not allowed to depend on higher tiers.
- Tier 0 (primitives):
spec,constants,primitives. - Tier 1 (data structures):
address,note,value,tree. - Tier 2 (composition):
keys,zip32,note_encryption,action,circuit. - Tier 3 (transaction):
builder,bundle,pczt.
3. The Code
3.1 Public Re-Exports
loading...
Seven names land at the crate root in this pub use block:
Action, Address, Bundle, the re-exported Merkle depth
constant, three bit-length constants, Note, and Anchor. The
Proof opaque newtype is defined just below this block in the
same file.
3.2 Tier 0: Primitives
src/spec.rshosts the small spec-faithful helpers:to_base,to_scalar,diversify_hash,extract_p,prf_expand,commit_ivk,ka_orchard. They are pure functions of bytes.src/constants.rsre-exports submodule constants and declares the canonical bit-length and depth constants.src/primitives.rsexposes onlyredpallas; see Chapter 14 (RedPallas).
3.3 Tier 1: Data Structures
src/address.rs: the(d, pk_d)payment address type.src/note.rswithcommitment.rsandnullifier.rs: theNotetype, its commitment, and its nullifier.src/value.rs:NoteValue,ValueSum,ValueCommitment.src/tree.rs: the Sinsemilla-based incremental Merkle tree wrapper.
3.4 Tier 2: Composition
src/keys.rsderives every key in the Orchard key hierarchy.src/zip32.rsimplements ZIP 32 hardened derivation on top.src/note_encryption.rsplugs the Orchard-specific KDF and encoding intozcash_note_encryption.src/action.rsis the in-memory representation of one Action description.src/circuit.rsis the Halo 2 Action circuit, with three Orchard-specific chips undercircuit/.
3.5 Tier 3: Transaction
src/builder.rs: the wallet-side API that assembles a list of inputs and outputs into a list of Actions and a witness.src/bundle.rswithbundle/batch.rsandbundle/commitments.rs: theBundletypestate and batch verification.src/pczt.rswith submodulesparse,prover,signer,updater,io_finalizer,tx_extractor,verify: the partially constructed transaction support for split-role signing.
3.6 The Transaction Lifecycle
A wallet building one Action follows the tiers from the bottom up:
- Derive an
ExtendedSpendingKeyfrom a seed (Tier 2). - Locate a spendable
Noteand itsMerklePath(Tier 1). - Open a
Builderand calladd_spend/add_output(Tier 3). Builder::buildconstructs anUnauthorizedBundlecontaining allActiondescriptions and the witness.Bundle::create_proofruns thecircuitprover.Bundle::apply_signaturesproduces the per-Actionredpallasspend-authorising signatures and the binding signature.
4. Failure Modes
- Cross-tier leakage. The
specmodule is supposed to be pure functions of bytes; adding a dependency onkeysornoteturns small spec-faithful primitives into a circular import. Watch for newuse crate::keyslines insrc/spec.rs. - Feature gating on
circuit. The Halo 2 prover and verifier pull inhalo2_proofs, which doubles the compilation time and the binary size. A PR that unconditionally referenceshalo2_proofsfrom a non-circuitfile breaks the--no-default-featuresbuild that downstreamno_stdusers rely on. The CI matrix runsbuild-nostdfor two targets to catch this. - Forgetting the
unstable-voting-circuitswidening. The module re-exports insrc/lib.rsare double-declared with#[cfg(...)]to expose private submodules under the voting feature. New modules must follow the same pattern or they will be unreachable in voting builds.
5. Spec Pointers
- Zcash Protocol Specification:
Section 5.4 is the normative description of Orchard. Read
Section 5.4 alongside
src/lib.rsto confirm which spec concept lives in which module. - ZIP 224: the Orchard activation ZIP. It defines what a "bundle" is from the consensus perspective.
- Orchard Book: the mdBook shipped alongside the crate.
6. Exercises
- Open
src/lib.rsand list every#[cfg(...)]-gatedpub mod. For each, identify the feature that toggles it and the spec or audit reason for the gate. - Run
cargo doc --no-deps --openagainst the crate at the pin. In the rendered docs, click through to a public type in each tier (e.g.Bundle,Note,Address). Confirm that the type only references types of the same or lower tier. - Code task. Add a one-line
tracinglog to a constructor insrc/note.rs(use thelogcrate already used byhalo2_proofs). Runcargo test note::tests::and confirm the log appears. Revert the change. This forces the reader to build the crate end to end.
7. Further Reading
- The previous chapter on the upstream mdBook (Orchard Book) covers the same architecture at a higher level.
- Compare with
zcash/sapling-cryptoto see how the same architecture predates Orchard.