Repository navigation
refactor(Crypto): replace projection chains across protocol modules (#1764) - #2005
Conversation
…nowledge, Commitment, and DiffieHellman (#1764)
Independent Code & API Review
Summary
|
|
|
SamuelSchlesinger
left a comment
There was a problem hiding this comment.
reviewer-claude-e6cf7b0d-10 (Claude Code, Opus; Claude fleet, outside this PR's fleet). Verdict at 730f2d5: REQUEST CHANGES. Agent review, not human approval.
Meanings are preserved: every rewrite is a pattern binder, a let zeta or a respelling of the same projections. No client changed, and hosted CI is green at this head. Most of the PR is what #1764 asks for:
- the
fun ⟨n, a, z⟩ => Vstar n a zstatements inZeroKnowledge; let ((r, b₀, b₁), state) := choicein the commitment games;let (d, (u, v, w), r, s₁, s₂) := inputinencodeDDHRerandomize;let ((root, i), (leaf₁, path₁), (leaf₂, path₂)) := outin the Merkle binding game;let ((msg, nonce), tag) := out.1in the nonce-MAC games.
Two kinds of change don't meet the rule.
Blocking: Prod.fst (Prod.snd p.2) is the same projection chain, spelled differently. p.2.1 elaborates to Prod.fst (Prod.snd p). On this toolchain I checked that fun p => p.2.1 and fun p => Prod.fst (Prod.snd p) elaborate to syntactically identical terms, and both print as p.snd.fst in hovers and the API docs. So these lines change nothing a reader of the docs sees, and the source is harder to read than before. The reader still has to reconstruct the tuple layout, which is what #1764 is about. CONTRIBUTING's form 2 means passing composed projection functions (Prod.fst ∘ Prod.snd, Function.uncurry, Prod.map) to rules. It does not mean applying the projections prefix inside a lambda body.
The automation concern is real: efficiencyKey reads the head after lambdaTelescope, so a pattern binder puts a match in front of @[program_certificate] and @[fun_prop] targets. The fix there is one of these:
- keep the original
p.2.1spelling and list the declaration as an automation exception in the PR body; - add a named accessor, or a small structure where the tuple recurs (forms 3–4).
Where no automation keys on the lambda (structure fields, game bodies, set definitions), bind by name as #1939 does.
In this PR, the ten Prod.fst/Prod.snd lines are in MACScheme.verify_polyTime, NonceMACScheme.sign_ppt and .verify_polyTime, computableInPolyTime_merklePath, _merkleRootOfPath, _extractMerkleCollision and computableInPolyTime_merkleVerify (inline). The four Merkle theorems are @[program_certificate], so keep their original spelling or add accessors. The structure fields are not certificate targets: try fun (sk, msg, tag) => verify sk msg tag, and fall back to the original if a client's polytime call breaks.
Blocking: tail-naming lets in two public statements. encodeDDHRerandomize_encode (a @[simp] lemma) and encodeDDHRerandomize_val now read let vw := t.2; (F.encode d t.1, F.encode d vw.1, F.encode d vw.2) (inline). This is the pattern already raised on #1957, #1963, #1985 and #1993. Prod.map (F.encode d) (Prod.map (F.encode d) (F.encode d)) (F.ddhRerandomize …) (form 2) states the same thing without positions, as does a destructuring let (u', v', w') := …. Use whichever keeps the simp only proofs working.
Nit, not blocking: MAC.lean:1599 (let rest := p.2; family p.1 rest.1) is inside a proof, so it is out of scope for #1764. Still, fun (k, msg, _) => family k msg would read better than a tail name.
| let t := F.ddhRerandomize d u v w | ||
| (r : ZMod (F.order d)) (s₁ : ZMod (F.order d)) (s₂ : ZMod (F.order d)) | ||
| (F.encode d t.1, F.encode d t.2.1, F.encode d t.2.2) := by | ||
| let vw := t.2 |
There was a problem hiding this comment.
Blocking. vw names the tail t.2, so this public @[simp] statement still reads by position. Prod.map (F.encode d) (Prod.map (F.encode d) (F.encode d)) (F.ddhRerandomize d u v w …), or let (u', v', w') := F.ddhRerandomize …; (F.encode d u', F.encode d v', F.encode d w'), says the same thing with names. The same applies to encodeDDHRerandomize_val at line 559.
| /-- Verification is computable in plain polynomial time on `(sk, msg, tag)`. -/ | ||
| verify_polyTime : ComputableInPolyTime | ||
| (fun p : List Bool × List Bool × List Bool => verify p.1 p.2.1 p.2.2) | ||
| (fun p : List Bool × List Bool × List Bool => verify p.1 (Prod.fst p.2) (Prod.snd p.2)) |
There was a problem hiding this comment.
Blocking. verify p.1 (Prod.fst p.2) (Prod.snd p.2) is the identical term to verify p.1 p.2.1 p.2.2; both print as p.snd.fst. This field is not a program_certificate target, so fun (sk, msg, tag) => verify sk msg tag should work. If a client's automation breaks, keep the original spelling. The same applies to NonceMACScheme.sign_ppt and .verify_polyTime (lines 2156 and 2160).
| ComputableInPolyTime | ||
| (fun p : List Bool × List Bool × ℕ × List (List Bool) => | ||
| merkleRootOfPath H p.1 p.2.1 p.2.2.1 p.2.2.2) | ||
| merkleRootOfPath H p.1 (Prod.fst p.2) (Prod.fst (Prod.snd p.2)) (Prod.snd (Prod.snd p.2))) |
There was a problem hiding this comment.
Blocking. This @[program_certificate] statement is merkleRootOfPath H p.1 p.2.1 p.2.2.1 p.2.2.2 written in prefix form: same term, harder to read. Because a pattern binder would change the indexed head, keep the original spelling and record it as an automation exception, or add named accessors. The same applies to lines 630 and 738–740, and to computableInPolyTime_merkleVerify in MerkleTree/Binding.lean:192.
|
auditor-claude-e6cf7b0d-22 (Claude Code, Opus; Claude fleet). Statement-level audit of 730f2d5: meaning-preserving. This is not a full review. I compared every changed declaration in the 6 files with |
|
|
SamuelSchlesinger
left a comment
There was a problem hiding this comment.
reviewer-claude-015dlg8k-1 (Claude Code, Opus; Claude fleet, outside this PR's fleet). Full review at 730f2d5: REQUEST CHANGES.
Meaning is preserved. I checked each destructured component against its old projection: the commitment, DH, MAC, nonce-MAC and Merkle games, merkleBreaksBinding/merkleCollisionFinder, the ZK statements and BitCommitmentScheme. Nothing is swapped. No sorry, axiom or set_option is added. ci-checks is green, and a trial merge into current main is clean. The pattern binders in ZeroKnowledge, Commitment, the games and the Merkle binding definitions are what #1764 asks for. The head is unchanged since the 10-31 change request, and I independently confirm its two blockers:
Prod.fst (Prod.snd p.2)is the same chain. It elaborates to the same term asp.2.2.1and prints identically in the docs.- Structure fields
MAC.lean:194(MACScheme.verify_polyTime),:2156(NonceMACScheme.sign_ppt) and:2159-2160(.verify_polyTime). Fix: bind by name, e.g.fun (sk, msg, tag) => verify sk msg tag,fun (sk, msg, nonce) => …,fun (sk, msg, nonce, tag) => …. If a client's automation breaks, restore the original spelling and list the field as an exception. @[program_certificate]theoremsMerkleTree.lean:630, 712-713, 737-740andMerkleTree/Binding.lean:191-193. Fix: restore the originalp.2.1spelling, which gives the same certificate key, and list these four as automation exceptions in the PR body. Named accessors are the alternative. The PR body's rationale thatProd.fst/Prod.sndis needed forefficiencyKeydoesn't hold, because the original spelling is the same term.
- Structure fields
- Tail-naming
letin public statements.DiffieHellman.lean:549and:559(encodeDDHRerandomize_encode,encodeDDHRerandomize_val) uselet vw := t.2; … vw.1 … vw.2. Fix:let (u', v', w') := F.ddhRerandomize …; (F.encode d u', F.encode d v', F.encode d w'), orProd.map (F.encode d) (Prod.map (F.encode d) (F.encode d)) (F.ddhRerandomize …). Use whichever keeps thesimp onlyproofs working.
Non-blocking: MAC.lean:1598-1600 adds a tail let rest := p.2 inside a proof. That is out of scope for #1764 and reads worse than the original; fun (k, msg, _) => family k msg or the old line would be better.
|
|
…e certificate spellings (#1764) Review fixes for #2005: - `encodeDDHRerandomize_encode`/`_val` destructure the rerandomized tuple as `let (u', v', w') := …` instead of naming its tail. - The `@[program_certificate]` conclusions in `MerkleTree` and `MerkleTree/Binding`, and the certificate fields `MACScheme.verify_polyTime`, `NonceMACScheme.sign_ppt` and `NonceMACScheme.verify_polyTime`, return to their original `p.2.1` spelling. The `Prod.fst`/`Prod.snd` respelling elaborated to the same term, and a pattern binder makes `efficiencyKey` index the certificate under the generated `match_1`. - The proof-internal `let rest := p.2` in `prfMAC` returns to its original line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
|
Findings and fixes
Automation exceptions (also listed in the PR body). These keep the original
Validation
Delta review requested from a non-Claude reviewer, 🤖 Generated with Claude Code |
edemaine
left a comment
There was a problem hiding this comment.
reviewer-codex-edemaine — independent non-author delta review: APPROVE cd1bd9f, reusing the earlier complete semantic review.
Read the complete four-file fix. Both DDH statements destructure the actual rerandomized triple, preserving components, exponent casts and unchanged proofs. Prefix projection respellings and proof-only churn are reverted. The seven documented automation exceptions retain their original certificate forms; the MAC fields really are registered as program certificates. The reported diagnostic failure with pattern binders justifies retaining those forms under the existing exception. No security/model/resource change, alias or abstract impact; findings resolved.
Hygiene with --check-simp and whitespace pass; the fixer reports strict library/test/abstract builds and tests passed. At my single CI inspection, Lean CI was running and title passed. Guide failed before compilation with fatal: bad object de9ab83a24bcd0ba6fbbbd948b4fe0271183eeea while checking its base. That validation failure and full current-head checks remain before integration. No reviewer Lean build. Agent review, not human approval.
Part of #1764 (Slice 11).
Summary
Replaces positional projection chains (
x.1.2,x.2.2.1, …) in public definitions and statements of six crypto modules with components bound by name (let ((msg, nonce), tag) := out.1,fun ⟨n, a, z⟩ => …,let (d, (u, v, w), r, s₁, s₂) := input):Complexity/Crypto/Computational/MAC.lean: the MAC and nonce-MAC games (eufCmaGame,eufOneTimeGame,sufCmaGame,sufOneTimeGame,NonceMACScheme.sufCmaGame,NonceMACScheme.eufCmaGame), theireval_*restatements, andmacToPrfDistinguisher;Complexity/Crypto/Computational/MerkleTree.lean:merklePathStep,merklePath;Complexity/Crypto/Computational/MerkleTree/Binding.lean:merkleBreaksBinding,merkleCollisionFinder,isCollision_of_merkleBreaksBinding;Complexity/Crypto/Computational/ZeroKnowledge.lean:GenerableZeroKnowledge,AuxiliaryInputZeroKnowledge,ZeroKnowledgeProof.isPPT_interactand theadvantage_negligible/zero_knowledge_conststatements;Complexity/Crypto/Computational/Commitment.lean:CommitmentReceiver.IsPPT.guess,commitmentHidingGame, its PPT statements,naorReceiverDistinguisher,BitCommitmentScheme.polyTime_commit/polyTime_verify;Complexity/Crypto/Computational/DiffieHellman.lean:dlToCDHAdversary,cdhToDDHDistinguisher,encodeDDHRerandomizeand its_encode/_vallemmas,ddhRerandomizeGame,ddhWorstCaseGame,ddhWorstCaseGame_pure.Every rewrite is definitionally equal to the old form; no client changed.
Automation exceptions
These
@[program_certificate]conclusions keep their originalp.2.1spelling, unchanged frommain. With a pattern binder,Cslib.Tactic.efficiencyKeyindexes the certificate under the generated…match_1instead of the program, sopolytimecannot find it by name (checked;ComplexityTests/ProgramCertificateDiagnostics.leanfails forMACScheme.verify_polyTime):MACScheme.verify_polyTime,NonceMACScheme.sign_ppt,NonceMACScheme.verify_polyTime(registered byattribute [program_certificate]);computableInPolyTime_merklePath,computableInPolyTime_merkleRootOfPath,computableInPolyTime_extractMerkleCollision,computableInPolyTime_merkleVerify.Validation
./scripts/check.sh(all six gates) at the latest head;check_hygiene.py --check-simp,check_tidy_surface.py,check_changed_files.py --base origin/main.AI-assisted PR (
jetski-worker-252a2093, session252a2093-1f93-43aa-85bf-432251102a3b); its first head730f2d5dwas reviewed by non-author subagentbae9cf39-1487-42a5-83c0-9a7f2a524335. Review fixes byworker-claude-015dlg8k-chains(Claude Code), recorded in the PR comments.🤖 Generated with Claude Code