Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The Knowledge-Soundness Contract

The Action circuit's knowledge-soundness result is one theorem, orchard_action_adaptiveStatement_knowledge_error_bound. Reading it tells you a probability is bounded — not what is bounded, what a successful extraction hands back, or what that thing certifies. Those live in the layers that prove it.

Zcash/Snark/Contract/ gathers them: KnowledgeContract is a record with one field per question an auditor must answer, and actionKnowledgeContract is its instance for the deployed circuit. The layer proves nothing new — it re-exports the definitions the theorem is stated in and applies the theorem itself unchanged, which is why its census pin carries exactly the endpoint's axiom footprint. The one substantive demand the record makes of an instance is the witness_statement field, discussed below. This page reads the instance in order.

The six questions

1. What is a run?

A generator random-oracle table and one Fiat–Shamir transcript, drawn independently. The URS basis is read from the table by orchardGeneratorROBasis, modelling halo2's parameter derivation (, , ) — a modelling assumption, not a theorem.

The adversary is adaptive in the statement: it outputs the public inputs and the proof together, and both the canonical verifying key and every selected instance commitment enter the transcript before the first challenge, so the statement cannot be chosen after seeing it. The adversary is also algebraic: its output type requires every emitted group element to carry a representation over the basis. That is a restriction on which adversaries the bound covers at all, not an assumption that can be discharged.

2. When does the verifier accept?

ComputedAdaptiveActionStatementFSFamily.accepts: halo2's checked acceptance at the adversary's own selected inputs and proof, over the URS read from the oracle table. This is DeployedAccepts, the verifier's entire check collapsed into one multiscalar multiplication — acceptance means the assembly succeeds and that MSM evaluates to zero. It is the deployed verifier's own condition, not a reformulation chosen to be convenient.

3. What does extraction return?

An ActionTerminal.ActionBundleWitness: the private witnesses of every Action in the bundle, packaged with proofs that they satisfy ActionSpec at the public inputs the adversary selected. It lives in Type — data a program can hold and inspect, not a proposition that a witness exists somewhere. The extractor is a total function; returning none is what extraction failure means, and that failure is the only event the bound is about.

("Executable" describes the extractor where the proving layer defines and checks it. The contract record is noncomputable — its law is a PMF, which Lean cannot run — and neither adds nor needs a computability check of its own.)

4. What does a returned witness certify?

BundleStatement: every Action in the bundle satisfies the circuit's statement at the public inputs the adversary selected. This field carries the weight — a bound on "accepted but extraction returned nothing" is worthless if extraction may return junk. witness_statement forecloses that: a returned witness entails the statement, and stating it as a field means no instance can quietly omit it.

5. What is the failure event?

Accepted, yet extraction returned nothing. Both conjuncts matter: a rejected run is not a failure, and neither is an accepted run that yielded a witness.

6. What is the error?

The endpoint's compositional formula: the adversary's discrete-log advantage at its query and group-work counts, plus , plus a per-query term collecting the Schwartz–Zippel budgets of each challenge surface. At the work-factor target it lands on , whose two arguments are the random-oracle query count and the group-operation count.

What the contract does not say

Completeness is not implied. That some run accepts, or that an honest prover's proof extracts, is a separate property. Nothing here rules out the vacuous case: a contract whose acceptance predicate holds nowhere satisfies every field. Read the contract as a bound on the adversary, never as evidence that the circuit works.

Ordinary soundness is not advertised separately — because it is free. On a false statement the extractor must have returned none, since a returned witness would have entailed it. So acceptFalseStatement_le gives the soundness bound at the same error for every contract, and no separate endpoint is advertised for it.

The ledger security capstones do not follow from it. The contract ends at ActionBundleWitness. The formal continuation begins, per Action, at Zcash.Security.Ledger.Bridge.actionSpec_to_ledger, which consumes the public input, private witness, and ActionSpec proof — and returns an ActionBreak or an existentially witnessed ledger statement in Prop, not an executable ledger witness. The ledger security capstones build on that handoff, and they depend on knowledge soundness rather than settle for less: they are stated in the witness-level model, over ledger actions that already carry witnesses, and extraction is what supplies those for a merely proof-carrying bundle. What this contract does not do is discharge that step for the deployed circuit — the witness-level model abstracts Halo 2 knowledge soundness away, and relating the two is a separate reduction on the different Halo 2 bases.

The assumptions are not fields of the record. They are the arguments of actionKnowledgeContract: a nonzero generator, an injective oracle-parameter query, the family-construction obligations, and the generic AdaptiveStatementDlogProfile, whose proverGroupWork and reductionGroupWork are caller-supplied labels with finderAdvantageLE the corresponding DLOG advantage bound. (The operationally accounted route is separate: AdaptiveStatementAdversaryCostCertificate and CertifiedAdaptiveStatementDlogProfile feed orchard_action_adaptiveStatement_certified_knowledge_error_bound.) Two more conditions are structural, carried by the adversary's type: the algebraic restriction above and the random-oracle modelling of the challenge schedule. What trusting each of these means is the subject of Security Models, and the Guide to the Ironwood Formalization states them in plain language.

Why the record is not Action-specific

KnowledgeContract is stated for any circuit. Action is its only instance because it is the only circuit carrying an advertised capstone — the other circuits are components composed into its specification. And the shape already recurs: the ledger security games pair a break event, a containment showing the event covers the property, and a bound — the same three moves as failure, witness_statement, and knowledge_sound. Keeping the record generic is what stops the second circuit's contract from becoming a second bespoke tree.