Skip to content

feat(emulated): checkZero mulcheck in hint#1749

Closed
shramee wants to merge 1 commit into
Consensys:masterfrom
mistcash:1748-assert-mulcheck
Closed

feat(emulated): checkZero mulcheck in hint#1749
shramee wants to merge 1 commit into
Consensys:masterfrom
mistcash:1748-assert-mulcheck

Conversation

@shramee
Copy link
Copy Markdown
Contributor

@shramee shramee commented Apr 12, 2026

closes #1748

Description

Is your feature request related to a problem? Please describe.
When an emulated element assert fails, it's hard to track the point of failure.

This is because when mulcheck is returned by the hint, the remainder is swapped out with zero, which is very constraint efficient.
However, a failing assert only triggers much later in deferred check call, making it hard to track the bug.

Describe the solution you'd like

Instead of adding a failing mulcheck in assert, assert call can tell the hint if a particular mulcheck should have zero remainder (forward existing isMulMod var) to the hint, and then hint can fail on computation itself allowing for easy error tracking.

This will make sure only valid mulchecks are added to deferred checks. And have better devX for writing emulated circuits.

Describe alternatives you've considered
Tried script for debugging (thanks @ivokub). Which helped with the debugging :)
But I believe this should be cleaner.

Additional context
Almost ended up thinking mulchecks weren't working properly for my large unruly overflowing emulated elements. Validated the added mulcheck in some python playground. It was failing. Found out about assert calls setting mulcheck rem to 0.

With this, we'll have no extra constraints, and error call stacks will provide easier path to follow for finding issues.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How has this been tested?

  • All emulated tests for BN254 fields

How has this been benchmarked?

  • na -

Checklist:

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • I did not modify files generated from templates
  • golangci-lint does not output errors locally
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

Note

Medium Risk
Modifies the mulHint input contract and adds an early error path in a core emulated-field hint; could change when/where failing circuits error and may break any callers that assume the old hint input layout.

Overview
Propagates a checkZero flag into the multiplication hint inputs (via callMulHint), extending the hint’s input header by one value.

Updates mulHint to parse the new flag and, when invoked for checkZero/mulcheck cases, fail immediately if a*b mod p produces a non-zero remainder, instead of letting an invalid mulcheck surface later during deferred verification.

Reviewed by Cursor Bugbot for commit 434bd2d. Bugbot is set up for automated code reviews on this repo. Configure here.

@ivokub
Copy link
Copy Markdown
Collaborator

ivokub commented May 22, 2026

Thanks @shramee for the PR. I completely agree currently debugging emulated circuits is a bit cumbersome particularly because we do the deferred checks and the actual failing constraints do not match the call site in the circuit definition.

However, on the other hand we try to be not opinionated for circuit definition and solving, i.e. we want the users to be able to define unsolvable witness.

I think for debugging purposes we would have to make the emulated gadget a bit more helpful, i.e. we should track the call stack instead in -tags debug mode which points to concrete failing place in the circuit. This is for example how API works for native computation. And when we don't use the debug tag we still get the meaningless "constraint failed" without call stack information.

@ivokub
Copy link
Copy Markdown
Collaborator

ivokub commented May 22, 2026

Thanks @shramee for the PR. I completely agree currently debugging emulated circuits is a bit cumbersome particularly because we do the deferred checks and the actual failing constraints do not match the call site in the circuit definition.

However, on the other hand we try to be not opinionated for circuit definition and solving, i.e. we want the users to be able to define unsolvable witness.

I think for debugging purposes we would have to make the emulated gadget a bit more helpful, i.e. we should track the call stack instead in -tags debug mode which points to concrete failing place in the circuit. This is for example how API works for native computation. And when we don't use the debug tag we still get the meaningless "constraint failed" without call stack information.

I created a new issue #1773 for tracking the implementation and will address it separately in a more comprehensive manner.

@ivokub ivokub closed this May 22, 2026
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.

fix(emulated): checkZero mulcheck should fail in hint

2 participants