test(blobs): pin the fracs hint's root-of-unity contract and widen its coverage - #25450
Merged
Merged
Conversation
…s coverage The barycentric formula only holds off the evaluation domain, so `compute_fracs` and `compute_factor` require `z^d != 1`. Make that explicit: - `compute_factor` already has `z^d` in-circuit, so it asserts `z^d != 1` there with bignum's `assert_is_not_equal` (a few gates, sound against the `+MOD` alias). `validate_fracs` has no solution at a root anyway, so this changes no accepted statement; it names the precondition in one place. - The `__compute_fracs` hint asserts the same condition on its own `z^d` instead of deriving every entry from an inverse of zero and returning an all-zero array. Its doc comment states the precondition and drops the claim that a root behaves as under batch inversion: `batch_invert` skipped the one zero denominator and returned the other 4095 fractions intact. Tests: - check the defining relation at every index for a corpus of eleven challenges (zero, small values, both sides of each 120-bit limb boundary, -2 and -3 at the top of the field, and a Poseidon2-sized value) instead of one - assert every fraction is -1 at z = 0 - the hint rejects z = 1, -1 and ROOTS[1000] with its own message, and `compute_factor` rejects a root in-circuit - `validate_fracs` rejects a root even when handed an array that is correct at every other index, showing the constraint has no solution independent of the hint - pin the squared-parent property ROOTS[2u]^2 == ROOTS[u] that the final level of the halving relies on, alongside the existing adjacent-negation check - reject a corrupted fraction at the last index, not only at index 0 Rejections that fail inside bignum's `evaluate_quadratic_expression` stay plain `should_fail`: that assertion carries no message and bignum is left untouched.
TomAFrench
approved these changes
Sep 10, 2026
TomAFrench
marked this pull request as ready for review
September 10, 2026 14:18
TomAFrench
requested review from
IlyasRidhuan,
LeilaWang,
iAmMichaelConnor,
iakovenkos and
ledwards2225
as code owners
September 10, 2026 14:18
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.
Follow-up to #25444, targeting its branch
cb/blob-fracs-halving. One squashed commit; the diff touches onlynoir-projects/fnd/noir-protocol-circuits/crates/blob/src/blob.nr. The vendored bignum crate is untouched.Why
The halving in
__compute_fracsderives all 4096 inverses from one inversion ofz^d - 1, so it requiresz^d != 1. #25444's comment and body say a root-of-unity challenge "behaves as before". It does not:batch_invertskipped the single zero denominator and returned the other 4095 fractions intact, whereas the halving returns all zeros. The difference is unobservable (at a rootfactor = 0soy_i = 0either way, andvalidate_fracshas no solution there), but the claim was wrong and the precondition was implicit.What changes
compute_factoralready hasz^din-circuit, so it assertsz^d != 1there with bignum'sassert_is_not_equal(a few gates, sound against thez^d = 1 + MODalias).validate_fracsis unsatisfiable at a root anyway, so this changes no accepted statement; it names the precondition in one place. It is a small ACIR change, so perf(blobs): derive the blob fracs by halving the roots of unity #25444's "The ACIR is untouched" no longer holds once this lands.__compute_fracshint asserts the same condition on its ownz^dwith the messageblob challenge z is a d-th root of unityrather than returning an all-zero array. Its doc comment states the precondition and drops the equivalence claim.Tests
-2and-3at the top of the field, and a Poseidon2-sized value) instead of one.-1is deliberately absent: it isROOTS[1], a root of unity.-1atz = 0.z = 1,-1andROOTS[1000]with its own message (should_fail_with), andcompute_factorrejects a root in-circuit withassert_is_not_equal fail.validate_fracsrejects a root even when handed an array that is correct at every other index (built withbatch_invert, exactly the old hint), showing the constraint itself has no solution independent of the hint.ROOTS[2u]^2 == ROOTS[u], which the final level of the halving relies on, is pinned next to the existing adjacent-negation check.Rejections that fail inside bignum's
evaluate_quadratic_expressionstay plainshould_fail: that assertion carries no message, and giving it one belongs in a bignum change rather than here.Ran the full
blobcrate with the repository-pinned compiler (Noir 1.0.0-rc.0,fae3abca7e51): 53 tests pass, up from 45 at the #25444 head.Analysis and derivation: https://gist.github.com/AztecBot/bfe643f0f99557cf0f6266eefb433c55
Created by claudebox · group:
slackbot· requested by Mike (@iAmMichaelConnor) · Slack thread