Skip to content

fix: Barrett reduction bug for primes with large quotient error - #36

Open
quangvdao wants to merge 2 commits into
a16z:dev/twist-shoutfrom
quangvdao:quang/fix-barrett-reduction
Open

fix: Barrett reduction bug for primes with large quotient error#36
quangvdao wants to merge 2 commits into
a16z:dev/twist-shoutfrom
quangvdao:quang/fix-barrett-reduction

Conversation

@quangvdao

Copy link
Copy Markdown
Collaborator

Summary

  • Bug: The Barrett reduction in mul_u64 / barrett_reduce_nplus1_to_n can underestimate the quotient q by 2 for certain primes (those where 2^{n_p-1}/p + (2^{n_p+63} mod p)/2^{n_p} >= 1). This produces a remainder r >= 4p, which the existing 3-way conditional subtraction (handling up to 3p) cannot reduce to canonical Montgomery form. Affected primes include BLS12-381 Fq, BLS12-377 Fr/Fq, Pallas/Vesta, secp256r1, and Curve25519. BN254 Fr/Fq and secp256k1 are not affected.
  • Fix: Use ceil(c / 2^{n_p}) instead of floor when computing the approximate high part of c. This makes the two rounding errors partially cancel, guaranteeing |q - m| <= 1. When the estimate overestimates (borrow on c - m*2p), we add 2p back. The remainder is then always in [0, 4p), which the existing conditional subtraction handles correctly.
  • Compile-time gating: A new const BARRETT_NEEDS_CEIL, computed from MODULUS and BARRETT_MU via exact bigint remainder arithmetic (const_remainder! macro), gates the fix. Primes where the original algorithm is safe (e.g., BN254) pay zero overhead.

Changes

  • ff/src/biginteger/mod.rs: Added const_remainder! macro for compile-time bigint modular remainder.
  • ff/src/fields/models/fp/montgomery_backend.rs:
    • Added BARRETT_NEEDS_CEIL compile-time constant.
    • Modified barrett_reduce_nplus1_to_n to apply the ceil fix when needed.
    • Added regression test with concrete counter-example for BLS12-381 Fq.
    • Added 1000-iteration random mul_u64 test over BLS12-381 Fq.

Test plan

  • Concrete counter-example for BLS12-381 Fq passes (previously produced non-canonical Montgomery form)
  • 1000-iteration random mul_u64 test over BLS12-381 Fq passes
  • All 74 existing unit tests pass
  • All 41 doc tests pass

Posted by Cursor assistant (model: claude-4.6-opus-high-thinking) on behalf of the user (Quang Dao) with approval.

…imes

For primes where 2^{n_p-1}/p + (2^{n_p+63} mod p)/2^{n_p} >= 1 (e.g.,
BLS12-381 Fq, BLS12-377 Fr/Fq, Pallas/Vesta, secp256r1, Curve25519),
the Barrett quotient estimate m can satisfy q - m = 2, producing a
remainder r >= 4p that the existing 3-way conditional subtraction
cannot reduce to canonical form.

The fix uses ceil(c / 2^{n_p}) instead of floor, which makes the two
rounding errors (floor of mu, ceil of c/2^{n_p}) partially cancel.
This keeps |q - m| <= 1 universally, so r is always in (-2p, 4p).
A conditional add-back of 2p handles the possible underflow when m
overestimates q by 1.

A compile-time const BARRETT_NEEDS_CEIL, computed from MODULUS and
BARRETT_MU via exact bigint remainder arithmetic, gates the fix so
that primes where the original algorithm is safe (e.g., BN254 Fr/Fq,
secp256k1) pay zero overhead.

Also adds a const_remainder! macro for computing bigint modular
remainders at compile time.

Includes regression test with a concrete counter-example for BLS12-381
Fq and a 1000-iteration random test over BLS12-381 Fq.

Made-with: Cursor
Reduce the number of Barrett kernel rounds in wide reduction paths and avoid rebuilding temporary N+1 buffers during folding. This removes the scaling cliff in BN254's wide Barrett and mixed Montgomery+Barrett reducers while preserving existing semantics.

Made-with: Cursor
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