Browse Source

Merge pull request #46 from str4d/ff-traits

Migrate to ff and group crates
master
str4d 6 years ago committed by GitHub
parent
commit
c57a31e82e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 368
      Cargo.lock
  2. 2
      Cargo.toml
  3. 12
      bellman/Cargo.toml
  4. 39
      bellman/src/domain.rs
  5. 11
      bellman/src/groth16/generator.rs
  6. 10
      bellman/src/groth16/mod.rs
  7. 10
      bellman/src/groth16/prover.rs
  8. 44
      bellman/src/groth16/tests/dummy_engine.rs
  9. 7
      bellman/src/groth16/tests/mod.rs
  10. 9
      bellman/src/groth16/verifier.rs
  11. 40
      bellman/src/lib.rs
  12. 25
      bellman/src/multiexp.rs
  13. 7
      bellman/tests/mimc.rs
  14. 3
      ff/.gitignore
  15. 18
      ff/Cargo.toml
  16. 202
      ff/LICENSE-APACHE
  17. 21
      ff/LICENSE-MIT
  18. 60
      ff/README.md
  19. 20
      ff/ff_derive/Cargo.toml
  20. 1065
      ff/ff_derive/src/lib.rs
  21. 393
      ff/src/lib.rs
  22. 3
      group/.gitignore
  23. 14
      group/COPYRIGHT
  24. 17
      group/Cargo.toml
  25. 201
      group/LICENSE-APACHE
  26. 23
      group/LICENSE-MIT
  27. 17
      group/README.md
  28. 196
      group/src/lib.rs
  29. 13
      group/src/tests/mod.rs
  30. 4
      group/src/wnaf.rs
  31. 1
      librustzcash/Cargo.toml
  32. 7
      librustzcash/src/rustzcash.rs
  33. 2
      librustzcash/src/tests/key_agreement.rs
  34. 3
      librustzcash/src/tests/key_components.rs
  35. 3
      librustzcash/src/tests/signatures.rs
  36. 9
      pairing/Cargo.toml
  37. 8
      pairing/README.md
  38. 4
      pairing/benches/bls12_381/ec.rs
  39. 2
      pairing/benches/bls12_381/fq.rs
  40. 2
      pairing/benches/bls12_381/fq12.rs
  41. 2
      pairing/benches/bls12_381/fq2.rs
  42. 2
      pairing/benches/bls12_381/fr.rs
  43. 2
      pairing/benches/bls12_381/mod.rs
  44. 2
      pairing/benches/pairing_benches.rs
  45. 38
      pairing/src/bls12_381/ec.rs
  46. 757
      pairing/src/bls12_381/fq.rs
  47. 4
      pairing/src/bls12_381/fq12.rs
  48. 36
      pairing/src/bls12_381/fq2.rs
  49. 4
      pairing/src/bls12_381/fq6.rs
  50. 666
      pairing/src/bls12_381/fr.rs
  51. 14
      pairing/src/bls12_381/mod.rs
  52. 3
      pairing/src/bls12_381/tests/mod.rs
  53. 685
      pairing/src/lib.rs
  54. 3
      pairing/src/tests/engine.rs
  55. 2
      pairing/src/tests/field.rs
  56. 1
      pairing/src/tests/mod.rs
  57. 2
      pairing/src/tests/repr.rs
  58. 5
      sapling-crypto/Cargo.toml
  59. 10
      sapling-crypto/src/circuit/boolean.rs
  60. 8
      sapling-crypto/src/circuit/ecc.rs
  61. 4
      sapling-crypto/src/circuit/lookup.rs
  62. 7
      sapling-crypto/src/circuit/multieq.rs
  63. 3
      sapling-crypto/src/circuit/multipack.rs
  64. 11
      sapling-crypto/src/circuit/num.rs
  65. 2
      sapling-crypto/src/circuit/pedersen_hash.rs
  66. 10
      sapling-crypto/src/circuit/sapling/mod.rs
  67. 3
      sapling-crypto/src/circuit/sprout/mod.rs
  68. 10
      sapling-crypto/src/circuit/test/mod.rs
  69. 9
      sapling-crypto/src/circuit/uint32.rs
  70. 2
      sapling-crypto/src/group_hash.rs
  71. 8
      sapling-crypto/src/jubjub/edwards.rs
  72. 8
      sapling-crypto/src/jubjub/fs.rs
  73. 8
      sapling-crypto/src/jubjub/mod.rs
  74. 8
      sapling-crypto/src/jubjub/montgomery.rs
  75. 2
      sapling-crypto/src/jubjub/tests.rs
  76. 1
      sapling-crypto/src/lib.rs
  77. 2
      sapling-crypto/src/pedersen_hash.rs
  78. 6
      sapling-crypto/src/primitives/mod.rs
  79. 2
      sapling-crypto/src/redjubjub.rs
  80. 1
      zcash_primitives/Cargo.toml
  81. 1
      zcash_primitives/src/lib.rs
  82. 6
      zcash_primitives/src/transaction/components.rs
  83. 2
      zcash_primitives/src/transaction/sighash.rs
  84. 1
      zcash_proofs/Cargo.toml
  85. 1
      zcash_proofs/src/lib.rs
  86. 6
      zcash_proofs/src/sapling/prover.rs
  87. 6
      zcash_proofs/src/sapling/verifier.rs
  88. 1
      zip32/Cargo.toml
  89. 4
      zip32/src/lib.rs

368
Cargo.lock generated

