├── .github └── workflows │ └── ci.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── ff_derive ├── Cargo.toml └── src │ ├── lib.rs │ └── pow_fixed.rs ├── rust-toolchain.toml ├── src ├── batch.rs ├── helpers.rs └── lib.rs └── tests └── derive.rs /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI checks 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: main 7 | 8 | jobs: 9 | test-msrv: 10 | name: Test MSRV on ${{ matrix.os }} 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | matrix: 14 | os: [ubuntu-latest, windows-latest, macOS-latest] 15 | steps: 16 | - uses: actions/checkout@v4 17 | - name: Run tests 18 | run: cargo test --verbose --all-features 19 | - name: Run tests (without bitvec) 20 | run: cargo test --verbose --no-default-features --features derive 21 | - name: Verify working directory is clean 22 | run: git diff --exit-code 23 | 24 | test-latest: 25 | name: Test latest on ${{ matrix.os }} 26 | runs-on: ${{ matrix.os }} 27 | strategy: 28 | matrix: 29 | os: [ubuntu-latest, windows-latest, macOS-latest] 30 | steps: 31 | - uses: actions/checkout@v4 32 | - uses: dtolnay/rust-toolchain@stable 33 | id: toolchain 34 | - run: rustup override set ${{steps.toolchain.outputs.name}} 35 | - name: Remove lockfile to build with latest dependencies 36 | run: rm Cargo.lock 37 | - name: Run tests 38 | run: cargo test --verbose --all-features 39 | - name: Run tests (without bitvec) 40 | run: cargo test --verbose --no-default-features --features derive 41 | - name: Verify working directory is clean (excluding lockfile) 42 | run: git diff --exit-code ':!Cargo.lock' 43 | 44 | build-nodefault: 45 | name: Build target ${{ matrix.target }} 46 | runs-on: ubuntu-latest 47 | strategy: 48 | matrix: 49 | target: 50 | - wasm32-wasi 51 | - thumbv6m-none-eabi 52 | - thumbv7em-none-eabihf 53 | steps: 54 | - uses: actions/checkout@v4 55 | with: 56 | path: crate_root 57 | # We use a synthetic crate to ensure no dev-dependencies are enabled, which can 58 | # be incompatible with some of these targets. 59 | - name: Create synthetic crate for testing 60 | run: cargo init --edition 2021 --lib ci-build 61 | - name: Copy Rust version into synthetic crate 62 | run: cp crate_root/rust-toolchain.toml ci-build/ 63 | - name: Copy patch directives into synthetic crate 64 | run: | 65 | echo "[patch.crates-io]" >> ./ci-build/Cargo.toml 66 | cat ./crate_root/Cargo.toml | sed "0,/.\+\(patch.crates.\+\)/d" >> ./ci-build/Cargo.toml 67 | - name: Add no_std pragma to lib.rs 68 | run: | 69 | echo "#![no_std]" > ./ci-build/src/lib.rs 70 | - name: Add ff as a dependency of the synthetic crate 71 | working-directory: ./ci-build 72 | # run: cargo add --no-default-features --path ../crate_root 73 | run: sed -i 's;\[dependencies\];\[dependencies\]\nff = { path = "../crate_root", default-features = false };g' ./Cargo.toml 74 | - name: Add target 75 | working-directory: ./ci-build 76 | run: rustup target add ${{ matrix.target }} 77 | - name: Build for target 78 | working-directory: ./ci-build 79 | run: cargo build --verbose --target ${{ matrix.target }} 80 | - name: Enable the bits feature of ff 81 | working-directory: ./ci-build 82 | # run: cargo add --no-default-features --features bits --path ../crate_root 83 | run: sed -i 's;ff = { path = "../crate_root", default-features = false };ff = { path = "../crate_root", default-features = false, features = ["bits"] };g' ./Cargo.toml 84 | - name: Build for target with the bits feature 85 | working-directory: ./ci-build 86 | run: cargo build --verbose --target ${{ matrix.target }} 87 | 88 | doc-links: 89 | name: Intra-doc links 90 | runs-on: ubuntu-latest 91 | steps: 92 | - uses: actions/checkout@v4 93 | - run: cargo fetch 94 | # Requires #![deny(rustdoc::broken_intra_doc_links)] in crates. 95 | - run: sudo apt-get -y install libfontconfig1-dev 96 | - name: Check intra-doc links 97 | run: cargo doc --all-features --document-private-items 98 | 99 | fmt: 100 | name: Rustfmt 101 | runs-on: ubuntu-latest 102 | steps: 103 | - uses: actions/checkout@v4 104 | - run: cargo fmt -- --check 105 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this library will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this library adheres to Rust's notion of 6 | [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.13.1] - 2025-03-09 11 | ### Changed 12 | - `ff_derive` now works with all odd primes, not just primes that are either 13 | `3 (mod 4)` or `1 (mod 16)`. 14 | 15 | ### Fixed 16 | - A type inference problem when `ff_derive` and `hybrid-array` are in the same 17 | dependency tree has been fixed. 18 | 19 | ## [0.13.0] - 2022-12-06 20 | ### Added 21 | - `ff::Field::{ZERO, ONE}` 22 | - `ff::Field::pow` 23 | - `ff::Field::{sqrt_ratio, sqrt_alt}` 24 | - `core::iter::{Sum, Product}` bounds on `ff::Field` 25 | - `ff::PrimeField::from_u128` 26 | - `ff::PrimeField::{MODULUS, TWO_INV}` 27 | - Constants related to multiplicative generators: 28 | - `ff::PrimeField::MULTIPLICATIVE_GENERATOR` 29 | - `ff::PrimeField::{ROOT_OF_UNITY, ROOT_OF_UNITY_INV}` 30 | - `ff::PrimeField::DELTA` 31 | - `ff::WithSmallOrderMulGroup` 32 | - `ff::FromUniformBytes` 33 | - `ff::helpers`: 34 | - `sqrt_tonelli_shanks` 35 | - `sqrt_ratio_generic` 36 | 37 | ### Changed 38 | - `ff::Field::sqrt` is now a provided method that uses the `Field::sqrt_ratio` 39 | method. Implementors of the `Field` trait can choose to implement 40 | `Field::sqrt_ratio` and use the provided `ff::Field::sqrt` method, especially 41 | if it is more efficient in practice, or they can keep their own implementation 42 | of `Field::sqrt` and implement `Field::sqrt_ratio` in terms of that 43 | implementation using the `ff::helpers::sqrt_ratio_generic` helper function. 44 | - `ff::PrimeField` is now documented as representing a non-binary field (i.e. 45 | its prime is not 2). This was always the intention, but is now a concrete 46 | requirement in order for `PrimeField::TWO_INV` to exist. 47 | 48 | ### Removed 49 | - `ff::Field::{zero, one}` (use `ff::Field::{ZERO, ONE}` instead). 50 | - `ff::PrimeField::{multiplicative_generator, root_of_unity}` (use 51 | `ff::PrimeField::{MULTIPLICATIVE_GENERATOR, ROOT_OF_UNITY}` instead). 52 | 53 | ## [0.12.1] - 2022-10-28 54 | ### Fixed 55 | - `ff_derive` previously generated a `Field::random` implementation that would 56 | overflow for fields that needed a full 64-bit spare limb. 57 | 58 | ## [0.12.0] - 2022-05-04 59 | ### Changed 60 | 61 | - MSRV is now 1.56.0. 62 | - Bumped `bitvec` to 1.0. 63 | 64 | ## [0.11.1] - 2022-05-04 65 | ### Fixed 66 | - `ff_derive` procedural macro can now be invoked within regular macros. 67 | - Previously, `ff_derive`'s procedural macro would generate implementations of 68 | `PrimeFieldBits` even when the `bits` crate feature was disabled. `ff_derive` 69 | can now be used without a dependency on `bitvec` by disabling feature 70 | features. The new crate feature `derive_bits` can be used to force the 71 | generation of `PrimeFieldBits` implementations. This new crate feature will be 72 | removed once our MSRV is at least 1.60 and we have access to [weak dependency 73 | features](https://blog.rust-lang.org/2022/04/07/Rust-1.60.0.html#new-syntax-for-cargo-features). 74 | 75 | ## [0.11.0] - 2021-09-02 76 | ### Added 77 | - `subtle::ConstantTimeEq` bound on `ff::Field` 78 | - `Copy + Send + Sync + 'static` bounds on `ff::PrimeField::Repr` 79 | - `ff::derive` module behind the `derive` feature flag, containing dependencies for the 80 | `PrimeField` derive macro: 81 | - Re-exports of required crates. 82 | - `adc, mac, sbb` constant-time const helper functions. 83 | - `ff::Field::is_zero_vartime` 84 | - `ff::PrimeField::from_repr_vartime` 85 | 86 | ### Changed 87 | - `ff::Field::is_zero` now returns `subtle::Choice`. 88 | - `ff::PrimeField::{is_odd, is_even}` now return `subtle::Choice`. 89 | - `ff::PrimeField::from_repr` now return `subtle::CtOption`. 90 | - `ff::PrimeField::from_str` has been renamed to `PrimeField::from_str_vartime`. 91 | 92 | ### Removed 93 | - `ff::{adc, mac_with_carry, sbb}` (replaced by `ff::derive::{adc, mac, sbb}`). 94 | 95 | ## [0.10.1] - 2021-08-11 96 | ### Added 97 | - `ff::BatchInvert` extension trait, implemented for iterators over mutable field elements 98 | which allows those field elements to be inverted in a batch. This trait is behind the 99 | new `alloc` feature flag. 100 | - `ff::BatchInverter` struct, which provides methods for non-allocating batch inversion of 101 | field elements contained within slices. 102 | 103 | ## [0.10.0] - 2021-06-01 104 | ### Added 105 | - `ff::PrimeFieldBits: PrimeField` trait, behind a `bits` feature flag. 106 | 107 | ### Changed 108 | - MSRV is now 1.51.0. 109 | - Bumped `bitvec` to 0.22 to enable fixing a performance regression in `ff 0.9`. 110 | The `bitvec::view::BitView` re-export has been replaced by 111 | `bitvec::view::BitViewSized`. 112 | - The `bitvec` dependency and its re-exports have been gated behind the `bits` 113 | feature flag. 114 | 115 | ### Removed 116 | - `ff::PrimeField::{ReprBits, char_le_bits, to_le_bits}` (replaced by 117 | `ff::PrimeFieldBits` trait). 118 | 119 | ### Fixed 120 | - `#[derive(PrimeField)]` now works on small moduli (that fit in a single `u64` 121 | limb). 122 | 123 | ## [0.9.0] - 2021-01-05 124 | ### Added 125 | - Re-export of `bitvec::view::BitView`. 126 | - `ff::FieldBits` type alias for the return type of 127 | `ff::PrimeField::{char_le_bits, to_le_bits}`. 128 | 129 | ### Changed 130 | - Bumped `bitvec` to 0.20, `rand_core` to 0.6. 131 | 132 | ### Removed 133 | - `From` and `From<&Self>` bounds on `ff::PrimeField::Repr`. 134 | 135 | ## [0.8.0] - 2020-09-08 136 | ### Added 137 | - `ff::PrimeField::{ReprBits, char_le_bits, to_le_bits}`, and a public 138 | dependency on `bitvec 0.18`. 139 | - `ff::Field::cube` method with provided implementation. 140 | - `Send + Sync` bounds on `ff::PrimeField::ReprBits` 141 | 142 | ### Changed 143 | - MSRV is now 1.44.0. 144 | - `ff::Field::random(rng: &mut R) -> Self` has been changed 145 | to `Field::random(rng: impl RngCore) -> Self`, to align with 146 | `group::Group::random`. 147 | 148 | ### Removed 149 | - `fmt::Display` bound on `ff::Field`. 150 | - `ff::PrimeField::char` (replaced by `ff::PrimeField::char_le_bits`). 151 | - `ff::{BitIterator, Endianness, PrimeField::ReprEndianness` (replaced by 152 | `ff::PrimeField::to_le_bits`). 153 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addchain" 7 | version = "0.2.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "3b2e69442aa5628ea6951fa33e24efe8313f4321a91bd729fc2f75bdfc858570" 10 | dependencies = [ 11 | "num-bigint", 12 | "num-integer", 13 | "num-traits", 14 | ] 15 | 16 | [[package]] 17 | name = "arrayref" 18 | version = "0.3.6" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" 21 | 22 | [[package]] 23 | name = "arrayvec" 24 | version = "0.7.2" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" 27 | 28 | [[package]] 29 | name = "autocfg" 30 | version = "1.1.0" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 33 | 34 | [[package]] 35 | name = "bitvec" 36 | version = "1.0.1" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" 39 | dependencies = [ 40 | "funty", 41 | "radium", 42 | "tap", 43 | "wyz", 44 | ] 45 | 46 | [[package]] 47 | name = "blake2b_simd" 48 | version = "1.0.0" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | checksum = "72936ee4afc7f8f736d1c38383b56480b5497b4617b4a77bdbf1d2ababc76127" 51 | dependencies = [ 52 | "arrayref", 53 | "arrayvec", 54 | "constant_time_eq", 55 | ] 56 | 57 | [[package]] 58 | name = "byteorder" 59 | version = "1.4.3" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 62 | 63 | [[package]] 64 | name = "cfg-if" 65 | version = "1.0.0" 66 | source = "registry+https://github.com/rust-lang/crates.io-index" 67 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 68 | 69 | [[package]] 70 | name = "constant_time_eq" 71 | version = "0.1.5" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" 74 | 75 | [[package]] 76 | name = "ff" 77 | version = "0.13.1" 78 | dependencies = [ 79 | "bitvec", 80 | "blake2b_simd", 81 | "byteorder", 82 | "ff_derive", 83 | "rand", 84 | "rand_core", 85 | "subtle", 86 | ] 87 | 88 | [[package]] 89 | name = "ff_derive" 90 | version = "0.13.1" 91 | dependencies = [ 92 | "addchain", 93 | "num-bigint", 94 | "num-integer", 95 | "num-traits", 96 | "proc-macro2", 97 | "quote", 98 | "syn", 99 | ] 100 | 101 | [[package]] 102 | name = "funty" 103 | version = "2.0.0" 104 | source = "registry+https://github.com/rust-lang/crates.io-index" 105 | checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" 106 | 107 | [[package]] 108 | name = "getrandom" 109 | version = "0.2.8" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" 112 | dependencies = [ 113 | "cfg-if", 114 | "libc", 115 | "wasi", 116 | ] 117 | 118 | [[package]] 119 | name = "libc" 120 | version = "0.2.137" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" 123 | 124 | [[package]] 125 | name = "num-bigint" 126 | version = "0.3.3" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" 129 | dependencies = [ 130 | "autocfg", 131 | "num-integer", 132 | "num-traits", 133 | ] 134 | 135 | [[package]] 136 | name = "num-integer" 137 | version = "0.1.45" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 140 | dependencies = [ 141 | "autocfg", 142 | "num-traits", 143 | ] 144 | 145 | [[package]] 146 | name = "num-traits" 147 | version = "0.2.15" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" 150 | dependencies = [ 151 | "autocfg", 152 | ] 153 | 154 | [[package]] 155 | name = "ppv-lite86" 156 | version = "0.2.16" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" 159 | 160 | [[package]] 161 | name = "proc-macro2" 162 | version = "1.0.47" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" 165 | dependencies = [ 166 | "unicode-ident", 167 | ] 168 | 169 | [[package]] 170 | name = "quote" 171 | version = "1.0.21" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" 174 | dependencies = [ 175 | "proc-macro2", 176 | ] 177 | 178 | [[package]] 179 | name = "radium" 180 | version = "0.7.0" 181 | source = "registry+https://github.com/rust-lang/crates.io-index" 182 | checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" 183 | 184 | [[package]] 185 | name = "rand" 186 | version = "0.8.5" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 189 | dependencies = [ 190 | "libc", 191 | "rand_chacha", 192 | "rand_core", 193 | ] 194 | 195 | [[package]] 196 | name = "rand_chacha" 197 | version = "0.3.1" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 200 | dependencies = [ 201 | "ppv-lite86", 202 | "rand_core", 203 | ] 204 | 205 | [[package]] 206 | name = "rand_core" 207 | version = "0.6.4" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 210 | dependencies = [ 211 | "getrandom", 212 | ] 213 | 214 | [[package]] 215 | name = "subtle" 216 | version = "2.4.1" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" 219 | 220 | [[package]] 221 | name = "syn" 222 | version = "1.0.103" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" 225 | dependencies = [ 226 | "proc-macro2", 227 | "quote", 228 | "unicode-ident", 229 | ] 230 | 231 | [[package]] 232 | name = "tap" 233 | version = "1.0.1" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" 236 | 237 | [[package]] 238 | name = "unicode-ident" 239 | version = "1.0.5" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" 242 | 243 | [[package]] 244 | name = "wasi" 245 | version = "0.11.0+wasi-snapshot-preview1" 246 | source = "registry+https://github.com/rust-lang/crates.io-index" 247 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 248 | 249 | [[package]] 250 | name = "wyz" 251 | version = "0.5.0" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e" 254 | dependencies = [ 255 | "tap", 256 | ] 257 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ff" 3 | version = "0.13.1" 4 | authors = [ 5 | "Sean Bowe ", 6 | "Jack Grigg ", 7 | ] 8 | edition = "2021" 9 | rust-version = "1.56" 10 | description = "Library for building and interfacing with finite fields" 11 | readme = "README.md" 12 | documentation = "https://docs.rs/ff/" 13 | homepage = "https://github.com/zkcrypto/ff" 14 | license = "MIT/Apache-2.0" 15 | repository = "https://github.com/zkcrypto/ff" 16 | 17 | [dependencies] 18 | bitvec = { version = "1", default-features = false, optional = true } 19 | byteorder = { version = "1", default-features = false, optional = true } 20 | ff_derive = { version = "0.13.1", path = "ff_derive", optional = true } 21 | rand_core = { version = "0.6", default-features = false } 22 | subtle = { version = "2.2.1", default-features = false, features = ["i128"] } 23 | 24 | [dev-dependencies] 25 | blake2b_simd = "1" 26 | rand = "0.8" 27 | 28 | [features] 29 | default = ["bits", "std"] 30 | alloc = [] 31 | bits = ["bitvec"] 32 | derive = ["byteorder", "ff_derive"] 33 | std = ["alloc"] 34 | # with MSRV 1.60 this could be merged into bits with ff_derive?/bits 35 | # see PR#72 for more information. 36 | derive_bits = ["bits", "ff_derive/bits"] 37 | 38 | [[test]] 39 | name = "derive" 40 | required-features = ["derive"] 41 | 42 | [badges] 43 | maintenance = { status = "actively-developed" } 44 | 45 | [package.metadata.docs.rs] 46 | all-features = true 47 | rustdoc-args = ["--cfg", "docsrs"] 48 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Sean Bowe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ff 2 | 3 | `ff` is a finite field library written in pure Rust, with no `unsafe{}` code. 4 | 5 | ## RFC process 6 | 7 | This crate follows the [zkcrypto RFC process](https://zkcrypto.github.io/rfcs/). 8 | If you want to propose "substantial" changes to this crate (in particular to the 9 | `ff` traits), please [create an RFC](https://github.com/zkcrypto/rfcs) for wider 10 | discussion. 11 | 12 | ## Disclaimers 13 | 14 | * This library does not provide constant-time guarantees. The traits enable downstream 15 | users to expose constant-time logic, but `#[derive(PrimeField)]` in particular does not 16 | generate constant-time code (even for trait methods that return constant-time-compatible 17 | values). 18 | 19 | ## Usage 20 | 21 | Add the `ff` crate to your `Cargo.toml`: 22 | 23 | ```toml 24 | [dependencies] 25 | ff = "0.13" 26 | ``` 27 | 28 | The `ff` crate contains the `Field` and `PrimeField` traits. 29 | See the **[documentation](https://docs.rs/ff/)** for more. 30 | 31 | ### `#![derive(PrimeField)]` 32 | 33 | If you need an implementation of a prime field, this library also provides a procedural 34 | macro that will expand into an efficient implementation of a prime field when supplied 35 | with the modulus. `PrimeFieldGenerator` must be an element of Fp of p-1 order, that is 36 | also quadratic nonresidue. 37 | 38 | First, enable the `derive` crate feature: 39 | 40 | ```toml 41 | [dependencies] 42 | ff = { version = "0.13", features = ["derive"] } 43 | ``` 44 | 45 | And then use the macro like so: 46 | 47 | ```rust 48 | #[macro_use] 49 | extern crate ff; 50 | 51 | #[derive(PrimeField)] 52 | #[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"] 53 | #[PrimeFieldGenerator = "7"] 54 | #[PrimeFieldReprEndianness = "little"] 55 | struct Fp([u64; 4]); 56 | ``` 57 | 58 | And that's it! `Fp` now implements `Field` and `PrimeField`. 59 | 60 | ## Minimum Supported Rust Version 61 | 62 | Requires Rust **1.56** or higher. 63 | 64 | Minimum supported Rust version can be changed in the future, but it will be done with a 65 | minor version bump. 66 | 67 | ## License 68 | 69 | Licensed under either of 70 | 71 | * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 72 | http://www.apache.org/licenses/LICENSE-2.0) 73 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 74 | 75 | at your option. 76 | 77 | ### Contribution 78 | 79 | Unless you explicitly state otherwise, any contribution intentionally 80 | submitted for inclusion in the work by you, as defined in the Apache-2.0 81 | license, shall be dual licensed as above, without any additional terms or 82 | conditions. 83 | -------------------------------------------------------------------------------- /ff_derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ff_derive" 3 | version = "0.13.1" 4 | authors = [ 5 | "Sean Bowe ", 6 | "Jack Grigg ", 7 | ] 8 | edition = "2021" 9 | rust-version = "1.56" 10 | description = "Procedural macro library used to build custom prime field implementations" 11 | documentation = "https://docs.rs/ff-derive/" 12 | homepage = "https://github.com/zkcrypto/ff" 13 | license = "MIT/Apache-2.0" 14 | repository = "https://github.com/zkcrypto/ff" 15 | 16 | [features] 17 | # enabled when generating bitvec code utilizing the version of ff's bitvec 18 | bits = [] 19 | 20 | [lib] 21 | proc-macro = true 22 | 23 | [dependencies] 24 | addchain = "0.2" 25 | num-bigint = "0.3" 26 | num-traits = "0.2" 27 | num-integer = "0.1" 28 | proc-macro2 = "1" 29 | quote = "1" 30 | syn = { version = "1", features = ["full"] } 31 | 32 | [badges] 33 | maintenance = { status = "passively-maintained" } 34 | -------------------------------------------------------------------------------- /ff_derive/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![recursion_limit = "1024"] 2 | 3 | extern crate proc_macro; 4 | extern crate proc_macro2; 5 | 6 | use num_bigint::BigUint; 7 | use num_integer::Integer; 8 | use num_traits::{One, ToPrimitive, Zero}; 9 | use quote::quote; 10 | use quote::TokenStreamExt; 11 | use std::iter; 12 | use std::str::FromStr; 13 | 14 | mod pow_fixed; 15 | 16 | enum ReprEndianness { 17 | Big, 18 | Little, 19 | } 20 | 21 | impl FromStr for ReprEndianness { 22 | type Err = (); 23 | 24 | fn from_str(s: &str) -> Result { 25 | match s { 26 | "big" => Ok(ReprEndianness::Big), 27 | "little" => Ok(ReprEndianness::Little), 28 | _ => Err(()), 29 | } 30 | } 31 | } 32 | 33 | impl ReprEndianness { 34 | fn modulus_repr(&self, modulus: &BigUint, bytes: usize) -> Vec { 35 | match self { 36 | ReprEndianness::Big => { 37 | let buf = modulus.to_bytes_be(); 38 | iter::repeat(0) 39 | .take(bytes - buf.len()) 40 | .chain(buf.into_iter()) 41 | .collect() 42 | } 43 | ReprEndianness::Little => { 44 | let mut buf = modulus.to_bytes_le(); 45 | buf.extend(iter::repeat(0).take(bytes - buf.len())); 46 | buf 47 | } 48 | } 49 | } 50 | 51 | fn from_repr(&self, name: &syn::Ident, limbs: usize) -> proc_macro2::TokenStream { 52 | let read_repr = match self { 53 | ReprEndianness::Big => quote! { 54 | ::ff::derive::byteorder::BigEndian::read_u64_into(r.as_ref(), &mut inner[..]); 55 | inner.reverse(); 56 | }, 57 | ReprEndianness::Little => quote! { 58 | ::ff::derive::byteorder::LittleEndian::read_u64_into(r.as_ref(), &mut inner[..]); 59 | }, 60 | }; 61 | 62 | quote! { 63 | use ::ff::derive::byteorder::ByteOrder; 64 | 65 | let r = { 66 | let mut inner = [0u64; #limbs]; 67 | #read_repr 68 | #name(inner) 69 | }; 70 | } 71 | } 72 | 73 | fn to_repr( 74 | &self, 75 | repr: proc_macro2::TokenStream, 76 | mont_reduce_self_params: &proc_macro2::TokenStream, 77 | limbs: usize, 78 | ) -> proc_macro2::TokenStream { 79 | let bytes = limbs * 8; 80 | 81 | let write_repr = match self { 82 | ReprEndianness::Big => quote! { 83 | r.0.reverse(); 84 | ::ff::derive::byteorder::BigEndian::write_u64_into(&r.0, &mut repr[..]); 85 | }, 86 | ReprEndianness::Little => quote! { 87 | ::ff::derive::byteorder::LittleEndian::write_u64_into(&r.0, &mut repr[..]); 88 | }, 89 | }; 90 | 91 | quote! { 92 | use ::ff::derive::byteorder::ByteOrder; 93 | 94 | let mut r = *self; 95 | r.mont_reduce( 96 | #mont_reduce_self_params 97 | ); 98 | 99 | let mut repr = [0u8; #bytes]; 100 | #write_repr 101 | #repr(repr) 102 | } 103 | } 104 | 105 | fn iter_be(&self) -> proc_macro2::TokenStream { 106 | match self { 107 | ReprEndianness::Big => quote! {self.0.iter()}, 108 | ReprEndianness::Little => quote! {self.0.iter().rev()}, 109 | } 110 | } 111 | } 112 | 113 | /// Derive the `PrimeField` trait. 114 | #[proc_macro_derive( 115 | PrimeField, 116 | attributes(PrimeFieldModulus, PrimeFieldGenerator, PrimeFieldReprEndianness) 117 | )] 118 | pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream { 119 | // Parse the type definition 120 | let ast: syn::DeriveInput = syn::parse(input).unwrap(); 121 | 122 | // We're given the modulus p of the prime field 123 | let modulus: BigUint = fetch_attr("PrimeFieldModulus", &ast.attrs) 124 | .expect("Please supply a PrimeFieldModulus attribute") 125 | .parse() 126 | .expect("PrimeFieldModulus should be a number"); 127 | 128 | // We may be provided with a generator of p - 1 order. It is required that this generator be quadratic 129 | // nonresidue. 130 | // TODO: Compute this ourselves. 131 | let generator: BigUint = fetch_attr("PrimeFieldGenerator", &ast.attrs) 132 | .expect("Please supply a PrimeFieldGenerator attribute") 133 | .parse() 134 | .expect("PrimeFieldGenerator should be a number"); 135 | 136 | // Field element representations may be in little-endian or big-endian. 137 | let endianness = fetch_attr("PrimeFieldReprEndianness", &ast.attrs) 138 | .expect("Please supply a PrimeFieldReprEndianness attribute") 139 | .parse() 140 | .expect("PrimeFieldReprEndianness should be 'big' or 'little'"); 141 | 142 | // The arithmetic in this library only works if the modulus*2 is smaller than the backing 143 | // representation. Compute the number of limbs we need. 144 | let mut limbs = 1; 145 | { 146 | let mod2 = (&modulus) << 1; // modulus * 2 147 | let mut cur = BigUint::one() << 64; // always 64-bit limbs for now 148 | while cur < mod2 { 149 | limbs += 1; 150 | cur <<= 64; 151 | } 152 | } 153 | 154 | // The struct we're deriving for must be a wrapper around `pub [u64; limbs]`. 155 | if let Some(err) = validate_struct(&ast, limbs) { 156 | return err.into(); 157 | } 158 | 159 | // Generate the identifier for the "Repr" type we must construct. 160 | let repr_ident = syn::Ident::new( 161 | &format!("{}Repr", ast.ident), 162 | proc_macro2::Span::call_site(), 163 | ); 164 | 165 | let mut gen = proc_macro2::TokenStream::new(); 166 | 167 | let (constants_impl, sqrt_impl) = 168 | prime_field_constants_and_sqrt(&ast.ident, &modulus, limbs, generator); 169 | 170 | gen.extend(constants_impl); 171 | gen.extend(prime_field_repr_impl(&repr_ident, &endianness, limbs * 8)); 172 | gen.extend(prime_field_impl( 173 | &ast.ident, 174 | &repr_ident, 175 | &modulus, 176 | &endianness, 177 | limbs, 178 | sqrt_impl, 179 | )); 180 | 181 | // Return the generated impl 182 | gen.into() 183 | } 184 | 185 | /// Checks that `body` contains `pub [u64; limbs]`. 186 | fn validate_struct(ast: &syn::DeriveInput, limbs: usize) -> Option { 187 | // The body should be a struct. 188 | let variant_data = match &ast.data { 189 | syn::Data::Struct(x) => x, 190 | _ => { 191 | return Some( 192 | syn::Error::new_spanned(ast, "PrimeField derive only works for structs.") 193 | .to_compile_error(), 194 | ) 195 | } 196 | }; 197 | 198 | // The struct should contain a single unnamed field. 199 | let fields = match &variant_data.fields { 200 | syn::Fields::Unnamed(x) if x.unnamed.len() == 1 => x, 201 | _ => { 202 | return Some( 203 | syn::Error::new_spanned( 204 | &ast.ident, 205 | format!( 206 | "The struct must contain an array of limbs. Change this to `{}([u64; {}])`", 207 | ast.ident, limbs, 208 | ), 209 | ) 210 | .to_compile_error(), 211 | ) 212 | } 213 | }; 214 | let field = &fields.unnamed[0]; 215 | 216 | // The field should be an array. 217 | let arr = match &field.ty { 218 | syn::Type::Array(x) => x, 219 | _ => { 220 | return Some( 221 | syn::Error::new_spanned( 222 | field, 223 | format!( 224 | "The inner field must be an array of limbs. Change this to `[u64; {}]`", 225 | limbs, 226 | ), 227 | ) 228 | .to_compile_error(), 229 | ) 230 | } 231 | }; 232 | 233 | // The array's element type should be `u64`. 234 | if match arr.elem.as_ref() { 235 | syn::Type::Path(path) => path 236 | .path 237 | .get_ident() 238 | .map(|x| x.to_string() != "u64") 239 | .unwrap_or(true), 240 | _ => true, 241 | } { 242 | return Some( 243 | syn::Error::new_spanned( 244 | arr, 245 | format!( 246 | "PrimeField derive requires 64-bit limbs. Change this to `[u64; {}]", 247 | limbs 248 | ), 249 | ) 250 | .to_compile_error(), 251 | ); 252 | } 253 | 254 | // The array's length should be a literal int equal to `limbs`. 255 | let expr_lit = match &arr.len { 256 | syn::Expr::Lit(expr_lit) => Some(&expr_lit.lit), 257 | syn::Expr::Group(expr_group) => match &*expr_group.expr { 258 | syn::Expr::Lit(expr_lit) => Some(&expr_lit.lit), 259 | _ => None, 260 | }, 261 | _ => None, 262 | }; 263 | let lit_int = match match expr_lit { 264 | Some(syn::Lit::Int(lit_int)) => Some(lit_int), 265 | _ => None, 266 | } { 267 | Some(x) => x, 268 | _ => { 269 | return Some( 270 | syn::Error::new_spanned( 271 | arr, 272 | format!("To derive PrimeField, change this to `[u64; {}]`.", limbs), 273 | ) 274 | .to_compile_error(), 275 | ) 276 | } 277 | }; 278 | if lit_int.base10_digits() != limbs.to_string() { 279 | return Some( 280 | syn::Error::new_spanned( 281 | lit_int, 282 | format!("The given modulus requires {} limbs.", limbs), 283 | ) 284 | .to_compile_error(), 285 | ); 286 | } 287 | 288 | // The field should not be public. 289 | match &field.vis { 290 | syn::Visibility::Inherited => (), 291 | _ => { 292 | return Some( 293 | syn::Error::new_spanned(&field.vis, "Field must not be public.").to_compile_error(), 294 | ) 295 | } 296 | } 297 | 298 | // Valid! 299 | None 300 | } 301 | 302 | /// Fetch an attribute string from the derived struct. 303 | fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option { 304 | for attr in attrs { 305 | if let Ok(meta) = attr.parse_meta() { 306 | match meta { 307 | syn::Meta::NameValue(nv) => { 308 | if nv.path.get_ident().map(|i| i.to_string()) == Some(name.to_string()) { 309 | match nv.lit { 310 | syn::Lit::Str(ref s) => return Some(s.value()), 311 | _ => { 312 | panic!("attribute {} should be a string", name); 313 | } 314 | } 315 | } 316 | } 317 | _ => { 318 | panic!("attribute {} should be a string", name); 319 | } 320 | } 321 | } 322 | } 323 | 324 | None 325 | } 326 | 327 | // Implement the wrapped ident `repr` with `bytes` bytes. 328 | fn prime_field_repr_impl( 329 | repr: &syn::Ident, 330 | endianness: &ReprEndianness, 331 | bytes: usize, 332 | ) -> proc_macro2::TokenStream { 333 | let repr_iter_be = endianness.iter_be(); 334 | 335 | quote! { 336 | #[derive(Copy, Clone)] 337 | pub struct #repr(pub [u8; #bytes]); 338 | 339 | impl ::ff::derive::subtle::ConstantTimeEq for #repr { 340 | fn ct_eq(&self, other: &#repr) -> ::ff::derive::subtle::Choice { 341 | self.0 342 | .iter() 343 | .zip(other.0.iter()) 344 | .map(|(a, b)| a.ct_eq(b)) 345 | .fold(1.into(), |acc, x| acc & x) 346 | } 347 | } 348 | 349 | impl ::core::cmp::PartialEq for #repr { 350 | fn eq(&self, other: &#repr) -> bool { 351 | use ::ff::derive::subtle::ConstantTimeEq; 352 | self.ct_eq(other).into() 353 | } 354 | } 355 | 356 | impl ::core::cmp::Eq for #repr { } 357 | 358 | impl ::core::default::Default for #repr { 359 | fn default() -> #repr { 360 | #repr([0u8; #bytes]) 361 | } 362 | } 363 | 364 | impl ::core::fmt::Debug for #repr 365 | { 366 | fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { 367 | write!(f, "0x")?; 368 | for i in #repr_iter_be { 369 | write!(f, "{:02x}", *i)?; 370 | } 371 | 372 | Ok(()) 373 | } 374 | } 375 | 376 | impl AsRef<[u8]> for #repr { 377 | #[inline(always)] 378 | fn as_ref(&self) -> &[u8] { 379 | &self.0 380 | } 381 | } 382 | 383 | impl AsMut<[u8]> for #repr { 384 | #[inline(always)] 385 | fn as_mut(&mut self) -> &mut [u8] { 386 | &mut self.0 387 | } 388 | } 389 | } 390 | } 391 | 392 | /// Convert BigUint into a vector of 64-bit limbs. 393 | fn biguint_to_real_u64_vec(mut v: BigUint, limbs: usize) -> Vec { 394 | let m = BigUint::one() << 64; 395 | let mut ret = vec![]; 396 | 397 | while v > BigUint::zero() { 398 | let limb: BigUint = &v % &m; 399 | ret.push(limb.to_u64().unwrap()); 400 | v >>= 64; 401 | } 402 | 403 | while ret.len() < limbs { 404 | ret.push(0); 405 | } 406 | 407 | assert!(ret.len() == limbs); 408 | 409 | ret 410 | } 411 | 412 | /// Convert BigUint into a tokenized vector of 64-bit limbs. 413 | fn biguint_to_u64_vec(v: BigUint, limbs: usize) -> proc_macro2::TokenStream { 414 | let ret = biguint_to_real_u64_vec(v, limbs); 415 | quote!([#(#ret,)*]) 416 | } 417 | 418 | fn biguint_num_bits(mut v: BigUint) -> u32 { 419 | let mut bits = 0; 420 | 421 | while v != BigUint::zero() { 422 | v >>= 1; 423 | bits += 1; 424 | } 425 | 426 | bits 427 | } 428 | 429 | /// BigUint modular exponentiation by square-and-multiply. 430 | fn exp(base: BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint { 431 | let mut ret = BigUint::one(); 432 | 433 | for i in exp 434 | .to_bytes_be() 435 | .into_iter() 436 | .flat_map(|x| (0..8).rev().map(move |i| (x >> i).is_odd())) 437 | { 438 | ret = (&ret * &ret) % modulus; 439 | if i { 440 | ret = (ret * &base) % modulus; 441 | } 442 | } 443 | 444 | ret 445 | } 446 | 447 | #[test] 448 | fn test_exp() { 449 | assert_eq!( 450 | exp( 451 | BigUint::from_str("4398572349857239485729348572983472345").unwrap(), 452 | &BigUint::from_str("5489673498567349856734895").unwrap(), 453 | &BigUint::from_str( 454 | "52435875175126190479447740508185965837690552500527637822603658699938581184513" 455 | ) 456 | .unwrap() 457 | ), 458 | BigUint::from_str( 459 | "4371221214068404307866768905142520595925044802278091865033317963560480051536" 460 | ) 461 | .unwrap() 462 | ); 463 | } 464 | 465 | fn prime_field_constants_and_sqrt( 466 | name: &syn::Ident, 467 | modulus: &BigUint, 468 | limbs: usize, 469 | generator: BigUint, 470 | ) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) { 471 | let bytes = limbs * 8; 472 | let modulus_num_bits = biguint_num_bits(modulus.clone()); 473 | 474 | // The number of bits we should "shave" from a randomly sampled representation, i.e., 475 | // if our modulus is 381 bits and our representation is 384 bits, we should shave 476 | // 3 bits from the beginning of a randomly sampled 384 bit representation to 477 | // reduce the cost of rejection sampling. 478 | let repr_shave_bits = (64 * limbs as u32) - biguint_num_bits(modulus.clone()); 479 | 480 | // Compute R = 2**(64 * limbs) mod m 481 | let r = (BigUint::one() << (limbs * 64)) % modulus; 482 | let to_mont = |v| (v * &r) % modulus; 483 | 484 | let two = BigUint::from_str("2").unwrap(); 485 | let p_minus_2 = modulus - &two; 486 | let invert = |v| exp(v, &p_minus_2, &modulus); 487 | 488 | // 2^-1 mod m 489 | let two_inv = biguint_to_u64_vec(to_mont(invert(two)), limbs); 490 | 491 | // modulus - 1 = 2^s * t 492 | let mut s: u32 = 0; 493 | let mut t = modulus - BigUint::from_str("1").unwrap(); 494 | while t.is_even() { 495 | t >>= 1; 496 | s += 1; 497 | } 498 | 499 | // Compute 2^s root of unity given the generator 500 | let root_of_unity = exp(generator.clone(), &t, &modulus); 501 | let root_of_unity_inv = biguint_to_u64_vec(to_mont(invert(root_of_unity.clone())), limbs); 502 | let root_of_unity = biguint_to_u64_vec(to_mont(root_of_unity), limbs); 503 | let delta = biguint_to_u64_vec( 504 | to_mont(exp(generator.clone(), &(BigUint::one() << s), &modulus)), 505 | limbs, 506 | ); 507 | let generator = biguint_to_u64_vec(to_mont(generator), limbs); 508 | 509 | let sqrt_impl = 510 | if (modulus % BigUint::from_str("4").unwrap()) == BigUint::from_str("3").unwrap() { 511 | // Addition chain for (r + 1) // 4 512 | let mod_plus_1_over_4 = pow_fixed::generate( 513 | "e! {self}, 514 | (modulus + BigUint::from_str("1").unwrap()) >> 2, 515 | ); 516 | 517 | quote! { 518 | use ::ff::derive::subtle::ConstantTimeEq; 519 | 520 | // Because r = 3 (mod 4) 521 | // sqrt can be done with only one exponentiation, 522 | // via the computation of self^((r + 1) // 4) (mod r) 523 | let sqrt = { 524 | #mod_plus_1_over_4 525 | }; 526 | 527 | ::ff::derive::subtle::CtOption::new( 528 | sqrt, 529 | (sqrt * &sqrt).ct_eq(self), // Only return Some if it's the square root. 530 | ) 531 | } 532 | } else { 533 | // Addition chain for (t - 1) // 2 534 | let t_minus_1_over_2 = if t == BigUint::one() { 535 | quote!( #name::ONE ) 536 | } else { 537 | pow_fixed::generate("e! {self}, (&t - BigUint::one()) >> 1) 538 | }; 539 | 540 | quote! { 541 | // Tonelli-Shanks algorithm works for every remaining odd prime. 542 | // https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5) 543 | use ::ff::derive::subtle::{ConditionallySelectable, ConstantTimeEq}; 544 | 545 | // w = self^((t - 1) // 2) 546 | let w = { 547 | #t_minus_1_over_2 548 | }; 549 | 550 | let mut v = S; 551 | let mut x = *self * &w; 552 | let mut b = x * &w; 553 | 554 | // Initialize z as the 2^S root of unity. 555 | let mut z = ROOT_OF_UNITY; 556 | 557 | for max_v in (1..=S).rev() { 558 | let mut k = 1; 559 | let mut tmp = b.square(); 560 | let mut j_less_than_v: ::ff::derive::subtle::Choice = 1.into(); 561 | 562 | for j in 2..max_v { 563 | let tmp_is_one = tmp.ct_eq(&#name::ONE); 564 | let squared = #name::conditional_select(&tmp, &z, tmp_is_one).square(); 565 | tmp = #name::conditional_select(&squared, &tmp, tmp_is_one); 566 | let new_z = #name::conditional_select(&z, &squared, tmp_is_one); 567 | j_less_than_v &= !j.ct_eq(&v); 568 | k = u32::conditional_select(&j, &k, tmp_is_one); 569 | z = #name::conditional_select(&z, &new_z, j_less_than_v); 570 | } 571 | 572 | let result = x * &z; 573 | x = #name::conditional_select(&result, &x, b.ct_eq(&#name::ONE)); 574 | z = z.square(); 575 | b *= &z; 576 | v = k; 577 | } 578 | 579 | ::ff::derive::subtle::CtOption::new( 580 | x, 581 | (x * &x).ct_eq(self), // Only return Some if it's the square root. 582 | ) 583 | } 584 | }; 585 | 586 | // Compute R^2 mod m 587 | let r2 = biguint_to_u64_vec((&r * &r) % modulus, limbs); 588 | 589 | let r = biguint_to_u64_vec(r, limbs); 590 | let modulus_le_bytes = ReprEndianness::Little.modulus_repr(modulus, limbs * 8); 591 | let modulus_str = format!("0x{}", modulus.to_str_radix(16)); 592 | let modulus = biguint_to_real_u64_vec(modulus.clone(), limbs); 593 | 594 | // Compute -m^-1 mod 2**64 by exponentiating by totient(2**64) - 1 595 | let mut inv = 1u64; 596 | for _ in 0..63 { 597 | inv = inv.wrapping_mul(inv); 598 | inv = inv.wrapping_mul(modulus[0]); 599 | } 600 | inv = inv.wrapping_neg(); 601 | 602 | ( 603 | quote! { 604 | type REPR_BYTES = [u8; #bytes]; 605 | type REPR_BITS = REPR_BYTES; 606 | 607 | /// This is the modulus m of the prime field 608 | const MODULUS: REPR_BITS = [#(#modulus_le_bytes,)*]; 609 | 610 | /// This is the modulus m of the prime field in limb form 611 | const MODULUS_LIMBS: #name = #name([#(#modulus,)*]); 612 | 613 | /// This is the modulus m of the prime field in hex string form 614 | const MODULUS_STR: &'static str = #modulus_str; 615 | 616 | /// The number of bits needed to represent the modulus. 617 | const MODULUS_BITS: u32 = #modulus_num_bits; 618 | 619 | /// The number of bits that must be shaved from the beginning of 620 | /// the representation when randomly sampling. 621 | const REPR_SHAVE_BITS: u32 = #repr_shave_bits; 622 | 623 | /// 2^{limbs*64} mod m 624 | const R: #name = #name(#r); 625 | 626 | /// 2^{limbs*64*2} mod m 627 | const R2: #name = #name(#r2); 628 | 629 | /// -(m^{-1} mod m) mod m 630 | const INV: u64 = #inv; 631 | 632 | /// 2^{-1} mod m 633 | const TWO_INV: #name = #name(#two_inv); 634 | 635 | /// Multiplicative generator of `MODULUS` - 1 order, also quadratic 636 | /// nonresidue. 637 | const GENERATOR: #name = #name(#generator); 638 | 639 | /// 2^s * t = MODULUS - 1 with t odd 640 | const S: u32 = #s; 641 | 642 | /// 2^s root of unity computed by GENERATOR^t 643 | const ROOT_OF_UNITY: #name = #name(#root_of_unity); 644 | 645 | /// (2^s)^{-1} mod m 646 | const ROOT_OF_UNITY_INV: #name = #name(#root_of_unity_inv); 647 | 648 | /// GENERATOR^{2^s} 649 | const DELTA: #name = #name(#delta); 650 | }, 651 | sqrt_impl, 652 | ) 653 | } 654 | 655 | /// Implement PrimeField for the derived type. 656 | fn prime_field_impl( 657 | name: &syn::Ident, 658 | repr: &syn::Ident, 659 | modulus: &BigUint, 660 | endianness: &ReprEndianness, 661 | limbs: usize, 662 | sqrt_impl: proc_macro2::TokenStream, 663 | ) -> proc_macro2::TokenStream { 664 | // Returns r{n} as an ident. 665 | fn get_temp(n: usize) -> syn::Ident { 666 | syn::Ident::new(&format!("r{}", n), proc_macro2::Span::call_site()) 667 | } 668 | 669 | // The parameter list for the mont_reduce() internal method. 670 | // r0: u64, mut r1: u64, mut r2: u64, ... 671 | let mut mont_paramlist = proc_macro2::TokenStream::new(); 672 | mont_paramlist.append_separated( 673 | (0..(limbs * 2)).map(|i| (i, get_temp(i))).map(|(i, x)| { 674 | if i != 0 { 675 | quote! {mut #x: u64} 676 | } else { 677 | quote! {#x: u64} 678 | } 679 | }), 680 | proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), 681 | ); 682 | 683 | // Implement montgomery reduction for some number of limbs 684 | fn mont_impl(limbs: usize) -> proc_macro2::TokenStream { 685 | let mut gen = proc_macro2::TokenStream::new(); 686 | 687 | for i in 0..limbs { 688 | { 689 | let temp = get_temp(i); 690 | gen.extend(quote! { 691 | let k = #temp.wrapping_mul(INV); 692 | let (_, carry) = ::ff::derive::mac(#temp, k, MODULUS_LIMBS.0[0], 0); 693 | }); 694 | } 695 | 696 | for j in 1..limbs { 697 | let temp = get_temp(i + j); 698 | gen.extend(quote! { 699 | let (#temp, carry) = ::ff::derive::mac(#temp, k, MODULUS_LIMBS.0[#j], carry); 700 | }); 701 | } 702 | 703 | let temp = get_temp(i + limbs); 704 | 705 | if i == 0 { 706 | gen.extend(quote! { 707 | let (#temp, carry2) = ::ff::derive::adc(#temp, 0, carry); 708 | }); 709 | } else { 710 | gen.extend(quote! { 711 | let (#temp, carry2) = ::ff::derive::adc(#temp, carry2, carry); 712 | }); 713 | } 714 | } 715 | 716 | for i in 0..limbs { 717 | let temp = get_temp(limbs + i); 718 | 719 | gen.extend(quote! { 720 | self.0[#i] = #temp; 721 | }); 722 | } 723 | 724 | gen 725 | } 726 | 727 | fn sqr_impl(a: proc_macro2::TokenStream, limbs: usize) -> proc_macro2::TokenStream { 728 | let mut gen = proc_macro2::TokenStream::new(); 729 | 730 | if limbs > 1 { 731 | for i in 0..(limbs - 1) { 732 | gen.extend(quote! { 733 | let carry = 0; 734 | }); 735 | 736 | for j in (i + 1)..limbs { 737 | let temp = get_temp(i + j); 738 | if i == 0 { 739 | gen.extend(quote! { 740 | let (#temp, carry) = ::ff::derive::mac(0, #a.0[#i], #a.0[#j], carry); 741 | }); 742 | } else { 743 | gen.extend(quote! { 744 | let (#temp, carry) = ::ff::derive::mac(#temp, #a.0[#i], #a.0[#j], carry); 745 | }); 746 | } 747 | } 748 | 749 | let temp = get_temp(i + limbs); 750 | 751 | gen.extend(quote! { 752 | let #temp = carry; 753 | }); 754 | } 755 | 756 | for i in 1..(limbs * 2) { 757 | let temp0 = get_temp(limbs * 2 - i); 758 | let temp1 = get_temp(limbs * 2 - i - 1); 759 | 760 | if i == 1 { 761 | gen.extend(quote! { 762 | let #temp0 = #temp1 >> 63; 763 | }); 764 | } else if i == (limbs * 2 - 1) { 765 | gen.extend(quote! { 766 | let #temp0 = #temp0 << 1; 767 | }); 768 | } else { 769 | gen.extend(quote! { 770 | let #temp0 = (#temp0 << 1) | (#temp1 >> 63); 771 | }); 772 | } 773 | } 774 | } else { 775 | let temp1 = get_temp(1); 776 | gen.extend(quote! { 777 | let #temp1 = 0; 778 | }); 779 | } 780 | 781 | for i in 0..limbs { 782 | let temp0 = get_temp(i * 2); 783 | let temp1 = get_temp(i * 2 + 1); 784 | if i == 0 { 785 | gen.extend(quote! { 786 | let (#temp0, carry) = ::ff::derive::mac(0, #a.0[#i], #a.0[#i], 0); 787 | }); 788 | } else { 789 | gen.extend(quote! { 790 | let (#temp0, carry) = ::ff::derive::mac(#temp0, #a.0[#i], #a.0[#i], carry); 791 | }); 792 | } 793 | 794 | gen.extend(quote! { 795 | let (#temp1, carry) = ::ff::derive::adc(#temp1, 0, carry); 796 | }); 797 | } 798 | 799 | let mut mont_calling = proc_macro2::TokenStream::new(); 800 | mont_calling.append_separated( 801 | (0..(limbs * 2)).map(get_temp), 802 | proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), 803 | ); 804 | 805 | gen.extend(quote! { 806 | let mut ret = *self; 807 | ret.mont_reduce(#mont_calling); 808 | ret 809 | }); 810 | 811 | gen 812 | } 813 | 814 | fn mul_impl( 815 | a: proc_macro2::TokenStream, 816 | b: proc_macro2::TokenStream, 817 | limbs: usize, 818 | ) -> proc_macro2::TokenStream { 819 | let mut gen = proc_macro2::TokenStream::new(); 820 | 821 | for i in 0..limbs { 822 | gen.extend(quote! { 823 | let carry = 0; 824 | }); 825 | 826 | for j in 0..limbs { 827 | let temp = get_temp(i + j); 828 | 829 | if i == 0 { 830 | gen.extend(quote! { 831 | let (#temp, carry) = ::ff::derive::mac(0, #a.0[#i], #b.0[#j], carry); 832 | }); 833 | } else { 834 | gen.extend(quote! { 835 | let (#temp, carry) = ::ff::derive::mac(#temp, #a.0[#i], #b.0[#j], carry); 836 | }); 837 | } 838 | } 839 | 840 | let temp = get_temp(i + limbs); 841 | 842 | gen.extend(quote! { 843 | let #temp = carry; 844 | }); 845 | } 846 | 847 | let mut mont_calling = proc_macro2::TokenStream::new(); 848 | mont_calling.append_separated( 849 | (0..(limbs * 2)).map(get_temp), 850 | proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), 851 | ); 852 | 853 | gen.extend(quote! { 854 | self.mont_reduce(#mont_calling); 855 | }); 856 | 857 | gen 858 | } 859 | 860 | /// Generates an implementation of multiplicative inversion within the target prime 861 | /// field. 862 | fn inv_impl(a: proc_macro2::TokenStream, modulus: &BigUint) -> proc_macro2::TokenStream { 863 | // Addition chain for p - 2 864 | let mod_minus_2 = pow_fixed::generate(&a, modulus - BigUint::from(2u64)); 865 | 866 | quote! { 867 | use ::ff::derive::subtle::ConstantTimeEq; 868 | 869 | // By Euler's theorem, if `a` is coprime to `p` (i.e. `gcd(a, p) = 1`), then: 870 | // a^-1 ≡ a^(phi(p) - 1) mod p 871 | // 872 | // `ff_derive` requires that `p` is prime; in this case, `phi(p) = p - 1`, and 873 | // thus: 874 | // a^-1 ≡ a^(p - 2) mod p 875 | let inv = { 876 | #mod_minus_2 877 | }; 878 | 879 | ::ff::derive::subtle::CtOption::new(inv, !#a.is_zero()) 880 | } 881 | } 882 | 883 | let squaring_impl = sqr_impl(quote! {self}, limbs); 884 | let multiply_impl = mul_impl(quote! {self}, quote! {other}, limbs); 885 | let invert_impl = inv_impl(quote! {self}, modulus); 886 | let montgomery_impl = mont_impl(limbs); 887 | 888 | // self.0[0].ct_eq(&other.0[0]) & self.0[1].ct_eq(&other.0[1]) & ... 889 | let mut ct_eq_impl = proc_macro2::TokenStream::new(); 890 | ct_eq_impl.append_separated( 891 | (0..limbs).map(|i| quote! { self.0[#i].ct_eq(&other.0[#i]) }), 892 | proc_macro2::Punct::new('&', proc_macro2::Spacing::Alone), 893 | ); 894 | 895 | fn mont_reduce_params(a: proc_macro2::TokenStream, limbs: usize) -> proc_macro2::TokenStream { 896 | // a.0[0], a.0[1], ..., 0, 0, 0, 0, ... 897 | let mut mont_reduce_params = proc_macro2::TokenStream::new(); 898 | mont_reduce_params.append_separated( 899 | (0..limbs) 900 | .map(|i| quote! { #a.0[#i] }) 901 | .chain((0..limbs).map(|_| quote! {0})), 902 | proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), 903 | ); 904 | mont_reduce_params 905 | } 906 | 907 | let mont_reduce_self_params = mont_reduce_params(quote! {self}, limbs); 908 | let mont_reduce_other_params = mont_reduce_params(quote! {other}, limbs); 909 | 910 | let from_repr_impl = endianness.from_repr(name, limbs); 911 | let to_repr_impl = endianness.to_repr(quote! {#repr}, &mont_reduce_self_params, limbs); 912 | 913 | let prime_field_bits_impl = if cfg!(feature = "bits") { 914 | let to_le_bits_impl = ReprEndianness::Little.to_repr( 915 | quote! {::ff::derive::bitvec::array::BitArray::new}, 916 | &mont_reduce_self_params, 917 | limbs, 918 | ); 919 | 920 | Some(quote! { 921 | impl ::ff::PrimeFieldBits for #name { 922 | type ReprBits = REPR_BITS; 923 | 924 | fn to_le_bits(&self) -> ::ff::FieldBits { 925 | #to_le_bits_impl 926 | } 927 | 928 | fn char_le_bits() -> ::ff::FieldBits { 929 | ::ff::FieldBits::new(MODULUS) 930 | } 931 | } 932 | }) 933 | } else { 934 | None 935 | }; 936 | 937 | let top_limb_index = limbs - 1; 938 | 939 | quote! { 940 | impl ::core::marker::Copy for #name { } 941 | 942 | impl ::core::clone::Clone for #name { 943 | fn clone(&self) -> #name { 944 | *self 945 | } 946 | } 947 | 948 | impl ::core::default::Default for #name { 949 | fn default() -> #name { 950 | use ::ff::Field; 951 | #name::ZERO 952 | } 953 | } 954 | 955 | impl ::ff::derive::subtle::ConstantTimeEq for #name { 956 | fn ct_eq(&self, other: &#name) -> ::ff::derive::subtle::Choice { 957 | use ::ff::PrimeField; 958 | self.to_repr().ct_eq(&other.to_repr()) 959 | } 960 | } 961 | 962 | impl ::core::cmp::PartialEq for #name { 963 | fn eq(&self, other: &#name) -> bool { 964 | use ::ff::derive::subtle::ConstantTimeEq; 965 | self.ct_eq(other).into() 966 | } 967 | } 968 | 969 | impl ::core::cmp::Eq for #name { } 970 | 971 | impl ::core::fmt::Debug for #name 972 | { 973 | fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { 974 | use ::ff::PrimeField; 975 | write!(f, "{}({:?})", stringify!(#name), self.to_repr()) 976 | } 977 | } 978 | 979 | /// Elements are ordered lexicographically. 980 | impl Ord for #name { 981 | #[inline(always)] 982 | fn cmp(&self, other: &#name) -> ::core::cmp::Ordering { 983 | let mut a = *self; 984 | a.mont_reduce( 985 | #mont_reduce_self_params 986 | ); 987 | 988 | let mut b = *other; 989 | b.mont_reduce( 990 | #mont_reduce_other_params 991 | ); 992 | 993 | a.cmp_native(&b) 994 | } 995 | } 996 | 997 | impl PartialOrd for #name { 998 | #[inline(always)] 999 | fn partial_cmp(&self, other: &#name) -> Option<::core::cmp::Ordering> { 1000 | Some(self.cmp(other)) 1001 | } 1002 | } 1003 | 1004 | impl From for #name { 1005 | #[inline(always)] 1006 | fn from(val: u64) -> #name { 1007 | let mut raw = [0u64; #limbs]; 1008 | raw[0] = val; 1009 | #name(raw) * R2 1010 | } 1011 | } 1012 | 1013 | impl From<#name> for #repr { 1014 | fn from(e: #name) -> #repr { 1015 | use ::ff::PrimeField; 1016 | e.to_repr() 1017 | } 1018 | } 1019 | 1020 | impl<'a> From<&'a #name> for #repr { 1021 | fn from(e: &'a #name) -> #repr { 1022 | use ::ff::PrimeField; 1023 | e.to_repr() 1024 | } 1025 | } 1026 | 1027 | impl ::ff::derive::subtle::ConditionallySelectable for #name { 1028 | fn conditional_select(a: &#name, b: &#name, choice: ::ff::derive::subtle::Choice) -> #name { 1029 | let mut res = [0u64; #limbs]; 1030 | for i in 0..#limbs { 1031 | res[i] = u64::conditional_select(&a.0[i], &b.0[i], choice); 1032 | } 1033 | #name(res) 1034 | } 1035 | } 1036 | 1037 | impl ::core::ops::Neg for #name { 1038 | type Output = #name; 1039 | 1040 | #[inline] 1041 | fn neg(self) -> #name { 1042 | use ::ff::Field; 1043 | 1044 | let mut ret = self; 1045 | if !ret.is_zero_vartime() { 1046 | let mut tmp = MODULUS_LIMBS; 1047 | tmp.sub_noborrow(&ret); 1048 | ret = tmp; 1049 | } 1050 | ret 1051 | } 1052 | } 1053 | 1054 | impl<'r> ::core::ops::Add<&'r #name> for #name { 1055 | type Output = #name; 1056 | 1057 | #[inline] 1058 | fn add(self, other: &#name) -> #name { 1059 | use ::core::ops::AddAssign; 1060 | 1061 | let mut ret = self; 1062 | ret.add_assign(other); 1063 | ret 1064 | } 1065 | } 1066 | 1067 | impl ::core::ops::Add for #name { 1068 | type Output = #name; 1069 | 1070 | #[inline] 1071 | fn add(self, other: #name) -> Self { 1072 | self + &other 1073 | } 1074 | } 1075 | 1076 | impl<'r> ::core::ops::AddAssign<&'r #name> for #name { 1077 | #[inline] 1078 | fn add_assign(&mut self, other: &#name) { 1079 | // This cannot exceed the backing capacity. 1080 | self.add_nocarry(other); 1081 | 1082 | // However, it may need to be reduced. 1083 | self.reduce(); 1084 | } 1085 | } 1086 | 1087 | impl ::core::ops::AddAssign for #name { 1088 | #[inline] 1089 | fn add_assign(&mut self, other: #name) { 1090 | self.add_assign(&other); 1091 | } 1092 | } 1093 | 1094 | impl<'r> ::core::ops::Sub<&'r #name> for #name { 1095 | type Output = #name; 1096 | 1097 | #[inline] 1098 | fn sub(self, other: &#name) -> Self { 1099 | use ::core::ops::SubAssign; 1100 | 1101 | let mut ret = self; 1102 | ret.sub_assign(other); 1103 | ret 1104 | } 1105 | } 1106 | 1107 | impl ::core::ops::Sub for #name { 1108 | type Output = #name; 1109 | 1110 | #[inline] 1111 | fn sub(self, other: #name) -> Self { 1112 | self - &other 1113 | } 1114 | } 1115 | 1116 | impl<'r> ::core::ops::SubAssign<&'r #name> for #name { 1117 | #[inline] 1118 | fn sub_assign(&mut self, other: &#name) { 1119 | // If `other` is larger than `self`, we'll need to add the modulus to self first. 1120 | if other.cmp_native(self) == ::core::cmp::Ordering::Greater { 1121 | self.add_nocarry(&MODULUS_LIMBS); 1122 | } 1123 | 1124 | self.sub_noborrow(other); 1125 | } 1126 | } 1127 | 1128 | impl ::core::ops::SubAssign for #name { 1129 | #[inline] 1130 | fn sub_assign(&mut self, other: #name) { 1131 | self.sub_assign(&other); 1132 | } 1133 | } 1134 | 1135 | impl<'r> ::core::ops::Mul<&'r #name> for #name { 1136 | type Output = #name; 1137 | 1138 | #[inline] 1139 | fn mul(self, other: &#name) -> Self { 1140 | use ::core::ops::MulAssign; 1141 | 1142 | let mut ret = self; 1143 | ret.mul_assign(other); 1144 | ret 1145 | } 1146 | } 1147 | 1148 | impl ::core::ops::Mul for #name { 1149 | type Output = #name; 1150 | 1151 | #[inline] 1152 | fn mul(self, other: #name) -> Self { 1153 | self * &other 1154 | } 1155 | } 1156 | 1157 | impl<'r> ::core::ops::MulAssign<&'r #name> for #name { 1158 | #[inline] 1159 | fn mul_assign(&mut self, other: &#name) 1160 | { 1161 | #multiply_impl 1162 | } 1163 | } 1164 | 1165 | impl ::core::ops::MulAssign for #name { 1166 | #[inline] 1167 | fn mul_assign(&mut self, other: #name) 1168 | { 1169 | self.mul_assign(&other); 1170 | } 1171 | } 1172 | 1173 | impl> ::core::iter::Sum for #name { 1174 | fn sum>(iter: I) -> Self { 1175 | use ::ff::Field; 1176 | 1177 | iter.fold(Self::ZERO, |acc, item| acc + item.borrow()) 1178 | } 1179 | } 1180 | 1181 | impl> ::core::iter::Product for #name { 1182 | fn product>(iter: I) -> Self { 1183 | use ::ff::Field; 1184 | 1185 | iter.fold(Self::ONE, |acc, item| acc * item.borrow()) 1186 | } 1187 | } 1188 | 1189 | impl ::ff::PrimeField for #name { 1190 | type Repr = #repr; 1191 | 1192 | fn from_repr(r: #repr) -> ::ff::derive::subtle::CtOption<#name> { 1193 | #from_repr_impl 1194 | 1195 | // Try to subtract the modulus 1196 | let borrow = r.0.iter().zip(MODULUS_LIMBS.0.iter()).fold(0, |borrow, (a, b)| { 1197 | ::ff::derive::sbb(*a, *b, borrow).1 1198 | }); 1199 | 1200 | // If the element is smaller than MODULUS then the 1201 | // subtraction will underflow, producing a borrow value 1202 | // of 0xffff...ffff. Otherwise, it'll be zero. 1203 | let is_some = ::ff::derive::subtle::Choice::from((borrow as u8) & 1); 1204 | 1205 | // Convert to Montgomery form by computing 1206 | // (a.R^0 * R^2) / R = a.R 1207 | ::ff::derive::subtle::CtOption::new(r * &R2, is_some) 1208 | } 1209 | 1210 | fn from_repr_vartime(r: #repr) -> Option<#name> { 1211 | #from_repr_impl 1212 | 1213 | if r.is_valid() { 1214 | Some(r * R2) 1215 | } else { 1216 | None 1217 | } 1218 | } 1219 | 1220 | fn to_repr(&self) -> #repr { 1221 | #to_repr_impl 1222 | } 1223 | 1224 | #[inline(always)] 1225 | fn is_odd(&self) -> ::ff::derive::subtle::Choice { 1226 | let mut r = *self; 1227 | r.mont_reduce( 1228 | #mont_reduce_self_params 1229 | ); 1230 | 1231 | // TODO: This looks like a constant-time result, but r.mont_reduce() is 1232 | // currently implemented using variable-time code. 1233 | ::ff::derive::subtle::Choice::from((r.0[0] & 1) as u8) 1234 | } 1235 | 1236 | const MODULUS: &'static str = MODULUS_STR; 1237 | 1238 | const NUM_BITS: u32 = MODULUS_BITS; 1239 | 1240 | const CAPACITY: u32 = Self::NUM_BITS - 1; 1241 | 1242 | const TWO_INV: Self = TWO_INV; 1243 | 1244 | const MULTIPLICATIVE_GENERATOR: Self = GENERATOR; 1245 | 1246 | const S: u32 = S; 1247 | 1248 | const ROOT_OF_UNITY: Self = ROOT_OF_UNITY; 1249 | 1250 | const ROOT_OF_UNITY_INV: Self = ROOT_OF_UNITY_INV; 1251 | 1252 | const DELTA: Self = DELTA; 1253 | } 1254 | 1255 | #prime_field_bits_impl 1256 | 1257 | impl ::ff::Field for #name { 1258 | const ZERO: Self = #name([0; #limbs]); 1259 | const ONE: Self = R; 1260 | 1261 | /// Computes a uniformly random element using rejection sampling. 1262 | fn random(mut rng: impl ::ff::derive::rand_core::RngCore) -> Self { 1263 | loop { 1264 | let mut tmp = { 1265 | let mut repr = [0u64; #limbs]; 1266 | for i in 0..#limbs { 1267 | repr[i] = rng.next_u64(); 1268 | } 1269 | #name(repr) 1270 | }; 1271 | 1272 | // Mask away the unused most-significant bits. 1273 | // Note: In some edge cases, `REPR_SHAVE_BITS` could be 64, in which case 1274 | // `0xfff... >> REPR_SHAVE_BITS` overflows. So use `checked_shr` instead. 1275 | // This is always sufficient because we will have at most one spare limb 1276 | // to accommodate values of up to twice the modulus. 1277 | tmp.0[#top_limb_index] &= 0xffffffffffffffffu64.checked_shr(REPR_SHAVE_BITS).unwrap_or(0); 1278 | 1279 | if tmp.is_valid() { 1280 | return tmp 1281 | } 1282 | } 1283 | } 1284 | 1285 | #[inline] 1286 | fn is_zero_vartime(&self) -> bool { 1287 | self.0.iter().all(|&e| e == 0) 1288 | } 1289 | 1290 | #[inline] 1291 | fn double(&self) -> Self { 1292 | let mut ret = *self; 1293 | 1294 | // This cannot exceed the backing capacity. 1295 | let mut last = 0; 1296 | for i in &mut ret.0 { 1297 | let tmp = *i >> 63; 1298 | *i <<= 1; 1299 | *i |= last; 1300 | last = tmp; 1301 | } 1302 | 1303 | // However, it may need to be reduced. 1304 | ret.reduce(); 1305 | 1306 | ret 1307 | } 1308 | 1309 | fn invert(&self) -> ::ff::derive::subtle::CtOption { 1310 | #invert_impl 1311 | } 1312 | 1313 | #[inline] 1314 | fn square(&self) -> Self 1315 | { 1316 | #squaring_impl 1317 | } 1318 | 1319 | fn sqrt_ratio(num: &Self, div: &Self) -> (::ff::derive::subtle::Choice, Self) { 1320 | ::ff::helpers::sqrt_ratio_generic(num, div) 1321 | } 1322 | 1323 | fn sqrt(&self) -> ::ff::derive::subtle::CtOption { 1324 | #sqrt_impl 1325 | } 1326 | } 1327 | 1328 | impl #name { 1329 | /// Compares two elements in native representation. This is only used 1330 | /// internally. 1331 | #[inline(always)] 1332 | fn cmp_native(&self, other: &#name) -> ::core::cmp::Ordering { 1333 | for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) { 1334 | if a < b { 1335 | return ::core::cmp::Ordering::Less 1336 | } else if a > b { 1337 | return ::core::cmp::Ordering::Greater 1338 | } 1339 | } 1340 | 1341 | ::core::cmp::Ordering::Equal 1342 | } 1343 | 1344 | /// Determines if the element is really in the field. This is only used 1345 | /// internally. 1346 | #[inline(always)] 1347 | fn is_valid(&self) -> bool { 1348 | // The Ord impl calls `reduce`, which in turn calls `is_valid`, so we use 1349 | // this internal function to eliminate the cycle. 1350 | self.cmp_native(&MODULUS_LIMBS) == ::core::cmp::Ordering::Less 1351 | } 1352 | 1353 | #[inline(always)] 1354 | fn add_nocarry(&mut self, other: &#name) { 1355 | let mut carry = 0; 1356 | 1357 | for (a, b) in self.0.iter_mut().zip(other.0.iter()) { 1358 | let (new_a, new_carry) = ::ff::derive::adc(*a, *b, carry); 1359 | *a = new_a; 1360 | carry = new_carry; 1361 | } 1362 | } 1363 | 1364 | #[inline(always)] 1365 | fn sub_noborrow(&mut self, other: &#name) { 1366 | let mut borrow = 0; 1367 | 1368 | for (a, b) in self.0.iter_mut().zip(other.0.iter()) { 1369 | let (new_a, new_borrow) = ::ff::derive::sbb(*a, *b, borrow); 1370 | *a = new_a; 1371 | borrow = new_borrow; 1372 | } 1373 | } 1374 | 1375 | /// Subtracts the modulus from this element if this element is not in the 1376 | /// field. Only used internally. 1377 | #[inline(always)] 1378 | fn reduce(&mut self) { 1379 | if !self.is_valid() { 1380 | self.sub_noborrow(&MODULUS_LIMBS); 1381 | } 1382 | } 1383 | 1384 | #[allow(clippy::too_many_arguments)] 1385 | #[inline(always)] 1386 | fn mont_reduce( 1387 | &mut self, 1388 | #mont_paramlist 1389 | ) 1390 | { 1391 | // The Montgomery reduction here is based on Algorithm 14.32 in 1392 | // Handbook of Applied Cryptography 1393 | // . 1394 | 1395 | #montgomery_impl 1396 | 1397 | self.reduce(); 1398 | } 1399 | } 1400 | } 1401 | } 1402 | -------------------------------------------------------------------------------- /ff_derive/src/pow_fixed.rs: -------------------------------------------------------------------------------- 1 | //! Fixed-exponent variable-base exponentiation using addition chains. 2 | 3 | use addchain::{build_addition_chain, Step}; 4 | use num_bigint::BigUint; 5 | use quote::quote; 6 | use syn::Ident; 7 | 8 | /// Returns t{n} as an ident. 9 | fn get_temp(n: usize) -> Ident { 10 | Ident::new(&format!("t{}", n), proc_macro2::Span::call_site()) 11 | } 12 | 13 | pub(crate) fn generate( 14 | base: &proc_macro2::TokenStream, 15 | exponent: BigUint, 16 | ) -> proc_macro2::TokenStream { 17 | let steps = build_addition_chain(exponent); 18 | 19 | let mut gen = proc_macro2::TokenStream::new(); 20 | 21 | // First entry in chain is one, i.e. the base. 22 | let start = get_temp(0); 23 | gen.extend(quote! { 24 | let #start = #base; 25 | }); 26 | 27 | let mut tmps = vec![start]; 28 | for (i, step) in steps.into_iter().enumerate() { 29 | let out = get_temp(i + 1); 30 | 31 | gen.extend(match step { 32 | Step::Double { index } => { 33 | let val = &tmps[index]; 34 | quote! { 35 | let #out = #val.square(); 36 | } 37 | } 38 | Step::Add { left, right } => { 39 | let left = &tmps[left]; 40 | let right = &tmps[right]; 41 | quote! { 42 | let #out = #left * #right; 43 | } 44 | } 45 | }); 46 | 47 | tmps.push(out.clone()); 48 | } 49 | 50 | let end = tmps.last().expect("have last"); 51 | gen.extend(quote! { 52 | #end 53 | }); 54 | 55 | gen 56 | } 57 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "1.56.0" 3 | components = [ "clippy", "rustfmt" ] 4 | -------------------------------------------------------------------------------- /src/batch.rs: -------------------------------------------------------------------------------- 1 | //! Batched field inversion APIs, using [Montgomery's trick]. 2 | //! 3 | //! [Montgomery's trick]: https://zcash.github.io/halo2/background/fields.html#montgomerys-trick 4 | 5 | use subtle::ConstantTimeEq; 6 | 7 | use crate::Field; 8 | 9 | /// Extension trait for iterators over mutable field elements which allows those field 10 | /// elements to be inverted in a batch. 11 | /// 12 | /// `I: IntoIterator` implements this trait when 13 | /// the `alloc` feature flag is enabled. 14 | /// 15 | /// For non-allocating contexts, see the [`BatchInverter`] struct. 16 | #[cfg(feature = "alloc")] 17 | #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] 18 | pub trait BatchInvert { 19 | /// Consumes this iterator and inverts each field element (when nonzero). Zero-valued 20 | /// elements are left as zero. 21 | /// 22 | /// Returns the inverse of the product of all nonzero field elements. 23 | fn batch_invert(self) -> F; 24 | } 25 | 26 | #[cfg(feature = "alloc")] 27 | #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] 28 | impl<'a, F, I> BatchInvert for I 29 | where 30 | F: Field + ConstantTimeEq, 31 | I: IntoIterator, 32 | { 33 | fn batch_invert(self) -> F { 34 | let mut acc = F::ONE; 35 | let iter = self.into_iter(); 36 | let mut tmp = alloc::vec::Vec::with_capacity(iter.size_hint().0); 37 | for p in iter { 38 | let q = *p; 39 | tmp.push((acc, p)); 40 | acc = F::conditional_select(&(acc * q), &acc, q.is_zero()); 41 | } 42 | acc = acc.invert().unwrap(); 43 | let allinv = acc; 44 | 45 | for (tmp, p) in tmp.into_iter().rev() { 46 | let skip = p.is_zero(); 47 | 48 | let tmp = tmp * acc; 49 | acc = F::conditional_select(&(acc * *p), &acc, skip); 50 | *p = F::conditional_select(&tmp, p, skip); 51 | } 52 | 53 | allinv 54 | } 55 | } 56 | 57 | /// A non-allocating batch inverter. 58 | pub struct BatchInverter {} 59 | 60 | impl BatchInverter { 61 | /// Inverts each field element in `elements` (when nonzero). Zero-valued elements are 62 | /// left as zero. 63 | /// 64 | /// - `scratch_space` is a slice of field elements that can be freely overwritten. 65 | /// 66 | /// Returns the inverse of the product of all nonzero field elements. 67 | /// 68 | /// # Panics 69 | /// 70 | /// This function will panic if `elements.len() != scratch_space.len()`. 71 | pub fn invert_with_external_scratch(elements: &mut [F], scratch_space: &mut [F]) -> F 72 | where 73 | F: Field + ConstantTimeEq, 74 | { 75 | assert_eq!(elements.len(), scratch_space.len()); 76 | 77 | let mut acc = F::ONE; 78 | for (p, scratch) in elements.iter().zip(scratch_space.iter_mut()) { 79 | *scratch = acc; 80 | acc = F::conditional_select(&(acc * *p), &acc, p.is_zero()); 81 | } 82 | acc = acc.invert().unwrap(); 83 | let allinv = acc; 84 | 85 | for (p, scratch) in elements.iter_mut().zip(scratch_space.iter()).rev() { 86 | let tmp = *scratch * acc; 87 | let skip = p.is_zero(); 88 | acc = F::conditional_select(&(acc * *p), &acc, skip); 89 | *p = F::conditional_select(&tmp, &p, skip); 90 | } 91 | 92 | allinv 93 | } 94 | 95 | /// Inverts each field element in `items` (when nonzero). Zero-valued elements are 96 | /// left as zero. 97 | /// 98 | /// - `element` is a function that extracts the element to be inverted from `items`. 99 | /// - `scratch_space` is a function that extracts the scratch space from `items`. 100 | /// 101 | /// Returns the inverse of the product of all nonzero field elements. 102 | pub fn invert_with_internal_scratch( 103 | items: &mut [T], 104 | element: TE, 105 | scratch_space: TS, 106 | ) -> F 107 | where 108 | F: Field + ConstantTimeEq, 109 | TE: Fn(&mut T) -> &mut F, 110 | TS: Fn(&mut T) -> &mut F, 111 | { 112 | let mut acc = F::ONE; 113 | for item in items.iter_mut() { 114 | *(scratch_space)(item) = acc; 115 | let p = (element)(item); 116 | acc = F::conditional_select(&(acc * *p), &acc, p.is_zero()); 117 | } 118 | acc = acc.invert().unwrap(); 119 | let allinv = acc; 120 | 121 | for item in items.iter_mut().rev() { 122 | let tmp = *(scratch_space)(item) * acc; 123 | let p = (element)(item); 124 | let skip = p.is_zero(); 125 | acc = F::conditional_select(&(acc * *p), &acc, skip); 126 | *p = F::conditional_select(&tmp, &p, skip); 127 | } 128 | 129 | allinv 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/helpers.rs: -------------------------------------------------------------------------------- 1 | //! Helper methods for implementing the `ff` traits. 2 | 3 | use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; 4 | 5 | use crate::PrimeField; 6 | 7 | /// Constant-time implementation of Tonelli–Shanks' square-root algorithm for 8 | /// `p mod 16 = 1`. 9 | /// 10 | /// `tm1d2` should be set to `(t - 1) // 2`, where `t = (modulus - 1) >> F::S`. 11 | /// 12 | /// ## Implementing [`Field::sqrt`] 13 | /// 14 | /// This function can be used to implement [`Field::sqrt`] for fields that both implement 15 | /// [`PrimeField`] and satisfy `p mod 16 = 1`. 16 | /// 17 | /// [`Field::sqrt`]: crate::Field::sqrt 18 | pub fn sqrt_tonelli_shanks>(f: &F, tm1d2: S) -> CtOption { 19 | // This is a constant-time version of https://eprint.iacr.org/2012/685.pdf (page 12, 20 | // algorithm 5). Steps 2-5 of the algorithm are omitted because they are only needed 21 | // to detect non-square input; it is more efficient to do that by checking at the end 22 | // whether the square of the result is the input. 23 | 24 | // w = self^((t - 1) // 2) 25 | let w = f.pow_vartime(tm1d2); 26 | 27 | let mut v = F::S; 28 | let mut x = w * f; 29 | let mut b = x * w; 30 | 31 | // Initialize z as the 2^S root of unity. 32 | let mut z = F::ROOT_OF_UNITY; 33 | 34 | for max_v in (1..=F::S).rev() { 35 | let mut k = 1; 36 | let mut b2k = b.square(); 37 | let mut j_less_than_v: Choice = 1.into(); 38 | 39 | // This loop has three phases based on the value of k for algorithm 5: 40 | // - for j <= k, we square b2k in order to calculate b^{2^k}. 41 | // - for k < j <= v, we square z in order to calculate ω. 42 | // - for j > v, we do nothing. 43 | for j in 2..max_v { 44 | let b2k_is_one = b2k.ct_eq(&F::ONE); 45 | let squared = F::conditional_select(&b2k, &z, b2k_is_one).square(); 46 | b2k = F::conditional_select(&squared, &b2k, b2k_is_one); 47 | let new_z = F::conditional_select(&z, &squared, b2k_is_one); 48 | j_less_than_v &= !j.ct_eq(&v); 49 | k = u32::conditional_select(&j, &k, b2k_is_one); 50 | z = F::conditional_select(&z, &new_z, j_less_than_v); 51 | } 52 | 53 | let result = x * z; 54 | x = F::conditional_select(&result, &x, b.ct_eq(&F::ONE)); 55 | z = z.square(); 56 | b *= z; 57 | v = k; 58 | } 59 | 60 | CtOption::new( 61 | x, 62 | (x * x).ct_eq(f), // Only return Some if it's the square root. 63 | ) 64 | } 65 | 66 | /// Computes: 67 | /// 68 | /// - $(\textsf{true}, \sqrt{\textsf{num}/\textsf{div}})$, if $\textsf{num}$ and 69 | /// $\textsf{div}$ are nonzero and $\textsf{num}/\textsf{div}$ is a square in the 70 | /// field; 71 | /// - $(\textsf{true}, 0)$, if $\textsf{num}$ is zero; 72 | /// - $(\textsf{false}, 0)$, if $\textsf{num}$ is nonzero and $\textsf{div}$ is zero; 73 | /// - $(\textsf{false}, \sqrt{G_S \cdot \textsf{num}/\textsf{div}})$, if 74 | /// $\textsf{num}$ and $\textsf{div}$ are nonzero and $\textsf{num}/\textsf{div}$ is 75 | /// a nonsquare in the field; 76 | /// 77 | /// where $G_S$ is a non-square. 78 | /// 79 | /// For this method, $G_S$ is currently [`PrimeField::ROOT_OF_UNITY`], a generator of the 80 | /// order $2^S$ subgroup. Users of this crate should not rely on this generator being 81 | /// fixed; it may be changed in future crate versions to simplify the implementation of 82 | /// the SSWU hash-to-curve algorithm. 83 | /// 84 | /// The choice of root from sqrt is unspecified. 85 | /// 86 | /// ## Implementing [`Field::sqrt_ratio`] 87 | /// 88 | /// This function can be used to implement [`Field::sqrt_ratio`] for fields that also 89 | /// implement [`PrimeField`]. If doing so, the default implementation of [`Field::sqrt`] 90 | /// *MUST* be overridden, or else both functions will recurse in a cycle until a stack 91 | /// overflow occurs. 92 | /// 93 | /// [`Field::sqrt_ratio`]: crate::Field::sqrt_ratio 94 | /// [`Field::sqrt`]: crate::Field::sqrt 95 | pub fn sqrt_ratio_generic(num: &F, div: &F) -> (Choice, F) { 96 | // General implementation: 97 | // 98 | // a = num * inv0(div) 99 | // = { 0 if div is zero 100 | // { num/div otherwise 101 | // 102 | // b = G_S * a 103 | // = { 0 if div is zero 104 | // { G_S*num/div otherwise 105 | // 106 | // Since G_S is non-square, a and b are either both zero (and both square), or 107 | // only one of them is square. We can therefore choose the square root to return 108 | // based on whether a is square, but for the boolean output we need to handle the 109 | // num != 0 && div == 0 case specifically. 110 | 111 | let a = div.invert().unwrap_or(F::ZERO) * num; 112 | let b = a * F::ROOT_OF_UNITY; 113 | let sqrt_a = a.sqrt(); 114 | let sqrt_b = b.sqrt(); 115 | 116 | let num_is_zero = num.is_zero(); 117 | let div_is_zero = div.is_zero(); 118 | let is_square = sqrt_a.is_some(); 119 | let is_nonsquare = sqrt_b.is_some(); 120 | assert!(bool::from( 121 | num_is_zero | div_is_zero | (is_square ^ is_nonsquare) 122 | )); 123 | 124 | ( 125 | is_square & (num_is_zero | !div_is_zero), 126 | CtOption::conditional_select(&sqrt_b, &sqrt_a, is_square).unwrap(), 127 | ) 128 | } 129 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate provides traits for working with finite fields. 2 | 3 | #![no_std] 4 | #![cfg_attr(docsrs, feature(doc_cfg))] 5 | // Catch documentation errors caused by code changes. 6 | #![deny(rustdoc::broken_intra_doc_links)] 7 | #![forbid(unsafe_code)] 8 | 9 | #[cfg(feature = "alloc")] 10 | extern crate alloc; 11 | 12 | mod batch; 13 | pub use batch::*; 14 | 15 | pub mod helpers; 16 | 17 | #[cfg(feature = "derive")] 18 | #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] 19 | pub use ff_derive::PrimeField; 20 | 21 | #[cfg(feature = "bits")] 22 | #[cfg_attr(docsrs, doc(cfg(feature = "bits")))] 23 | pub use bitvec::view::BitViewSized; 24 | 25 | #[cfg(feature = "bits")] 26 | use bitvec::{array::BitArray, order::Lsb0}; 27 | 28 | use core::fmt; 29 | use core::iter::{Product, Sum}; 30 | use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; 31 | 32 | use rand_core::RngCore; 33 | use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; 34 | 35 | /// Bit representation of a field element. 36 | #[cfg(feature = "bits")] 37 | #[cfg_attr(docsrs, doc(cfg(feature = "bits")))] 38 | pub type FieldBits = BitArray; 39 | 40 | /// This trait represents an element of a field. 41 | pub trait Field: 42 | Sized 43 | + Eq 44 | + Copy 45 | + Clone 46 | + Default 47 | + Send 48 | + Sync 49 | + fmt::Debug 50 | + 'static 51 | + ConditionallySelectable 52 | + ConstantTimeEq 53 | + Neg 54 | + Add 55 | + Sub 56 | + Mul 57 | + Sum 58 | + Product 59 | + for<'a> Add<&'a Self, Output = Self> 60 | + for<'a> Sub<&'a Self, Output = Self> 61 | + for<'a> Mul<&'a Self, Output = Self> 62 | + for<'a> Sum<&'a Self> 63 | + for<'a> Product<&'a Self> 64 | + AddAssign 65 | + SubAssign 66 | + MulAssign 67 | + for<'a> AddAssign<&'a Self> 68 | + for<'a> SubAssign<&'a Self> 69 | + for<'a> MulAssign<&'a Self> 70 | { 71 | /// The zero element of the field, the additive identity. 72 | const ZERO: Self; 73 | 74 | /// The one element of the field, the multiplicative identity. 75 | const ONE: Self; 76 | 77 | /// Returns an element chosen uniformly at random using a user-provided RNG. 78 | fn random(rng: impl RngCore) -> Self; 79 | 80 | /// Returns true iff this element is zero. 81 | fn is_zero(&self) -> Choice { 82 | self.ct_eq(&Self::ZERO) 83 | } 84 | 85 | /// Returns true iff this element is zero. 86 | /// 87 | /// # Security 88 | /// 89 | /// This method provides **no** constant-time guarantees. Implementors of the 90 | /// `Field` trait **may** optimise this method using non-constant-time logic. 91 | fn is_zero_vartime(&self) -> bool { 92 | self.is_zero().into() 93 | } 94 | 95 | /// Squares this element. 96 | #[must_use] 97 | fn square(&self) -> Self; 98 | 99 | /// Cubes this element. 100 | #[must_use] 101 | fn cube(&self) -> Self { 102 | self.square() * self 103 | } 104 | 105 | /// Doubles this element. 106 | #[must_use] 107 | fn double(&self) -> Self; 108 | 109 | /// Computes the multiplicative inverse of this element, 110 | /// failing if the element is zero. 111 | fn invert(&self) -> CtOption; 112 | 113 | /// Computes: 114 | /// 115 | /// - $(\textsf{true}, \sqrt{\textsf{num}/\textsf{div}})$, if $\textsf{num}$ and 116 | /// $\textsf{div}$ are nonzero and $\textsf{num}/\textsf{div}$ is a square in the 117 | /// field; 118 | /// - $(\textsf{true}, 0)$, if $\textsf{num}$ is zero; 119 | /// - $(\textsf{false}, 0)$, if $\textsf{num}$ is nonzero and $\textsf{div}$ is zero; 120 | /// - $(\textsf{false}, \sqrt{G_S \cdot \textsf{num}/\textsf{div}})$, if 121 | /// $\textsf{num}$ and $\textsf{div}$ are nonzero and $\textsf{num}/\textsf{div}$ is 122 | /// a nonsquare in the field; 123 | /// 124 | /// where $G_S$ is a non-square. 125 | /// 126 | /// # Warnings 127 | /// 128 | /// - The choice of root from `sqrt` is unspecified. 129 | /// - The value of $G_S$ is unspecified, and cannot be assumed to have any specific 130 | /// value in a generic context. 131 | fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self); 132 | 133 | /// Equivalent to `Self::sqrt_ratio(self, one())`. 134 | /// 135 | /// The provided method is implemented in terms of [`Self::sqrt_ratio`]. 136 | fn sqrt_alt(&self) -> (Choice, Self) { 137 | Self::sqrt_ratio(self, &Self::ONE) 138 | } 139 | 140 | /// Returns the square root of the field element, if it is 141 | /// quadratic residue. 142 | /// 143 | /// The provided method is implemented in terms of [`Self::sqrt_ratio`]. 144 | fn sqrt(&self) -> CtOption { 145 | let (is_square, res) = Self::sqrt_ratio(self, &Self::ONE); 146 | CtOption::new(res, is_square) 147 | } 148 | 149 | /// Exponentiates `self` by `exp`, where `exp` is a little-endian order integer 150 | /// exponent. 151 | /// 152 | /// # Guarantees 153 | /// 154 | /// This operation is constant time with respect to `self`, for all exponents with the 155 | /// same number of digits (`exp.as_ref().len()`). It is variable time with respect to 156 | /// the number of digits in the exponent. 157 | fn pow>(&self, exp: S) -> Self { 158 | let mut res = Self::ONE; 159 | for e in exp.as_ref().iter().rev() { 160 | for i in (0..64).rev() { 161 | res = res.square(); 162 | let mut tmp = res; 163 | tmp *= self; 164 | res.conditional_assign(&tmp, (((*e >> i) & 1) as u8).into()); 165 | } 166 | } 167 | res 168 | } 169 | 170 | /// Exponentiates `self` by `exp`, where `exp` is a little-endian order integer 171 | /// exponent. 172 | /// 173 | /// # Guarantees 174 | /// 175 | /// **This operation is variable time with respect to `self`, for all exponent.** If 176 | /// the exponent is fixed, this operation is effectively constant time. However, for 177 | /// stronger constant-time guarantees, [`Field::pow`] should be used. 178 | fn pow_vartime>(&self, exp: S) -> Self { 179 | let mut res = Self::ONE; 180 | for e in exp.as_ref().iter().rev() { 181 | for i in (0..64).rev() { 182 | res = res.square(); 183 | 184 | if ((*e >> i) & 1) == 1 { 185 | res.mul_assign(self); 186 | } 187 | } 188 | } 189 | 190 | res 191 | } 192 | } 193 | 194 | /// This represents an element of a non-binary prime field. 195 | pub trait PrimeField: Field + From { 196 | /// The prime field can be converted back and forth into this binary 197 | /// representation. 198 | type Repr: Copy + Default + Send + Sync + 'static + AsRef<[u8]> + AsMut<[u8]>; 199 | 200 | /// Interpret a string of numbers as a (congruent) prime field element. 201 | /// Does not accept unnecessary leading zeroes or a blank string. 202 | /// 203 | /// # Security 204 | /// 205 | /// This method provides **no** constant-time guarantees. 206 | fn from_str_vartime(s: &str) -> Option { 207 | if s.is_empty() { 208 | return None; 209 | } 210 | 211 | if s == "0" { 212 | return Some(Self::ZERO); 213 | } 214 | 215 | let mut res = Self::ZERO; 216 | 217 | let ten = Self::from(10); 218 | 219 | let mut first_digit = true; 220 | 221 | for c in s.chars() { 222 | match c.to_digit(10) { 223 | Some(c) => { 224 | if first_digit { 225 | if c == 0 { 226 | return None; 227 | } 228 | 229 | first_digit = false; 230 | } 231 | 232 | res.mul_assign(&ten); 233 | res.add_assign(&Self::from(u64::from(c))); 234 | } 235 | None => { 236 | return None; 237 | } 238 | } 239 | } 240 | 241 | Some(res) 242 | } 243 | 244 | /// Obtains a field element congruent to the integer `v`. 245 | /// 246 | /// For fields where `Self::CAPACITY >= 128`, this is injective and will produce a 247 | /// unique field element. 248 | /// 249 | /// For fields where `Self::CAPACITY < 128`, this is surjective; some field elements 250 | /// will be produced by multiple values of `v`. 251 | /// 252 | /// If you want to deterministically sample a field element representing a value, use 253 | /// [`FromUniformBytes`] instead. 254 | fn from_u128(v: u128) -> Self { 255 | let lower = v as u64; 256 | let upper = (v >> 64) as u64; 257 | let mut tmp = Self::from(upper); 258 | for _ in 0..64 { 259 | tmp = tmp.double(); 260 | } 261 | tmp + Self::from(lower) 262 | } 263 | 264 | /// Attempts to convert a byte representation of a field element into an element of 265 | /// this prime field, failing if the input is not canonical (is not smaller than the 266 | /// field's modulus). 267 | /// 268 | /// The byte representation is interpreted with the same endianness as elements 269 | /// returned by [`PrimeField::to_repr`]. 270 | fn from_repr(repr: Self::Repr) -> CtOption; 271 | 272 | /// Attempts to convert a byte representation of a field element into an element of 273 | /// this prime field, failing if the input is not canonical (is not smaller than the 274 | /// field's modulus). 275 | /// 276 | /// The byte representation is interpreted with the same endianness as elements 277 | /// returned by [`PrimeField::to_repr`]. 278 | /// 279 | /// # Security 280 | /// 281 | /// This method provides **no** constant-time guarantees. Implementors of the 282 | /// `PrimeField` trait **may** optimise this method using non-constant-time logic. 283 | fn from_repr_vartime(repr: Self::Repr) -> Option { 284 | Self::from_repr(repr).into() 285 | } 286 | 287 | /// Converts an element of the prime field into the standard byte representation for 288 | /// this field. 289 | /// 290 | /// The endianness of the byte representation is implementation-specific. Generic 291 | /// encodings of field elements should be treated as opaque. 292 | fn to_repr(&self) -> Self::Repr; 293 | 294 | /// Returns true iff this element is odd. 295 | fn is_odd(&self) -> Choice; 296 | 297 | /// Returns true iff this element is even. 298 | #[inline(always)] 299 | fn is_even(&self) -> Choice { 300 | !self.is_odd() 301 | } 302 | 303 | /// Modulus of the field written as a string for debugging purposes. 304 | /// 305 | /// The encoding of the modulus is implementation-specific. Generic users of the 306 | /// `PrimeField` trait should treat this string as opaque. 307 | const MODULUS: &'static str; 308 | 309 | /// How many bits are needed to represent an element of this field. 310 | const NUM_BITS: u32; 311 | 312 | /// How many bits of information can be reliably stored in the field element. 313 | /// 314 | /// This is usually `Self::NUM_BITS - 1`. 315 | const CAPACITY: u32; 316 | 317 | /// Inverse of $2$ in the field. 318 | const TWO_INV: Self; 319 | 320 | /// A fixed multiplicative generator of `modulus - 1` order. This element must also be 321 | /// a quadratic nonresidue. 322 | /// 323 | /// It can be calculated using [SageMath] as `GF(modulus).primitive_element()`. 324 | /// 325 | /// Implementations of this trait MUST ensure that this is the generator used to 326 | /// derive `Self::ROOT_OF_UNITY`. 327 | /// 328 | /// [SageMath]: https://www.sagemath.org/ 329 | const MULTIPLICATIVE_GENERATOR: Self; 330 | 331 | /// An integer `s` satisfying the equation `2^s * t = modulus - 1` with `t` odd. 332 | /// 333 | /// This is the number of leading zero bits in the little-endian bit representation of 334 | /// `modulus - 1`. 335 | const S: u32; 336 | 337 | /// The `2^s` root of unity. 338 | /// 339 | /// It can be calculated by exponentiating `Self::MULTIPLICATIVE_GENERATOR` by `t`, 340 | /// where `t = (modulus - 1) >> Self::S`. 341 | const ROOT_OF_UNITY: Self; 342 | 343 | /// Inverse of [`Self::ROOT_OF_UNITY`]. 344 | const ROOT_OF_UNITY_INV: Self; 345 | 346 | /// Generator of the `t-order` multiplicative subgroup. 347 | /// 348 | /// It can be calculated by exponentiating [`Self::MULTIPLICATIVE_GENERATOR`] by `2^s`, 349 | /// where `s` is [`Self::S`]. 350 | const DELTA: Self; 351 | } 352 | 353 | /// The subset of prime-order fields such that `(modulus - 1)` is divisible by `N`. 354 | /// 355 | /// If `N` is prime, there will be `N - 1` valid choices of [`Self::ZETA`]. Similarly to 356 | /// [`PrimeField::MULTIPLICATIVE_GENERATOR`], the specific choice does not matter, as long 357 | /// as the choice is consistent across all uses of the field. 358 | pub trait WithSmallOrderMulGroup: PrimeField { 359 | /// A field element of small multiplicative order $N$. 360 | /// 361 | /// The presence of this element allows you to perform (certain types of) 362 | /// endomorphisms on some elliptic curves. 363 | /// 364 | /// It can be calculated using [SageMath] as 365 | /// `GF(modulus).primitive_element() ^ ((modulus - 1) // N)`. 366 | /// Choosing the element of order $N$ that is smallest, when considered 367 | /// as an integer, may help to ensure consistency. 368 | /// 369 | /// [SageMath]: https://www.sagemath.org/ 370 | const ZETA: Self; 371 | } 372 | 373 | /// Trait for constructing a [`PrimeField`] element from a fixed-length uniform byte 374 | /// array. 375 | /// 376 | /// "Uniform" means that the byte array's contents must be indistinguishable from the 377 | /// [discrete uniform distribution]. Suitable byte arrays can be obtained: 378 | /// - from a cryptographically-secure randomness source (which makes this constructor 379 | /// equivalent to [`Field::random`]). 380 | /// - from a cryptographic hash function output, which enables a "random" field element to 381 | /// be selected deterministically. This is the primary use case for `FromUniformBytes`. 382 | /// 383 | /// The length `N` of the byte array is chosen by the trait implementer such that the loss 384 | /// of uniformity in the mapping from byte arrays to field elements is cryptographically 385 | /// negligible. 386 | /// 387 | /// [discrete uniform distribution]: https://en.wikipedia.org/wiki/Discrete_uniform_distribution 388 | /// 389 | /// # Examples 390 | /// 391 | /// ``` 392 | /// # #[cfg(feature = "derive")] { 393 | /// # // Fake this so we don't actually need a dev-dependency on bls12_381. 394 | /// # mod bls12_381 { 395 | /// # use ff::{Field, PrimeField}; 396 | /// # 397 | /// # #[derive(PrimeField)] 398 | /// # #[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"] 399 | /// # #[PrimeFieldGenerator = "7"] 400 | /// # #[PrimeFieldReprEndianness = "little"] 401 | /// # pub struct Scalar([u64; 4]); 402 | /// # 403 | /// # impl ff::FromUniformBytes<64> for Scalar { 404 | /// # fn from_uniform_bytes(_bytes: &[u8; 64]) -> Self { 405 | /// # // Fake impl for doctest 406 | /// # Scalar::ONE 407 | /// # } 408 | /// # } 409 | /// # } 410 | /// # 411 | /// use blake2b_simd::blake2b; 412 | /// use bls12_381::Scalar; 413 | /// use ff::FromUniformBytes; 414 | /// 415 | /// // `bls12_381::Scalar` implements `FromUniformBytes<64>`, and BLAKE2b (by default) 416 | /// // produces a 64-byte hash. 417 | /// let hash = blake2b(b"Some message"); 418 | /// let val = Scalar::from_uniform_bytes(hash.as_array()); 419 | /// # } 420 | /// ``` 421 | /// 422 | /// # Implementing `FromUniformBytes` 423 | /// 424 | /// [`Self::from_uniform_bytes`] should always be implemented by interpreting the provided 425 | /// byte array as the little endian unsigned encoding of an integer, and then reducing that 426 | /// integer modulo the field modulus. 427 | /// 428 | /// For security, `N` must be chosen so that `N * 8 >= Self::NUM_BITS + 128`. A larger 429 | /// value of `N` may be chosen for convenience; for example, for a field with a 255-bit 430 | /// modulus, `N = 64` is convenient as it matches the output length of several common 431 | /// cryptographic hash functions (such as SHA-512 and BLAKE2b). 432 | /// 433 | /// ## Trait design 434 | /// 435 | /// This trait exists because `PrimeField::from_uniform_bytes([u8; N])` cannot currently 436 | /// exist (trait methods cannot use associated constants in the const positions of their 437 | /// type signature, and we do not want `PrimeField` to require a generic const parameter). 438 | /// However, this has the side-effect that `FromUniformBytes` can be implemented multiple 439 | /// times for different values of `N`. Most implementations of [`PrimeField`] should only 440 | /// need to implement `FromUniformBytes` trait for one value of `N` (chosen following the 441 | /// above considerations); if you find yourself needing to implement it multiple times, 442 | /// please [let us know about your use case](https://github.com/zkcrypto/ff/issues/new) so 443 | /// we can take it into consideration for future evolutions of the `ff` traits. 444 | pub trait FromUniformBytes: PrimeField { 445 | /// Returns a field element that is congruent to the provided little endian unsigned 446 | /// byte representation of an integer. 447 | fn from_uniform_bytes(bytes: &[u8; N]) -> Self; 448 | } 449 | 450 | /// This represents the bits of an element of a prime field. 451 | #[cfg(feature = "bits")] 452 | #[cfg_attr(docsrs, doc(cfg(feature = "bits")))] 453 | pub trait PrimeFieldBits: PrimeField { 454 | /// The backing store for a bit representation of a prime field element. 455 | type ReprBits: BitViewSized + Send + Sync; 456 | 457 | /// Converts an element of the prime field into a little-endian sequence of bits. 458 | fn to_le_bits(&self) -> FieldBits; 459 | 460 | /// Returns the bits of the field characteristic (the modulus) in little-endian order. 461 | fn char_le_bits() -> FieldBits; 462 | } 463 | 464 | /// Functions and re-exported crates used by the [`PrimeField`] derive macro. 465 | #[cfg(feature = "derive")] 466 | #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] 467 | pub mod derive { 468 | pub use crate::arith_impl::*; 469 | 470 | pub use {byteorder, rand_core, subtle}; 471 | 472 | #[cfg(feature = "bits")] 473 | pub use bitvec; 474 | } 475 | 476 | #[cfg(feature = "derive")] 477 | mod arith_impl { 478 | /// Computes `a - (b + borrow)`, returning the result and the new borrow. 479 | #[inline(always)] 480 | pub const fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { 481 | let ret = (a as u128).wrapping_sub((b as u128) + ((borrow >> 63) as u128)); 482 | (ret as u64, (ret >> 64) as u64) 483 | } 484 | 485 | /// Computes `a + b + carry`, returning the result and the new carry over. 486 | #[inline(always)] 487 | pub const fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { 488 | let ret = (a as u128) + (b as u128) + (carry as u128); 489 | (ret as u64, (ret >> 64) as u64) 490 | } 491 | 492 | /// Computes `a + (b * c) + carry`, returning the result and the new carry over. 493 | #[inline(always)] 494 | pub const fn mac(a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { 495 | let ret = (a as u128) + ((b as u128) * (c as u128)) + (carry as u128); 496 | (ret as u64, (ret >> 64) as u64) 497 | } 498 | } 499 | -------------------------------------------------------------------------------- /tests/derive.rs: -------------------------------------------------------------------------------- 1 | //! This module exercises the `ff_derive` procedural macros, to ensure that changes to the 2 | //! `ff` crate are reflected in `ff_derive`. It also uses the resulting field to test some 3 | //! of the APIs provided by `ff`, such as batch inversion. 4 | 5 | #[macro_use] 6 | extern crate ff; 7 | 8 | /// The BLS12-381 scalar field. 9 | #[derive(PrimeField)] 10 | #[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"] 11 | #[PrimeFieldGenerator = "7"] 12 | #[PrimeFieldReprEndianness = "little"] 13 | struct Bls381K12Scalar([u64; 4]); 14 | 15 | mod fermat { 16 | /// The largest known Fermat prime, used to test the case `t = 1`. 17 | #[derive(PrimeField)] 18 | #[PrimeFieldModulus = "65537"] 19 | #[PrimeFieldGenerator = "3"] 20 | #[PrimeFieldReprEndianness = "little"] 21 | struct Fermat65537Field([u64; 1]); 22 | } 23 | 24 | mod full_limbs { 25 | #[derive(PrimeField)] 26 | #[PrimeFieldModulus = "39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319"] 27 | #[PrimeFieldGenerator = "19"] 28 | #[PrimeFieldReprEndianness = "little"] 29 | struct F384p([u64; 7]); 30 | 31 | #[test] 32 | fn random_masking_does_not_overflow() { 33 | use ff::Field; 34 | use rand::rngs::OsRng; 35 | 36 | let _ = F384p::random(OsRng); 37 | } 38 | } 39 | 40 | #[test] 41 | fn constants() { 42 | use ff::{Field, PrimeField}; 43 | 44 | assert_eq!( 45 | Bls381K12Scalar::MODULUS, 46 | "0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 47 | ); 48 | 49 | assert_eq!( 50 | Bls381K12Scalar::from(2) * Bls381K12Scalar::TWO_INV, 51 | Bls381K12Scalar::ONE, 52 | ); 53 | 54 | assert_eq!( 55 | Bls381K12Scalar::ROOT_OF_UNITY * Bls381K12Scalar::ROOT_OF_UNITY_INV, 56 | Bls381K12Scalar::ONE, 57 | ); 58 | 59 | // ROOT_OF_UNITY^{2^s} mod m == 1 60 | assert_eq!( 61 | Bls381K12Scalar::ROOT_OF_UNITY.pow(&[1u64 << Bls381K12Scalar::S, 0, 0, 0]), 62 | Bls381K12Scalar::ONE, 63 | ); 64 | 65 | // DELTA^{t} mod m == 1 66 | assert_eq!( 67 | Bls381K12Scalar::DELTA.pow(&[ 68 | 0xfffe5bfeffffffff, 69 | 0x09a1d80553bda402, 70 | 0x299d7d483339d808, 71 | 0x73eda753, 72 | ]), 73 | Bls381K12Scalar::ONE, 74 | ); 75 | } 76 | 77 | #[test] 78 | fn from_u128() { 79 | use ff::{Field, PrimeField}; 80 | 81 | assert_eq!(Bls381K12Scalar::from_u128(1), Bls381K12Scalar::ONE); 82 | assert_eq!(Bls381K12Scalar::from_u128(2), Bls381K12Scalar::from(2)); 83 | assert_eq!( 84 | Bls381K12Scalar::from_u128(u128::MAX), 85 | Bls381K12Scalar::from_str_vartime("340282366920938463463374607431768211455").unwrap(), 86 | ); 87 | } 88 | 89 | #[test] 90 | fn batch_inversion() { 91 | use ff::{BatchInverter, Field}; 92 | 93 | let one = Bls381K12Scalar::ONE; 94 | 95 | // [1, 2, 3, 4] 96 | let values: Vec<_> = (0..4) 97 | .scan(one, |acc, _| { 98 | let ret = *acc; 99 | *acc += &one; 100 | Some(ret) 101 | }) 102 | .collect(); 103 | 104 | // Test BatchInverter::invert_with_external_scratch 105 | { 106 | let mut elements = values.clone(); 107 | let mut scratch_space = vec![Bls381K12Scalar::ZERO; elements.len()]; 108 | BatchInverter::invert_with_external_scratch(&mut elements, &mut scratch_space); 109 | for (a, a_inv) in values.iter().zip(elements.into_iter()) { 110 | assert_eq!(*a * a_inv, one); 111 | } 112 | } 113 | 114 | // Test BatchInverter::invert_with_internal_scratch 115 | { 116 | let mut items: Vec<_> = values.iter().cloned().map(|p| (p, one)).collect(); 117 | BatchInverter::invert_with_internal_scratch( 118 | &mut items, 119 | |item| &mut item.0, 120 | |item| &mut item.1, 121 | ); 122 | for (a, (a_inv, _)) in values.iter().zip(items.into_iter()) { 123 | assert_eq!(*a * a_inv, one); 124 | } 125 | } 126 | 127 | // Test BatchInvert trait 128 | #[cfg(feature = "alloc")] 129 | { 130 | use ff::BatchInvert; 131 | let mut elements = values.clone(); 132 | elements.iter_mut().batch_invert(); 133 | for (a, a_inv) in values.iter().zip(elements.into_iter()) { 134 | assert_eq!(*a * a_inv, one); 135 | } 136 | } 137 | } 138 | 139 | #[test] 140 | fn sqrt() { 141 | use ff::{Field, PrimeField}; 142 | // A field modulo a prime such that p = 1 mod 4 and p != 1 mod 16 143 | #[derive(PrimeField)] 144 | #[PrimeFieldModulus = "357686312646216567629137"] 145 | #[PrimeFieldGenerator = "5"] 146 | #[PrimeFieldReprEndianness = "little"] 147 | struct Fp([u64; 2]); 148 | fn test(square_root: Fp) { 149 | let square = square_root.square(); 150 | let square_root = square.sqrt().unwrap(); 151 | assert_eq!(square_root.square(), square); 152 | } 153 | 154 | test(Fp::ZERO); 155 | test(Fp::ONE); 156 | use rand::rngs::OsRng; 157 | test(Fp::random(OsRng)); 158 | } 159 | --------------------------------------------------------------------------------