Browse Source

Initial commit

initialize
Pratyush Mishra 4 years ago
commit
43ca2132fd
209 changed files with 18825 additions and 0 deletions
  1. +128
    -0
      .github/workflows/ci.yml
  2. +11
    -0
      .gitignore
  3. +458
    -0
      Cargo.lock
  4. +52
    -0
      Cargo.toml
  5. +201
    -0
      LICENSE-APACHE
  6. +19
    -0
      LICENSE-MIT
  7. +31
    -0
      README.md
  8. +32
    -0
      bls12_377/Cargo.toml
  9. +1
    -0
      bls12_377/LICENSE-APACHE
  10. +1
    -0
      bls12_377/LICENSE-MIT
  11. +77
    -0
      bls12_377/src/curves/g1.rs
  12. +129
    -0
      bls12_377/src/curves/g2.rs
  13. +33
    -0
      bls12_377/src/curves/mod.rs
  14. +121
    -0
      bls12_377/src/curves/tests.rs
  15. +114
    -0
      bls12_377/src/fields/fq.rs
  16. +161
    -0
      bls12_377/src/fields/fq12.rs
  17. +69
    -0
      bls12_377/src/fields/fq2.rs
  18. +184
    -0
      bls12_377/src/fields/fq6.rs
  19. +95
    -0
      bls12_377/src/fields/fr.rs
  20. +27
    -0
      bls12_377/src/fields/mod.rs
  21. +530
    -0
      bls12_377/src/fields/tests.rs
  22. +35
    -0
      bls12_377/src/lib.rs
  23. +31
    -0
      bls12_381/Cargo.toml
  24. +1
    -0
      bls12_381/LICENSE-APACHE
  25. +1
    -0
      bls12_381/LICENSE-MIT
  26. +82
    -0
      bls12_381/src/curves/g1.rs
  27. +113
    -0
      bls12_381/src/curves/g2.rs
  28. +30
    -0
      bls12_381/src/curves/mod.rs
  29. +116
    -0
      bls12_381/src/curves/tests.rs
  30. +112
    -0
      bls12_381/src/fields/fq.rs
  31. +193
    -0
      bls12_381/src/fields/fq12.rs
  32. +73
    -0
      bls12_381/src/fields/fq2.rs
  33. +194
    -0
      bls12_381/src/fields/fq6.rs
  34. +96
    -0
      bls12_381/src/fields/fr.rs
  35. +27
    -0
      bls12_381/src/fields/mod.rs
  36. +2322
    -0
      bls12_381/src/fields/tests.rs
  37. +32
    -0
      bls12_381/src/lib.rs
  38. +31
    -0
      bn254/Cargo.toml
  39. +1
    -0
      bn254/LICENSE-APACHE
  40. +1
    -0
      bn254/LICENSE-MIT
  41. +67
    -0
      bn254/src/curves/g1.rs
  42. +112
    -0
      bn254/src/curves/g2.rs
  43. +82
    -0
      bn254/src/curves/mod.rs
  44. +85
    -0
      bn254/src/curves/tests.rs
  45. +96
    -0
      bn254/src/fields/fq.rs
  46. +159
    -0
      bn254/src/fields/fq12.rs
  47. +63
    -0
      bn254/src/fields/fq2.rs
  48. +195
    -0
      bn254/src/fields/fq6.rs
  49. +95
    -0
      bn254/src/fields/fr.rs
  50. +27
    -0
      bn254/src/fields/mod.rs
  51. +504
    -0
      bn254/src/fields/tests.rs
  52. +40
    -0
      bn254/src/lib.rs
  53. +29
    -0
      bw6_761/Cargo.toml
  54. +113
    -0
      bw6_761/src/curves/g1.rs
  55. +113
    -0
      bw6_761/src/curves/g2.rs
  56. +61
    -0
      bw6_761/src/curves/mod.rs
  57. +77
    -0
      bw6_761/src/curves/tests.rs
  58. +175
    -0
      bw6_761/src/fields/fq.rs
  59. +200
    -0
      bw6_761/src/fields/fq3.rs
  60. +106
    -0
      bw6_761/src/fields/fq6.rs
  61. +1
    -0
      bw6_761/src/fields/fr.rs
  62. +14
    -0
      bw6_761/src/fields/mod.rs
  63. +51
    -0
      bw6_761/src/fields/tests.rs
  64. +34
    -0
      bw6_761/src/lib.rs
  65. +29
    -0
      cp6_782/Cargo.toml
  66. +126
    -0
      cp6_782/src/curves/g1.rs
  67. +241
    -0
      cp6_782/src/curves/g2.rs
  68. +223
    -0
      cp6_782/src/curves/mod.rs
  69. +77
    -0
      cp6_782/src/curves/tests.rs
  70. +166
    -0
      cp6_782/src/fields/fq.rs
  71. +204
    -0
      cp6_782/src/fields/fq3.rs
  72. +112
    -0
      cp6_782/src/fields/fq6.rs
  73. +1
    -0
      cp6_782/src/fields/fr.rs
  74. +14
    -0
      cp6_782/src/fields/mod.rs
  75. +51
    -0
      cp6_782/src/fields/tests.rs
  76. +33
    -0
      cp6_782/src/lib.rs
  77. +50
    -0
      curve-benches/Cargo.toml
  78. +1
    -0
      curve-benches/LICENSE-APACHE
  79. +1
    -0
      curve-benches/LICENSE-MIT
  80. +9
    -0
      curve-benches/build.rs
  81. +23
    -0
      curve-benches/src/curves/bls12_377.rs
  82. +23
    -0
      curve-benches/src/curves/bls12_381.rs
  83. +23
    -0
      curve-benches/src/curves/bn254.rs
  84. +23
    -0
      curve-benches/src/curves/bw6_761.rs
  85. +20
    -0
      curve-benches/src/curves/cp6_782.rs
  86. +22
    -0
      curve-benches/src/curves/mnt4_298.rs
  87. +22
    -0
      curve-benches/src/curves/mnt4_753.rs
  88. +22
    -0
      curve-benches/src/curves/mnt6_298.rs
  89. +22
    -0
      curve-benches/src/curves/mnt6_753.rs
  90. +18
    -0
      curve-benches/src/curves/mod.rs
  91. +12
    -0
      curve-benches/src/lib.rs
  92. +357
    -0
      curve-benches/src/macros/ec.rs
  93. +405
    -0
      curve-benches/src/macros/field.rs
  94. +11
    -0
      curve-benches/src/macros/mod.rs
  95. +61
    -0
      curve-benches/src/macros/pairing.rs
  96. +49
    -0
      curve-benches/src/macros/utils.rs
  97. +33
    -0
      curve-tests/Cargo.toml
  98. +1
    -0
      curve-tests/LICENSE-APACHE
  99. +1
    -0
      curve-tests/LICENSE-MIT
  100. +531
    -0
      curve-tests/src/curves.rs

+ 128
- 0
.github/workflows/ci.yml

@ -0,0 +1,128 @@
name: CI
on:
pull_request:
push:
branches:
- master
env:
RUST_BACKTRACE: 1
jobs:
style:
name: Check Style
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
components: rustfmt
- name: cargo fmt --check
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
test:
name: Test
runs-on: ubuntu-latest
env:
RUSTFLAGS: -Dwarnings
strategy:
matrix:
rust:
- stable
- nightly
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Rust (${{ matrix.rust }})
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.rust }}
override: true
- uses: actions/cache@v2
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Check examples
uses: actions-rs/cargo@v1
with:
command: check
args: --examples --all
- name: Check examples with all features on stable
uses: actions-rs/cargo@v1
with:
command: check
args: --examples --all-features --all
if: matrix.rust == 'stable'
- name: Check benchmarks on nightly
uses: actions-rs/cargo@v1
with:
command: check
args: --all-features --examples --workspace --benches
if: matrix.rust == 'nightly'
- name: Test
uses: actions-rs/cargo@v1
with:
command: test
args: "--workspace \
--all-features \
--exclude curve-benches"
check_no_std:
name: Check no_std
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Rust (${{ matrix.rust }})
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: thumbv6m-none-eabi
override: true
- name: Install Rust ARM64 (${{ matrix.rust }})
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: aarch64-unknown-none
override: true
- uses: actions/cache@v2
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: check
uses: actions-rs/cargo@v1
with:
command: check
args: --examples --workspace --exclude ark-curve-tests --exclude ark-curve-benches --target thumbv6m-none-eabi
- name: build
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --exclude ark-curve-tests --exclude ark-curve-benches --target thumbv6m-none-eabi

+ 11
- 0
.gitignore

@ -0,0 +1,11 @@
target
Cargo.lock
.DS_Store
.idea
*.iml
*.ipynb_checkpoints
*.pyc
*.sage.py
params
*.swp
*.swo

+ 458
- 0
Cargo.lock

@ -0,0 +1,458 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "ark-bls12-377"
version = "0.1.0"
dependencies = [
"ark-curve-tests",
"ark-ec",
"ark-ff",
"ark-serialize",
"ark-std",
"rand",
"rand_xorshift",
]
[[package]]
name = "ark-bls12-381"
version = "0.1.0"
dependencies = [
"ark-curve-tests",
"ark-ec",
"ark-ff",
"ark-serialize",
"ark-std",
"rand",
"rand_xorshift",
]
[[package]]
name = "ark-bn254"
version = "0.1.0"
dependencies = [
"ark-curve-tests",
"ark-ec",
"ark-ff",
"ark-serialize",
"ark-std",
"rand",
"rand_xorshift",
]
[[package]]
name = "ark-bw6-761"
version = "0.1.0"
dependencies = [
"ark-bls12-377",
"ark-curve-tests",
"ark-ec",
"ark-ff",
"ark-serialize",
"ark-std",
"rand",
"rand_xorshift",
]
[[package]]
name = "ark-cp6-782"
version = "0.1.0"
dependencies = [
"ark-bls12-377",
"ark-curve-tests",
"ark-ec",
"ark-ff",
"ark-serialize",
"ark-std",
"rand",
"rand_xorshift",
]
[[package]]
name = "ark-curve-benches"
version = "0.1.1-alpha.0"
dependencies = [
"ark-bls12-377",
"ark-bls12-381",
"ark-bn254",
"ark-bw6-761",
"ark-cp6-782",
"ark-ec",
"ark-ff",
"ark-mnt4-298",
"ark-mnt4-753",
"ark-mnt6-298",
"ark-mnt6-753",
"ark-serialize",
"paste",
"rand",
"rand_xorshift",
"rustc_version",
]
[[package]]
name = "ark-curve-tests"
version = "0.1.0"
dependencies = [
"ark-ec",
"ark-ff",
"ark-serialize",
"ark-std",
"rand",
"rand_xorshift",
]
[[package]]
name = "ark-ec"
version = "0.1.0"
source = "git+https://github.com/arkworks-rs/algebra#d5202f896ca9700c5c22d7a1266ada600f913dc4"
dependencies = [
"ark-ff",
"ark-serialize",
"ark-std",
"derivative",
"num-traits",
"rand",
]
[[package]]
name = "ark-ed-on-bls12-377"
version = "0.1.0"
dependencies = [
"ark-bls12-377",
"ark-curve-tests",
"ark-ec",
"ark-ff",
"ark-serialize",
"ark-std",
"rand",
"rand_xorshift",
]
[[package]]
name = "ark-ed-on-bls12-381"
version = "0.1.0"
dependencies = [
"ark-bls12-381",
"ark-curve-tests",
"ark-ec",
"ark-ff",
"ark-serialize",
"ark-std",
"rand",
"rand_xorshift",
]
[[package]]
name = "ark-ed-on-bn254"
version = "0.1.0"
dependencies = [
"ark-bn254",
"ark-curve-tests",
"ark-ec",
"ark-ff",
"ark-serialize",
"ark-std",
"rand",
"rand_xorshift",
]
[[package]]
name = "ark-ed-on-bw6-761"
version = "0.1.0"
dependencies = [
"ark-ed-on-cp6-782",
]
[[package]]
name = "ark-ed-on-cp6-782"
version = "0.1.0"
dependencies = [
"ark-bls12-377",
"ark-curve-tests",
"ark-ec",
"ark-ff",
"ark-serialize",
"ark-std",
"rand",
"rand_xorshift",
]
[[package]]
name = "ark-ed-on-mnt4-298"
version = "0.1.0"
dependencies = [
"ark-curve-tests",
"ark-ec",
"ark-ff",
"ark-mnt4-298",
"ark-serialize",
"ark-std",
"rand",
"rand_xorshift",
]
[[package]]
name = "ark-ff"
version = "0.1.0"
source = "git+https://github.com/arkworks-rs/algebra#d5202f896ca9700c5c22d7a1266ada600f913dc4"
dependencies = [
"ark-ff-asm",
"ark-serialize",
"ark-std",
"derivative",
"num-traits",
"rand",
"rustc_version",
]
[[package]]
name = "ark-ff-asm"
version = "0.1.0"
source = "git+https://github.com/arkworks-rs/algebra#d5202f896ca9700c5c22d7a1266ada600f913dc4"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "ark-mnt4-298"
version = "0.1.0"
dependencies = [
"ark-curve-tests",
"ark-ec",
"ark-ff",
"ark-serialize",
"ark-std",
"rand",
"rand_xorshift",
]
[[package]]
name = "ark-mnt4-753"
version = "0.1.0"
dependencies = [
"ark-curve-tests",
"ark-ec",
"ark-ff",
"ark-serialize",
"ark-std",
"rand",
"rand_xorshift",
]
[[package]]
name = "ark-mnt6-298"
version = "0.1.0"
dependencies = [
"ark-curve-tests",
"ark-ec",
"ark-ff",
"ark-mnt4-298",
"ark-serialize",
"ark-std",
"rand",
"rand_xorshift",
]
[[package]]
name = "ark-mnt6-753"
version = "0.1.0"
dependencies = [
"ark-curve-tests",
"ark-ec",
"ark-ff",
"ark-mnt4-753",
"ark-serialize",
"ark-std",
"rand",
"rand_xorshift",
]
[[package]]
name = "ark-serialize"
version = "0.1.0"
source = "git+https://github.com/arkworks-rs/algebra#d5202f896ca9700c5c22d7a1266ada600f913dc4"
dependencies = [
"ark-std",
]
[[package]]
name = "ark-std"
version = "0.1.0"
source = "git+https://github.com/arkworks-rs/utils#7bde3ab01799da8429b8fa9c3f152201415cdfe7"
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "derivative"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "getrandom"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "libc"
version = "0.2.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743"
[[package]]
name = "num-traits"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
dependencies = [
"autocfg",
]
[[package]]
name = "paste"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0520af26d4cf99643dbbe093a61507922b57232d9978d8491fdc8f7b44573c8c"
[[package]]
name = "ppv-lite86"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20"
[[package]]
name = "proc-macro2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [
"getrandom",
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [
"rand_core",
]
[[package]]
name = "rand_xorshift"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8"
dependencies = [
"rand_core",
]
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
]
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "syn"
version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e03e57e4fcbfe7749842d53e24ccb9aa12b7252dbe5e91d2acad31834c8b8fdd"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"

+ 52
- 0
Cargo.toml

@ -0,0 +1,52 @@
[workspace]
members = [
"curve-benches",
"curve-tests",
"bls12_377",
"ed_on_bls12_377",
"bw6_761",
"ed_on_bw6_761",
"cp6_782",
"ed_on_cp6_782",
"bls12_381",
"ed_on_bls12_381",
"bn254",
"ed_on_bn254",
"mnt4_298",
"mnt6_298",
"ed_on_mnt4_298",
"mnt4_753",
"mnt6_753",
"ed_on_mnt4_298",
]
[profile.release]
opt-level = 3
lto = "thin"
incremental = true
[profile.bench]
opt-level = 3
debug = false
rpath = false
lto = "thin"
incremental = true
debug-assertions = false
[profile.dev]
opt-level = 0
[profile.test]
opt-level = 3
lto = "thin"
incremental = true
debug-assertions = true
debug = true

+ 201
- 0
LICENSE-APACHE

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

+ 19
- 0
LICENSE-MIT

@ -0,0 +1,19 @@
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

+ 31
- 0
README.md

@ -0,0 +1,31 @@
# Curve implementations
This directory contains implementations of some popular elliptic curves.
### BLS12-381 and embedded curves
* [`ark-bls12-381`](bls12-381): Implements the BLS12-381 pairing-friendly curve
* [`ark-ed-on-bls12-381`](ed-on-bls12-381): Implements a Twisted Edwards curve atop the scalar field of BLS12-381
### BLS12-377 and related curves
* [`ark-bls12-377`](bls12-377): Implements the BLS12-377 pairing-friendly curve
* [`ark-ed-on-bls12-377`](ed-on-bls12-377): Implements a Twisted Edwards curve atop the scalar field of BLS12-377
* [`ark-bw6-761`](bw6-761): Implements the BW6-761 pairing-friendly curve, which is a curve whose scalar field equals the base field of BLS12-377
* [`ark-ed-on-bw6-761`](ed-on-bw6-761): Implements a Twisted Edwards curve atop the scalar field of BW6-761
* [`ark-cp6-782`](cp6-782): Implements the CP6-782 pairing-friendly curve, which is a curve whose scalar field equals the base field of BLS12-377
* [`ark-ed-on-cp6-782`](ed-on-cp6-782): Implements a Twisted Edwards curve atop the scalar field of CP6-782. This is the same curve as in `ark-ed-on-bw6-761`
### BN254 and related curves
* [`ark-bn254`](bn254): Implements the BN254 pairing-friendly curve
* [`ark-ed-on-bn254`](ed-on-bn254): Implements a Twisted Edwards curve atop the scalar field of BN254
### MNT-298 cycle of curves and related curves
* [`ark-mnt4-298`](mnt4-298): Implements the MNT4-298 pairing-friendly curve. This curve forms a pairing-friendly cycle with MNT6-298
* [`ark-mnt6-298`](mnt6-298): Implements the MNT6-298 pairing-friendly curve. This curve forms a pairing-friendly cycle with MNT4-298
* [`ark-ed-on-mnt4-298`](ed-on-mnt4-298): Implements a Twisted Edwards curve atop the scalar field of MNT4-298
### MNT-753 cycle of curves and related curves
* [`ark-mnt4-753`](mnt4-753): Implements the MNT4-753 pairing-friendly curve. This curve forms a pairing-friendly cycle with MNT6-753
* [`ark-mnt6-753`](mnt6-753): Implements the MNT6-753 pairing-friendly curve. This curve forms a pairing-friendly cycle with MNT4-753
* [`ark-ed-on-mnt4-753`](ed-on-mnt4-753): Implements a Twisted Edwards curve atop the scalar field of MNT4-753

+ 32
- 0
bls12_377/Cargo.toml

@ -0,0 +1,32 @@
[package]
name = "ark-bls12-377"
version = "0.1.0"
authors = [ "arkworks contributors" ]
description = "The BLS12-377 pairing-friendly elliptic curve"
homepage = "https://arworks.rs"
repository = "https://github.com/arkworks/algebra"
documentation = "https://docs.rs/ark-bls12-377/"
keywords = ["cryptography", "finite fields", "elliptic curves" ]
categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0"
edition = "2018"
[dependencies]
ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false }
[dev-dependencies]
ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-curve-tests = { path = "../curve-tests", default-features = false }
rand = { version = "0.7", default-features = false }
rand_xorshift = "0.2"
[features]
default = [ "curve" ]
std = [ "ark-std/std", "ark-ff/std", "ark-ec/std" ]
curve = [ "scalar_field", "base_field" ]
scalar_field = []
base_field = []

+ 1
- 0
bls12_377/LICENSE-APACHE

@ -0,0 +1 @@
../LICENSE-APACHE

+ 1
- 0
bls12_377/LICENSE-MIT

@ -0,0 +1 @@
../LICENSE-MIT

+ 77
- 0
bls12_377/src/curves/g1.rs

@ -0,0 +1,77 @@
use ark_ec::models::{ModelParameters, SWModelParameters};
use ark_ff::{
biginteger::{BigInteger256, BigInteger384},
field_new, Zero,
};
use crate::{Fq, Fr};
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
impl ModelParameters for Parameters {
type BaseField = Fq;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = 0
const COEFF_A: Fq = field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0]));
/// COEFF_B = 1
#[rustfmt::skip]
const COEFF_B: Fq = field_new!(Fq, BigInteger384([
0x2cdffffffffff68,
0x51409f837fffffb1,
0x9f7db3a98a7d3ff2,
0x7b4e97b76e7c6305,
0x4cf495bf803c84e8,
0x8d6661e2fdf49a,
]));
/// COFACTOR = (x - 1)^2 / 3 = 30631250834960419227450344600217059328
const COFACTOR: &'static [u64] = &[0x0, 0x170b5d4430000000];
/// COFACTOR_INV = COFACTOR^{-1} mod r
/// = 5285428838741532253824584287042945485047145357130994810877
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, BigInteger256([
2013239619100046060,
4201184776506987597,
2526766393982337036,
1114629510922847535,
]));
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G1_GENERATOR_X, G1_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
}
}
/// G1_GENERATOR_X =
/// 81937999373150964239938255573465948239988671502647976594219695644855304257327692006745978603320413799295628339695
#[rustfmt::skip]
pub const G1_GENERATOR_X: Fq = field_new!(Fq, BigInteger384([
0x260f33b9772451f4,
0xc54dd773169d5658,
0x5c1551c469a510dd,
0x761662e4425e1698,
0xc97d78cc6f065272,
0xa41206b361fd4d,
]));
/// G1_GENERATOR_Y =
/// 241266749859715473739788878240585681733927191168601896383759122102112907357779751001206799952863815012735208165030
#[rustfmt::skip]
pub const G1_GENERATOR_Y: Fq = field_new!(Fq, BigInteger384([
0x8193961fb8cb81f3,
0x638d4c5f44adb8,
0xfafaf3dad4daf54a,
0xc27849e2d655cd18,
0x2ec3ddb401d52814,
0x7da93326303c71,
]));

+ 129
- 0
bls12_377/src/curves/g2.rs

@ -0,0 +1,129 @@
use ark_ec::models::{ModelParameters, SWModelParameters};
use ark_ff::{
biginteger::{BigInteger256, BigInteger384},
field_new, Zero,
};
use crate::{g1, Fq, Fq2, Fr};
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
impl ModelParameters for Parameters {
type BaseField = Fq2;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = [0, 0]
#[rustfmt::skip]
const COEFF_A: Fq2 = field_new!(Fq2,
g1::Parameters::COEFF_A,
g1::Parameters::COEFF_A,
);
// As per https://eprint.iacr.org/2012/072.pdf,
// this curve has b' = b/i, where b is the COEFF_B of G1, and x^6 -i is
// the irreducible poly used to extend from Fp2 to Fp12.
// In our case, i = u (App A.3, T_6).
/// COEFF_B = [0,
/// 155198655607781456406391640216936120121836107652948796323930557600032281009004493664981332883744016074664192874906]
#[rustfmt::skip]
const COEFF_B: Fq2 = field_new!(Fq2,
field_new!(Fq, BigInteger384([0, 0, 0, 0, 0, 0])),
field_new!(Fq, BigInteger384([
9255502405446297221,
10229180150694123945,
9215585410771530959,
13357015519562362907,
5437107869987383107,
16259554076827459,
])),
);
/// COFACTOR =
/// 7923214915284317143930293550643874566881017850177945424769256759165301436616933228209277966774092486467289478618404761412630691835764674559376407658497
#[rustfmt::skip]
const COFACTOR: &'static [u64] = &[
0x0000000000000001,
0x452217cc90000000,
0xa0f3622fba094800,
0xd693e8c36676bd09,
0x8c505634fae2e189,
0xfbb36b00e1dcc40c,
0xddd88d99a6f6a829,
0x26ba558ae9562a,
];
/// COFACTOR_INV = COFACTOR^{-1} mod r
/// = 6764900296503390671038341982857278410319949526107311149686707033187604810669
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, BigInteger256([
15499857013495546999,
4613531467548868169,
14546778081091178013,
549402535258503313,
]));
/// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G2_GENERATOR_X, G2_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
}
}
#[rustfmt::skip]
pub const G2_GENERATOR_X: Fq2 = field_new!(Fq2, G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
#[rustfmt::skip]
pub const G2_GENERATOR_Y: Fq2 = field_new!(Fq2, G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
/// G2_GENERATOR_X_C0 =
/// 233578398248691099356572568220835526895379068987715365179118596935057653620464273615301663571204657964920925606294
#[rustfmt::skip]
pub const G2_GENERATOR_X_C0: Fq = field_new!(Fq, BigInteger384([
0x68904082f268725b,
0x668f2ea74f45328b,
0xebca7a65802be84f,
0x1e1850f4c1ada3e6,
0x830dc22d588ef1e9,
0x1862a81767c0982,
]));
/// G2_GENERATOR_X_C1 =
/// 140913150380207355837477652521042157274541796891053068589147167627541651775299824604154852141315666357241556069118
#[rustfmt::skip]
pub const G2_GENERATOR_X_C1: Fq = field_new!(Fq, BigInteger384([
0x5f02a915c91c7f39,
0xf8c553ba388da2a7,
0xd51a416dbd198850,
0xe943c6f38ae3073a,
0xffe24aa8259a4981,
0x11853391e73dfdd,
]));
/// G2_GENERATOR_Y_C0 =
/// 63160294768292073209381361943935198908131692476676907196754037919244929611450776219210369229519898517858833747423
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C0: Fq = field_new!(Fq, BigInteger384([
0xd5b19b897881430f,
0x5be9118a5b371ed,
0x6063f91f86c131ee,
0x3244a61be8f4ec19,
0xa02e425b9f9a3a12,
0x18af8c04f3360d2,
]));
/// G2_GENERATOR_Y_C1 =
/// 149157405641012693445398062341192467754805999074082136895788947234480009303640899064710353187729182149407503257491
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C1: Fq = field_new!(Fq, BigInteger384([
0x57601ac71a5b96f5,
0xe99acc1714f2440e,
0x2339612f10118ea9,
0x8321e68a3b1cd722,
0x2b543b050cc74917,
0x590182b396c112,
]));

+ 33
- 0
bls12_377/src/curves/mod.rs

@ -0,0 +1,33 @@
use crate::*;
use ark_ec::{
bls12,
bls12::{Bls12, Bls12Parameters, TwistType},
};
pub mod g1;
pub mod g2;
#[cfg(test)]
mod tests;
pub struct Parameters;
impl Bls12Parameters for Parameters {
const X: &'static [u64] = &[0x8508c00000000001];
/// `x` is positive.
const X_IS_NEGATIVE: bool = false;
const TWIST_TYPE: TwistType = TwistType::D;
type Fp = Fq;
type Fp2Params = Fq2Parameters;
type Fp6Params = Fq6Parameters;
type Fp12Params = Fq12Parameters;
type G1Parameters = g1::Parameters;
type G2Parameters = g2::Parameters;
}
pub type Bls12_377 = Bls12<Parameters>;
pub type G1Affine = bls12::G1Affine<Parameters>;
pub type G1Projective = bls12::G1Projective<Parameters>;
pub type G2Affine = bls12::G2Affine<Parameters>;
pub type G2Projective = bls12::G2Projective<Parameters>;

+ 121
- 0
bls12_377/src/curves/tests.rs

@ -0,0 +1,121 @@
#![allow(unused_imports)]
use ark_ff::{
fields::{Field, FpParameters, PrimeField, SquareRootField},
test_rng, One, Zero,
};
use ark_serialize::CanonicalSerialize;
use ark_ec::{models::SWModelParameters, AffineCurve, PairingEngine, ProjectiveCurve};
use core::ops::{AddAssign, MulAssign};
use rand::Rng;
use crate::{g1, g2, Bls12_377, Fq, Fq12, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
use ark_curve_tests::{
curves::{curve_tests, sw_tests},
groups::group_test,
};
#[test]
fn test_g1_projective_curve() {
curve_tests::<G1Projective>();
sw_tests::<g1::Parameters>();
}
#[test]
fn test_g1_projective_group() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G1Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g1_generator() {
let generator = G1Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g2_projective_curve() {
curve_tests::<G2Projective>();
sw_tests::<g2::Parameters>();
}
#[test]
fn test_g2_projective_group() {
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g2_generator() {
let generator = G2Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_bilinearity() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G2Projective = rng.gen();
let s: Fr = rng.gen();
let mut sa = a;
sa.mul_assign(s);
let mut sb = b;
sb.mul_assign(s);
let ans1 = Bls12_377::pairing(sa, b);
let ans2 = Bls12_377::pairing(a, sb);
let ans3 = Bls12_377::pairing(a, b).pow(s.into_repr());
assert_eq!(ans1, ans2);
assert_eq!(ans2, ans3);
assert_ne!(ans1, Fq12::one());
assert_ne!(ans2, Fq12::one());
assert_ne!(ans3, Fq12::one());
assert_eq!(ans1.pow(Fr::characteristic()), Fq12::one());
assert_eq!(ans2.pow(Fr::characteristic()), Fq12::one());
assert_eq!(ans3.pow(Fr::characteristic()), Fq12::one());
}
#[test]
fn test_g1_generator_raw() {
let mut x = Fq::zero();
let mut i = 0;
loop {
// y^2 = x^3 + b
let mut rhs = x;
rhs.square_in_place();
rhs.mul_assign(&x);
rhs.add_assign(&g1::Parameters::COEFF_B);
if let Some(y) = rhs.sqrt() {
let p = G1Affine::new(x, if y < -y { y } else { -y }, false);
assert!(!p.is_in_correct_subgroup_assuming_on_curve());
let g1 = p.scale_by_cofactor();
if !g1.is_zero() {
assert_eq!(i, 1);
let g1 = G1Affine::from(g1);
assert!(g1.is_in_correct_subgroup_assuming_on_curve());
assert_eq!(g1, G1Affine::prime_subgroup_generator());
break;
}
}
i += 1;
x.add_assign(&Fq::one());
}
}

+ 114
- 0
bls12_377/src/fields/fq.rs

@ -0,0 +1,114 @@
use ark_ff::{biginteger::BigInteger384 as BigInteger, field_new, fields::*};
pub type Fq = Fp384<FqParameters>;
pub struct FqParameters;
impl Fp384Parameters for FqParameters {}
impl FftParameters for FqParameters {
type BigInt = BigInteger;
const TWO_ADICITY: u32 = 46u32;
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
2022196864061697551u64,
17419102863309525423u64,
8564289679875062096u64,
17152078065055548215u64,
17966377291017729567u64,
68610905582439508u64,
]);
}
impl FpParameters for FqParameters {
/// MODULUS = 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
0x8508c00000000001,
0x170b5d4430000000,
0x1ef3622fba094800,
0x1a22d9f300f5138f,
0xc63b05c06ca1493b,
0x1ae3a4617c510ea,
]);
const MODULUS_BITS: u32 = 377;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
const REPR_SHAVE_BITS: u32 = 7;
#[rustfmt::skip]
const R: BigInteger = BigInteger([
202099033278250856u64,
5854854902718660529u64,
11492539364873682930u64,
8885205928937022213u64,
5545221690922665192u64,
39800542322357402u64,
]);
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
0xb786686c9400cd22,
0x329fcaab00431b1,
0x22a5f11162d6b46d,
0xbfdf7d03827dc3ac,
0x837e92f041790bf9,
0x6dfccb1e914b88,
]);
const INV: u64 = 9586122913090633727u64;
// GENERATOR = -5
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
0xfc0b8000000002fa,
0x97d39cf6e000018b,
0x2072420fbfa05044,
0xcbbcbd50d97c3802,
0xbaf1ec35813f9eb,
0x9974a2c0945ad2,
]);
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x4284600000000000,
0xb85aea218000000,
0x8f79b117dd04a400,
0x8d116cf9807a89c7,
0x631d82e03650a49d,
0xd71d230be28875,
]);
// T and T_MINUS_ONE_DIV_TWO, where MODULUS - 1 = 2^S * T
// T = (MODULUS - 1) // 2^S =
// 3675842578061421676390135839012792950148785745837396071634149488243117337281387659330802195819009059
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0x7510c00000021423,
0x88bee82520005c2d,
0x67cc03d44e3c7bcd,
0x1701b28524ec688b,
0xe9185f1443ab18ec,
0x6b8,
]);
// (T - 1) // 2 =
// 1837921289030710838195067919506396475074392872918698035817074744121558668640693829665401097909504529
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0xba88600000010a11,
0xc45f741290002e16,
0xb3e601ea271e3de6,
0xb80d94292763445,
0x748c2f8a21d58c76,
0x35c,
]);
}
#[allow(dead_code)]
pub const FQ_ONE: Fq = field_new!(Fq, FqParameters::R);
#[allow(dead_code)]
pub const FQ_ZERO: Fq = field_new!(Fq, BigInteger([0, 0, 0, 0, 0, 0]));

