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

merge dev, fix conflicts, remove base64 crate

This commit is contained in:
dark64 2020-04-14 21:06:14 +02:00
commit edd7b5bbd1
38 changed files with 2182 additions and 699 deletions

View file

@ -57,6 +57,14 @@ jobs:
# - run:
# name: Generate code coverage report
# command: ./scripts/cov.sh
cpp_format:
docker:
- image: dark64/clang-format-checker:env
steps:
- checkout
- run:
name: Check cpp format (clang-format)
command: run-clang-format.py -r $(pwd)/zokrates_core/lib
wasm_test:
docker:
- image: rustlang/rust:nightly-slim
@ -133,6 +141,7 @@ workflows:
jobs:
- build
- test
- cpp_format
- wasm_test
- integration_test
- zokrates_js_build
@ -145,6 +154,7 @@ workflows:
requires:
- build
- test
- cpp_format
- wasm_test
- integration_test
- zokrates_js_build

287
Cargo.lock generated
View file

@ -60,9 +60,9 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
[[package]]
name = "backtrace"
version = "0.3.45"
version = "0.3.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad235dabf00f36301792cfe82499880ba54c6486be094d1047b02bacb67c14e8"
checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e"
dependencies = [
"backtrace-sys",
"cfg-if",
@ -72,49 +72,25 @@ dependencies = [
[[package]]
name = "backtrace-sys"
version = "0.1.34"
version = "0.1.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca797db0057bae1a7aa2eef3283a874695455cecf08a43bfb8507ee0ebc1ed69"
checksum = "7de8aba10a69c8e8d7622c5710229485ec32e9d55fdad160ea559c086fdcd118"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "base64"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5ca2cd0adc3f48f9e9ea5a6bbdf9ccc0bfade884847e484d452414c7ccffb3"
[[package]]
name = "bellman_ce"
version = "0.3.1"
source = "git+https://github.com/matter-labs/bellman?rev=9e35737#9e35737209d4afc2e69af1e0d7cbe6d02e32aecf"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0300152b8d0c0220c70a39d6da08adff84352f5dd28d91944bc60e9dc8cbebb9"
dependencies = [
"bit-vec",
"byteorder",
"cfg-if",
"crossbeam",
"futures",
"futures-cpupool",
"num_cpus",
"pairing_ce",
"rand 0.4.6",
"web-sys",
]
[[package]]
name = "bellman_ce"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "938ec0feff00f9dfda0e7cbfe8db8b717966a84f6a12e63ed0943c4a90d6a5de"
dependencies = [
"bit-vec",
"byteorder",
"cfg-if",
"crossbeam",
"futures",
"futures-cpupool",
"num_cpus",
"pairing_ce",
"rand 0.4.6",
@ -134,9 +110,9 @@ dependencies = [
[[package]]
name = "bit-vec"
version = "0.4.4"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f"
checksum = "a4523a10839ffae575fb08aa3423026c8cb4687eef43952afb956229d4f246f7"
[[package]]
name = "bitflags"
@ -190,9 +166,9 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.2.0"
version = "3.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742"
checksum = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187"
[[package]]
name = "byte-tools"
@ -452,9 +428,9 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231"
dependencies = [
"proc-macro2 1.0.9",
"proc-macro2 1.0.10",
"quote 1.0.3",
"syn 1.0.16",
"syn 1.0.17",
"synstructure",
]
@ -466,28 +442,28 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "ff_ce"
version = "0.7.1"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18af1ea1b80a4b474fae13af4c58cf0a5a2bc33832d5fa70f68a4b286178fdb5"
checksum = "83c0a6a2c53b0bd6d8cae976816dc8a171e0554c03f304e3dac110473e0219fd"
dependencies = [
"byteorder",
"ff_derive_ce",
"hex 0.3.2",
"hex",
"rand 0.4.6",
]
[[package]]
name = "ff_derive_ce"
version = "0.5.1"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d245b4e76c5b36bb7721ea15b7fbc61bebf0c5d2890eaf49fe1e2a3eed36db9"
checksum = "7543567f0c51910363eb5706ee2f5368a64e79a8ae607d0332aa60bae03a1bb1"
dependencies = [
"num-bigint 0.2.6",
"num-integer",
"num-traits 0.2.11",
"proc-macro2 0.4.30",
"quote 0.6.13",
"syn 0.14.9",
"proc-macro2 1.0.10",
"quote 1.0.3",
"syn 1.0.17",
]
[[package]]
@ -514,20 +490,81 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "futures"
version = "0.1.29"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef"
checksum = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-cpupool"
version = "0.1.8"
name = "futures-channel"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
checksum = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8"
dependencies = [
"futures",
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a"
[[package]]
name = "futures-executor"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
"num_cpus",
]
[[package]]
name = "futures-io"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6"
[[package]]
name = "futures-sink"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6"
[[package]]
name = "futures-task"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27"
[[package]]
name = "futures-util"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-sink",
"futures-task",
"memchr",
"pin-utils",
"slab",
]
[[package]]
name = "generic-array"
version = "0.12.3"
@ -550,9 +587,9 @@ dependencies = [
[[package]]
name = "git2"
version = "0.13.1"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef222034f2069cfc5af01ce423574d3d9a3925bd4052912a14e5bcfd7ca9e47a"
checksum = "2cfb93ca10f2934069c3aaafb753fbe0663f08ee009a01b6d62e062391447b15"
dependencies = [
"bitflags",
"libc",
@ -577,19 +614,13 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "hermit-abi"
version = "0.1.8"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8"
checksum = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e"
dependencies = [
"libc",
]
[[package]]
name = "hex"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
[[package]]
name = "hex"
version = "0.4.2"
@ -633,9 +664,9 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.36"
version = "0.3.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cb931d43e71f560c81badb0191596562bafad2be06a3f9025b845c847c60df5"
checksum = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055"
dependencies = [
"wasm-bindgen",
]
@ -654,9 +685,9 @@ checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
[[package]]
name = "libgit2-sys"
version = "0.12.2+1.0.0"
version = "0.12.3+1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a12c878ccc1a49ff71e264233a66d2114cdcc7fdc44c0ebe2b54075240831238"
checksum = "7637dc15e7f05a16011723e0448655081fc01a374bcd368e2c9b9c7f5c5ab3ea"
dependencies = [
"cc",
"libc",
@ -849,9 +880,9 @@ dependencies = [
[[package]]
name = "pairing_ce"
version = "0.18.0"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f075a9c570e2026111cb6dddf6a320e5163c42aa32500b315ec34acbcf7c9b36"
checksum = "6c7b23aa7f0489d9a5e8e15cc5b7cb4f3e9b9d64812b8875fb91d25b640b0939"
dependencies = [
"byteorder",
"ff_ce",
@ -904,9 +935,9 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
dependencies = [
"pest",
"pest_meta",
"proc-macro2 1.0.9",
"proc-macro2 1.0.10",
"quote 1.0.3",
"syn 1.0.16",
"syn 1.0.17",
]
[[package]]
@ -920,6 +951,12 @@ dependencies = [
"sha-1",
]
[[package]]
name = "pin-utils"
version = "0.1.0-alpha.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
[[package]]
name = "pkg-config"
version = "0.3.17"
@ -943,9 +980,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.9"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
dependencies = [
"unicode-xid 0.2.0",
]
@ -974,7 +1011,7 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
dependencies = [
"proc-macro2 1.0.9",
"proc-macro2 1.0.10",
]
[[package]]
@ -1134,7 +1171,7 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec318b68765114e578fe42446b6861565b302bc93089aa01669d19417a6de993"
dependencies = [
"bellman_ce 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bellman_ce",
"blake2-rfc_bellman_edition",
"byteorder",
"digest",
@ -1175,9 +1212,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.105"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff"
checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399"
[[package]]
name = "serde_bytes"
@ -1190,20 +1227,20 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.105"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8"
checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c"
dependencies = [
"proc-macro2 1.0.9",
"proc-macro2 1.0.10",
"quote 1.0.3",
"syn 1.0.16",
"syn 1.0.17",
]
[[package]]
name = "serde_json"
version = "1.0.48"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25"
checksum = "da07b57ee2623368351e9a0488bb0b261322a15a6e0ae53e243cbdc0f4208da9"
dependencies = [
"itoa",
"ryu",
@ -1259,6 +1296,12 @@ dependencies = [
"walkdir",
]
[[package]]
name = "slab"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
[[package]]
name = "smallvec"
version = "1.2.0"
@ -1271,17 +1314,6 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "syn"
version = "0.14.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
dependencies = [
"proc-macro2 0.4.30",
"quote 0.6.13",
"unicode-xid 0.1.0",
]
[[package]]
name = "syn"
version = "0.15.44"
@ -1295,11 +1327,11 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.16"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859"
checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
dependencies = [
"proc-macro2 1.0.9",
"proc-macro2 1.0.10",
"quote 1.0.3",
"unicode-xid 0.2.0",
]
@ -1310,9 +1342,9 @@ version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
dependencies = [
"proc-macro2 1.0.9",
"proc-macro2 1.0.10",
"quote 1.0.3",
"syn 1.0.16",
"syn 1.0.17",
"unicode-xid 0.2.0",
]
@ -1360,9 +1392,9 @@ dependencies = [
[[package]]
name = "tiny-keccak"
version = "2.0.1"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2953ca5148619bc99695c1274cb54c5275bbb913c6adad87e72eaf8db9787f69"
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
dependencies = [
"crunchy",
]
@ -1487,9 +1519,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]]
name = "wasm-bindgen"
version = "0.2.59"
version = "0.2.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3557c397ab5a8e347d434782bcd31fc1483d927a6826804cec05cc792ee2519d"
checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@ -1497,24 +1529,24 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.59"
version = "0.2.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0da9c9a19850d3af6df1cb9574970b566d617ecfaf36eb0b706b6f3ef9bd2f8"
checksum = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2 1.0.9",
"proc-macro2 1.0.10",
"quote 1.0.3",
"syn 1.0.16",
"syn 1.0.17",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.9"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "457414a91863c0ec00090dba537f88ab955d93ca6555862c29b6d860990b8a8a"
checksum = "7add542ea1ac7fdaa9dc25e031a6af33b7d63376292bd24140c637d00d1c312a"
dependencies = [
"cfg-if",
"js-sys",
@ -1524,9 +1556,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.59"
version = "0.2.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f6fde1d36e75a714b5fe0cffbb78978f222ea6baebb726af13c78869fdb4205"
checksum = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4"
dependencies = [
"quote 1.0.3",
"wasm-bindgen-macro-support",
@ -1534,28 +1566,28 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.59"
version = "0.2.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25bda4168030a6412ea8a047e27238cadf56f0e53516e1e83fec0a8b7c786f6d"
checksum = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931"
dependencies = [
"proc-macro2 1.0.9",
"proc-macro2 1.0.10",
"quote 1.0.3",
"syn 1.0.16",
"syn 1.0.17",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.59"
version = "0.2.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc9f36ad51f25b0219a3d4d13b90eb44cd075dff8b6280cca015775d7acaddd8"
checksum = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639"
[[package]]
name = "wasm-bindgen-test"
version = "0.3.9"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "449aeba7035e4a4710cd263bbac33519fa3828bff1c6f642fa8896601e7016ad"
checksum = "648da3460c6d2aa04b715a936329e2e311180efe650b2127d6267f4193ccac14"
dependencies = [
"console_error_panic_hook",
"js-sys",
@ -1567,19 +1599,19 @@ dependencies = [
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.9"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49449f8dcedc192bd0cf11b5711982decdd4dbad1029f92370e2b1215031dd59"
checksum = "cf2f86cd78a2aa7b1fb4bb6ed854eccb7f9263089c79542dca1576a1518a8467"
dependencies = [
"proc-macro2 1.0.9",
"proc-macro2 1.0.10",
"quote 1.0.3",
]
[[package]]
name = "web-sys"
version = "0.3.36"
version = "0.3.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "721c6263e2c66fd44501cc5efbfa2b7dfa775d13e4ea38c46299646ed1f9c70a"
checksum = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb"
dependencies = [
"js-sys",
"wasm-bindgen",
@ -1603,9 +1635,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.3"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80"
checksum = "fa515c5163a99cc82bab70fd3bfdd36d827be85de63737b40fcef2ce084a436e"
dependencies = [
"winapi",
]
@ -1654,8 +1686,7 @@ name = "zokrates_core"
version = "0.4.2"
dependencies = [
"assert_cli",
"base64",
"bellman_ce 0.3.1 (git+https://github.com/matter-labs/bellman?rev=9e35737)",
"bellman_ce",
"bincode",
"cc",
"cmake",
@ -1663,7 +1694,7 @@ dependencies = [
"ff_ce",
"git2",
"glob 0.2.11",
"hex 0.4.2",
"hex",
"lazy_static",
"num",
"num-bigint 0.1.44",
@ -1695,7 +1726,7 @@ dependencies = [
name = "zokrates_embed"
version = "0.1.1"
dependencies = [
"bellman_ce 0.3.1 (git+https://github.com/matter-labs/bellman?rev=9e35737)",
"bellman_ce",
"sapling-crypto_ce",
]

8
scripts/clang-format.sh Executable file
View file

@ -0,0 +1,8 @@
#!/bin/bash
# Usage: ./clang-format.sh zokrates_core/lib
dir=$1
for file in $dir/*.cpp $dir/*.hpp; do
clang-format -i -style=WebKit -verbose $file
done

View file

@ -4,7 +4,7 @@ def lt(field a,field b) -> (field):
def cutoff() -> (field):
return 31337
def getThing(index) -> (field):
def getThing(field index) -> (field):
field result = 3
result = if index == 0 then 13 else result fi
result = if index == 1 then 23 else result fi

View file

@ -719,12 +719,18 @@ mod tests {
#[test]
fn examples() {
for p in glob("./examples/**/*.zok").expect("Failed to read glob pattern") {
for p in glob("./examples/**/*").expect("Failed to read glob pattern") {
let path = match p {
Ok(x) => x,
Err(why) => panic!("Error: {:?}", why),
};
if !path.is_file() {
continue;
}
assert!(path.extension().expect("extension expected") == "zok");
if path.to_str().unwrap().contains("error") {
continue;
}
@ -747,7 +753,7 @@ mod tests {
#[test]
fn examples_with_input_success() {
//these examples should compile and run
for p in glob("./examples/test*.zok").expect("Failed to read glob pattern") {
for p in glob("./examples/test*").expect("Failed to read glob pattern") {
let path = match p {
Ok(x) => x,
Err(why) => panic!("Error: {:?}", why),
@ -775,7 +781,7 @@ mod tests {
#[should_panic]
fn examples_with_input_failure() {
//these examples should compile but not run
for p in glob("./examples/runtime_errors/*.zok").expect("Failed to read glob pattern") {
for p in glob("./examples/runtime_errors/*").expect("Failed to read glob pattern") {
let path = match p {
Ok(x) => x,
Err(why) => panic!("Error: {:?}", why),

View file

@ -25,17 +25,16 @@ serde_json = "1.0"
serde_bytes = "0.10"
bincode = "0.8.0"
hex = "0.4.2"
base64 = "0.12.0"
regex = "0.2"
pairing_ce = "0.18"
ff_ce = "0.7"
pairing_ce = "0.20"
ff_ce = "0.9"
zokrates_field = { version = "0.3.0", path = "../zokrates_field" }
zokrates_pest_ast = { version = "0.1.0", path = "../zokrates_pest_ast" }
zokrates_embed = { path = "../zokrates_embed" }
zokrates_common = { path = "../zokrates_common" }
rand = "0.4"
csv = "1"
bellman_ce = { git = "https://github.com/matter-labs/bellman", rev = "9e35737", default-features = false }
bellman_ce = { version = "0.3.3", default-features = false}
[dev-dependencies]
glob = "0.2.11"

View file

@ -156,76 +156,83 @@ fn statements_from_statement<'ast, T: Field>(
pest::Statement::Definition(s) => statements_from_definition(s),
pest::Statement::Iteration(s) => vec![absy::StatementNode::from(s)],
pest::Statement::Assertion(s) => vec![absy::StatementNode::from(s)],
pest::Statement::Assignment(s) => vec![absy::StatementNode::from(s)],
pest::Statement::Return(s) => vec![absy::StatementNode::from(s)],
pest::Statement::MultiAssignment(s) => statements_from_multi_assignment(s),
}
}
fn statements_from_multi_assignment<'ast, T: Field>(
assignment: pest::MultiAssignmentStatement<'ast>,
) -> Vec<absy::StatementNode<T>> {
use absy::NodeValue;
let declarations = assignment
.lhs
.clone()
.into_iter()
.filter(|i| i.ty.is_some())
.map(|i| {
absy::Statement::Declaration(
absy::Variable::new(
i.id.span.as_str(),
absy::UnresolvedTypeNode::from(i.ty.unwrap()),
)
.span(i.id.span),
)
.span(i.span)
});
let lhs = assignment
.lhs
.into_iter()
.map(|i| absy::Assignee::Identifier(i.id.span.as_str()).span(i.id.span))
.collect();
let multi_def = absy::Statement::MultipleDefinition(
lhs,
absy::Expression::FunctionCall(
&assignment.function_id.span.as_str(),
assignment
.arguments
.into_iter()
.map(|e| absy::ExpressionNode::from(e))
.collect(),
)
.span(assignment.function_id.span),
)
.span(assignment.span);
declarations.chain(std::iter::once(multi_def)).collect()
}
fn statements_from_definition<'ast, T: Field>(
definition: pest::DefinitionStatement<'ast>,
) -> Vec<absy::StatementNode<T>> {
use absy::NodeValue;
vec![
absy::Statement::Declaration(
absy::Variable::new(
definition.id.span.as_str(),
absy::UnresolvedTypeNode::from(definition.ty),
let lhs = definition.lhs;
match lhs.len() {
1 => {
// Definition or assignment
let a = lhs[0].clone();
let e: absy::ExpressionNode<T> = absy::ExpressionNode::from(definition.expression);
let s = match e.value {
absy::Expression::FunctionCall(..) => absy::Statement::MultipleDefinition(
vec![absy::AssigneeNode::from(a.a.clone())],
e,
),
_ => absy::Statement::Definition(absy::AssigneeNode::from(a.a.clone()), e),
};
match a.ty {
Some(ty) => {
assert_eq!(a.a.accesses.len(), 0);
let declaration = absy::Statement::Declaration(
absy::Variable::new(
a.a.id.span.as_str(),
absy::UnresolvedTypeNode::from(ty),
)
.span(a.a.id.span.clone()),
)
.span(definition.span.clone());
vec![declaration, s.span(definition.span)]
}
None => {
// Assignment
vec![s.span(definition.span)]
}
}
}
_ => {
// Multidefinition
let declarations = lhs.clone().into_iter().filter(|i| i.ty.is_some()).map(|a| {
let ty = a.ty;
let a = a.a;
assert_eq!(a.accesses.len(), 0);
absy::Statement::Declaration(
absy::Variable::new(
a.id.span.as_str(),
absy::UnresolvedTypeNode::from(ty.unwrap()),
)
.span(a.id.span),
)
.span(a.span)
});
let lhs = lhs
.into_iter()
.map(|i| absy::Assignee::Identifier(i.a.id.span.as_str()).span(i.a.id.span))
.collect();
let multi_def = absy::Statement::MultipleDefinition(
lhs,
absy::ExpressionNode::from(definition.expression),
)
.span(definition.id.span.clone()),
)
.span(definition.span.clone()),
absy::Statement::Definition(
absy::AssigneeNode::from(definition.id),
absy::ExpressionNode::from(definition.expression),
)
.span(definition.span),
]
.span(definition.span);
declarations.chain(std::iter::once(multi_def)).collect()
}
}
}
impl<'ast, T: Field> From<pest::ReturnStatement<'ast>> for absy::StatementNode<'ast, T> {
@ -289,18 +296,6 @@ impl<'ast, T: Field> From<pest::IterationStatement<'ast>> for absy::StatementNod
}
}
impl<'ast, T: Field> From<pest::AssignmentStatement<'ast>> for absy::StatementNode<'ast, T> {
fn from(statement: pest::AssignmentStatement<'ast>) -> absy::StatementNode<T> {
use absy::NodeValue;
absy::Statement::Definition(
absy::AssigneeNode::from(statement.assignee),
absy::ExpressionNode::from(statement.expression),
)
.span(statement.span)
}
}
impl<'ast, T: Field> From<pest::Expression<'ast>> for absy::ExpressionNode<'ast, T> {
fn from(expression: pest::Expression<'ast>) -> absy::ExpressionNode<'ast, T> {
match expression {
@ -971,4 +966,147 @@ mod tests {
absy::Module::<FieldPrime>::from(ast);
}
}
#[test]
fn declarations() {
use self::pest::Span;
let span = Span::new(&"", 0, 0).unwrap();
// For different definitions, we generate declarations
// Case 1: `id = expr` where `expr` is not a function call
// This is a simple assignment, doesn't implicitely declare a variable
// A `Definition` is generatedm and no `Declaration`s
let definition = pest::DefinitionStatement {
lhs: vec![pest::OptionallyTypedAssignee {
ty: None,
a: pest::Assignee {
id: pest::IdentifierExpression {
value: String::from("a"),
span: span.clone(),
},
accesses: vec![],
span: span.clone(),
},
span: span.clone(),
}],
expression: pest::Expression::Constant(pest::ConstantExpression::DecimalNumber(
pest::DecimalNumberExpression {
value: String::from("42"),
span: span.clone(),
},
)),
span: span.clone(),
};
let statements: Vec<absy::StatementNode<FieldPrime>> =
statements_from_definition(definition);
assert_eq!(statements.len(), 1);
match &statements[0].value {
absy::Statement::Definition(..) => {}
s => {
panic!("should be a Definition, found {}", s);
}
};
// Case 2: `id = expr` where `expr` is a function call
// A MultiDef is generated
let definition = pest::DefinitionStatement {
lhs: vec![pest::OptionallyTypedAssignee {
ty: None,
a: pest::Assignee {
id: pest::IdentifierExpression {
value: String::from("a"),
span: span.clone(),
},
accesses: vec![],
span: span.clone(),
},
span: span.clone(),
}],
expression: pest::Expression::Postfix(pest::PostfixExpression {
id: pest::IdentifierExpression {
value: String::from("foo"),
span: span.clone(),
},
accesses: vec![pest::Access::Call(pest::CallAccess {
expressions: vec![],
span: span.clone(),
})],
span: span.clone(),
}),
span: span.clone(),
};
let statements: Vec<absy::StatementNode<FieldPrime>> =
statements_from_definition(definition);
assert_eq!(statements.len(), 1);
match &statements[0].value {
absy::Statement::MultipleDefinition(..) => {}
s => {
panic!("should be a Definition, found {}", s);
}
};
// Case 3: `ids = expr` where `expr` is a function call
// This implicitely declares all variables which are type annotated
// `field a, b = foo()`
let definition = pest::DefinitionStatement {
lhs: vec![
pest::OptionallyTypedAssignee {
ty: Some(pest::Type::Basic(pest::BasicType::Field(pest::FieldType {
span: span.clone(),
}))),
a: pest::Assignee {
id: pest::IdentifierExpression {
value: String::from("a"),
span: span.clone(),
},
accesses: vec![],
span: span.clone(),
},
span: span.clone(),
},
pest::OptionallyTypedAssignee {
ty: None,
a: pest::Assignee {
id: pest::IdentifierExpression {
value: String::from("b"),
span: span.clone(),
},
accesses: vec![],
span: span.clone(),
},
span: span.clone(),
},
],
expression: pest::Expression::Postfix(pest::PostfixExpression {
id: pest::IdentifierExpression {
value: String::from("foo"),
span: span.clone(),
},
accesses: vec![pest::Access::Call(pest::CallAccess {
expressions: vec![],
span: span.clone(),
})],
span: span.clone(),
}),
span: span.clone(),
};
let statements: Vec<absy::StatementNode<FieldPrime>> =
statements_from_definition(definition);
assert_eq!(statements.len(), 2);
match &statements[1].value {
absy::Statement::MultipleDefinition(..) => {}
s => {
panic!("should be a Definition, found {}", s);
}
};
}
}

View file

@ -164,6 +164,9 @@ pub fn compile<T: Field, E: Into<imports::Error>>(
// optimize
let optimized_ir_prog = ir_prog.optimize();
// analyse (check for unused constraints)
let optimized_ir_prog = optimized_ir_prog.analyse();
Ok(CompilationArtifacts {
prog: optimized_ir_prog,
abi,

View file

@ -203,7 +203,7 @@ fn use_variable(
/// * the return value of the `FlatFunction` is not deterministic: as we decompose over log_2(p) + 1 bits, some
/// elements can have multiple representations: For example, `unpack(0)` is `[0, ..., 0]` but also `unpack(p)`
pub fn unpack<T: Field>() -> FlatFunction<T> {
let nbits = T::get_required_bits();
let bit_width = T::get_required_bits();
let mut counter = 0;
@ -221,23 +221,23 @@ pub fn unpack<T: Field>() -> FlatFunction<T> {
format!("i0"),
&mut counter,
))];
let directive_outputs: Vec<FlatVariable> = (0..T::get_required_bits())
let directive_outputs: Vec<FlatVariable> = (0..bit_width)
.map(|index| use_variable(&mut layout, format!("o{}", index), &mut counter))
.collect();
let solver = Solver::bits();
let solver = Solver::bits(bit_width);
let outputs = directive_outputs
.iter()
.enumerate()
.filter(|(index, _)| *index >= T::get_required_bits() - nbits)
.filter(|(index, _)| *index >= T::get_required_bits() - bit_width)
.map(|(_, o)| FlatExpression::Identifier(o.clone()))
.collect();
// o253, o252, ... o{253 - (nbits - 1)} are bits
let mut statements: Vec<FlatStatement<T>> = (0..nbits)
// o253, o252, ... o{253 - (bit_width - 1)} are bits
let mut statements: Vec<FlatStatement<T>> = (0..bit_width)
.map(|index| {
let bit = FlatExpression::Identifier(FlatVariable::new(T::get_required_bits() - index));
let bit = FlatExpression::Identifier(FlatVariable::new(bit_width - index));
FlatStatement::Condition(
bit.clone(),
FlatExpression::Mult(box bit.clone(), box bit.clone()),
@ -245,14 +245,14 @@ pub fn unpack<T: Field>() -> FlatFunction<T> {
})
.collect();
// sum check: o253 + o252 * 2 + ... + o{253 - (nbits - 1)} * 2**(nbits - 1)
// sum check: o253 + o252 * 2 + ... + o{253 - (bit_width - 1)} * 2**(bit_width - 1)
let mut lhs_sum = FlatExpression::Number(T::from(0));
for i in 0..nbits {
for i in 0..bit_width {
lhs_sum = FlatExpression::Add(
box lhs_sum,
box FlatExpression::Mult(
box FlatExpression::Identifier(FlatVariable::new(T::get_required_bits() - i)),
box FlatExpression::Identifier(FlatVariable::new(bit_width - i)),
box FlatExpression::Number(T::from(2).pow(i)),
),
);
@ -312,7 +312,7 @@ mod tests {
(0..FieldPrime::get_required_bits())
.map(|i| FlatVariable::new(i + 1))
.collect(),
Solver::bits(),
Solver::bits(FieldPrime::get_required_bits()),
vec![FlatVariable::new(0)]
))
);

View file

@ -566,8 +566,9 @@ impl<'ast, T: Field> Flattener<'ast, T> {
FlatExpression::Identifier(self.layout.get(&x).unwrap().clone()[0])
}
BooleanExpression::Lt(box lhs, box rhs) => {
// Get the bitwidth to know the size of the binary decompsitions for this Field
let bitwidth = T::get_required_bits();
// Get the bit width to know the size of the binary decompositions for this Field
let bit_width = T::get_required_bits();
let safe_width = bit_width - 2; // making sure we don't overflow, assert here?
// We know from semantic checking that lhs and rhs have the same type
// What the expression will flatten to depends on that type
@ -587,22 +588,22 @@ impl<'ast, T: Field> Flattener<'ast, T> {
{
// define variables for the bits
let lhs_bits_be: Vec<FlatVariable> =
(0..bitwidth).map(|_| self.use_sym()).collect();
(0..safe_width).map(|_| self.use_sym()).collect();
// add a directive to get the bits
statements_flattened.push(FlatStatement::Directive(FlatDirective::new(
lhs_bits_be.clone(),
Solver::bits(),
Solver::bits(safe_width),
vec![lhs_id],
)));
// bitness checks
for i in 0..bitwidth - 2 {
for i in 0..safe_width {
statements_flattened.push(FlatStatement::Condition(
FlatExpression::Identifier(lhs_bits_be[i + 2]),
FlatExpression::Identifier(lhs_bits_be[i]),
FlatExpression::Mult(
box FlatExpression::Identifier(lhs_bits_be[i + 2]),
box FlatExpression::Identifier(lhs_bits_be[i + 2]),
box FlatExpression::Identifier(lhs_bits_be[i]),
box FlatExpression::Identifier(lhs_bits_be[i]),
),
));
}
@ -610,12 +611,12 @@ impl<'ast, T: Field> Flattener<'ast, T> {
// bit decomposition check
let mut lhs_sum = FlatExpression::Number(T::from(0));
for i in 0..bitwidth - 2 {
for i in 0..safe_width {
lhs_sum = FlatExpression::Add(
box lhs_sum,
box FlatExpression::Mult(
box FlatExpression::Identifier(lhs_bits_be[i + 2]),
box FlatExpression::Number(T::from(2).pow(bitwidth - 2 - i - 1)),
box FlatExpression::Identifier(lhs_bits_be[i]),
box FlatExpression::Number(T::from(2).pow(safe_width - i - 1)),
),
);
}
@ -634,22 +635,22 @@ impl<'ast, T: Field> Flattener<'ast, T> {
{
// define variables for the bits
let rhs_bits_be: Vec<FlatVariable> =
(0..bitwidth).map(|_| self.use_sym()).collect();
(0..safe_width).map(|_| self.use_sym()).collect();
// add a directive to get the bits
statements_flattened.push(FlatStatement::Directive(FlatDirective::new(
rhs_bits_be.clone(),
Solver::bits(),
Solver::bits(safe_width),
vec![rhs_id],
)));
// bitness checks
for i in 0..bitwidth - 2 {
for i in 0..safe_width {
statements_flattened.push(FlatStatement::Condition(
FlatExpression::Identifier(rhs_bits_be[i + 2]),
FlatExpression::Identifier(rhs_bits_be[i]),
FlatExpression::Mult(
box FlatExpression::Identifier(rhs_bits_be[i + 2]),
box FlatExpression::Identifier(rhs_bits_be[i + 2]),
box FlatExpression::Identifier(rhs_bits_be[i]),
box FlatExpression::Identifier(rhs_bits_be[i]),
),
));
}
@ -657,12 +658,12 @@ impl<'ast, T: Field> Flattener<'ast, T> {
// bit decomposition check
let mut rhs_sum = FlatExpression::Number(T::from(0));
for i in 0..bitwidth - 2 {
for i in 0..safe_width {
rhs_sum = FlatExpression::Add(
box rhs_sum,
box FlatExpression::Mult(
box FlatExpression::Identifier(rhs_bits_be[i + 2]),
box FlatExpression::Number(T::from(2).pow(bitwidth - 2 - i - 1)),
box FlatExpression::Identifier(rhs_bits_be[i]),
box FlatExpression::Number(T::from(2).pow(safe_width - i - 1)),
),
);
}
@ -687,17 +688,17 @@ impl<'ast, T: Field> Flattener<'ast, T> {
// define variables for the bits
let sub_bits_be: Vec<FlatVariable> =
(0..bitwidth).map(|_| self.use_sym()).collect();
(0..bit_width).map(|_| self.use_sym()).collect();
// add a directive to get the bits
statements_flattened.push(FlatStatement::Directive(FlatDirective::new(
sub_bits_be.clone(),
Solver::bits(),
Solver::bits(bit_width),
vec![subtraction_result.clone()],
)));
// bitness checks
for i in 0..bitwidth {
for i in 0..bit_width {
statements_flattened.push(FlatStatement::Condition(
FlatExpression::Identifier(sub_bits_be[i]),
FlatExpression::Mult(
@ -710,19 +711,19 @@ impl<'ast, T: Field> Flattener<'ast, T> {
// sum(sym_b{i} * 2**i)
let mut expr = FlatExpression::Number(T::from(0));
for i in 0..bitwidth {
for i in 0..bit_width {
expr = FlatExpression::Add(
box expr,
box FlatExpression::Mult(
box FlatExpression::Identifier(sub_bits_be[i]),
box FlatExpression::Number(T::from(2).pow(bitwidth - i - 1)),
box FlatExpression::Number(T::from(2).pow(bit_width - i - 1)),
),
);
}
statements_flattened.push(FlatStatement::Condition(subtraction_result, expr));
FlatExpression::Identifier(sub_bits_be[bitwidth - 1])
FlatExpression::Identifier(sub_bits_be[bit_width - 1])
}
BooleanExpression::BoolEq(box lhs, box rhs) => {
// lhs and rhs are booleans, they flatten to 0 or 1

View file

@ -96,7 +96,7 @@ impl ProofSystem for G16 {
let mut raw: Vec<u8> = Vec::new();
proof.write(&mut raw).unwrap();
Proof::<G16ProofPoints>::new(proof_points, inputs, Some(base64::encode(&raw)))
Proof::<G16ProofPoints>::new(proof_points, inputs, Some(hex::encode(&raw)))
.to_json_pretty()
} else {
Proof::<G16ProofPoints>::new(proof_points, inputs, None).to_json_pretty()
@ -201,7 +201,7 @@ fn get_raw_proof(proof: &Proof<G16ProofPoints>) -> BellmanProof<Bn256> {
proof.raw.is_some(),
"Missing \"raw\" field in proof: pass \"--raw\" flag when generating proof"
);
let proof = base64::decode(proof.raw.as_ref().unwrap()).unwrap();
let proof = hex::decode(proof.raw.as_ref().unwrap()).unwrap();
BellmanProof::read(proof.as_slice()).unwrap()
}
@ -212,7 +212,7 @@ fn get_raw_vk(vk: String) -> VerifyingKey<Bn256> {
raw.is_some(),
"Missing \"vk.raw\" key: pass \"--raw\" flag when running setup"
);
let raw = base64::decode(raw.unwrap()).unwrap();
let raw = hex::decode(raw.unwrap()).unwrap();
VerifyingKey::read(raw.as_slice()).unwrap()
}
@ -252,7 +252,7 @@ fn serialize_vk(vk: VerifyingKey<Bn256>, include_raw: bool) -> String {
vk.write(&mut raw).unwrap();
writer
.write_record(&["vk.raw", base64::encode(&raw).as_str()])
.write_record(&["vk.raw", hex::encode(&raw).as_str()])
.unwrap();
}

View file

@ -995,7 +995,7 @@ impl<'ast> Checker<'ast> {
}
_ => Err(ErrorInner {
pos: Some(pos),
message: format!("{} should be a FunctionCall", rhs),
message: format!("{} should be a function call", rhs),
}),
}.map_err(|e| vec![e])
}

View file

@ -5,7 +5,7 @@ use zokrates_field::field::Field;
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, Hash, Eq)]
pub enum Solver {
ConditionEq,
Bits,
Bits(usize),
Div,
Sha256Round,
}
@ -20,7 +20,7 @@ impl Signed for Solver {
fn get_signature(&self) -> (usize, usize) {
match self {
Solver::ConditionEq => (1, 2),
Solver::Bits => (1, 254),
Solver::Bits(bit_width) => (1, *bit_width),
Solver::Div => (2, 1),
Solver::Sha256Round => (768, 26935),
}
@ -37,11 +37,11 @@ impl<T: Field> Executable<T> for Solver {
true => vec![T::zero(), T::one()],
false => vec![T::one(), T::one() / inputs[0].clone()],
},
Solver::Bits => {
Solver::Bits(bit_width) => {
let mut num = inputs[0].clone();
let mut res = vec![];
let bits = 254;
for i in (0..bits).rev() {
for i in (0..*bit_width).rev() {
if T::from(2).pow(i) <= num {
num = num - T::from(2).pow(i);
res.push(T::one());
@ -73,8 +73,8 @@ impl<T: Field> Executable<T> for Solver {
}
impl Solver {
pub fn bits() -> Self {
Solver::Bits
pub fn bits(width: usize) -> Self {
Solver::Bits(width)
}
}
@ -125,7 +125,9 @@ mod tests {
#[test]
fn bits_of_one() {
let inputs = vec![FieldPrime::from(1)];
let res = Solver::Bits.execute(&inputs).unwrap();
let res = Solver::Bits(FieldPrime::get_required_bits())
.execute(&inputs)
.unwrap();
assert_eq!(res[253], FieldPrime::from(1));
for i in 0..252 {
assert_eq!(res[i], FieldPrime::from(0));
@ -135,7 +137,9 @@ mod tests {
#[test]
fn bits_of_42() {
let inputs = vec![FieldPrime::from(42)];
let res = Solver::Bits.execute(&inputs).unwrap();
let res = Solver::Bits(FieldPrime::get_required_bits())
.execute(&inputs)
.unwrap();
assert_eq!(res[253], FieldPrime::from(0));
assert_eq!(res[252], FieldPrime::from(1));
assert_eq!(res[251], FieldPrime::from(0));

View file

@ -21,27 +21,59 @@ use typed_absy::types::{FunctionKey, StructMember, Type};
use typed_absy::{folder::*, *};
use zokrates_field::field::Field;
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
struct Location<'ast> {
module: TypedModuleId,
key: FunctionKey<'ast>,
}
impl<'ast> Location<'ast> {
fn module(&self) -> &TypedModuleId {
&self.module
}
}
type CallCache<'ast, T> = HashMap<
Location<'ast>,
HashMap<
FunctionKey<'ast>,
HashMap<Vec<TypedExpression<'ast, T>>, Vec<TypedExpression<'ast, T>>>,
>,
>;
/// An inliner
#[derive(Debug)]
pub struct Inliner<'ast, T: Field> {
modules: TypedModules<'ast, T>, // the modules in which to look for functions when inlining
module_id: TypedModuleId, // the current module we're visiting
statement_buffer: Vec<TypedStatement<'ast, T>>, // a buffer of statements to be added to the inlined statements
stack: Vec<(TypedModuleId, FunctionKey<'ast>, usize)>, // the current call stack
call_count: HashMap<(TypedModuleId, FunctionKey<'ast>), usize>, // the call count for each function
/// the modules in which to look for functions when inlining
modules: TypedModules<'ast, T>,
/// the current module we're visiting
location: Location<'ast>,
/// a buffer of statements to be added to the inlined statements
statement_buffer: Vec<TypedStatement<'ast, T>>,
/// the current call stack
stack: Vec<(TypedModuleId, FunctionKey<'ast>, usize)>,
/// the call count for each function
call_count: HashMap<(TypedModuleId, FunctionKey<'ast>), usize>,
/// the cache for memoization: for each function body, tracks function calls
call_cache: CallCache<'ast, T>,
}
impl<'ast, T: Field> Inliner<'ast, T> {
fn with_modules_and_module_id<S: Into<TypedModuleId>>(
fn with_modules_and_module_id_and_key<S: Into<TypedModuleId>>(
modules: TypedModules<'ast, T>,
module_id: S,
key: FunctionKey<'ast>,
) -> Self {
Inliner {
modules,
module_id: module_id.into(),
location: Location {
module: module_id.into(),
key,
},
statement_buffer: vec![],
stack: vec![],
call_count: HashMap::new(),
call_cache: HashMap::new(),
}
}
@ -59,7 +91,11 @@ impl<'ast, T: Field> Inliner<'ast, T> {
.unwrap();
// initialize an inliner over all modules, starting from the main module
let mut inliner = Inliner::with_modules_and_module_id(p.modules, main_module_id);
let mut inliner = Inliner::with_modules_and_module_id_and_key(
p.modules,
main_module_id,
main_key.clone(),
);
// inline all calls in the main function, recursively
let main = inliner.fold_function_symbol(main);
@ -101,24 +137,33 @@ impl<'ast, T: Field> Inliner<'ast, T> {
expressions: Vec<TypedExpression<'ast, T>>,
) -> Result<Vec<TypedExpression<'ast, T>>, (FunctionKey<'ast>, Vec<TypedExpression<'ast, T>>)>
{
match self.call_cache().get(key).map(|m| m.get(&expressions)) {
Some(Some(exprs)) => return Ok(exprs.clone()),
_ => {}
};
// here we clone a function symbol, which is cheap except when it contains the function body, in which case we'd clone anyways
match self.module().functions.get(&key).unwrap().clone() {
let res = match self.module().functions.get(&key).unwrap().clone() {
// if the function called is in the same module, we can go ahead and inline in this module
TypedFunctionSymbol::Here(function) => {
let (current_module, current_key) =
self.change_context(self.module_id().clone(), key.clone());
let module_id = self.module_id().clone();
// increase the number of calls for this function by one
let count = self
.call_count
.entry((self.module_id.clone(), key.clone()))
.entry((self.module_id().clone(), key.clone()))
.and_modify(|i| *i += 1)
.or_insert(1);
// push this call to the stack
self.stack
.push((self.module_id.clone(), key.clone(), *count));
self.stack.push((module_id, key.clone(), *count));
// add definitions for the inputs
let inputs_bindings: Vec<_> = function
.arguments
.iter()
.zip(expressions)
.zip(expressions.clone())
.map(|(a, e)| {
TypedStatement::Definition(
self.fold_assignee(TypedAssignee::Identifier(a.id.clone())),
@ -145,6 +190,8 @@ impl<'ast, T: Field> Inliner<'ast, T> {
// pop this call from the stack
self.stack.pop();
self.change_context(current_module, current_key);
match ret.pop().unwrap() {
TypedStatement::Return(exprs) => Ok(exprs),
_ => unreachable!(""),
@ -153,25 +200,64 @@ impl<'ast, T: Field> Inliner<'ast, T> {
// if the function called is in some other module, we switch focus to that module and call the function locally there
TypedFunctionSymbol::There(function_key, module_id) => {
// switch focus to `module_id`
let current_module = self.change_module(module_id);
let (current_module, current_key) =
self.change_context(module_id, function_key.clone());
// inline the call there
let res = self.try_inline_call(&function_key, expressions)?;
let res = self.try_inline_call(&function_key, expressions.clone())?;
// switch back focus
self.change_module(current_module);
self.change_context(current_module, current_key);
Ok(res)
}
// if the function is a flat symbol, replace the call with a call to the local function we provide so it can be inlined in flattening
TypedFunctionSymbol::Flat(embed) => Err((embed.key::<T>(), expressions)),
}
TypedFunctionSymbol::Flat(embed) => Err((embed.key::<T>(), expressions.clone())),
};
res.map(|exprs| {
self.call_cache_mut()
.entry(key.clone())
.or_insert_with(|| HashMap::new())
.insert(expressions, exprs.clone());
exprs
})
}
// Focus the inliner on another module with id `module_id` and return the current `module_id`
fn change_module(&mut self, module_id: TypedModuleId) -> TypedModuleId {
std::mem::replace(&mut self.module_id, module_id)
fn change_context(
&mut self,
module_id: TypedModuleId,
function_key: FunctionKey<'ast>,
) -> (TypedModuleId, FunctionKey<'ast>) {
let current_module = std::mem::replace(&mut self.location.module, module_id);
let current_key = std::mem::replace(&mut self.location.key, function_key);
(current_module, current_key)
}
fn module(&self) -> &TypedModule<'ast, T> {
self.modules.get(&self.module_id).unwrap()
self.modules.get(self.module_id()).unwrap()
}
fn call_cache(
&mut self,
) -> &HashMap<
FunctionKey<'ast>,
HashMap<Vec<TypedExpression<'ast, T>>, Vec<TypedExpression<'ast, T>>>,
> {
self.call_cache
.entry(self.location.clone())
.or_insert_with(|| HashMap::new())
}
fn call_cache_mut(
&mut self,
) -> &mut HashMap<
FunctionKey<'ast>,
HashMap<Vec<TypedExpression<'ast, T>>, Vec<TypedExpression<'ast, T>>>,
> {
self.call_cache.get_mut(&self.location).unwrap()
}
fn module_id(&self) -> &TypedModuleId {
self.location.module()
}
}
@ -567,6 +653,363 @@ mod tests {
);
}
#[test]
fn memoize_local_call() {
// // foo
// def foo(field a) -> (field):
// return a
// // main
// def main(field a) -> (field):
// field b = foo(a) + foo(a)
// return b
// inlined
// def main(field a) -> (field)
// field _0 = a + a
// return _0
let signature = Signature::new()
.outputs(vec![Type::FieldElement])
.inputs(vec![Type::FieldElement]);
let main: TypedModule<FieldPrime> = TypedModule {
functions: vec![
(
FunctionKey::with_id("main").signature(signature.clone()),
TypedFunctionSymbol::Here(TypedFunction {
arguments: vec![Parameter {
id: Variable::field_element("a".into()),
private: true,
}],
statements: vec![
TypedStatement::Definition(
TypedAssignee::Identifier(Variable::field_element("b".into())),
FieldElementExpression::Add(
box FieldElementExpression::FunctionCall(
FunctionKey::with_id("foo").signature(signature.clone()),
vec![FieldElementExpression::Identifier("a".into()).into()],
),
box FieldElementExpression::FunctionCall(
FunctionKey::with_id("foo").signature(signature.clone()),
vec![FieldElementExpression::Identifier("a".into()).into()],
),
)
.into(),
),
TypedStatement::Return(vec![FieldElementExpression::Identifier(
"b".into(),
)
.into()]),
],
signature: signature.clone(),
}),
),
(
FunctionKey::with_id("foo").signature(signature.clone()),
TypedFunctionSymbol::There(
FunctionKey::with_id("foo").signature(signature.clone()),
"foo".into(),
),
),
]
.into_iter()
.collect(),
};
let foo: TypedModule<FieldPrime> = TypedModule {
functions: vec![(
FunctionKey::with_id("foo").signature(signature.clone()),
TypedFunctionSymbol::Here(TypedFunction {
arguments: vec![Parameter {
id: Variable::field_element("a".into()),
private: true,
}],
statements: vec![TypedStatement::Return(vec![
FieldElementExpression::Identifier("a".into()).into(),
])],
signature: signature.clone(),
}),
)]
.into_iter()
.collect(),
};
let modules: HashMap<_, _> = vec![("main".into(), main), ("foo".into(), foo)]
.into_iter()
.collect();
let program = TypedProgram {
main: "main".into(),
modules,
};
let program = Inliner::inline(program);
assert_eq!(program.modules.len(), 1);
assert_eq!(
program
.modules
.get(&PathBuf::from("main"))
.unwrap()
.functions
.get(&FunctionKey::with_id("main").signature(signature.clone()))
.unwrap(),
&TypedFunctionSymbol::Here(TypedFunction {
arguments: vec![Parameter {
id: Variable::field_element("a".into()),
private: true,
}],
statements: vec![
TypedStatement::Definition(
TypedAssignee::Identifier(Variable::field_element(
Identifier::from("a").stack(vec![(
"foo".into(),
FunctionKey::with_id("foo").signature(signature.clone()),
1
)])
)),
FieldElementExpression::Identifier("a".into()).into()
),
TypedStatement::Definition(
TypedAssignee::Identifier(Variable::field_element("b".into())),
FieldElementExpression::Add(
box FieldElementExpression::Identifier(Identifier::from("a").stack(
vec![(
"foo".into(),
FunctionKey::with_id("foo").signature(signature.clone()),
1
)]
)),
box FieldElementExpression::Identifier(Identifier::from("a").stack(
vec![(
"foo".into(),
FunctionKey::with_id("foo").signature(signature.clone()),
1
)]
))
)
.into()
),
TypedStatement::Return(vec![
FieldElementExpression::Identifier("b".into()).into(),
])
],
signature: signature.clone(),
})
);
}
#[test]
fn only_memoize_in_same_function() {
// // foo
// def foo(field a) -> (field):
// return a
// // main
// def main(field a) -> (field):
// field b = foo(a) + bar(a)
// return b
//
// def bar(field a) -> (field):
// return foo(a)
// inlined
// def main(field a) -> (field)
// field _0 = a + a
// return _0
let signature = Signature::new()
.outputs(vec![Type::FieldElement])
.inputs(vec![Type::FieldElement]);
let main: TypedModule<FieldPrime> = TypedModule {
functions: vec![
(
FunctionKey::with_id("main").signature(
Signature::new()
.outputs(vec![Type::FieldElement])
.inputs(vec![Type::FieldElement]),
),
TypedFunctionSymbol::Here(TypedFunction {
arguments: vec![Parameter {
id: Variable::field_element("a".into()),
private: true,
}],
statements: vec![
TypedStatement::Definition(
TypedAssignee::Identifier(Variable::field_element("b".into())),
FieldElementExpression::Add(
box FieldElementExpression::FunctionCall(
FunctionKey::with_id("foo").signature(signature.clone()),
vec![FieldElementExpression::Identifier("a".into()).into()],
),
box FieldElementExpression::FunctionCall(
FunctionKey::with_id("bar").signature(signature.clone()),
vec![FieldElementExpression::Identifier("a".into()).into()],
),
)
.into(),
),
TypedStatement::Return(vec![FieldElementExpression::Identifier(
"b".into(),
)
.into()]),
],
signature: signature.clone(),
}),
),
(
FunctionKey::with_id("bar").signature(signature.clone()),
TypedFunctionSymbol::Here(TypedFunction {
arguments: vec![Parameter {
id: Variable::field_element("a".into()),
private: true,
}],
statements: vec![TypedStatement::Return(vec![
FieldElementExpression::FunctionCall(
FunctionKey::with_id("foo").signature(signature.clone()),
vec![FieldElementExpression::Identifier("a".into()).into()],
)
.into(),
])],
signature: signature.clone(),
}),
),
(
FunctionKey::with_id("foo").signature(signature.clone()),
TypedFunctionSymbol::There(
FunctionKey::with_id("foo").signature(signature.clone()),
"foo".into(),
),
),
]
.into_iter()
.collect(),
};
let foo: TypedModule<FieldPrime> = TypedModule {
functions: vec![(
FunctionKey::with_id("foo").signature(signature.clone()),
TypedFunctionSymbol::Here(TypedFunction {
arguments: vec![Parameter {
id: Variable::field_element("a".into()),
private: true,
}],
statements: vec![TypedStatement::Return(vec![
FieldElementExpression::Identifier("a".into()).into(),
])],
signature: signature.clone(),
}),
)]
.into_iter()
.collect(),
};
let modules: HashMap<_, _> = vec![("main".into(), main), ("foo".into(), foo)]
.into_iter()
.collect();
let program = TypedProgram {
main: "main".into(),
modules,
};
let program = Inliner::inline(program);
assert_eq!(program.modules.len(), 1);
assert_eq!(
program
.modules
.get(&PathBuf::from("main"))
.unwrap()
.functions
.get(&FunctionKey::with_id("main").signature(signature.clone()))
.unwrap(),
&TypedFunctionSymbol::Here(TypedFunction {
arguments: vec![Parameter {
id: Variable::field_element("a".into()),
private: true,
}],
statements: vec![
TypedStatement::Definition(
TypedAssignee::Identifier(Variable::field_element(
Identifier::from("a").stack(vec![(
"foo".into(),
FunctionKey::with_id("foo").signature(signature.clone()),
1
)])
)),
FieldElementExpression::Identifier("a".into()).into()
),
TypedStatement::Definition(
TypedAssignee::Identifier(Variable::field_element(
Identifier::from("a").stack(vec![(
"main".into(),
FunctionKey::with_id("bar").signature(signature.clone()),
1
)])
)),
FieldElementExpression::Identifier("a".into()).into()
),
TypedStatement::Definition(
TypedAssignee::Identifier(Variable::field_element(
Identifier::from("a").stack(vec![
(
"main".into(),
FunctionKey::with_id("bar").signature(signature.clone()),
1
),
(
"foo".into(),
FunctionKey::with_id("foo").signature(signature.clone()),
2
)
])
)),
FieldElementExpression::Identifier(Identifier::from("a").stack(vec![(
"main".into(),
FunctionKey::with_id("bar").signature(signature.clone()),
1
)]))
.into()
),
TypedStatement::Definition(
TypedAssignee::Identifier(Variable::field_element("b".into())),
FieldElementExpression::Add(
box FieldElementExpression::Identifier(Identifier::from("a").stack(
vec![(
"foo".into(),
FunctionKey::with_id("foo").signature(signature.clone()),
1
)]
)),
box FieldElementExpression::Identifier(Identifier::from("a").stack(
vec![
(
"main".into(),
FunctionKey::with_id("bar").signature(signature.clone()),
1
),
(
"foo".into(),
FunctionKey::with_id("foo").signature(signature.clone()),
2
)
]
))
)
.into()
),
TypedStatement::Return(vec![
FieldElementExpression::Identifier("b".into()).into(),
])
],
signature: signature.clone(),
})
);
}
#[test]
fn multi_def_from_other_module() {
// // foo

View file

@ -9,14 +9,19 @@ mod flat_propagation;
mod inline;
mod propagate_unroll;
mod propagation;
mod return_binder;
mod unconstrained_vars;
mod unroll;
use self::constrain_inputs::InputConstrainer;
use self::inline::Inliner;
use self::propagate_unroll::PropagatedUnroller;
use self::propagation::Propagator;
use self::return_binder::ReturnBinder;
use self::unconstrained_vars::UnconstrainedVariableDetector;
use crate::flat_absy::FlatProg;
use crate::typed_absy::TypedProgram;
use ir::Prog;
use zokrates_field::field::Field;
pub trait Analyse {
@ -27,6 +32,8 @@ impl<'ast, T: Field> Analyse for TypedProgram<'ast, T> {
fn analyse(self) -> Self {
// propagated unrolling
let r = PropagatedUnroller::unroll(self).unwrap_or_else(|e| panic!(e));
// return binding
let r = ReturnBinder::bind(r);
// inline
let r = Inliner::inline(r);
// propagate
@ -43,3 +50,10 @@ impl<T: Field> Analyse for FlatProg<T> {
self.propagate()
}
}
impl<T: Field> Analyse for Prog<T> {
fn analyse(self) -> Self {
let r = UnconstrainedVariableDetector::detect(self);
r
}
}

View file

@ -0,0 +1,55 @@
use typed_absy::folder::fold_statement;
use typed_absy::identifier::CoreIdentifier;
use typed_absy::*;
use zokrates_field::field::Field;
pub struct ReturnBinder;
impl ReturnBinder {
pub fn bind<'ast, T: Field>(p: TypedProgram<'ast, T>) -> TypedProgram<'ast, T> {
ReturnBinder {}.fold_program(p)
}
}
impl<'ast, T: Field> Folder<'ast, T> for ReturnBinder {
fn fold_statement(&mut self, s: TypedStatement<'ast, T>) -> Vec<TypedStatement<'ast, T>> {
match s {
TypedStatement::Return(exprs) => {
let ret_identifiers: Vec<Identifier<'ast>> = (0..exprs.len())
.map(|i| CoreIdentifier::Internal("RETURN", i).into())
.collect();
let ret_expressions: Vec<TypedExpression<'ast, T>> = exprs
.iter()
.zip(ret_identifiers.iter())
.map(|(e, i)| match e.get_type() {
Type::FieldElement => FieldElementExpression::Identifier(i.clone()).into(),
Type::Boolean => BooleanExpression::Identifier(i.clone()).into(),
Type::Array(array_type) => ArrayExpressionInner::Identifier(i.clone())
.annotate(*array_type.ty, array_type.size)
.into(),
Type::Struct(struct_type) => StructExpressionInner::Identifier(i.clone())
.annotate(struct_type)
.into(),
})
.collect();
exprs
.into_iter()
.zip(ret_identifiers.iter())
.map(|(e, i)| {
TypedStatement::Definition(
TypedAssignee::Identifier(Variable::with_id_and_type(
i.clone(),
e.get_type(),
)),
e,
)
})
.chain(std::iter::once(TypedStatement::Return(ret_expressions)))
.collect()
}
s => fold_statement(self, s),
}
}
}

View file

@ -0,0 +1,177 @@
use crate::ir::Prog;
use flat_absy::FlatVariable;
use ir::folder::Folder;
use ir::Directive;
use std::collections::HashSet;
use zokrates_field::field::Field;
#[derive(Debug)]
pub struct UnconstrainedVariableDetector {
pub(self) variables: HashSet<FlatVariable>,
}
impl UnconstrainedVariableDetector {
fn new<T: Field>(p: &Prog<T>) -> Self {
UnconstrainedVariableDetector {
variables: p
.parameters()
.iter()
.filter(|p| p.private)
.map(|p| p.id)
.collect(),
}
}
pub fn detect<T: Field>(p: Prog<T>) -> Prog<T> {
let mut instance = Self::new(&p);
let p = instance.fold_module(p);
// we should probably handle this case instead of asserting at some point
assert!(
instance.variables.is_empty(),
format!(
"Unconstrained variables are not allowed (found {} occasions)",
instance.variables.len()
)
);
p
}
}
impl<T: Field> Folder<T> for UnconstrainedVariableDetector {
fn fold_argument(&mut self, p: FlatVariable) -> FlatVariable {
p
}
fn fold_variable(&mut self, v: FlatVariable) -> FlatVariable {
self.variables.remove(&v);
v
}
fn fold_directive(&mut self, d: Directive<T>) -> Directive<T> {
self.variables.extend(d.outputs.iter());
d
}
}
#[cfg(test)]
mod tests {
use super::*;
use flat_absy::FlatVariable;
use ir::{Function, LinComb, Prog, QuadComb, Statement};
use num::Zero;
use solvers::Solver;
use zokrates_field::field::FieldPrime;
#[test]
#[should_panic]
fn should_detect_unconstrained_private_input() {
// def main(_0) -> (1):
// (1 * ~one) * (42 * ~one) == 1 * ~out_0
// return ~out_0
let _0 = FlatVariable::new(0); // unused var
let one = FlatVariable::one();
let out_0 = FlatVariable::public(0);
let main: Function<FieldPrime> = Function {
id: "main".to_string(),
arguments: vec![_0],
statements: vec![Statement::constraint(
QuadComb::from_linear_combinations(
LinComb::summand(1, one),
LinComb::summand(42, one),
),
LinComb::summand(1, out_0),
)],
returns: vec![out_0],
};
let p: Prog<FieldPrime> = Prog {
private: vec![true],
main,
};
UnconstrainedVariableDetector::detect(p);
}
#[test]
fn should_pass_with_constrained_private_input() {
// def main(_0) -> (1):
// (1 * ~one) * (1 * _0) == 1 * ~out_0
// return ~out_0
let _0 = FlatVariable::new(0);
let out_0 = FlatVariable::public(0);
let main: Function<FieldPrime> = Function {
id: "main".to_string(),
arguments: vec![_0],
statements: vec![Statement::definition(out_0, LinComb::from(_0))],
returns: vec![out_0],
};
let p: Prog<FieldPrime> = Prog {
private: vec![true],
main,
};
UnconstrainedVariableDetector::detect(p);
}
#[test]
fn should_pass_with_directive() {
// def main(_0) -> (1):
// # _1, _2 = ConditionEq((-42) * ~one + 1 * _0)
// ((-42) * ~one + 1 * _0) * (1 * _2) == 1 * _1
// (1 * ~one + (-1) * _1) * ((-42) * ~one + 1 * _0) == 0
// (1 * ~one) * (1 * ~one + (-1) * _1) == 1 * ~out_0
// return ~out_0
let _0 = FlatVariable::new(0);
let _1 = FlatVariable::new(1);
let _2 = FlatVariable::new(2);
let out_0 = FlatVariable::public(0);
let one = FlatVariable::one();
let main: Function<FieldPrime> = Function {
id: "main".to_string(),
arguments: vec![_0],
statements: vec![
Statement::Directive(Directive {
inputs: vec![LinComb::summand(-42, one) + LinComb::summand(1, _0)],
outputs: vec![_1, _2],
solver: Solver::ConditionEq,
}),
Statement::constraint(
QuadComb::from_linear_combinations(
LinComb::summand(-42, one) + LinComb::summand(1, _0),
LinComb::summand(1, _2),
),
LinComb::summand(1, _1),
),
Statement::constraint(
QuadComb::from_linear_combinations(
LinComb::summand(1, one) + LinComb::summand(-1, _1),
LinComb::summand(-42, one) + LinComb::summand(1, _0),
),
LinComb::zero(),
),
Statement::constraint(
QuadComb::from_linear_combinations(
LinComb::summand(1, one),
LinComb::summand(1, one) + LinComb::summand(-1, _1),
),
LinComb::summand(1, out_0),
),
],
returns: vec![out_0],
};
let p: Prog<FieldPrime> = Prog {
private: vec![true],
main,
};
UnconstrainedVariableDetector::detect(p);
}
}

View file

@ -9,6 +9,7 @@ use crate::typed_absy::types::{MemberId, Type};
use crate::typed_absy::*;
use std::collections::HashMap;
use std::collections::HashSet;
use typed_absy::identifier::CoreIdentifier;
use zokrates_field::field::Field;
pub enum Output<'ast, T: Field> {
@ -18,7 +19,7 @@ pub enum Output<'ast, T: Field> {
pub struct Unroller<'ast> {
// version index for any variable name
substitution: HashMap<&'ast str, usize>,
substitution: HashMap<CoreIdentifier<'ast>, usize>,
// whether all statements could be unrolled so far. Loops with variable bounds cannot.
complete: bool,
statement_count: usize,
@ -37,7 +38,7 @@ impl<'ast> Unroller<'ast> {
let res = match self.substitution.get(&v.id.id) {
Some(i) => Variable {
id: Identifier {
id: v.id.id,
id: v.id.id.clone(),
version: i + 1,
stack: vec![],
},

View file

@ -32,8 +32,7 @@ mod tests {
use std::collections::HashMap;
use typed_absy::types::{ArrayType, FunctionKey, StructMember};
use typed_absy::{
Identifier, Parameter, Type, TypedFunction, TypedFunctionSymbol, TypedModule, TypedProgram,
Variable,
Parameter, Type, TypedFunction, TypedFunctionSymbol, TypedModule, TypedProgram, Variable,
};
use zokrates_field::field::FieldPrime;
@ -45,19 +44,11 @@ mod tests {
TypedFunctionSymbol::Here(TypedFunction {
arguments: vec![
Parameter {
id: Variable::field_element(Identifier {
id: "a",
version: 0,
stack: vec![],
}),
id: Variable::field_element("a".into()),
private: true,
},
Parameter {
id: Variable::boolean(Identifier {
id: "b",
version: 0,
stack: vec![],
}),
id: Variable::boolean("b".into()),
private: false,
},
],

View file

@ -0,0 +1,83 @@
use std::fmt;
use typed_absy::types::FunctionKey;
use typed_absy::TypedModuleId;
#[derive(Debug, PartialEq, Clone, Hash, Eq)]
pub enum CoreIdentifier<'ast> {
Source(&'ast str),
Internal(&'static str, usize),
}
impl<'ast> fmt::Display for CoreIdentifier<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
CoreIdentifier::Source(s) => write!(f, "{}", s),
CoreIdentifier::Internal(s, i) => write!(f, "#INTERNAL#_{}_{}", s, i),
}
}
}
/// A identifier for a variable
#[derive(Debug, PartialEq, Clone, Hash, Eq)]
pub struct Identifier<'ast> {
/// the id of the variable
pub id: CoreIdentifier<'ast>,
/// the version of the variable, used after SSA transformation
pub version: usize,
/// the call stack of the variable, used when inlining
pub stack: Vec<(TypedModuleId, FunctionKey<'ast>, usize)>,
}
impl<'ast> fmt::Display for Identifier<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.stack.len() == 0 && self.version == 0 {
write!(f, "{}", self.id)
} else {
write!(
f,
"{}_{}_{}",
self.stack
.iter()
.map(|(name, sig, count)| format!(
"{}_{}_{}",
name.display(),
sig.to_slug(),
count
))
.collect::<Vec<_>>()
.join("_"),
self.id,
self.version
)
}
}
}
impl<'ast> From<&'ast str> for Identifier<'ast> {
fn from(id: &'ast str) -> Identifier<'ast> {
Identifier::from(CoreIdentifier::Source(id))
}
}
impl<'ast> From<CoreIdentifier<'ast>> for Identifier<'ast> {
fn from(id: CoreIdentifier<'ast>) -> Identifier<'ast> {
Identifier {
id,
version: 0,
stack: vec![],
}
}
}
#[cfg(test)]
impl<'ast> Identifier<'ast> {
pub fn version(mut self, version: usize) -> Self {
self.version = version;
self
}
pub fn stack(mut self, stack: Vec<(TypedModuleId, FunctionKey<'ast>, usize)>) -> Self {
self.stack = stack;
self
}
}

View file

@ -7,6 +7,7 @@
pub mod abi;
pub mod folder;
pub mod identifier;
mod parameter;
pub mod types;
mod variable;
@ -25,19 +26,9 @@ use zokrates_field::field::Field;
pub use self::folder::Folder;
use typed_absy::abi::{Abi, AbiInput};
pub use typed_absy::identifier::Identifier;
use typed_absy::types::StructMember;
/// A identifier for a variable
#[derive(Debug, PartialEq, Clone, Hash, Eq)]
pub struct Identifier<'ast> {
/// the id of the variable
pub id: &'ast str,
/// the version of the variable, used after SSA transformation
pub version: usize,
/// the call stack of the variable, used when inlining
pub stack: Vec<(TypedModuleId, FunctionKey<'ast>, usize)>,
}
/// An identifier for a `TypedModule`. Typically a path or uri.
pub type TypedModuleId = PathBuf;
@ -114,54 +105,6 @@ pub struct TypedModule<'ast, T: Field> {
pub functions: TypedFunctionSymbols<'ast, T>,
}
impl<'ast> fmt::Display for Identifier<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.stack.len() == 0 && self.version == 0 {
write!(f, "{}", self.id)
} else {
write!(
f,
"{}_{}_{}",
self.stack
.iter()
.map(|(name, sig, count)| format!(
"{}_{}_{}",
name.display(),
sig.to_slug(),
count
))
.collect::<Vec<_>>()
.join("_"),
self.id,
self.version
)
}
}
}
impl<'ast> From<&'ast str> for Identifier<'ast> {
fn from(id: &'ast str) -> Identifier<'ast> {
Identifier {
id,
version: 0,
stack: vec![],
}
}
}
#[cfg(test)]
impl<'ast> Identifier<'ast> {
pub fn version(mut self, version: usize) -> Self {
self.version = version;
self
}
pub fn stack(mut self, stack: Vec<(TypedModuleId, FunctionKey<'ast>, usize)>) -> Self {
self.stack = stack;
self
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum TypedFunctionSymbol<'ast, T: Field> {
Here(TypedFunction<'ast, T>),

View file

@ -0,0 +1,6 @@
{
"entry_point": "./tests/tests/arrays/fun_spread.zok",
"max_constraint_count": 1050,
"tests": [
]
}

View file

@ -0,0 +1,7 @@
import "utils/pack/nonStrictUnpack256.zok" as unpack256
def main(field[2] inputs) -> (field[512]):
field[512] preimage512 = [...unpack256(inputs[0]), ...unpack256(inputs[1])]
return preimage512

View file

@ -0,0 +1,3 @@
def dep(field a) -> (field): // this costs 2 constraits per call
field res = a ** 4
return res

View file

@ -0,0 +1,16 @@
{
"entry_point": "./tests/tests/memoize/memoize.zok",
"max_constraint_count": 14,
"tests": [
{
"input": {
"values": ["3"]
},
"output": {
"Ok": {
"values": []
}
}
}
]
}

View file

@ -0,0 +1,14 @@
from "./dep.zok" import dep as dep
def local(field a) -> (field): // this costs 3 constraints per call
field res = a ** 8
return res // currently expressions in the return statement don't get memoized
def main(field a) -> ():
// calling a local function many times with the same arg should cost only once
local(a) + local(a) + local(a) + local(a) + local(a) == 5 * (a ** 8)
// calling an imported function many times with the same arg should cost only once
dep(a) + dep(a) + dep(a) + dep(a) + dep(a) == 5 * (a ** 4)
return

View file

@ -10,5 +10,5 @@ wasm = ["bellman_ce/wasm", "sapling-crypto_ce/wasm"]
multicore = ["bellman_ce/multicore", "sapling-crypto_ce/multicore"]
[dependencies]
bellman_ce = { git = "https://github.com/matter-labs/bellman", rev = "9e35737", default-features = false}
bellman_ce = { version = "0.3.3", default-features = false}
sapling-crypto_ce = { version = "0.1.1", default-features = false }

View file

@ -12,8 +12,8 @@ bincode = "0.8.0"
serde_json = "1.0"
num-traits = { version = "0.2", default-features = false }
num-integer = { version = "0.1", default-features = false }
pairing_ce = "0.18"
ff_ce = { features = ["derive"], version = "0.7" }
pairing_ce = "0.20"
ff_ce = { features = ["derive"], version = "0.9" }
[dev-dependencies]
rand = "0.4"

File diff suppressed because it is too large Load diff

View file

@ -28,13 +28,13 @@
"test": "mocha --require esm --recursive tests"
},
"devDependencies": {
"dree": "^2.1.10",
"dree": "^2.4.14",
"esm": "^3.2.25",
"gulp": "^4.0.2",
"gulp-cli": "^2.2.0",
"mocha": "^6.2.2",
"rimraf": "^3.0.0",
"serve": "^11.2.0",
"mocha": "^7.1.1",
"rimraf": "^3.0.2",
"serve": "^11.3.0",
"text-encoding": "^0.7.0"
},
"dependencies": {}

View file

@ -122,11 +122,22 @@ mod tests {
rule: Rule::statement,
tokens: [
statement(0, 22, [
multi_assignment_statement(0, 9, [
optionally_typed_identifier(0, 1, [
identifier(0, 1)
definition_statement(0, 9, [
optionally_typed_assignee(0, 2, [
assignee(0, 2, [
identifier(0, 1)
])
]),
expression(4, 9, [
term(4, 9, [
postfix_expression(4, 9, [
identifier(4, 7),
access(7, 9, [
call_access(7, 9)
])
])
])
]),
identifier(4, 7),
])
])
]

View file

@ -36,22 +36,18 @@ vis = { vis_private | vis_public }
// Statements
statement = { (return_statement // does not require subsequent newline
| (iteration_statement
| multi_assignment_statement // try this first as we want all assignments based on return of function calls match here and not later
| definition_statement
| assignment_statement
| expression_statement
) ~ NEWLINE
) ~ NEWLINE* }
iteration_statement = { "for" ~ ty ~ identifier ~ "in" ~ expression ~ ".." ~ expression ~ "do" ~ NEWLINE* ~ statement* ~ "endfor"}
return_statement = { "return" ~ expression_list}
multi_assignment_statement = { optionally_typed_identifier_list ~ "=" ~ identifier ~ "(" ~ expression_list ~ ")"} // This is very specific with regards to parsing. However, I think more generality is not needed here.
definition_statement = {ty ~ identifier ~ "=" ~ expression} // declare and assign, so only identifiers are allowed, unlike `assignment_statement`
assignment_statement = {assignee ~ "=" ~ expression } // TODO: Is this optimal? Can the left side be written more elegantly?
definition_statement = { optionally_typed_assignee_list ~ "=" ~ expression } // declare and assign, so only identifiers are allowed, unlike `assignment_statement`
expression_statement = {expression}
optionally_typed_identifier_list = _{ optionally_typed_identifier ~ ("," ~ optionally_typed_identifier)* }
optionally_typed_identifier = { (identifier) | (ty ~ identifier) } // we don't use { ty? ~ identifier } as with a single token, it gets parsed as `ty` but we want `identifier`
optionally_typed_assignee_list = _{ optionally_typed_assignee ~ ("," ~ optionally_typed_assignee)* }
optionally_typed_assignee = { (ty ~ assignee) | (assignee) } // we don't use { ty? ~ identifier } as with a single token, it gets parsed as `ty` but we want `identifier`
// Expressions
expression_list = _{(expression ~ ("," ~ expression)*)?}
@ -118,7 +114,6 @@ op_unary = { op_not }
WHITESPACE = _{ " " | "\t" | "\\" ~ NEWLINE}
COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!NEWLINE ~ ANY)*) }
// TODO: Order by alphabet
keyword = @{"as"|"bool"|"byte"|"def"|"do"|"else"|"endfor"|"export"|"false"|"field"|"for"|"if"|"then"|"fi"|"import"|"from"|
"in"|"private"|"public"|"return"|"struct"|"true"|"uint"
}

View file

@ -9,11 +9,11 @@ extern crate lazy_static;
pub use ast::{
Access, ArrayAccess, ArrayInitializerExpression, ArrayType, AssertionStatement, Assignee,
AssigneeAccess, AssignmentStatement, BasicOrStructType, BasicType, BinaryExpression,
BinaryOperator, CallAccess, ConstantExpression, DefinitionStatement, Expression, File,
AssigneeAccess, BasicOrStructType, BasicType, BinaryExpression, BinaryOperator, CallAccess,
ConstantExpression, DecimalNumberExpression, DefinitionStatement, Expression, FieldType, File,
FromExpression, Function, IdentifierExpression, ImportDirective, ImportSource,
InlineArrayExpression, InlineStructExpression, InlineStructMember, IterationStatement,
MultiAssignmentStatement, Parameter, PostfixExpression, Range, RangeOrExpression,
OptionallyTypedAssignee, Parameter, PostfixExpression, Range, RangeOrExpression,
ReturnStatement, Span, Spread, SpreadOrExpression, Statement, StructDefinition, StructField,
TernaryExpression, ToExpression, Type, UnaryExpression, UnaryOperator, Visibility,
};
@ -315,24 +315,12 @@ mod ast {
Definition(DefinitionStatement<'ast>),
Assertion(AssertionStatement<'ast>),
Iteration(IterationStatement<'ast>),
Assignment(AssignmentStatement<'ast>),
MultiAssignment(MultiAssignmentStatement<'ast>),
}
#[derive(Debug, FromPest, PartialEq, Clone)]
#[pest_ast(rule(Rule::definition_statement))]
pub struct DefinitionStatement<'ast> {
pub ty: Type<'ast>,
pub id: IdentifierExpression<'ast>,
pub expression: Expression<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
#[derive(Debug, FromPest, PartialEq, Clone)]
#[pest_ast(rule(Rule::assignment_statement))]
pub struct AssignmentStatement<'ast> {
pub assignee: Assignee<'ast>,
pub lhs: Vec<OptionallyTypedAssignee<'ast>>,
pub expression: Expression<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
@ -358,16 +346,6 @@ mod ast {
pub span: Span<'ast>,
}
#[derive(Debug, FromPest, PartialEq, Clone)]
#[pest_ast(rule(Rule::multi_assignment_statement))]
pub struct MultiAssignmentStatement<'ast> {
pub lhs: Vec<OptionallyTypedIdentifier<'ast>>,
pub function_id: IdentifierExpression<'ast>,
pub arguments: Vec<Expression<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
#[derive(Debug, FromPest, PartialEq, Clone)]
#[pest_ast(rule(Rule::return_statement))]
pub struct ReturnStatement<'ast> {
@ -513,10 +491,10 @@ mod ast {
}
#[derive(Debug, FromPest, PartialEq, Clone)]
#[pest_ast(rule(Rule::optionally_typed_identifier))]
pub struct OptionallyTypedIdentifier<'ast> {
#[pest_ast(rule(Rule::optionally_typed_assignee))]
pub struct OptionallyTypedAssignee<'ast> {
pub ty: Option<Type<'ast>>,
pub id: IdentifierExpression<'ast>,
pub a: Assignee<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
@ -1018,54 +996,68 @@ mod tests {
returns: vec![Type::Basic(BasicType::Field(FieldType {
span: Span::new(&source, 15, 20).unwrap()
}))],
statements: vec![Statement::MultiAssignment(MultiAssignmentStatement {
function_id: IdentifierExpression {
value: String::from("foo"),
span: Span::new(&source, 36, 39).unwrap()
},
statements: vec![Statement::Definition(DefinitionStatement {
lhs: vec![
OptionallyTypedIdentifier {
OptionallyTypedAssignee {
ty: Some(Type::Basic(BasicType::Field(FieldType {
span: Span::new(&source, 23, 28).unwrap()
}))),
id: IdentifierExpression {
value: String::from("a"),
span: Span::new(&source, 29, 30).unwrap(),
a: Assignee {
id: IdentifierExpression {
value: String::from("a"),
span: Span::new(&source, 29, 30).unwrap(),
},
accesses: vec![],
span: Span::new(&source, 29, 30).unwrap()
},
span: Span::new(&source, 23, 30).unwrap()
},
OptionallyTypedIdentifier {
OptionallyTypedAssignee {
ty: None,
id: IdentifierExpression {
value: String::from("b"),
span: Span::new(&source, 32, 33).unwrap(),
a: Assignee {
id: IdentifierExpression {
value: String::from("b"),
span: Span::new(&source, 32, 33).unwrap(),
},
accesses: vec![],
span: Span::new(&source, 32, 34).unwrap()
},
span: Span::new(&source, 32, 33).unwrap()
span: Span::new(&source, 32, 34).unwrap()
},
],
arguments: vec![
Expression::Constant(ConstantExpression::DecimalNumber(
DecimalNumberExpression {
value: String::from("1"),
span: Span::new(&source, 40, 41).unwrap()
}
)),
Expression::add(
Expression::Constant(ConstantExpression::DecimalNumber(
DecimalNumberExpression {
value: String::from("2"),
span: Span::new(&source, 43, 44).unwrap()
}
)),
Expression::Constant(ConstantExpression::DecimalNumber(
DecimalNumberExpression {
value: String::from("3"),
span: Span::new(&source, 47, 48).unwrap()
}
)),
Span::new(&source, 43, 48).unwrap()
),
],
expression: Expression::Postfix(PostfixExpression {
id: IdentifierExpression {
value: String::from("foo"),
span: Span::new(&source, 36, 39).unwrap()
},
accesses: vec![Access::Call(CallAccess {
expressions: vec![
Expression::Constant(ConstantExpression::DecimalNumber(
DecimalNumberExpression {
value: String::from("1"),
span: Span::new(&source, 40, 41).unwrap()
}
)),
Expression::add(
Expression::Constant(ConstantExpression::DecimalNumber(
DecimalNumberExpression {
value: String::from("2"),
span: Span::new(&source, 43, 44).unwrap()
}
)),
Expression::Constant(ConstantExpression::DecimalNumber(
DecimalNumberExpression {
value: String::from("3"),
span: Span::new(&source, 47, 48).unwrap()
}
)),
Span::new(&source, 43, 48).unwrap()
),
],
span: Span::new(&source, 39, 49).unwrap()
})],
span: Span::new(&source, 36, 49).unwrap(),
}),
span: Span::new(&source, 23, 49).unwrap()
})],
span: Span::new(&source, 0, 50).unwrap(),