This PR adds an `@[mvcgen_witness_type]` tag attribute, analogous to `@[mvcgen_invariant_type]`, that allows users to mark types as witness types. Goals whose type is an application of a tagged type are classified as witnesses rather than verification conditions, and appear in a new `witnesses` section in the `mvcgen` tactic syntax (before `invariants`). Witnesses are concrete values the prover supplies (inspired by zero-knowledge proofs), as opposed to invariants (predicates maintained across iterations) or verification conditions (propositions to prove). The test uses a ZK-inspired example where a `SquareRootWitness` value must be provided by the prover, with the resulting constraint auto-discharged. Changes: - `src/Lean/Elab/Tactic/Do/Attr.lean`: register `@[mvcgen_witness_type]` tag attribute and `isMVCGenWitnessType` helper - `src/Lean/Elab/Tactic/Do/VCGen/Basic.lean`: add `witnesses` field to `State`, three-way classification in `addSubGoalAsVC` - `src/Std/Tactic/Do/Syntax.lean`: add `witnesses` section syntax (before `invariants`), extract shared `goalDotAlt`/`goalCaseAlt` syntax kinds - `src/Lean/Elab/Tactic/Do/VCGen.lean`: extract shared `elabGoalSection`, add `elabWitnesses`, wire up witness labeling and elaboration - `tests/elab/mvcgenWitnessType.lean`: end-to-end tests for witness-only, witness with `-leave`, and combined witness+invariant scenarios 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
71 lines
2.5 KiB
Text
71 lines
2.5 KiB
Text
import Std.Tactic.Do
|
|
import Std
|
|
set_option backward.do.legacy false
|
|
|
|
open Std Do
|
|
|
|
set_option grind.warning false
|
|
set_option mvcgen.warning false
|
|
|
|
-- Test that `@[mvcgen_witness_type]` works end-to-end.
|
|
--
|
|
-- In zero-knowledge proofs, a witness is a concrete value the prover privately knows
|
|
-- (e.g. a field element), as opposed to an invariant (a predicate maintained across
|
|
-- iterations) or a verification condition (a proposition to prove).
|
|
--
|
|
-- We model this by axiomatizing a circuit-like computation that requires a concrete
|
|
-- witness value. The `mvcgen` tactic classifies the witness goal as `witness1` and
|
|
-- the constraint as `vc1`.
|
|
|
|
-- A witness type: a concrete value the prover supplies (not a predicate).
|
|
@[mvcgen_witness_type]
|
|
structure SquareRootWitness where
|
|
root : Nat
|
|
|
|
-- An axiomatized circuit that verifies a square root claim.
|
|
opaque checkSquareRoot (n : Nat) : Id Bool
|
|
|
|
-- Spec: given a witness w whose root squares to n, the circuit returns true.
|
|
-- When mvcgen applies this spec, `w` becomes a metavariable of witness type,
|
|
-- and the precondition `w.root * w.root = n` becomes a verification condition.
|
|
@[spec]
|
|
axiom checkSquareRoot_spec {n : Nat} (w : SquareRootWitness) :
|
|
Triple (checkSquareRoot n) ⌜w.root * w.root = n⌝ (⇓ r => ⌜r = true⌝)
|
|
|
|
def verifySquareRoot : Id Bool := do
|
|
checkSquareRoot 9
|
|
|
|
-- mvcgen produces:
|
|
-- witness1 : SquareRootWitness (concrete value to provide)
|
|
-- vc1 : 3 * 3 = 9 (constraint, auto-solved after witness instantiation)
|
|
-- The prover supplies ⟨3⟩ as the witness; the constraint is then trivially true.
|
|
theorem verifySquareRoot_correct :
|
|
⦃⌜True⌝⦄ verifySquareRoot ⦃⇓ r => ⌜r = true⌝⦄ := by
|
|
mvcgen [verifySquareRoot] witnesses
|
|
· ⟨3⟩
|
|
|
|
-- With -leave, the VC remains for manual discharge.
|
|
theorem verifySquareRoot_manual :
|
|
⦃⌜True⌝⦄ verifySquareRoot ⦃⇓ r => ⌜r = true⌝⦄ := by
|
|
mvcgen -leave [verifySquareRoot] witnesses
|
|
· ⟨3⟩
|
|
with omega
|
|
|
|
-- Demonstrate that witnesses and invariants can coexist, with witnesses first.
|
|
|
|
-- A program that first checks a witness and then loops over a list.
|
|
def witnessAndLoop (xs : List Nat) : Id Nat := do
|
|
let mut s := 0
|
|
let _ ← checkSquareRoot 9
|
|
for x in xs do
|
|
s := s + x
|
|
pure s
|
|
|
|
-- Both witnesses (before invariants) in the mvcgen syntax.
|
|
theorem witnessAndLoop_correct (xs : List Nat) :
|
|
⦃⌜True⌝⦄ witnessAndLoop xs ⦃⇓ _ => ⌜True⌝⦄ := by
|
|
mvcgen [witnessAndLoop] witnesses
|
|
· ⟨3⟩
|
|
invariants
|
|
· ⇓ _ => ⌜True⌝
|
|
with grind
|