Merge pull request #46 from str4d/ff-traits
Migrate to ff and group crates
This commit is contained in:
commit
c57a31e82e
|
@ -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"
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"bellman",
|
||||
"ff",
|
||||
"group",
|
||||
"librustzcash",
|
||||
"pairing",
|
||||
"sapling-crypto",
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
use pairing::{
|
||||
Engine,
|
||||
Field,
|
||||
PrimeField
|
||||
};
|
||||
use ff::{Field, PrimeField};
|
||||
use pairing::Engine;
|
||||
|
||||
mod dummy_engine;
|
||||
use self::dummy_engine::*;
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
use pairing::{
|
||||
Engine,
|
||||
CurveProjective,
|
||||
CurveAffine,
|
||||
PrimeField
|
||||
};
|
||||
use ff::PrimeField;
|
||||
use group::{CurveAffine, CurveProjective};
|
||||
use pairing::{Engine, PairingCurveAffine};
|
||||
|
||||
use super::{
|
||||
Proof,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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::{
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
target/
|
||||
**/*.rs.bk
|
||||
Cargo.lock
|
|
@ -0,0 +1,18 @@
|
|||
[package]
|
||||
name = "ff"
|
||||
version = "0.4.0"
|
||||
authors = ["Sean Bowe <ewillbefull@gmail.com>"]
|
||||
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"]
|
|
@ -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.
|
||||
|
|
@ -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.
|
|
@ -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.
|
|
@ -0,0 +1,20 @@
|
|||
[package]
|
||||
name = "ff_derive"
|
||||
version = "0.3.0"
|
||||
authors = ["Sean Bowe <ewillbefull@gmail.com>"]
|
||||
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"
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
/target
|
||||
**/*.rs.bk
|
||||
Cargo.lock
|
|
@ -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.
|
|
@ -0,0 +1,17 @@
|
|||
[package]
|
||||
name = "group"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Sean Bowe <ewillbefull@gmail.com>",
|
||||
"Jack Grigg <jack@z.cash>",
|
||||
]
|
||||
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"
|
|
@ -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.
|
|
@ -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.
|
|
@ -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.
|
|
@ -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()),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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) {
|
|
@ -15,6 +15,7 @@ crate-type = ["staticlib"]
|
|||
|
||||
[dependencies]
|
||||
bellman = { path = "../bellman" }
|
||||
ff = { path = "../ff" }
|
||||
libc = "0.2"
|
||||
pairing = { path = "../pairing" }
|
||||
lazy_static = "1"
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -3,7 +3,10 @@ name = "pairing"
|
|||
|
||||
# Remember to change version string in README.md.
|
||||
version = "0.14.2"
|
||||
authors = ["Sean Bowe <ewillbefull@gmail.com>"]
|
||||
authors = [
|
||||
"Sean Bowe <ewillbefull@gmail.com>",
|
||||
"Jack Grigg <jack@z.cash>",
|
||||
]
|
||||
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 = []
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate ff;
|
||||
extern crate group;
|
||||
extern crate pairing;
|
||||
extern crate rand;
|
||||
extern crate test;
|
||||
|
|
|
@ -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>();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,647 +1,10 @@
|
|||
use LegendreSymbol::*;
|
||||
use {Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField};
|
||||
use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr};
|
||||
|
||||
// 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))
|
||||
}
|
||||
}
|
||||
|
||||
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(),
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
>,
|
||||
{
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use ff::PrimeFieldRepr;
|
||||
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
|
||||
|
||||
use super::*;
|
||||
use *;
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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,4 +1,3 @@
|
|||
pub mod curve;
|
||||
pub mod engine;
|
||||
pub mod field;
|
||||
pub mod repr;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use ff::PrimeFieldRepr;
|
||||
use rand::{SeedableRng, XorShiftRng};
|
||||
use PrimeFieldRepr;
|
||||
|
||||
pub fn random_repr_tests<R: PrimeFieldRepr>() {
|
||||
random_encoding_tests::<R>();
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use pairing::{Engine, Field};
|
||||
use ff::Field;
|
||||
use pairing::Engine;
|
||||
|
||||
use super::*;
|
||||
use super::num::{
|
||||
AllocatedNum,
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
use pairing::{
|
||||
Engine,
|
||||
Field,
|
||||
PrimeField
|
||||
};
|
||||
use ff::{Field, PrimeField};
|
||||
use pairing::Engine;
|
||||
|
||||
use bellman::{
|
||||
SynthesisError,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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::*;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use pairing::{Engine, Field};
|
||||
use ff::Field;
|
||||
use pairing::Engine;
|
||||
use bellman::{ConstraintSystem, SynthesisError, Circuit, LinearCombination};
|
||||
use circuit::boolean::{
|
||||
AllocatedBit,
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -4,7 +4,7 @@ use jubjub::{
|
|||
edwards
|
||||
};
|
||||
|
||||
use pairing::{
|
||||
use ff::{
|
||||
PrimeField
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
use pairing::{
|
||||
Field,
|
||||
SqrtField,
|
||||
PrimeField,
|
||||
PrimeFieldRepr,
|
||||
BitIterator
|
||||
};
|
||||
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
|
||||
|
||||
use super::{
|
||||
JubjubEngine,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
use pairing::{
|
||||
Field,
|
||||
SqrtField,
|
||||
PrimeField,
|
||||
PrimeFieldRepr,
|
||||
BitIterator
|
||||
};
|
||||
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
|
||||
|
||||
use super::{
|
||||
JubjubEngine,
|
||||
|
|
|
@ -6,7 +6,7 @@ use super::{
|
|||
edwards
|
||||
};
|
||||
|
||||
use pairing::{
|
||||
use ff::{
|
||||
Field,
|
||||
PrimeField,
|
||||
PrimeFieldRepr,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use ff::{Field, PrimeField, PrimeFieldRepr};
|
||||
use jubjub::*;
|
||||
use pairing::*;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Personalization {
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
use pairing::{
|
||||
Field,
|
||||
PrimeField,
|
||||
PrimeFieldRepr
|
||||
};
|
||||
use ff::{Field, PrimeField, PrimeFieldRepr};
|
||||
|
||||
use constants;
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ authors = [
|
|||
|
||||
[dependencies]
|
||||
byteorder = "1"
|
||||
ff = { path = "../ff" }
|
||||
lazy_static = "1"
|
||||
pairing = { path = "../pairing" }
|
||||
rand = "0.4"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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,5 +1,6 @@
|
|||
extern crate bellman;
|
||||
extern crate byteorder;
|
||||
extern crate ff;
|
||||
extern crate pairing;
|
||||
extern crate rand;
|
||||
extern crate sapling_crypto;
|
||||
|
|
|
@ -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::{
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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…
Reference in New Issue