@ -28,22 +28,6 @@ dependencies = [
"stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "aho-corasick"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "arrayvec"
version = "0.4.7"
@ -52,27 +36,6 @@ dependencies = [
"nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "backtrace"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "backtrace-sys"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bellman"
version = "0.1.0"
@ -80,8 +43,10 @@ dependencies = [
"bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ff 0.4.0",
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"group 0.1.0",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pairing 0.14.2",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -92,11 +57,6 @@ name = "bit-vec"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "1.0.1"
@ -130,61 +90,6 @@ name = "byteorder"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cargo_metadata"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cc"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clippy"
version = "0.0.200"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy_lints 0.0.200 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clippy_lints"
version = "0.0.200"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
"if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "constant_time_eq"
version = "0.1.3"
@ -204,16 +109,24 @@ dependencies = [
]
[[package]]
name = "either"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
name = "ff"
version = "0.4.0"
dependencies = [
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ff_derive 0.3.0",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "error-chain"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
name = "ff_derive"
version = "0.3.0"
dependencies = [
"backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"num-bigint 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -270,11 +183,11 @@ dependencies = [
]
[[package]]
name = "getopts"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
name = "group"
version = "0.1.0"
dependencies = [
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ff 0.4.0",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -294,34 +207,6 @@ dependencies = [
"proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "idna"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "if_chain"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "itertools"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itoa"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "1.0.0"
@ -339,6 +224,7 @@ dependencies = [
"bellman 0.1.0",
"blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)",
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ff 0.4.0",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
"pairing 0.14.2",
@ -348,19 +234,6 @@ dependencies = [
"zip32 0.0.0",
]
[[package]]
name = "matches"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "nodrop"
version = "0.1.12"
@ -406,15 +279,11 @@ name = "pairing"
version = "0.14.2"
dependencies = [
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.200 (registry+https://github.com/rust-lang/crates.io-index)",
"ff 0.4.0",
"group 0.1.0",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "percent-encoding"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro-hack"
version = "0.4.0"
@ -436,20 +305,6 @@ dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pulldown-cmark"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quine-mc_cluskey"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quote"
version = "0.6.8"
@ -483,26 +338,6 @@ name = "redox_syscall"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "regex"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rust-crypto"
version = "0.2.36"
@ -515,29 +350,11 @@ dependencies = [
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-demangle"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-serialize"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ryu"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "sapling-crypto"
version = "0.0.1"
@ -546,51 +363,13 @@ dependencies = [
"blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)",
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ff 0.4.0",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"pairing 0.14.2",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_derive"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_json"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "stream-cipher"
version = "0.1.1"
@ -609,14 +388,6 @@ dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.40"
@ -627,62 +398,16 @@ dependencies = [
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "toml"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "typenum"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ucd-util"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-bidi"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-normalization"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-width"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "url"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "utf8-ranges"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.4"
@ -708,6 +433,7 @@ version = "0.0.0"
dependencies = [
"blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)",
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ff 0.4.0",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pairing 0.14.2",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -720,6 +446,7 @@ version = "0.0.0"
dependencies = [
"bellman 0.1.0",
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ff 0.4.0",
"pairing 0.14.2",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"sapling-crypto 0.0.1",
@ -736,6 +463,7 @@ dependencies = [
"aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)",
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ff 0.4.0",
"fpe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pairing 0.14.2",
@ -746,28 +474,16 @@ dependencies = [
"checksum aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6fb1737cdc8da3db76e90ca817a194249a38fcb500c2e6ecec39b29448aa873"
"checksum aes-soft 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67cc03b0a090a05cb01e96998a01905d7ceedce1bc23b756c0bb7faa0682ccb1"
"checksum aesni 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6810b7fb9f2bb4f76f05ac1c170b8dde285b6308955dc3afd89710268c958d9e"
"checksum aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "68f56c7353e5a9547cbd76ed90f7bb5ffc3ba09d4ea9bd1d8c06c8b1142eeb5a"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"
"checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f"
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)" = "<none>"
"checksum block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "370424437b9459f3dfd68428ed9376ddfe03d8b70ede29cc533b3557df186ab4"
"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
"checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87"
"checksum cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1efca0b863ca03ed4c109fb1c55e0bc4bbeb221d3e103d86251046b06a526bd0"
"checksum cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "4a6007c146fdd28d4512a794b07ffe9d8e89e6bf86e2e0c4ddff2e1fb54a0007"
"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3"
"checksum clippy 0.0.200 (registry+https://github.com/rust-lang/crates.io-index)" = "927a1f79af10deb103df108347f23c6b7fa1731c953d6fb24d68be1748a0993f"
"checksum clippy_lints 0.0.200 (registry+https://github.com/rust-lang/crates.io-index)" = "d2432663f6bdb90255dcf9df5ca504f99b575bb471281591138f62f9d31f863b"
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
"checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19"
"checksum digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "00a49051fef47a72c9623101b19bd71924a45cca838826caae3eaa4d00772603"
"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
"checksum fpe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce3371c82bfbd984f624cab093f55e7336f5a6e589f8518e1258f54f011b89ad"
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
@ -775,58 +491,30 @@ dependencies = [
"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
"checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797"
"checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95"
"checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a"
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
"checksum if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4bac95d9aa0624e7b78187d6fb8ab012b41d9f6f54b1bcb61e61c4845f8357ec"
"checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450"
"checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606"
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
"checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d"
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
"checksum num-bigint 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3eceac7784c5dc97c2d6edf30259b4e153e6e2b42b3c85e9a6e9f45d06caef6e"
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
"checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe"
"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
"checksum opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d620c9c26834b34f039489ac0dfdb12c7ac15ccaf818350a64c9b5334a452ad7"
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
"checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0"
"checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892"
"checksum proc-macro2 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b331c6ad3411474cd55540398dc7ad89fc41488e64ec71fdecc9c9b86de96fb0"
"checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32"
"checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5"
"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"
"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
"checksum regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "67d0301b0c6804eca7e3c275119d0b01ff3b7ab9258a65709e608a66312a1025"
"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d"
"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)" = "22d340507cea0b7e6632900a176101fea959c7065d93ba555072da90aaaafc87"
"checksum serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)" = "234fc8b737737b148ccd625175fc6390f5e4dacfdaa543cb93a3430d984a9119"
"checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae"
"checksum stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "30dc6118470d69ce0fdcf7e6f95e95853f7f4f72f80d835d4519577c323814ab"
"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
"checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6"
"checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4"
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

2
Cargo.toml

@ -1,6 +1,8 @@
[workspace]
members = [
"bellman",
"ff",
"group",
"librustzcash",
"pairing",
"sapling-crypto",

12
bellman/Cargo.toml

@ -11,12 +11,20 @@ version = "0.1.0"
[dependencies]
rand = "0.4"
bit-vec = "0.4.4"
ff = { path = "../ff" }
futures = "0.1"
futures-cpupool = "0.1"
group = { path = "../group" }
num_cpus = "1"
crossbeam = "0.3"
pairing = { path = "../pairing" }
pairing = { path = "../pairing", optional = true }
byteorder = "1"
[features]
default = []
groth16 = ["pairing"]
default = ["groth16"]
[[test]]
name = "mimc"
path = "tests/mimc.rs"
required-features = ["groth16"]

39
bellman/src/domain.rs

@ -10,12 +10,8 @@
//! This allows us to perform polynomial operations in O(n)
//! by performing an O(n log n) FFT over such a domain.
use pairing::{
Engine,
Field,
PrimeField,
CurveProjective
};
use ff::{Field, PrimeField, ScalarEngine};
use group::CurveProjective;
use super::{
SynthesisError
@ -23,7 +19,7 @@ use super::{
use super::multicore::Worker;
pub struct EvaluationDomain<E: Engine, G: Group<E>> {
pub struct EvaluationDomain<E: ScalarEngine, G: Group<E>> {
coeffs: Vec<G>,
exp: u32,
omega: E::Fr,
@ -32,7 +28,7 @@ pub struct EvaluationDomain<E: Engine, G: Group<E>> {
minv: E::Fr
}
impl<E: Engine, G: Group<E>> EvaluationDomain<E, G> {
impl<E: ScalarEngine, G: Group<E>> EvaluationDomain<E, G> {
pub fn as_ref(&self) -> &[G] {
&self.coeffs
}
@ -189,7 +185,7 @@ impl<E: Engine, G: Group<E>> EvaluationDomain<E, G> {
}
}
pub trait Group<E: Engine>: Sized + Copy + Clone + Send + Sync {
pub trait Group<E: ScalarEngine>: Sized + Copy + Clone + Send + Sync {
fn group_zero() -> Self;
fn group_mul_assign(&mut self, by: &E::Fr);
fn group_add_assign(&mut self, other: &Self);
@ -227,23 +223,23 @@ impl<G: CurveProjective> Group<G::Engine> for Point<G> {
}
}
pub struct Scalar<E: Engine>(pub E::Fr);
pub struct Scalar<E: ScalarEngine>(pub E::Fr);
impl<E: Engine> PartialEq for Scalar<E> {
impl<E: ScalarEngine> PartialEq for Scalar<E> {
fn eq(&self, other: &Scalar<E>) -> bool {
self.0 == other.0
}
}
impl<E: Engine> Copy for Scalar<E> { }
impl<E: ScalarEngine> Copy for Scalar<E> { }
impl<E: Engine> Clone for Scalar<E> {
impl<E: ScalarEngine> Clone for Scalar<E> {
fn clone(&self) -> Scalar<E> {
*self
}
}
impl<E: Engine> Group<E> for Scalar<E> {
impl<E: ScalarEngine> Group<E> for Scalar<E> {
fn group_zero() -> Self {
Scalar(E::Fr::zero())
}
@ -258,7 +254,7 @@ impl<E: Engine> Group<E> for Scalar<E> {
}
}
fn best_fft<E: Engine, T: Group<E>>(a: &mut [T], worker: &Worker, omega: &E::Fr, log_n: u32)
fn best_fft<E: ScalarEngine, T: Group<E>>(a: &mut [T], worker: &Worker, omega: &E::Fr, log_n: u32)
{
let log_cpus = worker.log_num_cpus();
@ -269,7 +265,7 @@ fn best_fft<E: Engine, T: Group<E>>(a: &mut [T], worker: &Worker, omega: &E::Fr,
}
}
fn serial_fft<E: Engine, T: Group<E>>(a: &mut [T], omega: &E::Fr, log_n: u32)
fn serial_fft<E: ScalarEngine, T: Group<E>>(a: &mut [T], omega: &E::Fr, log_n: u32)
{
fn bitreverse(mut n: u32, l: u32) -> u32 {
let mut r = 0;
@ -314,7 +310,7 @@ fn serial_fft<E: Engine, T: Group<E>>(a: &mut [T], omega: &E::Fr, log_n: u32)
}
}
fn parallel_fft<E: Engine, T: Group<E>>(
fn parallel_fft<E: ScalarEngine, T: Group<E>>(
a: &mut [T],
worker: &Worker,
omega: &E::Fr,
@ -375,12 +371,13 @@ fn parallel_fft<E: Engine, T: Group<E>>(
// Test multiplying various (low degree) polynomials together and
// comparing with naive evaluations.
#[cfg(feature = "pairing")]
#[test]
fn polynomial_arith() {
use pairing::bls12_381::Bls12;
use rand::{self, Rand};
fn test_mul<E: Engine, R: rand::Rng>(rng: &mut R)
fn test_mul<E: ScalarEngine, R: rand::Rng>(rng: &mut R)
{
let worker = Worker::new();
@ -422,12 +419,13 @@ fn polynomial_arith() {
test_mul::<Bls12, _>(rng);
}
#[cfg(feature = "pairing")]
#[test]
fn fft_composition() {
use pairing::bls12_381::Bls12;
use rand;
fn test_comp<E: Engine, R: rand::Rng>(rng: &mut R)
fn test_comp<E: ScalarEngine, R: rand::Rng>(rng: &mut R)
{
let worker = Worker::new();
@ -460,13 +458,14 @@ fn fft_composition() {
test_comp::<Bls12, _>(rng);
}
#[cfg(feature = "pairing")]
#[test]
fn parallel_fft_consistency() {
use pairing::bls12_381::Bls12;
use rand::{self, Rand};
use std::cmp::min;
fn test_consistency<E: Engine, R: rand::Rng>(rng: &mut R)
fn test_consistency<E: ScalarEngine, R: rand::Rng>(rng: &mut R)
{
let worker = Worker::new();

11
bellman/src/groth16/generator.rs

@ -2,14 +2,9 @@ use rand::Rng;
use std::sync::Arc;
use pairing::{
Engine,
PrimeField,
Field,
Wnaf,
CurveProjective,
CurveAffine
};
use ff::{Field, PrimeField};
use group::{CurveAffine, CurveProjective, Wnaf};
use pairing::Engine;
use super::{
Parameters,

10
bellman/src/groth16/mod.rs

@ -1,7 +1,7 @@
use group::{CurveAffine, EncodedPoint};
use pairing::{
Engine,
CurveAffine,
EncodedPoint
PairingCurveAffine,
};
use ::{
@ -385,9 +385,9 @@ pub struct PreparedVerifyingKey<E: Engine> {
/// Pairing result of alpha*beta
alpha_g1_beta_g2: E::Fqk,
/// -gamma in G2
neg_gamma_g2: <E::G2Affine as CurveAffine>::Prepared,
neg_gamma_g2: <E::G2Affine as PairingCurveAffine>::Prepared,
/// -delta in G2
neg_delta_g2: <E::G2Affine as CurveAffine>::Prepared,
neg_delta_g2: <E::G2Affine as PairingCurveAffine>::Prepared,
/// Copy of IC from `VerifiyingKey`.
ic: Vec<E::G1Affine>
}
@ -486,8 +486,8 @@ mod test_with_bls12_381 {
use super::*;
use {Circuit, SynthesisError, ConstraintSystem};
use ff::Field;
use rand::{Rand, thread_rng};
use pairing::{Field};
use pairing::bls12_381::{Bls12, Fr};
#[test]

10
bellman/src/groth16/prover.rs

@ -4,13 +4,9 @@ use std::sync::Arc;
use futures::Future;
use pairing::{
Engine,
PrimeField,
Field,
CurveProjective,
CurveAffine
};
use ff::{Field, PrimeField};
use group::{CurveAffine, CurveProjective};
use pairing::Engine;
use super::{
ParameterSource,

44
bellman/src/groth16/tests/dummy_engine.rs

@ -1,16 +1,8 @@
use pairing::{
Engine,
PrimeField,
PrimeFieldRepr,
Field,
SqrtField,
LegendreSymbol,
CurveProjective,
CurveAffine,
PrimeFieldDecodingError,
GroupDecodingError,
EncodedPoint
};
use ff::{
Field, LegendreSymbol, PrimeField, PrimeFieldDecodingError,
PrimeFieldRepr, ScalarEngine, SqrtField};
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
use pairing::{Engine, PairingCurveAffine};
use std::cmp::Ordering;
use std::fmt;
@ -263,8 +255,11 @@ impl PrimeField for Fr {
#[derive(Clone)]
pub struct DummyEngine;
impl Engine for DummyEngine {
impl ScalarEngine for DummyEngine {
type Fr = Fr;
}
impl Engine for DummyEngine {
type G1 = Fr;
type G1Affine = Fr;
type G2 = Fr;
@ -277,8 +272,8 @@ impl Engine for DummyEngine {
fn miller_loop<'a, I>(i: I) -> Self::Fqk
where I: IntoIterator<Item=&'a (
&'a <Self::G1Affine as CurveAffine>::Prepared,
&'a <Self::G2Affine as CurveAffine>::Prepared
&'a <Self::G1Affine as PairingCurveAffine>::Prepared,
&'a <Self::G2Affine as PairingCurveAffine>::Prepared
)>
{
let mut acc = <Fr as Field>::zero();
@ -401,11 +396,8 @@ impl EncodedPoint for FakePoint {
}
impl CurveAffine for Fr {
type Pair = Fr;
type PairingResult = Fr;
type Compressed = FakePoint;
type Uncompressed = FakePoint;
type Prepared = Fr;
type Projective = Fr;
type Base = Fr;
type Scalar = Fr;
@ -437,6 +429,16 @@ impl CurveAffine for Fr {
res
}
fn into_projective(&self) -> Self::Projective {
*self
}
}
impl PairingCurveAffine for Fr {
type Prepared = Fr;
type Pair = Fr;
type PairingResult = Fr;
fn prepare(&self) -> Self::Prepared {
*self
}
@ -444,8 +446,4 @@ impl CurveAffine for Fr {
fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult {
self.mul(*other)
}
fn into_projective(&self) -> Self::Projective {
*self
}
}

7
bellman/src/groth16/tests/mod.rs

@ -1,8 +1,5 @@
use pairing::{
Engine,
Field,
PrimeField
};
use ff::{Field, PrimeField};
use pairing::Engine;
mod dummy_engine;
use self::dummy_engine::*;

9
bellman/src/groth16/verifier.rs

@ -1,9 +1,6 @@
use pairing::{
Engine,
CurveProjective,
CurveAffine,
PrimeField
};
use ff::PrimeField;
use group::{CurveAffine, CurveProjective};
use pairing::{Engine, PairingCurveAffine};
use super::{
Proof,

40
bellman/src/lib.rs

@ -1,3 +1,6 @@
extern crate ff;
extern crate group;
#[cfg(feature = "pairing")]
extern crate pairing;
extern crate rand;
extern crate num_cpus;
@ -10,9 +13,10 @@ extern crate byteorder;
pub mod multicore;
mod multiexp;
pub mod domain;
#[cfg(feature = "groth16")]
pub mod groth16;
use pairing::{Engine, Field};
use ff::{Field, ScalarEngine};
use std::ops::{Add, Sub};
use std::fmt;
@ -24,7 +28,7 @@ use std::marker::PhantomData;
/// rank-1 quadratic constraint systems. The `Circuit` trait represents a
/// circuit that can be synthesized. The `synthesize` method is called during
/// CRS generation and during proving.
pub trait Circuit<E: Engine> {
pub trait Circuit<E: ScalarEngine> {
/// Synthesize the circuit into a rank-1 quadratic constraint system
fn synthesize<CS: ConstraintSystem<E>>(
self,
@ -61,21 +65,21 @@ pub enum Index {
/// This represents a linear combination of some variables, with coefficients
/// in the scalar field of a pairing-friendly elliptic curve group.
#[derive(Clone)]
pub struct LinearCombination<E: Engine>(Vec<(Variable, E::Fr)>);
pub struct LinearCombination<E: ScalarEngine>(Vec<(Variable, E::Fr)>);
impl<E: Engine> AsRef<[(Variable, E::Fr)]> for LinearCombination<E> {
impl<E: ScalarEngine> AsRef<[(Variable, E::Fr)]> for LinearCombination<E> {
fn as_ref(&self) -> &[(Variable, E::Fr)] {
&self.0
}
}
impl<E: Engine> LinearCombination<E> {
impl<E: ScalarEngine> LinearCombination<E> {
pub fn zero() -> LinearCombination<E> {
LinearCombination(vec![])
}
}
impl<E: Engine> Add<(E::Fr, Variable)> for LinearCombination<E> {
impl<E: ScalarEngine> Add<(E::Fr, Variable)> for LinearCombination<E> {
type Output = LinearCombination<E>;
fn add(mut self, (coeff, var): (E::Fr, Variable)) -> LinearCombination<E> {
@ -85,7 +89,7 @@ impl<E: Engine> Add<(E::Fr, Variable)> for LinearCombination<E> {
}
}
impl<E: Engine> Sub<(E::Fr, Variable)> for LinearCombination<E> {
impl<E: ScalarEngine> Sub<(E::Fr, Variable)> for LinearCombination<E> {
type Output = LinearCombination<E>;
fn sub(self, (mut coeff, var): (E::Fr, Variable)) -> LinearCombination<E> {
@ -95,7 +99,7 @@ impl<E: Engine> Sub<(E::Fr, Variable)> for LinearCombination<E> {
}
}
impl<E: Engine> Add<Variable> for LinearCombination<E> {
impl<E: ScalarEngine> Add<Variable> for LinearCombination<E> {
type Output = LinearCombination<E>;
fn add(self, other: Variable) -> LinearCombination<E> {
@ -103,7 +107,7 @@ impl<E: Engine> Add<Variable> for LinearCombination<E> {
}
}
impl<E: Engine> Sub<Variable> for LinearCombination<E> {
impl<E: ScalarEngine> Sub<Variable> for LinearCombination<E> {
type Output = LinearCombination<E>;
fn sub(self, other: Variable) -> LinearCombination<E> {
@ -111,7 +115,7 @@ impl<E: Engine> Sub<Variable> for LinearCombination<E> {
}
}
impl<'a, E: Engine> Add<&'a LinearCombination<E>> for LinearCombination<E> {
impl<'a, E: ScalarEngine> Add<&'a LinearCombination<E>> for LinearCombination<E> {
type Output = LinearCombination<E>;
fn add(mut self, other: &'a LinearCombination<E>) -> LinearCombination<E> {
@ -123,7 +127,7 @@ impl<'a, E: Engine> Add<&'a LinearCombination<E>> for LinearCombination<E> {
}
}
impl<'a, E: Engine> Sub<&'a LinearCombination<E>> for LinearCombination<E> {
impl<'a, E: ScalarEngine> Sub<&'a LinearCombination<E>> for LinearCombination<E> {
type Output = LinearCombination<E>;
fn sub(mut self, other: &'a LinearCombination<E>) -> LinearCombination<E> {
@ -135,7 +139,7 @@ impl<'a, E: Engine> Sub<&'a LinearCombination<E>> for LinearCombination<E> {
}
}
impl<'a, E: Engine> Add<(E::Fr, &'a LinearCombination<E>)> for LinearCombination<E> {
impl<'a, E: ScalarEngine> Add<(E::Fr, &'a LinearCombination<E>)> for LinearCombination<E> {
type Output = LinearCombination<E>;
fn add(mut self, (coeff, other): (E::Fr, &'a LinearCombination<E>)) -> LinearCombination<E> {
@ -149,7 +153,7 @@ impl<'a, E: Engine> Add<(E::Fr, &'a LinearCombination<E>)> for LinearCombination
}
}
impl<'a, E: Engine> Sub<(E::Fr, &'a LinearCombination<E>)> for LinearCombination<E> {
impl<'a, E: ScalarEngine> Sub<(E::Fr, &'a LinearCombination<E>)> for LinearCombination<E> {
type Output = LinearCombination<E>;
fn sub(mut self, (coeff, other): (E::Fr, &'a LinearCombination<E>)) -> LinearCombination<E> {
@ -219,7 +223,7 @@ impl fmt::Display for SynthesisError {
/// Represents a constraint system which can have new variables
/// allocated and constrains between them formed.
pub trait ConstraintSystem<E: Engine>: Sized {
pub trait ConstraintSystem<E: ScalarEngine>: Sized {
/// Represents the type of the "root" of this constraint system
/// so that nested namespaces can minimize indirection.
type Root: ConstraintSystem<E>;
@ -291,9 +295,9 @@ pub trait ConstraintSystem<E: Engine>: Sized {
/// This is a "namespaced" constraint system which borrows a constraint system (pushing
/// a namespace context) and, when dropped, pops out of the namespace context.
pub struct Namespace<'a, E: Engine, CS: ConstraintSystem<E> + 'a>(&'a mut CS, PhantomData<E>);
pub struct Namespace<'a, E: ScalarEngine, CS: ConstraintSystem<E> + 'a>(&'a mut CS, PhantomData<E>);
impl<'cs, E: Engine, CS: ConstraintSystem<E>> ConstraintSystem<E> for Namespace<'cs, E, CS> {
impl<'cs, E: ScalarEngine, CS: ConstraintSystem<E>> ConstraintSystem<E> for Namespace<'cs, E, CS> {
type Root = CS::Root;
fn one() -> Variable {
@ -356,7 +360,7 @@ impl<'cs, E: Engine, CS: ConstraintSystem<E>> ConstraintSystem<E> for Namespace<
}
}
impl<'a, E: Engine, CS: ConstraintSystem<E>> Drop for Namespace<'a, E, CS> {
impl<'a, E: ScalarEngine, CS: ConstraintSystem<E>> Drop for Namespace<'a, E, CS> {
fn drop(&mut self) {
self.get_root().pop_namespace()
}
@ -364,7 +368,7 @@ impl<'a, E: Engine, CS: ConstraintSystem<E>> Drop for Namespace<'a, E, CS> {
/// Convenience implementation of ConstraintSystem<E> for mutable references to
/// constraint systems.
impl<'cs, E: Engine, CS: ConstraintSystem<E>> ConstraintSystem<E> for &'cs mut CS {
impl<'cs, E: ScalarEngine, CS: ConstraintSystem<E>> ConstraintSystem<E> for &'cs mut CS {
type Root = CS::Root;
fn one() -> Variable {

25
bellman/src/multiexp.rs

@ -1,11 +1,5 @@
use pairing::{
CurveAffine,
CurveProjective,
Engine,
PrimeField,
Field,
PrimeFieldRepr
};
use ff::{Field, PrimeField, PrimeFieldRepr, ScalarEngine};
use group::{CurveAffine, CurveProjective};
use std::sync::Arc;
use std::io;
use bit_vec::{self, BitVec};
@ -141,7 +135,7 @@ fn multiexp_inner<Q, D, G, S>(
pool: &Worker,
bases: S,
density_map: D,
exponents: Arc<Vec<<<G::Engine as Engine>::Fr as PrimeField>::Repr>>,
exponents: Arc<Vec<<<G::Engine as ScalarEngine>::Fr as PrimeField>::Repr>>,
mut skip: u32,
c: u32,
handle_trivial: bool
@ -167,8 +161,8 @@ fn multiexp_inner<Q, D, G, S>(
// Create space for the buckets
let mut buckets = vec![<G as CurveAffine>::Projective::zero(); (1 << c) - 1];
let zero = <G::Engine as Engine>::Fr::zero().into_repr();
let one = <G::Engine as Engine>::Fr::one().into_repr();
let zero = <G::Engine as ScalarEngine>::Fr::zero().into_repr();
let one = <G::Engine as ScalarEngine>::Fr::one().into_repr();
// Sort the bases into buckets
for (&exp, density) in exponents.iter().zip(density_map.as_ref().iter()) {
@ -211,7 +205,7 @@ fn multiexp_inner<Q, D, G, S>(
skip += c;
if skip >= <G::Engine as Engine>::Fr::NUM_BITS {
if skip >= <G::Engine as ScalarEngine>::Fr::NUM_BITS {
// There isn't another region.
Box::new(this)
} else {
@ -238,7 +232,7 @@ pub fn multiexp<Q, D, G, S>(
pool: &Worker,
bases: S,
density_map: D,
exponents: Arc<Vec<<<G::Engine as Engine>::Fr as PrimeField>::Repr>>
exponents: Arc<Vec<<<G::Engine as ScalarEngine>::Fr as PrimeField>::Repr>>
) -> Box<Future<Item=<G as CurveAffine>::Projective, Error=SynthesisError>>
where for<'a> &'a Q: QueryDensity,
D: Send + Sync + 'static + Clone + AsRef<Q>,
@ -261,6 +255,7 @@ pub fn multiexp<Q, D, G, S>(
multiexp_inner(pool, bases, density_map, exponents, 0, c, true)
}
#[cfg(feature = "pairing")]
#[test]
fn test_with_bls12() {
fn naive_multiexp<G: CurveAffine>(
@ -280,12 +275,12 @@ fn test_with_bls12() {
}
use rand::{self, Rand};
use pairing::bls12_381::Bls12;
use pairing::{bls12_381::Bls12, Engine};
const SAMPLES: usize = 1 << 14;
let rng = &mut rand::thread_rng();
let v = Arc::new((0..SAMPLES).map(|_| <Bls12 as Engine>::Fr::rand(rng).into_repr()).collect::<Vec<_>>());
let v = Arc::new((0..SAMPLES).map(|_| <Bls12 as ScalarEngine>::Fr::rand(rng).into_repr()).collect::<Vec<_>>());
let g = Arc::new((0..SAMPLES).map(|_| <Bls12 as Engine>::G1::rand(rng).into_affine()).collect::<Vec<_>>());
let naive = naive_multiexp(g.clone(), v.clone());

7
bellman/tests/mimc.rs

@ -1,4 +1,5 @@
extern crate bellman;
extern crate ff;
extern crate pairing;
extern crate rand;
@ -9,10 +10,8 @@ use rand::{thread_rng, Rng};
use std::time::{Duration, Instant};
// Bring in some tools for using pairing-friendly curves
use pairing::{
Engine,
Field
};
use ff::Field;
use pairing::Engine;
// We're going to use the BLS12-381 pairing-friendly elliptic curve.
use pairing::bls12_381::{

3
ff/.gitignore vendored

@ -0,0 +1,3 @@
target/
**/*.rs.bk
Cargo.lock

18
ff/Cargo.toml

@ -0,0 +1,18 @@
[package]
name = "ff"
version = "0.4.0"
authors = ["Sean Bowe <[email protected]>"]
description = "Library for building and interfacing with finite fields"
documentation = "https://docs.rs/ff/"
homepage = "https://github.com/ebfull/ff"
license = "MIT/Apache-2.0"
repository = "https://github.com/ebfull/ff"
[dependencies]
byteorder = "1"
rand = "0.4"
ff_derive = { version = "0.3.0", path = "ff_derive", optional = true }
[features]
default = []
derive = ["ff_derive"]

202
ff/LICENSE-APACHE

@ -0,0 +1,202 @@
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.

21
ff/LICENSE-MIT

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017 Sean Bowe
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.

60
ff/README.md

@ -0,0 +1,60 @@
# ff
`ff` is a finite field library written in pure Rust, with no `unsafe{}` code.
## Disclaimers
* This library does not provide constant-time guarantees.
## Usage
Add the `ff` crate to your `Cargo.toml`:
```toml
[dependencies]
ff = "0.4"
```
The `ff` crate contains `Field`, `PrimeField`, `PrimeFieldRepr` and `SqrtField` traits. See the **[documentation](https://docs.rs/ff/0.4.0/ff/)** for more.
### #![derive(PrimeField)]
If you need an implementation of a prime field, this library also provides a procedural macro that will expand into an efficient implementation of a prime field when supplied with the modulus. `PrimeFieldGenerator` must be an element of Fp of p-1 order, that is also quadratic nonresidue.
First, enable the `derive` crate feature:
```toml
[dependencies]
ff = { version = "0.4", features = ["derive"] }
```
And then use the macro like so:
```rust
extern crate rand;
#[macro_use]
extern crate ff;
#[derive(PrimeField)]
#[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"]
#[PrimeFieldGenerator = "7"]
struct Fp(FpRepr);
```
And that's it! `Fp` now implements `Field` and `PrimeField`. `Fp` will also implement `SqrtField` if supported. The library implements `FpRepr` itself and derives `PrimeFieldRepr` for it.
## License
Licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally
submitted for inclusion in the work by you, as defined in the Apache-2.0
license, shall be dual licensed as above, without any additional terms or
conditions.

20
ff/ff_derive/Cargo.toml

@ -0,0 +1,20 @@
[package]
name = "ff_derive"
version = "0.3.0"
authors = ["Sean Bowe <[email protected]>"]
description = "Procedural macro library used to build custom prime field implementations"
documentation = "https://docs.rs/ff/"
homepage = "https://github.com/ebfull/ff"
license = "MIT/Apache-2.0"
repository = "https://github.com/ebfull/ff"
[lib]
proc-macro = true
[dependencies]
num-bigint = "0.2"
num-traits = "0.2"
num-integer = "0.1"
proc-macro2 = "0.4"
quote = "0.6"
syn = "0.14"

1065
ff/ff_derive/src/lib.rs

File diff suppressed because it is too large Load Diff

393
ff/src/lib.rs

@ -0,0 +1,393 @@
#![allow(unused_imports)]
extern crate byteorder;
extern crate rand;
#[cfg(feature = "derive")]
#[macro_use]
extern crate ff_derive;
#[cfg(feature = "derive")]
pub use ff_derive::*;
use std::error::Error;
use std::fmt;
use std::io::{self, Read, Write};
/// This trait represents an element of a field.
pub trait Field:
Sized + Eq + Copy + Clone + Send + Sync + fmt::Debug + fmt::Display + 'static + rand::Rand
{
/// Returns the zero element of the field, the additive identity.
fn zero() -> Self;
/// Returns the one element of the field, the multiplicative identity.
fn one() -> Self;
/// Returns true iff this element is zero.
fn is_zero(&self) -> bool;
/// Squares this element.
fn square(&mut self);
/// Doubles this element.
fn double(&mut self);
/// Negates this element.
fn negate(&mut self);
/// Adds another element to this element.
fn add_assign(&mut self, other: &Self);
/// Subtracts another element from this element.
fn sub_assign(&mut self, other: &Self);
/// Multiplies another element by this element.
fn mul_assign(&mut self, other: &Self);
/// Computes the multiplicative inverse of this element, if nonzero.
fn inverse(&self) -> Option<Self>;
/// Exponentiates this element by a power of the base prime modulus via
/// the Frobenius automorphism.
fn frobenius_map(&mut self, power: usize);
/// Exponentiates this element by a number represented with `u64` limbs,
/// least significant digit first.
fn pow<S: AsRef<[u64]>>(&self, exp: S) -> Self {
let mut res = Self::one();
let mut found_one = false;
for i in BitIterator::new(exp) {
if found_one {
res.square();
} else {
found_one = i;
}
if i {
res.mul_assign(self);
}
}
res
}
}
/// This trait represents an element of a field that has a square root operation described for it.
pub trait SqrtField: Field {
/// Returns the Legendre symbol of the field element.
fn legendre(&self) -> LegendreSymbol;
/// Returns the square root of the field element, if it is
/// quadratic residue.
fn sqrt(&self) -> Option<Self>;
}
/// This trait represents a wrapper around a biginteger which can encode any element of a particular
/// prime field. It is a smart wrapper around a sequence of `u64` limbs, least-significant digit
/// first.
pub trait PrimeFieldRepr:
Sized
+ Copy
+ Clone
+ Eq
+ Ord
+ Send
+ Sync
+ Default
+ fmt::Debug
+ fmt::Display
+ 'static
+ rand::Rand
+ AsRef<[u64]>
+ AsMut<[u64]>
+ From<u64>
{
/// Subtract another represetation from this one.
fn sub_noborrow(&mut self, other: &Self);
/// Add another representation to this one.
fn add_nocarry(&mut self, other: &Self);
/// Compute the number of bits needed to encode this number. Always a
/// multiple of 64.
fn num_bits(&self) -> u32;
/// Returns true iff this number is zero.
fn is_zero(&self) -> bool;
/// Returns true iff this number is odd.
fn is_odd(&self) -> bool;
/// Returns true iff this number is even.
fn is_even(&self) -> bool;
/// Performs a rightwise bitshift of this number, effectively dividing
/// it by 2.
fn div2(&mut self);
/// Performs a rightwise bitshift of this number by some amount.
fn shr(&mut self, amt: u32);
/// Performs a leftwise bitshift of this number, effectively multiplying
/// it by 2. Overflow is ignored.
fn mul2(&mut self);
/// Performs a leftwise bitshift of this number by some amount.
fn shl(&mut self, amt: u32);
/// Writes this `PrimeFieldRepr` as a big endian integer.
fn write_be<W: Write>(&self, mut writer: W) -> io::Result<()> {
use byteorder::{BigEndian, WriteBytesExt};
for digit in self.as_ref().iter().rev() {
writer.write_u64::<BigEndian>(*digit)?;
}
Ok(())
}
/// Reads a big endian integer into this representation.
fn read_be<R: Read>(&mut self, mut reader: R) -> io::Result<()> {
use byteorder::{BigEndian, ReadBytesExt};
for digit in self.as_mut().iter_mut().rev() {
*digit = reader.read_u64::<BigEndian>()?;
}
Ok(())
}
/// Writes this `PrimeFieldRepr` as a little endian integer.
fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> {
use byteorder::{LittleEndian, WriteBytesExt};
for digit in self.as_ref().iter() {
writer.write_u64::<LittleEndian>(*digit)?;
}
Ok(())
}
/// Reads a little endian integer into this representation.
fn read_le<R: Read>(&mut self, mut reader: R) -> io::Result<()> {
use byteorder::{LittleEndian, ReadBytesExt};
for digit in self.as_mut().iter_mut() {
*digit = reader.read_u64::<LittleEndian>()?;
}
Ok(())
}
}
#[derive(Debug, PartialEq)]
pub enum LegendreSymbol {
Zero = 0,
QuadraticResidue = 1,
QuadraticNonResidue = -1,
}
/// An error that may occur when trying to interpret a `PrimeFieldRepr` as a
/// `PrimeField` element.
#[derive(Debug)]
pub enum PrimeFieldDecodingError {
/// The encoded value is not in the field
NotInField(String),
}
impl Error for PrimeFieldDecodingError {
fn description(&self) -> &str {
match *self {
PrimeFieldDecodingError::NotInField(..) => "not an element of the field",
}
}
}
impl fmt::Display for PrimeFieldDecodingError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
PrimeFieldDecodingError::NotInField(ref repr) => {
write!(f, "{} is not an element of the field", repr)
}
}
}
}
/// This represents an element of a prime field.
pub trait PrimeField: Field {
/// The prime field can be converted back and forth into this biginteger
/// representation.
type Repr: PrimeFieldRepr + From<Self>;
/// Interpret a string of numbers as a (congruent) prime field element.
/// Does not accept unnecessary leading zeroes or a blank string.
fn from_str(s: &str) -> Option<Self> {
if s.is_empty() {
return None;
}
if s == "0" {
return Some(Self::zero());
}
let mut res = Self::zero();
let ten = Self::from_repr(Self::Repr::from(10)).unwrap();
let mut first_digit = true;
for c in s.chars() {
match c.to_digit(10) {
Some(c) => {
if first_digit {
if c == 0 {
return None;
}
first_digit = false;
}
res.mul_assign(&ten);
res.add_assign(&Self::from_repr(Self::Repr::from(u64::from(c))).unwrap());
}
None => {
return None;
}
}
}
Some(res)
}
/// Convert this prime field element into a biginteger representation.
fn from_repr(Self::Repr) -> Result<Self, PrimeFieldDecodingError>;
/// Convert a biginteger representation into a prime field element, if
/// the number is an element of the field.
fn into_repr(&self) -> Self::Repr;
/// Returns the field characteristic; the modulus.
fn char() -> Self::Repr;
/// How many bits are needed to represent an element of this field.
const NUM_BITS: u32;
/// How many bits of information can be reliably stored in the field element.
const CAPACITY: u32;
/// Returns the multiplicative generator of `char()` - 1 order. This element
/// must also be quadratic nonresidue.
fn multiplicative_generator() -> Self;
/// 2^s * t = `char()` - 1 with t odd.
const S: u32;
/// Returns the 2^s root of unity computed by exponentiating the `multiplicative_generator()`
/// by t.
fn root_of_unity() -> Self;
}
/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
/// with well-defined relationships. Specific relationships (for example, a
/// pairing-friendly curve) can be defined in a subtrait.
pub trait ScalarEngine: Sized + 'static + Clone {
/// This is the scalar field of the engine's groups.
type Fr: PrimeField + SqrtField;
}
#[derive(Debug)]
pub struct BitIterator<E> {
t: E,
n: usize,
}
impl<E: AsRef<[u64]>> BitIterator<E> {
pub fn new(t: E) -> Self {
let n = t.as_ref().len() * 64;
BitIterator { t, n }
}
}
impl<E: AsRef<[u64]>> Iterator for BitIterator<E> {
type Item = bool;
fn next(&mut self) -> Option<bool> {
if self.n == 0 {
None
} else {
self.n -= 1;
let part = self.n / 64;
let bit = self.n - (64 * part);
Some(self.t.as_ref()[part] & (1 << bit) > 0)
}
}
}
#[test]
fn test_bit_iterator() {
let mut a = BitIterator::new([0xa953d79b83f6ab59, 0x6dea2059e200bd39]);
let expected = "01101101111010100010000001011001111000100000000010111101001110011010100101010011110101111001101110000011111101101010101101011001";
for e in expected.chars() {
assert!(a.next().unwrap() == (e == '1'));
}
assert!(a.next().is_none());
let expected = "1010010101111110101010000101101011101000011101110101001000011001100100100011011010001011011011010001011011101100110100111011010010110001000011110100110001100110011101101000101100011100100100100100001010011101010111110011101011000011101000111011011101011001";
let mut a = BitIterator::new([
0x429d5f3ac3a3b759,
0xb10f4c66768b1c92,
0x92368b6d16ecd3b4,
0xa57ea85ae8775219,
]);
for e in expected.chars() {
assert!(a.next().unwrap() == (e == '1'));
}
assert!(a.next().is_none());
}
pub use self::arith_impl::*;
mod arith_impl {
/// Calculate a - b - borrow, returning the result and modifying
/// the borrow value.
#[inline(always)]
pub fn sbb(a: u64, b: u64, borrow: &mut u64) -> u64 {
let tmp = (1u128 << 64) + u128::from(a) - u128::from(b) - u128::from(*borrow);
*borrow = if tmp >> 64 == 0 { 1 } else { 0 };
tmp as u64
}
/// Calculate a + b + carry, returning the sum and modifying the
/// carry value.
#[inline(always)]
pub fn adc(a: u64, b: u64, carry: &mut u64) -> u64 {
let tmp = u128::from(a) + u128::from(b) + u128::from(*carry);
*carry = (tmp >> 64) as u64;
tmp as u64
}
/// Calculate a + (b * c) + carry, returning the least significant digit
/// and setting carry to the most significant digit.
#[inline(always)]
pub fn mac_with_carry(a: u64, b: u64, c: u64, carry: &mut u64) -> u64 {
let tmp = (u128::from(a)) + u128::from(b) * u128::from(c) + u128::from(*carry);
*carry = (tmp >> 64) as u64;
tmp as u64
}
}

3
group/.gitignore vendored

@ -0,0 +1,3 @@
/target
**/*.rs.bk
Cargo.lock

14
group/COPYRIGHT

@ -0,0 +1,14 @@
Copyrights in the "group" library are retained by their contributors. No
copyright assignment is required to contribute to the "group" library.
The "group" library is licensed under either of
* Apache License, Version 2.0, (see ./LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license (see ./LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally
submitted for inclusion in the work by you, as defined in the Apache-2.0
license, shall be dual licensed as above, without any additional terms or
conditions.

17
group/Cargo.toml

@ -0,0 +1,17 @@
[package]
name = "group"
version = "0.1.0"
authors = [
"Sean Bowe <[email protected]>",
"Jack Grigg <[email protected]>",
]
license = "MIT/Apache-2.0"
description = "Elliptic curve group traits and utilities"
documentation = "https://docs.rs/group/"
homepage = "https://github.com/ebfull/group"
repository = "https://github.com/ebfull/group"
[dependencies]
ff = { path = "../ff" }
rand = "0.4"

201
group/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.

23
group/LICENSE-MIT

@ -0,0 +1,23 @@
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.

17
group/README.md

@ -0,0 +1,17 @@
# group [![Crates.io](https://img.shields.io/crates/v/group.svg)](https://crates.io/crates/group) #
## License
Licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally
submitted for inclusion in the work by you, as defined in the Apache-2.0
license, shall be dual licensed as above, without any additional terms or
conditions.

196
group/src/lib.rs

@ -0,0 +1,196 @@
extern crate ff;
extern crate rand;
use ff::{PrimeField, PrimeFieldDecodingError, ScalarEngine, SqrtField};
use std::error::Error;
use std::fmt;
pub mod tests;
mod wnaf;
pub use self::wnaf::Wnaf;
/// Projective representation of an elliptic curve point guaranteed to be
/// in the correct prime order subgroup.
pub trait CurveProjective:
PartialEq
+ Eq
+ Sized
+ Copy
+ Clone
+ Send
+ Sync
+ fmt::Debug
+ fmt::Display
+ rand::Rand
+ 'static
{
type Engine: ScalarEngine<Fr = Self::Scalar>;
type Scalar: PrimeField + SqrtField;
type Base: SqrtField;
type Affine: CurveAffine<Projective = Self, Scalar = Self::Scalar>;
/// Returns the additive identity.
fn zero() -> Self;
/// Returns a fixed generator of unknown exponent.
fn one() -> Self;
/// Determines if this point is the point at infinity.
fn is_zero(&self) -> bool;
/// Normalizes a slice of projective elements so that
/// conversion to affine is cheap.
fn batch_normalization(v: &mut [Self]);
/// Checks if the point is already "normalized" so that
/// cheap affine conversion is possible.
fn is_normalized(&self) -> bool;
/// Doubles this element.
fn double(&mut self);
/// Adds another element to this element.
fn add_assign(&mut self, other: &Self);
/// Subtracts another element from this element.
fn sub_assign(&mut self, other: &Self) {
let mut tmp = *other;
tmp.negate();
self.add_assign(&tmp);
}
/// Adds an affine element to this element.
fn add_assign_mixed(&mut self, other: &Self::Affine);
/// Negates this element.
fn negate(&mut self);
/// Performs scalar multiplication of this element.
fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S);
/// Converts this element into its affine representation.
fn into_affine(&self) -> Self::Affine;
/// Recommends a wNAF window table size given a scalar. Always returns a number
/// between 2 and 22, inclusive.
fn recommended_wnaf_for_scalar(scalar: <Self::Scalar as PrimeField>::Repr) -> usize;
/// Recommends a wNAF window size given the number of scalars you intend to multiply
/// a base by. Always returns a number between 2 and 22, inclusive.
fn recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize;
}
/// Affine representation of an elliptic curve point guaranteed to be
/// in the correct prime order subgroup.
pub trait CurveAffine:
Copy + Clone + Sized + Send + Sync + fmt::Debug + fmt::Display + PartialEq + Eq + 'static
{
type Engine: ScalarEngine<Fr = Self::Scalar>;
type Scalar: PrimeField + SqrtField;
type Base: SqrtField;
type Projective: CurveProjective<Affine = Self, Scalar = Self::Scalar>;
type Uncompressed: EncodedPoint<Affine = Self>;
type Compressed: EncodedPoint<Affine = Self>;
/// Returns the additive identity.
fn zero() -> Self;
/// Returns a fixed generator of unknown exponent.
fn one() -> Self;
/// Determines if this point represents the point at infinity; the
/// additive identity.
fn is_zero(&self) -> bool;
/// Negates this element.
fn negate(&mut self);
/// Performs scalar multiplication of this element with mixed addition.
fn mul<S: Into<<Self::Scalar as PrimeField>::Repr>>(&self, other: S) -> Self::Projective;
/// Converts this element into its affine representation.
fn into_projective(&self) -> Self::Projective;
/// Converts this element into its compressed encoding, so long as it's not
/// the point at infinity.
fn into_compressed(&self) -> Self::Compressed {
<Self::Compressed as EncodedPoint>::from_affine(*self)
}
/// Converts this element into its uncompressed encoding, so long as it's not
/// the point at infinity.
fn into_uncompressed(&self) -> Self::Uncompressed {
<Self::Uncompressed as EncodedPoint>::from_affine(*self)
}
}
/// An encoded elliptic curve point, which should essentially wrap a `[u8; N]`.
pub trait EncodedPoint:
Sized + Send + Sync + AsRef<[u8]> + AsMut<[u8]> + Clone + Copy + 'static
{
type Affine: CurveAffine;
/// Creates an empty representation.
fn empty() -> Self;
/// Returns the number of bytes consumed by this representation.
fn size() -> usize;
/// Converts an `EncodedPoint` into a `CurveAffine` element,
/// if the encoding represents a valid element.
fn into_affine(&self) -> Result<Self::Affine, GroupDecodingError>;
/// Converts an `EncodedPoint` into a `CurveAffine` element,
/// without guaranteeing that the encoding represents a valid
/// element. This is useful when the caller knows the encoding is
/// valid already.
///
/// If the encoding is invalid, this can break API invariants,
/// so caution is strongly encouraged.
fn into_affine_unchecked(&self) -> Result<Self::Affine, GroupDecodingError>;
/// Creates an `EncodedPoint` from an affine point, as long as the
/// point is not the point at infinity.
fn from_affine(affine: Self::Affine) -> Self;
}
/// An error that may occur when trying to decode an `EncodedPoint`.
#[derive(Debug)]
pub enum GroupDecodingError {
/// The coordinate(s) do not lie on the curve.
NotOnCurve,
/// The element is not part of the r-order subgroup.
NotInSubgroup,
/// One of the coordinates could not be decoded
CoordinateDecodingError(&'static str, PrimeFieldDecodingError),
/// The compression mode of the encoded element was not as expected
UnexpectedCompressionMode,
/// The encoding contained bits that should not have been set
UnexpectedInformation,
}
impl Error for GroupDecodingError {
fn description(&self) -> &str {
match *self {
GroupDecodingError::NotOnCurve => "coordinate(s) do not lie on the curve",
GroupDecodingError::NotInSubgroup => "the element is not part of an r-order subgroup",
GroupDecodingError::CoordinateDecodingError(..) => "coordinate(s) could not be decoded",
GroupDecodingError::UnexpectedCompressionMode => {
"encoding has unexpected compression mode"
}
GroupDecodingError::UnexpectedInformation => "encoding has unexpected information",
}
}
}
impl fmt::Display for GroupDecodingError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
GroupDecodingError::CoordinateDecodingError(description, ref err) => {
write!(f, "{} decoding error: {}", description, err)
}
_ => write!(f, "{}", self.description()),
}
}
}

13
pairing/src/tests/curve.rs → group/src/tests/mod.rs

@ -1,6 +1,6 @@
use rand::{Rand, Rng, SeedableRng, XorShiftRng};
use {CurveAffine, CurveProjective, EncodedPoint, Field};
use {CurveAffine, CurveProjective, EncodedPoint};
pub fn curve_tests<G: CurveProjective>() {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
@ -47,8 +47,7 @@ pub fn curve_tests<G: CurveProjective>() {
{
let a = G::rand(&mut rng);
let b = a.into_affine().into_projective();
let c = a
.into_affine()
let c = a.into_affine()
.into_projective()
.into_affine()
.into_projective();
@ -66,8 +65,9 @@ pub fn curve_tests<G: CurveProjective>() {
}
fn random_wnaf_tests<G: CurveProjective>() {
use ff::PrimeField;
use wnaf::*;
use PrimeField;
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
@ -179,6 +179,8 @@ fn random_wnaf_tests<G: CurveProjective>() {
}
fn random_negation_tests<G: CurveProjective>() {
use ff::Field;
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
for _ in 0..1000 {
@ -373,8 +375,7 @@ fn random_transformation_tests<G: CurveProjective>() {
v[s] = v[s].into_affine().into_projective();
}
let expected_v = v
.iter()
let expected_v = v.iter()
.map(|v| v.into_affine().into_projective())
.collect::<Vec<_>>();
G::batch_normalization(&mut v);

4
pairing/src/wnaf.rs → group/src/wnaf.rs

@ -1,4 +1,6 @@
use super::{CurveProjective, PrimeField, PrimeFieldRepr};
use ff::{PrimeField, PrimeFieldRepr};
use super::CurveProjective;
/// Replaces the contents of `table` with a w-NAF window table for the given window size.
pub(crate) fn wnaf_table<G: CurveProjective>(table: &mut Vec<G>, mut base: G, window: usize) {

1
librustzcash/Cargo.toml

@ -15,6 +15,7 @@ crate-type = ["staticlib"]
[dependencies]
bellman = { path = "../bellman" }
ff = { path = "../ff" }
libc = "0.2"
pairing = { path = "../pairing" }
lazy_static = "1"

7
librustzcash/src/rustzcash.rs

@ -1,6 +1,7 @@
extern crate bellman;
extern crate blake2_rfc;
extern crate byteorder;
extern crate ff;
extern crate libc;
extern crate pairing;
extern crate rand;
@ -13,10 +14,8 @@ mod hashreader;
#[macro_use]
extern crate lazy_static;
use pairing::{
bls12_381::{Bls12, Fr, FrRepr},
BitIterator, PrimeField, PrimeFieldRepr,
};
use ff::{BitIterator, PrimeField, PrimeFieldRepr};
use pairing::bls12_381::{Bls12, Fr, FrRepr};
use sapling_crypto::{
circuit::multipack,

2
librustzcash/src/tests/key_agreement.rs

@ -1,5 +1,5 @@
use ff::{PrimeField, PrimeFieldRepr};
use pairing::bls12_381::Bls12;
use pairing::{PrimeField, PrimeFieldRepr};
use rand::{OsRng, Rng};
use sapling_crypto::jubjub::{edwards, JubjubBls12};
use sapling_crypto::primitives::{Diversifier, ViewingKey};

3
librustzcash/src/tests/key_components.rs

@ -1,4 +1,5 @@
use pairing::{bls12_381::Bls12, PrimeField, PrimeFieldRepr};
use ff::{PrimeField, PrimeFieldRepr};
use pairing::bls12_381::Bls12;
use sapling_crypto::{
jubjub::{fs::FsRepr, FixedGenerators, JubjubEngine, JubjubParams},
primitives::{Diversifier, ProofGenerationKey},

3
librustzcash/src/tests/signatures.rs

@ -1,4 +1,5 @@
use pairing::{bls12_381::Bls12, PrimeField, PrimeFieldRepr};
use ff::{PrimeField, PrimeFieldRepr};
use pairing::bls12_381::Bls12;
use sapling_crypto::{
jubjub::{FixedGenerators, JubjubEngine},
redjubjub::{PrivateKey, PublicKey, Signature},

9
pairing/Cargo.toml

@ -3,7 +3,10 @@ name = "pairing"
# Remember to change version string in README.md.
version = "0.14.2"
authors = ["Sean Bowe <[email protected]>"]
authors = [
"Sean Bowe <[email protected]>",
"Jack Grigg <[email protected]>",
]
license = "MIT/Apache-2.0"
description = "Pairing-friendly elliptic curve library"
@ -14,10 +17,10 @@ repository = "https://github.com/ebfull/pairing"
[dependencies]
rand = "0.4"
byteorder = "1"
clippy = { version = "0.0.200", optional = true }
ff = { path = "../ff", features = ["derive"] }
group = { path = "../group" }
[features]
unstable-features = ["expose-arith"]
expose-arith = []
u128-support = []
default = []

8
pairing/README.md

@ -6,14 +6,6 @@ This is a Rust crate for using pairing-friendly elliptic curves. Currently, only
Bring the `pairing` crate into your project just as you normally would.
If you're using a supported platform and the nightly Rust compiler, you can enable the `u128-support` feature for faster arithmetic.
```toml
[dependencies.pairing]
version = "0.14"
features = ["u128-support"]
```
## Security Warnings
This library does not make any guarantees about constant-time operations, memory access patterns, or resistance to side-channel attacks.

4
pairing/benches/bls12_381/ec.rs

@ -1,8 +1,8 @@
mod g1 {
use rand::{Rand, SeedableRng, XorShiftRng};
use group::CurveProjective;
use pairing::bls12_381::*;
use pairing::CurveProjective;
#[bench]
fn bench_g1_mul_assign(b: &mut ::test::Bencher) {
@ -65,8 +65,8 @@ mod g1 {
mod g2 {
use rand::{Rand, SeedableRng, XorShiftRng};
use group::CurveProjective;
use pairing::bls12_381::*;
use pairing::CurveProjective;
#[bench]
fn bench_g2_mul_assign(b: &mut ::test::Bencher) {

2
pairing/benches/bls12_381/fq.rs

@ -1,7 +1,7 @@
use rand::{Rand, SeedableRng, XorShiftRng};
use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField};
use pairing::bls12_381::*;
use pairing::{Field, PrimeField, PrimeFieldRepr, SqrtField};
#[bench]
fn bench_fq_repr_add_nocarry(b: &mut ::test::Bencher) {

2
pairing/benches/bls12_381/fq12.rs

@ -1,7 +1,7 @@
use rand::{Rand, SeedableRng, XorShiftRng};
use ff::Field;
use pairing::bls12_381::*;
use pairing::Field;
#[bench]
fn bench_fq12_add_assign(b: &mut ::test::Bencher) {

2
pairing/benches/bls12_381/fq2.rs

@ -1,7 +1,7 @@
use rand::{Rand, SeedableRng, XorShiftRng};
use ff::{Field, SqrtField};
use pairing::bls12_381::*;
use pairing::{Field, SqrtField};
#[bench]
fn bench_fq2_add_assign(b: &mut ::test::Bencher) {

2
pairing/benches/bls12_381/fr.rs

@ -1,7 +1,7 @@
use rand::{Rand, SeedableRng, XorShiftRng};
use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField};
use pairing::bls12_381::*;
use pairing::{Field, PrimeField, PrimeFieldRepr, SqrtField};
#[bench]
fn bench_fr_repr_add_nocarry(b: &mut ::test::Bencher) {

2
pairing/benches/bls12_381/mod.rs

@ -7,7 +7,7 @@ mod fr;
use rand::{Rand, SeedableRng, XorShiftRng};
use pairing::bls12_381::*;
use pairing::{CurveAffine, Engine};
use pairing::{Engine, PairingCurveAffine};
#[bench]
fn bench_pairing_g1_preparation(b: &mut ::test::Bencher) {

2
pairing/benches/pairing_benches.rs

@ -1,5 +1,7 @@
#![feature(test)]
extern crate ff;
extern crate group;
extern crate pairing;
extern crate rand;
extern crate test;

38
pairing/src/bls12_381/ec.rs

@ -148,12 +148,9 @@ macro_rules! curve_impl {
type Engine = Bls12;
type Scalar = $scalarfield;
type Base = $basefield;
type Prepared = $prepared;
type Projective = $projective;
type Uncompressed = $uncompressed;
type Compressed = $compressed;
type Pair = $pairing;
type PairingResult = Fq12;
fn zero() -> Self {
$affine {
@ -182,6 +179,17 @@ macro_rules! curve_impl {
}
}
fn into_projective(&self) -> $projective {
(*self).into()
}
}
impl PairingCurveAffine for $affine {
type Prepared = $prepared;
type Pair = $pairing;
type PairingResult = Fq12;
fn prepare(&self) -> Self::Prepared {
$prepared::from_affine(*self)
}
@ -190,10 +198,6 @@ macro_rules! curve_impl {
self.perform_pairing(other)
}
fn into_projective(&self) -> $projective {
(*self).into()
}
}
impl Rand for $projective {
@ -623,12 +627,11 @@ macro_rules! curve_impl {
pub mod g1 {
use super::super::{Bls12, Fq, Fq12, FqRepr, Fr, FrRepr};
use super::g2::G2Affine;
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
use rand::{Rand, Rng};
use std::fmt;
use {
BitIterator, CurveAffine, CurveProjective, EncodedPoint, Engine, Field, GroupDecodingError,
PrimeField, PrimeFieldRepr, SqrtField,
};
use {Engine, PairingCurveAffine};
curve_impl!(
"G1",
@ -1263,19 +1266,19 @@ pub mod g1 {
#[test]
fn g1_curve_tests() {
::tests::curve::curve_tests::<G1>();
use group::tests::curve_tests;
curve_tests::<G1>();
}
}
pub mod g2 {
use super::super::{Bls12, Fq, Fq12, Fq2, FqRepr, Fr, FrRepr};
use super::g1::G1Affine;
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
use rand::{Rand, Rng};
use std::fmt;
use {
BitIterator, CurveAffine, CurveProjective, EncodedPoint, Engine, Field, GroupDecodingError,
PrimeField, PrimeFieldRepr, SqrtField,
};
use {Engine, PairingCurveAffine};
curve_impl!(
"G2",
@ -2018,7 +2021,8 @@ pub mod g2 {
#[test]
fn g2_curve_tests() {
::tests::curve::curve_tests::<G2>();
use group::tests::curve_tests;
curve_tests::<G2>();
}
}

757
pairing/src/bls12_381/fq.rs

@ -1,69 +1,5 @@
use super::fq2::Fq2;
use std::cmp::Ordering;
use {Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField};
// q = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
const MODULUS: FqRepr = FqRepr([
0xb9feffffffffaaab,
0x1eabfffeb153ffff,
0x6730d2a0f6b0f624,
0x64774b84f38512bf,
0x4b1ba7b6434bacd7,
0x1a0111ea397fe69a,
]);
// The number of bits needed to represent the modulus.
const MODULUS_BITS: u32 = 381;
// The number of bits that must be shaved from the beginning of
// the representation when randomly sampling.
const REPR_SHAVE_BITS: u32 = 3;
// R = 2**384 % q
const R: FqRepr = FqRepr([
0x760900000002fffd,
0xebf4000bc40c0002,
0x5f48985753c758ba,
0x77ce585370525745,
0x5c071a97a256ec6d,
0x15f65ec3fa80e493,
]);
// R2 = R^2 % q
const R2: FqRepr = FqRepr([
0xf4df1f341c341746,
0xa76e6a609d104f1,
0x8de5476c4c95b6d5,
0x67eb88a9939d83c0,
0x9a793e85b519952d,
0x11988fe592cae3aa,
]);
// INV = -(q^{-1} mod 2^64) mod 2^64
const INV: u64 = 0x89f3fffcfffcfffd;
// GENERATOR = 2 (multiplicative generator of q-1 order, that is also quadratic nonresidue)
const GENERATOR: FqRepr = FqRepr([
0x321300000006554f,
0xb93c0018d6c40005,
0x57605e0db0ddbb51,
0x8b256521ed1f9bcb,
0x6cf28d7901622c03,
0x11ebab9dbb81e28c,
]);
// 2^s * t = MODULUS - 1 with t odd
const S: u32 = 1;
// 2^s root of unity computed by GENERATOR^t
const ROOT_OF_UNITY: FqRepr = FqRepr([
0x43f5fffffffcaaae,
0x32b7fff2ed47fffd,
0x7e83a49a2e99d69,
0xeca8f3318332bb7a,
0xef148d1ea0f4c069,
0x40ab3263eff0206,
]);
use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr};
// B coefficient of BLS12-381 curve, 4.
pub const B_COEFF: Fq = Fq(FqRepr([
@ -507,669 +443,11 @@ pub const NEGATIVE_ONE: Fq = Fq(FqRepr([
0x40ab3263eff0206,
]));
#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
pub struct FqRepr(pub [u64; 6]);
impl ::rand::Rand for FqRepr {
#[inline(always)]
fn rand<R: ::rand::Rng>(rng: &mut R) -> Self {
FqRepr(rng.gen())
}
}
impl ::std::fmt::Display for FqRepr {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
try!(write!(f, "0x"));
for i in self.0.iter().rev() {
try!(write!(f, "{:016x}", *i));
}
Ok(())
}
}
impl AsRef<[u64]> for FqRepr {
#[inline(always)]
fn as_ref(&self) -> &[u64] {
&self.0
}
}
impl AsMut<[u64]> for FqRepr {
#[inline(always)]
fn as_mut(&mut self) -> &mut [u64] {
&mut self.0
}
}
impl From<u64> for FqRepr {
#[inline(always)]
fn from(val: u64) -> FqRepr {
let mut repr = Self::default();
repr.0[0] = val;
repr
}
}
impl Ord for FqRepr {
#[inline(always)]
fn cmp(&self, other: &FqRepr) -> Ordering {
for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) {
if a < b {
return Ordering::Less;
} else if a > b {
return Ordering::Greater;
}
}
Ordering::Equal
}
}
impl PartialOrd for FqRepr {
#[inline(always)]
fn partial_cmp(&self, other: &FqRepr) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PrimeFieldRepr for FqRepr {
#[inline(always)]
fn is_odd(&self) -> bool {
self.0[0] & 1 == 1
}
#[inline(always)]
fn is_even(&self) -> bool {
!self.is_odd()
}
#[inline(always)]
fn is_zero(&self) -> bool {
self.0.iter().all(|&e| e == 0)
}
#[inline(always)]
fn shr(&mut self, mut n: u32) {
if n >= 64 * 6 {
*self = Self::from(0);
return;
}
while n >= 64 {
let mut t = 0;
for i in self.0.iter_mut().rev() {
::std::mem::swap(&mut t, i);
}
n -= 64;
}
if n > 0 {
let mut t = 0;
for i in self.0.iter_mut().rev() {
let t2 = *i << (64 - n);
*i >>= n;
*i |= t;
t = t2;
}
}
}
#[inline(always)]
fn div2(&mut self) {
let mut t = 0;
for i in self.0.iter_mut().rev() {
let t2 = *i << 63;
*i >>= 1;
*i |= t;
t = t2;
}
}
#[inline(always)]
fn mul2(&mut self) {
let mut last = 0;
for i in &mut self.0 {
let tmp = *i >> 63;
*i <<= 1;
*i |= last;
last = tmp;
}
}
#[inline(always)]
fn shl(&mut self, mut n: u32) {
if n >= 64 * 6 {
*self = Self::from(0);
return;
}
while n >= 64 {
let mut t = 0;
for i in &mut self.0 {
::std::mem::swap(&mut t, i);
}
n -= 64;
}
if n > 0 {
let mut t = 0;
for i in &mut self.0 {
let t2 = *i >> (64 - n);
*i <<= n;
*i |= t;
t = t2;
}
}
}
#[inline(always)]
fn num_bits(&self) -> u32 {
let mut ret = (6 as u32) * 64;
for i in self.0.iter().rev() {
let leading = i.leading_zeros();
ret -= leading;
if leading != 64 {
break;
}
}
ret
}
#[inline(always)]
fn add_nocarry(&mut self, other: &FqRepr) {
let mut carry = 0;
for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
*a = ::adc(*a, *b, &mut carry);
}
}
#[inline(always)]
fn sub_noborrow(&mut self, other: &FqRepr) {
let mut borrow = 0;
for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
*a = ::sbb(*a, *b, &mut borrow);
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[derive(PrimeField)]
#[PrimeFieldModulus = "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787"]
#[PrimeFieldGenerator = "2"]
pub struct Fq(FqRepr);
/// `Fq` elements are ordered lexicographically.
impl Ord for Fq {
#[inline(always)]
fn cmp(&self, other: &Fq) -> Ordering {
self.into_repr().cmp(&other.into_repr())
}
}
impl PartialOrd for Fq {
#[inline(always)]
fn partial_cmp(&self, other: &Fq) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl ::std::fmt::Display for Fq {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "Fq({})", self.into_repr())
}
}
impl ::rand::Rand for Fq {
fn rand<R: ::rand::Rng>(rng: &mut R) -> Self {
loop {
let mut tmp = Fq(FqRepr::rand(rng));
// Mask away the unused bits at the beginning.
tmp.0.as_mut()[5] &= 0xffffffffffffffff >> REPR_SHAVE_BITS;
if tmp.is_valid() {
return tmp;
}
}
}
}
impl From<Fq> for FqRepr {
fn from(e: Fq) -> FqRepr {
e.into_repr()
}
}
impl PrimeField for Fq {
type Repr = FqRepr;
fn from_repr(r: FqRepr) -> Result<Fq, PrimeFieldDecodingError> {
let mut r = Fq(r);
if r.is_valid() {
r.mul_assign(&Fq(R2));
Ok(r)
} else {
Err(PrimeFieldDecodingError::NotInField(format!("{}", r.0)))
}
}
fn into_repr(&self) -> FqRepr {
let mut r = *self;
r.mont_reduce(
(self.0).0[0],
(self.0).0[1],
(self.0).0[2],
(self.0).0[3],
(self.0).0[4],
(self.0).0[5],
0,
0,
0,
0,
0,
0,
);
r.0
}
fn char() -> FqRepr {
MODULUS
}
const NUM_BITS: u32 = MODULUS_BITS;
const CAPACITY: u32 = Self::NUM_BITS - 1;
fn multiplicative_generator() -> Self {
Fq(GENERATOR)
}
const S: u32 = S;
fn root_of_unity() -> Self {
Fq(ROOT_OF_UNITY)
}
}
impl Field for Fq {
#[inline]
fn zero() -> Self {
Fq(FqRepr::from(0))
}
#[inline]
fn one() -> Self {
Fq(R)
}
#[inline]
fn is_zero(&self) -> bool {
self.0.is_zero()
}
#[inline]
fn add_assign(&mut self, other: &Fq) {
// This cannot exceed the backing capacity.
self.0.add_nocarry(&other.0);
// However, it may need to be reduced.
self.reduce();
}
#[inline]
fn double(&mut self) {
// This cannot exceed the backing capacity.
self.0.mul2();
// However, it may need to be reduced.
self.reduce();
}
#[inline]
fn sub_assign(&mut self, other: &Fq) {
// If `other` is larger than `self`, we'll need to add the modulus to self first.
if other.0 > self.0 {
self.0.add_nocarry(&MODULUS);
}
self.0.sub_noborrow(&other.0);
}
#[inline]
fn negate(&mut self) {
if !self.is_zero() {
let mut tmp = MODULUS;
tmp.sub_noborrow(&self.0);
self.0 = tmp;
}
}
fn inverse(&self) -> Option<Self> {
if self.is_zero() {
None
} else {
// Guajardo Kumar Paar Pelzl
// Efficient Software-Implementation of Finite Fields with Applications to Cryptography
// Algorithm 16 (BEA for Inversion in Fp)
let one = FqRepr::from(1);
let mut u = self.0;
let mut v = MODULUS;
let mut b = Fq(R2); // Avoids unnecessary reduction step.
let mut c = Self::zero();
while u != one && v != one {
while u.is_even() {
u.div2();
if b.0.is_even() {
b.0.div2();
} else {
b.0.add_nocarry(&MODULUS);
b.0.div2();
}
}
while v.is_even() {
v.div2();
if c.0.is_even() {
c.0.div2();
} else {
c.0.add_nocarry(&MODULUS);
c.0.div2();
}
}
if v < u {
u.sub_noborrow(&v);
b.sub_assign(&c);
} else {
v.sub_noborrow(&u);
c.sub_assign(&b);
}
}
if u == one {
Some(b)
} else {
Some(c)
}
}
}
#[inline(always)]
fn frobenius_map(&mut self, _: usize) {
// This has no effect in a prime field.
}
#[inline]
fn mul_assign(&mut self, other: &Fq) {
let mut carry = 0;
let r0 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry);
let r1 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry);
let r2 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry);
let r3 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry);
let r4 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[4], &mut carry);
let r5 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[5], &mut carry);
let r6 = carry;
let mut carry = 0;
let r1 = ::mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry);
let r2 = ::mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry);
let r3 = ::mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry);
let r4 = ::mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry);
let r5 = ::mac_with_carry(r5, (self.0).0[1], (other.0).0[4], &mut carry);
let r6 = ::mac_with_carry(r6, (self.0).0[1], (other.0).0[5], &mut carry);
let r7 = carry;
let mut carry = 0;
let r2 = ::mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry);
let r3 = ::mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry);
let r4 = ::mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry);
let r5 = ::mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry);
let r6 = ::mac_with_carry(r6, (self.0).0[2], (other.0).0[4], &mut carry);
let r7 = ::mac_with_carry(r7, (self.0).0[2], (other.0).0[5], &mut carry);
let r8 = carry;
let mut carry = 0;
let r3 = ::mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry);
let r4 = ::mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry);
let r5 = ::mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry);
let r6 = ::mac_with_carry(r6, (self.0).0[3], (other.0).0[3], &mut carry);
let r7 = ::mac_with_carry(r7, (self.0).0[3], (other.0).0[4], &mut carry);
let r8 = ::mac_with_carry(r8, (self.0).0[3], (other.0).0[5], &mut carry);
let r9 = carry;
let mut carry = 0;
let r4 = ::mac_with_carry(r4, (self.0).0[4], (other.0).0[0], &mut carry);
let r5 = ::mac_with_carry(r5, (self.0).0[4], (other.0).0[1], &mut carry);
let r6 = ::mac_with_carry(r6, (self.0).0[4], (other.0).0[2], &mut carry);
let r7 = ::mac_with_carry(r7, (self.0).0[4], (other.0).0[3], &mut carry);
let r8 = ::mac_with_carry(r8, (self.0).0[4], (other.0).0[4], &mut carry);
let r9 = ::mac_with_carry(r9, (self.0).0[4], (other.0).0[5], &mut carry);
let r10 = carry;
let mut carry = 0;
let r5 = ::mac_with_carry(r5, (self.0).0[5], (other.0).0[0], &mut carry);
let r6 = ::mac_with_carry(r6, (self.0).0[5], (other.0).0[1], &mut carry);
let r7 = ::mac_with_carry(r7, (self.0).0[5], (other.0).0[2], &mut carry);
let r8 = ::mac_with_carry(r8, (self.0).0[5], (other.0).0[3], &mut carry);
let r9 = ::mac_with_carry(r9, (self.0).0[5], (other.0).0[4], &mut carry);
let r10 = ::mac_with_carry(r10, (self.0).0[5], (other.0).0[5], &mut carry);
let r11 = carry;
self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11);
}
#[inline]
fn square(&mut self) {
let mut carry = 0;
let r1 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry);
let r2 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry);
let r3 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[3], &mut carry);
let r4 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[4], &mut carry);
let r5 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[5], &mut carry);
let r6 = carry;
let mut carry = 0;
let r3 = ::mac_with_carry(r3, (self.0).0[1], (self.0).0[2], &mut carry);
let r4 = ::mac_with_carry(r4, (self.0).0[1], (self.0).0[3], &mut carry);
let r5 = ::mac_with_carry(r5, (self.0).0[1], (self.0).0[4], &mut carry);
let r6 = ::mac_with_carry(r6, (self.0).0[1], (self.0).0[5], &mut carry);
let r7 = carry;
let mut carry = 0;
let r5 = ::mac_with_carry(r5, (self.0).0[2], (self.0).0[3], &mut carry);
let r6 = ::mac_with_carry(r6, (self.0).0[2], (self.0).0[4], &mut carry);
let r7 = ::mac_with_carry(r7, (self.0).0[2], (self.0).0[5], &mut carry);
let r8 = carry;
let mut carry = 0;
let r7 = ::mac_with_carry(r7, (self.0).0[3], (self.0).0[4], &mut carry);
let r8 = ::mac_with_carry(r8, (self.0).0[3], (self.0).0[5], &mut carry);
let r9 = carry;
let mut carry = 0;
let r9 = ::mac_with_carry(r9, (self.0).0[4], (self.0).0[5], &mut carry);
let r10 = carry;
let r11 = r10 >> 63;
let r10 = (r10 << 1) | (r9 >> 63);
let r9 = (r9 << 1) | (r8 >> 63);
let r8 = (r8 << 1) | (r7 >> 63);
let r7 = (r7 << 1) | (r6 >> 63);
let r6 = (r6 << 1) | (r5 >> 63);
let r5 = (r5 << 1) | (r4 >> 63);
let r4 = (r4 << 1) | (r3 >> 63);
let r3 = (r3 << 1) | (r2 >> 63);
let r2 = (r2 << 1) | (r1 >> 63);
let r1 = r1 << 1;
let mut carry = 0;
let r0 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[0], &mut carry);
let r1 = ::adc(r1, 0, &mut carry);
let r2 = ::mac_with_carry(r2, (self.0).0[1], (self.0).0[1], &mut carry);
let r3 = ::adc(r3, 0, &mut carry);
let r4 = ::mac_with_carry(r4, (self.0).0[2], (self.0).0[2], &mut carry);
let r5 = ::adc(r5, 0, &mut carry);
let r6 = ::mac_with_carry(r6, (self.0).0[3], (self.0).0[3], &mut carry);
let r7 = ::adc(r7, 0, &mut carry);
let r8 = ::mac_with_carry(r8, (self.0).0[4], (self.0).0[4], &mut carry);
let r9 = ::adc(r9, 0, &mut carry);
let r10 = ::mac_with_carry(r10, (self.0).0[5], (self.0).0[5], &mut carry);
let r11 = ::adc(r11, 0, &mut carry);
self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11);
}
}
impl Fq {
/// Determines if the element is really in the field. This is only used
/// internally.
#[inline(always)]
fn is_valid(&self) -> bool {
self.0 < MODULUS
}
/// Subtracts the modulus from this element if this element is not in the
/// field. Only used internally.
#[inline(always)]
fn reduce(&mut self) {
if !self.is_valid() {
self.0.sub_noborrow(&MODULUS);
}
}
#[inline(always)]
fn mont_reduce(
&mut self,
r0: u64,
mut r1: u64,
mut r2: u64,
mut r3: u64,
mut r4: u64,
mut r5: u64,
mut r6: u64,
mut r7: u64,
mut r8: u64,
mut r9: u64,
mut r10: u64,
mut r11: u64,
) {
// The Montgomery reduction here is based on Algorithm 14.32 in
// Handbook of Applied Cryptography
// <http://cacr.uwaterloo.ca/hac/about/chap14.pdf>.
let k = r0.wrapping_mul(INV);
let mut carry = 0;
::mac_with_carry(r0, k, MODULUS.0[0], &mut carry);
r1 = ::mac_with_carry(r1, k, MODULUS.0[1], &mut carry);
r2 = ::mac_with_carry(r2, k, MODULUS.0[2], &mut carry);
r3 = ::mac_with_carry(r3, k, MODULUS.0[3], &mut carry);
r4 = ::mac_with_carry(r4, k, MODULUS.0[4], &mut carry);
r5 = ::mac_with_carry(r5, k, MODULUS.0[5], &mut carry);
r6 = ::adc(r6, 0, &mut carry);
let carry2 = carry;
let k = r1.wrapping_mul(INV);
let mut carry = 0;
::mac_with_carry(r1, k, MODULUS.0[0], &mut carry);
r2 = ::mac_with_carry(r2, k, MODULUS.0[1], &mut carry);
r3 = ::mac_with_carry(r3, k, MODULUS.0[2], &mut carry);
r4 = ::mac_with_carry(r4, k, MODULUS.0[3], &mut carry);
r5 = ::mac_with_carry(r5, k, MODULUS.0[4], &mut carry);
r6 = ::mac_with_carry(r6, k, MODULUS.0[5], &mut carry);
r7 = ::adc(r7, carry2, &mut carry);
let carry2 = carry;
let k = r2.wrapping_mul(INV);
let mut carry = 0;
::mac_with_carry(r2, k, MODULUS.0[0], &mut carry);
r3 = ::mac_with_carry(r3, k, MODULUS.0[1], &mut carry);
r4 = ::mac_with_carry(r4, k, MODULUS.0[2], &mut carry);
r5 = ::mac_with_carry(r5, k, MODULUS.0[3], &mut carry);
r6 = ::mac_with_carry(r6, k, MODULUS.0[4], &mut carry);
r7 = ::mac_with_carry(r7, k, MODULUS.0[5], &mut carry);
r8 = ::adc(r8, carry2, &mut carry);
let carry2 = carry;
let k = r3.wrapping_mul(INV);
let mut carry = 0;
::mac_with_carry(r3, k, MODULUS.0[0], &mut carry);
r4 = ::mac_with_carry(r4, k, MODULUS.0[1], &mut carry);
r5 = ::mac_with_carry(r5, k, MODULUS.0[2], &mut carry);
r6 = ::mac_with_carry(r6, k, MODULUS.0[3], &mut carry);
r7 = ::mac_with_carry(r7, k, MODULUS.0[4], &mut carry);
r8 = ::mac_with_carry(r8, k, MODULUS.0[5], &mut carry);
r9 = ::adc(r9, carry2, &mut carry);
let carry2 = carry;
let k = r4.wrapping_mul(INV);
let mut carry = 0;
::mac_with_carry(r4, k, MODULUS.0[0], &mut carry);
r5 = ::mac_with_carry(r5, k, MODULUS.0[1], &mut carry);
r6 = ::mac_with_carry(r6, k, MODULUS.0[2], &mut carry);
r7 = ::mac_with_carry(r7, k, MODULUS.0[3], &mut carry);
r8 = ::mac_with_carry(r8, k, MODULUS.0[4], &mut carry);
r9 = ::mac_with_carry(r9, k, MODULUS.0[5], &mut carry);
r10 = ::adc(r10, carry2, &mut carry);
let carry2 = carry;
let k = r5.wrapping_mul(INV);
let mut carry = 0;
::mac_with_carry(r5, k, MODULUS.0[0], &mut carry);
r6 = ::mac_with_carry(r6, k, MODULUS.0[1], &mut carry);
r7 = ::mac_with_carry(r7, k, MODULUS.0[2], &mut carry);
r8 = ::mac_with_carry(r8, k, MODULUS.0[3], &mut carry);
r9 = ::mac_with_carry(r9, k, MODULUS.0[4], &mut carry);
r10 = ::mac_with_carry(r10, k, MODULUS.0[5], &mut carry);
r11 = ::adc(r11, carry2, &mut carry);
(self.0).0[0] = r6;
(self.0).0[1] = r7;
(self.0).0[2] = r8;
(self.0).0[3] = r9;
(self.0).0[4] = r10;
(self.0).0[5] = r11;
self.reduce();
}
}
impl SqrtField for Fq {
fn legendre(&self) -> ::LegendreSymbol {
use LegendreSymbol::*;
// s = self^((q - 1) // 2)
let s = self.pow([
0xdcff7fffffffd555,
0xf55ffff58a9ffff,
0xb39869507b587b12,
0xb23ba5c279c2895f,
0x258dd3db21a5d66b,
0xd0088f51cbff34d,
]);
if s == Fq::zero() {
Zero
} else if s == Fq::one() {
QuadraticResidue
} else {
QuadraticNonResidue
}
}
fn sqrt(&self) -> Option<Self> {
// Shank's algorithm for q mod 4 = 3
// https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2)
// a1 = self^((q - 3) // 4)
let mut a1 = self.pow([
0xee7fbfffffffeaaa,
0x7aaffffac54ffff,
0xd9cc34a83dac3d89,
0xd91dd2e13ce144af,
0x92c6e9ed90d2eb35,
0x680447a8e5ff9a6,
]);
let mut a0 = a1;
a0.square();
a0.mul_assign(self);
if a0 == NEGATIVE_ONE {
None
} else {
a1.mul_assign(self);
Some(a1)
}
}
}
#[test]
fn test_b_coeff() {
assert_eq!(Fq::from_repr(FqRepr::from(4)).unwrap(), B_COEFF);
@ -1899,6 +1177,8 @@ use rand::{Rand, SeedableRng, XorShiftRng};
#[test]
fn test_fq_repr_ordering() {
use std::cmp::Ordering;
fn assert_equality(a: FqRepr, b: FqRepr) {
assert_eq!(a, b);
assert!(a.cmp(&b) == Ordering::Equal);
@ -2304,14 +1584,16 @@ fn test_fq_is_valid() {
0x17c8be1800b9f059
])).is_valid()
);
assert!(!Fq(FqRepr([
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff
])).is_valid());
assert!(
!Fq(FqRepr([
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff
])).is_valid()
);
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
@ -2745,6 +2027,8 @@ fn test_fq_pow() {
#[test]
fn test_fq_sqrt() {
use ff::SqrtField;
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
assert_eq!(Fq::zero().sqrt().unwrap(), Fq::zero());
@ -2878,6 +2162,8 @@ fn test_fq_num_bits() {
#[test]
fn test_fq_root_of_unity() {
use ff::SqrtField;
assert_eq!(Fq::S, 1);
assert_eq!(
Fq::multiplicative_generator(),
@ -2924,7 +2210,8 @@ fn fq_repr_tests() {
#[test]
fn test_fq_legendre() {
use LegendreSymbol::*;
use ff::LegendreSymbol::*;
use ff::SqrtField;
assert_eq!(QuadraticResidue, Fq::one().legendre());
assert_eq!(Zero, Fq::zero().legendre());

4
pairing/src/bls12_381/fq12.rs

@ -1,8 +1,8 @@
use super::fq::FROBENIUS_COEFF_FQ12_C1;
use super::fq2::Fq2;
use super::fq6::Fq6;
use ff::Field;
use rand::{Rand, Rng};
use Field;
/// An element of Fq12, represented by c0 + c1 * w.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -182,7 +182,7 @@ fn test_fq12_mul_by_014() {
#[test]
fn fq12_field_tests() {
use PrimeField;
use ff::PrimeField;
::tests::field::random_field_tests::<Fq12>();
::tests::field::random_frobenius_tests::<Fq12, _>(super::fq::Fq::char(), 13);

36
pairing/src/bls12_381/fq2.rs

@ -1,6 +1,6 @@
use super::fq::{FROBENIUS_COEFF_FQ2_C1, Fq, NEGATIVE_ONE};
use ff::{Field, SqrtField};
use rand::{Rand, Rng};
use {Field, SqrtField};
use std::cmp::Ordering;
@ -160,7 +160,7 @@ impl Field for Fq2 {
}
impl SqrtField for Fq2 {
fn legendre(&self) -> ::LegendreSymbol {
fn legendre(&self) -> ::ff::LegendreSymbol {
self.norm().legendre()
}
@ -263,16 +263,18 @@ fn test_fq2_basics() {
);
assert!(Fq2::zero().is_zero());
assert!(!Fq2::one().is_zero());
assert!(!Fq2 {
c0: Fq::zero(),
c1: Fq::one(),
}.is_zero());
assert!(
!Fq2 {
c0: Fq::zero(),
c1: Fq::one(),
}.is_zero()
);
}
#[test]
fn test_fq2_squaring() {
use super::fq::FqRepr;
use PrimeField;
use ff::PrimeField;
let mut a = Fq2 {
c0: Fq::one(),
@ -346,7 +348,7 @@ fn test_fq2_squaring() {
#[test]
fn test_fq2_mul() {
use super::fq::FqRepr;
use PrimeField;
use ff::PrimeField;
let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([
@ -410,7 +412,7 @@ fn test_fq2_mul() {
#[test]
fn test_fq2_inverse() {
use super::fq::FqRepr;
use PrimeField;
use ff::PrimeField;
assert!(Fq2::zero().inverse().is_none());
@ -459,7 +461,7 @@ fn test_fq2_inverse() {
#[test]
fn test_fq2_addition() {
use super::fq::FqRepr;
use PrimeField;
use ff::PrimeField;
let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([
@ -523,7 +525,7 @@ fn test_fq2_addition() {
#[test]
fn test_fq2_subtraction() {
use super::fq::FqRepr;
use PrimeField;
use ff::PrimeField;
let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([
@ -587,7 +589,7 @@ fn test_fq2_subtraction() {
#[test]
fn test_fq2_negation() {
use super::fq::FqRepr;
use PrimeField;
use ff::PrimeField;
let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([
@ -634,7 +636,7 @@ fn test_fq2_negation() {
#[test]
fn test_fq2_doubling() {
use super::fq::FqRepr;
use PrimeField;
use ff::PrimeField;
let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([
@ -681,7 +683,7 @@ fn test_fq2_doubling() {
#[test]
fn test_fq2_frobenius_map() {
use super::fq::FqRepr;
use PrimeField;
use ff::PrimeField;
let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([
@ -794,7 +796,7 @@ fn test_fq2_frobenius_map() {
#[test]
fn test_fq2_sqrt() {
use super::fq::FqRepr;
use PrimeField;
use ff::PrimeField;
assert_eq!(
Fq2 {
@ -865,7 +867,7 @@ fn test_fq2_sqrt() {
#[test]
fn test_fq2_legendre() {
use LegendreSymbol::*;
use ff::LegendreSymbol::*;
assert_eq!(Zero, Fq2::zero().legendre());
// i^2 = -1
@ -900,7 +902,7 @@ fn test_fq2_mul_nonresidue() {
#[test]
fn fq2_field_tests() {
use PrimeField;
use ff::PrimeField;
::tests::field::random_field_tests::<Fq2>();
::tests::field::random_sqrt_tests::<Fq2>();

4
pairing/src/bls12_381/fq6.rs

@ -1,7 +1,7 @@
use super::fq::{FROBENIUS_COEFF_FQ6_C1, FROBENIUS_COEFF_FQ6_C2};
use super::fq2::Fq2;
use ff::Field;
use rand::{Rand, Rng};
use Field;
/// An element of Fq6, represented by c0 + c1 * v + c2 * v^(2).
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -367,7 +367,7 @@ fn test_fq6_mul_by_01() {
#[test]
fn fq6_field_tests() {
use PrimeField;
use ff::PrimeField;
::tests::field::random_field_tests::<Fq6>();
::tests::field::random_frobenius_tests::<Fq6, _>(super::fq::Fq::char(), 13);

666
pairing/src/bls12_381/fr.rs

@ -1,647 +1,10 @@
use LegendreSymbol::*;
use {Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField};
// r = 52435875175126190479447740508185965837690552500527637822603658699938581184513
const MODULUS: FrRepr = FrRepr([
0xffffffff00000001,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48,
]);
// The number of bits needed to represent the modulus.
const MODULUS_BITS: u32 = 255;
// The number of bits that must be shaved from the beginning of
// the representation when randomly sampling.
const REPR_SHAVE_BITS: u32 = 1;
// R = 2**256 % r
const R: FrRepr = FrRepr([
0x1fffffffe,
0x5884b7fa00034802,
0x998c4fefecbc4ff5,
0x1824b159acc5056f,
]);
// R2 = R^2 % r
const R2: FrRepr = FrRepr([
0xc999e990f3f29c6d,
0x2b6cedcb87925c23,
0x5d314967254398f,
0x748d9d99f59ff11,
]);
// INV = -(r^{-1} mod 2^64) mod 2^64
const INV: u64 = 0xfffffffeffffffff;
// GENERATOR = 7 (multiplicative generator of r-1 order, that is also quadratic nonresidue)
const GENERATOR: FrRepr = FrRepr([
0xefffffff1,
0x17e363d300189c0f,
0xff9c57876f8457b0,
0x351332208fc5a8c4,
]);
// 2^s * t = MODULUS - 1 with t odd
const S: u32 = 32;
// 2^s root of unity computed by GENERATOR^t
const ROOT_OF_UNITY: FrRepr = FrRepr([
0xb9b58d8c5f0e466a,
0x5b1b4c801819d7ec,
0xaf53ae352a31e64,
0x5bf3adda19e9b27b,
]);
#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
pub struct FrRepr(pub [u64; 4]);
impl ::rand::Rand for FrRepr {
#[inline(always)]
fn rand<R: ::rand::Rng>(rng: &mut R) -> Self {
FrRepr(rng.gen())
}
}
impl ::std::fmt::Display for FrRepr {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
try!(write!(f, "0x"));
for i in self.0.iter().rev() {
try!(write!(f, "{:016x}", *i));
}
Ok(())
}
}
impl AsRef<[u64]> for FrRepr {
#[inline(always)]
fn as_ref(&self) -> &[u64] {
&self.0
}
}
impl AsMut<[u64]> for FrRepr {
#[inline(always)]
fn as_mut(&mut self) -> &mut [u64] {
&mut self.0
}
}
impl From<u64> for FrRepr {
#[inline(always)]
fn from(val: u64) -> FrRepr {
let mut repr = Self::default();
repr.0[0] = val;
repr
}
}
impl Ord for FrRepr {
#[inline(always)]
fn cmp(&self, other: &FrRepr) -> ::std::cmp::Ordering {
for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) {
if a < b {
return ::std::cmp::Ordering::Less;
} else if a > b {
return ::std::cmp::Ordering::Greater;
}
}
::std::cmp::Ordering::Equal
}
}
impl PartialOrd for FrRepr {
#[inline(always)]
fn partial_cmp(&self, other: &FrRepr) -> Option<::std::cmp::Ordering> {
Some(self.cmp(other))
}
}
use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr};
impl PrimeFieldRepr for FrRepr {
#[inline(always)]
fn is_odd(&self) -> bool {
self.0[0] & 1 == 1
}
#[inline(always)]
fn is_even(&self) -> bool {
!self.is_odd()
}
#[inline(always)]
fn is_zero(&self) -> bool {
self.0.iter().all(|&e| e == 0)
}
#[inline(always)]
fn shr(&mut self, mut n: u32) {
if n >= 64 * 4 {
*self = Self::from(0);
return;
}
while n >= 64 {
let mut t = 0;
for i in self.0.iter_mut().rev() {
::std::mem::swap(&mut t, i);
}
n -= 64;
}
if n > 0 {
let mut t = 0;
for i in self.0.iter_mut().rev() {
let t2 = *i << (64 - n);
*i >>= n;
*i |= t;
t = t2;
}
}
}
#[inline(always)]
fn div2(&mut self) {
let mut t = 0;
for i in self.0.iter_mut().rev() {
let t2 = *i << 63;
*i >>= 1;
*i |= t;
t = t2;
}
}
#[inline(always)]
fn mul2(&mut self) {
let mut last = 0;
for i in &mut self.0 {
let tmp = *i >> 63;
*i <<= 1;
*i |= last;
last = tmp;
}
}
#[inline(always)]
fn shl(&mut self, mut n: u32) {
if n >= 64 * 4 {
*self = Self::from(0);
return;
}
while n >= 64 {
let mut t = 0;
for i in &mut self.0 {
::std::mem::swap(&mut t, i);
}
n -= 64;
}
if n > 0 {
let mut t = 0;
for i in &mut self.0 {
let t2 = *i >> (64 - n);
*i <<= n;
*i |= t;
t = t2;
}
}
}
#[inline(always)]
fn num_bits(&self) -> u32 {
let mut ret = (4 as u32) * 64;
for i in self.0.iter().rev() {
let leading = i.leading_zeros();
ret -= leading;
if leading != 64 {
break;
}
}
ret
}
#[inline(always)]
fn add_nocarry(&mut self, other: &FrRepr) {
let mut carry = 0;
for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
*a = ::adc(*a, *b, &mut carry);
}
}
#[inline(always)]
fn sub_noborrow(&mut self, other: &FrRepr) {
let mut borrow = 0;
for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
*a = ::sbb(*a, *b, &mut borrow);
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[derive(PrimeField)]
#[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"]
#[PrimeFieldGenerator = "7"]
pub struct Fr(FrRepr);
impl ::std::fmt::Display for Fr {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "Fr({})", self.into_repr())
}
}
impl ::rand::Rand for Fr {
fn rand<R: ::rand::Rng>(rng: &mut R) -> Self {
loop {
let mut tmp = Fr(FrRepr::rand(rng));
// Mask away the unused bits at the beginning.
tmp.0.as_mut()[3] &= 0xffffffffffffffff >> REPR_SHAVE_BITS;
if tmp.is_valid() {
return tmp;
}
}
}
}
impl From<Fr> for FrRepr {
fn from(e: Fr) -> FrRepr {
e.into_repr()
}
}
impl PrimeField for Fr {
type Repr = FrRepr;
fn from_repr(r: FrRepr) -> Result<Fr, PrimeFieldDecodingError> {
let mut r = Fr(r);
if r.is_valid() {
r.mul_assign(&Fr(R2));
Ok(r)
} else {
Err(PrimeFieldDecodingError::NotInField(format!("{}", r.0)))
}
}
fn into_repr(&self) -> FrRepr {
let mut r = *self;
r.mont_reduce(
(self.0).0[0],
(self.0).0[1],
(self.0).0[2],
(self.0).0[3],
0,
0,
0,
0,
);
r.0
}
fn char() -> FrRepr {
MODULUS
}
const NUM_BITS: u32 = MODULUS_BITS;
const CAPACITY: u32 = Self::NUM_BITS - 1;
fn multiplicative_generator() -> Self {
Fr(GENERATOR)
}
const S: u32 = S;
fn root_of_unity() -> Self {
Fr(ROOT_OF_UNITY)
}
}
impl Field for Fr {
#[inline]
fn zero() -> Self {
Fr(FrRepr::from(0))
}
#[inline]
fn one() -> Self {
Fr(R)
}
#[inline]
fn is_zero(&self) -> bool {
self.0.is_zero()
}
#[inline]
fn add_assign(&mut self, other: &Fr) {
// This cannot exceed the backing capacity.
self.0.add_nocarry(&other.0);
// However, it may need to be reduced.
self.reduce();
}
#[inline]
fn double(&mut self) {
// This cannot exceed the backing capacity.
self.0.mul2();
// However, it may need to be reduced.
self.reduce();
}
#[inline]
fn sub_assign(&mut self, other: &Fr) {
// If `other` is larger than `self`, we'll need to add the modulus to self first.
if other.0 > self.0 {
self.0.add_nocarry(&MODULUS);
}
self.0.sub_noborrow(&other.0);
}
#[inline]
fn negate(&mut self) {
if !self.is_zero() {
let mut tmp = MODULUS;
tmp.sub_noborrow(&self.0);
self.0 = tmp;
}
}
fn inverse(&self) -> Option<Self> {
if self.is_zero() {
None
} else {
// Guajardo Kumar Paar Pelzl
// Efficient Software-Implementation of Finite Fields with Applications to Cryptography
// Algorithm 16 (BEA for Inversion in Fp)
let one = FrRepr::from(1);
let mut u = self.0;
let mut v = MODULUS;
let mut b = Fr(R2); // Avoids unnecessary reduction step.
let mut c = Self::zero();
while u != one && v != one {
while u.is_even() {
u.div2();
if b.0.is_even() {
b.0.div2();
} else {
b.0.add_nocarry(&MODULUS);
b.0.div2();
}
}
while v.is_even() {
v.div2();
if c.0.is_even() {
c.0.div2();
} else {
c.0.add_nocarry(&MODULUS);
c.0.div2();
}
}
if v < u {
u.sub_noborrow(&v);
b.sub_assign(&c);
} else {
v.sub_noborrow(&u);
c.sub_assign(&b);
}
}
if u == one {
Some(b)
} else {
Some(c)
}
}
}
#[inline(always)]
fn frobenius_map(&mut self, _: usize) {
// This has no effect in a prime field.
}
#[inline]
fn mul_assign(&mut self, other: &Fr) {
let mut carry = 0;
let r0 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry);
let r1 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry);
let r2 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry);
let r3 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry);
let r4 = carry;
let mut carry = 0;
let r1 = ::mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry);
let r2 = ::mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry);
let r3 = ::mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry);
let r4 = ::mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry);
let r5 = carry;
let mut carry = 0;
let r2 = ::mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry);
let r3 = ::mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry);
let r4 = ::mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry);
let r5 = ::mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry);
let r6 = carry;
let mut carry = 0;
let r3 = ::mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry);
let r4 = ::mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry);
let r5 = ::mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry);
let r6 = ::mac_with_carry(r6, (self.0).0[3], (other.0).0[3], &mut carry);
let r7 = carry;
self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7);
}
#[inline]
fn square(&mut self) {
let mut carry = 0;
let r1 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry);
let r2 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry);
let r3 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[3], &mut carry);
let r4 = carry;
let mut carry = 0;
let r3 = ::mac_with_carry(r3, (self.0).0[1], (self.0).0[2], &mut carry);
let r4 = ::mac_with_carry(r4, (self.0).0[1], (self.0).0[3], &mut carry);
let r5 = carry;
let mut carry = 0;
let r5 = ::mac_with_carry(r5, (self.0).0[2], (self.0).0[3], &mut carry);
let r6 = carry;
let r7 = r6 >> 63;
let r6 = (r6 << 1) | (r5 >> 63);
let r5 = (r5 << 1) | (r4 >> 63);
let r4 = (r4 << 1) | (r3 >> 63);
let r3 = (r3 << 1) | (r2 >> 63);
let r2 = (r2 << 1) | (r1 >> 63);
let r1 = r1 << 1;
let mut carry = 0;
let r0 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[0], &mut carry);
let r1 = ::adc(r1, 0, &mut carry);
let r2 = ::mac_with_carry(r2, (self.0).0[1], (self.0).0[1], &mut carry);
let r3 = ::adc(r3, 0, &mut carry);
let r4 = ::mac_with_carry(r4, (self.0).0[2], (self.0).0[2], &mut carry);
let r5 = ::adc(r5, 0, &mut carry);
let r6 = ::mac_with_carry(r6, (self.0).0[3], (self.0).0[3], &mut carry);
let r7 = ::adc(r7, 0, &mut carry);
self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7);
}
}
impl Fr {
/// Determines if the element is really in the field. This is only used
/// internally.
#[inline(always)]
fn is_valid(&self) -> bool {
self.0 < MODULUS
}
/// Subtracts the modulus from this element if this element is not in the
/// field. Only used internally.
#[inline(always)]
fn reduce(&mut self) {
if !self.is_valid() {
self.0.sub_noborrow(&MODULUS);
}
}
#[inline(always)]
fn mont_reduce(
&mut self,
r0: u64,
mut r1: u64,
mut r2: u64,
mut r3: u64,
mut r4: u64,
mut r5: u64,
mut r6: u64,
mut r7: u64,
) {
// The Montgomery reduction here is based on Algorithm 14.32 in
// Handbook of Applied Cryptography
// <http://cacr.uwaterloo.ca/hac/about/chap14.pdf>.
let k = r0.wrapping_mul(INV);
let mut carry = 0;
::mac_with_carry(r0, k, MODULUS.0[0], &mut carry);
r1 = ::mac_with_carry(r1, k, MODULUS.0[1], &mut carry);
r2 = ::mac_with_carry(r2, k, MODULUS.0[2], &mut carry);
r3 = ::mac_with_carry(r3, k, MODULUS.0[3], &mut carry);
r4 = ::adc(r4, 0, &mut carry);
let carry2 = carry;
let k = r1.wrapping_mul(INV);
let mut carry = 0;
::mac_with_carry(r1, k, MODULUS.0[0], &mut carry);
r2 = ::mac_with_carry(r2, k, MODULUS.0[1], &mut carry);
r3 = ::mac_with_carry(r3, k, MODULUS.0[2], &mut carry);
r4 = ::mac_with_carry(r4, k, MODULUS.0[3], &mut carry);
r5 = ::adc(r5, carry2, &mut carry);
let carry2 = carry;
let k = r2.wrapping_mul(INV);
let mut carry = 0;
::mac_with_carry(r2, k, MODULUS.0[0], &mut carry);
r3 = ::mac_with_carry(r3, k, MODULUS.0[1], &mut carry);
r4 = ::mac_with_carry(r4, k, MODULUS.0[2], &mut carry);
r5 = ::mac_with_carry(r5, k, MODULUS.0[3], &mut carry);
r6 = ::adc(r6, carry2, &mut carry);
let carry2 = carry;
let k = r3.wrapping_mul(INV);
let mut carry = 0;
::mac_with_carry(r3, k, MODULUS.0[0], &mut carry);
r4 = ::mac_with_carry(r4, k, MODULUS.0[1], &mut carry);
r5 = ::mac_with_carry(r5, k, MODULUS.0[2], &mut carry);
r6 = ::mac_with_carry(r6, k, MODULUS.0[3], &mut carry);
r7 = ::adc(r7, carry2, &mut carry);
(self.0).0[0] = r4;
(self.0).0[1] = r5;
(self.0).0[2] = r6;
(self.0).0[3] = r7;
self.reduce();
}
}
impl SqrtField for Fr {
fn legendre(&self) -> ::LegendreSymbol {
// s = self^((r - 1) // 2)
let s = self.pow([
0x7fffffff80000000,
0xa9ded2017fff2dff,
0x199cec0404d0ec02,
0x39f6d3a994cebea4,
]);
if s == Self::zero() {
Zero
} else if s == Self::one() {
QuadraticResidue
} else {
QuadraticNonResidue
}
}
fn sqrt(&self) -> Option<Self> {
// Tonelli-Shank's algorithm for q mod 16 = 1
// https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5)
match self.legendre() {
Zero => Some(*self),
QuadraticNonResidue => None,
QuadraticResidue => {
let mut c = Fr(ROOT_OF_UNITY);
// r = self^((t + 1) // 2)
let mut r = self.pow([
0x7fff2dff80000000,
0x4d0ec02a9ded201,
0x94cebea4199cec04,
0x39f6d3a9,
]);
// t = self^t
let mut t = self.pow([
0xfffe5bfeffffffff,
0x9a1d80553bda402,
0x299d7d483339d808,
0x73eda753,
]);
let mut m = S;
while t != Self::one() {
let mut i = 1;
{
let mut t2i = t;
t2i.square();
loop {
if t2i == Self::one() {
break;
}
t2i.square();
i += 1;
}
}
for _ in 0..(m - i - 1) {
c.square();
}
r.mul_assign(&c);
c.square();
t.mul_assign(&c);
m = i;
}
Some(r)
}
}
}
}
#[cfg(test)]
use rand::{Rand, SeedableRng, XorShiftRng};
@ -909,6 +272,9 @@ fn test_fr_repr_sub_noborrow() {
#[test]
fn test_fr_legendre() {
use ff::LegendreSymbol::*;
use ff::SqrtField;
assert_eq!(QuadraticResidue, Fr::one().legendre());
assert_eq!(Zero, Fr::zero().legendre());
@ -1022,12 +388,14 @@ fn test_fr_is_valid() {
0x73eda753299d7d48
])).is_valid()
);
assert!(!Fr(FrRepr([
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff
])).is_valid());
assert!(
!Fr(FrRepr([
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff
])).is_valid()
);
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
@ -1417,6 +785,8 @@ fn test_fr_pow() {
#[test]
fn test_fr_sqrt() {
use ff::SqrtField;
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
assert_eq!(Fr::zero().sqrt().unwrap(), Fr::zero());
@ -1582,6 +952,8 @@ fn test_fr_num_bits() {
#[test]
fn test_fr_root_of_unity() {
use ff::SqrtField;
assert_eq!(Fr::S, 32);
assert_eq!(
Fr::multiplicative_generator(),

14
pairing/src/bls12_381/mod.rs

@ -18,7 +18,10 @@ pub use self::fq2::Fq2;
pub use self::fq6::Fq6;
pub use self::fr::{Fr, FrRepr};
use super::{BitIterator, CurveAffine, Engine, Field};
use super::{Engine, PairingCurveAffine};
use ff::{BitIterator, Field, ScalarEngine};
use group::CurveAffine;
// The BLS parameter x for BLS12-381 is -0xd201000000010000
const BLS_X: u64 = 0xd201000000010000;
@ -27,8 +30,11 @@ const BLS_X_IS_NEGATIVE: bool = true;
#[derive(Clone, Debug)]
pub struct Bls12;
impl Engine for Bls12 {
impl ScalarEngine for Bls12 {
type Fr = Fr;
}
impl Engine for Bls12 {
type G1 = G1;
type G1Affine = G1Affine;
type G2 = G2;
@ -41,8 +47,8 @@ impl Engine for Bls12 {
where
I: IntoIterator<
Item = &'a (
&'a <Self::G1Affine as CurveAffine>::Prepared,
&'a <Self::G2Affine as CurveAffine>::Prepared,
&'a <Self::G1Affine as PairingCurveAffine>::Prepared,
&'a <Self::G2Affine as PairingCurveAffine>::Prepared,
),
>,
{

3
pairing/src/bls12_381/tests/mod.rs

@ -1,3 +1,6 @@
use ff::PrimeFieldRepr;
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
use super::*;
use *;

685
pairing/src/lib.rs

@ -1,19 +1,19 @@
// `clippy` is a code linting tool for improving code quality by catching
// common mistakes or strange code patterns. If the `clippy` feature is
// provided, it is enabled and all compiler warnings are prohibited.
#![cfg_attr(feature = "clippy", deny(warnings))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", allow(inline_always))]
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "clippy", allow(unreadable_literal))]
#![cfg_attr(feature = "clippy", allow(many_single_char_names))]
#![cfg_attr(feature = "clippy", allow(new_without_default_derive))]
#![cfg_attr(feature = "clippy", allow(write_literal))]
// common mistakes or strange code patterns. If the `cargo-clippy` feature
// is provided, all compiler warnings are prohibited.
#![cfg_attr(feature = "cargo-clippy", deny(warnings))]
#![cfg_attr(feature = "cargo-clippy", allow(inline_always))]
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))]
#![cfg_attr(feature = "cargo-clippy", allow(many_single_char_names))]
#![cfg_attr(feature = "cargo-clippy", allow(new_without_default_derive))]
#![cfg_attr(feature = "cargo-clippy", allow(write_literal))]
// Force public structures to implement Debug
#![deny(missing_debug_implementations)]
extern crate byteorder;
extern crate ff;
extern crate group;
extern crate rand;
#[cfg(test)]
@ -21,20 +21,13 @@ pub mod tests;
pub mod bls12_381;
mod wnaf;
pub use self::wnaf::Wnaf;
use std::error::Error;
use std::fmt;
use std::io::{self, Read, Write};
use ff::{Field, PrimeField, ScalarEngine, SqrtField};
use group::{CurveAffine, CurveProjective};
/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
/// with well-defined relationships. In particular, the G1/G2 curve groups are
/// of prime order `r`, and are equipped with a bilinear pairing function.
pub trait Engine: Sized + 'static + Clone {
/// This is the scalar field of the G1/G2 groups.
type Fr: PrimeField + SqrtField;
pub trait Engine: ScalarEngine {
/// The projective representation of an element in G1.
type G1: CurveProjective<
Engine = Self,
@ -45,7 +38,7 @@ pub trait Engine: Sized + 'static + Clone {
+ From<Self::G1Affine>;
/// The affine representation of an element in G1.
type G1Affine: CurveAffine<
type G1Affine: PairingCurveAffine<
Engine = Self,
Base = Self::Fq,
Scalar = Self::Fr,
@ -65,7 +58,7 @@ pub trait Engine: Sized + 'static + Clone {
+ From<Self::G2Affine>;
/// The affine representation of an element in G2.
type G2Affine: CurveAffine<
type G2Affine: PairingCurveAffine<
Engine = Self,
Base = Self::Fqe,
Scalar = Self::Fr,
@ -89,8 +82,8 @@ pub trait Engine: Sized + 'static + Clone {
where
I: IntoIterator<
Item = &'a (
&'a <Self::G1Affine as CurveAffine>::Prepared,
&'a <Self::G2Affine as CurveAffine>::Prepared,
&'a <Self::G1Affine as PairingCurveAffine>::Prepared,
&'a <Self::G2Affine as PairingCurveAffine>::Prepared,
),
>;
@ -109,650 +102,16 @@ pub trait Engine: Sized + 'static + Clone {
}
}
/// Projective representation of an elliptic curve point guaranteed to be
/// in the correct prime order subgroup.
pub trait CurveProjective:
PartialEq
+ Eq
+ Sized
+ Copy
+ Clone
+ Send
+ Sync
+ fmt::Debug
+ fmt::Display
+ rand::Rand
+ 'static
{
type Engine: Engine<Fr = Self::Scalar>;
type Scalar: PrimeField + SqrtField;
type Base: SqrtField;
type Affine: CurveAffine<Projective = Self, Scalar = Self::Scalar>;
/// Returns the additive identity.
fn zero() -> Self;
/// Returns a fixed generator of unknown exponent.
fn one() -> Self;
/// Determines if this point is the point at infinity.
fn is_zero(&self) -> bool;
/// Normalizes a slice of projective elements so that
/// conversion to affine is cheap.
fn batch_normalization(v: &mut [Self]);
/// Checks if the point is already "normalized" so that
/// cheap affine conversion is possible.
fn is_normalized(&self) -> bool;
/// Doubles this element.
fn double(&mut self);
/// Adds another element to this element.
fn add_assign(&mut self, other: &Self);
/// Subtracts another element from this element.
fn sub_assign(&mut self, other: &Self) {
let mut tmp = *other;
tmp.negate();
self.add_assign(&tmp);
}
/// Adds an affine element to this element.
fn add_assign_mixed(&mut self, other: &Self::Affine);
/// Negates this element.
fn negate(&mut self);
/// Performs scalar multiplication of this element.
fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S);
/// Converts this element into its affine representation.
fn into_affine(&self) -> Self::Affine;
/// Recommends a wNAF window table size given a scalar. Always returns a number
/// between 2 and 22, inclusive.
fn recommended_wnaf_for_scalar(scalar: <Self::Scalar as PrimeField>::Repr) -> usize;
/// Recommends a wNAF window size given the number of scalars you intend to multiply
/// a base by. Always returns a number between 2 and 22, inclusive.
fn recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize;
}
/// Affine representation of an elliptic curve point guaranteed to be
/// in the correct prime order subgroup.
pub trait CurveAffine:
Copy + Clone + Sized + Send + Sync + fmt::Debug + fmt::Display + PartialEq + Eq + 'static
{
type Engine: Engine<Fr = Self::Scalar>;
type Scalar: PrimeField + SqrtField;
type Base: SqrtField;
type Projective: CurveProjective<Affine = Self, Scalar = Self::Scalar>;
/// Affine representation of an elliptic curve point that can be used
/// to perform pairings.
pub trait PairingCurveAffine: CurveAffine {
type Prepared: Clone + Send + Sync + 'static;
type Uncompressed: EncodedPoint<Affine = Self>;
type Compressed: EncodedPoint<Affine = Self>;
type Pair: CurveAffine<Pair = Self>;
type Pair: PairingCurveAffine<Pair = Self>;
type PairingResult: Field;
/// Returns the additive identity.
fn zero() -> Self;
/// Returns a fixed generator of unknown exponent.
fn one() -> Self;
/// Determines if this point represents the point at infinity; the
/// additive identity.
fn is_zero(&self) -> bool;
/// Negates this element.
fn negate(&mut self);
/// Performs scalar multiplication of this element with mixed addition.
fn mul<S: Into<<Self::Scalar as PrimeField>::Repr>>(&self, other: S) -> Self::Projective;
/// Prepares this element for pairing purposes.
fn prepare(&self) -> Self::Prepared;
/// Perform a pairing
fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult;
/// Converts this element into its affine representation.
fn into_projective(&self) -> Self::Projective;
/// Converts this element into its compressed encoding, so long as it's not
/// the point at infinity.
fn into_compressed(&self) -> Self::Compressed {
<Self::Compressed as EncodedPoint>::from_affine(*self)
}
/// Converts this element into its uncompressed encoding, so long as it's not
/// the point at infinity.
fn into_uncompressed(&self) -> Self::Uncompressed {
<Self::Uncompressed as EncodedPoint>::from_affine(*self)
}
}
/// An encoded elliptic curve point, which should essentially wrap a `[u8; N]`.
pub trait EncodedPoint:
Sized + Send + Sync + AsRef<[u8]> + AsMut<[u8]> + Clone + Copy + 'static
{
type Affine: CurveAffine;
/// Creates an empty representation.
fn empty() -> Self;
/// Returns the number of bytes consumed by this representation.
fn size() -> usize;
/// Converts an `EncodedPoint` into a `CurveAffine` element,
/// if the encoding represents a valid element.
fn into_affine(&self) -> Result<Self::Affine, GroupDecodingError>;
/// Converts an `EncodedPoint` into a `CurveAffine` element,
/// without guaranteeing that the encoding represents a valid
/// element. This is useful when the caller knows the encoding is
/// valid already.
///
/// If the encoding is invalid, this can break API invariants,
/// so caution is strongly encouraged.
fn into_affine_unchecked(&self) -> Result<Self::Affine, GroupDecodingError>;
/// Creates an `EncodedPoint` from an affine point, as long as the
/// point is not the point at infinity.
fn from_affine(affine: Self::Affine) -> Self;
}
/// This trait represents an element of a field.
pub trait Field:
Sized + Eq + Copy + Clone + Send + Sync + fmt::Debug + fmt::Display + 'static + rand::Rand
{
/// Returns the zero element of the field, the additive identity.
fn zero() -> Self;
/// Returns the one element of the field, the multiplicative identity.
fn one() -> Self;
/// Returns true iff this element is zero.
fn is_zero(&self) -> bool;
/// Squares this element.
fn square(&mut self);
/// Doubles this element.
fn double(&mut self);
/// Negates this element.
fn negate(&mut self);
/// Adds another element to this element.
fn add_assign(&mut self, other: &Self);
/// Subtracts another element from this element.
fn sub_assign(&mut self, other: &Self);
/// Multiplies another element by this element.
fn mul_assign(&mut self, other: &Self);
/// Computes the multiplicative inverse of this element, if nonzero.
fn inverse(&self) -> Option<Self>;
/// Exponentiates this element by a power of the base prime modulus via
/// the Frobenius automorphism.
fn frobenius_map(&mut self, power: usize);
/// Exponentiates this element by a number represented with `u64` limbs,
/// least significant digit first.
fn pow<S: AsRef<[u64]>>(&self, exp: S) -> Self {
let mut res = Self::one();
let mut found_one = false;
for i in BitIterator::new(exp) {
if found_one {
res.square();
} else {
found_one = i;
}
if i {
res.mul_assign(self);
}
}
res
}
}
/// This trait represents an element of a field that has a square root operation described for it.
pub trait SqrtField: Field {
/// Returns the Legendre symbol of the field element.
fn legendre(&self) -> LegendreSymbol;
/// Returns the square root of the field element, if it is
/// quadratic residue.
fn sqrt(&self) -> Option<Self>;
}
/// This trait represents a wrapper around a biginteger which can encode any element of a particular
/// prime field. It is a smart wrapper around a sequence of `u64` limbs, least-significant digit
/// first.
pub trait PrimeFieldRepr:
Sized
+ Copy
+ Clone
+ Eq
+ Ord
+ Send
+ Sync
+ Default
+ fmt::Debug
+ fmt::Display
+ 'static
+ rand::Rand
+ AsRef<[u64]>
+ AsMut<[u64]>
+ From<u64>
{
/// Subtract another represetation from this one.
fn sub_noborrow(&mut self, other: &Self);
/// Add another representation to this one.
fn add_nocarry(&mut self, other: &Self);
/// Compute the number of bits needed to encode this number. Always a
/// multiple of 64.
fn num_bits(&self) -> u32;
/// Returns true iff this number is zero.
fn is_zero(&self) -> bool;
/// Returns true iff this number is odd.
fn is_odd(&self) -> bool;
/// Returns true iff this number is even.
fn is_even(&self) -> bool;
/// Performs a rightwise bitshift of this number, effectively dividing
/// it by 2.
fn div2(&mut self);
/// Performs a rightwise bitshift of this number by some amount.
fn shr(&mut self, amt: u32);
/// Performs a leftwise bitshift of this number, effectively multiplying
/// it by 2. Overflow is ignored.
fn mul2(&mut self);
/// Performs a leftwise bitshift of this number by some amount.
fn shl(&mut self, amt: u32);
/// Writes this `PrimeFieldRepr` as a big endian integer.
fn write_be<W: Write>(&self, mut writer: W) -> io::Result<()> {
use byteorder::{BigEndian, WriteBytesExt};
for digit in self.as_ref().iter().rev() {
writer.write_u64::<BigEndian>(*digit)?;
}
Ok(())
}
/// Reads a big endian integer into this representation.
fn read_be<R: Read>(&mut self, mut reader: R) -> io::Result<()> {
use byteorder::{BigEndian, ReadBytesExt};
for digit in self.as_mut().iter_mut().rev() {
*digit = reader.read_u64::<BigEndian>()?;
}
Ok(())
}
/// Writes this `PrimeFieldRepr` as a little endian integer.
fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> {
use byteorder::{LittleEndian, WriteBytesExt};
for digit in self.as_ref().iter() {
writer.write_u64::<LittleEndian>(*digit)?;
}
Ok(())
}
/// Reads a little endian integer into this representation.
fn read_le<R: Read>(&mut self, mut reader: R) -> io::Result<()> {
use byteorder::{LittleEndian, ReadBytesExt};
for digit in self.as_mut().iter_mut() {
*digit = reader.read_u64::<LittleEndian>()?;
}
Ok(())
}
}
#[derive(Debug, PartialEq)]
pub enum LegendreSymbol {
Zero = 0,
QuadraticResidue = 1,
QuadraticNonResidue = -1,
}
/// An error that may occur when trying to interpret a `PrimeFieldRepr` as a
/// `PrimeField` element.
#[derive(Debug)]
pub enum PrimeFieldDecodingError {
/// The encoded value is not in the field
NotInField(String),
}
impl Error for PrimeFieldDecodingError {
fn description(&self) -> &str {
match *self {
PrimeFieldDecodingError::NotInField(..) => "not an element of the field",
}
}
}
impl fmt::Display for PrimeFieldDecodingError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
PrimeFieldDecodingError::NotInField(ref repr) => {
write!(f, "{} is not an element of the field", repr)
}
}
}
}
/// An error that may occur when trying to decode an `EncodedPoint`.
#[derive(Debug)]
pub enum GroupDecodingError {
/// The coordinate(s) do not lie on the curve.
NotOnCurve,
/// The element is not part of the r-order subgroup.
NotInSubgroup,
/// One of the coordinates could not be decoded
CoordinateDecodingError(&'static str, PrimeFieldDecodingError),
/// The compression mode of the encoded element was not as expected
UnexpectedCompressionMode,
/// The encoding contained bits that should not have been set
UnexpectedInformation,
}
impl Error for GroupDecodingError {
fn description(&self) -> &str {
match *self {
GroupDecodingError::NotOnCurve => "coordinate(s) do not lie on the curve",
GroupDecodingError::NotInSubgroup => "the element is not part of an r-order subgroup",
GroupDecodingError::CoordinateDecodingError(..) => "coordinate(s) could not be decoded",
GroupDecodingError::UnexpectedCompressionMode => {
"encoding has unexpected compression mode"
}
GroupDecodingError::UnexpectedInformation => "encoding has unexpected information",
}
}
}
impl fmt::Display for GroupDecodingError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
GroupDecodingError::CoordinateDecodingError(description, ref err) => {
write!(f, "{} decoding error: {}", description, err)
}
_ => write!(f, "{}", self.description()),
}
}
}
/// This represents an element of a prime field.
pub trait PrimeField: Field {
/// The prime field can be converted back and forth into this biginteger
/// representation.
type Repr: PrimeFieldRepr + From<Self>;
/// Interpret a string of numbers as a (congruent) prime field element.
/// Does not accept unnecessary leading zeroes or a blank string.
fn from_str(s: &str) -> Option<Self> {
if s.is_empty() {
return None;
}
if s == "0" {
return Some(Self::zero());
}
let mut res = Self::zero();
let ten = Self::from_repr(Self::Repr::from(10)).unwrap();
let mut first_digit = true;
for c in s.chars() {
match c.to_digit(10) {
Some(c) => {
if first_digit {
if c == 0 {
return None;
}
first_digit = false;
}
res.mul_assign(&ten);
res.add_assign(&Self::from_repr(Self::Repr::from(u64::from(c))).unwrap());
}
None => {
return None;
}
}
}
Some(res)
}
/// Convert this prime field element into a biginteger representation.
fn from_repr(Self::Repr) -> Result<Self, PrimeFieldDecodingError>;
/// Convert a biginteger representation into a prime field element, if
/// the number is an element of the field.
fn into_repr(&self) -> Self::Repr;
/// Returns the field characteristic; the modulus.
fn char() -> Self::Repr;
/// How many bits are needed to represent an element of this field.
const NUM_BITS: u32;
/// How many bits of information can be reliably stored in the field element.
const CAPACITY: u32;
/// Returns the multiplicative generator of `char()` - 1 order. This element
/// must also be quadratic nonresidue.
fn multiplicative_generator() -> Self;
/// 2^s * t = `char()` - 1 with t odd.
const S: u32;
/// Returns the 2^s root of unity computed by exponentiating the `multiplicative_generator()`
/// by t.
fn root_of_unity() -> Self;
}
#[derive(Debug)]
pub struct BitIterator<E> {
t: E,
n: usize,
}
impl<E: AsRef<[u64]>> BitIterator<E> {
pub fn new(t: E) -> Self {
let n = t.as_ref().len() * 64;
BitIterator { t, n }
}
}
impl<E: AsRef<[u64]>> Iterator for BitIterator<E> {
type Item = bool;
fn next(&mut self) -> Option<bool> {
if self.n == 0 {
None
} else {
self.n -= 1;
let part = self.n / 64;
let bit = self.n - (64 * part);
Some(self.t.as_ref()[part] & (1 << bit) > 0)
}
}
}
#[test]
fn test_bit_iterator() {
let mut a = BitIterator::new([0xa953d79b83f6ab59, 0x6dea2059e200bd39]);
let expected = "01101101111010100010000001011001111000100000000010111101001110011010100101010011110101111001101110000011111101101010101101011001";
for e in expected.chars() {
assert!(a.next().unwrap() == (e == '1'));
}
assert!(a.next().is_none());
let expected = "1010010101111110101010000101101011101000011101110101001000011001100100100011011010001011011011010001011011101100110100111011010010110001000011110100110001100110011101101000101100011100100100100100001010011101010111110011101011000011101000111011011101011001";
let mut a = BitIterator::new([
0x429d5f3ac3a3b759,
0xb10f4c66768b1c92,
0x92368b6d16ecd3b4,
0xa57ea85ae8775219,
]);
for e in expected.chars() {
assert!(a.next().unwrap() == (e == '1'));
}
assert!(a.next().is_none());
}
#[cfg(not(feature = "expose-arith"))]
use self::arith_impl::*;
#[cfg(feature = "expose-arith")]
pub use self::arith_impl::*;
#[cfg(feature = "u128-support")]
mod arith_impl {
/// Calculate a - b - borrow, returning the result and modifying
/// the borrow value.
#[inline(always)]
pub fn sbb(a: u64, b: u64, borrow: &mut u64) -> u64 {
let tmp = (1u128 << 64) + u128::from(a) - u128::from(b) - u128::from(*borrow);
*borrow = if tmp >> 64 == 0 { 1 } else { 0 };
tmp as u64
}
/// Calculate a + b + carry, returning the sum and modifying the
/// carry value.
#[inline(always)]
pub fn adc(a: u64, b: u64, carry: &mut u64) -> u64 {
let tmp = u128::from(a) + u128::from(b) + u128::from(*carry);
*carry = (tmp >> 64) as u64;
tmp as u64
}
/// Calculate a + (b * c) + carry, returning the least significant digit
/// and setting carry to the most significant digit.
#[inline(always)]
pub fn mac_with_carry(a: u64, b: u64, c: u64, carry: &mut u64) -> u64 {
let tmp = (u128::from(a)) + u128::from(b) * u128::from(c) + u128::from(*carry);
*carry = (tmp >> 64) as u64;
tmp as u64
}
}
#[cfg(not(feature = "u128-support"))]
mod arith_impl {
#[inline(always)]
fn split_u64(i: u64) -> (u64, u64) {
(i >> 32, i & 0xFFFFFFFF)
}
#[inline(always)]
fn combine_u64(hi: u64, lo: u64) -> u64 {
(hi << 32) | lo
}
/// Calculate a - b - borrow, returning the result and modifying
/// the borrow value.
#[inline(always)]
pub fn sbb(a: u64, b: u64, borrow: &mut u64) -> u64 {
let (a_hi, a_lo) = split_u64(a);
let (b_hi, b_lo) = split_u64(b);
let (b, r0) = split_u64((1 << 32) + a_lo - b_lo - *borrow);
let (b, r1) = split_u64((1 << 32) + a_hi - b_hi - ((b == 0) as u64));
*borrow = (b == 0) as u64;
combine_u64(r1, r0)
}
/// Calculate a + b + carry, returning the sum and modifying the
/// carry value.
#[inline(always)]
pub fn adc(a: u64, b: u64, carry: &mut u64) -> u64 {
let (a_hi, a_lo) = split_u64(a);
let (b_hi, b_lo) = split_u64(b);
let (carry_hi, carry_lo) = split_u64(*carry);
let (t, r0) = split_u64(a_lo + b_lo + carry_lo);
let (t, r1) = split_u64(t + a_hi + b_hi + carry_hi);
*carry = t;
combine_u64(r1, r0)
}
/// Calculate a + (b * c) + carry, returning the least significant digit
/// and setting carry to the most significant digit.
#[inline(always)]
pub fn mac_with_carry(a: u64, b: u64, c: u64, carry: &mut u64) -> u64 {
/*
[ b_hi | b_lo ]
[ c_hi | c_lo ] *
-------------------------------------------
[ b_lo * c_lo ] <-- w
[ b_hi * c_lo ] <-- x
[ b_lo * c_hi ] <-- y
[ b_hi * c_lo ] <-- z
[ a_hi | a_lo ]
[ C_hi | C_lo ]
*/
let (a_hi, a_lo) = split_u64(a);
let (b_hi, b_lo) = split_u64(b);
let (c_hi, c_lo) = split_u64(c);
let (carry_hi, carry_lo) = split_u64(*carry);
let (w_hi, w_lo) = split_u64(b_lo * c_lo);
let (x_hi, x_lo) = split_u64(b_hi * c_lo);
let (y_hi, y_lo) = split_u64(b_lo * c_hi);
let (z_hi, z_lo) = split_u64(b_hi * c_hi);
let (t, r0) = split_u64(w_lo + a_lo + carry_lo);
let (t, r1) = split_u64(t + w_hi + x_lo + y_lo + a_hi + carry_hi);
let (t, r2) = split_u64(t + x_hi + y_hi + z_lo);
let (_, r3) = split_u64(t + z_hi);
*carry = combine_u64(r3, r2);
combine_u64(r1, r0)
}
}

3
pairing/src/tests/engine.rs

@ -1,6 +1,7 @@
use group::{CurveAffine, CurveProjective};
use rand::{Rand, SeedableRng, XorShiftRng};
use {CurveAffine, CurveProjective, Engine, Field, PrimeField};
use {Engine, Field, PairingCurveAffine, PrimeField};
pub fn engine_tests<E: Engine>() {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);

2
pairing/src/tests/field.rs

@ -1,5 +1,5 @@
use ff::{Field, LegendreSymbol, PrimeField, SqrtField};
use rand::{Rng, SeedableRng, XorShiftRng};
use {Field, LegendreSymbol, PrimeField, SqrtField};
pub fn random_frobenius_tests<F: Field, C: AsRef<[u64]>>(characteristic: C, maxpower: usize) {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);

1
pairing/src/tests/mod.rs

@ -1,4 +1,3 @@
pub mod curve;
pub mod engine;
pub mod field;
pub mod repr;

2
pairing/src/tests/repr.rs

@ -1,5 +1,5 @@
use ff::PrimeFieldRepr;
use rand::{SeedableRng, XorShiftRng};
use PrimeFieldRepr;
pub fn random_repr_tests<R: PrimeFieldRepr>() {
random_encoding_tests::<R>();

5
sapling-crypto/Cargo.toml

@ -14,6 +14,7 @@ features = ["expose-arith"]
[dependencies]
bellman = { path = "../bellman" }
ff = { path = "../ff" }
rand = "0.4"
digest = "0.7"
byteorder = "1"
@ -25,7 +26,3 @@ rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9"
[dev-dependencies]
hex-literal = "0.1"
rust-crypto = "0.2"
[features]
default = ["u128-support"]
u128-support = ["pairing/u128-support"]

10
sapling-crypto/src/circuit/boolean.rs

@ -1,9 +1,5 @@
use pairing::{
Engine,
Field,
PrimeField,
BitIterator
};
use ff::{BitIterator, Field, PrimeField};
use pairing::Engine;
use bellman::{
ConstraintSystem,
@ -806,8 +802,8 @@ impl From<AllocatedBit> for Boolean {
#[cfg(test)]
mod test {
use bellman::{ConstraintSystem};
use ff::{Field, PrimeField};
use pairing::bls12_381::{Bls12, Fr};
use pairing::{Field, PrimeField};
use ::circuit::test::*;
use super::{
AllocatedBit,

8
sapling-crypto/src/circuit/ecc.rs

@ -1,7 +1,5 @@
use pairing::{
Engine,
Field
};
use ff::Field;
use pairing::Engine;
use bellman::{
SynthesisError,
@ -751,8 +749,8 @@ impl<E: JubjubEngine> MontgomeryPoint<E> {
mod test {
use bellman::{ConstraintSystem};
use rand::{XorShiftRng, SeedableRng, Rand, Rng};
use ff::{BitIterator, Field, PrimeField};
use pairing::bls12_381::{Bls12, Fr};
use pairing::{BitIterator, Field, PrimeField};
use ::circuit::test::*;
use ::jubjub::{
montgomery,

4
sapling-crypto/src/circuit/lookup.rs

@ -1,4 +1,6 @@
use pairing::{Engine, Field};
use ff::Field;
use pairing::Engine;
use super::*;
use super::num::{
AllocatedNum,

7
sapling-crypto/src/circuit/multieq.rs

@ -1,8 +1,5 @@
use pairing::{
Engine,
Field,
PrimeField
};
use ff::{Field, PrimeField};
use pairing::Engine;
use bellman::{
SynthesisError,

3
sapling-crypto/src/circuit/multipack.rs

@ -1,4 +1,5 @@
use pairing::{Engine, Field, PrimeField};
use ff::{Field, PrimeField};
use pairing::Engine;
use bellman::{ConstraintSystem, SynthesisError};
use super::boolean::{Boolean};
use super::num::Num;

11
sapling-crypto/src/circuit/num.rs

@ -1,10 +1,5 @@
use pairing::{
Engine,
Field,
PrimeField,
PrimeFieldRepr,
BitIterator
};
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr};
use pairing::Engine;
use bellman::{
SynthesisError,
@ -462,8 +457,8 @@ impl<E: Engine> Num<E> {
mod test {
use rand::{SeedableRng, Rand, Rng, XorShiftRng};
use bellman::{ConstraintSystem};
use ff::{BitIterator, Field, PrimeField};
use pairing::bls12_381::{Bls12, Fr};
use pairing::{Field, PrimeField, BitIterator};
use ::circuit::test::*;
use super::{AllocatedNum, Boolean};

2
sapling-crypto/src/circuit/pedersen_hash.rs

@ -116,8 +116,8 @@ mod test {
use super::*;
use ::circuit::test::*;
use ::circuit::boolean::{Boolean, AllocatedBit};
use ff::PrimeField;
use pairing::bls12_381::{Bls12, Fr};
use pairing::PrimeField;
#[test]
fn test_pedersen_hash_constraints() {

10
sapling-crypto/src/circuit/sapling/mod.rs

@ -1,8 +1,4 @@
use pairing::{
PrimeField,
PrimeFieldRepr,
Field,
};
use ff::{Field, PrimeField, PrimeFieldRepr};
use bellman::{
SynthesisError,
@ -602,7 +598,7 @@ impl<'a, E: JubjubEngine> Circuit<E> for Output<'a, E> {
#[test]
fn test_input_circuit_with_bls12_381() {
use pairing::{Field, BitIterator};
use ff::{BitIterator, Field};
use pairing::bls12_381::*;
use rand::{SeedableRng, Rng, XorShiftRng};
use ::circuit::test::*;
@ -734,7 +730,7 @@ fn test_input_circuit_with_bls12_381() {
#[test]
fn test_output_circuit_with_bls12_381() {
use pairing::{Field};
use ff::Field;
use pairing::bls12_381::*;
use rand::{SeedableRng, Rng, XorShiftRng};
use ::circuit::test::*;

3
sapling-crypto/src/circuit/sprout/mod.rs

@ -1,4 +1,5 @@
use pairing::{Engine, Field};
use ff::Field;
use pairing::Engine;
use bellman::{ConstraintSystem, SynthesisError, Circuit, LinearCombination};
use circuit::boolean::{
AllocatedBit,

10
sapling-crypto/src/circuit/test/mod.rs

@ -1,9 +1,5 @@
use pairing::{
Engine,
Field,
PrimeField,
PrimeFieldRepr
};
use ff::{Field, PrimeField, PrimeFieldRepr};
use pairing::Engine;
use bellman::{
LinearCombination,
@ -445,8 +441,8 @@ impl<E: Engine> ConstraintSystem<E> for TestConstraintSystem<E> {
#[test]
fn test_cs() {
use ff::PrimeField;
use pairing::bls12_381::{Bls12, Fr};
use pairing::PrimeField;
let mut cs = TestConstraintSystem::<Bls12>::new();
assert!(cs.is_satisfied());

9
sapling-crypto/src/circuit/uint32.rs

@ -1,8 +1,5 @@
use pairing::{
Engine,
Field,
PrimeField
};
use ff::{Field, PrimeField};
use pairing::Engine;
use bellman::{
SynthesisError,
@ -415,8 +412,8 @@ mod test {
use rand::{XorShiftRng, SeedableRng, Rng};
use ::circuit::boolean::{Boolean};
use super::{UInt32};
use ff::Field;
use pairing::bls12_381::{Bls12};
use pairing::{Field};
use ::circuit::test::*;
use bellman::{ConstraintSystem};
use circuit::multieq::MultiEq;

2
sapling-crypto/src/group_hash.rs

@ -4,7 +4,7 @@ use jubjub::{
edwards
};
use pairing::{
use ff::{
PrimeField
};

8
sapling-crypto/src/jubjub/edwards.rs

@ -1,10 +1,4 @@
use pairing::{
Field,
SqrtField,
PrimeField,
PrimeFieldRepr,
BitIterator
};
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
use super::{
JubjubEngine,

8
sapling-crypto/src/jubjub/fs.rs

@ -1,7 +1,9 @@
use byteorder::{ByteOrder, LittleEndian};
use pairing::{BitIterator, Field, PrimeField, SqrtField, PrimeFieldRepr, PrimeFieldDecodingError, LegendreSymbol};
use pairing::LegendreSymbol::*;
use pairing::{adc, sbb, mac_with_carry};
use ff::{
adc, mac_with_carry, sbb, BitIterator, Field,
LegendreSymbol::{self, *},
PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField,
};
use super::ToUniform;

8
sapling-crypto/src/jubjub/mod.rs

@ -17,12 +17,8 @@
//! the Montgomery curve forms a group isomorphism, allowing points
//! to be freely converted between the two forms.
use pairing::{
Engine,
Field,
PrimeField,
SqrtField
};
use ff::{Field, PrimeField, SqrtField};
use pairing::Engine;
use group_hash::group_hash;

8
sapling-crypto/src/jubjub/montgomery.rs

@ -1,10 +1,4 @@
use pairing::{
Field,
SqrtField,
PrimeField,
PrimeFieldRepr,
BitIterator
};
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
use super::{
JubjubEngine,

2
sapling-crypto/src/jubjub/tests.rs

@ -6,7 +6,7 @@ use super::{
edwards
};
use pairing::{
use ff::{
Field,
PrimeField,
PrimeFieldRepr,

1
sapling-crypto/src/lib.rs

@ -2,6 +2,7 @@ extern crate pairing;
extern crate bellman;
extern crate blake2_rfc;
extern crate digest;
extern crate ff;
extern crate rand;
extern crate byteorder;

2
sapling-crypto/src/pedersen_hash.rs

@ -1,5 +1,5 @@
use ff::{Field, PrimeField, PrimeFieldRepr};
use jubjub::*;
use pairing::*;
#[derive(Copy, Clone)]
pub enum Personalization {

6
sapling-crypto/src/primitives/mod.rs

@ -1,8 +1,4 @@
use pairing::{
Field,
PrimeField,
PrimeFieldRepr
};
use ff::{Field, PrimeField, PrimeFieldRepr};
use constants;

2
sapling-crypto/src/redjubjub.rs

@ -1,7 +1,7 @@
//! Implementation of RedJubjub, a specialization of RedDSA to the Jubjub curve.
//! See section 5.4.6 of the Sapling protocol specification.
use pairing::{Field, PrimeField, PrimeFieldRepr};
use ff::{Field, PrimeField, PrimeFieldRepr};
use rand::{Rng, Rand};
use std::io::{self, Read, Write};

1
zcash_primitives/Cargo.toml

@ -7,6 +7,7 @@ authors = [
[dependencies]
byteorder = "1"
ff = { path = "../ff" }
lazy_static = "1"
pairing = { path = "../pairing" }
rand = "0.4"

1
zcash_primitives/src/lib.rs

@ -3,6 +3,7 @@ extern crate lazy_static;
extern crate blake2_rfc;
extern crate byteorder;
extern crate ff;
extern crate pairing;
extern crate rand;
extern crate sapling_crypto;

6
zcash_primitives/src/transaction/components.rs

@ -1,8 +1,6 @@
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use pairing::{
bls12_381::{Bls12, Fr, FrRepr},
PrimeField, PrimeFieldRepr,
};
use ff::{PrimeField, PrimeFieldRepr};
use pairing::bls12_381::{Bls12, Fr, FrRepr};
use sapling_crypto::{
jubjub::{edwards, Unknown},
redjubjub::{PublicKey, Signature},

2
zcash_primitives/src/transaction/sighash.rs

@ -1,6 +1,6 @@
use blake2_rfc::blake2b::Blake2b;
use byteorder::{LittleEndian, WriteBytesExt};
use pairing::{PrimeField, PrimeFieldRepr};
use ff::{PrimeField, PrimeFieldRepr};
use super::{
components::{Amount, Script, TxOut},

1
zcash_proofs/Cargo.toml

@ -8,6 +8,7 @@ authors = [
[dependencies]
bellman = { path = "../bellman" }
byteorder = "1"
ff = { path = "../ff" }
pairing = { path = "../pairing" }
rand = "0.4"
sapling-crypto = { path = "../sapling-crypto" }

1
zcash_proofs/src/lib.rs

@ -1,5 +1,6 @@
extern crate bellman;
extern crate byteorder;
extern crate ff;
extern crate pairing;
extern crate rand;
extern crate sapling_crypto;

6
zcash_proofs/src/sapling/prover.rs

@ -2,10 +2,8 @@ use bellman::groth16::{
create_random_proof, verify_proof, Parameters, PreparedVerifyingKey, Proof,
};
use byteorder::{LittleEndian, ReadBytesExt};
use pairing::{
bls12_381::{Bls12, Fr, FrRepr},
Field, PrimeField, PrimeFieldRepr,
};
use ff::{Field, PrimeField, PrimeFieldRepr};
use pairing::bls12_381::{Bls12, Fr, FrRepr};
use rand::{OsRng, Rand};
use sapling_crypto::{
circuit::{

6
zcash_proofs/src/sapling/verifier.rs

@ -1,8 +1,6 @@
use bellman::groth16::{verify_proof, PreparedVerifyingKey, Proof};
use pairing::{
bls12_381::{Bls12, Fr},
Field,
};
use ff::Field;
use pairing::bls12_381::{Bls12, Fr};
use sapling_crypto::{
circuit::multipack,
jubjub::{edwards, FixedGenerators, JubjubBls12, Unknown},

1
zip32/Cargo.toml

@ -14,6 +14,7 @@ repository = "https://github.com/zcash-hackworks/zip32"
[dependencies]
aes = "0.2"
byteorder = "1"
ff = { path = "../ff" }
fpe = "0.1"
lazy_static = "1.0"
pairing = { path = "../pairing" }

4
zip32/src/lib.rs

@ -1,6 +1,7 @@
extern crate aes;
extern crate blake2_rfc;
extern crate byteorder;
extern crate ff;
extern crate fpe;
#[macro_use]
extern crate lazy_static;
@ -10,8 +11,9 @@ extern crate sapling_crypto;
use aes::Aes256;
use blake2_rfc::blake2b::{Blake2b, Blake2bResult};
use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
use ff::{Field, PrimeField, PrimeFieldRepr};
use fpe::ff1::{BinaryNumeralString, FF1};
use pairing::{bls12_381::Bls12, Field, PrimeField, PrimeFieldRepr};
use pairing::bls12_381::Bls12;
use sapling_crypto::{
jubjub::{
edwards, FixedGenerators, JubjubBls12, JubjubEngine, JubjubParams, ToUniform, Unknown,

Loading…
Cancel
Save