Skip to content

S11: let AliasCheck grant a unique tag, and make Sign require it - #153

Draft
OBrezhniev wants to merge 1 commit into
fix/circomlib_buses_reviewfrom
fix/aliascheck-unique-tag
Draft

OBrezhniev wants to merge 1 commit into
fix/circomlib_buses_reviewfrom
fix/aliascheck-unique-tag

Conversation

@OBrezhniev

Copy link
Copy Markdown
Member

Stacked on #149 (fix/circomlib_buses_review); this PR shows only its own commits. Independent of the other stacked PRs unless stated. Full suite passes on the branch.

Sign computed on bits without an alias check, so the bits of 1 gave sign 0 and the bits of 1+p gave sign 1 for the same field element. AliasCheck was the only checker with no output, so the property could not be expressed. No new constraints in the library.

Let AliasCheck grant a unique tag, and make Sign require it

Sign() promises 0 when in <= p \ 2, but it computes on bits, and a
maxbits()-bit vector does not determine a field element: for x below
2**maxbits() - p, the bits of x and of x + p both satisfy the linear
constraint of Num2Bits(maxbits())(x). Through test/circuits/sign_test.circom
the bits of 1 gave sign 0 and the bits of 1 + p gave sign 1, so a prover
free to choose the decomposition flipped the sign. The library's own uses
in pointbits.circom were safe only because they run AliasCheck first, a
discipline nothing required.

The tag system could not express the property: AliasCheck was the only
checker with no output, so "these bits are alias free" could not travel
with the signals, and unique existed only on the BinaryNumber bus.

AliasCheck now returns its input tagged {binary, unique}; Num2Bits_strict
routes its bits through the check and grants the same; Sign requires it.
No new constraints anywhere: the check that existed is now also a grant.
Bits2Num_strict keeps its internal check and interface.

Callers of Sign must now alias check, which they must for correctness in
any case. sign_test.circom does; its cases for q and for 2**254 - 1,
which are not field elements, are now rejected instead of returning a
sign, and the bits of 1 + q are rejected rather than read as negative.
The bare AliasCheck()(...) statements in binnum_test.circom become
_ <== AliasCheck()(...) since the template now has an output.

🤖 Generated with Claude Code

https://claude.ai/code/session_01D1w729xzwemQigkf3PCisD

Sign() promises 0 when in <= p \ 2, but it computes on bits, and a
maxbits()-bit vector does not determine a field element: for x below
2**maxbits() - p, the bits of x and of x + p both satisfy the linear
constraint of Num2Bits(maxbits())(x). Through test/circuits/sign_test.circom
the bits of 1 gave sign 0 and the bits of 1 + p gave sign 1, so a prover
free to choose the decomposition flipped the sign. The library's own uses
in pointbits.circom were safe only because they run AliasCheck first, a
discipline nothing required.

The tag system could not express the property: AliasCheck was the only
checker with no output, so "these bits are alias free" could not travel
with the signals, and unique existed only on the BinaryNumber bus.

AliasCheck now returns its input tagged {binary, unique}; Num2Bits_strict
routes its bits through the check and grants the same; Sign requires it.
No new constraints anywhere: the check that existed is now also a grant.
Bits2Num_strict keeps its internal check and interface.

Callers of Sign must now alias check, which they must for correctness in
any case. sign_test.circom does; its cases for q and for 2**254 - 1,
which are not field elements, are now rejected instead of returning a
sign, and the bits of 1 + q are rejected rather than read as negative.
The bare AliasCheck()(...) statements in binnum_test.circom become
_ <== AliasCheck()(...) since the template now has an output.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D1w729xzwemQigkf3PCisD
@OBrezhniev
OBrezhniev force-pushed the fix/aliascheck-unique-tag branch from d73ccf8 to e6bcc0e Compare September 29, 2026 20:08
@OBrezhniev
OBrezhniev force-pushed the fix/circomlib_buses_review branch from 7198ad7 to d5f158d Compare September 29, 2026 20:08
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