+ 161
- 0
bls12_377/src/fields/fq12.rs

@ -0,0 +1,161 @@
use super::*;
use ark_ff::{biginteger::BigInteger384, field_new, fields::*};
pub type Fq12 = Fp12<Fq12Parameters>;
#[derive(Clone, Copy)]
pub struct Fq12Parameters;
impl Fp12Parameters for Fq12Parameters {
type Fp6Params = Fq6Parameters;
const NONRESIDUE: Fq6 = field_new!(Fq6, FQ2_ZERO, FQ2_ONE, FQ2_ZERO);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP12_C1: &'static [Fq2] = &[
// Fp2::NONRESIDUE^(((q^0) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x2cdffffffffff68,
0x51409f837fffffb1,
0x9f7db3a98a7d3ff2,
0x7b4e97b76e7c6305,
0x4cf495bf803c84e8,
0x8d6661e2fdf49a,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^1) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x6ec47a04a3f7ca9e,
0xa42e0cb968c1fa44,
0x578d5187fbd2bd23,
0x930eeb0ac79dd4bd,
0xa24883de1e09a9ee,
0xdaa7058067d46f,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^2) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x5892506da58478da,
0x133366940ac2a74b,
0x9b64a150cdf726cf,
0x5cc426090a9c587e,
0x5cf848adfdcd640c,
0x4702bf3ac02380,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^3) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x982c13d9d084771f,
0xfd49de0c6da34a32,
0x61a530d183ab0e53,
0xdf8fe44106dd9879,
0x40f29b58d88472bc,
0x158723199046d5d,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^4) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xdacd106da5847973,
0xd8fe2454bac2a79a,
0x1ada4fd6fd832edc,
0xfb9868449d150908,
0xd63eb8aeea32285e,
0x167d6a36f873fd0,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^5) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x296799d52c8cac81,
0x591bd15304e14fee,
0xa17df4987d85130,
0x4c80f9363f3fc3bc,
0x9eaa177aba7ac8ce,
0x7dcb2c189c98ed,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^6) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x823ac00000000099,
0xc5cabdc0b000004f,
0x7f75ae862f8c080d,
0x9ed4423b9278b089,
0x79467000ec64c452,
0x120d3e434c71c50,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^(((q^7) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x164445fb5c083563,
0x72dd508ac73e05bc,
0xc76610a7be368adc,
0x8713eee839573ed1,
0x23f281e24e979f4c,
0xd39340975d3c7b,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^8) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x2c766f925a7b8727,
0x3d7f6b0253d58b5,
0x838ec0deec122131,
0xbd5eb3e9f658bb10,
0x6942bd126ed3e52e,
0x1673786dd04ed6a,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^9) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xecdcac262f7b88e2,
0x19c17f37c25cb5cd,
0xbd4e315e365e39ac,
0x3a92f5b1fa177b15,
0x85486a67941cd67e,
0x55c8147ec0a38d,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^10) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xaa3baf925a7b868e,
0x3e0d38ef753d5865,
0x4191258bc861923,
0x1e8a71ae63e00a87,
0xeffc4d11826f20dc,
0x4663a2a83dd119,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^11) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x5ba1262ad3735380,
0xbdef8bf12b1eb012,
0x14db82e63230f6cf,
0xcda1e0bcc1b54fd3,
0x2790ee45b226806c,
0x1306f19ff2877fd,
])),
FQ_ZERO,
),
];
}

+ 69
- 0
bls12_377/src/fields/fq2.rs

@ -0,0 +1,69 @@
use super::*;
use ark_ff::{biginteger::BigInteger384 as BigInteger, field_new, fields::*};
pub type Fq2 = Fp2<Fq2Parameters>;
pub struct Fq2Parameters;
impl Fp2Parameters for Fq2Parameters {
type Fp = Fq;
/// NONRESIDUE = -5
#[rustfmt::skip]
const NONRESIDUE: Fq = field_new!(Fq, BigInteger([
0xfc0b8000000002fa,
0x97d39cf6e000018b,
0x2072420fbfa05044,
0xcbbcbd50d97c3802,
0xbaf1ec35813f9eb,
0x9974a2c0945ad2,
]));
/// QUADRATIC_NONRESIDUE = U
#[rustfmt::skip]
const QUADRATIC_NONRESIDUE: (Fq, Fq) = (
field_new!(Fq, BigInteger([0, 0, 0, 0, 0, 0])),
field_new!(Fq, BigInteger([
202099033278250856u64,
5854854902718660529u64,
11492539364873682930u64,
8885205928937022213u64,
5545221690922665192u64,
39800542322357402u64,
])),
);
/// Coefficients for the Frobenius automorphism.
#[rustfmt::skip]
const FROBENIUS_COEFF_FP2_C1: &'static [Fq] = &[
// NONRESIDUE**(((q^0) - 1) / 2)
field_new!(Fq, BigInteger([
0x2cdffffffffff68,
0x51409f837fffffb1,
0x9f7db3a98a7d3ff2,
0x7b4e97b76e7c6305,
0x4cf495bf803c84e8,
0x8d6661e2fdf49a,
])),
// NONRESIDUE**(((q^1) - 1) / 2)
field_new!(Fq, BigInteger([
0x823ac00000000099,
0xc5cabdc0b000004f,
0x7f75ae862f8c080d,
0x9ed4423b9278b089,
0x79467000ec64c452,
0x120d3e434c71c50,
])),
];
#[inline(always)]
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp {
let original = fe;
let mut fe = -fe.double();
fe.double_in_place();
fe - original
}
}
pub const FQ2_ZERO: Fq2 = field_new!(Fq2, FQ_ZERO, FQ_ZERO);
pub const FQ2_ONE: Fq2 = field_new!(Fq2, FQ_ONE, FQ_ZERO);

+ 184
- 0
bls12_377/src/fields/fq6.rs

@ -0,0 +1,184 @@
use super::*;
use ark_ff::{biginteger::BigInteger384, field_new, fields::*};
pub type Fq6 = Fp6<Fq6Parameters>;
#[derive(Clone, Copy)]
pub struct Fq6Parameters;
impl Fp6Parameters for Fq6Parameters {
type Fp2Params = Fq2Parameters;
/// NONRESIDUE = U
#[rustfmt::skip]
const NONRESIDUE: Fq2 = field_new!(Fq2,
field_new!(Fq, BigInteger384([0, 0, 0, 0, 0, 0])),
field_new!(Fq, BigInteger384([
202099033278250856u64,
5854854902718660529u64,
11492539364873682930u64,
8885205928937022213u64,
5545221690922665192u64,
39800542322357402u64,
])),
);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C1: &'static [Fq2] = &[
// Fp2::NONRESIDUE^(((q^0) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x2cdffffffffff68,
0x51409f837fffffb1,
0x9f7db3a98a7d3ff2,
0x7b4e97b76e7c6305,
0x4cf495bf803c84e8,
0x8d6661e2fdf49a,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^(((q^1) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x5892506da58478da,
0x133366940ac2a74b,
0x9b64a150cdf726cf,
0x5cc426090a9c587e,
0x5cf848adfdcd640c,
0x4702bf3ac02380,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^(((q^2) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xdacd106da5847973,
0xd8fe2454bac2a79a,
0x1ada4fd6fd832edc,
0xfb9868449d150908,
0xd63eb8aeea32285e,
0x167d6a36f873fd0,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^(((q^3) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x823ac00000000099,
0xc5cabdc0b000004f,
0x7f75ae862f8c080d,
0x9ed4423b9278b089,
0x79467000ec64c452,
0x120d3e434c71c50,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^(((q^4) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x2c766f925a7b8727,
0x3d7f6b0253d58b5,
0x838ec0deec122131,
0xbd5eb3e9f658bb10,
0x6942bd126ed3e52e,
0x1673786dd04ed6a,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^(((q^5) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xaa3baf925a7b868e,
0x3e0d38ef753d5865,
0x4191258bc861923,
0x1e8a71ae63e00a87,
0xeffc4d11826f20dc,
0x4663a2a83dd119,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
];
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C2: &'static [Fq2] = &[
// Fp2::NONRESIDUE^((2*(q^0) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x2cdffffffffff68,
0x51409f837fffffb1,
0x9f7db3a98a7d3ff2,
0x7b4e97b76e7c6305,
0x4cf495bf803c84e8,
0x8d6661e2fdf49a,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^((2*(q^1) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xdacd106da5847973,
0xd8fe2454bac2a79a,
0x1ada4fd6fd832edc,
0xfb9868449d150908,
0xd63eb8aeea32285e,
0x167d6a36f873fd0,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^((2*(q^2) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x2c766f925a7b8727,
0x3d7f6b0253d58b5,
0x838ec0deec122131,
0xbd5eb3e9f658bb10,
0x6942bd126ed3e52e,
0x1673786dd04ed6a,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^((2*(q^3) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x2cdffffffffff68,
0x51409f837fffffb1,
0x9f7db3a98a7d3ff2,
0x7b4e97b76e7c6305,
0x4cf495bf803c84e8,
0x8d6661e2fdf49a,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^((2*(q^4) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xdacd106da5847973,
0xd8fe2454bac2a79a,
0x1ada4fd6fd832edc,
0xfb9868449d150908,
0xd63eb8aeea32285e,
0x167d6a36f873fd0,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^((2*(q^5) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x2c766f925a7b8727,
0x3d7f6b0253d58b5,
0x838ec0deec122131,
0xbd5eb3e9f658bb10,
0x6942bd126ed3e52e,
0x1673786dd04ed6a,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
];
#[inline(always)]
fn mul_fp2_by_nonresidue(fe: &Fq2) -> Fq2 {
// Karatsuba multiplication with constant other = u.
let c0 = Fq2Parameters::mul_fp_by_nonresidue(&fe.c1);
let c1 = fe.c0;
field_new!(Fq2, c0, c1)
}
}

+ 95
- 0
bls12_377/src/fields/fr.rs

@ -0,0 +1,95 @@
use ark_ff::{biginteger::BigInteger256 as BigInteger, fields::*};
pub type Fr = Fp256<FrParameters>;
pub struct FrParameters;
impl Fp256Parameters for FrParameters {}
impl FftParameters for FrParameters {
type BigInt = BigInteger;
const TWO_ADICITY: u32 = 47;
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
0x3c3d3ca739381fb2,
0x9a14cda3ec99772b,
0xd7aacc7c59724826,
0xd1ba211c5cc349c,
]);
}
impl FpParameters for FrParameters {
/// MODULUS = 8444461749428370424248824938781546531375899335154063827935233455917409239041
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
725501752471715841u64,
6461107452199829505u64,
6968279316240510977u64,
1345280370688173398u64,
]);
const MODULUS_BITS: u32 = 253;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
const REPR_SHAVE_BITS: u32 = 3;
#[rustfmt::skip]
const R: BigInteger = BigInteger([
9015221291577245683u64,
8239323489949974514u64,
1646089257421115374u64,
958099254763297437u64,
]);
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
2726216793283724667u64,
14712177743343147295u64,
12091039717619697043u64,
81024008013859129u64,
]);
const INV: u64 = 725501752471715839u64;
// GENERATOR = 11
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
1855201571499933546u64,
8511318076631809892u64,
6222514765367795509u64,
1122129207579058019u64,
]);
/// (r - 1)/2 =
/// 4222230874714185212124412469390773265687949667577031913967616727958704619520
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x8508c00000000000,
0xacd53b7f68000000,
0x305a268f2e1bd800,
0x955b2af4d1652ab,
]);
// T and T_MINUS_ONE_DIV_TWO, where r - 1 = 2^s * t
/// t = (r - 1) / 2^s =
/// 60001509534603559531609739528203892656505753216962260608619555
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0xedfda00000021423,
0x9a3cb86f6002b354,
0xcabd34594aacc168,
0x2556,
]);
/// (t - 1) / 2 =
/// 30000754767301779765804869764101946328252876608481130304309777
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x76fed00000010a11,
0x4d1e5c37b00159aa,
0x655e9a2ca55660b4,
0x12ab,
]);
}

+ 27
- 0
bls12_377/src/fields/mod.rs

@ -0,0 +1,27 @@
#[cfg(feature = "scalar_field")]
pub mod fr;
#[cfg(feature = "scalar_field")]
pub use self::fr::*;
#[cfg(feature = "base_field")]
pub mod fq;
#[cfg(feature = "base_field")]
pub use self::fq::*;
#[cfg(feature = "curve")]
pub mod fq2;
#[cfg(feature = "curve")]
pub use self::fq2::*;
#[cfg(feature = "curve")]
pub mod fq6;
#[cfg(feature = "curve")]
pub use self::fq6::*;
#[cfg(feature = "curve")]
pub mod fq12;
#[cfg(feature = "curve")]
pub use self::fq12::*;
#[cfg(all(feature = "curve", test))]
mod tests;

+ 530
- 0
bls12_377/src/fields/tests.rs

@ -0,0 +1,530 @@
use ark_ff::{
biginteger::{BigInteger, BigInteger384},
fields::{
fp6_3over2::Fp6Parameters, FftField, FftParameters, Field, Fp2Parameters, FpParameters,
PrimeField, SquareRootField,
},
test_rng, One, UniformRand, Zero,
};
use ark_serialize::{buffer_bit_byte_size, CanonicalSerialize};
use core::{
cmp::Ordering,
ops::{AddAssign, MulAssign, SubAssign},
};
use rand::{Rng, SeedableRng};
use rand_xorshift::XorShiftRng;
use crate::{Fq, Fq12, Fq2, Fq2Parameters, Fq6, Fq6Parameters, FqParameters, Fr};
use ark_curve_tests::fields::*;
pub(crate) const ITERATIONS: usize = 5;
#[test]
fn test_fr() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let a: Fr = rng.gen();
let b: Fr = rng.gen();
field_test(a, b);
primefield_test::<Fr>();
sqrt_field_test(b);
let byte_size = a.serialized_size();
field_serialization_test::<Fr>(byte_size);
}
}
#[test]
fn test_fq() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let a: Fq = rng.gen();
let b: Fq = rng.gen();
field_test(a, b);
primefield_test::<Fq>();
sqrt_field_test(a);
let byte_size = a.serialized_size();
let (_, buffer_size) = buffer_bit_byte_size(Fq::size_in_bits());
assert_eq!(byte_size, buffer_size);
field_serialization_test::<Fq>(byte_size);
}
}
#[test]
fn test_fq2() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let a: Fq2 = rng.gen();
let b: Fq2 = rng.gen();
field_test(a, b);
sqrt_field_test(a);
}
frobenius_test::<Fq2, _>(Fq::characteristic(), 13);
let byte_size = Fq2::zero().serialized_size();
field_serialization_test::<Fq2>(byte_size);
}
#[test]
fn test_fq6() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let g: Fq6 = rng.gen();
let h: Fq6 = rng.gen();
field_test(g, h);
}
frobenius_test::<Fq6, _>(Fq::characteristic(), 13);
let byte_size = Fq6::zero().serialized_size();
field_serialization_test::<Fq6>(byte_size);
}
#[test]
fn test_fq12() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let g: Fq12 = rng.gen();
let h: Fq12 = rng.gen();
field_test(g, h);
}
frobenius_test::<Fq12, _>(Fq::characteristic(), 13);
let byte_size = Fq12::zero().serialized_size();
field_serialization_test::<Fq12>(byte_size);
}
#[test]
fn test_fq_repr_from() {
assert_eq!(
BigInteger384::from(100),
BigInteger384([100, 0, 0, 0, 0, 0])
);
}
#[test]
fn test_fq_repr_is_odd() {
assert!(!BigInteger384::from(0).is_odd());
assert!(BigInteger384::from(0).is_even());
assert!(BigInteger384::from(1).is_odd());
assert!(!BigInteger384::from(1).is_even());
assert!(!BigInteger384::from(324834872).is_odd());
assert!(BigInteger384::from(324834872).is_even());
assert!(BigInteger384::from(324834873).is_odd());
assert!(!BigInteger384::from(324834873).is_even());
}
#[test]
fn test_fq_repr_is_zero() {
assert!(BigInteger384::from(0).is_zero());
assert!(!BigInteger384::from(1).is_zero());
assert!(!BigInteger384([0, 0, 0, 0, 1, 0]).is_zero());
}
#[test]
fn test_fq_repr_num_bits() {
let mut a = BigInteger384::from(0);
assert_eq!(0, a.num_bits());
a = BigInteger384::from(1);
for i in 1..385 {
assert_eq!(i, a.num_bits());
a.mul2();
}
assert_eq!(0, a.num_bits());
}
#[test]
fn test_fq_add_assign() {
// Test associativity
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
// Generate a, b, c and ensure (a + b) + c == a + (b + c).
let a = Fq::rand(&mut rng);
let b = Fq::rand(&mut rng);
let c = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.add_assign(&b);
tmp1.add_assign(&c);
let mut tmp2 = b;
tmp2.add_assign(&c);
tmp2.add_assign(&a);
assert_eq!(tmp1, tmp2);
}
}
#[test]
fn test_fq_sub_assign() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
// Ensure that (a - b) + (b - a) = 0.
let a = Fq::rand(&mut rng);
let b = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.sub_assign(&b);
let mut tmp2 = b;
tmp2.sub_assign(&a);
tmp1.add_assign(&tmp2);
assert!(tmp1.is_zero());
}
}
#[test]
fn test_fq_mul_assign() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000000 {
// Ensure that (a * b) * c = a * (b * c)
let a = Fq::rand(&mut rng);
let b = Fq::rand(&mut rng);
let c = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.mul_assign(&b);
tmp1.mul_assign(&c);
let mut tmp2 = b;
tmp2.mul_assign(&c);
tmp2.mul_assign(&a);
assert_eq!(tmp1, tmp2);
}
for _ in 0..1000000 {
// Ensure that r * (a + b + c) = r*a + r*b + r*c
let r = Fq::rand(&mut rng);
let mut a = Fq::rand(&mut rng);
let mut b = Fq::rand(&mut rng);
let mut c = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.add_assign(&b);
tmp1.add_assign(&c);
tmp1.mul_assign(&r);
a.mul_assign(&r);
b.mul_assign(&r);
c.mul_assign(&r);
a.add_assign(&b);
a.add_assign(&c);
assert_eq!(tmp1, a);
}
}
#[test]
fn test_fq_squaring() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000000 {
// Ensure that (a * a) = a^2
let a = Fq::rand(&mut rng);
let mut tmp = a;
tmp.square_in_place();
let mut tmp2 = a;
tmp2.mul_assign(&a);
assert_eq!(tmp, tmp2);
}
}
#[test]
fn test_fq_inverse() {
assert!(Fq::zero().inverse().is_none());
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let one = Fq::one();
for _ in 0..1000 {
// Ensure that a * a^-1 = 1
let mut a = Fq::rand(&mut rng);
let ainv = a.inverse().unwrap();
a.mul_assign(&ainv);
assert_eq!(a, one);
}
}
#[test]
fn test_fq_double_in_place() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
// Ensure doubling a is equivalent to adding a to itself.
let mut a = Fq::rand(&mut rng);
let mut b = a;
b.add_assign(&a);
a.double_in_place();
assert_eq!(a, b);
}
}
#[test]
fn test_fq_negate() {
{
let a = -Fq::zero();
assert!(a.is_zero());
}
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
// Ensure (a - (-a)) = 0.
let mut a = Fq::rand(&mut rng);
let b = -a;
a.add_assign(&b);
assert!(a.is_zero());
}
}
#[test]
fn test_fq_pow() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for i in 0..1000 {
// Exponentiate by various small numbers and ensure it consists with repeated
// multiplication.
let a = Fq::rand(&mut rng);
let target = a.pow(&[i]);
let mut c = Fq::one();
for _ in 0..i {
c.mul_assign(&a);
}
assert_eq!(c, target);
}
for _ in 0..1000 {
// Exponentiating by the modulus should have no effect in a prime field.
let a = Fq::rand(&mut rng);
assert_eq!(a, a.pow(Fq::characteristic()));
}
}
#[test]
fn test_fq_sqrt() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
assert_eq!(Fq::zero().sqrt().unwrap(), Fq::zero());
for _ in 0..1000 {
// Ensure sqrt(a^2) = a or -a
let a = Fq::rand(&mut rng);
let nega = -a;
let mut b = a;
b.square_in_place();
let b = b.sqrt().unwrap();
assert!(a == b || nega == b);
}
for _ in 0..1000 {
// Ensure sqrt(a)^2 = a for random a
let a = Fq::rand(&mut rng);
if let Some(mut tmp) = a.sqrt() {
tmp.square_in_place();
assert_eq!(a, tmp);
}
}
}
#[test]
fn test_fq_num_bits() {
assert_eq!(FqParameters::MODULUS_BITS, 377);
assert_eq!(FqParameters::CAPACITY, 376);
}
#[test]
fn test_fq_root_of_unity() {
assert_eq!(FqParameters::TWO_ADICITY, 46);
assert_eq!(
Fq::multiplicative_generator().pow([
0x7510c00000021423,
0x88bee82520005c2d,
0x67cc03d44e3c7bcd,
0x1701b28524ec688b,
0xe9185f1443ab18ec,
0x6b8
]),
Fq::two_adic_root_of_unity()
);
assert_eq!(
Fq::two_adic_root_of_unity().pow([1 << FqParameters::TWO_ADICITY]),
Fq::one()
);
assert!(Fq::multiplicative_generator().sqrt().is_none());
}
#[test]
fn test_fq_ordering() {
// BigInteger384's ordering is well-tested, but we still need to make sure the
// Fq elements aren't being compared in Montgomery form.
for i in 0..100 {
assert!(Fq::from(BigInteger384::from(i + 1)) > Fq::from(BigInteger384::from(i)));
}
}
#[test]
fn test_fq_legendre() {
use ark_ff::fields::LegendreSymbol::*;
assert_eq!(QuadraticResidue, Fq::one().legendre());
assert_eq!(Zero, Fq::zero().legendre());
assert_eq!(
QuadraticResidue,
Fq::from(BigInteger384::from(4)).legendre()
);
assert_eq!(
QuadraticNonResidue,
Fq::from(BigInteger384::from(5)).legendre()
);
}
#[test]
fn test_fq2_ordering() {
let mut a = Fq2::new(Fq::zero(), Fq::zero());
let mut b = a.clone();
assert!(a.cmp(&b) == Ordering::Equal);
b.c0.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Less);
a.c0.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Equal);
b.c1.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Less);
a.c0.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Less);
a.c1.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Greater);
b.c0.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Equal);
}
#[test]
fn test_fq2_basics() {
assert_eq!(Fq2::new(Fq::zero(), Fq::zero(),), Fq2::zero());
assert_eq!(Fq2::new(Fq::one(), Fq::zero(),), Fq2::one());
assert!(Fq2::zero().is_zero());
assert!(!Fq2::one().is_zero());
assert!(!Fq2::new(Fq::zero(), Fq::one(),).is_zero());
}
#[test]
fn test_fq2_legendre() {
use ark_ff::fields::LegendreSymbol::*;
assert_eq!(Zero, Fq2::zero().legendre());
// i^2 = -1
let mut m1 = -Fq2::one();
assert_eq!(QuadraticResidue, m1.legendre());
m1 = Fq6Parameters::mul_fp2_by_nonresidue(&m1);
assert_eq!(QuadraticNonResidue, m1.legendre());
}
#[test]
fn test_fq2_mul_nonresidue() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let nqr = Fq2::new(Fq::zero(), Fq::one());
let quadratic_non_residue = Fq2::new(
Fq2Parameters::QUADRATIC_NONRESIDUE.0,
Fq2Parameters::QUADRATIC_NONRESIDUE.1,
);
for _ in 0..1000 {
let mut a = Fq2::rand(&mut rng);
let mut b = a;
a = quadratic_non_residue * &a;
b.mul_assign(&nqr);
assert_eq!(a, b);
}
}
#[test]
fn test_fq6_mul_by_1() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
let c1 = Fq2::rand(&mut rng);
let mut a = Fq6::rand(&mut rng);
let mut b = a;
a.mul_by_1(&c1);
b.mul_assign(&Fq6::new(Fq2::zero(), c1, Fq2::zero()));
assert_eq!(a, b);
}
}
#[test]
fn test_fq6_mul_by_01() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
let c0 = Fq2::rand(&mut rng);
let c1 = Fq2::rand(&mut rng);
let mut a = Fq6::rand(&mut rng);
let mut b = a;
a.mul_by_01(&c0, &c1);
b.mul_assign(&Fq6::new(c0, c1, Fq2::zero()));
assert_eq!(a, b);
}
}
#[test]
fn test_fq12_mul_by_014() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
let c0 = Fq2::rand(&mut rng);
let c1 = Fq2::rand(&mut rng);
let c5 = Fq2::rand(&mut rng);
let mut a = Fq12::rand(&mut rng);
let mut b = a;
a.mul_by_014(&c0, &c1, &c5);
b.mul_assign(&Fq12::new(
Fq6::new(c0, c1, Fq2::zero()),
Fq6::new(Fq2::zero(), c5, Fq2::zero()),
));
assert_eq!(a, b);
}
}
#[test]
fn test_fq12_mul_by_034() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
let c0 = Fq2::rand(&mut rng);
let c3 = Fq2::rand(&mut rng);
let c4 = Fq2::rand(&mut rng);
let mut a = Fq12::rand(&mut rng);
let mut b = a;
a.mul_by_034(&c0, &c3, &c4);
b.mul_assign(&Fq12::new(
Fq6::new(c0, Fq2::zero(), Fq2::zero()),
Fq6::new(c3, c4, Fq2::zero()),
));
assert_eq!(a, b);
}
}

+ 35
- 0
bls12_377/src/lib.rs

@ -0,0 +1,35 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(
warnings,
unused,
future_incompatible,
nonstandard_style,
rust_2018_idioms
)]
#![forbid(unsafe_code)]
//! This library implements the BLS12_377 curve generated in [[BCGMMW20, “Zexe”]](https://eprint.iacr.org/2018/962).
//! The name denotes that it is a Barreto--Lynn--Scott curve of embedding degree 12,
//! defined over a 377-bit (prime) field. The main feature of this curve is that
//! both the scalar field and the base field are highly 2-adic.
//! (This is in contrast to the BLS12_381 curve for which only the scalar field is highly 2-adic.)
//!
//!
//! Curve information:
//! * Base field: q = 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177
//! * Scalar field: r = 8444461749428370424248824938781546531375899335154063827935233455917409239041
//! * valuation(q - 1, 2) = 46
//! * valuation(r - 1, 2) = 47
//! * G1 curve equation: y^2 = x^3 + 1
//! * G2 curve equation: y^2 = x^3 + B, where
//! * B = Fq2(0, 155198655607781456406391640216936120121836107652948796323930557600032281009004493664981332883744016074664192874906)
#[cfg(feature = "curve")]
mod curves;
mod fields;
#[cfg(feature = "curve")]
pub use curves::*;
pub use fields::*;

+ 31
- 0
bls12_381/Cargo.toml

@ -0,0 +1,31 @@
[package]
name = "ark-bls12-381"
version = "0.1.0"
authors = [ "arkworks contributors" ]
description = "The BLS12-381 pairing-friendly elliptic curve"
homepage = "https://arworks.rs"
repository = "https://github.com/arkworks/algebra"
documentation = "https://docs.rs/ark-bls12-381/"
keywords = ["cryptography", "finite fields", "elliptic curves" ]
categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0"
edition = "2018"
[dependencies]
ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false }
[dev-dependencies]
ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-curve-tests = { path = "../curve-tests", default-features = false }
rand = { version = "0.7", default-features = false }
rand_xorshift = "0.2"
[features]
default = [ "curve" ]
std = [ "ark-std/std", "ark-ff/std", "ark-ec/std" ]
curve = [ "scalar_field" ]
scalar_field = []

+ 1
- 0
bls12_381/LICENSE-APACHE

@ -0,0 +1 @@
../LICENSE-APACHE

+ 1
- 0
bls12_381/LICENSE-MIT

@ -0,0 +1 @@
../LICENSE-MIT

+ 82
- 0
bls12_381/src/curves/g1.rs

