chore: Native curve audit#20936
Conversation
| TEST(FqConstants, RInv) | ||
| { | ||
| // r_inv = -q^{-1} mod 2^64 | ||
| uint512_t r{ 0, 1 }; |
There was a problem hiding this comment.
This was using r = 1 << 256
| static constexpr fq frobenius_on_twisted_curve_y_1{ | ||
| 0xa1d77ce45ffe77c7UL, 0x07affd117826d1dbUL, 0x6d16bd27bb7edc6bUL, 0x2c87200285defeccUL | ||
| }; | ||
| static constexpr fq twist_cube_root_0{ |
| static constexpr fq twist_coeff_b_1{ | ||
| 0x38e7ecccd1dcff67UL, 0x65f0b37d93ce0d3eUL, 0xd749d0dd22ac00aaUL, 0x0141b9ce4a688d4dUL | ||
| }; | ||
| static constexpr fq twist_mul_by_q_x_0{ |
There was a problem hiding this comment.
Changed names to make them more descriptive
f7702a3 to
a003ee8
Compare
| @@ -25,18 +25,16 @@ class BN254 { | |||
| using TargetField = bb::fq12; | |||
|
|
|||
| static constexpr const char* name = "BN254"; | |||
There was a problem hiding this comment.
Old issue, closed
| static constexpr uint64_t primitive_root_3 = 0UL; | ||
|
|
||
| // Coset generators in Montgomery form for R=2^256 mod Modulus. Used in FFT-based proving systems | ||
| static constexpr uint64_t coset_generator_0 = 0x7a17caa950ad28d7ULL; |
There was a problem hiding this comment.
We need only the first coset generator, I removed the other ones from all the fields
| constexpr fq b = uint256_t{ 0x744fc10aec23e56aUL, 0x5dea4788a3b936a6UL, 0xa0a89f4a8af01df1UL, 0x72ae28836807df3UL }; | ||
| constexpr fq expected = | ||
| uint256_t{ 0x6c0a789c0028fd09UL, 0xca9520d84c684efaUL, 0xcbf3f7b023a852b4UL, 0x1b2e4dac41400621UL }; | ||
| constexpr fq a{ 0x83aa80986c4f06f8, 0xbd01cce5e3b3afc3, 0x1cba208cb70aa13b, 0x2a582eb35a932e0d }; |
There was a problem hiding this comment.
Prior to this change the elements were in non-Montgomery form. I changed them so that we use Montgomery form in all tests
| constexpr fq inv = a.invert(); | ||
| // Verify a * a^-1 = 1 | ||
| static_assert(a * inv == fq::one()); | ||
| } |
There was a problem hiding this comment.
Moved to generic field testing
| k1.self_to_montgomery_form(); | ||
| k2.self_to_montgomery_form(); | ||
|
|
||
| EXPECT_LT(uint256_t(k1).get_msb(), 128); |
There was a problem hiding this comment.
They were present in other tests so I added them here as well
| @@ -3,75 +3,6 @@ | |||
|
|
|||
| using namespace bb; | |||
There was a problem hiding this comment.
I don't see the value of these tests
| @@ -403,22 +307,6 @@ TEST(fq12, SqrCheckAgainstConstants) | |||
| EXPECT_EQ(result, expected); | |||
| } | |||
There was a problem hiding this comment.
Inverse moved to generic field testing; unitary inverse is below
|
|
||
| EXPECT_EQ(result, expected); | ||
| } | ||
|
|
There was a problem hiding this comment.
Add some generic testing
| Prime field documentation {#field_docs} | ||
| === | ||
| Barretenberg has its own implementation of finite field arithmetic. The implementation targets 254-bit (bn254, grumpkin) and 256-bit (secp256k1, secp256r1) fields. Internally the field is represented as a little-endian C-array of 4 uint64_t limbs. For 254-bit fields, the internal representation must be in the range \f$[0, 2p)\f$ (which we refer to as the _coarse representation_), while for 256-bit fields the internal representation is an arbitrary `uint256_t`. | ||
| Barretenberg has its own implementation of finite field arithmetic. The implementation targets 254-bit (bn254, grumpkin) and 256-bit (secp256k1, secp256r1) fields. Internally the field is represented as a little-endian C-array of 4 uint64_t limbs. For 254-bit fields, the internal representation must be in the range $[0, 2p)$ (which we refer to as the _coarse representation_), while for 256-bit fields the internal representation is an arbitrary `uint256_t`. |
There was a problem hiding this comment.
Changed formatting to markdown math instead of Doxygen math
| Params::coset_generator_3, | ||
| }; | ||
| #else | ||
| const field result{ |
There was a problem hiding this comment.
Removed some unused code
| } | ||
|
|
||
| constexpr field12 from_montgomery_form() | ||
| constexpr field12 from_montgomery_form() const |
There was a problem hiding this comment.
Needed for uniform testing
| // References: https://eips.ethereum.org/EIPS/eip-196, https://hackmd.io/@jpw/bn254 | ||
| static constexpr const char* expected_modulus_decimal = | ||
| "21888242871839275222246405745257275088696311157297823662689037894645226208583"; | ||
| static constexpr bool has_cube_root = true; |
| @@ -1,289 +0,0 @@ | |||
| /** | |||
There was a problem hiding this comment.
Thanks for refactoring out of the bn254 folder, cleaning up, and incorporating all fields
| // divide by 2^256 by taking the highest four limbs. See field_docs.hpp for more details. | ||
| static constexpr uint64_t r_inv = 0x87d20782e4866389UL; | ||
|
|
||
| // 2^(-64) mod Modulus |
There was a problem hiding this comment.
This is a nit, but I think it's better to cite the field docs here. The main reason we cite the Ingoyama hackmd is for what we call "Yuval reduction", which we use for WASM.
There was a problem hiding this comment.
(so, we cite it when we do 2^(-29) below)
| } | ||
|
|
||
| TEST(fq12, MulSqrConsistency) | ||
| TEST(fq12, FrobeniusMapSixIsConjugation) |
barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp
Outdated
Show resolved
Hide resolved
notnotraju
left a comment
There was a problem hiding this comment.
Looks good, thanks! Left a few trivial comments.
…; mark from_montgomery_form as const in fq12
…ore general testing
c46da72 to
3332452
Compare
The `FromMontgomeryForm` test in `general_field.test.cpp` (added by #20936) was comparing raw limbs after `from_montgomery_form()`, expecting exactly `{1, 0, 0, 0}`. However, the WASM Montgomery multiplication returns coarse results in `[0, 2p)`, so `from_montgomery_form(one())` can return `p+1` instead of `1` — both represent the same field element, but the raw limbs differ. This caused `ecc_tests` to fail in WASM builds (`FieldTest/0.FromMontgomeryForm` for BN254 Fq and `FieldTest/1.FromMontgomeryForm` for BN254 Fr), which dequeued merge-train/barretenberg PR #21084 from the merge queue. Fix: use `from_montgomery_form_reduced()` for base fields to ensure full reduction to `[0, p)` before raw limb comparison. Extension fields already use `from_montgomery_form_reduced()` internally on their components, so they are unaffected. ClaudeBox log: http://ci.aztec-labs.com/5f9c459fdf9e2366-1
BEGIN_COMMIT_OVERRIDE fix: add -g0 to zig presets to eliminate 11GB debug info bloat (#21071) fix: resolve flaky p2p_client test race condition on ARM64 (#21088) chore: remove domain iteration macros and address backing memory race (#20988) fix: [ECCVM] added domain separation for the multiset equality check. (#20352) feat: hybrid CRS hash verification — 8MB chunks, parallel, span-based (#21113) chore: unify splitting scalars interface (#20805) chore: add a unique id to each origin tag (#20924) chore: Native curve audit (#20936) chore: Update bootstrap in test vk haven't changed script (#21153) fix: use reduced form in WASM FromMontgomeryForm test (#21164) chore: erase ephemeral secrets from memory in schnorr and aes (#21106) chore: suppress clangd target triple version diagnostic (#21180) feat: Optimise new claim calculation (#21179) docs: add Quick Start build instructions to barretenberg README (#20951) feat: batched chonk verification (#21083) fix: link libc++ instead of libstdc++ for Rust FFI on Linux (#21203) fix: [ECCVM] in the transcript table, no-ops force the next accumulator to be 0. (#20849) fix: resolve merge-train conflict with next (zig wrapper scripts + -g0) (#21201) fix: [ECCVM] rare edge case completeness issue when `z1 == 0` but `z2 != 0` (#20858) fix: use actual data extent for CommitmentKey in HypernovaDeciderProver (#21206) END_COMMIT_OVERRIDE
🧾 Audit Context
First part of the audit of
ecc/curves. This PR is concerned with curve fields: we restructure testing, standardise struct format, and add some more constant checks.🛠️ Changes Made
✅ Checklist
📌 Notes for Reviewers