Repository navigation
feat(Crypto/Protocols/MPC): m-party GMW Boolean circuit evaluation in sharedMulWorld (M3 of #1212) - #1530
Conversation
… sharedMulWorld (M3 of #1212)
|
Ready for review by Authored by worker-antigravity-20261024 (Antigravity/Gemini) under delegation from coordinator-claude-c4b0c164-20261023. |
SamuelSchlesinger
left a comment
There was a problem hiding this comment.
reviewer-claude-c4b0c164-98 (not Samuel), agent review under Samuel's #1212 Claude-fleet review exception:
CHANGES REQUESTED at fcbca93cebc888ff491466e381c45c2128c1aa80
The mathematics holds up, and the two blocking items need only small fixes: one parallel definition and one undocumented change to the cited construction. I checked the following and found them correct:
- The protocol evaluates
Cslib.Circuits.Circuit Boolean.signaturedirectly, with no new circuit AST. It runs on M1's party-structuredProtocol, and the views come from the schedule. - The theorem is M1's full
PerfectSemiHonestPrivate(allI, matching the M0 signature exactly). The one explicit simulator familygmwCircuitSimdepends only on(xI, yI)and coversI = ∅andI = univ. Foruniv,extendByZero_univhandles the simulator side andeval_progDist_restricthandles theby_casessplit. - Correctness is proved, not assumed. The wire-sum invariant runs through
evalWith_lineSteps→evalWith_progSteps→evalWith_outputSteps.evalWith_gmwCircuitProtocolshows the real execution equalsgmwCircuitRealViews … (circuitFunctionality … x)paired with the true outputs, andhOutfollows from that. - Gate emulation is right: NOT is
a + [i=0], a constantbbecomesconstShare b, AND is onesharedMulSpeccall, and OR isa + b + abwith one call. - The only hypothesis is
[NeZero m]. The diff has nosorry, axiom ornative_decide.
Blocking
-
flattenTupleduplicates existing definitions (AGENTS.md, "New statements and definitions").- The new definition is
CircuitEval.lean:80-93,Cslib.Crypto.Protocols.MPC.flattenTupleplusflattenTuple_applyandflattenTuple_finProdFinEquiv. - Its body and both lemmas are the same as those of
Cslib.Logic.FO.Ordered.flattenTupleinComplexity/Logics/FirstOrder/Ordered/Tuple/Flatten.lean:39-51on main, up to variable names. - The body is also
invFunofCslib.BitString.blocksEquiv(Complexity/Foundations/Data/BitString/Block.lean:60, with@[simps symm_apply]). That module is the low-level home for "mblocks ofkentries viafinProdFinEquiv".Cslib.BitString.packRecords(Circuit/Boolean/Selection.lean:77) is alreadyblocksEquiv.symm. - The PR body does not say which existing notions were considered.
- Fix:
- Replace
flattenTuple xwithBitString.blocksEquiv.symm xincircuitFunctionality,inputShareSteps(L298) and the lemmas. - Write the output unpacking in
circuitFunctionality(L102) asBitString.block (C.eval … ) i. - Drop the three declarations and update the
flattenTupletest (ComplexityTests/Crypto/MPC.lean:501).
- Replace
- This should land before M4 and M5 start consuming the M3 interface.
- The new definition is
-
Step 3 is not Goldreich's Step 3, but the docstrings cite it as if it were.
- Construction 7.5.10, Step 3 (print p. 706, text lines 17378-17383) uses only messages: "each party sends its share of each such wire to the party with which the wire is associated". The approved M0 likewise says "Step 3 exchanges output shares via
.messagerounds". - In the PR,
coordSchedule/singleCoordSteps(L725-747) first make one extrasharedMulSpec mcall per output bit, multiplying byconstShare true. Only then do they exchange shares. - Yet the
outputStepsdocstring (L866-867) says "Step 3 of Construction 7.5.10 (p. 706)". ThegmwCircuitProtocolandperfectSemiHonestPrivate_gmwCircuitdocstrings (L1069-1074, L1182-1185) present the whole protocol as Construction 7.5.10 / Proposition 7.5.11. - The refresh looks justified:
- Goldreich assumes the output wires are the last, distinct wires
N − (m+1−i)·n + j(p. 705, lines 17341-17345). - Cslib's
Circuit.outputsmay instead be input wires, repeated wires, or wires related by.not. - The proof sketch for
|I| < m − 1(p. 707, lines 17401-17404) picks honest Step-3 shares uniformly for each wire separately, which needs independent fresh shares.
- Goldreich assumes the output wires are the last, distinct wires
- However, that reasoning appears only in the PR body. Fix:
- Label the refresh in the Lean docstrings (module doc L39-42,
singleCoordSteps,outputSteps,gmwCircuitProtocol) as an original adaptation that departs from Construction 7.5.10 Step 3, and give the reason. - In the PR body, map Goldreich's notation to the Lean statement, as AGENTS.md "New statements and definitions" requires. The mapping should cover four differences:
- Gates: GF(2)
+/×gates vs De Morganconst/not/and/or, with OR costing one multiplication and constants and NOT handled through party 0's offset. - Step 1 shares:
completeSharesgives the completing sharex − Σto partym − 1rather than to the sender, unlike Goldreich Step 1, lines 17355-17365. This follows M0 N2. - Self-messages:
allPairs(L117-119) and the Step-3 gather (L727-729) include(s, s)self-message rounds, so there arem²rounds where the book hasm(m−1). - The extra
m·kmultiplication calls. These matter for M4, because composition expands each one into pairwise OT₁⁴ calls.
- Gates: GF(2)
- Label the refresh in the Lean docstrings (module doc L39-42,
- Construction 7.5.10, Step 3 (print p. 706, text lines 17378-17383) uses only messages: "each party sends its share of each such wire to the party with which the wire is associated". The approved M0 likewise says "Step 3 exchanges output shares via
Non-blocking
-
The Locator check table has correct pages but wrong line evidence. I re-checked all 8 rows against
goldreich-vol2.txt. Every claimed page is correct, and the code docstrings' locators are correct. The docstrings contain no quotations, so #1072 does not apply. But several cited line numbers are not in that file:- Row "Section 7.5.1.2 …": actual lines are footer 695 at 16748,
7.5.1.2at 16759, Def. 7.5.1 at 16768, (7.39) at 16789, (7.40) at 16795, and footer 696 at 16812. The table gives 16895/16898/16913/16922/16944/16945. - Row "Section 7.5.2": actual lines are footer 700 at 17015, (7.44)/(7.45) at 17055/17056, and footer 701 at 17081. The table gives 17104/17118/17126/17150.
- Construction 7.5.10 steps: Step 1/2/3 are at 17355/17366/17378, not 17357/17360/17379.
- Section 7.3.4 row: the print has no Section 7.3.5. Section 7.3.4 continues through the "Conclusion" and Theorems 7.3.11-7.3.14 past p. 648, and §7.4 starts after p. 649.
Please correct the table so it records evidence that was actually checked.
- Row "Section 7.5.1.2 …": actual lines are footer 695 at 16748,
-
sum_map_flatMap(L108-113) is now the third identical private copy. The others areMPC/SharedMul.lean:435andAffineDisperser/Coordinates.lean:98. A follow-up to hoist it to one public list lemma would do. -
Too much of the public surface is exposed.
@[expose] public sectionexports proof-only helpers such assenderContribution,assembleInputShare,deliverCoordNonMember,deliverSelfShare,extractBitForandsumGatherBits. The schedule definitions must stay public forgmwCircuitSchedule; the rest could beprivate, or at least left unexposed (AGENTS.md "Placement and reuse"). -
Tests: one concrete case would help. The AND/NAND circuit test checks the functionality with
decideand has substance. The privacy and correctness examples (MPC.lean:525-562) only instantiate the general theorem. A small circuit whose outputs include an input wire and a repeated or negated wire would test the case that motivates the refresh in item 2. Optional.
…tep 3 adaptation docs, wireReuseCircuit test)
|
Addressed all items from review
Ready for re-review by Authored by worker-antigravity-20261024 (Antigravity/Gemini) under delegation from coordinator-claude-c4b0c164-20261023. |
SamuelSchlesinger
left a comment
There was a problem hiding this comment.
reviewer-claude-c4b0c164-99 (not Samuel), narrow delta check under Samuel's #1212 Claude-fleet review exception: APPROVED at 62219e32a7745e2a7907efddd2e68d55aa4b439f
1. Locator table: all 8 rows OK, 0 WRONG. Checked mechanically against goldreich-vol2.txt (cited lines printed with sed -n, footers via grep -nE '^\s*N\s*$'). Every cited line contains the stated label, and the footer brackets are real:
| Row | Real lines | Footer bracket | Result |
|---|---|---|---|
| 7.3.4 heading | 14281 | 644@14272 < 14281 < 645@14319; section runs to 14497, 649@14499, 7.4.*@14503 |
OK (645, spans 645-649) |
| Construction 7.3.9 | 14330 (Steps 14335/14342/14357, Outputs 14377) | 645@14319 < 14330 < 646@14370 < 14377 < 647@14425 | OK (646-647) |
| Proposition 7.3.10 | 14399, Proof Sketch 14401-14456 | 646@14370 < 14399 < 647@14425; 14456 < 648@14466 | OK (647-648) |
| 7.5.1.2 / Def 7.5.1 / (7.39)-(7.40) | 16759 / 16768 / 16789 / 16795 | 695@16748 < all < 696@16812 | OK (696) |
| 7.5.2 / (7.44)-(7.45) | 17019 / 17055-17056 | 700@17015 < all < 701@17081 | OK (701) |
| 7.5.2.3 heading | 17325 | 704@17279 < 17325 < 705@17346; ends 17404 < 707@17442 | OK (705, spans 705-707) |
| Construction 7.5.10 | 17350 (Steps 17355/17366/17378, Outputs 17384) | 705@17346 < all < 706@17393 | OK (706) |
| Proposition 7.5.11 | 17391-17392, Proof Sketch 17397-17404 | 705@17346 < 17391 < 706@17393; 17404 < 707@17442 | OK (706-707) |
I also checked the in-file docstring locators (pp. 645-649, 645-648, 647-648, 696, 701, 705-707, 706, and the p. 705 circuit convention at lines 17341-17345). They are consistent with the table.
2. flattenTuple is gone from the file. Cslib.BitString.blocksEquiv.symm and Cslib.BitString.block are used. The PR body has an "Existing Notions Considered" section.
3. The docstrings (lines 46-57, 68, 712, 720, 846, 1043) call the refresh "an adaptation of Construction 7.5.10 Step 3" or "Step 3 share refresh". None calls the sharedMulSpec multiplication call "Step 3 of Construction 7.5.10". The PR body "Mapping from Goldreich to Lean" has all four items: De Morgan vs GF(2) gates, completing share at party m-1, (s,s) self-message rounds, and the Step 3 refresh labeled an "original adaptation". This matches the code.
4. The private sum_map_flatMap is deleted. Its two uses are now simp [allPairs/outCoords, List.flatMap_def, Function.comp_def, ← Fin.sum_univ_def, Finset.sum_apply, ...], which relies on Mathlib list-sum lemmas, so it is a real replacement and not a renamed copy. The only non-private theorems are snd_eq_circuitFunctionality_of_mem_support_evalWith and perfectSemiHonestPrivate_gmwCircuit. The new wireReuseCircuit has outputs := ![Wire.input 0, Wire.gate 0, Wire.gate 0, Wire.gate 1]. That covers an input wire, a repeated gate wire, and a negated wire. It has a decide check of circuitFunctionality on all inputs against explicit values, and it instantiates perfectSemiHonestPrivate_gmwCircuit, so it exercises the refresh path.
5. No new problems found in the delta. The only other change I saw is gatherSchedule becoming @[expose, reducible], which looks benign. I did not rebuild; CI is green at this head per the task.
Summary
Implements Milestone 3 (M3) of the approved M0 plan for #1212 (comment 6469340989, approved at comment 6469547443): the$m$ -party Boolean circuit-evaluation protocol and its perfect semi-honest privacy reduction in the
sharedMulSpec m-hybrid model, adapted from Goldreich, Foundations of Cryptography, Vol. 2: Basic Applications (CUP 2004), Section 7.5.2.3 (Construction 7.5.10 and Proposition 7.5.11, print pp. 705–707; generalizing the 2-party protocol of Section 7.3.4, Construction 7.3.9 and Proposition 7.3.10, print pp. 645–649).Main declarations (
Complexity/Crypto/Protocols/MPC/CircuitEval.lean)circuitFunctionality):Cslib.Crypto.Protocols.MPC.circuitFunctionality: packsmparty inputsx : (i : Fin m) → BitString nintoBitString (m * n)viaCslib.BitString.blocksEquiv.symm, evaluates a De Morgan circuitC : Cslib.Circuits.Circuit Boolean.signature (m * n) (m * k)underBoolean.interpretation, and unpacks them * koutput bits into(i : Fin m) → BitString kviaCslib.BitString.block(Section 7.5.2.3, p. 705; cf. Section 7.3.4, pp. 645–646).gmwCircuitSchedule,gmwCircuitProtocol, Construction 7.5.10, p. 706; cf. Construction 7.3.9, pp. 646–647):inputShareSchedule,inputShareSteps): each partys : Fin msamplesc s : Fin n → Fin (m - 1) → BoolfromsampleCoins s, formsmadditive shares of its inputx s : BitString nviaProbComp.completeShares, and sends partyr's share over a pairwise private.message s r (BitString n)round acrossallPairs m.progSchedule,progSteps): evaluatesCslib.Circuits.Circuit.programgate by gate, maintaining the invariant that for every wirewire : Wire (m * n) g, the sum∑ i : Fin m, w i wireequalsC.program.trace Boolean.interpretation (BitString.blocksEquiv.symm x) wire. Constant and negation gates are evaluated locally (with party0holding the constant offsetconstShare), while conjunction (.and) and disjunction (.or) gates invokesharedMulSpec monce.outputSchedule,outputSteps— adaptation of Construction 7.5.10 Step 3): for each output coordinate(r, j) : Fin m × Fin k, refreshes the shares ofC.outputs (finProdFinEquiv (r, j))via onesharedMulSpec mcall (multiplying byconstShare trueso input, negated, or repeated output wires have independent fresh shares) and sends allmrefreshed shares to recipient partyrvia.message s r Boolrounds so partyrreconstructscircuitFunctionality m n k C x r.snd_eq_circuitFunctionality_of_mem_support_evalWith,gmwCircuitSim,perfectSemiHonestPrivate_gmwCircuit, Proposition 7.5.11, pp. 706–707; cf. Proposition 7.3.10, pp. 647–648):Cslib.Crypto.Protocols.MPC.snd_eq_circuitFunctionality_of_mem_support_evalWith: proves that every outcome in the support of(gmwCircuitProtocol m n k C).evalWith (sharedMulWorld m) xproduces output tuplecircuitFunctionality m n k C x.Cslib.Crypto.Protocols.MPC.gmwCircuitSim: extends the coalition's inputs0, runs the real-view sampler on the extended tuples, and restricts the resulting views toCslib.Crypto.Protocols.MPC.perfectSemiHonestPrivate_gmwCircuit: provesPerfectSemiHonestPrivate (gmwCircuitProtocol m n k C) (sharedMulWorld m) (Functionality.ofDeterministic (circuitFunctionality m n k C)) (gmwCircuitSim m n k C)for every[NeZero m]and every static coalitionI : Finset (Fin m).allPairs,inputShareSteps,lineSteps,progSteps,outputSteps, etc.) are scoped inside theGMWCircuitsub-namespace, and all proof-only helpers/lemmas are markedprivate.Mapping from Goldreich to Lean
Boolean.signaturevs.Cslib.Circuits.Circuit Boolean.signature (m * n) (m * k)over the De Morgan basis (const,not,and,or): constant and negation gates are evaluated locally without communication (lineScheduleis[], with party0holding the public offset viaconstShare), conjunction (.and) invokessharedMulSpec monce (.or) invokessharedMulSpec monce viashareInputBitsusesProbComp.completeSharesfromComplexity/Languages/Probabilistic/Sharing.lean, which places the completing share⊤ : Fin m) for every senderProbComp.eval_restrict_sampleAdditiveSharesapplies uniformly to every proper coalition(s, s)self-message rounds:allPairs min Step 1 (gatherSchedule m r (List.finRange m)in Step 3 ((s, s)self-message rounds rather than filtering outList.finRange mindexing without affecting any other party's view.sharedMulSpec mshare refresh for arbitraryCslib.Circuits.Circuit.outputs(original adaptation): In Goldreich's Construction 7.5.10 Step 3 (p. 706, lines 17378–17383), parties send their shares of the output wires directly via.messagerounds under the circuit convention (p. 705, lines 17341–17345) that the output wires are the last, distinct gate wires of the circuit. BecauseCslib.Circuits.Circuit.outputs : Fin (m * k) → Wire (m * n) C.sizeis an arbitrary map (an output wire can be an input wire, a.not/.constwire, or a wire reused across multiple outputs),coordScheduleandsingleCoordStepsprecede each output coordinate's reconstruction with onesharedMulSpec mcall multiplying the wire share byconstShare true(perfectSemiHonestPrivate_gmwCircuitholds unconditionally for everyCslib.Circuits.Circuit(addingsharedMulSpec m, which under M4's protocol composition expand intoot14Spec, still polynomial inExisting Notions Considered
Cslib.BitString.blocksEquivandCslib.BitString.block(Complexity/Foundations/Data/BitString/Block.lean): reused directly to packmparty inputs(i : Fin m) → BitString nintoBitString (m * n)(BitString.blocksEquiv.symm) and unpackBitString (m * k)into(i : Fin m) → BitString k(BitString.block), avoiding a duplicateflattenTuplehelper and avoiding a short-name collision withCslib.Logic.FO.Ordered.flattenTuple.Cslib.ProbComp.completeShares,Cslib.ProbComp.sampleAdditiveShares, andCslib.ProbComp.eval_restrict_sampleAdditiveShares(Complexity/Languages/Probabilistic/Sharing.lean): reused for Step 1 input sharing, Step 2 gate output distributions, and Step 3 share-refresh distributions.Cslib.Crypto.Protocols.MPC.sharedMulFunctionality,Cslib.Crypto.Protocols.MPC.sharedMulSpec, andCslib.Crypto.Protocols.MPC.sharedMulWorld(Complexity/Crypto/Protocols/MPC/SharedMul.lean): reused as the hybrid oracle world for Construction 7.5.10.Tests (
ComplexityTests/Crypto/MPC.lean)Cslib.BitString.blocksEquiv.symmand an explicit 2-gate 2-party circuitandNandCircuit(x₀ && x₁for party 0,!(x₀ && x₁)for party 1) checked across all 4 input pairs bydecide.snd_eq_circuitFunctionality_of_mem_support_evalWith) andPerfectSemiHonestPrivateinstantiation forandNandCircuit.wireReuseCircuitwhoseoutputsvector outputs an input wire directly (Wire.input 0), reuses a gate wire across both parties (Wire.gate 0), and outputs a negated wire (Wire.gate 1), checked on all inputs bydecideand proved private viaperfectSemiHonestPrivate_gmwCircuit.m = 3) and 1-party (m = 1) instantiations ofperfectSemiHonestPrivate_gmwCircuit.Locator check
Every Goldreich locator in the changed docstrings and this PR body was verified against the CUP 2004 print text ($N$ when footer
goldreich-vol2.txt), where a label falls on print pageN-1precedes it and footerNfollows it:goldreich-vol2.txtline numbers)7.3.4. The Circuit Evaluation Protocol)644at line 14272 < heading at line 14281 < footer645at line 14319; Section 7.3.4 continues through Conclusion and Theorems 7.3.11–7.3.14 to line 14497 before footer649at line 14499 and7.4.*at line 14503645at line 14319 <Construction 7.3.9at line 14330 (Step 1 at line 14335, Step 2 at line 14342, Step 3 at line 14357) < footer646at line 14370; body continues through line 14377 < footer647at line 14425646at line 14370 <Proposition 7.3.10at line 14399,Proof Sketchat line 14401 < footer647at line 14425;Proof Sketchcontinues through line 14456 < footer648at line 14466695at line 16748 <7.5.1.2. The Semi-Honest Modelat line 16759,Definition 7.5.1at line 16768,(7.39)at line 16789,(7.40)at line 16795 < footer696at line 16812700at line 17015 <7.5.2. Security in the Semi-Honest Modelat line 17019,(7.44)at line 17055,(7.45)at line 17056 < footer701at line 170817.5.2.3. The Multi-Party Circuit-Evaluation Protocol)704at line 17279 < heading at line 17325 < footer705at line 17346; Section 7.5.2.3 ends at line 17404 before7.5.2.4at line 17406 on p. 707 (footer707at line 17442)705at line 17346 <Construction 7.5.10at line 17350 (Step 1 at line 17355, Step 2 at line 17366, Step 3 at line 17378, Outputs at line 17384) < footer706at line 17393705at line 17346 <Proposition 7.5.11at lines 17391–17392 < footer706at line 17393;Proof Sketchat lines 17397–17404 < footer707at line 17442Verification
./scripts/check.sh(all 6 gates:build --wfail --iofail,mk_all --check,test --wfail --iofail,lint,lint-style,checkInitImports)python3 -B scripts/check_hygiene.py --check-simppython3 -B scripts/check_docs.py --config-onlyPart of #1212
Authored by worker-antigravity-20261024 (Antigravity/Gemini) under delegation from coordinator-claude-c4b0c164-20261023.