@ -0,0 +1,82 @@
use crate::*;
use ark_ec::{
bls12,
models::{ModelParameters, SWModelParameters},
};
use ark_ff::{
biginteger::{BigInteger256, BigInteger384},
field_new, Zero,
};
pub type G1Affine = bls12::G1Affine<crate::Parameters>;
pub type G1Projective = bls12::G1Projective<crate::Parameters>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
impl ModelParameters for Parameters {
type BaseField = Fq;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = 0
const COEFF_A: Fq = field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0]));
/// COEFF_B = 4
#[rustfmt::skip]
const COEFF_B: Fq = field_new!(Fq, BigInteger384([
0xaa270000000cfff3,
0x53cc0032fc34000a,
0x478fe97a6b0a807f,
0xb1d37ebee6ba24d7,
0x8ec9733bbf78ab2f,
0x9d645513d83de7e,
]));
/// COFACTOR = (x - 1)^2 / 3 = 76329603384216526031706109802092473003
const COFACTOR: &'static [u64] = &[0x8c00aaab0000aaab, 0x396c8c005555e156];
/// COFACTOR_INV = COFACTOR^{-1} mod r
/// = 52435875175126190458656871551744051925719901746859129887267498875565241663483
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, BigInteger256([
288839107172787499,
1152722415086798946,
2612889808468387987,
5124657601728438008,
]));
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G1_GENERATOR_X, G1_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
}
}
/// G1_GENERATOR_X =
/// 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507
#[rustfmt::skip]
pub const G1_GENERATOR_X: Fq = field_new!(Fq, BigInteger384([
0x5cb38790fd530c16,
0x7817fc679976fff5,
0x154f95c7143ba1c1,
0xf0ae6acdf3d0e747,
0xedce6ecc21dbf440,
0x120177419e0bfb75,
]));
/// G1_GENERATOR_Y =
/// 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569
#[rustfmt::skip]
pub const G1_GENERATOR_Y: Fq = field_new!(Fq, BigInteger384([
0xbaac93d50ce72271,
0x8c22631a7918fd8e,
0xdd595f13570725ce,
0x51ac582950405194,
0xe1c8c3fad0059c0,
0xbbc3efc5008a26a,
]));

+ 113
- 0
bls12_381/src/curves/g2.rs

@ -0,0 +1,113 @@
use crate::*;
use ark_ec::{
bls12,
models::{ModelParameters, SWModelParameters},
};
use ark_ff::{
biginteger::{BigInteger256, BigInteger384},
field_new, Zero,
};
pub type G2Affine = bls12::G2Affine<crate::Parameters>;
pub type G2Projective = bls12::G2Projective<crate::Parameters>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
impl ModelParameters for Parameters {
type BaseField = Fq2;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = [0, 0]
const COEFF_A: Fq2 = field_new!(Fq2, g1::Parameters::COEFF_A, g1::Parameters::COEFF_A,);
/// COEFF_B = [4, 4]
const COEFF_B: Fq2 = field_new!(Fq2, g1::Parameters::COEFF_B, g1::Parameters::COEFF_B,);
/// COFACTOR = (x^8 - 4 x^7 + 5 x^6) - (4 x^4 + 6 x^3 - 4 x^2 - 4 x + 13) //
/// 9
/// = 305502333931268344200999753193121504214466019254188142667664032982267604182971884026507427359259977847832272839041616661285803823378372096355777062779109
#[rustfmt::skip]
const COFACTOR: &'static [u64] = &[
0xcf1c38e31c7238e5,
0x1616ec6e786f0c70,
0x21537e293a6691ae,
0xa628f1cb4d9e82ef,
0xa68a205b2e5a7ddf,
0xcd91de4547085aba,
0x91d50792876a202,
0x5d543a95414e7f1,
];
/// COFACTOR_INV = COFACTOR^{-1} mod r
/// 26652489039290660355457965112010883481355318854675681319708643586776743290055
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, BigInteger256([
6746407649509787816,
1304054119431494378,
2461312685643913071,
5956596749362435284,
]));
/// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G2_GENERATOR_X, G2_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
}
}
pub const G2_GENERATOR_X: Fq2 = field_new!(Fq2, G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
pub const G2_GENERATOR_Y: Fq2 = field_new!(Fq2, G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
/// G2_GENERATOR_X_C0 =
/// 352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160
#[rustfmt::skip]
pub const G2_GENERATOR_X_C0: Fq = field_new!(Fq, BigInteger384([
0xf5f28fa202940a10,
0xb3f5fb2687b4961a,
0xa1a893b53e2ae580,
0x9894999d1a3caee9,
0x6f67b7631863366b,
0x58191924350bcd7,
]));
/// G2_GENERATOR_X_C1 =
/// 3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758
#[rustfmt::skip]
pub const G2_GENERATOR_X_C1: Fq = field_new!(Fq, BigInteger384([
0xa5a9c0759e23f606,
0xaaa0c59dbccd60c3,
0x3bb17e18e2867806,
0x1b1ab6cc8541b367,
0xc2b6ed0ef2158547,
0x11922a097360edf3,
]));
/// G2_GENERATOR_Y_C0 =
/// 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C0: Fq = field_new!(Fq, BigInteger384([
0x4c730af860494c4a,
0x597cfa1f5e369c5a,
0xe7e6856caa0a635a,
0xbbefb5e96e0d495f,
0x7d3a975f0ef25a2,
0x83fd8e7e80dae5,
]));
/// G2_GENERATOR_Y_C1 =
/// 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C1: Fq = field_new!(Fq, BigInteger384([
0xadc0fc92df64b05d,
0x18aa270a2b1461dc,
0x86adac6a3be4eba0,
0x79495c4ec93da33a,
0xe7175850a43ccaed,
0xb2bc2a163de1bf2,
]));

+ 30
- 0
bls12_381/src/curves/mod.rs

@ -0,0 +1,30 @@
use ark_ec::bls12::{Bls12, Bls12Parameters, TwistType};
use crate::{Fq, Fq12Parameters, Fq2Parameters, Fq6Parameters};
pub mod g1;
pub mod g2;
#[cfg(test)]
mod tests;
pub use self::{
g1::{G1Affine, G1Projective},
g2::{G2Affine, G2Projective},
};
pub type Bls12_381 = Bls12<Parameters>;
pub struct Parameters;
impl Bls12Parameters for Parameters {
const X: &'static [u64] = &[0xd201000000010000];
const X_IS_NEGATIVE: bool = true;
const TWIST_TYPE: TwistType = TwistType::M;
type Fp = Fq;
type Fp2Params = Fq2Parameters;
type Fp6Params = Fq6Parameters;
type Fp12Params = Fq12Parameters;
type G1Parameters = self::g1::Parameters;
type G2Parameters = self::g2::Parameters;
}

+ 116
- 0
bls12_381/src/curves/tests.rs

@ -0,0 +1,116 @@
#![allow(unused_imports)]
use ark_ec::{models::SWModelParameters, AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ff::{
fields::{Field, FpParameters, PrimeField, SquareRootField},
test_rng, One, Zero,
};
use ark_serialize::CanonicalSerialize;
use core::ops::{AddAssign, MulAssign};
use rand::Rng;
use crate::{g1, g2, Bls12_381, Fq, Fq12, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
use ark_curve_tests::{curves::*, groups::*};
#[test]
fn test_g1_projective_curve() {
curve_tests::<G1Projective>();
sw_tests::<g1::Parameters>();
}
#[test]
fn test_g1_projective_group() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G1Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g1_generator() {
let generator = G1Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g2_projective_curve() {
curve_tests::<G2Projective>();
sw_tests::<g2::Parameters>();
}
#[test]
fn test_g2_projective_group() {
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g2_generator() {
let generator = G2Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_bilinearity() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G2Projective = rng.gen();
let s: Fr = rng.gen();
let mut sa = a;
sa.mul_assign(s);
let mut sb = b;
sb.mul_assign(s);
let ans1 = Bls12_381::pairing(sa, b);
let ans2 = Bls12_381::pairing(a, sb);
let ans3 = Bls12_381::pairing(a, b).pow(s.into_repr());
assert_eq!(ans1, ans2);
assert_eq!(ans2, ans3);
assert_ne!(ans1, Fq12::one());
assert_ne!(ans2, Fq12::one());
assert_ne!(ans3, Fq12::one());
assert_eq!(ans1.pow(Fr::characteristic()), Fq12::one());
assert_eq!(ans2.pow(Fr::characteristic()), Fq12::one());
assert_eq!(ans3.pow(Fr::characteristic()), Fq12::one());
}
#[test]
fn test_g1_generator_raw() {
let mut x = Fq::zero();
let mut i = 0;
loop {
// y^2 = x^3 + b
let mut rhs = x;
rhs.square_in_place();
rhs.mul_assign(&x);
rhs.add_assign(&g1::Parameters::COEFF_B);
if let Some(y) = rhs.sqrt() {
let p = G1Affine::new(x, if y < -y { y } else { -y }, false);
assert!(!p.is_in_correct_subgroup_assuming_on_curve());
let g1 = p.scale_by_cofactor();
if !g1.is_zero() {
assert_eq!(i, 4);
let g1 = G1Affine::from(g1);
assert!(g1.is_in_correct_subgroup_assuming_on_curve());
assert_eq!(g1, G1Affine::prime_subgroup_generator());
break;
}
}
i += 1;
x.add_assign(&Fq::one());
}
}

+ 112
- 0
bls12_381/src/fields/fq.rs

@ -0,0 +1,112 @@
use ark_ff::{
biginteger::BigInteger384 as BigInteger,
field_new,
fields::{FftParameters, Fp384, Fp384Parameters, FpParameters},
};
pub type Fq = Fp384<FqParameters>;
pub struct FqParameters;
impl Fp384Parameters for FqParameters {}
impl FftParameters for FqParameters {
type BigInt = BigInteger;
const TWO_ADICITY: u32 = 1;
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
0x43f5fffffffcaaae,
0x32b7fff2ed47fffd,
0x7e83a49a2e99d69,
0xeca8f3318332bb7a,
0xef148d1ea0f4c069,
0x40ab3263eff0206,
]);
}
impl FpParameters for FqParameters {
/// MODULUS = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
0xb9feffffffffaaab,
0x1eabfffeb153ffff,
0x6730d2a0f6b0f624,
0x64774b84f38512bf,
0x4b1ba7b6434bacd7,
0x1a0111ea397fe69a,
]);
const MODULUS_BITS: u32 = 381;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
const REPR_SHAVE_BITS: u32 = 3;
#[rustfmt::skip]
const R: BigInteger = BigInteger([
0x760900000002fffd,
0xebf4000bc40c0002,
0x5f48985753c758ba,
0x77ce585370525745,
0x5c071a97a256ec6d,
0x15f65ec3fa80e493,
]);
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
0xf4df1f341c341746,
0xa76e6a609d104f1,
0x8de5476c4c95b6d5,
0x67eb88a9939d83c0,
0x9a793e85b519952d,
0x11988fe592cae3aa,
]);
const INV: u64 = 0x89f3fffcfffcfffd;
// GENERATOR = 2
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
0x321300000006554f,
0xb93c0018d6c40005,
0x57605e0db0ddbb51,
0x8b256521ed1f9bcb,
0x6cf28d7901622c03,
0x11ebab9dbb81e28c,
]);
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0xdcff7fffffffd555,
0xf55ffff58a9ffff,
0xb39869507b587b12,
0xb23ba5c279c2895f,
0x258dd3db21a5d66b,
0xd0088f51cbff34d,
]);
// T and T_MINUS_ONE_DIV_TWO, where MODULUS - 1 = 2^S * T
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0xdcff7fffffffd555,
0xf55ffff58a9ffff,
0xb39869507b587b12,
0xb23ba5c279c2895f,
0x258dd3db21a5d66b,
0xd0088f51cbff34d,
]);
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0xee7fbfffffffeaaa,
0x7aaffffac54ffff,
0xd9cc34a83dac3d89,
0xd91dd2e13ce144af,
0x92c6e9ed90d2eb35,
0x680447a8e5ff9a6,
]);
}
pub const FQ_ONE: Fq = field_new!(Fq, FqParameters::R);
pub const FQ_ZERO: Fq = field_new!(Fq, BigInteger([0, 0, 0, 0, 0, 0]));

+ 193
- 0
bls12_381/src/fields/fq12.rs

@ -0,0 +1,193 @@
use crate::*;
use ark_ff::{biginteger::BigInteger384, field_new, fields::*};
pub type Fq12 = Fp12<Fq12Parameters>;
#[derive(Clone, Copy)]
pub struct Fq12Parameters;
impl Fp12Parameters for Fq12Parameters {
type Fp6Params = Fq6Parameters;
const NONRESIDUE: Fq6 = field_new!(Fq6, FQ2_ZERO, FQ2_ONE, FQ2_ZERO);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP12_C1: &'static [Fq2] = &[
// Fq2(u + 1)**(((q^0) - 1) / 6)
FQ2_ONE,
// Fq2(u + 1)**(((q^1) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x7089552b319d465,
0xc6695f92b50a8313,
0x97e83cccd117228f,
0xa35baecab2dc29ee,
0x1ce393ea5daace4d,
0x8f2220fb0fb66eb,
])),
field_new!(Fq, BigInteger384([
0xb2f66aad4ce5d646,
0x5842a06bfc497cec,
0xcf4895d42599d394,
0xc11b9cba40a8e8d0,
0x2e3813cbe5a0de89,
0x110eefda88847faf,
])),
),
// Fq2(u + 1)**(((q^2) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xecfb361b798dba3a,
0xc100ddb891865a2c,
0xec08ff1232bda8e,
0xd5c13cc6f1ca4721,
0x47222a47bf7b5c04,
0x110f184e51c5f59,
])),
FQ_ZERO,
),
// Fq2(u + 1)**(((q^3) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x3e2f585da55c9ad1,
0x4294213d86c18183,
0x382844c88b623732,
0x92ad2afd19103e18,
0x1d794e4fac7cf0b9,
0xbd592fc7d825ec8,
])),
field_new!(Fq, BigInteger384([
0x7bcfa7a25aa30fda,
0xdc17dec12a927e7c,
0x2f088dd86b4ebef1,
0xd1ca2087da74d4a7,
0x2da2596696cebc1d,
0xe2b7eedbbfd87d2,
])),
),
// Fq2(u + 1)**(((q^4) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x30f1361b798a64e8,
0xf3b8ddab7ece5a2a,
0x16a8ca3ac61577f7,
0xc26a2ff874fd029b,
0x3636b76660701c6e,
0x51ba4ab241b6160,
])),
FQ_ZERO,
),
// Fq2(u + 1)**(((q^5) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x3726c30af242c66c,
0x7c2ac1aad1b6fe70,
0xa04007fbba4b14a2,
0xef517c3266341429,
0x95ba654ed2226b,
0x2e370eccc86f7dd,
])),
field_new!(Fq, BigInteger384([
0x82d83cf50dbce43f,
0xa2813e53df9d018f,
0xc6f0caa53c65e181,
0x7525cf528d50fe95,
0x4a85ed50f4798a6b,
0x171da0fd6cf8eebd,
])),
),
// Fq2(u + 1)**(((q^6) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x43f5fffffffcaaae,
0x32b7fff2ed47fffd,
0x7e83a49a2e99d69,
0xeca8f3318332bb7a,
0xef148d1ea0f4c069,
0x40ab3263eff0206,
])),
FQ_ZERO,
),
// Fq2(u + 1)**(((q^7) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xb2f66aad4ce5d646,
0x5842a06bfc497cec,
0xcf4895d42599d394,
0xc11b9cba40a8e8d0,
0x2e3813cbe5a0de89,
0x110eefda88847faf,
])),
field_new!(Fq, BigInteger384([
0x7089552b319d465,
0xc6695f92b50a8313,
0x97e83cccd117228f,
0xa35baecab2dc29ee,
0x1ce393ea5daace4d,
0x8f2220fb0fb66eb,
])),
),
// Fq2(u + 1)**(((q^8) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xcd03c9e48671f071,
0x5dab22461fcda5d2,
0x587042afd3851b95,
0x8eb60ebe01bacb9e,
0x3f97d6e83d050d2,
0x18f0206554638741,
])),
FQ_ZERO,
),
// Fq2(u + 1)**(((q^9) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x7bcfa7a25aa30fda,
0xdc17dec12a927e7c,
0x2f088dd86b4ebef1,
0xd1ca2087da74d4a7,
0x2da2596696cebc1d,
0xe2b7eedbbfd87d2,
])),
field_new!(Fq, BigInteger384([
0x3e2f585da55c9ad1,
0x4294213d86c18183,
0x382844c88b623732,
0x92ad2afd19103e18,
0x1d794e4fac7cf0b9,
0xbd592fc7d825ec8,
])),
),
// Fq2(u + 1)**(((q^10) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x890dc9e4867545c3,
0x2af322533285a5d5,
0x50880866309b7e2c,
0xa20d1b8c7e881024,
0x14e4f04fe2db9068,
0x14e56d3f1564853a,
])),
FQ_ZERO,
),
// Fq2(u + 1)**(((q^11) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x82d83cf50dbce43f,
0xa2813e53df9d018f,
0xc6f0caa53c65e181,
0x7525cf528d50fe95,
0x4a85ed50f4798a6b,
0x171da0fd6cf8eebd,
])),
field_new!(Fq, BigInteger384([
0x3726c30af242c66c,
0x7c2ac1aad1b6fe70,
0xa04007fbba4b14a2,
0xef517c3266341429,
0x95ba654ed2226b,
0x2e370eccc86f7dd,
])),
),
];
}

+ 73
- 0
bls12_381/src/fields/fq2.rs

@ -0,0 +1,73 @@
use crate::*;
use ark_ff::{biginteger::BigInteger384 as BigInteger, field_new, fields::*};
pub type Fq2 = Fp2<Fq2Parameters>;
pub struct Fq2Parameters;
impl Fp2Parameters for Fq2Parameters {
type Fp = Fq;
/// NONRESIDUE = -1
#[rustfmt::skip]
const NONRESIDUE: Fq = field_new!(Fq, BigInteger([
0x43f5fffffffcaaae,
0x32b7fff2ed47fffd,
0x7e83a49a2e99d69,
0xeca8f3318332bb7a,
0xef148d1ea0f4c069,
0x40ab3263eff0206,
]));
/// QUADRATIC_NONRESIDUE = (U + 1)
#[rustfmt::skip]
const QUADRATIC_NONRESIDUE: (Fq, Fq) = (
field_new!(Fq, BigInteger([
0x760900000002fffd,
0xebf4000bc40c0002,
0x5f48985753c758ba,
0x77ce585370525745,
0x5c071a97a256ec6d,
0x15f65ec3fa80e493,
])),
field_new!(Fq, BigInteger([
0x760900000002fffd,
0xebf4000bc40c0002,
0x5f48985753c758ba,
0x77ce585370525745,
0x5c071a97a256ec6d,
0x15f65ec3fa80e493,
])),
);
/// Coefficients for the Frobenius automorphism.
#[rustfmt::skip]
const FROBENIUS_COEFF_FP2_C1: &'static [Fq] = &[
// Fq(-1)**(((q^0) - 1) / 2)
field_new!(Fq, BigInteger([
0x760900000002fffd,
0xebf4000bc40c0002,
0x5f48985753c758ba,
0x77ce585370525745,
0x5c071a97a256ec6d,
0x15f65ec3fa80e493,
])),
// Fq(-1)**(((q^1) - 1) / 2)
field_new!(Fq, BigInteger([
0x43f5fffffffcaaae,
0x32b7fff2ed47fffd,
0x7e83a49a2e99d69,
0xeca8f3318332bb7a,
0xef148d1ea0f4c069,
0x40ab3263eff0206,
])),
];
#[inline(always)]
fn mul_fp_by_nonresidue(fp: &Self::Fp) -> Self::Fp {
-(*fp)
}
}
pub const FQ2_ZERO: Fq2 = field_new!(Fq2, FQ_ZERO, FQ_ZERO);
pub const FQ2_ONE: Fq2 = field_new!(Fq2, FQ_ONE, FQ_ZERO);

+ 194
- 0
bls12_381/src/fields/fq6.rs

@ -0,0 +1,194 @@
use crate::*;
use ark_ff::{biginteger::BigInteger384, field_new, fields::*};
pub type Fq6 = Fp6<Fq6Parameters>;
#[derive(Clone, Copy)]
pub struct Fq6Parameters;
impl Fp6Parameters for Fq6Parameters {
type Fp2Params = Fq2Parameters;
/// NONRESIDUE = (U + 1)
#[rustfmt::skip]
const NONRESIDUE: Fq2 = field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x760900000002fffd,
0xebf4000bc40c0002,
0x5f48985753c758ba,
0x77ce585370525745,
0x5c071a97a256ec6d,
0x15f65ec3fa80e493,
])),
field_new!(Fq, BigInteger384([
0x760900000002fffd,
0xebf4000bc40c0002,
0x5f48985753c758ba,
0x77ce585370525745,
0x5c071a97a256ec6d,
0x15f65ec3fa80e493,
])),
);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C1: &'static [Fq2] = &[
// Fq2(u + 1)**(((q^0) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x760900000002fffd,
0xebf4000bc40c0002,
0x5f48985753c758ba,
0x77ce585370525745,
0x5c071a97a256ec6d,
0x15f65ec3fa80e493,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fq2(u + 1)**(((q^1) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
field_new!(Fq, BigInteger384([
0xcd03c9e48671f071,
0x5dab22461fcda5d2,
0x587042afd3851b95,
0x8eb60ebe01bacb9e,
0x3f97d6e83d050d2,
0x18f0206554638741,
])),
),
// Fq2(u + 1)**(((q^2) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x30f1361b798a64e8,
0xf3b8ddab7ece5a2a,
0x16a8ca3ac61577f7,
0xc26a2ff874fd029b,
0x3636b76660701c6e,
0x51ba4ab241b6160,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fq2(u + 1)**(((q^3) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
field_new!(Fq, BigInteger384([
0x760900000002fffd,
0xebf4000bc40c0002,
0x5f48985753c758ba,
0x77ce585370525745,
0x5c071a97a256ec6d,
0x15f65ec3fa80e493,
])),
),
// Fq2(u + 1)**(((q^4) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xcd03c9e48671f071,
0x5dab22461fcda5d2,
0x587042afd3851b95,
0x8eb60ebe01bacb9e,
0x3f97d6e83d050d2,
0x18f0206554638741,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fq2(u + 1)**(((q^5) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
field_new!(Fq, BigInteger384([
0x30f1361b798a64e8,
0xf3b8ddab7ece5a2a,
0x16a8ca3ac61577f7,
0xc26a2ff874fd029b,
0x3636b76660701c6e,
0x51ba4ab241b6160,
])),
),
];
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C2: &'static [Fq2] = &[
// Fq2(u + 1)**(((2q^0) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x760900000002fffd,
0xebf4000bc40c0002,
0x5f48985753c758ba,
0x77ce585370525745,
0x5c071a97a256ec6d,
0x15f65ec3fa80e493,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fq2(u + 1)**(((2q^1) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x890dc9e4867545c3,
0x2af322533285a5d5,
0x50880866309b7e2c,
0xa20d1b8c7e881024,
0x14e4f04fe2db9068,
0x14e56d3f1564853a,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fq2(u + 1)**(((2q^2) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xcd03c9e48671f071,
0x5dab22461fcda5d2,
0x587042afd3851b95,
0x8eb60ebe01bacb9e,
0x3f97d6e83d050d2,
0x18f0206554638741,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fq2(u + 1)**(((2q^3) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x43f5fffffffcaaae,
0x32b7fff2ed47fffd,
0x7e83a49a2e99d69,
0xeca8f3318332bb7a,
0xef148d1ea0f4c069,
0x40ab3263eff0206,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fq2(u + 1)**(((2q^4) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0x30f1361b798a64e8,
0xf3b8ddab7ece5a2a,
0x16a8ca3ac61577f7,
0xc26a2ff874fd029b,
0x3636b76660701c6e,
0x51ba4ab241b6160,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
// Fq2(u + 1)**(((2q^5) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger384([
0xecfb361b798dba3a,
0xc100ddb891865a2c,
0xec08ff1232bda8e,
0xd5c13cc6f1ca4721,
0x47222a47bf7b5c04,
0x110f184e51c5f59,
])),
field_new!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
),
];
/// Multiply this element by the quadratic nonresidue 1 + u.
/// Make this generic.
fn mul_fp2_by_nonresidue(fe: &Fq2) -> Fq2 {
let mut copy = *fe;
let t0 = copy.c0;
copy.c0 -= &fe.c1;
copy.c1 += &t0;
copy
}
}

+ 96
- 0
bls12_381/src/fields/fr.rs

@ -0,0 +1,96 @@
use ark_ff::{
biginteger::BigInteger256 as BigInteger,
fields::{FftParameters, Fp256, Fp256Parameters, FpParameters},
};
pub type Fr = Fp256<FrParameters>;
pub struct FrParameters;
impl Fp256Parameters for FrParameters {}
impl FftParameters for FrParameters {
type BigInt = BigInteger;
const TWO_ADICITY: u32 = 32;
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
0xb9b58d8c5f0e466a,
0x5b1b4c801819d7ec,
0xaf53ae352a31e64,
0x5bf3adda19e9b27b,
]);
}
impl FpParameters for FrParameters {
/// MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
0xffffffff00000001,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48,
]);
const MODULUS_BITS: u32 = 255;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
const REPR_SHAVE_BITS: u32 = 1;
#[rustfmt::skip]
const R: BigInteger = BigInteger([
0x1fffffffe,
0x5884b7fa00034802,
0x998c4fefecbc4ff5,
0x1824b159acc5056f,
]);
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
0xc999e990f3f29c6d,
0x2b6cedcb87925c23,
0x5d314967254398f,
0x748d9d99f59ff11,
]);
const INV: u64 = 0xfffffffeffffffff;
//
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
0xefffffff1,
0x17e363d300189c0f,
0xff9c57876f8457b0,
0x351332208fc5a8c4,
]);
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x7fffffff80000000,
0xa9ded2017fff2dff,
0x199cec0404d0ec02,
0x39f6d3a994cebea4,
]);
// T and T_MINUS_ONE_DIV_TWO, where MODULUS - 1 = 2^S * T
// T = (MODULUS - 1) / 2^S =
// 12208678567578594777604504606729831043093128246378069236549469339647
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0xfffe5bfeffffffff,
0x9a1d80553bda402,
0x299d7d483339d808,
0x73eda753,
]);
// (T - 1) / 2 =
// 6104339283789297388802252303364915521546564123189034618274734669823
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x7fff2dff7fffffff,
0x4d0ec02a9ded201,
0x94cebea4199cec04,
0x39f6d3a9,
]);
}

+ 27
- 0
bls12_381/src/fields/mod.rs

@ -0,0 +1,27 @@
#[cfg(feature = "scalar_field")]
pub mod fr;
#[cfg(feature = "scalar_field")]
pub use self::fr::*;
#[cfg(feature = "curve")]
pub mod fq;
#[cfg(feature = "curve")]
pub use self::fq::*;
#[cfg(feature = "curve")]
pub mod fq2;
#[cfg(feature = "curve")]
pub use self::fq2::*;
#[cfg(feature = "curve")]
pub mod fq6;
#[cfg(feature = "curve")]
pub use self::fq6::*;
#[cfg(feature = "curve")]
pub mod fq12;
#[cfg(feature = "curve")]
pub use self::fq12::*;
#[cfg(all(feature = "curve", feature = "std", test))]
mod tests;

+ 2322
- 0
bls12_381/src/fields/tests.rs
File diff suppressed because it is too large
View File


+ 32
- 0
bls12_381/src/lib.rs

@ -0,0 +1,32 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(
warnings,
unused,
future_incompatible,
nonstandard_style,
rust_2018_idioms
)]
#![forbid(unsafe_code)]
//! This library implements the BLS12_381 curve generated by [Sean Bowe](https://electriccoin.co/blog/new-snark-curve/).
//! The name denotes that it is a Barreto--Lynn--Scott curve of embedding degree 12,
//! defined over a 381-bit (prime) field.
//! This curve was intended to replace the BN254 curve to provide a higher security
//! level without incurring a large performance overhead.
//!
//!
//! Curve information:
//! * Base field: q = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
//! * Scalar field: r = 52435875175126190479447740508185965837690552500527637822603658699938581184513
//! * valuation(q - 1, 2) = 1
//! * valuation(r - 1, 2) = 32
//! * G1 curve equation: y^2 = x^3 + 4
//! * G2 curve equation: y^2 = x^3 + Fq2(4, 4)
#[cfg(feature = "curve")]
mod curves;
mod fields;
#[cfg(feature = "curve")]
pub use curves::*;
pub use fields::*;

+ 31
- 0
bn254/Cargo.toml

@ -0,0 +1,31 @@
[package]
name = "ark-bn254"
version = "0.1.0"
authors = [ "arkworks contributors" ]
description = "The BN254 pairing-friendly elliptic curve"
homepage = "https://arworks.rs"
repository = "https://github.com/arkworks/algebra"
documentation = "https://docs.rs/ark-bn254/"
keywords = ["cryptography", "finite fields", "elliptic curves" ]
categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0"
edition = "2018"
[dependencies]
ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false }
[dev-dependencies]
ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-curve-tests = { path = "../curve-tests", default-features = false }
rand = { version = "0.7", default-features = false }
rand_xorshift = "0.2"
[features]
default = [ "curve" ]
std = [ "ark-std/std", "ark-ff/std", "ark-ec/std" ]
curve = [ "scalar_field" ]
scalar_field = []

+ 1
- 0
bn254/LICENSE-APACHE

@ -0,0 +1 @@
../LICENSE-APACHE

+ 1
- 0
bn254/LICENSE-MIT

@ -0,0 +1 @@
../LICENSE-MIT

+ 67
- 0
bn254/src/curves/g1.rs

@ -0,0 +1,67 @@
use ark_ec::models::{ModelParameters, SWModelParameters};
use ark_ff::{biginteger::BigInteger256, field_new, Zero};
use crate::{Fq, Fr};
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
impl ModelParameters for Parameters {
type BaseField = Fq;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = 0
const COEFF_A: Fq = field_new!(Fq, BigInteger256([0x0, 0x0, 0x0, 0x0]));
/// COEFF_B = 3
#[rustfmt::skip]
const COEFF_B: Fq = field_new!(Fq, BigInteger256([
0x7a17caa950ad28d7,
0x1f6ac17ae15521b9,
0x334bea4e696bd284,
0x2a1f6744ce179d8e,
]));
/// COFACTOR = 1
const COFACTOR: &'static [u64] = &[0x1];
/// COFACTOR_INV = COFACTOR^{-1} mod r = 1
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, BigInteger256([
0xac96341c4ffffffb,
0x36fc76959f60cd29,
0x666ea36f7879462e,
0xe0a77c19a07df2f,
]));
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G1_GENERATOR_X, G1_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
}
}
/// G1_GENERATOR_X =
/// 1
#[rustfmt::skip]
pub const G1_GENERATOR_X: Fq = field_new!(Fq, BigInteger256([
0xd35d438dc58f0d9d,
0x0a78eb28f5c70b3d,
0x666ea36f7879462c,
0x0e0a77c19a07df2f,
]));
/// G1_GENERATOR_Y =
/// 2
#[rustfmt::skip]
pub const G1_GENERATOR_Y: Fq = field_new!(Fq, BigInteger256([
0xa6ba871b8b1e1b3a,
0x14f1d651eb8e167b,
0xccdd46def0f28c58,
0x1c14ef83340fbe5e,
]));

