Skip to content

feat: allow modifying the upper bound in bits.ToBinary - #1809

Open
zexoverz wants to merge 1 commit into
Consensys-Incorporated:masterfrom
zexoverz:feat/tobinary-upper-bound
Open

feat: allow modifying the upper bound in bits.ToBinary#1809
zexoverz wants to merge 1 commit into
Consensys-Incorporated:masterfrom
zexoverz:feat/tobinary-upper-bound

Conversation

@zexoverz

@zexoverz zexoverz commented Aug 18, 2026

Copy link
Copy Markdown

Closes #1434.

ToBinary compares the decomposition against the native modulus minus one, which is the weakest bound that still keeps the decomposition unique. Callers who already know their value lives in a smaller range had no way to say so, which came up in the discussion on #1420.

WithUpperBound sets that constant. Two guards come with it. A bound at or above the modulus is rejected, because it readmits the a / a+r ambiguity the check exists to prevent. And it is refused alongside OmitModulusCheck, since one asks for a bound check and the other removes it.

The part worth reviewing closely is that an explicit bound always enforces the comparison, including when WithNbDigits is below the field bitlength and the check would otherwise be skipped. The digit count implies its own bound, not the caller's, so without this WithNbDigits(8) together with WithUpperBound(100) would have silently constrained nothing. There is a test for exactly that case.

Constant inputs are checked at compile time, matching how WithNbDigits already reports an out-of-range constant.

With the option unset every path is unchanged. Tests run across the curves and backends via CheckCircuit; std/rangecheck, std/math/cmp and std/selector still pass.


Note

Cursor Bugbot is generating a summary for commit d8cd6fa. Configure here.

Closes Consensys-Incorporated#1434.

ToBinary compares the decomposition against the native modulus minus one, which
is the weakest bound that still keeps the decomposition unique. Callers who know
their value lives in a smaller range had no way to say so.

WithUpperBound sets that constant. It is rejected at or above the modulus, since
a larger bound readmits the a / a+r ambiguity the check exists to prevent, and it
is refused alongside OmitModulusCheck because the two ask for opposite things.

An explicit bound always enforces the comparison, including when WithNbDigits is
below the field bitlength and the check would otherwise be skipped: the digit
count does not imply the caller's bound. Constant inputs are checked at compile
time, matching how WithNbDigits already reports an out-of-range constant.

With the option unset every path is unchanged.
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.

feat: allow modifying the upper bound in bits.ToBinary

1 participant