1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

implement sha256 on bellman, remove libsnark version

This commit is contained in:
schaeff 2019-04-01 19:59:12 +02:00
parent b3c432ae2f
commit f8fa3efccf
18 changed files with 777 additions and 706 deletions

103
Cargo.lock generated
View file

@ -70,7 +70,7 @@ name = "backtrace-sys"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -149,7 +149,7 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.31"
version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -184,10 +184,10 @@ dependencies = [
[[package]]
name = "cmake"
version = "0.1.35"
version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -295,6 +295,11 @@ dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crunchy"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "csv"
version = "1.0.5"
@ -317,10 +322,10 @@ name = "curl-sys"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -331,6 +336,14 @@ name = "difference"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "digest"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "either"
version = "1.5.1"
@ -400,6 +413,14 @@ dependencies = [
"num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "generic-array"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "git2"
version = "0.8.0"
@ -410,7 +431,7 @@ dependencies = [
"libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -464,12 +485,12 @@ name = "libgit2-sys"
version = "0.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"curl-sys 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
"libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -478,10 +499,10 @@ name = "libssh2-sys"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -491,7 +512,7 @@ name = "libz-sys"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -607,10 +628,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "openssl-sys"
version = "0.9.42"
version = "0.9.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -895,6 +916,21 @@ dependencies = [
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "sapling-crypto"
version = "0.0.4"
source = "git+https://github.com/matterinc/sapling-crypto?tag=0.0.4#6ac48e2f920bd54358b7a4cca0a96f87753009e4"
dependencies = [
"bellman 0.2.0 (git+https://github.com/matterinc/bellman?tag=0.2.0)",
"blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)",
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "scopeguard"
version = "0.3.3"
@ -1040,6 +1076,19 @@ dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tiny-keccak"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crunchy 0.1.6 (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.3"
@ -1167,8 +1216,8 @@ dependencies = [
"bellman 0.2.0 (git+https://github.com/matterinc/bellman?tag=0.2.0)",
"bimap 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
"cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"cmake 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"ff 0.5.0 (git+https://github.com/matterinc/ff?tag=0.5)",
"git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1187,6 +1236,16 @@ dependencies = [
"serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmi 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"zokrates_embed 0.1.0",
"zokrates_field 0.3.2",
]
[[package]]
name = "zokrates_embed"
version = "0.1.0"
dependencies = [
"bellman 0.2.0 (git+https://github.com/matterinc/bellman?tag=0.2.0)",
"sapling-crypto 0.0.4 (git+https://github.com/matterinc/sapling-crypto?tag=0.0.4)",
"zokrates_field 0.3.2",
]
@ -1245,11 +1304,11 @@ dependencies = [
"checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f"
"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
"checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe"
"checksum cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ce8bb087aacff865633f0bd5aeaed910fe2fe55b55f4739527f2e023a2e53d"
"checksum cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ad0daef304fa0b4238f5f7ed7178774b43b06f6a9b6509f6642bef4ff1f7b9b2"
"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4"
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec65ee4f9c9d16f335091d23693457ed4928657ba4982289d7fafee03bc614a"
"checksum cmake 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "c11b79fbf026d6ec02704f7248c6da99be02068bf57f624bb08af72ad29f2c06"
"checksum colored 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e9a455e156a4271e12fd0246238c380b1e223e3736663c7a18ed8b6362028a9"
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
"checksum crossbeam 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b14492071ca110999a20bf90e3833406d5d66bfd93b4e52ec9539025ff43fe0d"
@ -1261,10 +1320,12 @@ dependencies = [
"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
"checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04"
"checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65"
"checksum curl-sys 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7b8d8e51964f58c8053337fcef48e1c4608c7ee70c6f2e457674a97dda5a5828"
"checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8"
"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac"
"checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee"
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
@ -1274,6 +1335,7 @@ dependencies = [
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b"
"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
"checksum git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7339329bfa14a00223244311560d11f8f489b453fb90092af97f267a6090ab0"
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
@ -1301,7 +1363,7 @@ dependencies = [
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
"checksum openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)" = "cb534d752bf98cf363b473950659ac2546517f9c6be9723771614ab3f03bbc9e"
"checksum openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)" = "33c86834957dd5b915623e94f2f4ab2c70dd8f6b70679824155d5ae21dbd495d"
"checksum pairing 0.16.2 (git+https://github.com/matterinc/pairing?tag=0.16.2)" = "<none>"
"checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc"
"checksum parity-wasm 0.35.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3e1e076c4e01399b6cd0793a8df42f90bba3ae424671ef421d1608a943155d93"
@ -1335,6 +1397,7 @@ dependencies = [
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
"checksum sapling-crypto 0.0.4 (git+https://github.com/matterinc/sapling-crypto?tag=0.0.4)" = "<none>"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"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"
@ -1352,6 +1415,8 @@ dependencies = [
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426"

View file

@ -5,4 +5,5 @@ members = [
"zokrates_cli",
"zokrates_fs_resolver",
"zokrates_stdlib",
"zokrates_embed",
]

View file

@ -29,6 +29,7 @@ bellman = { git = "https://github.com/matterinc/bellman", tag = "0.2.0" }
pairing = { git = "https://github.com/matterinc/pairing", tag = "0.16.2" }
ff = { git = 'https://github.com/matterinc/ff', features = ["derive"], tag = "0.5" }
zokrates_field = { version = "0.3.0", path = "../zokrates_field" }
zokrates_embed = { path = "../zokrates_embed" }
rand = "0.4"
wasmi = "0.4.2"
parity-wasm = "0.35.3"

View file

@ -57,18 +57,6 @@ fn main() {
.file("lib/pghr13.cpp")
.compile("libwraplibsnark.a");
// build gadgets
cc::Build::new()
.cpp(true)
.flag("-std=c++11")
.include(libsnark_source_path)
.include(libsnark_source_path.join("depends/libff"))
.include(libsnark_source_path.join("depends/libfqfft"))
.define("CURVE_ALT_BN128", None)
.file("lib/wraplibsnarkgadgets.cpp")
.compile("libwraplibsnarkgadgets.a");
println!(
"cargo:rustc-link-search=native={}",
libsnark.join("lib").display()

View file

@ -1,237 +0,0 @@
//https://gist.github.com/kobigurk/24c25e68219df87c348f1a78db51bb52
#include <iostream>
#include "wraplibsnarkgadgets.hpp"
#include "libsnark/gadgetlib1/gadget.hpp"
#include "libsnark/gadgetlib1/protoboard.hpp"
#include "libff/common/default_types/ec_pp.hpp"
#include "libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_components.hpp"
#include "libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp"
using namespace libsnark;
using namespace libff;
using std::vector;
typedef libff::Fr<alt_bn128_pp> FieldT;
pb_variable_array<FieldT> from_bits(std::vector<bool> bits, pb_variable<FieldT>& ZERO)
{
pb_variable_array<FieldT> acc;
for (size_t i = 0; i < bits.size(); i++) {
bool bit = bits[i];
acc.emplace_back(bit ? ONE : ZERO);
}
return acc;
}
vector<unsigned long> bit_list_to_ints(vector<bool> bit_list, const size_t wordsize)
{
vector<unsigned long> res;
size_t iterations = bit_list.size()/wordsize+1;
for (size_t i = 0; i < iterations; ++i) {
unsigned long current = 0;
for (size_t j = 0; j < wordsize; ++j) {
if (bit_list.size() == (i*wordsize+j)) break;
current += (bit_list[i*wordsize+j] * (1ul<<(wordsize-1-j)));
}
res.push_back(current);
}
return res;
}
// conversion byte[32] <-> libsnark bigint.
libff::bigint<libff::alt_bn128_r_limbs> libsnarkBigintFromBytesAux(const uint8_t* _x)
{
libff::bigint<libff::alt_bn128_r_limbs> x;
for (unsigned i = 0; i < 4; i++) {
for (unsigned j = 0; j < 8; j++) {
x.data[3 - i] |= uint64_t(_x[i * 8 + j]) << (8 * (7-j));
}
}
return x;
}
void constraint_to_json(linear_combination<FieldT> constraints, std::stringstream &ss)
{
ss << "{";
uint count = 0;
for (const linear_term<FieldT>& lt : constraints.terms)
{
if (count != 0) {
ss << ",";
}
ss << '"' << lt.index << '"' << ":" << '"' << lt.coeff << '"';
count++;
}
ss << "}";
}
std::string r1cs_to_json(protoboard<FieldT> pb)
{
r1cs_constraint_system<FieldT> constraints = pb.get_constraint_system();
std::stringstream ss;
ss << "{\"variable_count\":";
ss << pb.num_variables() + 1; // ~one is not counted in pb.num_variables()
ss << ",\"inputs\":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768], \"outputs\":[769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024],\"constraints\":[";
for (size_t c = 0; c < constraints.num_constraints(); ++c)
{
ss << "[";// << "\"A\"=";
constraint_to_json(constraints.constraints[c].a, ss);
ss << ",";// << "\"B\"=";
constraint_to_json(constraints.constraints[c].b, ss);
ss << ",";// << "\"C\"=";;
constraint_to_json(constraints.constraints[c].c, ss);
if (c == constraints.num_constraints()-1 ) {
ss << "]\n";
} else {
ss << "],\n";
}
}
ss << "]}";
ss.rdbuf()->pubseekpos(0, std::ios_base::out);
return ss.str();
}
std::string array_to_json(protoboard<FieldT> pb)
{
std::stringstream ss;
r1cs_variable_assignment<FieldT> values = pb.full_variable_assignment();
ss << "{\"variables\":[";
ss << 1 << ","; // the variable zero to the one constant
for (size_t i = 0; i < values.size(); ++i)
{
ss << values[i].as_bigint();
if (i < values.size() - 1) { ss << ",";}
}
ss << "]}";
// std::cout << ss.rdbuf();
ss.rdbuf()->pubseekpos(0, std::ios_base::out);
return(ss.str());
}
class sha256round: gadget<FieldT>
{
private:
std::shared_ptr<block_variable<FieldT>> block;
public:
std::shared_ptr<sha256_compression_function_gadget<FieldT>> hasher;
sha256round(
protoboard<FieldT> &pb,
pb_variable_array<FieldT>& myIV,
pb_variable_array<FieldT>& a,
pb_variable_array<FieldT>& b,
digest_variable<FieldT> &result
) : gadget<FieldT>(pb, "sha256round") {
block.reset(new block_variable<FieldT>(pb, {
a,
b
}, "block"));
hasher.reset(new sha256_compression_function_gadget<FieldT>(
pb,
myIV,
block->bits,
result,
"hasher"));
}
void generate_r1cs_constraints() {
hasher->generate_r1cs_constraints();
}
void generate_r1cs_witness() {
hasher->generate_r1cs_witness();
}
};
char* _sha256RoundConstraints()
{
libff::alt_bn128_pp::init_public_params();
protoboard<FieldT> pb;
pb_variable_array<FieldT> left;
left.allocate(pb, 256, "left");
pb_variable_array<FieldT> right;
right.allocate(pb, 256, "right");
digest_variable<FieldT> IV(pb, 256, "IV");
digest_variable<FieldT> output(pb, 256, "output");
IV.generate_r1cs_constraints(); //binary check for IV vector
output.generate_r1cs_constraints(); //binary check for output vector
sha256round g(pb, IV.bits, left, right, output);
g.generate_r1cs_constraints();
auto json = r1cs_to_json(pb);
auto result = new char[json.size() + 1];
memcpy(result, json.c_str(), json.size() + 1);
return result;
}
char* _sha256RoundWitness(const uint8_t* inputs, int inputs_length)
{
assert(inputs_length==768);
libff::alt_bn128_pp::init_public_params();
protoboard<FieldT> pb;
pb_variable_array<FieldT> left;
left.allocate(pb, 256, "left");
pb_variable_array<FieldT> right;
right.allocate(pb, 256, "right");
digest_variable<FieldT> IV(pb, 256, "IV");
digest_variable<FieldT> output(pb, 256, "output");
libff::bit_vector left_bv;
libff::bit_vector right_bv;
libff::bit_vector IV_bv;
for (int i = 0; i < 256; i++) {
left_bv.push_back(libsnarkBigintFromBytesAux(inputs + i*32) == 1);
}
for (int i = 256; i < 512; i++) {
right_bv.push_back(libsnarkBigintFromBytesAux(inputs + i*32) == 1);
}
for (int i = 512; i < 768; i++) {
IV_bv.push_back(libsnarkBigintFromBytesAux(inputs + i*32) == 1);
}
left.fill_with_bits(pb, left_bv);
right.fill_with_bits(pb, right_bv);
IV.generate_r1cs_witness(IV_bv);
sha256round g(pb, IV.bits, left, right, output);
g.generate_r1cs_witness();
assert(pb.is_satisfied());
auto json = array_to_json(pb);
auto result = new char[json.size() + 1];
memcpy(result, json.c_str(), json.size() + 1);
return result;
}

View file

@ -1,25 +0,0 @@
/**
* @file wraplibsnark.hpp
* @author Jacob Eberhardt <jacob.eberhardt@tu-berlin.de
* @author Dennis Kuhnert <dennis.kuhnert@campus.tu-berlin.de>
* @date 2017
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
char* _sha256RoundConstraints();
char* _sha256RoundWitness(const uint8_t* input, int input_length);
// External interface to free memory
void _free_string(char const *str) {
delete[] str;
}
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -1,5 +1,6 @@
use helpers::{Executable, Signed};
use std::fmt;
use zokrates_embed::generate_sha256_round_witness;
use zokrates_field::field::Field;
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
@ -8,16 +9,12 @@ pub enum RustHelper {
ConditionEq,
Bits,
Div,
Sha256Round,
}
impl fmt::Display for RustHelper {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
RustHelper::Identity => write!(f, "Identity"),
RustHelper::ConditionEq => write!(f, "ConditionEq"),
RustHelper::Bits => write!(f, "Bits"),
RustHelper::Div => write!(f, "Div"),
}
write!(f, "{:?}", self)
}
}
@ -28,6 +25,7 @@ impl Signed for RustHelper {
RustHelper::ConditionEq => (1, 2),
RustHelper::Bits => (1, 254),
RustHelper::Div => (2, 1),
RustHelper::Sha256Round => (768, 26935),
}
}
}
@ -56,6 +54,12 @@ impl<T: Field> Executable<T> for RustHelper {
Ok(res)
}
RustHelper::Div => Ok(vec![inputs[0].clone() / inputs[1].clone()]),
RustHelper::Sha256Round => {
let i = &inputs[0..512];
let h = &inputs[512..];
assert!(h.len() == 256);
Ok(generate_sha256_round_witness(i, h))
}
}
}
}

View file

@ -139,26 +139,20 @@ impl Importer {
let pos = import.pos();
let import = &import.value;
// handle the case of special libsnark and packing imports
if import.source.starts_with("LIBSNARK") {
#[cfg(feature = "libsnark")]
{
use helpers::LibsnarkGadgetHelper;
use libsnark::get_sha256round_constraints;
use serde_json::from_str;
use standard::{DirectiveR1CS, R1CS};
if import.source.starts_with("BELLMAN") {
match import.source.as_ref() {
"LIBSNARK/sha256round" => {
let r1cs: R1CS = from_str(&get_sha256round_constraints()).unwrap();
let dr1cs: DirectiveR1CS = DirectiveR1CS {
r1cs,
directive: LibsnarkGadgetHelper::Sha256Round,
"BELLMAN/sha256round" => {
use standard::sha_round;
let compiled = FlatProg {
functions: vec![sha_round()],
};
let compiled = FlatProg::from(dr1cs);
let alias = match import.alias {
Some(ref alias) => alias.clone(),
None => String::from("sha256round"),
};
origins.push(CompiledImport::new(compiled, alias));
}
s => {
@ -169,11 +163,6 @@ impl Importer {
.into());
}
}
}
#[cfg(not(feature = "libsnark"))]
{
panic!("libsnark is not enabled, cannot access {}", import.source)
}
} else if import.source.starts_with("PACKING") {
use types::conversions::split;

View file

@ -21,6 +21,7 @@ extern crate rustc_hex;
extern crate serde_bytes;
#[cfg(feature = "wasm")]
extern crate wasmi;
extern crate zokrates_embed;
extern crate zokrates_field;
mod flatten;
@ -29,7 +30,6 @@ mod imports;
mod optimizer;
mod parser;
mod semantics;
#[cfg(feature = "libsnark")]
mod standard;
mod static_analysis;
mod typed_absy;
@ -39,7 +39,4 @@ pub mod absy;
pub mod compile;
pub mod flat_absy;
pub mod ir;
#[cfg(feature = "libsnark")]
pub mod libsnark;
// #[cfg(feature = "libsnark")]
pub mod proof_system;

View file

@ -1,132 +0,0 @@
//
// @file libsnark.rs
// @author Jacob Eberhardt <jacob.eberhardt@tu-berlin.de
// @author Dennis Kuhnert <dennis.kuhnert@campus.tu-berlin.de>
// @date 2017
extern crate libc;
use self::libc::{c_char, c_int, uint8_t};
use std::ffi::CStr;
use std::string::String;
use zokrates_field::field::Field;
extern "C" {
fn _sha256RoundConstraints() -> *mut c_char;
fn _sha256RoundWitness(inputs: *const uint8_t, inputs_length: c_int) -> *mut c_char;
fn _free_string(str: *const c_char);
}
pub fn get_sha256round_constraints() -> String {
let c_buf: *const c_char = unsafe { _sha256RoundConstraints() };
let c_str: &CStr = unsafe { CStr::from_ptr(c_buf) };
let str_slice: &str = c_str.to_str().unwrap();
let str_buf: String = str_slice.to_owned(); //memory allocated in Rust
unsafe { _free_string(c_buf) }; //memory deallocated in Cpp
str_buf
}
pub fn get_sha256round_witness<T: Field>(inputs: &Vec<T>) -> String {
let mut inputs_arr: Vec<[u8; 32]> = vec![[0u8; 32]; inputs.len()];
for (index, value) in inputs.into_iter().enumerate() {
inputs_arr[index] = vec_as_u8_32_array(&value.into_byte_vector());
}
let c_buf: *const c_char =
unsafe { _sha256RoundWitness(inputs_arr[0].as_ptr(), inputs.len() as i32) };
let c_str: &CStr = unsafe { CStr::from_ptr(c_buf) };
let str_slice: &str = c_str.to_str().unwrap();
let str_buf: String = str_slice.to_owned();
unsafe { _free_string(c_buf) };
str_buf
}
// utility function. Converts a Fields vector-based byte representation to fixed size array.
fn vec_as_u8_32_array(vec: &Vec<u8>) -> [u8; 32] {
assert!(vec.len() <= 32);
let mut array = [0u8; 32];
for (index, byte) in vec.iter().enumerate() {
array[31 - index] = *byte;
}
array
}
#[cfg(test)]
mod tests {
use super::*;
use flat_absy::*;
use helpers;
use num_bigint::BigUint;
use serde_json;
use standard;
use zokrates_field::field::FieldPrime;
#[cfg(test)]
mod sha256_gadget {
use super::*;
#[test]
fn can_get_sha256_constraints() {
let _a = get_sha256round_constraints();
}
#[test]
fn can_generate_sha_256_witness_null() {
let inputs = vec![FieldPrime::from(0); 768];
let _b = get_sha256round_witness(&inputs);
}
#[test]
fn can_generate_flattened_code() {
let constraints = get_sha256round_constraints();
let r1cs: standard::R1CS = serde_json::from_str(&constraints).unwrap();
let _prog: FlatProg<FieldPrime> = FlatProg::from(standard::DirectiveR1CS {
r1cs,
directive: helpers::LibsnarkGadgetHelper::Sha256Round,
});
}
}
#[cfg(test)]
mod libsnark_integration {
use super::*;
#[test]
fn serialization_dec() {
assert_eq!(
BigUint::parse_bytes(
b"5472060717959818805561601436314318772174077789324455915672259473661306552146",
10
)
.unwrap()
.to_bytes_le(),
FieldPrime::try_from_str(
"5472060717959818805561601436314318772174077789324455915672259473661306552146"
)
.unwrap()
.into_byte_vector()
);
}
#[test]
fn serialization_bin() {
assert_eq!(
BigUint::parse_bytes(b"110000011001000100111001110010111000010011000110100000001010011011100001010000010001011011011010000001100000010101100001011101100101111000000101101010100100010110100001110001110010101000110100111100001000001000110000010110110110000111110011111101010010",2).unwrap().to_bytes_le(),
FieldPrime::try_from_str("5472060717959818805561601436314318772174077789324455915672259473661306552146").unwrap().into_byte_vector()
);
}
#[test]
fn vec_to_array() {
let byte_vector: Vec<u8> = FieldPrime::try_from_str(
"5472060717959818805561601436314318772174077789324455915672259473661306552146",
)
.unwrap()
.into_byte_vector();
let array: [u8; 32] = vec_as_u8_32_array(&byte_vector);
for (index, value) in byte_vector.iter().enumerate() {
assert_eq!(*value, array[31 - index]);
}
}
}
}

View file

@ -45,7 +45,7 @@ fn bellman_combination<CS: ConstraintSystem<Bn256>>(
l.0.into_iter()
.map(|(k, v)| {
(
Fr::from(v),
v.into_bellman(),
symbols
.entry(k)
.or_insert_with(|| {
@ -57,7 +57,7 @@ fn bellman_combination<CS: ConstraintSystem<Bn256>>(
.0
.remove(&k)
.ok_or(SynthesisError::AssignmentMissing)?
.into())
.into_bellman())
},
),
false => cs.alloc(
@ -67,7 +67,7 @@ fn bellman_combination<CS: ConstraintSystem<Bn256>>(
.0
.remove(&k)
.ok_or(SynthesisError::AssignmentMissing)?
.into())
.into_bellman())
},
),
}
@ -107,7 +107,7 @@ impl Prog<FieldPrime> {
.0
.remove(&var)
.ok_or(SynthesisError::AssignmentMissing)?
.into())
.into_bellman())
},
),
false => cs.alloc_input(
@ -117,7 +117,7 @@ impl Prog<FieldPrime> {
.0
.remove(&var)
.ok_or(SynthesisError::AssignmentMissing)?
.into())
.into_bellman())
},
),
}
@ -172,7 +172,7 @@ impl Computation<FieldPrime> {
.map(|(a, _)| a)
.map(|v| self.witness.clone().unwrap().0.get(v).unwrap().clone())
.chain(self.witness.clone().unwrap().return_values())
.map(|v| Fr::from(v.clone()))
.map(|v| v.clone().into_bellman())
.collect()
}

View file

@ -1,57 +1,18 @@
use flat_absy::{FlatExpression, FlatExpressionList, FlatFunction, FlatStatement};
use flat_absy::{FlatParameter, FlatVariable};
use helpers::{DirectiveStatement, Helper, LibsnarkGadgetHelper};
use helpers::{DirectiveStatement, Helper, RustHelper};
use reduce::Reduce;
use std::collections::BTreeMap;
use types::{Signature, Type};
use zokrates_field::field::Field;
// for r1cs import, can be moved.
// r1cs data structure reflecting JSON standard format:
// {
// variable_count: 435,
// inputs: [offset_1, offset_33], // # of inputs to pass
// outputs: [offset_42, offset_63, offset_55], // indices of the outputs in the witness
// constraints: [ // constraints verified by the witness
// [
// {offset_1: value_a1, offset_2: value_a2, ...},
// {offset_1: value_b1, offset_2: value_b2, ...},
// {offset_1: value_c1, offset_2: value_c2, ...}
// ]
// }
#[derive(Serialize, Deserialize, Debug)]
pub struct R1CS {
pub inputs: Vec<usize>,
pub outputs: Vec<usize>,
pub variable_count: usize,
pub constraints: Vec<Constraint>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Witness {
pub variables: Vec<usize>,
}
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct Constraint {
a: BTreeMap<usize, String>,
b: BTreeMap<usize, String>,
c: BTreeMap<usize, String>,
}
pub struct DirectiveR1CS {
pub r1cs: R1CS,
pub directive: LibsnarkGadgetHelper,
}
impl<T: Field> Into<FlatStatement<T>> for Constraint {
fn into(self: Constraint) -> FlatStatement<T> {
let rhs_a = match self
impl<T: Field> From<zokrates_embed::Constraint<T>> for FlatStatement<T> {
fn from(c: zokrates_embed::Constraint<T>) -> FlatStatement<T> {
let rhs_a = match c
.a
.into_iter()
.map(|(key, val)| {
FlatExpression::Mult(
box FlatExpression::Number(T::from_dec_string(val.to_string())),
box FlatExpression::Number(val),
box FlatExpression::Identifier(FlatVariable::new(key)),
)
})
@ -64,12 +25,12 @@ impl<T: Field> Into<FlatStatement<T>> for Constraint {
None => FlatExpression::Number(T::zero()),
};
let rhs_b = match self
let rhs_b = match c
.b
.into_iter()
.map(|(key, val)| {
FlatExpression::Mult(
box FlatExpression::Number(T::from_dec_string(val.to_string())),
box FlatExpression::Number(val),
box FlatExpression::Identifier(FlatVariable::new(key)),
)
})
@ -82,12 +43,12 @@ impl<T: Field> Into<FlatStatement<T>> for Constraint {
None => FlatExpression::Number(T::zero()),
};
let lhs = match self
let lhs = match c
.c
.into_iter()
.map(|(key, val)| {
FlatExpression::Mult(
box FlatExpression::Number(T::from_dec_string(val.to_string())),
box FlatExpression::Number(val),
box FlatExpression::Identifier(FlatVariable::new(key)),
)
})
@ -104,35 +65,15 @@ impl<T: Field> Into<FlatStatement<T>> for Constraint {
}
}
impl<T: Field> Into<FlatFunction<T>> for DirectiveR1CS {
fn into(self: DirectiveR1CS) -> FlatFunction<T> {
let r1cs = self.r1cs;
pub fn sha_round<T: Field>() -> FlatFunction<T> {
let (r1cs, input, current_hash, output) = zokrates_embed::generate_sha256_round_constraints();
let variable_count = r1cs.variable_count;
let input_binding_statements = std::iter::once(FlatStatement::Condition(
FlatVariable::new(0).into(),
FlatExpression::Number(T::from(1)),
))
.chain(r1cs.inputs.iter().enumerate().map(|(index, i)| {
FlatStatement::Condition(
FlatVariable::new(*i).into(),
FlatVariable::new(index + variable_count).into(),
)
}));
// insert flattened statements to represent constraints
let constraint_statements = r1cs.constraints.into_iter().map(|c| c.into());
// define the entire witness
let variables = vec![0; variable_count]
.iter()
.enumerate()
.map(|(i, _)| FlatVariable::new(i))
.collect();
let variable_count = r1cs.aux_count + 1; // auxiliary and ONE
// define the inputs with dummy variables: arguments to the function and to the directive
let input_variables: Vec<FlatVariable> = (0..r1cs.inputs.len())
let input_variables: Vec<FlatVariable> = input
.iter()
.chain(current_hash.iter())
.map(|i| FlatVariable::new(i + variable_count))
.collect();
let arguments = input_variables
@ -147,9 +88,27 @@ impl<T: Field> Into<FlatFunction<T>> for DirectiveR1CS {
.map(|i| FlatExpression::Identifier(i))
.collect();
let input_binding_statements = // bind first variable to ~one
std::iter::once(FlatStatement::Condition(
FlatVariable::new(0).into(),
FlatExpression::Number(T::from(1)),
))
// bind input and current_hash to inputs
.chain(input.iter().chain(current_hash.iter()).map(|i| {
FlatStatement::Condition(
FlatVariable::new(*i).into(),
FlatVariable::new(i + variable_count).into(),
)
}));
// insert flattened statements to represent constraints
let constraint_statements = r1cs.constraints.into_iter().map(|c| c.into());
// define the entire witness
let variables = (0..variable_count).map(|i| FlatVariable::new(i)).collect();
// define which subset of the witness is returned
let outputs: Vec<FlatExpression<T>> = r1cs
.outputs
let outputs: Vec<FlatExpression<T>> = output
.into_iter()
.map(|o| FlatExpression::Identifier(FlatVariable::new(o)))
.collect();
@ -160,13 +119,11 @@ impl<T: Field> Into<FlatFunction<T>> for DirectiveR1CS {
};
// insert a directive to set the witness based on the libsnark gadget and inputs
let directive_statement = match self.directive {
LibsnarkGadgetHelper::Sha256Round => FlatStatement::Directive(DirectiveStatement {
let directive_statement = FlatStatement::Directive(DirectiveStatement {
outputs: variables,
inputs: inputs,
helper: Helper::LibsnarkGadget(LibsnarkGadgetHelper::Sha256Round),
}),
};
helper: Helper::Rust(RustHelper::Sha256Round),
});
// insert a statement to return the subset of the witness
let return_statement = FlatStatement::Return(FlatExpressionList {
@ -186,43 +143,64 @@ impl<T: Field> Into<FlatFunction<T>> for DirectiveR1CS {
signature,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json;
use zokrates_field::field::FieldPrime;
#[test]
fn deserialize_constraint() {
let constraint = r#"[{"2026": "1"}, {"0": "1", "2026": "1751751751751751751751751751751751751751751"}, {"0": "0"}]"#;
let _c: Constraint = serde_json::from_str(constraint).unwrap();
}
#[test]
fn constraint_into_flat_statement() {
let constraint = r#"[{"2026": "1"}, {"0": "1", "2026": "1751751751751751751751751751751751751751751"}, {"0": "0"}]"#;
let c: Constraint = serde_json::from_str(constraint).unwrap();
let _statement: FlatStatement<FieldPrime> = c.into();
}
#[test]
fn generate_sha256_constraints() {
use flat_absy::FlatProg;
use libsnark::get_sha256round_constraints;
let r1cs: R1CS = serde_json::from_str(&get_sha256round_constraints()).unwrap();
let v_count = r1cs.variable_count;
let compiled = sha_round();
let dr1cs: DirectiveR1CS = DirectiveR1CS {
r1cs,
directive: LibsnarkGadgetHelper::Sha256Round,
};
let compiled: FlatProg<FieldPrime> = FlatProg::from(dr1cs);
// function should have a signature of 768 inputs and 256 outputs
assert_eq!(
compiled.signature,
Signature::new()
.inputs(vec![Type::FieldElement; 768])
.outputs(vec![Type::FieldElement; 256])
);
// function should have 768 inputs
assert_eq!(compiled.arguments.len(), 768,);
// function should return 256 values
assert_eq!(
compiled
.statements
.iter()
.filter_map(|s| match s {
FlatStatement::Return(v) => Some(v),
_ => None,
})
.next()
.unwrap()
.expressions
.len(),
256,
);
// directive should take 768 inputs and return n_var outputs
let directive = compiled
.statements
.iter()
.filter_map(|s| match s {
FlatStatement::Directive(d) => Some(d.clone()),
_ => None,
})
.next()
.unwrap();
assert_eq!(directive.inputs.len(), 768);
assert_eq!(directive.outputs.len(), 26935);
// function input should be offset by variable_count
assert_eq!(
compiled.arguments[0].id,
FlatVariable::new(directive.outputs.len() + 1)
);
// libsnark variable #0: index 0 should equal 1
assert_eq!(
compiled.functions[0].statements[1],
compiled.statements[1],
FlatStatement::Condition(
FlatVariable::new(0).into(),
FlatExpression::Number(FieldPrime::from(1))
@ -231,11 +209,25 @@ mod tests {
// libsnark input #0: index 1 should equal zokrates input #0: index v_count
assert_eq!(
compiled.functions[0].statements[2],
FlatStatement::Condition(
FlatVariable::new(1).into(),
FlatVariable::new(v_count).into()
)
compiled.statements[2],
FlatStatement::Condition(FlatVariable::new(1).into(), FlatVariable::new(26936).into())
);
let f = ::ir::Function::from(compiled);
let prog = ::ir::Prog {
main: f,
private: vec![true; 768],
};
//use rand::Rng;
// let mut rng = rand::thread_rng();
// let input: Vec<_> = (0..768).map(|_| {
// rng.gen_range(0, 2)
// }).collect();
let input = (0..512).map(|_| 0).chain((0..256).map(|_| 1)).collect();
prog.execute(&input).unwrap();
}
}

10
zokrates_embed/Cargo.toml Normal file
View file

@ -0,0 +1,10 @@
[package]
name = "zokrates_embed"
version = "0.1.0"
authors = ["schaeff <thibaut@schaeff.fr>"]
edition = "2018"
[dependencies]
sapling-crypto = { git = 'https://github.com/matterinc/sapling-crypto', tag = "0.0.4" }
bellman = { git = 'https://github.com/matterinc/bellman', tag = "0.2.0" }
zokrates_field = { path = "../zokrates_field" }

412
zokrates_embed/src/lib.rs Normal file
View file

@ -0,0 +1,412 @@
use bellman::pairing::Engine;
use bellman::ConstraintSystem;
use bellman::{Index, LinearCombination, SynthesisError, Variable};
use sapling_crypto::circuit::boolean::{AllocatedBit, Boolean};
use sapling_crypto::circuit::sha256::sha256_compression_function;
use sapling_crypto::circuit::uint32::UInt32;
use zokrates_field::field::Field;
#[derive(Debug)]
struct BellmanR1CS<E: Engine> {
aux_count: usize,
constraints: Vec<BellmanConstraint<E>>,
}
impl<E: Engine> BellmanR1CS<E> {
pub fn new() -> Self {
BellmanR1CS {
aux_count: 0,
constraints: vec![],
}
}
}
#[derive(Debug)]
struct BellmanWitness<E: Engine> {
pub values: Vec<E::Fr>,
}
#[derive(Debug, PartialEq)]
struct BellmanConstraint<E: Engine> {
pub a: Vec<(usize, E::Fr)>,
pub b: Vec<(usize, E::Fr)>,
pub c: Vec<(usize, E::Fr)>,
}
#[derive(Debug, PartialEq)]
pub struct Constraint<T: Field> {
pub a: Vec<(usize, T)>,
pub b: Vec<(usize, T)>,
pub c: Vec<(usize, T)>,
}
#[derive(Debug)]
pub struct R1CS<T: Field> {
pub aux_count: usize,
pub constraints: Vec<Constraint<T>>,
}
fn sha256_round<T: Field, CS: ConstraintSystem<T::BellmanEngine>>(
mut cs: CS,
input: Option<&Vec<T>>,
current_hash: Option<&Vec<T>>,
) -> Result<(Vec<usize>, Vec<usize>, Vec<usize>), SynthesisError> {
let input_bits = (0..512)
.map(|i| {
AllocatedBit::alloc::<T::BellmanEngine, _>(
&mut cs.namespace(|| format!("input_{}", i)),
Some(input.as_ref().unwrap()[i] == T::from(1)),
)
.unwrap()
})
.collect::<Vec<_>>();
let input = input_bits
.iter()
.map(|i| Boolean::Is(i.clone()))
.collect::<Vec<_>>();
let current_hash_bits = (0..256)
.map(|i| {
AllocatedBit::alloc::<T::BellmanEngine, _>(
&mut cs.namespace(|| format!("current_hash_{}", i)),
Some(current_hash.as_ref().unwrap()[i] == T::from(1)),
)
.unwrap()
})
.collect::<Vec<_>>();
let current_hash = current_hash_bits
.chunks(32)
.map(|chunk| {
UInt32::from_bits_be(
&chunk
.into_iter()
.map(|i| Boolean::Is(i.clone()))
.collect::<Vec<_>>(),
)
})
.collect::<Vec<_>>();
let res =
sha256_compression_function::<T::BellmanEngine, _>(&mut cs, &input, &current_hash).unwrap();
let output_bits = res
.into_iter()
.flat_map(|u| u.into_bits_be())
.map(|b| b.get_variable().unwrap().clone())
.collect::<Vec<_>>();
Ok((
input_bits
.into_iter()
.map(|b| BellmanR1CS::<T::BellmanEngine>::var_to_index(b.get_variable()))
.collect(),
current_hash_bits
.into_iter()
.map(|b| BellmanR1CS::<T::BellmanEngine>::var_to_index(b.get_variable()))
.collect(),
output_bits
.into_iter()
.map(|b| BellmanR1CS::<T::BellmanEngine>::var_to_index(b.get_variable()))
.collect(),
))
}
impl<T: Field> R1CS<T> {
fn from_bellman(cs: BellmanR1CS<T::BellmanEngine>) -> Self {
R1CS {
aux_count: cs.aux_count,
constraints: cs
.constraints
.into_iter()
.map(|c| Constraint::from_bellman(c))
.collect(),
}
}
}
impl<T: Field> Constraint<T> {
fn from_bellman(cs: BellmanConstraint<T::BellmanEngine>) -> Self {
let res = Constraint {
a: cs
.a
.into_iter()
.map(|(variable, coefficient)| (variable, T::from_bellman(coefficient)))
.collect(),
b: cs
.b
.into_iter()
.map(|(variable, coefficient)| (variable, T::from_bellman(coefficient)))
.collect(),
c: cs
.c
.into_iter()
.map(|(variable, coefficient)| (variable, T::from_bellman(coefficient)))
.collect(),
};
res
}
}
impl<E: Engine> ConstraintSystem<E> for BellmanWitness<E> {
type Root = Self;
fn alloc<F, A, AR>(&mut self, _annotation: A, f: F) -> Result<Variable, SynthesisError>
where
F: FnOnce() -> Result<E::Fr, SynthesisError>,
A: FnOnce() -> AR,
AR: Into<String>,
{
// we only care about the value
let index = self.values.len();
let var = Variable::new_unchecked(Index::Aux(index));
self.values.push(f().unwrap());
Ok(var)
}
fn alloc_input<F, A, AR>(&mut self, _annotation: A, _f: F) -> Result<Variable, SynthesisError>
where
F: FnOnce() -> Result<E::Fr, SynthesisError>,
A: FnOnce() -> AR,
AR: Into<String>,
{
unreachable!("Bellman helpers are not allowed to allocate public variables")
}
fn enforce<A, AR, LA, LB, LC>(&mut self, _annotation: A, _a: LA, _b: LB, _c: LC)
where
A: FnOnce() -> AR,
AR: Into<String>,
LA: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
LB: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
LC: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
{
// do nothing
}
fn push_namespace<NR, N>(&mut self, _name_fn: N)
where
NR: Into<String>,
N: FnOnce() -> NR,
{
// do nothing
}
fn pop_namespace(&mut self) {
// do nothing
}
fn get_root(&mut self) -> &mut Self::Root {
self
}
}
impl<E: Engine> ConstraintSystem<E> for BellmanR1CS<E> {
type Root = Self;
fn alloc<F, A, AR>(&mut self, _annotation: A, _f: F) -> Result<Variable, SynthesisError>
where
F: FnOnce() -> Result<E::Fr, SynthesisError>,
A: FnOnce() -> AR,
AR: Into<String>,
{
// we don't care about the value as we're only getting the CS
let index = self.aux_count;
let var = Variable::new_unchecked(Index::Aux(index));
self.aux_count += 1;
Ok(var)
}
fn alloc_input<F, A, AR>(&mut self, _annotation: A, _f: F) -> Result<Variable, SynthesisError>
where
F: FnOnce() -> Result<E::Fr, SynthesisError>,
A: FnOnce() -> AR,
AR: Into<String>,
{
unreachable!("Bellman helpers are not allowed to allocate public variables")
}
fn enforce<A, AR, LA, LB, LC>(&mut self, _annotation: A, a: LA, b: LB, c: LC)
where
A: FnOnce() -> AR,
AR: Into<String>,
LA: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
LB: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
LC: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
{
let a = a(LinearCombination::zero());
let b = b(LinearCombination::zero());
let c = c(LinearCombination::zero());
let a = a
.as_ref()
.into_iter()
.map(|(variable, coefficient)| {
(BellmanR1CS::<E>::var_to_index(*variable), *coefficient)
})
.collect();
let b = b
.as_ref()
.into_iter()
.map(|(variable, coefficient)| {
(BellmanR1CS::<E>::var_to_index(*variable), *coefficient)
})
.collect();
let c = c
.as_ref()
.into_iter()
.map(|(variable, coefficient)| {
(BellmanR1CS::<E>::var_to_index(*variable), *coefficient)
})
.collect();
self.constraints.push(BellmanConstraint { a, b, c });
}
fn push_namespace<NR, N>(&mut self, _name_fn: N)
where
NR: Into<String>,
N: FnOnce() -> NR,
{
// do nothing
}
fn pop_namespace(&mut self) {
// do nothing
}
fn get_root(&mut self) -> &mut Self::Root {
self
}
}
pub fn generate_xor_constraints<T: Field>() -> (R1CS<T>, usize) {
let mut cs = BellmanR1CS::new();
let i0 = Boolean::Is(AllocatedBit::alloc::<T::BellmanEngine, _>(&mut cs, None).unwrap());
let i1 = Boolean::Is(AllocatedBit::alloc::<T::BellmanEngine, _>(&mut cs, None).unwrap());
let res = Boolean::xor(&mut cs, &i0, &i1).unwrap();
let res =
BellmanR1CS::<T::BellmanEngine>::var_to_index(res.get_variable().unwrap().get_variable());
let cs = R1CS::from_bellman(cs);
(cs, res)
}
pub fn generate_xor_witness<T: Field>(i1: bool, i2: bool) -> Vec<T> {
let mut cs = BellmanWitness {
values: vec![T::from(1).into_bellman()],
};
let i0 = Boolean::Is(AllocatedBit::alloc::<T::BellmanEngine, _>(&mut cs, Some(i1)).unwrap());
let i1 = Boolean::Is(AllocatedBit::alloc::<T::BellmanEngine, _>(&mut cs, Some(i2)).unwrap());
Boolean::xor(&mut cs, &i0, &i1).unwrap();
cs.values.into_iter().map(|v| T::from_bellman(v)).collect()
}
pub fn generate_sha256_round_constraints<T: Field>() -> (R1CS<T>, Vec<usize>, Vec<usize>, Vec<usize>)
{
let mut cs = BellmanR1CS::new();
let (input_bits, current_hash_bits, output_bits) = sha256_round::<T, _>(
&mut cs,
Some(&vec![T::from(0); 512]),
Some(&vec![T::from(0); 256]),
)
.unwrap();
// res is now the allocated bits for input, current_hash and sha256_output
let cs = R1CS::<T>::from_bellman(cs);
(cs, input_bits, current_hash_bits, output_bits)
}
pub fn generate_sha256_round_witness<T: Field>(input: &[T], current_hash: &[T]) -> Vec<T> {
assert_eq!(input.len(), 512);
assert_eq!(current_hash.len(), 256);
let mut cs = BellmanWitness {
values: vec![T::from(1).into_bellman()],
};
sha256_round(&mut cs, Some(&input.to_vec()), Some(&current_hash.to_vec())).unwrap();
cs.values.into_iter().map(|v| T::from_bellman(v)).collect()
}
impl<E: Engine> BellmanR1CS<E> {
fn var_to_index(v: Variable) -> usize {
match v.get_unchecked() {
Index::Aux(i) => i + 1,
Index::Input(0) => 0,
_ => unreachable!(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use zokrates_field::field::FieldPrime;
#[test]
fn generate_constraints() {
let (_c, input, current_hash, output) = generate_sha256_round_constraints::<FieldPrime>();
assert_eq!(input.len(), 512);
assert_eq!(current_hash.len(), 256);
assert_eq!(output.len(), 256);
}
#[test]
fn generate_witness() {
let witness = generate_sha256_round_witness(
&vec![FieldPrime::from(0); 512],
&vec![FieldPrime::from(0); 256],
);
assert_eq!(witness.len(), 26935);
}
#[test]
fn xor() {
let (_, indice) = generate_xor_constraints::<FieldPrime>();
assert_eq!(
FieldPrime::from(0),
generate_xor_witness::<FieldPrime>(true, true)[indice]
);
assert_eq!(
FieldPrime::from(1),
generate_xor_witness::<FieldPrime>(true, false)[indice]
);
assert_eq!(
FieldPrime::from(1),
generate_xor_witness::<FieldPrime>(false, true)[indice]
);
assert_eq!(
FieldPrime::from(0),
generate_xor_witness::<FieldPrime>(false, false)[indice]
);
}
#[test]
fn test_cs() {
use sapling_crypto::circuit::test::TestConstraintSystem;
let mut cs = TestConstraintSystem::new();
let _ = sha256_round::<FieldPrime, _>(
&mut cs,
Some(&vec![FieldPrime::from(0); 512]),
Some(&vec![FieldPrime::from(1); 256]),
)
.unwrap();
assert!(cs.is_satisfied());
}
}

View file

@ -1,84 +0,0 @@
use crate::field::{Field, FieldPrime};
use ff::{PrimeField, PrimeFieldRepr};
use pairing::bn256::Fr;
impl From<FieldPrime> for Fr {
fn from(e: FieldPrime) -> Fr {
let s = e.to_dec_string();
Fr::from_str(&s).unwrap()
}
}
impl From<Fr> for FieldPrime {
fn from(e: Fr) -> FieldPrime {
let mut res: Vec<u8> = vec![];
e.into_repr().write_le(&mut res).unwrap();
FieldPrime::from_byte_vector(res)
}
}
#[cfg(test)]
mod tests {
use super::*;
use ff::Field;
extern crate rand;
use rand::{thread_rng, Rng};
#[test]
fn fr_to_field_to_fr() {
let rng = &mut thread_rng();
let a: Fr = rng.gen();
assert_eq!(Fr::from(FieldPrime::from(a)), a);
}
#[test]
fn field_to_fr_to_field() {
// use Fr to get a random element
let rng = &mut thread_rng();
let a: Fr = rng.gen();
// now test idempotence
let a = FieldPrime::from(a);
assert_eq!(FieldPrime::from(Fr::from(a.clone())), a);
}
#[test]
fn one() {
let a = FieldPrime::from(1);
assert_eq!(Fr::from(a), Fr::one());
}
#[test]
fn zero() {
let a = FieldPrime::from(0);
assert_eq!(Fr::from(a), Fr::zero());
}
#[test]
fn minus_one() {
let mut a: Fr = Fr::one();
a.negate();
assert_eq!(FieldPrime::from(a), FieldPrime::from(-1));
}
#[test]
fn add() {
let rng = &mut thread_rng();
let mut a: Fr = rng.gen();
let b: Fr = rng.gen();
let aa = FieldPrime::from(a);
let bb = FieldPrime::from(b);
let cc = aa + bb;
a.add_assign(&b);
assert_eq!(FieldPrime::from(a), cc);
}
}

View file

@ -8,6 +8,9 @@ use lazy_static::lazy_static;
use num_bigint::{BigInt, BigUint, Sign, ToBigInt};
use num_integer::Integer;
use num_traits::{Num, One, Zero};
use pairing::bn256::Bn256;
use pairing::ff::ScalarEngine;
use pairing::Engine;
use serde_derive::{Deserialize, Serialize};
use std::convert::From;
use std::fmt;
@ -53,6 +56,22 @@ pub trait Field:
+ Pow<Self, Output = Self>
+ for<'a> Pow<&'a Self, Output = Self>
{
/// An associated type to be able to operate with Bellman ff traits
type BellmanEngine: Engine;
fn from_bellman(e: <Self::BellmanEngine as ScalarEngine>::Fr) -> Self {
use ff::{PrimeField, PrimeFieldRepr};
let mut res: Vec<u8> = vec![];
e.into_repr().write_le(&mut res).unwrap();
Self::from_byte_vector(res)
}
fn into_bellman(self) -> <Self::BellmanEngine as ScalarEngine>::Fr {
use ff::PrimeField;
let s = self.to_dec_string();
<Self::BellmanEngine as ScalarEngine>::Fr::from_str(&s).unwrap()
}
/// Returns this `Field`'s contents as little-endian byte vector
fn into_byte_vector(&self) -> Vec<u8>;
/// Returns an element of this `Field` from a little-endian byte vector
@ -82,6 +101,8 @@ pub struct FieldPrime {
}
impl Field for FieldPrime {
type BellmanEngine = Bn256;
fn into_byte_vector(&self) -> Vec<u8> {
match self.value.to_biguint() {
Option::Some(val) => val.to_bytes_le(),
@ -716,4 +737,74 @@ mod tests {
s_field
);
}
mod bellman {
use super::*;
use ff::Field as FField;
extern crate rand;
use pairing::bn256::Fr;
use rand::{thread_rng, Rng};
use Field;
#[test]
fn fr_to_field_to_fr() {
let rng = &mut thread_rng();
for _ in 0..1000 {
let a: Fr = rng.gen();
assert_eq!(FieldPrime::from_bellman(a).into_bellman(), a);
}
}
#[test]
fn field_to_fr_to_field() {
// use Fr to get a random element
let rng = &mut thread_rng();
for _ in 0..1000 {
let a: Fr = rng.gen();
// now test idempotence
let a = FieldPrime::from_bellman(a);
assert_eq!(FieldPrime::from_bellman(a.clone().into_bellman()), a);
}
}
#[test]
fn one() {
let a = FieldPrime::from(1);
assert_eq!(a.into_bellman(), Fr::one());
}
#[test]
fn zero() {
let a = FieldPrime::from(0);
assert_eq!(a.into_bellman(), Fr::zero());
}
#[test]
fn minus_one() {
let mut a: Fr = Fr::one();
a.negate();
assert_eq!(FieldPrime::from_bellman(a), FieldPrime::from(-1));
}
#[test]
fn add() {
let rng = &mut thread_rng();
let mut a: Fr = rng.gen();
let b: Fr = rng.gen();
let aa = FieldPrime::from_bellman(a);
let bb = FieldPrime::from_bellman(b);
let cc = aa + bb;
a.add_assign(&b);
assert_eq!(FieldPrime::from_bellman(a), cc);
}
}
}

View file

@ -1,2 +1 @@
mod conversion;
pub mod field;

View file

@ -1,4 +1,4 @@
import "LIBSNARK/sha256round" as sha256
import "BELLMAN/sha256round" as sha256
// a and b is NOT checked to be of type bool
// IV vector is checked to be of type bool
def main(field[256] a, field[256] b, field[256] IV) -> (field[256]):