+ 112
- 0
bn254/src/curves/g2.rs

@ -0,0 +1,112 @@
use ark_ec::models::{ModelParameters, SWModelParameters};
use ark_ff::{biginteger::BigInteger256, field_new, Zero};
use crate::{g1, Fq, Fq2, Fr};
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
impl ModelParameters for Parameters {
type BaseField = Fq2;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = [0, 0]
#[rustfmt::skip]
const COEFF_A: Fq2 = field_new!(Fq2,
g1::Parameters::COEFF_A,
g1::Parameters::COEFF_A,
);
/// COEFF_B = 3/(u+9)
/// = (19485874751759354771024239261021720505790618469301721065564631296452457478373, 266929791119991161246907387137283842545076965332900288569378510910307636690)
#[rustfmt::skip]
const COEFF_B: Fq2 = field_new!(Fq2,
field_new!(Fq, BigInteger256([
0x3bf938e377b802a8,
0x020b1b273633535d,
0x26b7edf049755260,
0x2514c6324384a86d,
])),
field_new!(Fq, BigInteger256([
0x38e7ecccd1dcff67,
0x65f0b37d93ce0d3e,
0xd749d0dd22ac00aa,
0x0141b9ce4a688d4d,
])),
);
/// COFACTOR = (36 * X^4) + (36 * X^3) + (30 * X^2) + 6*X + 1
/// = 21888242871839275222246405745257275088844257914179612981679871602714643921549
#[rustfmt::skip]
const COFACTOR: &'static [u64] = &[
0x345f2299c0f9fa8d,
0x06ceecda572a2489,
0xb85045b68181585e,
0x30644e72e131a029,
];
/// COFACTOR_INV = COFACTOR^{-1} mod r
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, BigInteger256([
0x7fff17d53ff2895e,
0xd0617390cf7919e5,
0xb9af426b22d0eb61,
0x270485e31bd72a4d,
]));
/// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G2_GENERATOR_X, G2_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
}
}
#[rustfmt::skip]
pub const G2_GENERATOR_X: Fq2 = field_new!(Fq2, G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
#[rustfmt::skip]
pub const G2_GENERATOR_Y: Fq2 = field_new!(Fq2, G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
/// G2_GENERATOR_X_C0 =
/// 10857046999023057135944570762232829481370756359578518086990519993285655852781
#[rustfmt::skip]
pub const G2_GENERATOR_X_C0: Fq = field_new!(Fq, BigInteger256([
0x8e83b5d102bc2026,
0xdceb1935497b0172,
0xfbb8264797811adf,
0x19573841af96503b,
]));
/// G2_GENERATOR_X_C1 =
/// 11559732032986387107991004021392285783925812861821192530917403151452391805634
#[rustfmt::skip]
pub const G2_GENERATOR_X_C1: Fq = field_new!(Fq, BigInteger256([
0xafb4737da84c6140,
0x6043dd5a5802d8c4,
0x09e950fc52a02f86,
0x14fef0833aea7b6b,
]));
/// G2_GENERATOR_Y_C0 =
/// 8495653923123431417604973247489272438418190587263600148770280649306958101930
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C0: Fq = field_new!(Fq, BigInteger256([
0x619dfa9d886be9f6,
0xfe7fd297f59e9b78,
0xff9e1a62231b7dfe,
0x28fd7eebae9e4206,
]));
/// G2_GENERATOR_Y_C1 =
/// 4082367875863433681332203403145435568316851327593401208105741076214120093531
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C1: Fq = field_new!(Fq, BigInteger256([
0x64095b56c71856ee,
0xdc57f922327d3cbb,
0x55f935be33351076,
0x0da4a0e693fd6482,
]));

+ 82
- 0
bn254/src/curves/mod.rs

@ -0,0 +1,82 @@
use crate::*;
use ark_ec::{
bn,
bn::{Bn, BnParameters, TwistType},
};
use ark_ff::{biginteger::BigInteger256, field_new};
pub mod g1;
pub mod g2;
#[cfg(test)]
mod tests;
pub struct Parameters;
impl BnParameters for Parameters {
const X: &'static [u64] = &[4965661367192848881];
/// `x` is positive.
const X_IS_NEGATIVE: bool = false;
const ATE_LOOP_COUNT: &'static [i8] = &[
0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 1, -1, 0, 0, 1, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0, -1, 0, 0, 0,
0, 1, 1, 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, 0, 0, 1, 1, 0,
-1, 0, 0, 1, 0, 1, 1,
];
/// `ate_loop_count` is positive.
const ATE_LOOP_COUNT_IS_NEGATIVE: bool = false;
const TWIST_MUL_BY_Q_X: Fq2 = field_new!(
Fq2,
field_new!(
Fq,
BigInteger256([
0xb5773b104563ab30,
0x347f91c8a9aa6454,
0x7a007127242e0991,
0x1956bcd8118214ec,
])
),
field_new!(
Fq,
BigInteger256([
0x6e849f1ea0aa4757,
0xaa1c7b6d89f89141,
0xb6e713cdfae0ca3a,
0x26694fbb4e82ebc3,
])
),
);
const TWIST_MUL_BY_Q_Y: Fq2 = field_new!(
Fq2,
field_new!(
Fq,
BigInteger256([
0xe4bbdd0c2936b629,
0xbb30f162e133bacb,
0x31a9d1b6f9645366,
0x253570bea500f8dd,
])
),
field_new!(
Fq,
BigInteger256([
0xa1d77ce45ffe77c7,
0x07affd117826d1db,
0x6d16bd27bb7edc6b,
0x2c87200285defecc,
])
),
);
const TWIST_TYPE: TwistType = TwistType::D;
type Fp = Fq;
type Fp2Params = Fq2Parameters;
type Fp6Params = Fq6Parameters;
type Fp12Params = Fq12Parameters;
type G1Parameters = g1::Parameters;
type G2Parameters = g2::Parameters;
}
pub type Bn254 = Bn<Parameters>;
pub type G1Affine = bn::G1Affine<Parameters>;
pub type G1Projective = bn::G1Projective<Parameters>;
pub type G2Affine = bn::G2Affine<Parameters>;
pub type G2Projective = bn::G2Projective<Parameters>;

+ 85
- 0
bn254/src/curves/tests.rs

@ -0,0 +1,85 @@
#![allow(unused_imports)]
use ark_ec::{models::SWModelParameters, AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ff::{
fields::{Field, FpParameters, PrimeField, SquareRootField},
test_rng, One, Zero,
};
use ark_serialize::CanonicalSerialize;
use core::ops::{AddAssign, MulAssign};
use rand::Rng;
use crate::{g1, g2, Bn254, Fq, Fq12, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
use ark_curve_tests::{curves::*, groups::*};
#[test]
fn test_g1_projective_curve() {
curve_tests::<G1Projective>();
sw_tests::<g1::Parameters>();
}
#[test]
fn test_g1_projective_group() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G1Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g1_generator() {
let generator = G1Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g2_projective_curve() {
curve_tests::<G2Projective>();
sw_tests::<g2::Parameters>();
}
#[test]
fn test_g2_projective_group() {
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g2_generator() {
let generator = G2Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_bilinearity() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G2Projective = rng.gen();
let s: Fr = rng.gen();
let mut sa = a;
sa.mul_assign(s);
let mut sb = b;
sb.mul_assign(s);
let ans1 = Bn254::pairing(sa, b);
let ans2 = Bn254::pairing(a, sb);
let ans3 = Bn254::pairing(a, b).pow(s.into_repr());
assert_eq!(ans1, ans2);
assert_eq!(ans2, ans3);
assert_ne!(ans1, Fq12::one());
assert_ne!(ans2, Fq12::one());
assert_ne!(ans3, Fq12::one());
assert_eq!(ans1.pow(Fr::characteristic()), Fq12::one());
assert_eq!(ans2.pow(Fr::characteristic()), Fq12::one());
assert_eq!(ans3.pow(Fr::characteristic()), Fq12::one());
}

+ 96
- 0
bn254/src/fields/fq.rs

@ -0,0 +1,96 @@
use ark_ff::{biginteger::BigInteger256 as BigInteger, field_new, fields::*};
pub type Fq = Fp256<FqParameters>;
pub struct FqParameters;
impl Fp256Parameters for FqParameters {}
impl FftParameters for FqParameters {
type BigInt = BigInteger;
const TWO_ADICITY: u32 = 1;
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
0x68c3488912edefaa,
0x8d087f6872aabf4f,
0x51e1a24709081231,
0x2259d6b14729c0fa,
]);
}
impl FpParameters for FqParameters {
/// MODULUS = 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
0x3c208c16d87cfd47,
0x97816a916871ca8d,
0xb85045b68181585d,
0x30644e72e131a029,
]);
const MODULUS_BITS: u32 = 254;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
const REPR_SHAVE_BITS: u32 = 2;
#[rustfmt::skip]
const R: BigInteger = BigInteger([
0xd35d438dc58f0d9d,
0x0a78eb28f5c70b3d,
0x666ea36f7879462c,
0xe0a77c19a07df2f,
]);
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
0xf32cfc5b538afa89,
0xb5e71911d44501fb,
0x47ab1eff0a417ff6,
0x6d89f71cab8351f,
]);
const INV: u64 = 9786893198990664585u64;
// GENERATOR = 3
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
0x7a17caa950ad28d7,
0x1f6ac17ae15521b9,
0x334bea4e696bd284,
0x2a1f6744ce179d8e,
]);
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x9e10460b6c3e7ea3,
0xcbc0b548b438e546,
0xdc2822db40c0ac2e,
0x183227397098d014,
]);
// T and T_MINUS_ONE_DIV_TWO, where MODULUS - 1 = 2^S * T
// T = (MODULUS - 1) // 2^S =
// 10944121435919637611123202872628637544348155578648911831344518947322613104291
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0x9e10460b6c3e7ea3,
0xcbc0b548b438e546,
0xdc2822db40c0ac2e,
0x183227397098d014,
]);
// (T - 1) // 2 =
// 1837921289030710838195067919506396475074392872918698035817074744121558668640693829665401097909504529
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x4f082305b61f3f51,
0x65e05aa45a1c72a3,
0x6e14116da0605617,
0xc19139cb84c680a,
]);
}
pub const FQ_ONE: Fq = field_new!(Fq, FqParameters::R);
pub const FQ_ZERO: Fq = field_new!(Fq, BigInteger([0, 0, 0, 0]));

+ 159
- 0
bn254/src/fields/fq12.rs

@ -0,0 +1,159 @@
use super::*;
use ark_ff::{biginteger::BigInteger256, field_new, fields::*};
pub type Fq12 = Fp12<Fq12Parameters>;
#[derive(Clone, Copy)]
pub struct Fq12Parameters;
impl Fp12Parameters for Fq12Parameters {
type Fp6Params = Fq6Parameters;
const NONRESIDUE: Fq6 = field_new!(Fq6, FQ2_ZERO, FQ2_ONE, FQ2_ZERO);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP12_C1: &'static [Fq2] = &[
// Fp2::NONRESIDUE^(((q^0) - 1) / 6)
FQ2_ONE,
// Fp2::NONRESIDUE^(((q^1) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0xaf9ba69633144907,
0xca6b1d7387afb78a,
0x11bded5ef08a2087,
0x02f34d751a1f3a7c,
])),
field_new!(Fq, BigInteger256([
0xa222ae234c492d72,
0xd00f02a4565de15b,
0xdc2ff3a253dfc926,
0x10a75716b3899551,
])),
),
// Fp2::NONRESIDUE^(((q^2) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0xca8d800500fa1bf2,
0xf0c5d61468b39769,
0x0e201271ad0d4418,
0x04290f65bad856e6,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^3) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0x365316184e46d97d,
0x0af7129ed4c96d9f,
0x659da72fca1009b5,
0x08116d8983a20d23,
])),
field_new!(Fq, BigInteger256([
0xb1df4af7c39c1939,
0x3d9f02878a73bf7f,
0x9b2220928caf0ae0,
0x26684515eff054a6,
])),
),
// Fp2::NONRESIDUE^(((q^4) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0x3350c88e13e80b9c,
0x7dce557cdb5e56b9,
0x6001b4b8b615564a,
0x2682e617020217e0,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^5) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0x86b76f821b329076,
0x408bf52b4d19b614,
0x53dfb9d0d985e92d,
0x051e20146982d2a7,
])),
field_new!(Fq, BigInteger256([
0x0fbc9cd47752ebc7,
0x6d8fffe33415de24,
0xbef22cf038cf41b9,
0x15c0edff3c66bf54,
])),
),
// Fp2::NONRESIDUE^(((q^6) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0x68c3488912edefaa,
0x8d087f6872aabf4f,
0x51e1a24709081231,
0x2259d6b14729c0fa,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^7) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0x8c84e580a568b440,
0xcd164d1de0c21302,
0xa692585790f737d5,
0x2d7100fdc71265ad,
])),
field_new!(Fq, BigInteger256([
0x99fdddf38c33cfd5,
0xc77267ed1213e931,
0xdc2052142da18f36,
0x1fbcf75c2da80ad7,
])),
),
// Fp2::NONRESIDUE^(((q^8) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0x71930c11d782e155,
0xa6bb947cffbe3323,
0xaa303344d4741444,
0x2c3b3f0d26594943,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^9) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0x05cd75fe8a3623ca,
0x8c8a57f293a85cee,
0x52b29e86b7714ea8,
0x2852e0e95d8f9306,
])),
field_new!(Fq, BigInteger256([
0x8a41411f14e0e40e,
0x59e26809ddfe0b0d,
0x1d2e2523f4d24d7d,
0x09fc095cf1414b83,
])),
),
// Fp2::NONRESIDUE^(((q^10) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0x08cfc388c494f1ab,
0x19b315148d1373d4,
0x584e90fdcb6c0213,
0x09e1685bdf2f8849,
])),
FQ_ZERO,
),
// Fp2::NONRESIDUE^(((q^11) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0xb5691c94bd4a6cd1,
0x56f575661b581478,
0x64708be5a7fb6f30,
0x2b462e5e77aecd82,
])),
field_new!(Fq, BigInteger256([
0x2c63ef42612a1180,
0x29f16aae345bec69,
0xf95e18c648b216a4,
0x1aa36073a4cae0d4,
])),
),
];
}

+ 63
- 0
bn254/src/fields/fq2.rs

@ -0,0 +1,63 @@
use super::*;
use ark_ff::{biginteger::BigInteger256 as BigInteger, field_new, fields::*};
pub type Fq2 = Fp2<Fq2Parameters>;
pub struct Fq2Parameters;
impl Fp2Parameters for Fq2Parameters {
type Fp = Fq;
/// NONRESIDUE = -1
#[rustfmt::skip]
const NONRESIDUE: Fq = field_new!(Fq, BigInteger([
0x68c3488912edefaa,
0x8d087f6872aabf4f,
0x51e1a24709081231,
0x2259d6b14729c0fa,
]));
/// QUADRATIC_NONRESIDUE = U+2
#[rustfmt::skip]
const QUADRATIC_NONRESIDUE: (Fq, Fq) = (
field_new!(Fq, BigInteger([
12014063508332092218u64,
1509222997478479483u64,
14762033076929465432u64,
2023505479389396574u64,
])),
field_new!(Fq, BigInteger([
202099033278250856u64,
8885205928937022213u64,
5545221690922665192u64,
39800542322357402u64,
])),
);
/// Coefficients for the Frobenius automorphism.
#[rustfmt::skip]
const FROBENIUS_COEFF_FP2_C1: &'static [Fq] = &[
// NONRESIDUE**(((q^0) - 1) / 2)
field_new!(Fq, BigInteger([
0xd35d438dc58f0d9d,
0x0a78eb28f5c70b3d,
0x666ea36f7879462c,
0xe0a77c19a07df2f,
])),
// NONRESIDUE**(((q^1) - 1) / 2)
field_new!(Fq, BigInteger([
0x68c3488912edefaa,
0x8d087f6872aabf4f,
0x51e1a24709081231,
0x2259d6b14729c0fa,
])),
];
#[inline(always)]
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp {
-(*fe)
}
}
pub const FQ2_ZERO: Fq2 = field_new!(Fq2, FQ_ZERO, FQ_ZERO);
pub const FQ2_ONE: Fq2 = field_new!(Fq2, FQ_ONE, FQ_ZERO);

+ 195
- 0
bn254/src/fields/fq6.rs

@ -0,0 +1,195 @@
use super::*;
use ark_ff::{biginteger::BigInteger256, field_new, fields::*};
pub type Fq6 = Fp6<Fq6Parameters>;
#[derive(Clone, Copy)]
pub struct Fq6Parameters;
impl Fp6Parameters for Fq6Parameters {
type Fp2Params = Fq2Parameters;
/// NONRESIDUE = U+9
#[rustfmt::skip]
const NONRESIDUE: Fq2 = field_new!(Fq2,
field_new!(Fq, BigInteger256([
0xf60647ce410d7ff7,
0x2f3d6f4dd31bd011,
0x2943337e3940c6d1,
0x1d9598e8a7e39857,
])),
field_new!(Fq, BigInteger256([
202099033278250856u64,
8885205928937022213u64,
5545221690922665192u64,
39800542322357402u64,
])),
);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C1: &'static [Fq2] = &[
// Fp2::NONRESIDUE^(((q^0) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0xd35d438dc58f0d9d,
0x0a78eb28f5c70b3d,
0x666ea36f7879462c,
0xe0a77c19a07df2f,
])),
field_new!(Fq, BigInteger256([0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^(((q^1) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0xb5773b104563ab30,
0x347f91c8a9aa6454,
0x7a007127242e0991,
0x1956bcd8118214ec,
])),
field_new!(Fq, BigInteger256([
0x6e849f1ea0aa4757,
0xaa1c7b6d89f89141,
0xb6e713cdfae0ca3a,
0x26694fbb4e82ebc3,
])),
),
// Fp2::NONRESIDUE^(((q^2) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0x3350c88e13e80b9c,
0x7dce557cdb5e56b9,
0x6001b4b8b615564a,
0x2682e617020217e0,
])),
field_new!(Fq, BigInteger256([0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^(((q^3) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0xc9af22f716ad6bad,
0xb311782a4aa662b2,
0x19eeaf64e248c7f4,
0x20273e77e3439f82,
])),
field_new!(Fq, BigInteger256([
0xacc02860f7ce93ac,
0x3933d5817ba76b4c,
0x69e6188b446c8467,
0xa46036d4417cc55,
])),
),
// Fp2::NONRESIDUE^(((q^4) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0x71930c11d782e155,
0xa6bb947cffbe3323,
0xaa303344d4741444,
0x2c3b3f0d26594943,
])),
field_new!(Fq, BigInteger256([0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^(((q^5) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0xf91aba2654e8e3b1,
0x4771cb2fdc92ce12,
0xdcb16ae0fc8bdf35,
0x274aa195cd9d8be4,
])),
field_new!(Fq, BigInteger256([
0x5cfc50ae18811f8b,
0x4bb28433cb43988c,
0x4fd35f13c3b56219,
0x301949bd2fc8883a,
])),
),
];
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C2: &'static [Fq2] = &[
// Fp2::NONRESIDUE^((2*(q^0) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0xd35d438dc58f0d9d,
0x0a78eb28f5c70b3d,
0x666ea36f7879462c,
0xe0a77c19a07df2f,
])),
field_new!(Fq, BigInteger256([0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^((2*(q^1) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0x7361d77f843abe92,
0xa5bb2bd3273411fb,
0x9c941f314b3e2399,
0x15df9cddbb9fd3ec,
])),
field_new!(Fq, BigInteger256([
0x5dddfd154bd8c949,
0x62cb29a5a4445b60,
0x37bc870a0c7dd2b9,
0x24830a9d3171f0fd,
])),
),
// Fp2::NONRESIDUE^((2*(q^2) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0x71930c11d782e155,
0xa6bb947cffbe3323,
0xaa303344d4741444,
0x2c3b3f0d26594943,
])),
field_new!(Fq, BigInteger256([0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^((2*(q^3) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0x448a93a57b6762df,
0xbfd62df528fdeadf,
0xd858f5d00e9bd47a,
0x6b03d4d3476ec58,
])),
field_new!(Fq, BigInteger256([
0x2b19daf4bcc936d1,
0xa1a54e7a56f4299f,
0xb533eee05adeaef1,
0x170c812b84dda0b2,
])),
),
// Fp2::NONRESIDUE^((2*(q^4) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0x3350c88e13e80b9c,
0x7dce557cdb5e56b9,
0x6001b4b8b615564a,
0x2682e617020217e0,
])),
field_new!(Fq, BigInteger256([0x0, 0x0, 0x0, 0x0])),
),
// Fp2::NONRESIDUE^((2*(q^5) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, BigInteger256([
0x843420f1d8dadbd6,
0x31f010c9183fcdb2,
0x436330b527a76049,
0x13d47447f11adfe4,
])),
field_new!(Fq, BigInteger256([
0xef494023a857fa74,
0x2a925d02d5ab101a,
0x83b015829ba62f10,
0x2539111d0c13aea3,
])),
),
];
#[inline(always)]
fn mul_fp2_by_nonresidue(fe: &Fq2) -> Fq2 {
// (c0+u*c1)*(9+u) = (9*c0-c1)+u*(9*c1+c0)
let mut f = *fe;
f.double_in_place().double_in_place().double_in_place();
let c0 = f.c0 + fe.c0 + Fq2Parameters::mul_fp_by_nonresidue(&fe.c1);
let c1 = f.c1 + fe.c1 + fe.c0;
field_new!(Fq2, c0, c1)
}
}

+ 95
- 0
bn254/src/fields/fr.rs

@ -0,0 +1,95 @@
use ark_ff::{biginteger::BigInteger256 as BigInteger, fields::*};
pub type Fr = Fp256<FrParameters>;
pub struct FrParameters;
impl Fp256Parameters for FrParameters {}
impl FftParameters for FrParameters {
type BigInt = BigInteger;
const TWO_ADICITY: u32 = 28;
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
7164790868263648668u64,
11685701338293206998u64,
6216421865291908056u64,
1756667274303109607u64,
]);
}
impl FpParameters for FrParameters {
/// MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
4891460686036598785u64,
2896914383306846353u64,
13281191951274694749u64,
3486998266802970665u64,
]);
const MODULUS_BITS: u32 = 254;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
const REPR_SHAVE_BITS: u32 = 2;
#[rustfmt::skip]
const R: BigInteger = BigInteger([
12436184717236109307u64,
3962172157175319849u64,
7381016538464732718u64,
1011752739694698287u64,
]);
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
1997599621687373223u64,
6052339484930628067u64,
10108755138030829701u64,
150537098327114917u64,
]);
const INV: u64 = 14042775128853446655u64;
// GENERATOR = 5
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
1949230679015292902u64,
16913946402569752895u64,
5177146667339417225u64,
1571765431670520771u64,
]);
/// (r - 1)/2 =
/// 10944121435919637611123202872628637544274182200208017171849102093287904247808
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0xa1f0fac9f8000000,
0x9419f4243cdcb848,
0xdc2822db40c0ac2e,
0x183227397098d014,
]);
// T and T_MINUS_ONE_DIV_TWO, where r - 1 = 2^s * t
/// t = (r - 1) / 2^s =
/// 81540058820840996586704275553141814055101440848469862132140264610111
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0x9b9709143e1f593f,
0x181585d2833e8487,
0x131a029b85045b68,
0x30644e72e,
]);
/// (t - 1) / 2 =
/// 40770029410420498293352137776570907027550720424234931066070132305055
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0xcdcb848a1f0fac9f,
0x0c0ac2e9419f4243,
0x098d014dc2822db4,
0x183227397,
]);
}

+ 27
- 0
bn254/src/fields/mod.rs

@ -0,0 +1,27 @@
#[cfg(feature = "scalar_field")]
pub mod fr;
#[cfg(feature = "scalar_field")]
pub use self::fr::*;
#[cfg(feature = "curve")]
pub mod fq;
#[cfg(feature = "curve")]
pub use self::fq::*;
#[cfg(feature = "curve")]
pub mod fq2;
#[cfg(feature = "curve")]
pub use self::fq2::*;
#[cfg(feature = "curve")]
pub mod fq6;
#[cfg(feature = "curve")]
pub use self::fq6::*;
#[cfg(feature = "curve")]
pub mod fq12;
#[cfg(feature = "curve")]
pub use self::fq12::*;
#[cfg(all(feature = "curve", test))]
mod tests;

+ 504
- 0
bn254/src/fields/tests.rs

@ -0,0 +1,504 @@
use ark_ff::{
biginteger::{BigInteger, BigInteger256},
fields::{
fp6_3over2::Fp6Parameters, FftField, FftParameters, Field, FpParameters, PrimeField,
SquareRootField,
},
test_rng, One, UniformRand, Zero,
};
use ark_serialize::{buffer_bit_byte_size, CanonicalSerialize};
use core::{
cmp::Ordering,
ops::{AddAssign, MulAssign, SubAssign},
};
use rand::{Rng, SeedableRng};
use rand_xorshift::XorShiftRng;
use crate::{Fq, Fq12, Fq2, Fq6, Fq6Parameters, FqParameters, Fr};
use ark_curve_tests::fields::*;
pub(crate) const ITERATIONS: usize = 5;
#[test]
fn test_fr() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let a: Fr = rng.gen();
let b: Fr = rng.gen();
field_test(a, b);
primefield_test::<Fr>();
sqrt_field_test(b);
let byte_size = a.serialized_size();
field_serialization_test::<Fr>(byte_size);
}
}
#[test]
fn test_fq() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let a: Fq = rng.gen();
let b: Fq = rng.gen();
field_test(a, b);
primefield_test::<Fq>();
sqrt_field_test(a);
let byte_size = a.serialized_size();
let (_, buffer_size) = buffer_bit_byte_size(Fq::size_in_bits());
assert_eq!(byte_size, buffer_size);
field_serialization_test::<Fq>(byte_size);
}
}
#[test]
fn test_fq2() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let a: Fq2 = rng.gen();
let b: Fq2 = rng.gen();
field_test(a, b);
sqrt_field_test(a);
}
frobenius_test::<Fq2, _>(Fq::characteristic(), 13);
let byte_size = Fq2::zero().serialized_size();
field_serialization_test::<Fq2>(byte_size);
}
#[test]
fn test_fq6() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let g: Fq6 = rng.gen();
let h: Fq6 = rng.gen();
field_test(g, h);
}
frobenius_test::<Fq6, _>(Fq::characteristic(), 13);
let byte_size = Fq6::zero().serialized_size();
field_serialization_test::<Fq6>(byte_size);
}
#[test]
fn test_fq12() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let g: Fq12 = rng.gen();
let h: Fq12 = rng.gen();
field_test(g, h);
}
frobenius_test::<Fq12, _>(Fq::characteristic(), 13);
let byte_size = Fq12::zero().serialized_size();
field_serialization_test::<Fq12>(byte_size);
}
#[test]
fn test_fq_repr_from() {
assert_eq!(BigInteger256::from(100), BigInteger256([100, 0, 0, 0]));
}
#[test]
fn test_fq_repr_is_odd() {
assert!(!BigInteger256::from(0).is_odd());
assert!(BigInteger256::from(0).is_even());
assert!(BigInteger256::from(1).is_odd());
assert!(!BigInteger256::from(1).is_even());
assert!(!BigInteger256::from(324834872).is_odd());
assert!(BigInteger256::from(324834872).is_even());
assert!(BigInteger256::from(324834873).is_odd());
assert!(!BigInteger256::from(324834873).is_even());
}
#[test]
fn test_fq_repr_is_zero() {
assert!(BigInteger256::from(0).is_zero());
assert!(!BigInteger256::from(1).is_zero());
assert!(!BigInteger256([0, 0, 1, 0]).is_zero());
}
#[test]
fn test_fq_repr_num_bits() {
let mut a = BigInteger256::from(0);
assert_eq!(0, a.num_bits());
a = BigInteger256::from(1);
for i in 1..257 {
assert_eq!(i, a.num_bits());
a.mul2();
}
assert_eq!(0, a.num_bits());
}
#[test]
fn test_fq_add_assign() {
// Test associativity
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
// Generate a, b, c and ensure (a + b) + c == a + (b + c).
let a = Fq::rand(&mut rng);
let b = Fq::rand(&mut rng);
let c = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.add_assign(&b);
tmp1.add_assign(&c);
let mut tmp2 = b;
tmp2.add_assign(&c);
tmp2.add_assign(&a);
assert_eq!(tmp1, tmp2);
}
}
#[test]
fn test_fq_sub_assign() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
// Ensure that (a - b) + (b - a) = 0.
let a = Fq::rand(&mut rng);
let b = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.sub_assign(&b);
let mut tmp2 = b;
tmp2.sub_assign(&a);
tmp1.add_assign(&tmp2);
assert!(tmp1.is_zero());
}
}
#[test]
fn test_fq_mul_assign() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000000 {
// Ensure that (a * b) * c = a * (b * c)
let a = Fq::rand(&mut rng);
let b = Fq::rand(&mut rng);
let c = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.mul_assign(&b);
tmp1.mul_assign(&c);
let mut tmp2 = b;
tmp2.mul_assign(&c);
tmp2.mul_assign(&a);
assert_eq!(tmp1, tmp2);
}
for _ in 0..1000000 {
// Ensure that r * (a + b + c) = r*a + r*b + r*c
let r = Fq::rand(&mut rng);
let mut a = Fq::rand(&mut rng);
let mut b = Fq::rand(&mut rng);
let mut c = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.add_assign(&b);
tmp1.add_assign(&c);
tmp1.mul_assign(&r);
a.mul_assign(&r);
b.mul_assign(&r);
c.mul_assign(&r);
a.add_assign(&b);
a.add_assign(&c);
assert_eq!(tmp1, a);
}
}
#[test]
fn test_fq_squaring() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000000 {
// Ensure that (a * a) = a^2
let a = Fq::rand(&mut rng);
let mut tmp = a;
tmp.square_in_place();
let mut tmp2 = a;
tmp2.mul_assign(&a);
assert_eq!(tmp, tmp2);
}
}
#[test]
fn test_fq_inverse() {
assert!(Fq::zero().inverse().is_none());
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let one = Fq::one();
for _ in 0..1000 {
// Ensure that a * a^-1 = 1
let mut a = Fq::rand(&mut rng);
let ainv = a.inverse().unwrap();
a.mul_assign(&ainv);
assert_eq!(a, one);
}
}
#[test]
fn test_fq_double_in_place() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
// Ensure doubling a is equivalent to adding a to itself.
let mut a = Fq::rand(&mut rng);
let mut b = a;
b.add_assign(&a);
a.double_in_place();
assert_eq!(a, b);
}
}
#[test]
fn test_fq_negate() {
{
let a = -Fq::zero();
assert!(a.is_zero());
}
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
// Ensure (a - (-a)) = 0.
let mut a = Fq::rand(&mut rng);
let b = -a;
a.add_assign(&b);
assert!(a.is_zero());
}
}
#[test]
fn test_fq_pow() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for i in 0..1000 {
// Exponentiate by various small numbers and ensure it consists with repeated
// multiplication.
let a = Fq::rand(&mut rng);
let target = a.pow(&[i]);
let mut c = Fq::one();
for _ in 0..i {
c.mul_assign(&a);
}
assert_eq!(c, target);
}
for _ in 0..1000 {
// Exponentiating by the modulus should have no effect in a prime field.
let a = Fq::rand(&mut rng);
assert_eq!(a, a.pow(Fq::characteristic()));
}
}
#[test]
fn test_fq_sqrt() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
assert_eq!(Fq::zero().sqrt().unwrap(), Fq::zero());
for _ in 0..1000 {
// Ensure sqrt(a^2) = a or -a
let a = Fq::rand(&mut rng);
let nega = -a;
let mut b = a;
b.square_in_place();
let b = b.sqrt().unwrap();
assert!(a == b || nega == b);
}
for _ in 0..1000 {
// Ensure sqrt(a)^2 = a for random a
let a = Fq::rand(&mut rng);
if let Some(mut tmp) = a.sqrt() {
tmp.square_in_place();
assert_eq!(a, tmp);
}
}
}
#[test]
fn test_fq_num_bits() {
assert_eq!(FqParameters::MODULUS_BITS, 254);
assert_eq!(FqParameters::CAPACITY, 253);
}
#[test]
fn test_fq_root_of_unity() {
assert_eq!(FqParameters::TWO_ADICITY, 1);
assert_eq!(
Fq::multiplicative_generator().pow([
0x9e10460b6c3e7ea3,
0xcbc0b548b438e546,
0xdc2822db40c0ac2e,
0x183227397098d014,
]),
Fq::two_adic_root_of_unity()
);
assert_eq!(
Fq::two_adic_root_of_unity().pow([1 << FqParameters::TWO_ADICITY]),
Fq::one()
);
assert!(Fq::multiplicative_generator().sqrt().is_none());
}
#[test]
fn test_fq_ordering() {
// BigInteger256's ordering is well-tested, but we still need to make sure the
// Fq elements aren't being compared in Montgomery form.
for i in 0..100 {
assert!(Fq::from(BigInteger256::from(i + 1)) > Fq::from(BigInteger256::from(i)));
}
}
#[test]
fn test_fq_legendre() {
use ark_ff::fields::LegendreSymbol::*;
assert_eq!(QuadraticResidue, Fq::one().legendre());
assert_eq!(Zero, Fq::zero().legendre());
assert_eq!(
QuadraticResidue,
Fq::from(BigInteger256::from(4)).legendre()
);
assert_eq!(
QuadraticNonResidue,
Fq::from(BigInteger256::from(5)).legendre()
);
}
#[test]
fn test_fq2_ordering() {
let mut a = Fq2::new(Fq::zero(), Fq::zero());
let mut b = a.clone();
assert!(a.cmp(&b) == Ordering::Equal);
b.c0.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Less);
a.c0.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Equal);
b.c1.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Less);
a.c0.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Less);
a.c1.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Greater);
b.c0.add_assign(&Fq::one());
assert!(a.cmp(&b) == Ordering::Equal);
}
#[test]
fn test_fq2_basics() {
assert_eq!(Fq2::new(Fq::zero(), Fq::zero(),), Fq2::zero());
assert_eq!(Fq2::new(Fq::one(), Fq::zero(),), Fq2::one());
assert!(Fq2::zero().is_zero());
assert!(!Fq2::one().is_zero());
assert!(!Fq2::new(Fq::zero(), Fq::one(),).is_zero());
}
#[test]
fn test_fq2_legendre() {
use ark_ff::fields::LegendreSymbol::*;
assert_eq!(Zero, Fq2::zero().legendre());
// i^2 = -1
let mut m1 = -Fq2::one();
assert_eq!(QuadraticResidue, m1.legendre());
m1 = Fq6Parameters::mul_fp2_by_nonresidue(&m1);
assert_eq!(QuadraticNonResidue, m1.legendre());
}
#[test]
fn test_fq6_mul_by_1() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
let c1 = Fq2::rand(&mut rng);
let mut a = Fq6::rand(&mut rng);
let mut b = a;
a.mul_by_1(&c1);
b.mul_assign(&Fq6::new(Fq2::zero(), c1, Fq2::zero()));
assert_eq!(a, b);
}
}
#[test]
fn test_fq6_mul_by_01() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
let c0 = Fq2::rand(&mut rng);
let c1 = Fq2::rand(&mut rng);
let mut a = Fq6::rand(&mut rng);
let mut b = a;
a.mul_by_01(&c0, &c1);
b.mul_assign(&Fq6::new(c0, c1, Fq2::zero()));
assert_eq!(a, b);
}
}
#[test]
fn test_fq12_mul_by_014() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
let c0 = Fq2::rand(&mut rng);
let c1 = Fq2::rand(&mut rng);
let c5 = Fq2::rand(&mut rng);
let mut a = Fq12::rand(&mut rng);
let mut b = a;
a.mul_by_014(&c0, &c1, &c5);
b.mul_assign(&Fq12::new(
Fq6::new(c0, c1, Fq2::zero()),
Fq6::new(Fq2::zero(), c5, Fq2::zero()),
));
assert_eq!(a, b);
}
}
#[test]
fn test_fq12_mul_by_034() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
let c0 = Fq2::rand(&mut rng);
let c3 = Fq2::rand(&mut rng);
let c4 = Fq2::rand(&mut rng);
let mut a = Fq12::rand(&mut rng);
let mut b = a;
a.mul_by_034(&c0, &c3, &c4);
b.mul_assign(&Fq12::new(
Fq6::new(c0, Fq2::zero(), Fq2::zero()),
Fq6::new(c3, c4, Fq2::zero()),
));
assert_eq!(a, b);
}
}

