Skip to content

fix: EQ over cross-kind SigmaProps throws when the left is a conjecture#888

Open
mwaddip wants to merge 1 commit into
ergoplatform:developfrom
mwaddip:fix/sigmaprop-eq-conjecture-throw
Open

fix: EQ over cross-kind SigmaProps throws when the left is a conjecture#888
mwaddip wants to merge 1 commit into
ergoplatform:developfrom
mwaddip:fix/sigmaprop-eq-conjecture-throw

Conversation

@mwaddip

@mwaddip mwaddip commented Jun 7, 2026

Copy link
Copy Markdown

Scala DataValueComparer.equalSigmaBoolean (DataValueComparer.scala:253) dispatches on the LEFT node: the leaf arms (ProveDlog/ProveDHTuple/TrivialProp) return false on a mismatched right, but the conjecture arms are guarded (case CAND(children) if r.isInstanceOf[CAND]), so a conjecture left vs a different-kind right falls through to the top-level sys.error — eval THROWS, asymmetrically: (pkA && pkB) == pkA throws, pkA == (pkA && pkB) is false. NEQ shares the comparer; children recurse, so nested mismatches throw too.

Our Eq/NEq used derive-PartialEq (symmetric false): a guard script the JVM rejects-with-exception validated under sigma-rust.

Fix: SigmaProp==SigmaProp goes through an equalSigmaBoolean mirror. Tests drive four JVM-blessed byte vectors plus unit pins.

Scala DataValueComparer.equalSigmaBoolean (DataValueComparer.scala:253)
dispatches on the LEFT node: the leaf arms (ProveDlog / ProveDHTuple /
TrivialProp) return false on a mismatched right via their inner
`case _ => false`, but the conjecture arms are guarded
(`case CAND(children) if r.isInstanceOf[CAND]`), so a conjecture left
against a different-kind right falls through every arm to the top-level
`case _ => sys.error(...)` and script evaluation THROWS. The behavior is
asymmetric: `(pkA && pkB) == pkA` throws while `pkA == (pkA && pkB)` is
false, and NEQ shares the comparer. Children recurse through
equalSigmaBoolean, so nested mismatches inside matching tops throw too.

Our Eq/NEq used derive-PartialEq, returning symmetric false everywhere —
a guard script the JVM fails-with-exception evaluated to false and
validated under sigma-rust.

Route SigmaProp = SigmaProp through an equalSigmaBoolean mirror: matched
leaves compare structurally; matched conjectures recurse (length mismatch
false before children; Cthreshold k mismatch short-circuits before
children); on a kind mismatch a leaf left is false and a conjecture left
is an EvalError carrying the JVM message.

Regression tests drive the four JVM-blessed byte vectors from the
conformance corpus (santa-eval EQ_of_SigmaProp_conjecture_mismatch,
parse blessed bytes -> eval) plus unit pins for the NEQ twin, the nested
throw, structural recursion, and both short-circuits.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant