fix(equiv): equivF_abs must check the glob-A oracle footprint on both oracles - #1099
Open
namasikanam wants to merge 1 commit into
Open
fix(equiv): equivF_abs must check the glob-A oracle footprint on both oracles#1099namasikanam wants to merge 1 commit into
namasikanam wants to merge 1 commit into
Conversation
`FunAbsLow.equivF_abs_spec` (and `equivF_abs_upto`) ran `check_oracle_use`
on the right oracle only when it was syntactically equal to the left one.
With two distinct oracle modules where the right oracle writes a global that
belongs to `glob A`, the `={glob A}` obligation was silently dropped while
still asserted in the conclusion, so EC accepted a false
equiv[ A(O1).main ~ A(O2).main : ={glob A} ==> ={res} ]
which `byequiv` turns into `1 = 0`.
Check both oracles unconditionally, each against its own abstract top
(`topl`/`topr`). When either oracle touches `glob A` the `eqglob` obligation
is now correctly required.
This exposes a pre-existing unsoundness in the standard library:
`theories/query_counting/Counter.eca` declares the distinguisher `D` with
`{ -S }` but not `{ -Counter }`, so `Counter.c` is in `glob D` and the
counter-incrementing right oracle writes it. `ind_counting` is therefore
false (a distinguisher that branches on `Counter.c` queries a different
number of times against `S` vs `Counter(S)`). Restrict `D` to `{ -S, -Counter }`
(the file's second section already uses `{ -Counter }`); the stdlib then
builds clean (128/128).
Regression: tests/equivf-abs-oracle-glob.ec (asserts the buggy proof no
longer closes, via the `fail` idiom).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
namasikanam
force-pushed
the
fix/equivf-abs-oracle-glob
branch
from
August 24, 2026 10:02
2cd9f52 to
dbe3d72
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The abstract-function relational rule (
equivF_abs) checks the oracle'sglob Afootprinton the left oracle only. With two distinct oracle modules
O1 <> O2, a write toglob Aby the right oracleO2is never checked, so the={glob A}obligation is droppedwhile still asserted in the conclusion. EC then accepts a false
equiv[ A(O1).main ~ A(O2).main : ={glob A} ==> ={res} ], andbyequivturns it into1 = 0.Root cause
In
FunAbsLow.equivF_abs_spec, theuseflag (whether to include theeqglobobligation)runs
check_oracle_useon the right oracleo_ronly inside theo_l = o_rbranch:For
o_l <> o_rthe right oracle is never checked.equivF_abs_upto(UpToLow) has theidentical asymmetric guard.
Fix (
src/phl/ecPhlFun.ml)Check both oracles unconditionally, each against its own abstract top:
Applied to both
equivF_abs_specandequivF_abs_upto. When either oracle touchesglob A, theeqglobobligation is now correctly required (and the false equiv above nolonger type-checks).
Impact: an existing stdlib lemma is unsound
This is not only synthetic.
theories/query_counting/Counter.ecaproveswith
declare module D <: Distinguisher { -S }—Dis restricted fromSbut not fromCounter, soCounter.c ∈ glob D. The right oracleCounter(S).oraclewritesCounter.c(= writes
glob D), and the dropped right-oracle check is exactly what let this proof through.The lemma is false: a distinguisher that records
c0 := Counter.cand re-queries iffCounter.c = c0queries twice against bareSbut once againstCounter(S), soglob Sdiffers — giving
1 = 0.This PR therefore also fixes the theory:
declare module D <: Distinguisher { -S, -Counter }(the sound restriction; the file's second section already uses
D{-Counter}). With the tacticfix in place the theory compiles, and a
Counter.c-reading distinguisher is correctly no longera valid instantiation.
Test
Must-fail regression
tests/ko/equivf-abs-oracle-glob.ec: the distinct-oracle equiv where onlythe right oracle writes
glob Ais now rejected (the writer-on-left case was already rejected,confirming the asymmetry). The updated
Counter.ecaexercises the fixed theory.