+ 40
- 0
bn254/src/lib.rs

@ -0,0 +1,40 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(
warnings,
unused,
future_incompatible,
nonstandard_style,
rust_2018_idioms
)]
#![forbid(unsafe_code)]
//! This library implements the BN254 curve that was sampled as part of the [[BCTV14]][https://eprint.iacr.org/2013/879.pdf] paper .
//! The name denotes that it is a Barreto--Naehrig curve of embedding degree 12,
//! defined over a 254-bit (prime) field. The scalar field is highly 2-adic.
//!
//! This curve is also implemented in [libff](https://github.com/scipr-lab/libff/tree/master/libff/algebra/curves/alt_bn128) under the name `bn128`.
//! It is the same as the `bn256` curve used in Ethereum (eg: [go-ethereum](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn254/cloudflare)).
//!
//! #CAUTION
//! **This curve does not satisfy the 128-bit security level anymore.**
//!
//!
//! Curve information:
//! * Base field: q = 21888242871839275222246405745257275088696311157297823662689037894645226208583
//! * Scalar field: r = 21888242871839275222246405745257275088548364400416034343698204186575808495617
//! * valuation(q - 1, 2) = 1
//! * valuation(r - 1, 2) = 28
//! * G1 curve equation: y^2 = x^3 + 3
//! * G2 curve equation: y^2 = x^3 + B, where
//! * B = 3/(u+9) where Fq2[u]=Fq/u+1
//! = Fq2(19485874751759354771024239261021720505790618469301721065564631296452457478373, 266929791119991161246907387137283842545076965332900288569378510910307636690)
#[cfg(feature = "curve")]
mod curves;
mod fields;
#[cfg(feature = "curve")]
pub use curves::*;
pub use fields::*;

+ 29
- 0
bw6_761/Cargo.toml

@ -0,0 +1,29 @@
[package]
name = "ark-bw6-761"
version = "0.1.0"
authors = [ "arkworks contributors" ]
description = "The BW6-761 pairing-friendly elliptic curve"
homepage = "https://arworks.rs"
repository = "https://github.com/arkworks/algebra"
documentation = "https://docs.rs/ark-bw6-761/"
keywords = ["cryptography", "finite fields", "elliptic curves" ]
categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0"
edition = "2018"
[dependencies]
ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false }
ark-bls12-377 = { path = "../bls12_377", default-features = false, features = [ "base_field" ] }
[dev-dependencies]
ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-curve-tests = { path = "../curve-tests", default-features = false }
rand = { version = "0.7", default-features = false }
rand_xorshift = "0.2"
[features]
default = []
std = [ "ark-std/std", "ark-ff/std", "ark-ec/std", "ark-bls12-377/std" ]

+ 113
- 0
bw6_761/src/curves/g1.rs

@ -0,0 +1,113 @@
use crate::{Fq, Fr};
use ark_ec::{
models::{ModelParameters, SWModelParameters},
short_weierstrass_jacobian::{GroupAffine, GroupProjective},
};
use ark_ff::{
biginteger::{BigInteger384, BigInteger768},
field_new,
};
pub type G1Affine = GroupAffine<Parameters>;
pub type G1Projective = GroupProjective<Parameters>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
impl ModelParameters for Parameters {
type BaseField = Fq;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = 0
#[rustfmt::skip]
const COEFF_A: Fq = field_new!(Fq, BigInteger768([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]));
/// COEFF_B = -1
#[rustfmt::skip]
const COEFF_B: Fq = field_new!(Fq, BigInteger768([
0xf29a000000007ab6,
0x8c391832e000739b,
0x77738a6b6870f959,
0xbe36179047832b03,
0x84f3089e56574722,
0xc5a3614ac0b1d984,
0x5c81153f4906e9fe,
0x4d28be3a9f55c815,
0xd72c1d6f77d5f5c5,
0x73a18e069ac04458,
0xf9dfaa846595555f,
0xd0f0a60a5be58c,
]));
/// COFACTOR =
/// 26642435879335816683987677701488073867751118270052650655942102502312977592501693353047140953112195348280268661194876
#[rustfmt::skip]
const COFACTOR: &'static [u64] = &[
0x3de580000000007c,
0x832ba4061000003b,
0xc61c554757551c0c,
0xc856a0853c9db94c,
0x2c77d5ac34cb12ef,
0xad1972339049ce76,
];
/// COFACTOR^(-1) mod r =
/// 91141326767669940707819291241958318717982251277713150053234367522357946997763584490607453720072232540829942217804
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, BigInteger384([
489703175600125849,
3883341943836920852,
1678256062427438196,
5848789333018172718,
7127967896440782320,
71512347676739162,
]));
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G1_GENERATOR_X, G1_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_elem: &Self::BaseField) -> Self::BaseField {
use ark_ff::Zero;
Self::BaseField::zero()
}
}
/// G1_GENERATOR_X =
/// 6238772257594679368032145693622812838779005809760824733138787810501188623461307351759238099287535516224314149266511977132140828635950940021790489507611754366317801811090811367945064510304504157188661901055903167026722666149426237
#[rustfmt::skip]
pub const G1_GENERATOR_X: Fq = field_new!(Fq, BigInteger768([
0xd6e42d7614c2d770,
0x4bb886eddbc3fc21,
0x64648b044098b4d2,
0x1a585c895a422985,
0xf1a9ac17cf8685c9,
0x352785830727aea5,
0xddf8cb12306266fe,
0x6913b4bfbc9e949a,
0x3a4b78d67ba5f6ab,
0x0f481c06a8d02a04,
0x91d4e7365c43edac,
0xf4d17cd48beca5,
]));
/// G1_GENERATOR_Y =
/// 2101735126520897423911504562215834951148127555913367997162789335052900271653517958562461315794228241561913734371411178226936527683203879553093934185950470971848972085321797958124416462268292467002957525517188485984766314758624099
#[rustfmt::skip]
pub const G1_GENERATOR_Y: Fq = field_new!(Fq, BigInteger768([
0x97e805c4bd16411f,
0x870d844e1ee6dd08,
0x1eba7a37cb9eab4d,
0xd544c4df10b9889a,
0x8fe37f21a33897be,
0xe9bf99a43a0885d2,
0xd7ee0c9e273de139,
0xaa6a9ec7a38dd791,
0x8f95d3fcf765da8e,
0x42326e7db7357c99,
0xe217e407e218695f,
0x9d1eb23b7cf684,
]));

+ 113
- 0
bw6_761/src/curves/g2.rs

@ -0,0 +1,113 @@
use crate::{Fq, Fr};
use ark_ec::{
models::{ModelParameters, SWModelParameters},
short_weierstrass_jacobian::{GroupAffine, GroupProjective},
};
use ark_ff::{
biginteger::{BigInteger384, BigInteger768},
field_new,
};
pub type G2Affine = GroupAffine<Parameters>;
pub type G2Projective = GroupProjective<Parameters>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
impl ModelParameters for Parameters {
type BaseField = Fq;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = 0
#[rustfmt::skip]
const COEFF_A: Fq = field_new!(Fq, BigInteger768([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]));
/// COEFF_B = 4
#[rustfmt::skip]
const COEFF_B: Fq = field_new!(Fq, BigInteger768([
0x136efffffffe16c9,
0x82cf5a6dcffe3319,
0x6458c05f1f0e0741,
0xd10ae605e52a4eda,
0x41ca591c0266e100,
0x7d0fd59c3626929f,
0x9967dc004d00c112,
0x1ccff9c033379af5,
0x9ad6ec10a23f63af,
0x5cec11251a72c235,
0x8d18b1ae789ba83e,
10403402007434220,
]));
/// COFACTOR =
/// 26642435879335816683987677701488073867751118270052650655942102502312977592501693353047140953112195348280268661194869
#[rustfmt::skip]
const COFACTOR: &'static [u64] = &[
0x3de5800000000075,
0x832ba4061000003b,
0xc61c554757551c0c,
0xc856a0853c9db94c,
0x2c77d5ac34cb12ef,
0xad1972339049ce76,
];
/// COFACTOR^(-1) mod r =
/// 214911522365886453591244899095480747723790054550866810551297776298664428889000553861210287833206024638187939842124
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, BigInteger384([
14378295991815829998,
14586153992421458638,
9788477762582722914,
12654821707953664524,
15185631607604703397,
26723985783783076,
]));
/// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G2_GENERATOR_X, G2_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_elem: &Self::BaseField) -> Self::BaseField {
use ark_ff::Zero;
Self::BaseField::zero()
}
}
/// G2_GENERATOR_X =
/// 6445332910596979336035888152774071626898886139774101364933948236926875073754470830732273879639675437155036544153105017729592600560631678554299562762294743927912429096636156401171909259073181112518725201388196280039960074422214428
#[rustfmt::skip]
pub const G2_GENERATOR_X: Fq = field_new!(Fq, BigInteger768([
0x3d902a84cd9f4f78,
0x864e451b8a9c05dd,
0xc2b3c0d6646c5673,
0x17a7682def1ecb9d,
0xbe31a1e0fb768fe3,
0x4df125e09b92d1a6,
0x0943fce635b02ee9,
0xffc8e7ad0605e780,
0x8165c00a39341e95,
0x8ccc2ae90a0f094f,
0x73a8b8cc0ad09e0c,
0x11027e203edd9f4,
]));
/// G2_GENERATOR_Y =
/// 562923658089539719386922163444547387757586534741080263946953401595155211934630598999300396317104182598044793758153214972605680357108252243146746187917218885078195819486220416605630144001533548163105316661692978285266378674355041
#[rustfmt::skip]
pub const G2_GENERATOR_Y: Fq = field_new!(Fq, BigInteger768([
0x9a159be4e773f67c,
0x6b957244aa8f4e6b,
0xa27b70c9c945a38c,
0xacb6a09fda11d0ab,
0x3abbdaa9bb6b1291,
0xdbdf642af5694c36,
0xb6360bb9560b369f,
0xac0bd1e822b8d6da,
0xfa355d17afe6945f,
0x8d6a0fc1fbcad35e,
0x72a63c7874409840,
0x114976e5b0db280,
]));

+ 61
- 0
bw6_761/src/curves/mod.rs

@ -0,0 +1,61 @@
use crate::*;
use ark_ec::{
bw6,
bw6::{BW6Parameters, TwistType, BW6},
};
use ark_ff::biginteger::BigInteger768 as BigInteger;
pub mod g1;
pub mod g2;
#[cfg(test)]
mod tests;
#[derive(PartialEq, Eq)]
pub struct Parameters;
impl BW6Parameters for Parameters {
const X: BigInteger = BigInteger([
0x8508c00000000001,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
]);
/// `x` is positive.
const X_IS_NEGATIVE: bool = false;
// X+1
const ATE_LOOP_COUNT_1: &'static [u64] = &[0x8508c00000000002];
const ATE_LOOP_COUNT_1_IS_NEGATIVE: bool = false;
// X^3-X^2-X
const ATE_LOOP_COUNT_2: &'static [i8] = &[
-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, -1, 0, 0,
1, 0, 0, 0, -1, 0, 0, -1, 0, 1, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, -1, 0, 1, 0, 1, 0, 0, 0, 1,
0, -1, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 1,
];
const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool = false;
const TWIST_TYPE: TwistType = TwistType::M;
type Fp = Fq;
type Fp3Params = Fq3Parameters;
type Fp6Params = Fq6Parameters;
type G1Parameters = g1::Parameters;
type G2Parameters = g2::Parameters;
}
pub type BW6_761 = BW6<Parameters>;
pub type G1Affine = bw6::G1Affine<Parameters>;
pub type G1Projective = bw6::G1Projective<Parameters>;
pub type G2Affine = bw6::G2Affine<Parameters>;
pub type G2Projective = bw6::G2Projective<Parameters>;

+ 77
- 0
bw6_761/src/curves/tests.rs

@ -0,0 +1,77 @@
use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ff::{test_rng, Field, One, PrimeField};
use rand::Rng;
use crate::*;
use ark_curve_tests::{curves::*, groups::*};
#[test]
fn test_g1_projective_curve() {
curve_tests::<G1Projective>();
sw_tests::<g1::Parameters>();
}
#[test]
fn test_g1_projective_group() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G1Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g1_generator() {
let generator = G1Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g2_projective_curve() {
curve_tests::<G2Projective>();
sw_tests::<g2::Parameters>();
}
#[test]
fn test_g2_projective_group() {
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g2_generator() {
let generator = G2Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_bilinearity() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G2Projective = rng.gen();
let s: Fr = rng.gen();
let sa = a.mul(s);
let sb = b.mul(s);
let ans1 = BW6_761::pairing(sa, b);
let ans2 = BW6_761::pairing(a, sb);
let ans3 = BW6_761::pairing(a, b).pow(s.into_repr());
assert_eq!(ans1, ans2);
assert_eq!(ans2, ans3);
assert_ne!(ans1, Fq6::one());
assert_ne!(ans2, Fq6::one());
assert_ne!(ans3, Fq6::one());
assert_eq!(ans1.pow(Fr::characteristic()), Fq6::one());
assert_eq!(ans2.pow(Fr::characteristic()), Fq6::one());
assert_eq!(ans3.pow(Fr::characteristic()), Fq6::one());
}

+ 175
- 0
bw6_761/src/fields/fq.rs

@ -0,0 +1,175 @@
use ark_ff::{
biginteger::BigInteger768 as BigInteger,
field_new,
fields::{FftParameters, Fp768, Fp768Parameters, FpParameters},
};
pub type Fq = Fp768<FqParameters>;
pub struct FqParameters;
pub const FQ_ONE: Fq = field_new!(Fq, FqParameters::R);
pub const FQ_ZERO: Fq = field_new!(Fq, BigInteger([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]));
impl Fp768Parameters for FqParameters {}
impl FftParameters for FqParameters {
type BigInt = BigInteger;
// The internal representation of this type is six 64-bit unsigned
// integers in little-endian order. Values are always in
// Montgomery form; i.e., Scalar(a) = aR mod p, with R=2^768.
// (MODULUS - 1) % 2^TWO_ADICITY == 0
const TWO_ADICITY: u32 = 1;
// least_quadratic_nonresidue(MODULUS) in Sage.
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
17481284903592032950u64,
10104133845767975835u64,
8607375506753517913u64,
13706168424391191299u64,
9580010308493592354u64,
14241333420363995524u64,
6665632285037357566u64,
5559902898979457045u64,
15504799981718861253u64,
8332096944629367896u64,
18005297320867222879u64,
58811391084848524u64,
]);
}
impl FpParameters for FqParameters {
/// MODULUS = 6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068299
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
0xf49d00000000008b,
0xe6913e6870000082,
0x160cf8aeeaf0a437,
0x98a116c25667a8f8,
0x71dcd3dc73ebff2e,
0x8689c8ed12f9fd90,
0x03cebaff25b42304,
0x707ba638e584e919,
0x528275ef8087be41,
0xb926186a81d14688,
0xd187c94004faff3e,
0x122e824fb83ce0a
]);
const MODULUS_BITS: u32 = 761;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
// gap to 64-bit machine word
const REPR_SHAVE_BITS: u32 = 7;
// 2^768 % MODULUS
#[rustfmt::skip]
const R: BigInteger = BigInteger([
144959613005956565u64,
6509995272855063783u64,
11428286765660613342u64,
15738672438262922740u64,
17071399330169272331u64,
13899911246788437003u64,
12055474021000362245u64,
2545351818702954755u64,
8887388221587179644u64,
5009280847225881135u64,
15539704305423854047u64,
23071597697427581u64,
]);
// R^2
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
14305184132582319705u64,
8868935336694416555u64,
9196887162930508889u64,
15486798265448570248u64,
5402985275949444416u64,
10893197322525159598u64,
3204916688966998390u64,
12417238192559061753u64,
12426306557607898622u64,
1305582522441154384u64,
10311846026977660324u64,
48736111365249031u64,
]);
// (-1/MODULUS) % 2^64
const INV: u64 = 744663313386281181u64;
/// GENERATOR = 2
// primitive_root(MODULUS)
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
289919226011913130u64,
13019990545710127566u64,
4409829457611675068u64,
13030600802816293865u64,
15696054586628993047u64,
9353078419867322391u64,
5664203968291172875u64,
5090703637405909511u64,
17774776443174359288u64,
10018561694451762270u64,
12632664537138156478u64,
46143195394855163u64,
]);
// (MODULUS - 1) / 2
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x7a4e800000000045,
0xf3489f3438000041,
0x0b067c577578521b,
0x4c508b612b33d47c,
0x38ee69ee39f5ff97,
0x4344e476897cfec8,
0x81e75d7f92da1182,
0xb83dd31c72c2748c,
0x29413af7c043df20,
0x5c930c3540e8a344,
0x68c3e4a0027d7f9f,
0x9174127dc1e705,
]);
// T =
// 3445725192157866269698394841137828771239834456268075054756895080104811711121745868043841591644705843820432283876893306725580879560277123879674755849562650799475802549689254425186271815711798397975949850214984556421382456559534149
// (MODULUS - 1) / 2 ^ TWO_ADICITY
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0x7a4e800000000045,
0xf3489f3438000041,
0x0b067c577578521b,
0x4c508b612b33d47c,
0x38ee69ee39f5ff97,
0x4344e476897cfec8,
0x81e75d7f92da1182,
0xb83dd31c72c2748c,
0x29413af7c043df20,
0x5c930c3540e8a344,
0x68c3e4a0027d7f9f,
0x9174127dc1e705,
]);
// (T - 1)/2 =
// 1722862596078933134849197420568914385619917228134037527378447540052405855560872934021920795822352921910216141938446653362790439780138561939837377924781325399737901274844627212593135907855899198987974925107492278210691228279767074
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0xbd27400000000022,
0xf9a44f9a1c000020,
0x05833e2bbabc290d,
0xa62845b09599ea3e,
0x1c7734f71cfaffcb,
0x21a2723b44be7f64,
0x40f3aebfc96d08c1,
0x5c1ee98e39613a46,
0x14a09d7be021ef90,
0xae49861aa07451a2,
0xb461f250013ebfcf,
0x48ba093ee0f382,
]);
}

+ 200
- 0
bw6_761/src/fields/fq3.rs

@ -0,0 +1,200 @@
use ark_ff::{
biginteger::BigInteger768 as BigInteger,
field_new,
fields::fp3::{Fp3, Fp3Parameters},
};
use crate::Fq;
pub type Fq3 = Fp3<Fq3Parameters>;
pub struct Fq3Parameters;
impl Fp3Parameters for Fq3Parameters {
type Fp = Fq;
/// NONRESIDUE = -4
// Fq3 = Fq[u]/u^3+4
#[rustfmt::skip]
const NONRESIDUE: Fq = field_new!(Fq, BigInteger([
0xe12e00000001e9c2,
0x63c1e3faa001cd69,
0xb1b4384fcbe29cf6,
0xc79630bc713d5a1d,
0x30127ac071851e2d,
0x0979f350dcd36af1,
0x6a66defed8b361f2,
0x53abac78b24d4e23,
0xb7ab89dede485a92,
0x5c3a0745675e8452,
0x446f17918c5f5700,
0xfdf24e3267fa1e,
]));
// (MODULUS^3 - 1) % 2^TWO_ADICITY == 0
const TWO_ADICITY: u32 = 1;
// (T-1)/2 with T = (MODULUS^3-1) / 2^TWO_ADICITY
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: &'static [u64] = &[
0xb5e7c000000a3eac,
0xf79b99dbf41cf4ab,
0xe9372b1919e55ee5,
0xbb7bbc4936c1980b,
0x7c0cb9d4399b36e1,
0x73304a5507bb1ae0,
0x92f639be8963936f,
0x4f574ac2439ba816,
0x670d9bd389dd29ef,
0x606ddf900d2124f1,
0x928fb14985ec3270,
0x6b2f2428c5f420f3,
0xac9ade29d5ab5fbe,
0xec0d0434c4005822,
0x973f10d7f3c5c108,
0x6d5e83fc81095979,
0xdac3e6e4e1647752,
0x227febf93994603e,
0x4ab8755d894167d1,
0x4fd2d3f67d8b537a,
0x33e196a4d5f4030a,
0x88b51fb72092df1a,
0xa67e5b1e8fc48316,
0xb0855eb2a00d7dab,
0xe875dd2da6751442,
0x777594a243e25676,
0x294e0f70376a85a8,
0x83f431c7988e4f18,
0x8e8fb6af3ca2f5f1,
0x7297896b4b9e90f1,
0xff38f54664d66123,
0xb5ecf80bfff41e13,
0x1662a3666bb8392a,
0x07a0968e8742d3e1,
0xf12927e564bcdfdc,
0x5de9825a0e,
];
// NONRESIDUE^T % q
#[rustfmt::skip]
const QUADRATIC_NONRESIDUE_TO_T: (Fq, Fq, Fq) = (
field_new!(Fq, BigInteger([
0xf29a000000007ab6,
0x8c391832e000739b,
0x77738a6b6870f959,
0xbe36179047832b03,
0x84f3089e56574722,
0xc5a3614ac0b1d984,
0x5c81153f4906e9fe,
0x4d28be3a9f55c815,
0xd72c1d6f77d5f5c5,
0x73a18e069ac04458,
0xf9dfaa846595555f,
0xd0f0a60a5be58c,
])),
field_new!(Fq, BigInteger([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),
field_new!(Fq, BigInteger([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),
);
// NQR ^ (MODULUS^i - 1)/3, i=0,1,2 with NQR = u = (0,1,0)
#[rustfmt::skip]
const FROBENIUS_COEFF_FP3_C1: &'static [Fq] = &[
field_new!(Fq, BigInteger([
0x0202ffffffff85d5,
0x5a5826358fff8ce7,
0x9e996e43827faade,
0xda6aff320ee47df4,
0xece9cb3e1d94b80b,
0xc0e667a25248240b,
0xa74da5bfdcad3905,
0x2352e7fe462f2103,
0x7b56588008b1c87c,
0x45848a63e711022f,
0xd7a81ebb9f65a9df,
0x51f77ef127e87d,
])),
field_new!(Fq, BigInteger([
0x7f96b51bd840c549,
0xd59782096496171f,
0x49b046fd9ce14bbc,
0x4b6163bba7527a56,
0xef6c92fb771d59f1,
0x0425bedbac1dfdc7,
0xd3ac39de759c0ffd,
0x9f43ed0e063a81d0,
0x5bd7d20b4f9a3ce2,
0x0411f03c36cf5c3c,
0x2d658fd49661c472,
0x1100249ae760b93,
])),
field_new!(Fq, BigInteger([
0x67a04ae427bfb5f8,
0x9d32d491eb6a5cff,
0x43d03c1cb68051d4,
0x0b75ca96f69859a5,
0x0763497f5325ec60,
0x48076b5c278dd94d,
0x8ca3965ff91efd06,
0x1e6077657ea02f5d,
0xcdd6c153a8c37724,
0x28b5b634e5c22ea4,
0x9e01e3efd42e902c,
0xe3d6815769a804,
])),
];
// NQR ^ (2*MODULUS^i - 2)/3, i=0,1,2 with NQR = u = (0,1,0)
#[rustfmt::skip]
const FROBENIUS_COEFF_FP3_C2: &'static [Fq] = &[
field_new!(Fq, BigInteger([
0x0202ffffffff85d5,
0x5a5826358fff8ce7,
0x9e996e43827faade,
0xda6aff320ee47df4,
0xece9cb3e1d94b80b,
0xc0e667a25248240b,
0xa74da5bfdcad3905,
0x2352e7fe462f2103,
0x7b56588008b1c87c,
0x45848a63e711022f,
0xd7a81ebb9f65a9df,
0x51f77ef127e87d,
])),
field_new!(Fq, BigInteger([
0x67a04ae427bfb5f8,
0x9d32d491eb6a5cff,
0x43d03c1cb68051d4,
0x0b75ca96f69859a5,
0x0763497f5325ec60,
0x48076b5c278dd94d,
0x8ca3965ff91efd06,
0x1e6077657ea02f5d,
0xcdd6c153a8c37724,
0x28b5b634e5c22ea4,
0x9e01e3efd42e902c,
0xe3d6815769a804,
])),
field_new!(Fq, BigInteger([
0x7f96b51bd840c549,
0xd59782096496171f,
0x49b046fd9ce14bbc,
0x4b6163bba7527a56,
0xef6c92fb771d59f1,
0x0425bedbac1dfdc7,
0xd3ac39de759c0ffd,
0x9f43ed0e063a81d0,
0x5bd7d20b4f9a3ce2,
0x0411f03c36cf5c3c,
0x2d658fd49661c472,
0x1100249ae760b93,
])),
];
#[inline(always)]
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp {
let original = -(*fe);
let double = original + &original;
double + &double
}
}

+ 106
- 0
bw6_761/src/fields/fq6.rs

@ -0,0 +1,106 @@
use crate::{Fq, Fq3, Fq3Parameters, FQ_ONE, FQ_ZERO};
use ark_ff::{
biginteger::BigInteger768 as BigInteger,
field_new,
fields::fp6_2over3::{Fp6, Fp6Parameters},
};
pub type Fq6 = Fp6<Fq6Parameters>;
pub struct Fq6Parameters;
impl Fp6Parameters for Fq6Parameters {
type Fp3Params = Fq3Parameters;
/// NONRESIDUE = (0, 1, 0)
#[rustfmt::skip]
const NONRESIDUE: Fq3 = field_new!(Fq3, FQ_ZERO, FQ_ONE, FQ_ZERO);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C1: &'static [Fq] = &[
field_new!(Fq, BigInteger([
0x0202ffffffff85d5,
0x5a5826358fff8ce7,
0x9e996e43827faade,
0xda6aff320ee47df4,
0xece9cb3e1d94b80b,
0xc0e667a25248240b,
0xa74da5bfdcad3905,
0x2352e7fe462f2103,
0x7b56588008b1c87c,
0x45848a63e711022f,
0xd7a81ebb9f65a9df,
0x51f77ef127e87d,
])),
field_new!(Fq, BigInteger([
0x8cfcb51bd8404a93,
0x495e69d68495a383,
0xd23cbc9234705263,
0x8d2b4c2b5fcf4f52,
0x6a798a5d20c612ce,
0x3e825d90eb6c2443,
0x772b249f2c9525fe,
0x521b2ed366e4b9bb,
0x84abb49bd7c4471d,
0x907062359c0f17e3,
0x3385e55030cc6f12,
0x3f11a3a41a2606,
])),
field_new!(Fq, BigInteger([
0x7f96b51bd840c549,
0xd59782096496171f,
0x49b046fd9ce14bbc,
0x4b6163bba7527a56,
0xef6c92fb771d59f1,
0x0425bedbac1dfdc7,
0xd3ac39de759c0ffd,
0x9f43ed0e063a81d0,
0x5bd7d20b4f9a3ce2,
0x0411f03c36cf5c3c,
0x2d658fd49661c472,
0x1100249ae760b93,
])),
field_new!(Fq, BigInteger([
0xf29a000000007ab6,
0x8c391832e000739b,
0x77738a6b6870f959,
0xbe36179047832b03,
0x84f3089e56574722,
0xc5a3614ac0b1d984,
0x5c81153f4906e9fe,
0x4d28be3a9f55c815,
0xd72c1d6f77d5f5c5,
0x73a18e069ac04458,
0xf9dfaa846595555f,
0xd0f0a60a5be58c,
])),
field_new!(Fq, BigInteger([
0x67a04ae427bfb5f8,
0x9d32d491eb6a5cff,
0x43d03c1cb68051d4,
0x0b75ca96f69859a5,
0x0763497f5325ec60,
0x48076b5c278dd94d,
0x8ca3965ff91efd06,
0x1e6077657ea02f5d,
0xcdd6c153a8c37724,
0x28b5b634e5c22ea4,
0x9e01e3efd42e902c,
0xe3d6815769a804,
])),
field_new!(Fq, BigInteger([
0x75064ae427bf3b42,
0x10f9bc5f0b69e963,
0xcc5cb1b14e0f587b,
0x4d3fb306af152ea1,
0x827040e0fccea53d,
0x82640a1166dbffc8,
0x30228120b0181307,
0xd137b92adf4a6748,
0xf6aaa3e430ed815e,
0xb514282e4b01ea4b,
0xa422396b6e993acc,
0x12e5db4d0dc277,
])),
];
}

+ 1
- 0
bw6_761/src/fields/fr.rs

@ -0,0 +1 @@
pub use ark_bls12_377::{Fq as Fr, FqParameters as FrParameters};

+ 14
- 0
bw6_761/src/fields/mod.rs

@ -0,0 +1,14 @@
pub mod fr;
pub use self::fr::*;
pub mod fq;
pub use self::fq::*;
pub mod fq3;
pub use self::fq3::*;
pub mod fq6;
pub use self::fq6::*;
#[cfg(test)]
mod tests;

+ 51
- 0
bw6_761/src/fields/tests.rs

@ -0,0 +1,51 @@
use ark_ff::{test_rng, Field, PrimeField};
use ark_serialize::{buffer_bit_byte_size, CanonicalSerialize};
use rand::Rng;
use crate::*;
use ark_curve_tests::fields::*;
#[test]
fn test_fr() {
let mut rng = test_rng();
let a: Fr = rng.gen();
let b: Fr = rng.gen();
field_test(a, b);
sqrt_field_test(a);
primefield_test::<Fr>();
}
#[test]
fn test_fq() {
let mut rng = test_rng();
let a: Fq = rng.gen();
let b: Fq = rng.gen();
field_test(a, b);
primefield_test::<Fq>();
sqrt_field_test(a);
let byte_size = a.serialized_size();
let (_, buffer_size) = buffer_bit_byte_size(Fq::size_in_bits());
assert_eq!(byte_size, buffer_size);
field_serialization_test::<Fq>(byte_size);
}
#[test]
fn test_fq3() {
let mut rng = test_rng();
let a: Fq3 = rng.gen();
let b: Fq3 = rng.gen();
field_test(a, b);
sqrt_field_test(a);
frobenius_test::<Fq3, _>(Fq::characteristic(), 13);
}
#[test]
fn test_fq6() {
let mut rng = test_rng();
let a: Fq6 = rng.gen();
let b: Fq6 = rng.gen();
field_test(a, b);
frobenius_test::<Fq6, _>(Fq::characteristic(), 13);
}

+ 34
- 0
bw6_761/src/lib.rs

@ -0,0 +1,34 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(
warnings,
unused,
future_incompatible,
nonstandard_style,
rust_2018_idioms
)]
#![forbid(unsafe_code)]
//! This library implements the BW6_761 curve generated in [[EG20]](https://eprint.iacr.org/2020/351).
//! The name denotes that it is a curve generated using the Brezing--Weng method, and that
//! its embedding degree is 6.
//! The main feature of this curve is that the scalar field equals the base field of the BLS12_377 curve.
//!
//! Curve information:
//! * Base field: q = 6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068299
//! * Scalar field: r = 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177
//! * valuation(q - 1, 2) = 1
//! * valuation(r - 1, 2) = 46
//!
//! G1 curve equation: y^2 = x^3 + ax + b, where
//! * a = 0,
//! * b = -1,
//!
//! G2 curve equation: y^2 = x^3 + Ax + B
//! * A = 0
//! * B = 4
mod curves;
mod fields;
pub use curves::*;
pub use fields::*;

+ 29
- 0
cp6_782/Cargo.toml

@ -0,0 +1,29 @@
[package]
name = "ark-cp6-782"
version = "0.1.0"
authors = [ "arkworks contributors" ]
description = "The CP6-782 pairing-friendly elliptic curve"
homepage = "https://arworks.rs"
repository = "https://github.com/arkworks/algebra"
documentation = "https://docs.rs/ark-cp6-782/"
keywords = ["cryptography", "finite fields", "elliptic curves" ]
categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0"
edition = "2018"
[dependencies]
ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false }
ark-bls12-377 = { path = "../bls12_377", default-features = false, features = [ "base_field" ] }
[dev-dependencies]
ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-curve-tests = { path = "../curve-tests", default-features = false }
rand = { version = "0.7", default-features = false }
rand_xorshift = "0.2"
[features]
default = []
std = [ "ark-std/std", "ark-ff/std", "ark-ec/std", "ark-bls12-377/std" ]

+ 126
- 0
cp6_782/src/curves/g1.rs

@ -0,0 +1,126 @@
use ark_ec::{
models::{ModelParameters, SWModelParameters},
short_weierstrass_jacobian::{GroupAffine, GroupProjective},
};
use ark_ff::{
biginteger::{BigInteger384, BigInteger832},
field_new,
};
use crate::{Fq, Fr};
pub type G1Affine = GroupAffine<Parameters>;
pub type G1Projective = GroupProjective<Parameters>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
impl ModelParameters for Parameters {
type BaseField = Fq;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = 5
#[rustfmt::skip]
const COEFF_A: Fq = field_new!(Fq, BigInteger832([
0x781c76643018bd7a,
0x64f3a5a4f1d1ad48,
0xd2f8a1eb4f72692d,
0xc35eb123c6ed72ca,
0xb58d6bcfd32de058,
0x841eab13b02a492c,
0x4b70dc5a54c487e7,
0x2f231a8808a74c59,
0x5e2915154d70b050,
0x8a40fa16f37a6b37,
0xd01980093a72c54b,
0xef6845c25398004c,
0x48,
]));
/// COEFF_B = 17764315118651679038286329069295091506801468118146712649886336045535808055361274148466772191243305528312843236347777260247138934336850548243151534538734724191505953341403463040067571652261229308333392040104884438208594329793895206056414
#[rustfmt::skip]
const COEFF_B: Fq = field_new!(Fq, BigInteger832([
0xec5bd271ad37429,
0x9db8ac843ecca28a,
0x94f29bcb7e01bc74,
0x1b0bebb77bb5af0,
0x75b8cef4aa27ee17,
0xb5767ae80812cf6b,
0x592fa41e377a0d8c,
0xb6c6deedbb52df3e,
0xcb1343e488737fd4,
0x878020734d05b5a9,
0x2f51354eddfa069a,
0x498e2ecdc545243e,
0x2c2,
]));
/// COFACTOR =
/// 86482221941698704497288378992285180119495364068003923046442785886272123124361700722982503222189455144364945735564951561028
#[rustfmt::skip]
const COFACTOR: &'static [u64] = &[
0x5657b9b57b942344,
0x84f9a65f3bd54eaf,
0x5ea4214e35cd127,
0xe3cbcbc14ec1501d,
0xf196cb845a3092ab,
0x7e14627ad0e19017,
0x217db4,
];
/// COFACTOR^(-1) mod r =
/// 163276846538158998893990986356139314746223949404500031940624325017036397274793417940375498603127780919653358641788
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, BigInteger384([
4179837108212676264,
15545810469293120493,
13202863094424182470,
9506285060796071546,
9248558385029790142,
87030208545296111,
]));
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G1_GENERATOR_X, G1_GENERATOR_Y);
}
/// G1_GENERATOR_X =
/// 5511163824921585887915590525772884263960974614921003940645351443740084257508990841338974915037175497689287870585840954231884082785026301437744745393958283053278991955159266640440849940136976927372133743626748847559939620888818486853646
#[rustfmt::skip]
pub const G1_GENERATOR_X: Fq = field_new!(Fq, BigInteger832([
0x5901480e5bc22290,
0x20024afcdb9bd3a9,
0x12dc18ff416e8138,
0x28c69aa0ea223e18,
0xafb1524a1eb7efe6,
0x3d5c34edc3764ca2,
0x736c2230c8466ce9,
0xacfaa04e051014f1,
0x5d5ff82f00ff2964,
0x64c13ba270a26eaf,
0x50e9864b56ab172e,
0xd8370826a322499e,
0x00000000000006f1,
]));
/// G1_GENERATOR_Y =
/// 7913123550914612057135582061699117755797758113868200992327595317370485234417808273674357776714522052694559358668442301647906991623400754234679697332299689255516547752391831738454121261248793568285885897998257357202903170202349380518443
#[rustfmt::skip]
pub const G1_GENERATOR_Y: Fq = field_new!(Fq, BigInteger832([
0x8af8b64b402e1953,
0xd1bbceb3a258ea51,
0xdca9efa3140aaa0d,
0x807a610058ddedb2,
0xeb898562fe88076c,
0x0e4342ca56dd8ce2,
0x4f5528d29f1bde9a,
0xf18b0c6c19feb372,
0x94503ac2fac9199c,
0xffc86a8aff08ea34,
0xf7b1295214735d8c,
0x44eda9e0f55edd10,
0x0000000000000ef3,
]));

+ 241
- 0
cp6_782/src/curves/g2.rs

@ -0,0 +1,241 @@
use ark_ec::{
models::{ModelParameters, SWModelParameters},
short_weierstrass_jacobian::{GroupAffine, GroupProjective},
};
use ark_ff::{
biginteger::{BigInteger384, BigInteger832},
field_new,
};
use crate::{Fq, Fq3, Fr, FQ_ZERO};
pub type G2Affine = GroupAffine<Parameters>;
pub type G2Projective = GroupProjective<Parameters>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
impl ModelParameters for Parameters {
type BaseField = Fq3;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = (0, 0, COEFF_A * TWIST^2) = (0, 0, 5)
#[rustfmt::skip]
const COEFF_A: Fq3 = field_new!(Fq3,
FQ_ZERO,
FQ_ZERO,
field_new!(Fq, BigInteger832([
0x781c76643018bd7a,
0x64f3a5a4f1d1ad48,
0xd2f8a1eb4f72692d,
0xc35eb123c6ed72ca,
0xb58d6bcfd32de058,
0x841eab13b02a492c,
0x4b70dc5a54c487e7,
0x2f231a8808a74c59,
0x5e2915154d70b050,
0x8a40fa16f37a6b37,
0xd01980093a72c54b,
0xef6845c25398004c,
0x48,
])),
);
/// COEFF_B = (G1::COEFF_B * TWIST^3, 0, 0) =
/// (7237353553714858194254855835825640240663090882935418626687402315497764195116318527743248304684159666286416318482685337633828994152723793439622384740540789612754127688659139509552568164770448654259255628317166934203899992395064470477612,
/// 0, 0)
#[rustfmt::skip]
const COEFF_B: Fq3 = field_new!(Fq3,
field_new!(Fq, BigInteger832([
0xc00a9afc5cbce615,
0x0260c2b730644102,
0x9051e955661691ec,
0x15f9af8514839e37,
0xfa62826ca407172b,
0x37043dc868f48874,
0x876b5588d132b025,
0x481952128335562a,
0x4ffa729aeddd7dcd,
0xe181a5dae94a399f,
0x671fb50145b255d8,
0xbc3860730482d728,
0x00000000000023dd,
])),
FQ_ZERO,
FQ_ZERO,
);
/// COFACTOR =
/// 43276679045916726782882096851503554444292580777869919574700824986947162516693702667493938255647666346010819253090121562084993205202476199057555142869892665220155573207800985012241638987472334344174208389303164492698303448192856551557283997344470334833850065978668184377503856699635686872344035470027430053642178229054516302338812152178131995800255516474185251732445975837621097393375441662426280154371264547168198834382681059556891327702516519955053315674076980350109237328216856859758931256208439575383786363605925879337208599843910819433766160937121108797819223653884174994325142959644019600
#[rustfmt::skip]
const COFACTOR: &'static [u64] = &[
0x4b77fca151d50b90,
0x8c98a12bd486d2fb,
0x1f0c9a51593693f8,
0x1d6f388069c063c1,
0x556e918748f06793,
0x2cea7dc01aae2140,
0x4216f0595cee44d0,
0x7a5e400154f633cf,
0xbb74eb9b6630846b,
0x8eb48c92998f3358,
0xbedd37f629e8e634,
0xc541018fe4d10cc7,
0x574956a099ace2c3,
0xa597504275948226,
0x7ecaaf050acb91f3,
0x0f25b044f4e9c932,
0xf8c39cbf0df97780,
0xd8f9eda95d6abf3e,
0xd1d80da227dd39c1,
0x8b589c61531dbce7,
0xfee4439281455474,
0x9eea59baa2aeb4a1,
0xa3b8a42c4e1e6f5a,
0xc4b99b0d9b077d21,
0xd09033887d09b4d2,
0x4a86d8ebb7fdf52a,
0xbe7ce44dd084e05d,
0x4ed25f7ebe6c44b3,
0xd7f8e3ef00255961,
0xa1ad2ad61580ef78,
0x19e70d3618ca3,
];
/// COFACTOR^(-1) mod r =
/// 45586359457219724873147353901735745013467692594291916855200979604570630929674383405372210802279573887880950375598
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, BigInteger384([
7373687189387546408,
11284009518041539892,
301575489693670883,
13203058298476577559,
18441611830097862156,
4115759498196698,
]));
/// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G2_GENERATOR_X, G2_GENERATOR_Y);
}
const G2_GENERATOR_X: Fq3 =
field_new!(Fq3, G2_GENERATOR_X_C0, G2_GENERATOR_X_C1, G2_GENERATOR_X_C2);
const G2_GENERATOR_Y: Fq3 =
field_new!(Fq3, G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1, G2_GENERATOR_Y_C2);
/// G2_GENERATOR_X_C0 =
/// 13426761183630949215425595811885033211332897733228446437546263564078445562454176776915160094418980045665397361295624472103734543457352048745726512354895954850428989867542989474136256025045975283415690491751906307188562464175510373683338
#[rustfmt::skip]
pub const G2_GENERATOR_X_C0: Fq = field_new!(Fq, BigInteger832([
0x03b3fe4c8d4ecac7,
0x9568212677524d1e,
0xf5de3f2228d187c1,
0x7bac772e31a420ef,
0x0255cf59968a612b,
0x991d4676f6b5d605,
0x02dd2ae4831d29ea,
0xbeca7c9a62e392c2,
0xfc1d0633d48d2fc5,
0x7867813be5f7d2a1,
0x6f567b6617030028,
0xf08c9fa6ca6809df,
0x0000000000000de9,
]));
/// G2_GENERATOR_X_C1 =
/// 20471601555918880743198170952645906008198510944268658573129351735028343217532386920456705632337352161031960990613816401042894531220068552819818037605513359562118363589199569321421558696125646867661360498323171027455638052943806292028610
#[rustfmt::skip]
pub const G2_GENERATOR_X_C1: Fq = field_new!(Fq, BigInteger832([
0xefd1b506e5fbe05f,
0xad27d47a4975140c,
0xfa11540132dbc27a,
0x8dca42b6da7c4717,
0x66d30fd7fd76207a,
0xb8e4f65c68932b1d,
0x3b7f971e93ad14be,
0xf860a89f4e582f9f,
0x7d438aaa3986f73b,
0xa37ec0c18c6e106a,
0x9f2dfb98b5185b54,
0x19995e421ca939bc,
0x0000000000002f4f,
]));
/// G2_GENERATOR_X_C2 =
/// 3905053196875761830053608605277158152930144841844497593936739534395003062685449846381431331169369910535935138116320442345524758217411779027270883193856999691582831339845600938304719916501940381093815781408183227875600753651697934495980
#[rustfmt::skip]
pub const G2_GENERATOR_X_C2: Fq = field_new!(Fq, BigInteger832([
0xc081ed832bdf911e,
0xb85ff7aeebdfe7b3,
0x96dce6bb307b14eb,
0x578f7ded84bd824c,
0xb799305a9971d184,
0x0116ad33c2874b90,
0x862dce68efdca245,
0x4190947c70534c1d,
0x1b1aa80334248d03,
0xb13b07aff63fcf27,
0x5727687b73ab4fff,
0xf559a7f4eb8d180a,
0x0000000000002d37,
]));
/// G2_GENERATOR_Y_C0 =
/// 8567517639523571619872938228644013584947463594196306323477160496987712111576624702939472765993995586889532559039169098780892505598589581147768095093536988446010255611523736706017580686335404469207486594272103717837888228343074699140243
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C0: Fq = field_new!(Fq, BigInteger832([
0x3f680b59e26b33d1,
0x720fdf65b9e15b17,
0x0f0b56def11247b1,
0x5ea05417c8a4a52c,
0x4ad59dc4f7c47a09,
0xf393e0db62107115,
0xde3b16404a53d2bb,
0xeaa74961636280e0,
0x2d16ccd14cf5a88c,
0x5667565a06187d0e,
0xb446fdc7565d0261,
0xd3ad395d6fd0faab,
0x0000000000000655,
]));
/// G2_GENERATOR_Y_C1 =
/// 3890537069205870914984502594450293167889863914413852788876350245583932846980126025043974070704295857226211547108005650399870458089721518559480870503159804530091559886149680718531004778697982910253701559194337987238111062202037698927752
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C1: Fq = field_new!(Fq, BigInteger832([
0x9e86cc63207679dd,
0x4e16d9a9d87c3e47,
0xdbee3524db80627d,
0x137322b87d93befc,
0x24a7ca2f9aae90a0,
0x44abea538df3e854,
0xc01d176c6e042eee,
0xf5fcc4caabc75699,
0x1f99972699a38960,
0x30d4cc8256bf963d,
0xa3634826edcfefff,
0x34f3bd0c8e5a4b38,
0x0000000000001d28,
]));
/// G2_GENERATOR_Y_C2 =
/// 10936269922612615564271188303104593362724754284143779051599749016735041389483971486958818324356025479751246744831831158558101688599198721653921723013062333636402617118847009085485166284126970598561393411916461254016145116183331671450721
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C2: Fq = field_new!(Fq, BigInteger832([
0xfc478105dedf3654,
0xa6fcfcfdd2710d6a,
0x05a68c283d5d4c65,
0x9fab8d94c667a679,
0x009b0a616ea54ff9,
0xf0df517bc7bc6382,
0xdb44338e7491f5b7,
0xcd192a7e53453f45,
0xa041a7a60982d92c,
0x4dd01c62bae4c7ff,
0x79a69a54e6b66178,
0xd47b0bfe832b05f8,
0x00000000000000ef,
]));

+ 223
- 0
cp6_782/src/curves/mod.rs

@ -0,0 +1,223 @@
use ark_ec::{models::SWModelParameters, PairingEngine};
use ark_ff::{
biginteger::BigInteger832,
field_new,
fields::{BitIteratorBE, Field, FpParameters},
One,
};
use crate::{Fq, Fq3, Fq6, FqParameters, Fr};
pub mod g1;
pub use self::g1::{G1Affine, G1Projective};
pub mod g2;
pub use self::g2::{G2Affine, G2Projective};
#[cfg(test)]
mod tests;
pub type GT = Fq6;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct CP6_782;
impl PairingEngine for CP6_782 {
type Fr = Fr;
type G1Projective = G1Projective;
type G1Affine = G1Affine;
type G1Prepared = G1Affine;
type G2Projective = G2Projective;
type G2Affine = G2Affine;
type G2Prepared = G2Affine;
type Fq = Fq;
type Fqe = Fq3;
type Fqk = Fq6;
fn miller_loop<'a, I>(i: I) -> Self::Fqk
where
I: IntoIterator<Item = &'a (Self::G1Prepared, Self::G2Prepared)>,
{
let mut result = Self::Fqk::one();
for &(ref p, ref q) in i {
result *= &CP6_782::ate_miller_loop(p, q);
}
result
}
fn final_exponentiation(r: &Self::Fqk) -> Option<Self::Fqk> {
Some(CP6_782::final_exponentiation(r))
}
}
impl CP6_782 {
pub fn ate_pairing(p: &G1Affine, q: &G2Affine) -> GT {
CP6_782::final_exponentiation(&CP6_782::ate_miller_loop(p, q))
}
fn ate_miller_loop(p: &G1Affine, q: &G2Affine) -> Fq6 {
let px = p.x;
let py = p.y;
let qx = q.x;
let qy = q.y;
let mut py_twist_squared = TWIST.square();
py_twist_squared.mul_assign_by_fp(&py);
let mut old_rx;
let mut old_ry;
let mut rx = qx;
let mut ry = qy;
let mut f = Fq6::one();
// The for loop is executed for all bits (EXCEPT the MSB itself) of
// cp6_782_param_p (skipping leading zeros) in MSB to LSB order
for bit in BitIteratorBE::without_leading_zeros(ATE_LOOP_COUNT).skip(1) {
old_rx = rx;
old_ry = ry;
let old_rx_square = old_rx.square();
let old_rx_square_3 = old_rx_square.double() + &old_rx_square;
let old_rx_square_3_a = old_rx_square_3 + &g2::Parameters::COEFF_A;
let old_ry_double_inverse = old_ry.double().inverse().unwrap();
let gamma = old_rx_square_3_a * &old_ry_double_inverse;
let gamma_twist = gamma * &TWIST;
let gamma_old_rx = gamma * &old_rx;
let mut gamma_twist_px = gamma_twist;
gamma_twist_px.mul_assign_by_fp(&px);
let x = py_twist_squared;
let y = gamma_old_rx - &old_ry - &gamma_twist_px;
let ell_rr_at_p = Fq6::new(x, y);
rx = gamma.square() - &old_rx.double();
ry = gamma * &(old_rx - &rx) - &old_ry;
f = f.square() * &ell_rr_at_p;
if bit {
old_rx = rx;
old_ry = ry;
let gamma = (old_ry - &qy) * &((old_rx - &qx).inverse().unwrap());
let gamma_twist = gamma * &TWIST;
let gamma_qx = gamma * &qx;
let mut gamma_twist_px = gamma_twist;
gamma_twist_px.mul_assign_by_fp(&px);
let x = py_twist_squared;
let y = gamma_qx - &qy - &gamma_twist_px;
let ell_rq_at_p = Fq6::new(x, y);
rx = gamma.square() - &old_rx - &qx;
ry = gamma * &(old_rx - &rx) - &old_ry;
f = f * &ell_rq_at_p;
}
}
f
}
fn final_exponentiation(value: &Fq6) -> GT {
let value_inv = value.inverse().unwrap();
let value_to_first_chunk = CP6_782::final_exponentiation_first(value, &value_inv);
let value_inv_to_first_chunk = CP6_782::final_exponentiation_first(&value_inv, value);
CP6_782::final_exponentiation_last(&value_to_first_chunk, &value_inv_to_first_chunk)
}
fn final_exponentiation_first(elt: &Fq6, elt_inv: &Fq6) -> Fq6 {
// (q^3-1)*(q+1)
// elt_q3 = elt^(q^3)
let mut elt_q3 = elt.clone();
elt_q3.frobenius_map(3);
// elt_q3_over_elt = elt^(q^3-1)
let elt_q3_over_elt = elt_q3 * elt_inv;
// alpha = elt^((q^3-1) * q)
let mut alpha = elt_q3_over_elt.clone();
alpha.frobenius_map(1);
// beta = elt^((q^3-1)*(q+1)
alpha * &elt_q3_over_elt
}
fn final_exponentiation_last(elt: &Fq6, elt_inv: &Fq6) -> Fq6 {
let mut elt_q = elt.clone();
elt_q.frobenius_map(1);
let w1_part = elt_q.cyclotomic_exp(&FINAL_EXPONENT_LAST_CHUNK_W1);
let w0_part = if FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG {
elt_inv.cyclotomic_exp(&FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0)
} else {
elt.cyclotomic_exp(&FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0)
};
w1_part * &w0_part
}
}
/// FQ_ZERO = 0
pub const FQ_ZERO: Fq = field_new!(Fq, BigInteger832([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]));
/// FQ_ONE = 1
pub const FQ_ONE: Fq = field_new!(Fq, FqParameters::R);
/// TWIST = (0, 1, 0)
pub const TWIST: Fq3 = field_new!(Fq3, FQ_ZERO, FQ_ONE, FQ_ZERO);
/// ATE_IS_LOOP_COUNT_NEG = false
pub const ATE_IS_LOOP_COUNT_NEG: bool = false;
/// ATE_LOOP_COUNT =
/// 506464946133393486072777102926336625944849939610982267859828541006717966526573193706126370441346337661774335955699621
pub const ATE_LOOP_COUNT: [u64; 13] = [
0x55c5b9b57b942ae8,
0x3d52287d3dfd424a,
0xcf1ff9d6a543deb7,
0x820c9c5711ceeebc,
0x549a2d44305d20fe,
0x50f5c131afd70235,
0xab3596c8617c5792,
0x830c728d80f9d78b,
0x6a7223ee72023d07,
0xbc5d176b746af026,
0xe959283d8f526663,
0xc4d2263babf8941f,
0x3848,
];
/// FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG = true
pub const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true;
/// FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0 =
/// 7000705447348627246181409558336018323010329260726930841638672011287206690002601216854775649561085256265269640040570922609783227469279331691880282815325569032149343779036142830666859805506518426649197067288711084398033
pub const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger832 = BigInteger832([
0xb62ef36af72855d1,
0x676b5cef49d290fa,
0xd17fcf3c60947427,
0x5b93d992bc1b2849,
0x2171887cecd072cb,
0x879a2873f1516f4a,
0x8cc6856bd2cdf24e,
0xbff4fb6644d01993,
0x5dcbeea3e31ea667,
0x5f256f47681649f3,
0x2355a2b0839967fe,
0x144ed,
0x0,
]);
/// FINAL_EXPONENT_LAST_CHUNK_W1 =
/// 86482221941698704497288378992285180119495364068003923046442785886272123124361700722982503222189455144364945735564951562986
pub const FINAL_EXPONENT_LAST_CHUNK_W1: BigInteger832 = BigInteger832([
0x5657b9b57b942aea,
0x84f9a65f3bd54eaf,
0x5ea4214e35cd127,
0xe3cbcbc14ec1501d,
0xf196cb845a3092ab,
0x7e14627ad0e19017,
0x217db4,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
]);

+ 77
- 0
cp6_782/src/curves/tests.rs

@ -0,0 +1,77 @@
use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ff::{test_rng, Field, One, PrimeField};
use rand::Rng;
use crate::*;
use ark_curve_tests::{curves::*, groups::*};
#[test]
fn test_g1_projective_curve() {
curve_tests::<G1Projective>();
sw_tests::<g1::Parameters>();
}
#[test]
fn test_g1_projective_group() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G1Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g1_generator() {
let generator = G1Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g2_projective_curve() {
curve_tests::<G2Projective>();
sw_tests::<g2::Parameters>();
}
#[test]
fn test_g2_projective_group() {
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g2_generator() {
let generator = G2Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_bilinearity() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G2Projective = rng.gen();
let s: Fr = rng.gen();
let sa = a.mul(s);
let sb = b.mul(s);
let ans1 = CP6_782::pairing(sa, b);
let ans2 = CP6_782::pairing(a, sb);
let ans3 = CP6_782::pairing(a, b).pow(s.into_repr());
assert_eq!(ans1, ans2);
assert_eq!(ans2, ans3);
assert_ne!(ans1, Fq6::one());
assert_ne!(ans2, Fq6::one());
assert_ne!(ans3, Fq6::one());
assert_eq!(ans1.pow(Fr::characteristic()), Fq6::one());
assert_eq!(ans2.pow(Fr::characteristic()), Fq6::one());
assert_eq!(ans3.pow(Fr::characteristic()), Fq6::one());
}

+ 166
- 0
cp6_782/src/fields/fq.rs

@ -0,0 +1,166 @@
use ark_ff::{
biginteger::BigInteger832 as BigInteger,
fields::{FftParameters, Fp832, Fp832Parameters, FpParameters},
};
pub type Fq = Fp832<FqParameters>;
pub struct FqParameters;
impl Fp832Parameters for FqParameters {}
impl FftParameters for FqParameters {
type BigInt = BigInteger;
const TWO_ADICITY: u32 = 3;
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
18044746167194862600u64,
63590321303744709u64,
5009346151370959890u64,
2859114157767503991u64,
8301813204852325413u64,
5629414263664332594u64,
2637340888701394641u64,
17433538052687852753u64,
2230763098934759248u64,
3785382115983092023u64,
8895511354022222370u64,
15792083141709071785u64,
1328u64,
]);
}
impl FpParameters for FqParameters {
/// MODULUS = 22369874298875696930346742206501054934775599465297184582183496627646774052458024540232479018147881220178054575403841904557897715222633333372134756426301062487682326574958588001132586331462553235407484089304633076250782629492557320825577
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
0xdace79b57b942ae9,
0x545d85c16dfd424a,
0xee135c065f4d26b7,
0x9c2f764a12c4024b,
0x1ad533049cfe6a39,
0x52a3fb77c79c1320,
0xab3596c8617c5792,
0x830c728d80f9d78b,
0x6a7223ee72023d07,
0xbc5d176b746af026,
0xe959283d8f526663,
0xc4d2263babf8941f,
0x3848,
]);
const MODULUS_BITS: u32 = 782;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
const REPR_SHAVE_BITS: u32 = 50;
#[rustfmt::skip]
const R: BigInteger = BigInteger([
11190988450819017841u64,
16170411717126802030u64,
2265463223430229059u64,
16946880912571045974u64,
11155248462028513229u64,
12855672356664541314u64,
8489376931127408159u64,
2655797810825538098u64,
9648483887143916718u64,
17514963461276738952u64,
16777089214204267338u64,
15649035958020076168u64,
8659u64,
]);
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
13983406830510863714u64,
17863856572171232656u64,
1698388424046564526u64,
1773634430448388392u64,
8684647957094413275u64,
3992637317298078843u64,
18420879196616862245u64,
3238482510270583127u64,
7928200707794018216u64,
10024831010452223910u64,
9613847725664942650u64,
15361265984156787358u64,
7833u64,
]);
const INV: u64 = 14469047335842394791u64;
/// GENERATOR = 13
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
16669393626057438558u64,
1640520694378723217u64,
1598646156981121135u64,
12401834967100173388u64,
2356467520877704673u64,
14759118825104212161u64,
5556628239575210651u64,
5317520392768798654u64,
16398429955031064995u64,
3556102264904210145u64,
8166834915717907988u64,
11926665585800594452u64,
11716u64,
]);
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x6d673cdabdca1574,
0xaa2ec2e0b6fea125,
0xf709ae032fa6935b,
0xce17bb2509620125,
0xd6a99824e7f351c,
0x2951fdbbe3ce0990,
0xd59acb6430be2bc9,
0xc1863946c07cebc5,
0x353911f739011e83,
0xde2e8bb5ba357813,
0xf4ac941ec7a93331,
0x6269131dd5fc4a0f,
0x1c24,
]);
// (T - 1)/2 =
// 1398117143679731058146671387906315933423474966581074036386468539227923378278626533764529938634242576261128410962740119034868607201414583335758422276643816405480145410934911750070786645716409577212967755581539567265673914343284832551598
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0xadace79b57b942ae,
0x7545d85c16dfd424,
0xbee135c065f4d26b,
0x99c2f764a12c4024,
0x1ad533049cfe6a3,
0x252a3fb77c79c132,
0xbab3596c8617c579,
0x7830c728d80f9d78,
0x66a7223ee72023d0,
0x3bc5d176b746af02,
0xfe959283d8f52666,
0x8c4d2263babf8941,
0x384,
]);
// T =
// 2796234287359462116293342775812631866846949933162148072772937078455846756557253067529059877268485152522256821925480238069737214402829166671516844553287632810960290821869823500141573291432819154425935511163079134531347828686569665103197
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0x5b59cf36af72855d,
0xea8bb0b82dbfa849,
0x7dc26b80cbe9a4d6,
0x3385eec942588049,
0x35aa660939fcd47,
0x4a547f6ef8f38264,
0x7566b2d90c2f8af2,
0xf0618e51b01f3af1,
0xcd4e447dce4047a0,
0x778ba2ed6e8d5e04,
0xfd2b2507b1ea4ccc,
0x189a44c7757f1283,
0x709,
]);
}

+ 204
- 0
cp6_782/src/fields/fq3.rs

@ -0,0 +1,204 @@
use crate::Fq;
use ark_ff::{
biginteger::BigInteger832 as BigInteger,
field_new,
fields::fp3::{Fp3, Fp3Parameters},
Field,
};
pub type Fq3 = Fp3<Fq3Parameters>;
pub struct Fq3Parameters;
impl Fp3Parameters for Fq3Parameters {
type Fp = Fq;
/// NONRESIDUE = 13
#[rustfmt::skip]
const NONRESIDUE: Fq = field_new!(Fq, BigInteger([
0xe755952f4650755e,
0x16c44ce1331ef791,
0x162f8835b467306f,
0xac1c2b31e1062c4c,
0x20b3dab9a2a935e1,
0xccd2ec5fd01e00c1,
0x4d1d1bf190c8da9b,
0x49cba09fb0e13fbe,
0xe392ed2957c061a3,
0x3159d02b3c93d6e1,
0x71566d160a9f8614,
0xa5840728fc854414,
0x2dc4,
]));
const TWO_ADICITY: u32 = 3;
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: &'static [u64] = &[
0x62730e2cd2029617,
0x660647f735cb88cf,
0x274359d60784f69d,
0x83067194eb102629,
0x54ea4a12a9381160,
0xade0b24e398dac25,
0xb476ae9f927e81cb,
0x220fd4a9178adc3b,
0x57e0cb9b0569745b,
0xba15024addc8f52e,
0x145b9bc116144ab6,
0x6bc2260726e88b15,
0x51da6bf151066474,
0x9fd1b3190f6320cf,
0x2097bfb7bf4167b0,
0x27c35b1e7e628e09,
0x94f80c9d623dd9bb,
0x20bfa6d5bf31e7d3,
0x19fb862c049d3a8,
0xdf4c5efe04c0cec1,
0x32c9a8abe9b50297,
0x268d5c2076b44f0a,
0x76027ec67b23ca21,
0x248d61e0c45d270,
0x419cd0d1d6be027e,
0xbcd8dc3b1986ef18,
0x73093d8719c862c2,
0x651d60f8f9f6fcd9,
0x8dabebe38a09b261,
0xfa85b5a9e180cd3f,
0x6a97fc618f319fb7,
0xce08b93a5652a8e1,
0x37525cbc4ba24cf9,
0xb104c580df9d2150,
0x1407c1bfe240a89d,
0x34c96a73372daf9a,
0x2b87fda171,
];
#[rustfmt::skip]
const QUADRATIC_NONRESIDUE_TO_T: (Fq, Fq, Fq) = (
field_new!(Fq, BigInteger([
0x59987c0ef8e31739,
0x59578d750d6f57dd,
0x9672547570dddab8,
0x1a1f630e1d6dbdd5,
0xde15f46e52d7613e,
0x6a1b6e4f80179926,
0x461ad119d93123b,
0x12054e3654907ed9,
0x85ea06b12bf811a0,
0xc01d53d07347f9ec,
0x70c424eb666c3922,
0x1796ce4ed605d49e,
0x68b,
])),
field_new!(Fq, BigInteger([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),
field_new!(Fq, BigInteger([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),
);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP3_C1: &'static [Fq] = &[
field_new!(Fq, BigInteger([
0x9b4e60b420910c71,
0xe068d7c83f284a6e,
0x1f708acc7c452c43,
0xeb2f6a66cca51856,
0x9acf675f886e9fcd,
0xb26885e567cc8082,
0x75d05357183eb61f,
0x24db4a09b5842a32,
0x85e64cf9ba4b14ae,
0xf311a6784358a588,
0xe8d431c061aecb4a,
0xd92c8b4aab19f288,
0x21d3,
])),
field_new!(Fq, BigInteger([
0xe793e750fc0c0fdc,
0x28cd75f5634a867e,
0xde5e9b1261eb3c33,
0x68a0fb1c17595903,
0x19626d2c9f392e46,
0xc4d95794cb378b83,
0x54870f1f582d67c9,
0xf3f1a0ac4aceb56d,
0x811361215ea4fd47,
0x32cd6ee17d95bd00,
0x725f9881049a9c52,
0x5acb70be0613a307,
0x11bb,
])),
field_new!(Fq, BigInteger([
0x57ec31b05ef70e9c,
0x4b273803cb8a715d,
0xf0443627811cbe40,
0x485f10c72ec590f1,
0x66a35e7875569c25,
0xdb621dfd9498071a,
0xe0de3451f11039a8,
0x6a3f87d780a6f7eb,
0x637875d359122b11,
0x967e0211b37c8d9d,
0x8e255dfc2908fec6,
0x90da2a32facafe8f,
0x4b9,
])),
];
#[rustfmt::skip]
const FROBENIUS_COEFF_FP3_C2: &'static [Fq] = &[
field_new!(Fq, BigInteger([
0x9b4e60b420910c71,
0xe068d7c83f284a6e,
0x1f708acc7c452c43,
0xeb2f6a66cca51856,
0x9acf675f886e9fcd,
0xb26885e567cc8082,
0x75d05357183eb61f,
0x24db4a09b5842a32,
0x85e64cf9ba4b14ae,
0xf311a6784358a588,
0xe8d431c061aecb4a,
0xd92c8b4aab19f288,
0x21d3,
])),
field_new!(Fq, BigInteger([
0x57ec31b05ef70e9c,
0x4b273803cb8a715d,
0xf0443627811cbe40,
0x485f10c72ec590f1,
0x66a35e7875569c25,
0xdb621dfd9498071a,
0xe0de3451f11039a8,
0x6a3f87d780a6f7eb,
0x637875d359122b11,
0x967e0211b37c8d9d,
0x8e255dfc2908fec6,
0x90da2a32facafe8f,
0x4b9,
])),
field_new!(Fq, BigInteger([
0xe793e750fc0c0fdc,
0x28cd75f5634a867e,
0xde5e9b1261eb3c33,
0x68a0fb1c17595903,
0x19626d2c9f392e46,
0xc4d95794cb378b83,
0x54870f1f582d67c9,
0xf3f1a0ac4aceb56d,
0x811361215ea4fd47,
0x32cd6ee17d95bd00,
0x725f9881049a9c52,
0x5acb70be0613a307,
0x11bb,
])),
];
#[inline(always)]
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp {
let original = *fe;
let mut four_fe = fe.double();
four_fe.double_in_place();
let eight_fe = four_fe.double();
eight_fe + &four_fe + &original
}
}

+ 112
- 0
cp6_782/src/fields/fq6.rs

@ -0,0 +1,112 @@
use crate::{Fq, Fq3, Fq3Parameters, FQ_ONE, FQ_ZERO};
use ark_ff::{
biginteger::BigInteger832 as BigInteger,
field_new,
fields::fp6_2over3::{Fp6, Fp6Parameters},
};
pub type Fq6 = Fp6<Fq6Parameters>;
pub struct Fq6Parameters;
impl Fp6Parameters for Fq6Parameters {
type Fp3Params = Fq3Parameters;
/// NONRESIDUE = (0, 1, 0).
#[rustfmt::skip]
const NONRESIDUE: Fq3 = field_new!(Fq3, FQ_ZERO, FQ_ONE, FQ_ZERO);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C1: &'static [Fq] = &[
field_new!(Fq, BigInteger([
0x9b4e60b420910c71,
0xe068d7c83f284a6e,
0x1f708acc7c452c43,
0xeb2f6a66cca51856,
0x9acf675f886e9fcd,
0xb26885e567cc8082,
0x75d05357183eb61f,
0x24db4a09b5842a32,
0x85e64cf9ba4b14ae,
0xf311a6784358a588,
0xe8d431c061aecb4a,
0xd92c8b4aab19f288,
0x21d3,
])),
field_new!(Fq, BigInteger([
0x82e248051c9d1c4d,
0x9364dbda272d0ed,
0xfdcf25dede306877,
0x53d06582e3fe7159,
0xb431d48c27a7ce14,
0x7741dd7a33040c05,
0xca576276706c1de9,
0x18cceab60052df9f,
0x6f9ae1b18f011f6,
0x25df1559c0ee6289,
0x5b33ca416649679d,
0x33f7fc08b12d9590,
0x338f,
])),
field_new!(Fq, BigInteger([
0xe793e750fc0c0fdc,
0x28cd75f5634a867e,
0xde5e9b1261eb3c33,
0x68a0fb1c17595903,
0x19626d2c9f392e46,
0xc4d95794cb378b83,
0x54870f1f582d67c9,
0xf3f1a0ac4aceb56d,
0x811361215ea4fd47,
0x32cd6ee17d95bd00,
0x725f9881049a9c52,
0x5acb70be0613a307,
0x11bb,
])),
field_new!(Fq, BigInteger([
0x3f8019015b031e78,
0x73f4adf92ed4f7dc,
0xcea2d139e307fa73,
0xb1000be3461ee9f5,
0x8005cba5148fca6b,
0xa03b75925fcf929d,
0x35654371493da172,
0x5e312883cb75ad59,
0xe48bd6f4b7b72859,
0xc94b70f331124a9d,
0x84f67d2da39b18,
0xeba59af100dea197,
0x1674,
])),
field_new!(Fq, BigInteger([
0x57ec31b05ef70e9c,
0x4b273803cb8a715d,
0xf0443627811cbe40,
0x485f10c72ec590f1,
0x66a35e7875569c25,
0xdb621dfd9498071a,
0xe0de3451f11039a8,
0x6a3f87d780a6f7eb,
0x637875d359122b11,
0x967e0211b37c8d9d,
0x8e255dfc2908fec6,
0x90da2a32facafe8f,
0x4b9,
])),
field_new!(Fq, BigInteger([
0xf33a92647f881b0d,
0x2b900fcc0ab2bbcb,
0xfb4c0f3fd61ea84,
0x338e7b2dfb6aa948,
0x172c5d7fdc53bf3,
0x8dcaa3e2fc64879d,
0x56ae87a9094eefc8,
0x8f1ad1e1362b221e,
0xe95ec2cd135d3fbf,
0x898fa889f6d53325,
0x76f98fbc8ab7ca11,
0x6a06b57da5e4f118,
0x268d,
])),
];
}

+ 1
- 0
cp6_782/src/fields/fr.rs

@ -0,0 +1 @@
pub use ark_bls12_377::{Fq as Fr, FqParameters as FrParameters};

+ 14
- 0
cp6_782/src/fields/mod.rs

@ -0,0 +1,14 @@
pub mod fr;
pub use self::fr::*;
pub mod fq;
pub use self::fq::*;
pub mod fq3;
pub use self::fq3::*;
pub mod fq6;
pub use self::fq6::*;
#[cfg(all(feature = "cp6_782", test))]
mod tests;

+ 51
- 0
cp6_782/src/fields/tests.rs

@ -0,0 +1,51 @@
use ark_ff::{test_rng, Field, PrimeField};
use ark_serialize::{buffer_bit_byte_size, CanonicalSerialize};
use rand::Rng;
use crate::*;
use ark_curve_tests::fields::*;
#[test]
fn test_fr() {
let mut rng = test_rng();
let a: Fr = rng.gen();
let b: Fr = rng.gen();
field_test(a, b);
sqrt_field_test(a);
primefield_test::<Fr>();
}
#[test]
fn test_fq() {
let mut rng = test_rng();
let a: Fq = rng.gen();
let b: Fq = rng.gen();
field_test(a, b);
primefield_test::<Fq>();
sqrt_field_test(a);
let byte_size = a.serialized_size();
let (_, buffer_size) = buffer_bit_byte_size(Fq::size_in_bits());
assert_eq!(byte_size, buffer_size);
field_serialization_test::<Fq>(byte_size);
}
#[test]
fn test_fq3() {
let mut rng = test_rng();
let a: Fq3 = rng.gen();
let b: Fq3 = rng.gen();
field_test(a, b);
sqrt_field_test(a);
frobenius_test::<Fq3, _>(Fq::characteristic(), 13);
}
#[test]
fn test_fq6() {
let mut rng = test_rng();
let a: Fq6 = rng.gen();
let b: Fq6 = rng.gen();
field_test(a, b);
frobenius_test::<Fq6, _>(Fq::characteristic(), 13);
}

+ 33
- 0
cp6_782/src/lib.rs

@ -0,0 +1,33 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(
warnings,
unused,
future_incompatible,
nonstandard_style,
rust_2018_idioms
)]
#![forbid(unsafe_code)]
//! This library implements the CP6_782 curve generated in [[BCGMMW20, “Zexe”]](https://eprint.iacr.org/2018/962).
//! The name denotes that it was generated using the Cocks--Pinch method for the embedding degree 6.
//! The main feature of this curve is that the scalar field equals the base field of the BLS12_377 curve.
//!
//! Curve information:
//! * Base field: q = 22369874298875696930346742206501054934775599465297184582183496627646774052458024540232479018147881220178054575403841904557897715222633333372134756426301062487682326574958588001132586331462553235407484089304633076250782629492557320825577
//! * Scalar field: r = 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177
//! * valuation(q - 1, 2) = 3
//! * valuation(r - 1, 2) = 46
//!
//! G1 curve equation: y^2 = x^3 + ax + b, where
//! * a = 5,
//! * b = 17764315118651679038286329069295091506801468118146712649886336045535808055361274148466772191243305528312843236347777260247138934336850548243151534538734724191505953341403463040067571652261229308333392040104884438208594329793895206056414,
//!
//! G2 curve equation: y^2 = x^3 + Ax + B
//! * A = Fq3(0, 0, 5)
//! * B = Fq3(7237353553714858194254855835825640240663090882935418626687402315497764195116318527743248304684159666286416318482685337633828994152723793439622384740540789612754127688659139509552568164770448654259255628317166934203899992395064470477612, 0, 0)
mod curves;
mod fields;
pub use curves::*;
pub use fields::*;

+ 50
- 0
curve-benches/Cargo.toml

@ -0,0 +1,50 @@
[package]
name = "ark-curve-benches"
version = "0.1.1-alpha.0"
authors = [
"Sean Bowe",
"Alessandro Chiesa",
"Matthew Green",
"Ian Miers",
"Pratyush Mishra",
"Howard Wu"
]
description = "A benchmark library for finite fields and elliptic curves"
homepage = "https://arkworks.rs"
repository = "https://github.com/arkworks-rs/algebra"
documentation = "https://docs.rs/algebra/"
keywords = ["cryptography", "finite fields", "elliptic curves", "pairing"]
categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0"
edition = "2018"
publish = false
build = "build.rs"
################################# Dependencies ################################
[dependencies]
ark-ec = { git = "https://github.com/arkworks-rs/algebra" }
ark-ff = { git = "https://github.com/arkworks-rs/algebra" }
ark-serialize = { git = "https://github.com/arkworks-rs/algebra" }
ark-mnt4-298 = { path = "../mnt4_298", optional = true }
ark-mnt6-298 = { path = "../mnt6_298", optional = true }
ark-mnt4-753 = { path = "../mnt4_753", optional = true }
ark-mnt6-753 = { path = "../mnt6_753", optional = true }
ark-bn254 = { path = "../bn254", default-features = false, optional = true }
ark-bls12-377 = { path = "../bls12_377", optional = true }
ark-bls12-381 = { path = "../bls12_381", optional = true }
ark-bw6-761 = { path = "../bw6_761", optional = true }
ark-cp6-782 = { path = "../cp6_782", optional = true }
rand = "0.7"
rand_xorshift = { version = "0.2" }
paste = "1.0"
[features]
asm = [ "ark-ff/asm"]
n_fold = []
[build-dependencies]
rustc_version = "0.2"

+ 1
- 0
curve-benches/LICENSE-APACHE

@ -0,0 +1 @@
../LICENSE-APACHE

+ 1
- 0
curve-benches/LICENSE-MIT

@ -0,0 +1 @@
../LICENSE-MIT

+ 9
- 0
curve-benches/build.rs

@ -0,0 +1,9 @@
extern crate rustc_version;
use rustc_version::{version_meta, Channel};
fn main() {
if version_meta().expect("nightly check failed").channel == Channel::Nightly {
println!("cargo:rustc-cfg=nightly");
}
}

+ 23
- 0
curve-benches/src/curves/bls12_377.rs

@ -0,0 +1,23 @@
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::{AddAssign, MulAssign, SubAssign};
use ark_bls12_377::bls12_377::{
fq::Fq, fq2::Fq2, fr::Fr, Bls12_377, Fq12, G1Affine, G1Projective as G1, G2Affine,
G2Projective as G2, Parameters,
};
use ark_ec::{
bls12::{G1Prepared, G2Prepared},
PairingEngine, ProjectiveCurve,
};
use ark_ff::{
biginteger::{BigInteger256 as FrRepr, BigInteger384 as FqRepr},
BigInteger, Field, PrimeField, SquareRootField, UniformRand,
};
ec_bench!();
f_bench!(1, Fq2, Fq2, fq2);
f_bench!(2, Fq12, Fq12, fq12);
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
f_bench!(Fr, Fr, FrRepr, FrRepr, fr);
pairing_bench!(Bls12_377, Fq12, prepared_v);

+ 23
- 0
curve-benches/src/curves/bls12_381.rs

@ -0,0 +1,23 @@
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::{AddAssign, MulAssign, SubAssign};
use ark_bls12_381::bls12_381::{
fq::Fq, fq2::Fq2, fr::Fr, Bls12_381, Fq12, G1Affine, G1Projective as G1, G2Affine,
G2Projective as G2, Parameters,
};
use ark_ec::{
bls12::{G1Prepared, G2Prepared},
PairingEngine, ProjectiveCurve,
};
use ark_ff::{
biginteger::{BigInteger256 as FrRepr, BigInteger384 as FqRepr},
BigInteger, Field, PrimeField, SquareRootField, UniformRand,
};
ec_bench!();
f_bench!(1, Fq2, Fq2, fq2);
f_bench!(2, Fq12, Fq12, fq12);
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
f_bench!(Fr, Fr, FrRepr, FrRepr, fr);
pairing_bench!(Bls12_381, Fq12, prepared_v);

+ 23
- 0
curve-benches/src/curves/bn254.rs

@ -0,0 +1,23 @@
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::{AddAssign, MulAssign, SubAssign};
use ark_ec::{
bn::{G1Prepared, G2Prepared},
PairingEngine, ProjectiveCurve,
};
use ark_ef::{
biginteger::{BigInteger256 as FrRepr, BigInteger256 as FqRepr},
BigInteger, Field, PrimeField, SquareRootField, UniformRand,
};
use ark_en254::bn254::{
fq::Fq, fq2::Fq2, fr::Fr, Bls12_381, Fq12, G1Affine, G1Projective as G1, G2Affine,
G2Projective as G2, Parameters,
};
ec_bench!();
f_bench!(1, Fq2, Fq2, fq2);
f_bench!(2, Fq12, Fq12, fq12);
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
f_bench!(Fr, Fr, FrRepr, FrRepr, fr);
pairing_bench!(Bn254, Fq12, prepared_v);

+ 23
- 0
curve-benches/src/curves/bw6_761.rs

@ -0,0 +1,23 @@
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::{AddAssign, MulAssign, SubAssign};
use ark_bls12_377::bw6_761::{
fq::Fq, fq3::Fq3, fr::Fr, Fq6, G1Affine, G1Projective as G1, G2Affine, G2Projective as G2,
Parameters, BW6_761,
};
use ark_ec::{
bw6::{G1Prepared, G2Prepared},
PairingEngine, ProjectiveCurve,
};
use ark_ff::{
biginteger::{BigInteger384 as FrRepr, BigInteger768 as FqRepr},
BigInteger, Field, PrimeField, SquareRootField, UniformRand,
};
ec_bench!();
f_bench!(1, Fq3, Fq3, fq3);
f_bench!(2, Fq6, Fq6, fq6);
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
f_bench!(Fr, Fr, FrRepr, FrRepr, fr);
pairing_bench!(BW6_761, Fq6, prepared_v);

+ 20
- 0
curve-benches/src/curves/cp6_782.rs

@ -0,0 +1,20 @@
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::{AddAssign, MulAssign, SubAssign};
use ark_bls12_377::cp6_782::{
fq::Fq, fq3::Fq3, fr::Fr, Fq6, G1Affine, G1Projective as G1, G2Affine, G2Projective as G2,
CP6_782,
};
use ark_ec::{PairingEngine, ProjectiveCurve};
use ark_ff::{
biginteger::{BigInteger384 as FrRepr, BigInteger832 as FqRepr},
BigInteger, Field, PrimeField, SquareRootField, UniformRand,
};
ec_bench!();
f_bench!(1, Fq3, Fq3, fq3);
f_bench!(2, Fq6, Fq6, fq6);
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
f_bench!(Fr, Fr, FrRepr, FrRepr, fr);
pairing_bench!(CP6_782, Fq6, affine_v);

+ 22
- 0
curve-benches/src/curves/mnt4_298.rs

@ -0,0 +1,22 @@
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::{AddAssign, MulAssign, SubAssign};
use ark_ec::{
mnt4::{G1Prepared, G2Prepared},
PairingEngine, ProjectiveCurve,
};
use ark_ff::{
biginteger::BigInteger320 as FqRepr, BigInteger, Field, PrimeField, SquareRootField,
UniformRand,
};
use ark_mnt_298::mnt4_298::{
fq::Fq, fq2::Fq2, fr::Fr, Fq4, G1Affine, G1Projective as G1, G2Affine, G2Projective as G2,
Parameters, MNT4_298,
};
ec_bench!();
f_bench!(1, Fq2, Fq2, fq2);
f_bench!(2, Fq4, Fq4, fq4);
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
pairing_bench!(MNT4_298, Fq4, prepared_v);

+ 22
- 0
curve-benches/src/curves/mnt4_753.rs

@ -0,0 +1,22 @@
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::{AddAssign, MulAssign, SubAssign};
use ark_ec::{
mnt4::{G1Prepared, G2Prepared},
PairingEngine, ProjectiveCurve,
};
use ark_ff::{
biginteger::BigInteger768 as FqRepr, BigInteger, Field, PrimeField, SquareRootField,
UniformRand,
};
use ark_mnt_753::mnt4_753::{
fq::Fq, fq2::Fq2, fr::Fr, Fq4, G1Affine, G1Projective as G1, G2Affine, G2Projective as G2,
Parameters, MNT4_753,
};
ec_bench!();
f_bench!(1, Fq2, Fq2, fq2);
f_bench!(2, Fq4, Fq4, fq4);
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
pairing_bench!(MNT4_753, Fq4, prepared_v);

+ 22
- 0
curve-benches/src/curves/mnt6_298.rs

@ -0,0 +1,22 @@
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::{AddAssign, MulAssign, SubAssign};
use ark_ec::{
mnt6::{G1Prepared, G2Prepared},
PairingEngine, ProjectiveCurve,
};
use ark_ff::{
biginteger::BigInteger320 as FqRepr, BigInteger, Field, PrimeField, SquareRootField,
UniformRand,
};
use ark_mnt_298::mnt6_298::{
fq::Fq, fq3::Fq3, fr::Fr, Fq6, G1Affine, G1Projective as G1, G2Affine, G2Projective as G2,
Parameters, MNT6_298,
};
ec_bench!();
f_bench!(1, Fq3, Fq3, fq3);
f_bench!(2, Fq6, Fq6, fq6);
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
pairing_bench!(MNT6_298, Fq6, prepared_v);

+ 22
- 0
curve-benches/src/curves/mnt6_753.rs

@ -0,0 +1,22 @@
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::{AddAssign, MulAssign, SubAssign};
use ark_ec::{
mnt6::{G1Prepared, G2Prepared},
PairingEngine, ProjectiveCurve,
};
use ark_ff::{
biginteger::BigInteger768 as FqRepr, BigInteger, Field, PrimeField, SquareRootField,
UniformRand,
};
use ark_mnt_753::mnt6_753::{
fq::Fq, fq3::Fq3, fr::Fr, Fq6, G1Affine, G1Projective as G1, G2Affine, G2Projective as G2,
Parameters, MNT6_753,
};
ec_bench!();
f_bench!(1, Fq3, Fq3, fq3);
f_bench!(2, Fq6, Fq6, fq6);
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
pairing_bench!(MNT6_753, Fq6, prepared_v);

+ 18
- 0
curve-benches/src/curves/mod.rs

@ -0,0 +1,18 @@
#[cfg(feature = "bls12_377")]
mod bls12_377;
#[cfg(feature = "bls12_381")]
mod bls12_381;
#[cfg(feature = "bn254")]
mod bn254;
#[cfg(feature = "bw6_761")]
mod bw6_761;
#[cfg(feature = "cp6_782")]
mod cp6_782;
#[cfg(feature = "mnt4_298")]
mod mnt4_298;
#[cfg(feature = "mnt4_753")]
mod mnt4_753;
#[cfg(feature = "mnt6_298")]
mod mnt6_298;
#[cfg(feature = "mnt6_753")]
mod mnt6_753;

+ 12
- 0
curve-benches/src/lib.rs

@ -0,0 +1,12 @@
#![cfg_attr(nightly, feature(test))]
#![allow(unused_macros, unused_imports)]
#[cfg(nightly)]
extern crate test;
#[cfg(all(nightly, test))]
#[macro_use]
pub mod macros;
#[cfg(all(nightly, test))]
mod curves;

+ 357
- 0
curve-benches/src/macros/ec.rs

@ -0,0 +1,357 @@
macro_rules! ec_bench {
() => {
#[bench]
fn bench_g1_rand(b: &mut ::test::Bencher) {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
b.iter(|| G1::rand(&mut rng));
}
#[bench]
fn bench_g1_mul_assign(b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<(G1, Fr)> = (0..SAMPLES)
.map(|_| (G1::rand(&mut rng), Fr::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
tmp *= v[count].1;
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn bench_g1_add_assign(b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<(G1, G1)> = (0..SAMPLES)
.map(|_| (G1::rand(&mut rng), G1::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
n_fold!(tmp, v, add_assign, count);
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn bench_g1_add_assign_mixed(b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<(G1, G1Affine)> = (0..SAMPLES)
.map(|_| (G1::rand(&mut rng), G1::rand(&mut rng).into()))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
n_fold!(tmp, v, add_assign_mixed, count);
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn bench_g1_double(b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<(G1, G1)> = (0..SAMPLES)
.map(|_| (G1::rand(&mut rng), G1::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
n_fold!(tmp, double_in_place);
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn bench_g1_deser(b: &mut ::test::Bencher) {
use ark_ec::ProjectiveCurve;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let mut num_bytes = 0;
let tmp = G1::rand(&mut rng).into_affine();
let v: Vec<_> = (0..SAMPLES)
.flat_map(|_| {
let mut bytes = Vec::with_capacity(1000);
tmp.serialize(&mut bytes).unwrap();
num_bytes = bytes.len();
bytes
})
.collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
let index = count * num_bytes;
G1Affine::deserialize(&v[index..(index + num_bytes)]).unwrap()
});
}
#[bench]
fn bench_g1_ser(b: &mut ::test::Bencher) {
use ark_ec::ProjectiveCurve;
use ark_serialize::CanonicalSerialize;
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let mut v: Vec<_> = (0..SAMPLES).map(|_| G1::rand(&mut rng)).collect();
let v = G1::batch_normalization_into_affine(v.as_mut_slice());
let mut bytes = Vec::with_capacity(1000);
let mut count = 0;
b.iter(|| {
let tmp = v[count];
count = (count + 1) % SAMPLES;
bytes.clear();
tmp.serialize(&mut bytes)
});
}
#[bench]
fn bench_g1_deser_unchecked(b: &mut ::test::Bencher) {
use ark_ec::ProjectiveCurve;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let mut num_bytes = 0;
let tmp = G1::rand(&mut rng).into_affine();
let v: Vec<_> = (0..SAMPLES)
.flat_map(|_| {
let mut bytes = Vec::with_capacity(1000);
tmp.serialize_unchecked(&mut bytes).unwrap();
num_bytes = bytes.len();
bytes
})
.collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
let index = count * num_bytes;
G1Affine::deserialize_unchecked(&v[index..(index + num_bytes)]).unwrap()
});
}
#[bench]
fn bench_g1_ser_unchecked(b: &mut ::test::Bencher) {
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let mut v: Vec<_> = (0..SAMPLES).map(|_| G1::rand(&mut rng)).collect();
let v = G1::batch_normalization_into_affine(v.as_mut_slice());
let mut bytes = Vec::with_capacity(1000);
let mut count = 0;
b.iter(|| {
let tmp = v[count];
count = (count + 1) % SAMPLES;
bytes.clear();
tmp.serialize_unchecked(&mut bytes)
});
}
#[bench]
fn bench_g2_rand(b: &mut ::test::Bencher) {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
b.iter(|| G2::rand(&mut rng));
}
#[bench]
fn bench_g2_mul_assign(b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<(G2, Fr)> = (0..SAMPLES)
.map(|_| (G2::rand(&mut rng), Fr::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
tmp *= v[count].1;
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn bench_g2_add_assign(b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<(G2, G2)> = (0..SAMPLES)
.map(|_| (G2::rand(&mut rng), G2::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
tmp.add_assign(&v[count].1);
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn bench_g2_add_assign_mixed(b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<(G2, G2Affine)> = (0..SAMPLES)
.map(|_| (G2::rand(&mut rng), G2::rand(&mut rng).into()))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
tmp.add_assign_mixed(&v[count].1);
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn bench_g2_double(b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<(G2, G2)> = (0..SAMPLES)
.map(|_| (G2::rand(&mut rng), G2::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
tmp.double_in_place();
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn bench_g2_deser(b: &mut ::test::Bencher) {
use ark_ec::ProjectiveCurve;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let mut num_bytes = 0;
let tmp = G2::rand(&mut rng).into_affine();
let v: Vec<_> = (0..SAMPLES)
.flat_map(|_| {
let mut bytes = Vec::with_capacity(1000);
tmp.serialize(&mut bytes).unwrap();
num_bytes = bytes.len();
bytes
})
.collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
let index = count * num_bytes;
G2Affine::deserialize(&v[index..(index + num_bytes)]).unwrap()
});
}
#[bench]
fn bench_g2_ser(b: &mut ::test::Bencher) {
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let mut v: Vec<_> = (0..SAMPLES).map(|_| G2::rand(&mut rng)).collect();
let v = G2::batch_normalization_into_affine(v.as_mut_slice());
let mut bytes = Vec::with_capacity(1000);
let mut count = 0;
b.iter(|| {
let tmp = v[count];
count = (count + 1) % SAMPLES;
bytes.clear();
tmp.serialize(&mut bytes)
});
}
#[bench]
fn bench_g2_deser_unchecked(b: &mut ::test::Bencher) {
use ark_ec::ProjectiveCurve;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let mut num_bytes = 0;
let tmp = G2::rand(&mut rng).into_affine();
let v: Vec<_> = (0..SAMPLES)
.flat_map(|_| {
let mut bytes = Vec::with_capacity(1000);
tmp.serialize_unchecked(&mut bytes).unwrap();
num_bytes = bytes.len();
bytes
})
.collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
let index = count * num_bytes;
G2Affine::deserialize_unchecked(&v[index..(index + num_bytes)]).unwrap()
});
}
#[bench]
fn bench_g2_ser_unchecked(b: &mut ::test::Bencher) {
use ark_ec::ProjectiveCurve;
use ark_serialize::CanonicalSerialize;
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let mut v: Vec<_> = (0..SAMPLES).map(|_| G2::rand(&mut rng)).collect();
let v = G2::batch_normalization_into_affine(v.as_mut_slice());
let mut bytes = Vec::with_capacity(1000);
let mut count = 0;
b.iter(|| {
let tmp = v[count];
count = (count + 1) % SAMPLES;
bytes.clear();
tmp.serialize_unchecked(&mut bytes)
});
}
};
}

+ 405
- 0
curve-benches/src/macros/field.rs

@ -0,0 +1,405 @@
macro_rules! f_bench {
// Use this for base fields
($f:ident, $f_type:ty, $f_repr:ident, $f_repr_type:ty, $field_ident:ident) => {
field_common!($f, $f_type, $field_ident);
sqrt!($f, $f_type, $field_ident);
field_base!($f, $f_type, $f_repr, $f_repr_type, $field_ident);
};
// use this for intermediate fields
(1, $f:ident, $f_type:ty, $field_ident:ident) => {
field_common!($f, $f_type, $field_ident);
sqrt!($f, $f_type, $field_ident);
};
// Use this for the full extension field Fqk
(2, $f:ident, $f_type:ty, $field_ident:ident) => {
field_common!($f, $f_type, $field_ident);
};
}
macro_rules! field_common {
($f:ident, $f_type:ty, $field_ident:ident) => {
paste::item! {
#[bench]
fn [<bench_ $field_ident _add_assign>](b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<_> = (0..SAMPLES)
.map(|_| ($f::rand(&mut rng), $f::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
n_fold!(tmp, v, add_assign, count);
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn [<bench_ $field_ident _sub_assign>](b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<_> = (0..SAMPLES)
.map(|_| ($f::rand(&mut rng), $f::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
n_fold!(tmp, v, sub_assign, count);
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn [<bench_ $field_ident _mul_assign>](b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<_> = (0..SAMPLES)
.map(|_| ($f::rand(&mut rng), $f::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
n_fold!(tmp, v, mul_assign, count);
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn [<bench_ $field_ident _double>](b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count];
n_fold!(tmp, double_in_place);
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn [<bench_ $field_ident _square>](b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count];
n_fold!(tmp, square_in_place);
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn [<bench_ $field_ident _inverse>](b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
let mut count = 0;
b.iter(|| {
let tmp = v[count].inverse();
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn [<bench_ $field_ident _deser>](b: &mut ::test::Bencher) {
use ark_serialize::{CanonicalSerialize, CanonicalDeserialize};
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let mut num_bytes = 0;
let v: Vec<_> = (0..SAMPLES).flat_map(|_| {
let mut bytes = Vec::with_capacity(1000);
let tmp = $f::rand(&mut rng);
tmp.serialize(&mut bytes).unwrap();
num_bytes = bytes.len();
bytes
}).collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
let index = count * num_bytes;
$f_type::deserialize(&v[index..(index + num_bytes)]).unwrap()
});
}
#[bench]
fn [<bench_ $field_ident _ser>](b: &mut ::test::Bencher) {
use ark_serialize::CanonicalSerialize;
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
let mut bytes = Vec::with_capacity(1000);
let mut count = 0;
b.iter(|| {
let tmp = v[count];
count = (count + 1) % SAMPLES;
bytes.clear();
tmp.serialize(&mut bytes)
});
}
#[bench]
fn [<bench_ $field_ident _deser_unchecked>](b: &mut ::test::Bencher) {
use ark_serialize::{CanonicalSerialize, CanonicalDeserialize};
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let mut num_bytes = 0;
let v: Vec<_> = (0..SAMPLES).flat_map(|_| {
let mut bytes = Vec::with_capacity(1000);
let tmp = $f::rand(&mut rng);
tmp.serialize_unchecked(&mut bytes).unwrap();
num_bytes = bytes.len();
bytes
}).collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
let index = count * num_bytes;
$f_type::deserialize_unchecked(&v[index..(index + num_bytes)]).unwrap()
});
}
#[bench]
fn [<bench_ $field_ident _ser_unchecked>](b: &mut ::test::Bencher) {
use ark_serialize::CanonicalSerialize;
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
let mut bytes = Vec::with_capacity(1000);
let mut count = 0;
b.iter(|| {
let tmp = v[count];
count = (count + 1) % SAMPLES;
bytes.clear();
tmp.serialize_unchecked(&mut bytes)
});
}
}
};
}
macro_rules! sqrt {
($f:ident, $f_type:ty, $field_ident:ident) => {
paste::item! {
#[bench]
fn [<bench_ $field_ident _sqrt>](b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<$f_type> = (0..SAMPLES)
.map(|_| {
let mut tmp = $f::rand(&mut rng);
tmp.square_in_place();
tmp
})
.collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
v[count].sqrt()
});
}
}
};
}
macro_rules! field_base {
($f:ident, $f_type:ty, $f_repr:ident, $f_repr_type:ty, $field_ident:ident) => {
paste::item! {
#[bench]
fn [<bench_ $field_ident _repr_add_nocarry>](b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<_> = (0..SAMPLES)
.map(|_| {
let mut tmp1 = $f_repr::rand(&mut rng);
let mut tmp2 = $f_repr::rand(&mut rng);
// Shave a few bits off to avoid overflow.
for _ in 0..3 {
tmp1.div2();
tmp2.div2();
}
(tmp1, tmp2)
})
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
n_fold!(tmp, v, add_nocarry, count);
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn [<bench_ $field_ident _repr_sub_noborrow>](b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<_> = (0..SAMPLES)
.map(|_| {
let tmp1 = $f_repr::rand(&mut rng);
let mut tmp2 = tmp1;
// Ensure tmp2 is smaller than tmp1.
for _ in 0..10 {
tmp2.div2();
}
(tmp1, tmp2)
})
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
n_fold!(tmp, v, sub_noborrow, count);
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn [<bench_ $field_ident _repr_num_bits>](b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<$f_repr_type> = (0..SAMPLES).map(|_| $f_repr::rand(&mut rng)).collect();
let mut count = 0;
b.iter(|| {
let tmp = v[count].num_bits();
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn [<bench_ $field_ident _repr_mul2>](b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<$f_repr_type> = (0..SAMPLES).map(|_| $f_repr::rand(&mut rng)).collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count];
n_fold!(tmp, mul2);
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn [<bench_ $field_ident _repr_div2>](b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<$f_repr_type> = (0..SAMPLES).map(|_| $f_repr::rand(&mut rng)).collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count];
n_fold!(tmp, div2);
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn [<bench_ $field_ident _negate>](b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count];
tmp = -tmp;
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn [<bench_ $field_ident _into_repr>](b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
v[count].into_repr()
});
}
#[bench]
fn [<bench_ $field_ident _from_repr>](b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<$f_repr_type> = (0..SAMPLES)
.map(|_| $f::rand(&mut rng).into_repr())
.collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
$f::from(v[count])
});
}
}
};
}

+ 11
- 0
curve-benches/src/macros/mod.rs

@ -0,0 +1,11 @@
#[macro_use]
mod ec;
#[macro_use]
mod field;
#[macro_use]
mod pairing;
#[macro_use]
mod utils;

+ 61
- 0
curve-benches/src/macros/pairing.rs

@ -0,0 +1,61 @@
macro_rules! pairing_bench {
($curve:ident, $pairing_field:ident, $pairing_type:ident) => {
#[bench]
fn bench_pairing_miller_loop(b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
$pairing_type!(v, rng);
let mut count = 0;
b.iter(|| {
let tmp = $curve::miller_loop(&[(v[count].0.clone(), v[count].1.clone())]);
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn bench_pairing_final_exponentiation(b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<$pairing_field> = (0..SAMPLES)
.map(|_| {
(
G1Affine::from(G1::rand(&mut rng)).into(),
G2Affine::from(G2::rand(&mut rng)).into(),
)
})
.map(|(p, q)| $curve::miller_loop(&[(p, q)]))
.collect();
let mut count = 0;
b.iter(|| {
let tmp = $curve::final_exponentiation(&v[count]);
count = (count + 1) % SAMPLES;
tmp
});
}
#[bench]
fn bench_pairing_full(b: &mut ::test::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let v: Vec<(G1, G2)> = (0..SAMPLES)
.map(|_| (G1::rand(&mut rng), G2::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let tmp = $curve::pairing(v[count].0, v[count].1);
count = (count + 1) % SAMPLES;
tmp
});
}
};
}

+ 49
- 0
curve-benches/src/macros/utils.rs

@ -0,0 +1,49 @@
macro_rules! n_fold {
($tmp:ident, $v:ident, $func:ident, $count:ident) => {
const ITERS: usize = 1000;
#[cfg(not(feature = "n_fold"))]
$tmp.$func(&$v[$count].1);
#[cfg(feature = "n_fold")]
for _ in 0..ITERS {
$tmp.$func(&$v[$count].1);
}
};
($tmp:ident, $func:ident) => {
const ITERS: usize = 1000;
#[cfg(not(feature = "n_fold"))]
$tmp.$func();
#[cfg(feature = "n_fold")]
for _ in 0..ITERS {
$tmp.$func();
}
};
}
macro_rules! prepared_v {
($v:ident, $rng:ident) => {
let $v: Vec<(G1Prepared<Parameters>, G2Prepared<Parameters>)> = (0..SAMPLES)
.map(|_| {
(
G1Affine::from(G1::rand(&mut $rng)).into(),
G2Affine::from(G2::rand(&mut $rng)).into(),
)
})
.collect();
};
}
macro_rules! affine_v {
($v:ident, $rng:ident) => {
let $v: Vec<(G1Affine, G2Affine)> = (0..SAMPLES)
.map(|_| {
(
G1Affine::from(G1::rand(&mut $rng)).into(),
G2Affine::from(G2::rand(&mut $rng)).into(),
)
})
.collect();
};
}

+ 33
- 0
curve-tests/Cargo.toml

@ -0,0 +1,33 @@
[package]
name = "ark-curve-tests"
version = "0.1.0"
authors = [
"Sean Bowe",
"Alessandro Chiesa",
"Matthew Green",
"Ian Miers",
"Pratyush Mishra",
"Howard Wu",
"arkworks contributors"
]
description = "A library for tests for finite fields, elliptic curves, and pairings"
homepage = "https://arworks.rs"
repository = "https://github.com/arkworks/algebra"
documentation = "https://docs.rs/ark-curve-tests/"
keywords = ["cryptography", "finite fields", "elliptic curves" ]
categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0"
edition = "2018"
[dependencies]
ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false }
ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
rand = { version = "0.7", default-features = false}
rand_xorshift = { version = "0.2", default-features = false}
[features]
default = []
std = [ "ark-std/std", "ark-ff/std", "ark-serialize/std", "ark-ec/std" ]

+ 1
- 0
curve-tests/LICENSE-APACHE

@ -0,0 +1 @@
../LICENSE-APACHE

+ 1
- 0
curve-tests/LICENSE-MIT

@ -0,0 +1 @@
../LICENSE-MIT

+ 531
- 0
curve-tests/src/curves.rs

@ -0,0 +1,531 @@
#![allow(unused)]
use ark_ec::{
AffineCurve, MontgomeryModelParameters, ProjectiveCurve, SWModelParameters, TEModelParameters,
};
use ark_ff::{Field, One, PrimeField, UniformRand, Zero};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, SWFlags, SerializationError};
use ark_std::{io::Cursor, vec::Vec};
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
pub const ITERATIONS: usize = 10;
fn random_addition_test<G: ProjectiveCurve>() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..ITERATIONS {
let a = G::rand(&mut rng);
let b = G::rand(&mut rng);
let c = G::rand(&mut rng);
let a_affine = a.into_affine();
let b_affine = b.into_affine();
let c_affine = c.into_affine();
// a + a should equal the doubling
{
let mut aplusa = a;
aplusa.add_assign(&a);
let mut aplusamixed = a;
aplusamixed.add_assign_mixed(&a.into_affine());
let mut adouble = a;
adouble.double_in_place();
assert_eq!(aplusa, adouble);
assert_eq!(aplusa, aplusamixed);
}
let mut tmp = vec![G::zero(); 6];
// (a + b) + c
tmp[0] = (a + &b) + &c;
// a + (b + c)
tmp[1] = a + &(b + &c);
// (a + c) + b
tmp[2] = (a + &c) + &b;
// Mixed addition
// (a + b) + c
tmp[3] = a_affine.into_projective();
tmp[3].add_assign_mixed(&b_affine);
tmp[3].add_assign_mixed(&c_affine);
// a + (b + c)
tmp[4] = b_affine.into_projective();
tmp[4].add_assign_mixed(&c_affine);
tmp[4].add_assign_mixed(&a_affine);
// (a + c) + b
tmp[5] = a_affine.into_projective();
tmp[5].add_assign_mixed(&c_affine);
tmp[5].add_assign_mixed(&b_affine);
// Comparisons
for i in 0..6 {
for j in 0..6 {
if tmp[i] != tmp[j] {
println!("{} \n{}", tmp[i], tmp[j]);
}
assert_eq!(tmp[i], tmp[j], "Associativity failed {} {}", i, j);
assert_eq!(
tmp[i].into_affine(),
tmp[j].into_affine(),
"Associativity failed"
);
}
assert!(tmp[i] != a);
assert!(tmp[i] != b);
assert!(tmp[i] != c);
assert!(a != tmp[i]);
assert!(b != tmp[i]);
assert!(c != tmp[i]);
}
}
}
fn random_multiplication_test<G: ProjectiveCurve>() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..ITERATIONS {
let mut a = G::rand(&mut rng);
let mut b = G::rand(&mut rng);
let a_affine = a.into_affine();
let b_affine = b.into_affine();
let s = G::ScalarField::rand(&mut rng);
// s ( a + b )
let mut tmp1 = a;
tmp1.add_assign(&b);
tmp1.mul_assign(s);
// sa + sb
a.mul_assign(s);
b.mul_assign(s);
let mut tmp2 = a;
tmp2.add_assign(&b);
// Affine multiplication
let mut tmp3 = a_affine.mul(s.into_repr());
tmp3.add_assign(&b_affine.mul(s.into_repr()));
assert_eq!(tmp1, tmp2);
assert_eq!(tmp1, tmp3);
}
}
fn random_doubling_test<G: ProjectiveCurve>() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..ITERATIONS {
let mut a = G::rand(&mut rng);
let mut b = G::rand(&mut rng);
// 2(a + b)
let mut tmp1 = a;
tmp1.add_assign(&b);
tmp1.double_in_place();
// 2a + 2b
a.double_in_place();
b.double_in_place();
let mut tmp2 = a;
tmp2.add_assign(&b);
let mut tmp3 = a;
tmp3.add_assign_mixed(&b.into_affine());
assert_eq!(tmp1, tmp2);
assert_eq!(tmp1, tmp3);
}
}
fn random_negation_test<G: ProjectiveCurve>() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..ITERATIONS {
let r = G::rand(&mut rng);
let s = G::ScalarField::rand(&mut rng);
let sneg = -s;
assert!((s + &sneg).is_zero());
let mut t1 = r;
t1.mul_assign(s);
let mut t2 = r;
t2.mul_assign(sneg);
let mut t3 = t1;
t3.add_assign(&t2);
assert!(t3.is_zero());
let mut t4 = t1;
t4.add_assign_mixed(&t2.into_affine());
assert!(t4.is_zero());
t1 = -t1;
assert_eq!(t1, t2);
}
}
fn random_transformation_test<G: ProjectiveCurve>() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..ITERATIONS {
let g = G::rand(&mut rng);
let g_affine = g.into_affine();
let g_projective = g_affine.into_projective();
assert_eq!(g, g_projective);
}
// Batch normalization
for _ in 0..10 {
let mut v = (0..ITERATIONS)
.map(|_| G::rand(&mut rng))
.collect::<Vec<_>>();
for i in &v {
assert!(!i.is_normalized());
}
use rand::distributions::{Distribution, Uniform};
let between = Uniform::from(0..ITERATIONS);
// Sprinkle in some normalized points
for _ in 0..5 {
v[between.sample(&mut rng)] = G::zero();
}
for _ in 0..5 {
let s = between.sample(&mut rng);
v[s] = v[s].into_affine().into_projective();
}
let expected_v = v
.iter()
.map(|v| v.into_affine().into_projective())
.collect::<Vec<_>>();
G::batch_normalization(&mut v);
for i in &v {
assert!(i.is_normalized());
}
assert_eq!(v, expected_v);
}
}
pub fn curve_tests<G: ProjectiveCurve>() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
// Negation edge case with zero.
{
let z = -G::zero();
assert!(z.is_zero());
}
// Doubling edge case with zero.
{
let mut z = -G::zero();
z.double_in_place();
assert!(z.is_zero());
}
// Addition edge cases with zero
{
let mut r = G::rand(&mut rng);
let rcopy = r;
r.add_assign(&G::zero());
assert_eq!(r, rcopy);
r.add_assign_mixed(&G::Affine::zero());
assert_eq!(r, rcopy);
let mut z = G::zero();
z.add_assign(&G::zero());
assert!(z.is_zero());
z.add_assign_mixed(&G::Affine::zero());
assert!(z.is_zero());
let mut z2 = z;
z2.add_assign(&r);
z.add_assign_mixed(&r.into_affine());
assert_eq!(z, z2);
assert_eq!(z, r);
}
// Transformations
{
let a = G::rand(&mut rng);
let b = a.into_affine().into_projective();
let c = a
.into_affine()
.into_projective()
.into_affine()
.into_projective();
assert_eq!(a, b);
assert_eq!(b, c);
}
// Test COFACTOR and COFACTOR_INV
{
let a = G::rand(&mut rng);
let b = a.into_affine();
let c = b.mul_by_cofactor_inv().mul_by_cofactor();
assert_eq!(b, c);
}
random_addition_test::<G>();
random_multiplication_test::<G>();
random_doubling_test::<G>();
random_negation_test::<G>();
random_transformation_test::<G>();
}
pub fn sw_tests<P: SWModelParameters>() {
sw_curve_serialization_test::<P>();
sw_from_random_bytes::<P>();
}
pub fn sw_from_random_bytes<P: SWModelParameters>() {
use ark_ec::models::short_weierstrass_jacobian::{GroupAffine, GroupProjective};
let buf_size = GroupAffine::<P>::zero().serialized_size();
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..ITERATIONS {
let a = GroupProjective::<P>::rand(&mut rng);
let mut a = a.into_affine();
{
let mut serialized = vec![0; buf_size];
let mut cursor = Cursor::new(&mut serialized[..]);
a.serialize(&mut cursor).unwrap();
let mut cursor = Cursor::new(&serialized[..]);
let p1 = GroupAffine::<P>::deserialize(&mut cursor).unwrap();
let p2 = GroupAffine::<P>::from_random_bytes(&serialized).unwrap();
assert_eq!(p1, p2);
}
}
}
pub fn sw_curve_serialization_test<P: SWModelParameters>() {
use ark_ec::models::short_weierstrass_jacobian::{GroupAffine, GroupProjective};
let buf_size = GroupAffine::<P>::zero().serialized_size();
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..ITERATIONS {
let a = GroupProjective::<P>::rand(&mut rng);
let mut a = a.into_affine();
{
let mut serialized = vec![0; buf_size];
let mut cursor = Cursor::new(&mut serialized[..]);
a.serialize(&mut cursor).unwrap();
let mut cursor = Cursor::new(&serialized[..]);
let b = GroupAffine::<P>::deserialize(&mut cursor).unwrap();
assert_eq!(a, b);
}
{
a.y = -a.y;
let mut serialized = vec![0; buf_size];
let mut cursor = Cursor::new(&mut serialized[..]);
a.serialize(&mut cursor).unwrap();
let mut cursor = Cursor::new(&serialized[..]);
let b = GroupAffine::<P>::deserialize(&mut cursor).unwrap();
assert_eq!(a, b);
}
{
let a = GroupAffine::<P>::zero();
let mut serialized = vec![0; buf_size];
let mut cursor = Cursor::new(&mut serialized[..]);
a.serialize(&mut cursor).unwrap();
let mut cursor = Cursor::new(&serialized[..]);
let b = GroupAffine::<P>::deserialize(&mut cursor).unwrap();
assert_eq!(a, b);
}
{
let a = GroupAffine::<P>::zero();
let mut serialized = vec![0; buf_size - 1];
let mut cursor = Cursor::new(&mut serialized[..]);
a.serialize(&mut cursor).unwrap_err();
}
{
let serialized = vec![0; buf_size - 1];
let mut cursor = Cursor::new(&serialized[..]);
GroupAffine::<P>::deserialize(&mut cursor).unwrap_err();
}
{
let mut serialized = vec![0; a.uncompressed_size()];
let mut cursor = Cursor::new(&mut serialized[..]);
a.serialize_uncompressed(&mut cursor).unwrap();
let mut cursor = Cursor::new(&serialized[..]);
let b = GroupAffine::<P>::deserialize_uncompressed(&mut cursor).unwrap();
assert_eq!(a, b);
}
{
a.y = -a.y;
let mut serialized = vec![0; a.uncompressed_size()];
let mut cursor = Cursor::new(&mut serialized[..]);
a.serialize_uncompressed(&mut cursor).unwrap();
let mut cursor = Cursor::new(&serialized[..]);
let b = GroupAffine::<P>::deserialize_uncompressed(&mut cursor).unwrap();
assert_eq!(a, b);
}
{
let a = GroupAffine::<P>::zero();
let mut serialized = vec![0; a.uncompressed_size()];
let mut cursor = Cursor::new(&mut serialized[..]);
a.serialize_uncompressed(&mut cursor).unwrap();
let mut cursor = Cursor::new(&serialized[..]);
let b = GroupAffine::<P>::deserialize_uncompressed(&mut cursor).unwrap();
assert_eq!(a, b);
}
}
}
pub fn montgomery_conversion_test<P>()
where
P: TEModelParameters,
{
// A = 2 * (a + d) / (a - d)
let a = P::BaseField::one().double()
* &(P::COEFF_A + &P::COEFF_D)
* &(P::COEFF_A - &P::COEFF_D).inverse().unwrap();
// B = 4 / (a - d)
let b = P::BaseField::one().double().double() * &(P::COEFF_A - &P::COEFF_D).inverse().unwrap();
assert_eq!(a, P::MontgomeryModelParameters::COEFF_A);
assert_eq!(b, P::MontgomeryModelParameters::COEFF_B);
}
pub fn edwards_tests<P: TEModelParameters>()
where
P::BaseField: PrimeField,
{
edwards_curve_serialization_test::<P>();
edwards_from_random_bytes::<P>();
}
pub fn edwards_from_random_bytes<P: TEModelParameters>()
where
P::BaseField: PrimeField,
{
use ark_ec::models::twisted_edwards_extended::{GroupAffine, GroupProjective};
use ark_ff::{to_bytes, ToBytes};
let buf_size = GroupAffine::<P>::zero().serialized_size();
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..ITERATIONS {
let a = GroupProjective::<P>::rand(&mut rng);
let mut a = a.into_affine();
{
let mut serialized = vec![0; buf_size];
let mut cursor = Cursor::new(&mut serialized[..]);
a.serialize(&mut cursor).unwrap();
let mut cursor = Cursor::new(&serialized[..]);
let p1 = GroupAffine::<P>::deserialize(&mut cursor).unwrap();
let p2 = GroupAffine::<P>::from_random_bytes(&serialized).unwrap();
assert_eq!(p1, p2);
}
}
for _ in 0..ITERATIONS {
let mut biginteger =
<<GroupAffine<P> as AffineCurve>::BaseField as PrimeField>::BigInt::rand(&mut rng);
let mut bytes = to_bytes![biginteger].unwrap();
let mut g = GroupAffine::<P>::from_random_bytes(&bytes);
while g.is_none() {
bytes.iter_mut().for_each(|i| *i = i.wrapping_sub(1));
g = GroupAffine::<P>::from_random_bytes(&bytes);
}
let _g = g.unwrap();
}
}
pub fn edwards_curve_serialization_test<P: TEModelParameters>() {
use ark_ec::models::twisted_edwards_extended::{GroupAffine, GroupProjective};
let buf_size = GroupAffine::<P>::zero().serialized_size();
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..ITERATIONS {
let a = GroupProjective::<P>::rand(&mut rng);
let a = a.into_affine();
{
let mut serialized = vec![0; buf_size];
let mut cursor = Cursor::new(&mut serialized[..]);
a.serialize(&mut cursor).unwrap();
let mut cursor = Cursor::new(&serialized[..]);
let b = GroupAffine::<P>::deserialize(&mut cursor).unwrap();
assert_eq!(a, b);
}
{
let a = GroupAffine::<P>::zero();
let mut serialized = vec![0; buf_size];
let mut cursor = Cursor::new(&mut serialized[..]);
a.serialize(&mut cursor).unwrap();
let mut cursor = Cursor::new(&serialized[..]);
let b = GroupAffine::<P>::deserialize(&mut cursor).unwrap();
assert_eq!(a, b);
}
{
let a = GroupAffine::<P>::zero();
let mut serialized = vec![0; buf_size - 1];
let mut cursor = Cursor::new(&mut serialized[..]);
a.serialize(&mut cursor).unwrap_err();
}
{
let serialized = vec![0; buf_size - 1];
let mut cursor = Cursor::new(&serialized[..]);
GroupAffine::<P>::deserialize(&mut cursor).unwrap_err();
}
{
let mut serialized = vec![0; a.uncompressed_size()];
let mut cursor = Cursor::new(&mut serialized[..]);
a.serialize_uncompressed(&mut cursor).unwrap();
let mut cursor = Cursor::new(&serialized[..]);
let b = GroupAffine::<P>::deserialize_uncompressed(&mut cursor).unwrap();
assert_eq!(a, b);
}
{
let a = GroupAffine::<P>::zero();
let mut serialized = vec![0; a.uncompressed_size()];
let mut cursor = Cursor::new(&mut serialized[..]);
a.serialize_uncompressed(&mut cursor).unwrap();
let mut cursor = Cursor::new(&serialized[..]);
let b = GroupAffine::<P>::deserialize_uncompressed(&mut cursor).unwrap();
assert_eq!(a, b);
}
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save