diff --git a/.circleci/config.yml b/.circleci/config.yml index 22d9f760..4bc00ba7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -47,17 +47,10 @@ jobs: no_output_timeout: 1h command: WITH_LIBSNARK=1 RUSTFLAGS="-D warnings" ./test.sh - save-sccache-cache - cpp_format: - docker: - - image: zokrates/env:latest - steps: - - checkout - - run: - name: Check cpp format (clang-format) - command: run-clang-format.py -r $(pwd)/zokrates_core/lib wasm_test: docker: - image: zokrates/env:latest + resource_class: large steps: - checkout - run: @@ -68,8 +61,8 @@ jobs: - run: name: Test on firefox command: | - cd zokrates_core - wasm-pack test --firefox --headless -- --no-default-features --features "wasm ark" + cd zokrates_test + wasm-pack test --firefox --headless - save-sccache-cache integration_test: docker: @@ -255,7 +248,6 @@ workflows: jobs: - build - test - - cpp_format - wasm_test - integration_test - zokrates_js_build @@ -314,7 +306,6 @@ workflows: requires: - build - test - - cpp_format - wasm_test - integration_test - zokrates_js_build diff --git a/Cargo.lock b/Cargo.lock index 1f27e682..013b4efa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,7 +140,7 @@ dependencies = [ "ark-serialize", "ark-std", "derivative", - "num-traits 0.2.14", + "num-traits 0.2.15", "zeroize", ] @@ -156,7 +156,7 @@ dependencies = [ "ark-std", "derivative", "num-bigint 0.4.3", - "num-traits 0.2.14", + "num-traits 0.2.15", "paste", "rustc_version", "zeroize", @@ -168,8 +168,8 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" dependencies = [ - "quote 1.0.17", - "syn 1.0.91", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -179,9 +179,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" dependencies = [ "num-bigint 0.4.3", - "num-traits 0.2.14", - "quote 1.0.17", - "syn 1.0.91", + "num-traits 0.2.15", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -246,7 +246,7 @@ dependencies = [ "derivative", "num-bigint 0.4.3", "num-integer", - "num-traits 0.2.14", + "num-traits 0.2.15", "tracing", ] @@ -291,7 +291,7 @@ dependencies = [ "ark-std", "derivative", "num-bigint 0.4.3", - "num-traits 0.2.14", + "num-traits 0.2.15", "tracing", ] @@ -323,9 +323,9 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8dd4e5f0bf8285d5ed538d27fab7411f3e297908fd93c62195de8bee3f199e82" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -345,7 +345,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" dependencies = [ - "num-traits 0.2.14", + "num-traits 0.2.15", "rand 0.8.5", ] @@ -402,9 +402,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7862e21c893d65a1650125d157eaeec691439379a1cee17ee49031b79236ada4" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -415,9 +415,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" +checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61" dependencies = [ "addr2line", "cc", @@ -644,7 +644,7 @@ checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ "camino", "cargo-platform", - "semver 1.0.7", + "semver 1.0.9", "serde", "serde_json", ] @@ -654,9 +654,6 @@ name = "cc" version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" -dependencies = [ - "jobserver", -] [[package]] name = "cfg-if" @@ -866,8 +863,8 @@ version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" dependencies = [ - "quote 1.0.17", - "syn 1.0.91", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -876,9 +873,9 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -1044,9 +1041,9 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", "synstructure", ] @@ -1065,17 +1062,6 @@ dependencies = [ "instant", ] -[[package]] -name = "ff_ce" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c0a6a2c53b0bd6d8cae976816dc8a171e0554c03f304e3dac110473e0219fd" -dependencies = [ - "byteorder", - "hex 0.4.3", - "rand 0.4.6", -] - [[package]] name = "ff_ce" version = "0.10.3" @@ -1096,10 +1082,10 @@ checksum = "50c052fa6d4c2f12305ec364bfb8ef884836f3f61ea015b202372ff996d1ac4b" dependencies = [ "num-bigint 0.2.6", "num-integer", - "num-traits 0.2.14", - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "num-traits 0.2.15", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -1276,6 +1262,12 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" + [[package]] name = "hashbrown" version = "0.11.2" @@ -1287,9 +1279,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c21d40587b92fa6a6c6e3c1bdbf87d75511db5672f9c93175574b3a00df1758" +checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" dependencies = [ "ahash", ] @@ -1354,19 +1346,19 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] name = "indexmap" -version = "1.8.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" dependencies = [ "autocfg", - "hashbrown 0.11.2", + "hashbrown 0.9.1", ] [[package]] @@ -1399,15 +1391,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" -[[package]] -name = "jobserver" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" -dependencies = [ - "libc", -] - [[package]] name = "js-sys" version = "0.3.57" @@ -1434,15 +1417,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.122" +version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259" +checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" [[package]] name = "log" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if 1.0.0", ] @@ -1461,9 +1444,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" @@ -1476,12 +1459,11 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.4.4" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" dependencies = [ "adler", - "autocfg", ] [[package]] @@ -1498,7 +1480,7 @@ checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" dependencies = [ "num-integer", "num-iter", - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] @@ -1512,7 +1494,7 @@ dependencies = [ "num-integer", "num-iter", "num-rational", - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] @@ -1523,7 +1505,7 @@ checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" dependencies = [ "autocfg", "num-integer", - "num-traits 0.2.14", + "num-traits 0.2.15", "serde", ] @@ -1535,37 +1517,37 @@ checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ "autocfg", "num-integer", - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] name = "num-complex" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085" +checksum = "97fbc387afefefd5e9e39493299f3069e14a140dd34dc19b4c1c1a8fddb6a790" dependencies = [ - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] name = "num-iter" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" dependencies = [ "autocfg", "num-integer", - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] @@ -1577,7 +1559,7 @@ dependencies = [ "autocfg", "num-bigint 0.4.3", "num-integer", - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] @@ -1586,14 +1568,14 @@ version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" dependencies = [ - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] @@ -1624,16 +1606,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] name = "object" -version = "0.27.1" +version = "0.28.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" dependencies = [ "memchr", ] @@ -1672,7 +1654,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfc00d65b1d29e0a067a967fcea83d8db261c149f76a557ba73f0304f01cdfde" dependencies = [ "byteorder", - "ff_ce 0.10.3", + "ff_ce", "rand 0.4.6", ] @@ -1697,9 +1679,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c45ed1f39709f5a89338fab50e59816b2e8815f5bb58276e7ddf9afd495f73f8" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -1748,9 +1730,9 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -1782,9 +1764,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -1840,9 +1822,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", "version_check", ] @@ -1852,8 +1834,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", + "proc-macro2 1.0.38", + "quote 1.0.18", "version_check", ] @@ -1868,11 +1850,11 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" +checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" dependencies = [ - "unicode-xid 0.2.2", + "unicode-xid 0.2.3", ] [[package]] @@ -1897,11 +1879,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.38", ] [[package]] @@ -2059,13 +2041,13 @@ dependencies = [ [[package]] name = "revm" -version = "1.2.0" -source = "git+https://github.com/bluealloy/revm#5f789910838ca144feb196dd91f88f5b5b1fe923" +version = "1.3.1" +source = "git+https://github.com/bluealloy/revm#8c63ba6c7f3667064608c2489c3e4b3e54451110" dependencies = [ "arrayref", "auto_impl", "bytes", - "hashbrown 0.12.0", + "hashbrown 0.12.1", "num_enum", "primitive-types", "revm_precompiles", @@ -2075,8 +2057,8 @@ dependencies = [ [[package]] name = "revm_precompiles" -version = "0.4.0" -source = "git+https://github.com/bluealloy/revm#5f789910838ca144feb196dd91f88f5b5b1fe923" +version = "1.0.0" +source = "git+https://github.com/bluealloy/revm#8c63ba6c7f3667064608c2489c3e4b3e54451110" dependencies = [ "bytes", "num 0.4.0", @@ -2183,9 +2165,9 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b5b9d7322572e1f3aeed208668ce87789b3645dbb73082c5ce99a004103a35" +checksum = "aa6f71720acd498e888501dd485d54bb437735f02dd95eb717dac5aee6631894" dependencies = [ "cc", ] @@ -2201,9 +2183,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4" +checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" dependencies = [ "serde", ] @@ -2219,9 +2201,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" dependencies = [ "serde_derive", ] @@ -2238,20 +2220,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] name = "serde_json" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ "indexmap", "itoa 1.0.1", @@ -2411,13 +2393,13 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.91" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" +checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "unicode-xid 0.2.2", + "proc-macro2 1.0.38", + "quote 1.0.18", + "unicode-xid 0.2.3", ] [[package]] @@ -2426,10 +2408,10 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", - "unicode-xid 0.2.2", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", + "unicode-xid 0.2.3", ] [[package]] @@ -2482,22 +2464,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -2520,18 +2502,18 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "serde", ] [[package]] name = "tracing" -version = "0.1.32" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" +checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", @@ -2541,20 +2523,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] name = "tracing-core" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90442985ee2f57c9e1b548ee72ae842f4a9a20e3f417cc38dbc5dc684d9bb4ee" +checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" [[package]] name = "typed-arena" @@ -2615,9 +2597,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" [[package]] name = "utf8-ranges" @@ -2667,6 +2649,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" dependencies = [ "cfg-if 1.0.0", + "serde", + "serde_json", "wasm-bindgen-macro", ] @@ -2679,9 +2663,9 @@ dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", "wasm-bindgen-shared", ] @@ -2703,7 +2687,7 @@ version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" dependencies = [ - "quote 1.0.17", + "quote 1.0.18", "wasm-bindgen-macro-support", ] @@ -2713,9 +2697,9 @@ version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2746,8 +2730,8 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a77c5a6f82cc6093a321ca5fb3dc9327fe51675d477b3799b4a9375bac3b7b4c" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", + "proc-macro2 1.0.38", + "quote 1.0.18", ] [[package]] @@ -2802,9 +2786,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb5728b8afd3f280a869ce1d4c554ffaed35f45c231fc41bfbd0381bef50317" +checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" dependencies = [ "zeroize_derive", ] @@ -2815,9 +2799,9 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", "synstructure", ] @@ -2828,10 +2812,70 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "zokrates_core", + "zokrates_ast", "zokrates_field", ] +[[package]] +name = "zokrates_ark" +version = "0.1.0" +dependencies = [ + "ark-bls12-377", + "ark-bn254", + "ark-bw6-761", + "ark-crypto-primitives", + "ark-ec", + "ark-ff", + "ark-gm17", + "ark-groth16", + "ark-marlin", + "ark-poly", + "ark-poly-commit", + "ark-relations", + "ark-serialize", + "digest 0.9.0", + "hex 0.4.3", + "rand 0.8.5", + "sha3 0.9.1", + "zokrates_ast", + "zokrates_field", + "zokrates_interpreter", + "zokrates_proof_systems", +] + +[[package]] +name = "zokrates_ast" +version = "0.1.0" +dependencies = [ + "ark-bls12-377", + "cfg-if 0.1.10", + "csv", + "num-bigint 0.2.6", + "pairing_ce", + "serde", + "serde_cbor", + "serde_json", + "zokrates_embed", + "zokrates_field", + "zokrates_pest_ast", +] + +[[package]] +name = "zokrates_bellman" +version = "0.1.0" +dependencies = [ + "bellman_ce", + "getrandom", + "hex 0.4.3", + "pairing_ce", + "phase2", + "rand 0.4.6", + "zokrates_ast", + "zokrates_field", + "zokrates_interpreter", + "zokrates_proof_systems", +] + [[package]] name = "zokrates_cli" version = "0.7.13" @@ -2860,10 +2904,15 @@ dependencies = [ "tempdir", "typed-arena", "zokrates_abi", + "zokrates_ark", + "zokrates_ast", + "zokrates_bellman", "zokrates_common", "zokrates_core", "zokrates_field", "zokrates_fs_resolver", + "zokrates_interpreter", + "zokrates_proof_systems", "zokrates_solidity_test", ] @@ -2875,51 +2924,23 @@ version = "0.1.0" name = "zokrates_core" version = "0.6.12" dependencies = [ - "ark-bls12-377", - "ark-bn254", - "ark-bw6-761", - "ark-crypto-primitives", - "ark-ec", - "ark-ff", - "ark-gm17", - "ark-groth16", - "ark-marlin", - "ark-poly", - "ark-poly-commit", - "ark-relations", - "ark-serialize", - "bellman_ce", - "cc", "cfg-if 0.1.10", - "cmake", "csv", - "digest 0.9.0", - "ethabi", - "ff_ce 0.9.0", - "getrandom", - "hex 0.4.3", "lazy_static", "log", "num 0.1.42", "num-bigint 0.2.6", - "pairing_ce", - "phase2", "pretty_assertions", - "primitive-types", - "rand 0.4.6", - "rand 0.8.5", "reduce", - "regex 0.2.11", "serde", - "serde_cbor", "serde_json", - "sha3 0.9.1", "typed-arena", - "wasm-bindgen-test", + "zokrates_ast", "zokrates_common", "zokrates_embed", "zokrates_field", "zokrates_fs_resolver", + "zokrates_interpreter", "zokrates_pest_ast", ] @@ -2965,7 +2986,7 @@ dependencies = [ "lazy_static", "num-bigint 0.2.6", "num-integer", - "num-traits 0.2.14", + "num-traits 0.2.15", "rand 0.4.6", "serde", "serde_derive", @@ -2981,6 +3002,41 @@ dependencies = [ "zokrates_common", ] +[[package]] +name = "zokrates_interpreter" +version = "0.1.0" +dependencies = [ + "ark-bls12-377", + "num 0.1.42", + "num-bigint 0.2.6", + "pairing_ce", + "serde", + "zokrates_ast", + "zokrates_embed", + "zokrates_field", +] + +[[package]] +name = "zokrates_js" +version = "1.0.43" +dependencies = [ + "console_error_panic_hook", + "indexmap", + "js-sys", + "serde", + "serde_json", + "typed-arena", + "wasm-bindgen", + "zokrates_abi", + "zokrates_ark", + "zokrates_ast", + "zokrates_common", + "zokrates_core", + "zokrates_field", + "zokrates_interpreter", + "zokrates_proof_systems", +] + [[package]] name = "zokrates_parser" version = "0.2.6" @@ -3002,6 +3058,22 @@ dependencies = [ "zokrates_parser", ] +[[package]] +name = "zokrates_proof_systems" +version = "0.1.0" +dependencies = [ + "cfg-if 0.1.10", + "ethabi", + "getrandom", + "hex 0.4.3", + "primitive-types", + "rand 0.4.6", + "regex 0.2.11", + "serde", + "zokrates_ast", + "zokrates_field", +] + [[package]] name = "zokrates_solidity_test" version = "0.1.0" @@ -3033,10 +3105,16 @@ dependencies = [ "serde_derive", "serde_json", "typed-arena", + "wasm-bindgen-test", "zokrates_abi", + "zokrates_ark", + "zokrates_ast", + "zokrates_common", "zokrates_core", "zokrates_field", "zokrates_fs_resolver", + "zokrates_interpreter", + "zokrates_proof_systems", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 80ac413c..b09fa804 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,13 @@ members = [ "zokrates_test", "zokrates_core_test", "zokrates_solidity_test", + "zokrates_ark", + "zokrates_ast", + "zokrates_interpreter", + "zokrates_embed", + "zokrates_bellman", + "zokrates_proof_systems", + "zokrates_js", ] -exclude = ["zokrates_js"] \ No newline at end of file +exclude = [] \ No newline at end of file diff --git a/Dockerfile.env b/Dockerfile.env index eee307da..1be291a8 100644 --- a/Dockerfile.env +++ b/Dockerfile.env @@ -15,14 +15,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ build-essential \ software-properties-common \ - cmake \ - gnupg \ - libboost-all-dev \ - libgmp3-dev \ - libprocps-dev \ - libssl-dev \ pkg-config \ - clang-format \ python-is-python3 \ python-markdown \ && add-apt-repository ppa:mozillateam/ppa \ diff --git a/build.sh b/build.sh index 64994644..c467308b 100755 --- a/build.sh +++ b/build.sh @@ -3,8 +3,4 @@ # Exit if any subcommand fails set -e -if [ -n "$WITH_LIBSNARK" ]; then - cargo build --package zokrates_cli --features="libsnark" -else - cargo build --package zokrates_cli -fi \ No newline at end of file +cargo build --package zokrates_cli \ No newline at end of file diff --git a/build_release.sh b/build_release.sh index d57d78c7..dbc89108 100755 --- a/build_release.sh +++ b/build_release.sh @@ -4,8 +4,4 @@ set -e export RUSTFLAGS="--remap-path-prefix=$PWD=" -if [ -n "$WITH_LIBSNARK" ]; then - cargo build --release --package zokrates_cli --features="libsnark" -else - cargo build --release --package zokrates_cli -fi +cargo build --release --package zokrates_cli diff --git a/changelogs/unreleased/1151-schaeff b/changelogs/unreleased/1151-schaeff new file mode 100644 index 00000000..ceac4401 --- /dev/null +++ b/changelogs/unreleased/1151-schaeff @@ -0,0 +1 @@ +Split codebase into smaller crates \ No newline at end of file diff --git a/changelogs/unreleased/1153-schaeff b/changelogs/unreleased/1153-schaeff new file mode 100644 index 00000000..4a96037f --- /dev/null +++ b/changelogs/unreleased/1153-schaeff @@ -0,0 +1 @@ +Drop support for libsnark \ No newline at end of file diff --git a/dev.Dockerfile b/dev.Dockerfile index abffa9d0..267cf436 100644 --- a/dev.Dockerfile +++ b/dev.Dockerfile @@ -4,11 +4,6 @@ MAINTAINER JacobEberhardt , Thibaut Schaeffer "] edition = "2018" +[features] +default = ["ark", "bellman"] +ark = ["zokrates_ast/ark"] +bellman = ["zokrates_ast/bellman"] + [dependencies] zokrates_field = { version = "0.5", path = "../zokrates_field", default-features = false } -zokrates_core = { version = "0.6", path = "../zokrates_core", default-features = false } +zokrates_ast = { version = "0.1", path = "../zokrates_ast", default-features = false } serde = "1.0" serde_derive = "1.0" serde_json = { version = "1.0", features = ["preserve_order"] } diff --git a/zokrates_abi/src/lib.rs b/zokrates_abi/src/lib.rs index 8136d583..6454c202 100644 --- a/zokrates_abi/src/lib.rs +++ b/zokrates_abi/src/lib.rs @@ -15,7 +15,7 @@ impl Encode for Inputs { } use std::fmt; -use zokrates_core::typed_absy::types::{ConcreteType, UBitwidth}; +use zokrates_ast::typed::types::{ConcreteType, UBitwidth}; use zokrates_field::Field; @@ -380,9 +380,7 @@ pub fn parse_strict_json( #[cfg(test)] mod tests { use super::*; - use zokrates_core::typed_absy::types::{ - ConcreteStructMember, ConcreteStructType, ConcreteType, - }; + use zokrates_ast::typed::types::{ConcreteStructMember, ConcreteStructType, ConcreteType}; use zokrates_field::Bn128Field; #[test] diff --git a/zokrates_ark/Cargo.toml b/zokrates_ark/Cargo.toml new file mode 100644 index 00000000..a90cbd26 --- /dev/null +++ b/zokrates_ark/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "zokrates_ark" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +zokrates_field = { version = "0.5", path = "../zokrates_field", default-features = false } +zokrates_ast = { version = "0.1", path = "../zokrates_ast", default-features = false } +zokrates_proof_systems = { version = "0.1", path = "../zokrates_proof_systems", default-features = false } + +ark-ff = { version = "^0.3.0", default-features = false } +ark-ec = { version = "^0.3.0", default-features = false } +ark-bn254 = { version = "^0.3.0", features = ["curve"], default-features = false } +ark-bls12-377 = { version = "^0.3.0", features = ["curve"], default-features = false } +ark-bw6-761 = { version = "^0.3.0", default-features = false } +ark-gm17 = { version = "^0.3.0", default-features = false } +ark-groth16 = { version = "^0.3.0", default-features = false } +ark-serialize = { version = "^0.3.0", default-features = false } +ark-relations = { version = "^0.3.0", default-features = false } +ark-marlin = { git = "https://github.com/arkworks-rs/marlin", rev = "63cfd82", default-features = false } +ark-poly = { version = "^0.3.0", default-features = false } +ark-poly-commit = { version = "^0.3.0", default-features = false } +ark-crypto-primitives = { version = "^0.3.0", default-features = false } +sha3 = { version = "0.9" } +digest = { version = "0.9" } +rand_0_8 = { version = "0.8", package = "rand" } +hex = "0.4.2" + +[dev-dependencies] +zokrates_interpreter = { version = "0.1", path = "../zokrates_interpreter", features = ["ark"] } + + diff --git a/zokrates_ark/src/gm17.rs b/zokrates_ark/src/gm17.rs new file mode 100644 index 00000000..2e4fc842 --- /dev/null +++ b/zokrates_ark/src/gm17.rs @@ -0,0 +1,163 @@ +use ark_crypto_primitives::SNARK; +use ark_gm17::{ + prepare_verifying_key, verify_proof, PreparedVerifyingKey, Proof as ArkProof, ProvingKey, + VerifyingKey, GM17 as ArkGM17, +}; +use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; +use zokrates_field::{ArkFieldExtensions, Field}; + +use crate::Computation; +use crate::{parse_fr, parse_g1, parse_g2}; +use crate::{serialization, Ark}; +use rand_0_8::{rngs::StdRng, SeedableRng}; +use zokrates_ast::ir::{ProgIterator, Statement, Witness}; +use zokrates_proof_systems::gm17::{ProofPoints, VerificationKey, GM17}; +use zokrates_proof_systems::Scheme; +use zokrates_proof_systems::{Backend, NonUniversalBackend, Proof, SetupKeypair}; + +impl NonUniversalBackend for Ark { + fn setup>>( + program: ProgIterator, + ) -> SetupKeypair { + let computation = Computation::without_witness(program); + + let rng = &mut StdRng::from_entropy(); + let (pk, vk) = ArkGM17::::circuit_specific_setup(computation, rng).unwrap(); + + let mut pk_vec: Vec = Vec::new(); + pk.serialize_uncompressed(&mut pk_vec).unwrap(); + + let vk = VerificationKey { + h: parse_g2::(&vk.h_g2), + g_alpha: parse_g1::(&vk.g_alpha_g1), + h_beta: parse_g2::(&vk.h_beta_g2), + g_gamma: parse_g1::(&vk.g_gamma_g1), + h_gamma: parse_g2::(&vk.h_gamma_g2), + query: vk.query.iter().map(|g1| parse_g1::(g1)).collect(), + }; + + SetupKeypair::new(vk, pk_vec) + } +} + +impl Backend for Ark { + fn generate_proof>>( + program: ProgIterator, + witness: Witness, + proving_key: Vec, + ) -> Proof { + let computation = Computation::with_witness(program, witness); + + let inputs = computation + .public_inputs_values() + .iter() + .map(parse_fr::) + .collect::>(); + + let pk = ProvingKey::<::ArkEngine>::deserialize_uncompressed( + &mut proving_key.as_slice(), + ) + .unwrap(); + + let rng = &mut StdRng::from_entropy(); + let proof = ArkGM17::::prove(&pk, computation, rng).unwrap(); + + let proof_points = ProofPoints { + a: parse_g1::(&proof.a), + b: parse_g2::(&proof.b), + c: parse_g1::(&proof.c), + }; + + Proof::new(proof_points, inputs) + } + + fn verify(vk: >::VerificationKey, proof: Proof) -> bool { + let vk = VerifyingKey { + h_g2: serialization::to_g2::(vk.h), + g_alpha_g1: serialization::to_g1::(vk.g_alpha), + h_beta_g2: serialization::to_g2::(vk.h_beta), + g_gamma_g1: serialization::to_g1::(vk.g_gamma), + h_gamma_g2: serialization::to_g2::(vk.h_gamma), + query: vk + .query + .into_iter() + .map(serialization::to_g1::) + .collect(), + }; + + let ark_proof = ArkProof { + a: serialization::to_g1::(proof.proof.a), + b: serialization::to_g2::(proof.proof.b), + c: serialization::to_g1::(proof.proof.c), + }; + + let pvk: PreparedVerifyingKey<::ArkEngine> = + prepare_verifying_key(&vk); + + let public_inputs: Vec<_> = proof + .inputs + .iter() + .map(|s| { + T::try_from_str(s.trim_start_matches("0x"), 16) + .unwrap() + .into_ark() + }) + .collect::>(); + + verify_proof(&pvk, &ark_proof, &public_inputs).unwrap() + } +} + +#[cfg(test)] +mod tests { + use zokrates_ast::flat::{Parameter, Variable}; + use zokrates_ast::ir::{Prog, Statement}; + use zokrates_interpreter::Interpreter; + + use super::*; + use zokrates_field::{Bls12_377Field, Bw6_761Field}; + + #[test] + fn verify_bls12_377_field() { + let program: Prog = Prog { + arguments: vec![Parameter::public(Variable::new(0))], + return_count: 1, + statements: vec![Statement::constraint(Variable::new(0), Variable::public(0))], + }; + + let keypair = >::setup(program.clone()); + let interpreter = Interpreter::default(); + + let witness = interpreter + .execute(program.clone(), &[Bls12_377Field::from(42)]) + .unwrap(); + + let proof = + >::generate_proof(program, witness, keypair.pk); + let ans = >::verify(keypair.vk, proof); + + assert!(ans); + } + + #[test] + fn verify_bw6_761_field() { + let program: Prog = Prog { + arguments: vec![Parameter::public(Variable::new(0))], + return_count: 1, + statements: vec![Statement::constraint(Variable::new(0), Variable::public(0))], + }; + + let keypair = >::setup(program.clone()); + let interpreter = Interpreter::default(); + + let witness = interpreter + .execute(program.clone(), &[Bw6_761Field::from(42)]) + .unwrap(); + + let proof = + >::generate_proof(program, witness, keypair.pk); + let ans = >::verify(keypair.vk, proof); + + assert!(ans); + } +} diff --git a/zokrates_core/src/proof_system/ark/groth16.rs b/zokrates_ark/src/groth16.rs similarity index 51% rename from zokrates_core/src/proof_system/ark/groth16.rs rename to zokrates_ark/src/groth16.rs index f687b448..69e12ba1 100644 --- a/zokrates_core/src/proof_system/ark/groth16.rs +++ b/zokrates_ark/src/groth16.rs @@ -1,25 +1,24 @@ -use crate::proof_system::{Backend, NonUniversalBackend, NotBw6_761Field, Proof, SetupKeypair}; use ark_crypto_primitives::SNARK; use ark_groth16::{ prepare_verifying_key, verify_proof, Groth16, PreparedVerifyingKey, Proof as ArkProof, ProvingKey, VerifyingKey, }; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; +use zokrates_field::ArkFieldExtensions; use zokrates_field::Field; -use zokrates_field::{ArkFieldExtensions, Bw6_761Field}; +use zokrates_proof_systems::{Backend, NonUniversalBackend, Proof, SetupKeypair}; -use crate::ir::{ProgIterator, Statement, Witness}; -use crate::proof_system::ark::Computation; -use crate::proof_system::ark::{parse_fr, serialization, Ark}; -use crate::proof_system::ark::{parse_g1, parse_g2}; -use crate::proof_system::groth16::{ProofPoints, VerificationKey, G16}; -use crate::proof_system::Scheme; -use ark_bw6_761::BW6_761; +use crate::Computation; +use crate::{parse_fr, serialization, Ark}; +use crate::{parse_g1, parse_g2}; use rand_0_8::{rngs::StdRng, SeedableRng}; +use zokrates_ast::ir::{ProgIterator, Statement, Witness}; +use zokrates_proof_systems::groth16::{ProofPoints, VerificationKey, G16}; +use zokrates_proof_systems::Scheme; const G16_WARNING: &str = "WARNING: You are using the G16 scheme which is subject to malleability. See zokrates.github.io/toolbox/proving_schemes.html#g16-malleability for implications."; -impl Backend for Ark { +impl Backend for Ark { fn generate_proof>>( program: ProgIterator, witness: Witness, @@ -86,7 +85,7 @@ impl Backend for Ark { } } -impl NonUniversalBackend for Ark { +impl NonUniversalBackend for Ark { fn setup>>( program: ProgIterator, ) -> SetupKeypair { @@ -112,108 +111,11 @@ impl NonUniversalBackend for Ark { - fn generate_proof>>( - program: ProgIterator, - witness: Witness, - proving_key: Vec, - ) -> Proof { - println!("{}", G16_WARNING); - - let computation = Computation::with_witness(program, witness); - - let inputs = computation - .public_inputs_values() - .iter() - .map(parse_fr::) - .collect::>(); - - let pk = - ProvingKey::::deserialize_uncompressed(&mut proving_key.as_slice()).unwrap(); - - let rng = &mut StdRng::from_entropy(); - let proof = Groth16::::prove(&pk, computation, rng).unwrap(); - - let proof_points = ProofPoints { - a: parse_g1::(&proof.a), - b: parse_g2::(&proof.b), - c: parse_g1::(&proof.c), - }; - - Proof::new(proof_points, inputs) - } - - fn verify( - vk: >::VerificationKey, - proof: Proof, - ) -> bool { - let vk = VerifyingKey { - alpha_g1: serialization::to_g1::(vk.alpha), - beta_g2: serialization::to_g2::(vk.beta), - gamma_g2: serialization::to_g2::(vk.gamma), - delta_g2: serialization::to_g2::(vk.delta), - gamma_abc_g1: vk - .gamma_abc - .into_iter() - .map(serialization::to_g1::) - .collect(), - }; - - let pvk: PreparedVerifyingKey = prepare_verifying_key(&vk); - let ark_proof = ArkProof { - a: serialization::to_g1::(proof.proof.a), - b: serialization::to_g2::(proof.proof.b), - c: serialization::to_g1::(proof.proof.c), - }; - - let public_inputs: Vec<_> = proof - .inputs - .iter() - .map(|s| { - Bw6_761Field::try_from_str(s.trim_start_matches("0x"), 16) - .unwrap() - .into_ark() - }) - .collect::>(); - - verify_proof(&pvk, &ark_proof, &public_inputs).unwrap() - } -} - -impl NonUniversalBackend for Ark { - fn setup>>( - program: ProgIterator, - ) -> SetupKeypair { - println!("{}", G16_WARNING); - - let computation = Computation::without_witness(program); - - let rng = &mut StdRng::from_entropy(); - let (pk, vk) = Groth16::::circuit_specific_setup(computation, rng).unwrap(); - - let mut pk_vec: Vec = Vec::new(); - pk.serialize_uncompressed(&mut pk_vec).unwrap(); - - let vk = VerificationKey { - alpha: parse_g1::(&vk.alpha_g1), - beta: parse_g2::(&vk.beta_g2), - gamma: parse_g2::(&vk.gamma_g2), - delta: parse_g2::(&vk.delta_g2), - gamma_abc: vk - .gamma_abc_g1 - .iter() - .map(parse_g1::) - .collect(), - }; - - SetupKeypair::new(vk, pk_vec) - } -} - #[cfg(test)] mod tests { - use crate::flat_absy::{FlatParameter, FlatVariable}; - use crate::ir::{Interpreter, Prog, Statement}; + use zokrates_ast::flat::{Parameter, Variable}; + use zokrates_ast::ir::{Prog, Statement}; + use zokrates_interpreter::Interpreter; use super::*; use zokrates_field::{Bls12_377Field, Bw6_761Field}; @@ -221,12 +123,9 @@ mod tests { #[test] fn verify_bls12_377_field() { let program: Prog = Prog { - arguments: vec![FlatParameter::public(FlatVariable::new(0))], + arguments: vec![Parameter::public(Variable::new(0))], return_count: 1, - statements: vec![Statement::constraint( - FlatVariable::new(0), - FlatVariable::public(0), - )], + statements: vec![Statement::constraint(Variable::new(0), Variable::public(0))], }; let keypair = >::setup(program.clone()); @@ -246,12 +145,9 @@ mod tests { #[test] fn verify_bw6_761_field() { let program: Prog = Prog { - arguments: vec![FlatParameter::public(FlatVariable::new(0))], + arguments: vec![Parameter::public(Variable::new(0))], return_count: 1, - statements: vec![Statement::constraint( - FlatVariable::new(0), - FlatVariable::public(0), - )], + statements: vec![Statement::constraint(Variable::new(0), Variable::public(0))], }; let keypair = >::setup(program.clone()); diff --git a/zokrates_core/src/proof_system/ark/mod.rs b/zokrates_ark/src/lib.rs similarity index 71% rename from zokrates_core/src/proof_system/ark/mod.rs rename to zokrates_ark/src/lib.rs index 192d7303..6df8e5c6 100644 --- a/zokrates_core/src/proof_system/ark/mod.rs +++ b/zokrates_ark/src/lib.rs @@ -2,14 +2,14 @@ pub mod gm17; pub mod groth16; pub mod marlin; -use crate::flat_absy::FlatVariable; -use crate::ir::{CanonicalLinComb, ProgIterator, Statement, Witness}; use ark_ec::PairingEngine; use ark_relations::r1cs::{ ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, LinearCombination, - SynthesisError, Variable, + SynthesisError, Variable as ArkVariable, }; use std::collections::BTreeMap; +use zokrates_ast::common::Variable; +use zokrates_ast::ir::{CanonicalLinComb, ProgIterator, Statement, Witness}; use zokrates_field::{ArkFieldExtensions, Field}; pub use self::parse::*; @@ -41,7 +41,7 @@ impl>> Computation { fn ark_combination( l: CanonicalLinComb, cs: &mut ConstraintSystem<<::ArkEngine as PairingEngine>::Fr>, - symbols: &mut BTreeMap, + symbols: &mut BTreeMap, witness: &mut Witness, ) -> LinearCombination<<::ArkEngine as PairingEngine>::Fr> { l.0.into_iter() @@ -72,23 +72,35 @@ fn ark_combination( .fold(LinearCombination::zero(), |acc, e| acc + e) } -impl>> ProgIterator { - pub fn generate_constraints( +impl>> Computation { + pub fn public_inputs_values(&self) -> Vec<::Fr> { + self.program + .public_inputs(self.witness.as_ref().unwrap()) + .iter() + .map(|v| v.clone().into_ark()) + .collect() + } +} + +impl>> + ConstraintSynthesizer<<::ArkEngine as PairingEngine>::Fr> + for Computation +{ + fn generate_constraints( self, cs: ConstraintSystemRef<<::ArkEngine as PairingEngine>::Fr>, - witness: Option>, ) -> Result<(), SynthesisError> { // mapping from IR variables let mut symbols = BTreeMap::new(); - let mut witness = witness.unwrap_or_else(Witness::empty); + let mut witness = self.witness.unwrap_or_else(Witness::empty); - assert!(symbols.insert(FlatVariable::one(), ConstraintSystem::<<::ArkEngine as PairingEngine>::Fr>::one()).is_none()); + assert!(symbols.insert(Variable::one(), ConstraintSystem::<<::ArkEngine as PairingEngine>::Fr>::one()).is_none()); match cs { ConstraintSystemRef::CS(rc) => { let mut cs = rc.borrow_mut(); - symbols.extend(self.arguments.iter().enumerate().map(|(_, p)| { + symbols.extend(self.program.arguments.iter().enumerate().map(|(_, p)| { let wire = match p.private { true => cs.new_witness_variable(|| { Ok(witness @@ -109,7 +121,7 @@ impl>> ProgIt (p.id, wire) })); - for statement in self.statements { + for statement in self.program.statements { if let Statement::Constraint(quad, lin, _) = statement { let a = ark_combination( quad.left.clone().into_canonical(), @@ -141,32 +153,11 @@ impl>> ProgIt } } -impl>> Computation { - pub fn public_inputs_values(&self) -> Vec<::Fr> { - self.program - .public_inputs(self.witness.as_ref().unwrap()) - .iter() - .map(|v| v.clone().into_ark()) - .collect() - } -} - -impl>> - ConstraintSynthesizer<<::ArkEngine as PairingEngine>::Fr> - for Computation -{ - fn generate_constraints( - self, - cs: ConstraintSystemRef<<::ArkEngine as PairingEngine>::Fr>, - ) -> Result<(), SynthesisError> { - self.program.generate_constraints(cs, self.witness) - } -} - mod parse { use super::*; - use crate::proof_system::{Fr, G1Affine, G2Affine, G2AffineFq}; use ark_ff::ToBytes; + use zokrates_field::G2Type; + use zokrates_proof_systems::{Fr, G1Affine, G2Affine, G2AffineFq, G2AffineFq2}; pub fn parse_g1( e: &::G1Affine, @@ -196,48 +187,46 @@ mod parse { e.write(&mut bytes).unwrap(); let length = bytes.len() - 1; // [x, y, infinity] - infinity - let element_length = length / 4; - let mut elements = vec![]; - for i in 0..4 { - let start = i * element_length; - let end = start + element_length; - let mut e = bytes[start..end].to_vec(); - e.reverse(); - elements.push(e); + match T::G2_TYPE { + G2Type::Fq2 => { + let element_length = length / 4; + + let mut elements = vec![]; + for i in 0..4 { + let start = i * element_length; + let end = start + element_length; + let mut e = bytes[start..end].to_vec(); + e.reverse(); + elements.push(e); + } + + G2Affine::Fq2(G2AffineFq2( + ( + format!("0x{}", hex::encode(&elements[0])), + format!("0x{}", hex::encode(&elements[1])), + ), + ( + format!("0x{}", hex::encode(&elements[2])), + format!("0x{}", hex::encode(&elements[3])), + ), + )) + } + G2Type::Fq => { + let element_length = length / 2; + + let mut x = bytes[0..element_length].to_vec(); + let mut y = bytes[element_length..length].to_vec(); + + x.reverse(); + y.reverse(); + + G2Affine::Fq(G2AffineFq( + format!("0x{}", hex::encode(&x)), + format!("0x{}", hex::encode(&y)), + )) + } } - - G2Affine( - ( - format!("0x{}", hex::encode(&elements[0])), - format!("0x{}", hex::encode(&elements[1])), - ), - ( - format!("0x{}", hex::encode(&elements[2])), - format!("0x{}", hex::encode(&elements[3])), - ), - ) - } - - pub fn parse_g2_fq( - e: &::G2Affine, - ) -> G2AffineFq { - let mut bytes: Vec = Vec::new(); - e.write(&mut bytes).unwrap(); - - let length = bytes.len() - 1; // [x, y, infinity] - infinity - let element_length = length / 2; - - let mut x = bytes[0..element_length].to_vec(); - let mut y = bytes[element_length..length].to_vec(); - - x.reverse(); - y.reverse(); - - G2AffineFq( - format!("0x{}", hex::encode(&x)), - format!("0x{}", hex::encode(&y)), - ) } pub fn parse_fr(e: &::Fr) -> Fr { @@ -250,10 +239,10 @@ mod parse { } pub mod serialization { - use crate::proof_system::{G1Affine, G2Affine, G2AffineFq}; use ark_ec::PairingEngine; use ark_ff::FromBytes; use zokrates_field::ArkFieldExtensions; + use zokrates_proof_systems::{G1Affine, G2Affine}; #[inline] fn decode_hex(value: String) -> Vec { @@ -273,22 +262,21 @@ pub mod serialization { pub fn to_g2(g2: G2Affine) -> ::G2Affine { let mut bytes = vec![]; - bytes.append(&mut decode_hex((g2.0).0)); - bytes.append(&mut decode_hex((g2.0).1)); - bytes.append(&mut decode_hex((g2.1).0)); - bytes.append(&mut decode_hex((g2.1).1)); - bytes.push(0u8); // infinity flag - ::G2Affine::read(&*bytes).unwrap() - } - - pub fn to_g2_fq( - g2: G2AffineFq, - ) -> ::G2Affine { - let mut bytes = vec![]; - bytes.append(&mut decode_hex(g2.0)); - bytes.append(&mut decode_hex(g2.1)); - bytes.push(0u8); // infinity flag + match g2 { + G2Affine::Fq(g2) => { + bytes.append(&mut decode_hex(g2.0)); + bytes.append(&mut decode_hex(g2.1)); + bytes.push(0u8); // infinity flag + } + G2Affine::Fq2(g2) => { + bytes.append(&mut decode_hex((g2.0).0)); + bytes.append(&mut decode_hex((g2.0).1)); + bytes.append(&mut decode_hex((g2.1).0)); + bytes.append(&mut decode_hex((g2.1).1)); + bytes.push(0u8); // infinity flag + } + }; ::G2Affine::read(&*bytes).unwrap() } diff --git a/zokrates_core/src/proof_system/ark/marlin.rs b/zokrates_ark/src/marlin.rs similarity index 93% rename from zokrates_core/src/proof_system/ark/marlin.rs rename to zokrates_ark/src/marlin.rs index 7f105b23..823e91dd 100644 --- a/zokrates_core/src/proof_system/ark/marlin.rs +++ b/zokrates_ark/src/marlin.rs @@ -23,13 +23,13 @@ use std::marker::PhantomData; use zokrates_field::{ArkFieldExtensions, Field}; -use crate::ir::{ProgIterator, Statement, Witness}; -use crate::proof_system::ark::Ark; -use crate::proof_system::ark::Computation; -use crate::proof_system::ark::{parse_fr, parse_g1, parse_g2, serialization}; -use crate::proof_system::marlin::{self, KZGVerifierKey, ProofPoints, VerificationKey}; -use crate::proof_system::Scheme; -use crate::proof_system::{Backend, Proof, SetupKeypair, UniversalBackend}; +use crate::Ark; +use crate::Computation; +use crate::{parse_fr, parse_g1, parse_g2, serialization}; +use zokrates_ast::ir::{ProgIterator, Statement, Witness}; +use zokrates_proof_systems::marlin::{self, KZGVerifierKey, ProofPoints, VerificationKey}; +use zokrates_proof_systems::Scheme; +use zokrates_proof_systems::{Backend, Proof, SetupKeypair, UniversalBackend}; const MINIMUM_CONSTRAINT_COUNT: usize = 2; @@ -386,27 +386,28 @@ impl Backend for Ark { #[cfg(test)] mod tests { - use crate::flat_absy::{FlatParameter, FlatVariable}; - use crate::ir::{Interpreter, Prog, QuadComb, Statement}; + use zokrates_ast::flat::{Parameter, Variable}; + use zokrates_ast::ir::{Prog, QuadComb, Statement}; + use zokrates_interpreter::Interpreter; use super::*; - use crate::proof_system::scheme::Marlin; use zokrates_field::{Bls12_377Field, Bw6_761Field}; + use zokrates_proof_systems::Marlin; #[test] fn verify_bls12_377_field() { let program: Prog = Prog { - arguments: vec![FlatParameter::private(FlatVariable::new(0))], + arguments: vec![Parameter::private(Variable::new(0))], return_count: 1, statements: vec![ Statement::constraint( QuadComb::from_linear_combinations( - FlatVariable::new(0).into(), - FlatVariable::new(0).into(), + Variable::new(0).into(), + Variable::new(0).into(), ), - FlatVariable::new(1), + Variable::new(1), ), - Statement::constraint(FlatVariable::new(1), FlatVariable::public(0)), + Statement::constraint(Variable::new(1), Variable::public(0)), ], }; @@ -429,17 +430,17 @@ mod tests { #[test] fn verify_bw6_761_field() { let program: Prog = Prog { - arguments: vec![FlatParameter::private(FlatVariable::new(0))], + arguments: vec![Parameter::private(Variable::new(0))], return_count: 1, statements: vec![ Statement::constraint( QuadComb::from_linear_combinations( - FlatVariable::new(0).into(), - FlatVariable::new(0).into(), + Variable::new(0).into(), + Variable::new(0).into(), ), - FlatVariable::new(1), + Variable::new(1), ), - Statement::constraint(FlatVariable::new(1), FlatVariable::public(0)), + Statement::constraint(Variable::new(1), Variable::public(0)), ], }; diff --git a/zokrates_ast/Cargo.toml b/zokrates_ast/Cargo.toml new file mode 100644 index 00000000..bb22c519 --- /dev/null +++ b/zokrates_ast/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "zokrates_ast" +version = "0.1.0" +edition = "2021" + +[features] +default = ["bellman", "ark"] +bellman = ["zokrates_field/bellman", "pairing_ce", "zokrates_embed/bellman"] +ark = ["ark-bls12-377", "zokrates_embed/ark"] + +[dependencies] +zokrates_pest_ast = { version = "0.2.0", path = "../zokrates_pest_ast" } +cfg-if = "0.1" +zokrates_field = { version = "0.5", path = "../zokrates_field", default-features = false } +serde = { version = "1.0", features = ["derive"] } +csv = "1" +serde_cbor = "0.11.2" +num-bigint = { version = "0.2", default-features = false } +serde_json = { version = "1.0", features = ["preserve_order"] } +zokrates_embed = { version = "0.1.0", path = "../zokrates_embed", default-features = false } +pairing_ce = { version = "^0.21", optional = true } +ark-bls12-377 = { version = "^0.3.0", features = ["curve"], default-features = false, optional = true } + + + + diff --git a/zokrates_core/src/embed.rs b/zokrates_ast/src/common/embed.rs similarity index 90% rename from zokrates_core/src/embed.rs rename to zokrates_ast/src/common/embed.rs index 3f38778a..635e6092 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_ast/src/common/embed.rs @@ -1,16 +1,13 @@ -use crate::absy::{ - types::{UnresolvedSignature, UnresolvedType}, - ConstantGenericNode, Expression, -}; -use crate::flat_absy::{ - FlatDirective, FlatExpression, FlatFunctionIterator, FlatParameter, FlatStatement, - FlatVariable, RuntimeError, -}; -use crate::solvers::Solver; -use crate::typed_absy::types::{ +use crate::common::{Parameter, RuntimeError, Solver, Variable}; +use crate::flat::{FlatDirective, FlatExpression, FlatFunctionIterator, FlatStatement}; +use crate::typed::types::{ ConcreteGenericsAssignment, DeclarationConstant, DeclarationSignature, DeclarationType, GenericIdentifier, }; +use crate::untyped::{ + types::{UnresolvedSignature, UnresolvedType}, + ConstantGenericNode, Expression, +}; use std::collections::HashMap; use zokrates_field::Field; @@ -321,7 +318,7 @@ fn flat_expression_from_vec(v: &[(usize, T)]) -> FlatExpression { let (key, val) = v[0].clone(); FlatExpression::Mult( box FlatExpression::Number(val), - box FlatExpression::Identifier(FlatVariable::new(key)), + box FlatExpression::Identifier(Variable::new(key)), ) } n => { @@ -380,14 +377,14 @@ pub fn sha256_round( .clone() .into_iter() .chain(current_hash_argument_indices.clone()) - .map(|i| FlatParameter { - id: FlatVariable::new(i), + .map(|i| Parameter { + id: Variable::new(i), private: true, }) .collect(); // define a binding of the first variable in the constraint system to one let one_binding_statement = FlatStatement::Condition( - FlatVariable::new(0).into(), + Variable::new(0).into(), FlatExpression::Number(T::from(1)), RuntimeError::BellmanOneBinding, ); @@ -395,8 +392,8 @@ pub fn sha256_round( // bind input and current_hash to inputs input_indices.chain(current_hash_indices).zip(input_argument_indices.clone().into_iter().chain(current_hash_argument_indices.clone())).map(|(cs_index, argument_index)| { FlatStatement::Condition( - FlatVariable::new(cs_index).into(), - FlatVariable::new(argument_index).into(), + Variable::new(cs_index).into(), + Variable::new(argument_index).into(), RuntimeError::BellmanInputBinding ) }); @@ -415,14 +412,14 @@ pub fn sha256_round( }); // define which subset of the witness is returned - let outputs = output_indices.map(|o| FlatExpression::Identifier(FlatVariable::new(o))); + let outputs = output_indices.map(|o| FlatExpression::Identifier(Variable::new(o))); // insert a directive to set the witness based on the bellman gadget and inputs let directive_statement = FlatStatement::Directive(FlatDirective { - outputs: cs_indices.map(FlatVariable::new).collect(), + outputs: cs_indices.map(Variable::new).collect(), inputs: input_argument_indices .into_iter() .chain(current_hash_argument_indices) - .map(|i| FlatVariable::new(i).into()) + .map(|i| Variable::new(i).into()) .collect(), solver: Solver::Sha256Round, }); @@ -430,7 +427,7 @@ pub fn sha256_round( let return_statements = outputs .into_iter() .enumerate() - .map(|(index, e)| FlatStatement::Definition(FlatVariable::public(index), e)); + .map(|(index, e)| FlatStatement::Definition(Variable::public(index), e)); let statements = std::iter::once(directive_statement) .chain(std::iter::once(one_binding_statement)) .chain(input_binding_statements) @@ -468,15 +465,15 @@ pub fn snark_verify_bls12_377( let input_arguments = input_argument_indices .clone() - .map(|i| FlatParameter::private(FlatVariable::new(i))); + .map(|i| Parameter::private(Variable::new(i))); let proof_arguments = proof_argument_indices .clone() - .map(|i| FlatParameter::private(FlatVariable::new(i))); + .map(|i| Parameter::private(Variable::new(i))); let vk_arguments = vk_argument_indices .clone() - .map(|i| FlatParameter::private(FlatVariable::new(i))); + .map(|i| Parameter::private(Variable::new(i))); let arguments = input_arguments .chain(proof_arguments) @@ -484,7 +481,7 @@ pub fn snark_verify_bls12_377( .collect(); let one_binding_statement = FlatStatement::Condition( - FlatExpression::Identifier(FlatVariable::new(0)), + FlatExpression::Identifier(Variable::new(0)), FlatExpression::Number(T::from(1)), RuntimeError::ArkOneBinding, ); @@ -500,8 +497,8 @@ pub fn snark_verify_bls12_377( ) .map(|(cs_index, argument_index)| { FlatStatement::Condition( - FlatVariable::new(cs_index).into(), - FlatVariable::new(argument_index).into(), + Variable::new(cs_index).into(), + Variable::new(argument_index).into(), RuntimeError::ArkInputBinding, ) }) @@ -524,17 +521,17 @@ pub fn snark_verify_bls12_377( .collect(); let return_statement = FlatStatement::Definition( - FlatVariable::public(0), - FlatExpression::Identifier(FlatVariable::new(out_index)), + Variable::public(0), + FlatExpression::Identifier(Variable::new(out_index)), ); // insert a directive to set the witness let directive_statement = FlatStatement::Directive(FlatDirective { - outputs: cs_indices.map(FlatVariable::new).collect(), + outputs: cs_indices.map(Variable::new).collect(), inputs: input_argument_indices .chain(proof_argument_indices) .chain(vk_argument_indices) - .map(|i| FlatVariable::new(i).into()) + .map(|i| Variable::new(i).into()) .collect(), solver: Solver::SnarkVerifyBls12377(n), }); @@ -553,11 +550,11 @@ pub fn snark_verify_bls12_377( } fn use_variable( - layout: &mut HashMap, + layout: &mut HashMap, name: String, index: &mut usize, -) -> FlatVariable { - let var = FlatVariable::new(*index); +) -> Variable { + let var = Variable::new(*index); layout.insert(name, var); *index += 1; var @@ -578,8 +575,8 @@ pub fn unpack_to_bitwidth( let mut layout = HashMap::new(); - let arguments = vec![FlatParameter { - id: FlatVariable::new(0), + let arguments = vec![Parameter { + id: Variable::new(0), private: true, }]; @@ -591,7 +588,7 @@ pub fn unpack_to_bitwidth( &mut counter, ))]; - let directive_outputs: Vec = (0..bit_width) + let directive_outputs: Vec = (0..bit_width) .map(|index| use_variable(&mut layout, format!("o{}", index), &mut counter)) .collect(); @@ -607,7 +604,7 @@ pub fn unpack_to_bitwidth( // o253, o252, ... o{253 - (bit_width - 1)} are bits let mut statements: Vec> = (0..bit_width) .map(|index| { - let bit = FlatExpression::Identifier(FlatVariable::new(bit_width - index)); + let bit = FlatExpression::Identifier(Variable::new(bit_width - index)); FlatStatement::Condition( bit.clone(), FlatExpression::Mult(box bit.clone(), box bit.clone()), @@ -623,7 +620,7 @@ pub fn unpack_to_bitwidth( lhs_sum = FlatExpression::Add( box lhs_sum, box FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(bit_width - i)), + box FlatExpression::Identifier(Variable::new(bit_width - i)), box FlatExpression::Number(T::from(2).pow(i)), ), ); @@ -632,7 +629,7 @@ pub fn unpack_to_bitwidth( statements.push(FlatStatement::Condition( lhs_sum, FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(0)), + box FlatExpression::Identifier(Variable::new(0)), box FlatExpression::Number(T::from(1)), ), RuntimeError::Sum, @@ -651,7 +648,7 @@ pub fn unpack_to_bitwidth( outputs .into_iter() .enumerate() - .map(|(index, e)| FlatStatement::Definition(FlatVariable::public(index), e)), + .map(|(index, e)| FlatStatement::Definition(Variable::public(index), e)), ); FlatFunctionIterator { @@ -675,18 +672,15 @@ mod tests { let unpack = unpack_to_bitwidth::(Bn128Field::get_required_bits()).collect(); - assert_eq!( - unpack.arguments, - vec![FlatParameter::private(FlatVariable::new(0))] - ); + assert_eq!(unpack.arguments, vec![Parameter::private(Variable::new(0))]); assert_eq!( unpack.statements[0], FlatStatement::Directive(FlatDirective::new( (0..Bn128Field::get_required_bits()) - .map(|i| FlatVariable::new(i + 1)) + .map(|i| Variable::new(i + 1)) .collect(), Solver::bits(Bn128Field::get_required_bits()), - vec![FlatVariable::new(0)] + vec![Variable::new(0)] )) ); assert_eq!( @@ -700,7 +694,6 @@ mod tests { #[cfg(test)] mod sha256 { use super::*; - use crate::ir::Interpreter; #[test] fn generate_sha256_constraints() { @@ -729,14 +722,14 @@ mod tests { // function input should be offset by variable_count assert_eq!( compiled.arguments[0].id, - FlatVariable::new(directive.outputs.len() + 1) + Variable::new(directive.outputs.len() + 1) ); // bellman variable #0: index 0 should equal 1 assert_eq!( compiled.statements[1], FlatStatement::Condition( - FlatVariable::new(0).into(), + Variable::new(0).into(), FlatExpression::Number(Bn128Field::from(1)), RuntimeError::BellmanOneBinding ) @@ -746,22 +739,11 @@ mod tests { assert_eq!( compiled.statements[2], FlatStatement::Condition( - FlatVariable::new(1).into(), - FlatVariable::new(26936).into(), + Variable::new(1).into(), + Variable::new(26936).into(), RuntimeError::BellmanInputBinding ) ); - - let input: Vec<_> = (0..512) - .map(|_| 0) - .chain((0..256).map(|_| 1)) - .map(Bn128Field::from) - .collect(); - - let ir = crate::ir::from_flat::from_flat(compiled); - - let interpreter = Interpreter::default(); - interpreter.execute(ir, &input).unwrap(); } } } diff --git a/zokrates_ast/src/common/error.rs b/zokrates_ast/src/common/error.rs new file mode 100644 index 00000000..f1d8b2d1 --- /dev/null +++ b/zokrates_ast/src/common/error.rs @@ -0,0 +1,91 @@ +use serde::{Deserialize, Serialize}; +use std::fmt; + +#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)] +pub enum RuntimeError { + BellmanConstraint, + BellmanOneBinding, + BellmanInputBinding, + ArkConstraint, + ArkOneBinding, + ArkInputBinding, + Bitness, + Sum, + Equal, + Le, + BranchIsolation, + ConstantLtBitness, + ConstantLtSum, + LtBitness, + LtSum, + LtFinalBitness, + LtFinalSum, + LtSymetric, + Or, + Xor, + Inverse, + Euclidean, + ShaXor, + Division, + SourceAssertion(String), + ArgumentBitness, + SelectRangeCheck, +} + +impl From for RuntimeError { + fn from(error: crate::zir::RuntimeError) -> Self { + match error { + crate::zir::RuntimeError::SourceAssertion(s) => RuntimeError::SourceAssertion(s), + crate::zir::RuntimeError::SelectRangeCheck => RuntimeError::SelectRangeCheck, + } + } +} + +impl RuntimeError { + pub fn is_malicious(&self) -> bool { + use RuntimeError::*; + + !matches!( + self, + SourceAssertion(_) | Inverse | LtSum | SelectRangeCheck | ArgumentBitness + ) + } +} + +impl fmt::Display for RuntimeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use RuntimeError::*; + + let msg = match self { + BellmanConstraint => "Bellman constraint is unsatisfied", + BellmanOneBinding => "Bellman ~one binding is unsatisfied", + BellmanInputBinding => "Bellman input binding is unsatisfied", + ArkConstraint => "Ark constraint is unsatisfied", + ArkOneBinding => "Ark ~one binding is unsatisfied", + ArkInputBinding => "Ark input binding is unsatisfied", + Bitness => "Bitness check failed", + Sum => "Sum check failed", + Equal => "Equal check failed", + Le => "Constant Le check failed", + BranchIsolation => "Branch isolation failed", + ConstantLtBitness => "Bitness check failed in constant Lt check", + ConstantLtSum => "Sum check failed in constant Lt check", + LtBitness => "Bitness check failed in Lt check", + LtSum => "Sum check failed in Lt check", + LtFinalBitness => "Bitness check failed in final Lt check", + LtFinalSum => "Sum check failed in final Lt check", + LtSymetric => "Symetrical check failed in Lt check", + Or => "Or check failed", + Xor => "Xor check failed", + Inverse => "Division by zero", + Euclidean => "Euclidean check failed", + ShaXor => "Internal Sha check failed", + Division => "Division check failed", + SourceAssertion(m) => m.as_str(), + ArgumentBitness => "Argument bitness check failed", + SelectRangeCheck => "Out of bounds array access", + }; + + write!(f, "{}", msg) + } +} diff --git a/zokrates_ast/src/common/mod.rs b/zokrates_ast/src/common/mod.rs new file mode 100644 index 00000000..c7d5e0b4 --- /dev/null +++ b/zokrates_ast/src/common/mod.rs @@ -0,0 +1,11 @@ +pub mod embed; +mod error; +mod parameter; +mod solvers; +mod variable; + +pub use self::embed::FlatEmbed; +pub use self::error::RuntimeError; +pub use self::parameter::Parameter; +pub use self::solvers::Solver; +pub use self::variable::Variable; diff --git a/zokrates_core/src/flat_absy/flat_parameter.rs b/zokrates_ast/src/common/parameter.rs similarity index 50% rename from zokrates_core/src/flat_absy/flat_parameter.rs rename to zokrates_ast/src/common/parameter.rs index c54ec5e7..4b17395f 100644 --- a/zokrates_core/src/flat_absy/flat_parameter.rs +++ b/zokrates_ast/src/common/parameter.rs @@ -1,47 +1,44 @@ -use crate::flat_absy::flat_variable::FlatVariable; +use super::variable::Variable; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fmt; #[derive(Serialize, Deserialize, Hash, Eq, PartialEq, Clone, Copy)] -pub struct FlatParameter { - pub id: FlatVariable, +pub struct Parameter { + pub id: Variable, pub private: bool, } -impl FlatParameter { - fn new(id: FlatVariable, private: bool) -> Self { - FlatParameter { id, private } +impl Parameter { + fn new(id: Variable, private: bool) -> Self { + Parameter { id, private } } - pub fn public(v: FlatVariable) -> Self { + pub fn public(v: Variable) -> Self { Self::new(v, false) } - pub fn private(v: FlatVariable) -> Self { + pub fn private(v: Variable) -> Self { Self::new(v, true) } } -impl fmt::Display for FlatParameter { +impl fmt::Display for Parameter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let visibility = if self.private { "private " } else { "" }; write!(f, "{}{}", visibility, self.id) } } -impl fmt::Debug for FlatParameter { +impl fmt::Debug for Parameter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "FlatParameter(id: {:?})", self.id) + write!(f, "Parameter(id: {:?})", self.id) } } -impl FlatParameter { - pub fn apply_substitution( - self, - substitution: &HashMap, - ) -> FlatParameter { - FlatParameter { +impl Parameter { + pub fn apply_substitution(self, substitution: &HashMap) -> Parameter { + Parameter { id: *substitution.get(&self.id).unwrap(), private: self.private, } diff --git a/zokrates_core/src/solvers/mod.rs b/zokrates_ast/src/common/solvers.rs similarity index 100% rename from zokrates_core/src/solvers/mod.rs rename to zokrates_ast/src/common/solvers.rs diff --git a/zokrates_core/src/flat_absy/flat_variable.rs b/zokrates_ast/src/common/variable.rs similarity index 71% rename from zokrates_core/src/flat_absy/flat_variable.rs rename to zokrates_ast/src/common/variable.rs index 1fe3f6b4..7a6b9b01 100644 --- a/zokrates_core/src/flat_absy/flat_variable.rs +++ b/zokrates_ast/src/common/variable.rs @@ -7,23 +7,23 @@ use std::fmt; // id == 0 for ~one // id < 0 for public outputs #[derive(Serialize, Deserialize, Clone, PartialEq, Hash, Eq, Ord, PartialOrd, Copy)] -pub struct FlatVariable { +pub struct Variable { id: isize, } -impl FlatVariable { +impl Variable { pub fn new(id: usize) -> Self { - FlatVariable { + Variable { id: 1 + id as isize, } } pub fn one() -> Self { - FlatVariable { id: 0 } + Variable { id: 0 } } pub fn public(id: usize) -> Self { - FlatVariable { + Variable { id: -(id as isize) - 1, } } @@ -35,21 +35,21 @@ impl FlatVariable { pub fn try_from_human_readable(s: &str) -> Result { if s == "~one" { - return Ok(FlatVariable::one()); + return Ok(Variable::one()); } let mut public = s.split("~out_"); match public.nth(1) { Some(v) => { let v = v.parse().map_err(|_| s)?; - Ok(FlatVariable::public(v)) + Ok(Variable::public(v)) } None => { let mut private = s.split('_'); match private.nth(1) { Some(v) => { let v = v.parse().map_err(|_| s)?; - Ok(FlatVariable::new(v)) + Ok(Variable::new(v)) } None => Err(s), } @@ -58,7 +58,7 @@ impl FlatVariable { } } -impl fmt::Display for FlatVariable { +impl fmt::Display for Variable { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.id { 0 => write!(f, "~one"), @@ -68,7 +68,7 @@ impl fmt::Display for FlatVariable { } } -impl fmt::Debug for FlatVariable { +impl fmt::Debug for Variable { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.id { 0 => write!(f, "~one"), @@ -78,8 +78,8 @@ impl fmt::Debug for FlatVariable { } } -impl FlatVariable { - pub fn apply_substitution(self, substitution: &HashMap) -> &Self { +impl Variable { + pub fn apply_substitution(self, substitution: &HashMap) -> &Self { substitution.get(&self).unwrap() } @@ -94,18 +94,18 @@ mod tests { #[test] fn one() { - assert_eq!(format!("{}", FlatVariable::one()), "~one"); + assert_eq!(format!("{}", Variable::one()), "~one"); } #[test] fn public() { - assert_eq!(format!("{}", FlatVariable::public(0)), "~out_0"); - assert_eq!(format!("{}", FlatVariable::public(42)), "~out_42"); + assert_eq!(format!("{}", Variable::public(0)), "~out_0"); + assert_eq!(format!("{}", Variable::public(42)), "~out_42"); } #[test] fn private() { - assert_eq!(format!("{}", FlatVariable::new(0)), "_0"); - assert_eq!(format!("{}", FlatVariable::new(42)), "_42"); + assert_eq!(format!("{}", Variable::new(0)), "_0"); + assert_eq!(format!("{}", Variable::new(42)), "_42"); } } diff --git a/zokrates_ast/src/flat/folder.rs b/zokrates_ast/src/flat/folder.rs new file mode 100644 index 00000000..254f2d5f --- /dev/null +++ b/zokrates_ast/src/flat/folder.rs @@ -0,0 +1,107 @@ +// Generic walk through an IR AST. Not mutating in place + +use super::*; +use crate::common::Variable; +use zokrates_field::Field; + +pub trait Folder: Sized { + fn fold_program(&mut self, p: FlatProg) -> FlatProg { + fold_program(self, p) + } + + fn fold_argument(&mut self, p: Parameter) -> Parameter { + fold_argument(self, p) + } + + fn fold_variable(&mut self, v: Variable) -> Variable { + fold_variable(self, v) + } + + fn fold_statement(&mut self, s: FlatStatement) -> Vec> { + fold_statement(self, s) + } + + fn fold_expression(&mut self, e: FlatExpression) -> FlatExpression { + fold_expression(self, e) + } + + fn fold_directive(&mut self, d: FlatDirective) -> FlatDirective { + fold_directive(self, d) + } +} + +pub fn fold_program>(f: &mut F, p: FlatProg) -> FlatProg { + FlatProg { + arguments: p + .arguments + .into_iter() + .map(|a| f.fold_argument(a)) + .collect(), + statements: p + .statements + .into_iter() + .flat_map(|s| f.fold_statement(s)) + .collect(), + return_count: p.return_count, + } +} + +pub fn fold_statement>( + f: &mut F, + s: FlatStatement, +) -> Vec> { + match s { + FlatStatement::Condition(left, right, error) => vec![FlatStatement::Condition( + f.fold_expression(left), + f.fold_expression(right), + error, + )], + FlatStatement::Definition(v, e) => vec![FlatStatement::Definition( + f.fold_variable(v), + f.fold_expression(e), + )], + FlatStatement::Directive(d) => vec![FlatStatement::Directive(f.fold_directive(d))], + } +} + +pub fn fold_expression>( + f: &mut F, + e: FlatExpression, +) -> FlatExpression { + match e { + FlatExpression::Number(n) => FlatExpression::Number(n), + FlatExpression::Identifier(id) => FlatExpression::Identifier(f.fold_variable(id)), + FlatExpression::Add(box left, box right) => { + FlatExpression::Add(box f.fold_expression(left), box f.fold_expression(right)) + } + FlatExpression::Sub(box left, box right) => { + FlatExpression::Sub(box f.fold_expression(left), box f.fold_expression(right)) + } + FlatExpression::Mult(box left, box right) => { + FlatExpression::Mult(box f.fold_expression(left), box f.fold_expression(right)) + } + } +} + +pub fn fold_directive>(f: &mut F, ds: FlatDirective) -> FlatDirective { + FlatDirective { + inputs: ds + .inputs + .into_iter() + .map(|e| f.fold_expression(e)) + .collect(), + outputs: ds.outputs.into_iter().map(|o| f.fold_variable(o)).collect(), + ..ds + } +} + +pub fn fold_argument>(f: &mut F, a: Parameter) -> Parameter { + Parameter { + id: f.fold_variable(a.id), + private: a.private, + } +} + +pub fn fold_variable>(_f: &mut F, v: Variable) -> Variable { + v +} diff --git a/zokrates_core/src/flat_absy/mod.rs b/zokrates_ast/src/flat/mod.rs similarity index 71% rename from zokrates_core/src/flat_absy/mod.rs rename to zokrates_ast/src/flat/mod.rs index 01260145..27ac6e7f 100644 --- a/zokrates_core/src/flat_absy/mod.rs +++ b/zokrates_ast/src/flat/mod.rs @@ -5,99 +5,17 @@ //! @author Jacob Eberhardt //! @date 2017 -pub mod flat_parameter; -pub mod flat_variable; +pub mod folder; -pub use self::flat_parameter::FlatParameter; -pub use self::flat_variable::FlatVariable; +pub use crate::common::Parameter; +pub use crate::common::RuntimeError; +pub use crate::common::Variable; -use serde::{Deserialize, Serialize}; - -use crate::solvers::Solver; +use crate::common::Solver; use std::collections::HashMap; use std::fmt; use zokrates_field::Field; -#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)] -pub enum RuntimeError { - BellmanConstraint, - BellmanOneBinding, - BellmanInputBinding, - ArkConstraint, - ArkOneBinding, - ArkInputBinding, - Bitness, - Sum, - Equal, - Le, - BranchIsolation, - ConstantLtBitness, - ConstantLtSum, - LtBitness, - LtSum, - LtFinalBitness, - LtFinalSum, - LtSymetric, - Or, - Xor, - Inverse, - Euclidean, - ShaXor, - Division, - SourceAssertion(String), - ArgumentBitness, - SelectRangeCheck, -} - -impl RuntimeError { - pub(crate) fn is_malicious(&self) -> bool { - use RuntimeError::*; - - !matches!( - self, - SourceAssertion(_) | Inverse | LtSum | SelectRangeCheck | ArgumentBitness - ) - } -} - -impl fmt::Display for RuntimeError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use RuntimeError::*; - - let msg = match self { - BellmanConstraint => "Bellman constraint is unsatisfied", - BellmanOneBinding => "Bellman ~one binding is unsatisfied", - BellmanInputBinding => "Bellman input binding is unsatisfied", - ArkConstraint => "Ark constraint is unsatisfied", - ArkOneBinding => "Ark ~one binding is unsatisfied", - ArkInputBinding => "Ark input binding is unsatisfied", - Bitness => "Bitness check failed", - Sum => "Sum check failed", - Equal => "Equal check failed", - Le => "Constant Le check failed", - BranchIsolation => "Branch isolation failed", - ConstantLtBitness => "Bitness check failed in constant Lt check", - ConstantLtSum => "Sum check failed in constant Lt check", - LtBitness => "Bitness check failed in Lt check", - LtSum => "Sum check failed in Lt check", - LtFinalBitness => "Bitness check failed in final Lt check", - LtFinalSum => "Sum check failed in final Lt check", - LtSymetric => "Symetrical check failed in Lt check", - Or => "Or check failed", - Xor => "Xor check failed", - Inverse => "Division by zero", - Euclidean => "Euclidean check failed", - ShaXor => "Internal Sha check failed", - Division => "Division check failed", - SourceAssertion(m) => m.as_str(), - ArgumentBitness => "Argument bitness check failed", - SelectRangeCheck => "Out of bounds array access", - }; - - write!(f, "{}", msg) - } -} - pub type FlatProg = FlatFunction; pub type FlatFunction = FlatFunctionIterator>>; @@ -107,7 +25,7 @@ pub type FlatProgIterator = FlatFunctionIterator; #[derive(Clone, PartialEq, Debug)] pub struct FlatFunctionIterator>> { /// Arguments of the function - pub arguments: Vec, + pub arguments: Vec, /// Vector of statements that are executed when running the function pub statements: I, /// Number of outputs @@ -157,7 +75,7 @@ impl fmt::Display for FlatFunction { #[derive(Clone, PartialEq, Debug)] pub enum FlatStatement { Condition(FlatExpression, FlatExpression, RuntimeError), - Definition(FlatVariable, FlatExpression), + Definition(Variable, FlatExpression), Directive(FlatDirective), } @@ -176,7 +94,7 @@ impl fmt::Display for FlatStatement { impl FlatStatement { pub fn apply_substitution( self, - substitution: &HashMap, + substitution: &HashMap, ) -> FlatStatement { match self { FlatStatement::Definition(id, x) => FlatStatement::Definition( @@ -213,13 +131,13 @@ impl FlatStatement { #[derive(Clone, Hash, Debug, PartialEq, Eq)] pub struct FlatDirective { pub inputs: Vec>, - pub outputs: Vec, + pub outputs: Vec, pub solver: Solver, } impl FlatDirective { pub fn new>>( - outputs: Vec, + outputs: Vec, solver: Solver, inputs: Vec, ) -> Self { @@ -257,7 +175,7 @@ impl fmt::Display for FlatDirective { #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub enum FlatExpression { Number(T), - Identifier(FlatVariable), + Identifier(Variable), Add(Box>, Box>), Sub(Box>, Box>), Mult(Box>, Box>), @@ -272,7 +190,7 @@ impl From for FlatExpression { impl FlatExpression { pub fn apply_substitution( self, - substitution: &HashMap, + substitution: &HashMap, ) -> FlatExpression { match self { e @ FlatExpression::Number(_) => e, @@ -328,8 +246,8 @@ impl fmt::Display for FlatExpression { } } -impl From for FlatExpression { - fn from(v: FlatVariable) -> FlatExpression { +impl From for FlatExpression { + fn from(v: Variable) -> FlatExpression { FlatExpression::Identifier(v) } } diff --git a/zokrates_core/src/static_analysis/unconstrained_vars.rs b/zokrates_ast/src/ir/check.rs similarity index 80% rename from zokrates_core/src/static_analysis/unconstrained_vars.rs rename to zokrates_ast/src/ir/check.rs index 807ceae4..11c5fd84 100644 --- a/zokrates_core/src/static_analysis/unconstrained_vars.rs +++ b/zokrates_ast/src/ir/check.rs @@ -1,15 +1,15 @@ -use crate::flat_absy::FlatParameter; -use crate::flat_absy::FlatVariable; use crate::ir::folder::Folder; use crate::ir::Directive; +use crate::ir::Parameter; use crate::ir::ProgIterator; use crate::ir::Statement; +use crate::ir::Variable; use std::collections::HashSet; use zokrates_field::Field; #[derive(Debug)] pub struct UnconstrainedVariableDetector { - pub(self) variables: HashSet, + pub(self) variables: HashSet, } impl UnconstrainedVariableDetector { @@ -33,10 +33,10 @@ impl UnconstrainedVariableDetector { } impl Folder for UnconstrainedVariableDetector { - fn fold_argument(&mut self, p: FlatParameter) -> FlatParameter { + fn fold_argument(&mut self, p: Parameter) -> Parameter { p } - fn fold_variable(&mut self, v: FlatVariable) -> FlatVariable { + fn fold_variable(&mut self, v: Variable) -> Variable { self.variables.remove(&v); v } diff --git a/zokrates_core/src/ir/expression.rs b/zokrates_ast/src/ir/expression.rs similarity index 82% rename from zokrates_core/src/ir/expression.rs rename to zokrates_ast/src/ir/expression.rs index 57ec2753..a32a1293 100644 --- a/zokrates_core/src/ir/expression.rs +++ b/zokrates_ast/src/ir/expression.rs @@ -1,4 +1,5 @@ -use crate::flat_absy::FlatVariable; +use super::Witness; +use crate::common::Variable; use serde::{Deserialize, Serialize}; use std::collections::btree_map::{BTreeMap, Entry}; use std::fmt; @@ -54,10 +55,10 @@ impl fmt::Display for QuadComb { } #[derive(Clone, Debug, Serialize, Deserialize, Hash, PartialEq, Eq)] -pub struct LinComb(pub Vec<(FlatVariable, T)>); +pub struct LinComb(pub Vec<(Variable, T)>); #[derive(PartialEq, PartialOrd, Clone, Eq, Ord, Hash, Debug, Serialize, Deserialize)] -pub struct CanonicalLinComb(pub BTreeMap); +pub struct CanonicalLinComb(pub BTreeMap); #[derive(PartialEq, PartialOrd, Clone, Eq, Ord, Hash, Debug, Serialize, Deserialize)] pub struct CanonicalQuadComb { @@ -81,7 +82,7 @@ impl From> for LinComb { } impl LinComb { - pub fn summand>(mult: U, var: FlatVariable) -> LinComb { + pub fn summand>(mult: U, var: Variable) -> LinComb { let res = vec![(var, mult.into())]; LinComb(res) @@ -105,7 +106,7 @@ impl LinComb { // take the first variable in the lincomb let first = &self.0[0].0; - if first != &FlatVariable::one() { + if first != &Variable::one() { return Err(self); } @@ -119,7 +120,13 @@ impl LinComb { } } - pub fn try_summand(self) -> Result<(FlatVariable, T), Self> { + pub fn is_assignee(&self, witness: &Witness) -> bool { + self.0.len() == 1 + && self.0.get(0).unwrap().1 == T::from(1) + && !witness.0.contains_key(&self.0.get(0).unwrap().0) + } + + pub fn try_summand(self) -> Result<(Variable, T), Self> { match self.0.len() { // if the lincomb is empty, it is not reduceable to a summand 0 => Err(self), @@ -143,7 +150,7 @@ impl LinComb { } pub fn one() -> LinComb { - Self::summand(1, FlatVariable::one()) + Self::summand(1, Variable::one()) } } @@ -212,8 +219,8 @@ impl fmt::Display for LinComb { } } -impl From for LinComb { - fn from(v: FlatVariable) -> LinComb { +impl From for LinComb { + fn from(v: Variable) -> LinComb { let r = vec![(v, T::one())]; LinComb(r) } @@ -277,32 +284,32 @@ mod tests { #[test] fn add_zero() { let a: LinComb = LinComb::zero(); - let b: LinComb = FlatVariable::new(42).into(); + let b: LinComb = Variable::new(42).into(); let c = a + b.clone(); assert_eq!(c, b); } #[test] fn add() { - let a: LinComb = FlatVariable::new(42).into(); - let b: LinComb = FlatVariable::new(42).into(); + let a: LinComb = Variable::new(42).into(); + let b: LinComb = Variable::new(42).into(); let c = a + b; let expected_vec = vec![ - (FlatVariable::new(42), Bn128Field::from(1)), - (FlatVariable::new(42), Bn128Field::from(1)), + (Variable::new(42), Bn128Field::from(1)), + (Variable::new(42), Bn128Field::from(1)), ]; assert_eq!(c, LinComb(expected_vec)); } #[test] fn sub() { - let a: LinComb = FlatVariable::new(42).into(); - let b: LinComb = FlatVariable::new(42).into(); + let a: LinComb = Variable::new(42).into(); + let b: LinComb = Variable::new(42).into(); let c = a - b; let expected_vec = vec![ - (FlatVariable::new(42), Bn128Field::from(1)), - (FlatVariable::new(42), Bn128Field::from(-1)), + (Variable::new(42), Bn128Field::from(1)), + (Variable::new(42), Bn128Field::from(-1)), ]; assert_eq!(c, LinComb(expected_vec)); @@ -311,7 +318,7 @@ mod tests { #[test] fn display() { let a: LinComb = - LinComb::from(FlatVariable::new(42)) + LinComb::summand(3, FlatVariable::new(21)); + LinComb::from(Variable::new(42)) + LinComb::summand(3, Variable::new(21)); assert_eq!(&a.to_string(), "1 * _42 + 3 * _21"); let zero: LinComb = LinComb::zero(); assert_eq!(&zero.to_string(), "0"); @@ -322,8 +329,8 @@ mod tests { use super::*; #[test] fn from_linear() { - let a: LinComb = LinComb::summand(3, FlatVariable::new(42)) - + LinComb::summand(4, FlatVariable::new(33)); + let a: LinComb = + LinComb::summand(3, Variable::new(42)) + LinComb::summand(4, Variable::new(33)); let expected = QuadComb { left: LinComb::one(), right: a.clone(), @@ -344,14 +351,14 @@ mod tests { #[test] fn display() { let a: QuadComb = QuadComb { - left: LinComb::summand(3, FlatVariable::new(42)) - + LinComb::summand(4, FlatVariable::new(33)), - right: LinComb::summand(1, FlatVariable::new(21)), + left: LinComb::summand(3, Variable::new(42)) + + LinComb::summand(4, Variable::new(33)), + right: LinComb::summand(1, Variable::new(21)), }; assert_eq!(&a.to_string(), "(3 * _42 + 4 * _33) * (1 * _21)"); let a: QuadComb = QuadComb { left: LinComb::zero(), - right: LinComb::summand(1, FlatVariable::new(21)), + right: LinComb::summand(1, Variable::new(21)), }; assert_eq!(&a.to_string(), "(0) * (1 * _21)"); } @@ -363,19 +370,19 @@ mod tests { #[test] fn try_summand() { let summand = LinComb(vec![ - (FlatVariable::new(42), Bn128Field::from(1)), - (FlatVariable::new(42), Bn128Field::from(2)), - (FlatVariable::new(42), Bn128Field::from(3)), + (Variable::new(42), Bn128Field::from(1)), + (Variable::new(42), Bn128Field::from(2)), + (Variable::new(42), Bn128Field::from(3)), ]); assert_eq!( summand.try_summand(), - Ok((FlatVariable::new(42), Bn128Field::from(6))) + Ok((Variable::new(42), Bn128Field::from(6))) ); let not_summand = LinComb(vec![ - (FlatVariable::new(41), Bn128Field::from(1)), - (FlatVariable::new(42), Bn128Field::from(2)), - (FlatVariable::new(42), Bn128Field::from(3)), + (Variable::new(41), Bn128Field::from(1)), + (Variable::new(42), Bn128Field::from(2)), + (Variable::new(42), Bn128Field::from(3)), ]); assert!(not_summand.try_summand().is_err()); diff --git a/zokrates_core/src/ir/folder.rs b/zokrates_ast/src/ir/folder.rs similarity index 85% rename from zokrates_core/src/ir/folder.rs rename to zokrates_ast/src/ir/folder.rs index a50c71f6..753a3836 100644 --- a/zokrates_core/src/ir/folder.rs +++ b/zokrates_ast/src/ir/folder.rs @@ -1,7 +1,7 @@ // Generic walk through an IR AST. Not mutating in place -use crate::flat_absy::flat_variable::FlatVariable; -use crate::ir::*; +use super::*; +use crate::common::Variable; use zokrates_field::Field; pub trait Folder: Sized { @@ -9,11 +9,11 @@ pub trait Folder: Sized { fold_program(self, p) } - fn fold_argument(&mut self, p: FlatParameter) -> FlatParameter { + fn fold_argument(&mut self, p: Parameter) -> Parameter { fold_argument(self, p) } - fn fold_variable(&mut self, v: FlatVariable) -> FlatVariable { + fn fold_variable(&mut self, v: Variable) -> Variable { fold_variable(self, v) } @@ -91,13 +91,13 @@ pub fn fold_directive>(f: &mut F, ds: Directive) -> Di } } -pub fn fold_argument>(f: &mut F, a: FlatParameter) -> FlatParameter { - FlatParameter { +pub fn fold_argument>(f: &mut F, a: Parameter) -> Parameter { + Parameter { id: f.fold_variable(a.id), private: a.private, } } -pub fn fold_variable>(_f: &mut F, v: FlatVariable) -> FlatVariable { +pub fn fold_variable>(_f: &mut F, v: Variable) -> Variable { v } diff --git a/zokrates_core/src/ir/from_flat.rs b/zokrates_ast/src/ir/from_flat.rs similarity index 81% rename from zokrates_core/src/ir/from_flat.rs rename to zokrates_ast/src/ir/from_flat.rs index 640336b3..abe2b075 100644 --- a/zokrates_core/src/ir/from_flat.rs +++ b/zokrates_ast/src/ir/from_flat.rs @@ -1,6 +1,4 @@ -use crate::flat_absy::{ - FlatDirective, FlatExpression, FlatProgIterator, FlatStatement, FlatVariable, -}; +use crate::flat::{FlatDirective, FlatExpression, FlatProgIterator, FlatStatement, Variable}; use crate::ir::{Directive, LinComb, ProgIterator, QuadComb, Statement}; use zokrates_field::Field; @@ -33,7 +31,7 @@ impl From> for LinComb { fn from(flat_expression: FlatExpression) -> LinComb { match flat_expression { FlatExpression::Number(ref n) if *n == T::from(0) => LinComb::zero(), - FlatExpression::Number(n) => LinComb::summand(n, FlatVariable::one()), + FlatExpression::Number(n) => LinComb::summand(n, Variable::one()), FlatExpression::Identifier(id) => LinComb::from(id), FlatExpression::Add(box e1, box e2) => LinComb::from(e1) + LinComb::from(e2), FlatExpression::Sub(box e1, box e2) => LinComb::from(e1) - LinComb::from(e2), @@ -48,7 +46,7 @@ impl From> for LinComb { FlatExpression::Mult( box FlatExpression::Number(n1), box FlatExpression::Number(n2), - ) => LinComb::summand(n1 * n2, FlatVariable::one()), + ) => LinComb::summand(n1 * n2, Variable::one()), e => unreachable!("{}", e), } } @@ -109,7 +107,7 @@ mod tests { fn one() { // 1 let one = FlatExpression::Number(Bn128Field::from(1)); - let expected: LinComb = FlatVariable::one().into(); + let expected: LinComb = Variable::one().into(); assert_eq!(LinComb::from(one), expected); } @@ -117,7 +115,7 @@ mod tests { fn forty_two() { // 42 let one = FlatExpression::Number(Bn128Field::from(42)); - let expected: LinComb = LinComb::summand(42, FlatVariable::one()); + let expected: LinComb = LinComb::summand(42, Variable::one()); assert_eq!(LinComb::from(one), expected); } @@ -125,11 +123,11 @@ mod tests { fn add() { // x + y let add = FlatExpression::Add( - box FlatExpression::Identifier(FlatVariable::new(42)), - box FlatExpression::Identifier(FlatVariable::new(21)), + box FlatExpression::Identifier(Variable::new(42)), + box FlatExpression::Identifier(Variable::new(21)), ); let expected: LinComb = - LinComb::summand(1, FlatVariable::new(42)) + LinComb::summand(1, FlatVariable::new(21)); + LinComb::summand(1, Variable::new(42)) + LinComb::summand(1, Variable::new(21)); assert_eq!(LinComb::from(add), expected); } @@ -139,15 +137,15 @@ mod tests { let add = FlatExpression::Add( box FlatExpression::Mult( box FlatExpression::Number(Bn128Field::from(42)), - box FlatExpression::Identifier(FlatVariable::new(42)), + box FlatExpression::Identifier(Variable::new(42)), ), box FlatExpression::Mult( box FlatExpression::Number(Bn128Field::from(21)), - box FlatExpression::Identifier(FlatVariable::new(21)), + box FlatExpression::Identifier(Variable::new(21)), ), ); - let expected: LinComb = LinComb::summand(42, FlatVariable::new(42)) - + LinComb::summand(21, FlatVariable::new(21)); + let expected: LinComb = + LinComb::summand(42, Variable::new(42)) + LinComb::summand(21, Variable::new(21)); assert_eq!(LinComb::from(add), expected); } @@ -156,16 +154,16 @@ mod tests { // x*42 + y*21 let add = FlatExpression::Add( box FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(42)), + box FlatExpression::Identifier(Variable::new(42)), box FlatExpression::Number(Bn128Field::from(42)), ), box FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(21)), + box FlatExpression::Identifier(Variable::new(21)), box FlatExpression::Number(Bn128Field::from(21)), ), ); - let expected: LinComb = LinComb::summand(42, FlatVariable::new(42)) - + LinComb::summand(21, FlatVariable::new(21)); + let expected: LinComb = + LinComb::summand(42, Variable::new(42)) + LinComb::summand(21, Variable::new(21)); assert_eq!(LinComb::from(add), expected); } } diff --git a/zokrates_core/src/ir/mod.rs b/zokrates_ast/src/ir/mod.rs similarity index 82% rename from zokrates_core/src/ir/mod.rs rename to zokrates_ast/src/ir/mod.rs index 4fa7ca60..13811b11 100644 --- a/zokrates_core/src/ir/mod.rs +++ b/zokrates_ast/src/ir/mod.rs @@ -1,15 +1,13 @@ -use crate::flat_absy::flat_parameter::FlatParameter; -use crate::flat_absy::{FlatVariable, RuntimeError}; -use crate::solvers::Solver; +//use crate::solvers::Solver; use serde::{Deserialize, Serialize}; use std::fmt; use std::hash::Hash; use zokrates_field::Field; +mod check; mod expression; pub mod folder; pub mod from_flat; -mod interpreter; mod serialize; pub mod smtlib2; pub mod visitor; @@ -18,8 +16,11 @@ mod witness; pub use self::expression::QuadComb; pub use self::expression::{CanonicalLinComb, LinComb}; pub use self::serialize::ProgEnum; +pub use crate::common::Parameter; +pub use crate::common::RuntimeError; +pub use crate::common::Solver; +pub use crate::common::Variable; -pub use self::interpreter::{Error, ExecutionResult, Interpreter}; pub use self::witness::Witness; #[derive(Debug, Serialize, Deserialize, Clone, Hash, PartialEq, Eq)] @@ -29,7 +30,7 @@ pub enum Statement { } impl Statement { - pub fn definition>>(v: FlatVariable, e: U) -> Self { + pub fn definition>>(v: Variable, e: U) -> Self { Statement::Constraint(e.into(), v.into(), None) } @@ -41,7 +42,7 @@ impl Statement { #[derive(Clone, Debug, Serialize, Deserialize, Hash, PartialEq, Eq)] pub struct Directive { pub inputs: Vec>, - pub outputs: Vec, + pub outputs: Vec, pub solver: Solver, } @@ -78,13 +79,13 @@ pub type Prog = ProgIterator>>; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct ProgIterator>> { - pub arguments: Vec, + pub arguments: Vec, pub return_count: usize, pub statements: I, } impl>> ProgIterator { - pub fn new(arguments: Vec, statements: I, return_count: usize) -> Self { + pub fn new(arguments: Vec, statements: I, return_count: usize) -> Self { Self { arguments, return_count, @@ -100,8 +101,8 @@ impl>> ProgIterator { } } - pub fn returns(&self) -> Vec { - (0..self.return_count).map(FlatVariable::public).collect() + pub fn returns(&self) -> Vec { + (0..self.return_count).map(Variable::public).collect() } pub fn public_count(&self) -> usize { @@ -140,7 +141,7 @@ impl Prog { impl fmt::Display for Prog { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let returns = (0..self.return_count) - .map(FlatVariable::public) + .map(Variable::public) .map(|e| format!("{}", e)) .collect::>() .join(", "); @@ -158,6 +159,15 @@ impl fmt::Display for Prog { for s in &self.statements { writeln!(f, "\t{}", s)?; } + writeln!( + f, + "\treturn {}", + (0..self.return_count) + .map(Variable::public) + .map(|e| format!("{}", e)) + .collect::>() + .join(", ") + )?; writeln!(f, "\treturn {}", returns)?; writeln!(f, "}}") @@ -176,10 +186,10 @@ mod tests { fn print_constraint() { let c: Statement = Statement::Constraint( QuadComb::from_linear_combinations( - FlatVariable::new(42).into(), - FlatVariable::new(42).into(), + Variable::new(42).into(), + Variable::new(42).into(), ), - FlatVariable::new(42).into(), + Variable::new(42).into(), None, ); assert_eq!(format!("{}", c), "(1 * _42) * (1 * _42) == 1 * _42") diff --git a/zokrates_core/src/ir/serialize.rs b/zokrates_ast/src/ir/serialize.rs similarity index 96% rename from zokrates_core/src/ir/serialize.rs rename to zokrates_ast/src/ir/serialize.rs index fecf1324..0737c31e 100644 --- a/zokrates_core/src/ir/serialize.rs +++ b/zokrates_ast/src/ir/serialize.rs @@ -1,7 +1,6 @@ -use crate::{ - ir::{ProgIterator, Statement}, - static_analysis::UnconstrainedVariableDetector, -}; +use crate::ir::check::UnconstrainedVariableDetector; + +use super::{ProgIterator, Statement}; use serde_cbor::{self, StreamDeserializer}; use std::io::{Read, Write}; use zokrates_field::*; @@ -60,7 +59,7 @@ impl>> ProgIterator { /// serialize a program iterator, returning the number of constraints serialized /// Note that we only return constraints, not other statements such as directives pub fn serialize(self, mut w: W) -> Result { - use crate::ir::folder::Folder; + use super::folder::Folder; w.write_all(ZOKRATES_MAGIC)?; w.write_all(ZOKRATES_VERSION_2)?; @@ -137,7 +136,7 @@ impl<'de, R: Read> struct ArgumentsVisitor; impl<'de> serde::de::Visitor<'de> for ArgumentsVisitor { - type Value = Vec; + type Value = Vec; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { formatter.write_str("seq of flat param") } @@ -239,13 +238,13 @@ impl<'de, R: Read> #[cfg(test)] mod tests { use super::*; - use crate::ir; + use crate::ir::Prog; use std::io::{Cursor, Seek, SeekFrom}; use zokrates_field::{Bls12_381Field, Bn128Field}; #[test] fn ser_deser_v2() { - let p: ir::Prog = ir::Prog::default(); + let p: Prog = Prog::default(); let mut buffer = Cursor::new(vec![]); p.clone().serialize(&mut buffer).unwrap(); @@ -258,7 +257,7 @@ mod tests { assert_eq!(ProgEnum::Bn128Program(p), deserialized_p.collect()); - let p: ir::Prog = ir::Prog::default(); + let p: Prog = Prog::default(); let mut buffer = Cursor::new(vec![]); p.clone().serialize(&mut buffer).unwrap(); diff --git a/zokrates_core/src/ir/smtlib2.rs b/zokrates_ast/src/ir/smtlib2.rs similarity index 93% rename from zokrates_core/src/ir/smtlib2.rs rename to zokrates_ast/src/ir/smtlib2.rs index 560a1b90..66e78ccf 100644 --- a/zokrates_core/src/ir/smtlib2.rs +++ b/zokrates_ast/src/ir/smtlib2.rs @@ -21,11 +21,11 @@ impl fmt::Display for SMTLib2Display<'_, T> { } struct FlatVariableCollector { - variables: BTreeSet, + variables: BTreeSet, } impl Visitor for FlatVariableCollector { - fn visit_variable(&mut self, v: &FlatVariable) { + fn visit_variable(&mut self, v: &Variable) { self.variables.insert(*v); } } @@ -33,10 +33,10 @@ impl Visitor for FlatVariableCollector { impl SMTLib2 for Prog { fn to_smtlib2(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut collector = FlatVariableCollector { - variables: BTreeSet::::new(), + variables: BTreeSet::::new(), }; collector.visit_module(self); - collector.variables.insert(FlatVariable::one()); + collector.variables.insert(Variable::one()); writeln!(f, "; Auto generated by ZoKrates")?; writeln!( @@ -122,7 +122,7 @@ impl SMTLib2 for LinComb { } } -impl SMTLib2 for FlatVariable { +impl SMTLib2 for Variable { fn to_smtlib2(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "|{}|", self) } diff --git a/zokrates_core/src/ir/visitor.rs b/zokrates_ast/src/ir/visitor.rs similarity index 89% rename from zokrates_core/src/ir/visitor.rs rename to zokrates_ast/src/ir/visitor.rs index 236ade45..8de5a1f5 100644 --- a/zokrates_core/src/ir/visitor.rs +++ b/zokrates_ast/src/ir/visitor.rs @@ -1,7 +1,7 @@ // Generic walk through an IR AST. Not mutating in place -use crate::flat_absy::flat_variable::FlatVariable; -use crate::ir::*; +use super::*; +use crate::common::Variable; use zokrates_field::Field; pub trait Visitor: Sized { @@ -9,11 +9,11 @@ pub trait Visitor: Sized { visit_module(self, p) } - fn visit_argument(&mut self, p: &FlatParameter) { + fn visit_argument(&mut self, p: &Parameter) { visit_argument(self, p) } - fn visit_variable(&mut self, v: &FlatVariable) { + fn visit_variable(&mut self, v: &Variable) { visit_variable(self, v) } @@ -85,11 +85,11 @@ pub fn visit_directive>(f: &mut F, ds: &Directive) { } } -pub fn visit_argument>(f: &mut F, a: &FlatParameter) { +pub fn visit_argument>(f: &mut F, a: &Parameter) { f.visit_variable(&a.id) } -pub fn visit_variable>(_f: &mut F, _v: &FlatVariable) {} +pub fn visit_variable>(_f: &mut F, _v: &Variable) {} pub fn visit_value>(_f: &mut F, _v: &T) {} diff --git a/zokrates_core/src/ir/witness.rs b/zokrates_ast/src/ir/witness.rs similarity index 82% rename from zokrates_core/src/ir/witness.rs rename to zokrates_ast/src/ir/witness.rs index 865556b5..e1ef7090 100644 --- a/zokrates_core/src/ir/witness.rs +++ b/zokrates_ast/src/ir/witness.rs @@ -1,12 +1,12 @@ -use crate::flat_absy::FlatVariable; +use crate::common::Variable; use std::collections::{BTreeMap, HashMap}; use std::fmt; use std::io; use std::io::{Read, Write}; use zokrates_field::Field; -#[derive(Clone, Debug, PartialEq)] -pub struct Witness(pub BTreeMap); +#[derive(Clone, Debug, PartialEq, Default)] +pub struct Witness(pub BTreeMap); impl Witness { pub fn return_values(&self) -> Vec { @@ -17,11 +17,15 @@ impl Witness { .collect::>(); (0..out.len()) - .map(|i| *out.get(&FlatVariable::public(i)).unwrap()) + .map(|i| *out.get(&Variable::public(i)).unwrap()) .cloned() .collect() } + pub fn insert(&mut self, var: Variable, val: T) -> Option { + self.0.insert(var, val) + } + pub fn format_outputs(&self) -> String { self.0 .iter() @@ -63,13 +67,12 @@ impl Witness { .deserialize::<(String, String)>() .map(|r| { r.map(|(variable, value)| { - let variable = - FlatVariable::try_from_human_readable(&variable).map_err(|why| { - io::Error::new( - io::ErrorKind::Other, - format!("Invalid variable in witness: {}", why), - ) - })?; + let variable = Variable::try_from_human_readable(&variable).map_err(|why| { + io::Error::new( + io::ErrorKind::Other, + format!("Invalid variable in witness: {}", why), + ) + })?; let value = T::try_from_dec_str(&value).map_err(|_| { io::Error::new( io::ErrorKind::Other, @@ -83,7 +86,7 @@ impl Witness { e => io::Error::new(io::ErrorKind::Other, format!("{:?}", e)), })? }) - .collect::>>()?; + .collect::>>()?; Ok(Witness(map)) } @@ -116,9 +119,9 @@ mod tests { fn serialize_deserialize() { let w = Witness( vec![ - (FlatVariable::new(42), Bn128Field::from(42)), - (FlatVariable::public(8), Bn128Field::from(8)), - (FlatVariable::one(), Bn128Field::from(1)), + (Variable::new(42), Bn128Field::from(42)), + (Variable::public(8), Bn128Field::from(8)), + (Variable::one(), Bn128Field::from(1)), ] .into_iter() .collect(), diff --git a/zokrates_ast/src/lib.rs b/zokrates_ast/src/lib.rs new file mode 100644 index 00000000..797b8561 --- /dev/null +++ b/zokrates_ast/src/lib.rs @@ -0,0 +1,10 @@ +#![feature(box_patterns, box_syntax)] + +pub mod common; +pub mod flat; +pub mod ir; +pub mod typed; +pub mod untyped; +pub mod zir; + +pub use common::Solver; diff --git a/zokrates_core/src/typed_absy/abi.rs b/zokrates_ast/src/typed/abi.rs similarity index 98% rename from zokrates_core/src/typed_absy/abi.rs rename to zokrates_ast/src/typed/abi.rs index 1f770d60..253d27e2 100644 --- a/zokrates_core/src/typed_absy/abi.rs +++ b/zokrates_ast/src/typed/abi.rs @@ -1,4 +1,4 @@ -use crate::typed_absy::types::{ConcreteSignature, ConcreteType}; +use crate::typed::types::{ConcreteSignature, ConcreteType}; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] @@ -30,12 +30,12 @@ impl Abi { #[cfg(test)] mod tests { use super::*; - use crate::typed_absy::types::{ + use crate::typed::types::{ ConcreteArrayType, ConcreteFunctionKey, ConcreteStructMember, ConcreteStructType, GTupleType, UBitwidth, }; - use crate::typed_absy::DeclarationType; - use crate::typed_absy::{ + use crate::typed::DeclarationType; + use crate::typed::{ parameter::DeclarationParameter, variable::DeclarationVariable, ConcreteTupleType, ConcreteType, TypedFunction, TypedFunctionSymbol, TypedFunctionSymbolDeclaration, TypedModule, TypedProgram, diff --git a/zokrates_core/src/typed_absy/folder.rs b/zokrates_ast/src/typed/folder.rs similarity index 99% rename from zokrates_core/src/typed_absy/folder.rs rename to zokrates_ast/src/typed/folder.rs index bbdf2ec6..efcb9c25 100644 --- a/zokrates_core/src/typed_absy/folder.rs +++ b/zokrates_ast/src/typed/folder.rs @@ -1,7 +1,7 @@ // Generic walk through a typed AST. Not mutating in place -use crate::typed_absy::types::*; -use crate::typed_absy::*; +use crate::typed::types::*; +use crate::typed::*; use zokrates_field::Field; pub trait Fold<'ast, T: Field>: Sized { diff --git a/zokrates_core/src/typed_absy/identifier.rs b/zokrates_ast/src/typed/identifier.rs similarity index 97% rename from zokrates_core/src/typed_absy/identifier.rs rename to zokrates_ast/src/typed/identifier.rs index 56246eb5..2eb64390 100644 --- a/zokrates_core/src/typed_absy/identifier.rs +++ b/zokrates_ast/src/typed/identifier.rs @@ -1,4 +1,4 @@ -use crate::typed_absy::CanonicalConstantIdentifier; +use crate::typed::CanonicalConstantIdentifier; use std::convert::TryInto; use std::fmt; diff --git a/zokrates_core/src/typed_absy/integer.rs b/zokrates_ast/src/typed/integer.rs similarity index 99% rename from zokrates_core/src/typed_absy/integer.rs rename to zokrates_ast/src/typed/integer.rs index be781112..d9970cf4 100644 --- a/zokrates_core/src/typed_absy/integer.rs +++ b/zokrates_ast/src/typed/integer.rs @@ -1,10 +1,10 @@ -use crate::typed_absy::types::{ +use crate::typed::types::{ ArrayType, DeclarationArrayType, DeclarationConstant, DeclarationStructMember, DeclarationStructType, DeclarationTupleType, DeclarationType, GArrayType, GStructType, GTupleType, GType, GenericIdentifier, StructType, TupleType, Type, }; -use crate::typed_absy::UBitwidth; -use crate::typed_absy::{ +use crate::typed::UBitwidth; +use crate::typed::{ ArrayExpression, ArrayExpressionInner, BooleanExpression, Conditional, ConditionalExpression, Expr, FieldElementExpression, Select, SelectExpression, StructExpression, StructExpressionInner, TupleExpression, TupleExpressionInner, Typed, TypedExpression, @@ -791,7 +791,7 @@ impl<'ast, T> From for IntExpression<'ast, T> { #[cfg(test)] mod tests { use super::*; - use crate::typed_absy::ConditionalKind; + use crate::typed::ConditionalKind; use zokrates_field::Bn128Field; #[test] diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_ast/src/typed/mod.rs similarity index 98% rename from zokrates_core/src/typed_absy/mod.rs rename to zokrates_ast/src/typed/mod.rs index 2298b9f5..dbab5a30 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_ast/src/typed/mod.rs @@ -25,28 +25,29 @@ pub use self::types::{ GArrayType, GStructType, GType, GenericIdentifier, Signature, StructType, TupleType, Type, UBitwidth, }; -use crate::parser::Position; -use crate::typed_absy::types::{ConcreteGenericsAssignment, IntoType}; + +use crate::typed::types::{ConcreteGenericsAssignment, IntoType}; +use crate::untyped::Position; pub use self::variable::{ConcreteVariable, DeclarationVariable, GVariable, Variable}; use std::marker::PhantomData; use std::path::{Path, PathBuf}; -pub use crate::typed_absy::integer::IntExpression; -pub use crate::typed_absy::uint::{bitwidth, UExpression, UExpressionInner, UMetadata}; +pub use crate::typed::integer::IntExpression; +pub use crate::typed::uint::{bitwidth, UExpression, UExpressionInner, UMetadata}; -use crate::embed::FlatEmbed; +use crate::common::FlatEmbed; use std::collections::BTreeMap; use std::convert::{TryFrom, TryInto}; use std::fmt; -pub use crate::typed_absy::types::{ArrayType, FunctionKey, MemberId}; +pub use crate::typed::types::{ArrayType, FunctionKey, MemberId}; use zokrates_field::Field; pub use self::folder::Folder; -use crate::typed_absy::abi::{Abi, AbiInput}; +use crate::typed::abi::{Abi, AbiInput}; use std::ops::{Add, Div, Mul, Sub}; pub use self::identifier::Identifier; @@ -85,12 +86,6 @@ pub struct TypedProgram<'ast, T> { pub main: OwnedTypedModuleId, } -impl<'ast, T> TypedProgram<'ast, T> { - pub fn main_function(&self) -> TypedFunction<'ast, T> { - unimplemented!() - } -} - impl<'ast, T: Field> TypedProgram<'ast, T> { pub fn abi(&self) -> Abi { let main = &self.modules[&self.main] @@ -109,7 +104,7 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { .iter() .map(|p| { types::ConcreteType::try_from( - crate::typed_absy::types::try_from_g_type::< + crate::typed::types::try_from_g_type::< DeclarationConstant<'ast, T>, UExpression<'ast, T>, >(p.id._type.clone()) @@ -124,10 +119,9 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { }) .collect(), output: types::ConcreteType::try_from( - crate::typed_absy::types::try_from_g_type::< - DeclarationConstant<'ast, T>, - UExpression<'ast, T>, - >(*main.signature.output.clone()) + types::try_from_g_type::, UExpression<'ast, T>>( + *main.signature.output.clone(), + ) .unwrap(), ) .unwrap(), @@ -2153,7 +2147,7 @@ impl<'ast, T: Clone> Member<'ast, T> for UExpression<'ast, T> { fn member(s: StructExpression<'ast, T>, id: MemberId) -> Self { let ty = s.ty().members.iter().find(|member| id == member.id); let bitwidth = match ty { - Some(crate::typed_absy::types::StructMember { + Some(crate::typed::types::StructMember { ty: box Type::Uint(bitwidth), .. }) => *bitwidth, @@ -2167,7 +2161,7 @@ impl<'ast, T: Clone> Member<'ast, T> for ArrayExpression<'ast, T> { fn member(s: StructExpression<'ast, T>, id: MemberId) -> Self { let ty = s.ty().members.iter().find(|member| id == member.id); let (ty, size) = match ty { - Some(crate::typed_absy::types::StructMember { + Some(crate::typed::types::StructMember { ty: box Type::Array(array_ty), .. }) => (*array_ty.ty.clone(), array_ty.size.clone()), @@ -2181,7 +2175,7 @@ impl<'ast, T: Clone> Member<'ast, T> for StructExpression<'ast, T> { fn member(s: StructExpression<'ast, T>, id: MemberId) -> Self { let ty = s.ty().members.iter().find(|member| id == member.id); let struct_ty = match ty { - Some(crate::typed_absy::types::StructMember { + Some(crate::typed::types::StructMember { ty: box Type::Struct(struct_ty), .. }) => struct_ty.clone(), @@ -2195,7 +2189,7 @@ impl<'ast, T: Clone> Member<'ast, T> for TupleExpression<'ast, T> { fn member(s: StructExpression<'ast, T>, id: MemberId) -> Self { let ty = s.ty().members.iter().find(|member| id == member.id); let tuple_ty = match ty { - Some(crate::typed_absy::types::StructMember { + Some(crate::typed::types::StructMember { ty: box Type::Tuple(tuple_ty), .. }) => tuple_ty.clone(), diff --git a/zokrates_core/src/typed_absy/parameter.rs b/zokrates_ast/src/typed/parameter.rs similarity index 90% rename from zokrates_core/src/typed_absy/parameter.rs rename to zokrates_ast/src/typed/parameter.rs index 34dbb5b0..45b0dcae 100644 --- a/zokrates_core/src/typed_absy/parameter.rs +++ b/zokrates_ast/src/typed/parameter.rs @@ -1,5 +1,5 @@ -use crate::typed_absy::types::DeclarationConstant; -use crate::typed_absy::GVariable; +use crate::typed::types::DeclarationConstant; +use crate::typed::GVariable; use std::fmt; #[derive(Clone, PartialEq, Eq, Hash)] @@ -8,7 +8,6 @@ pub struct GParameter<'ast, S> { pub private: bool, } -#[cfg(test)] impl<'ast, S> From> for GParameter<'ast, S> { fn from(v: GVariable<'ast, S>) -> Self { GParameter { diff --git a/zokrates_core/src/typed_absy/result_folder.rs b/zokrates_ast/src/typed/result_folder.rs similarity index 99% rename from zokrates_core/src/typed_absy/result_folder.rs rename to zokrates_ast/src/typed/result_folder.rs index 3adb51e0..24298004 100644 --- a/zokrates_core/src/typed_absy/result_folder.rs +++ b/zokrates_ast/src/typed/result_folder.rs @@ -1,7 +1,7 @@ // Generic walk through a typed AST. Not mutating in place -use crate::typed_absy::types::*; -use crate::typed_absy::*; +use crate::typed::types::*; +use crate::typed::*; use zokrates_field::Field; pub trait ResultFold<'ast, T: Field>: Sized { diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_ast/src/typed/types.rs similarity index 99% rename from zokrates_core/src/typed_absy/types.rs rename to zokrates_ast/src/typed/types.rs index 4bad5960..239afb1e 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_ast/src/typed/types.rs @@ -1,7 +1,7 @@ -use crate::typed_absy::{ +use crate::typed::{ CoreIdentifier, Identifier, OwnedTypedModuleId, TypedExpression, UExpression, UExpressionInner, }; -use crate::typed_absy::{TryFrom, TryInto}; +use crate::typed::{TryFrom, TryInto}; use serde::{de::Error, ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; use std::collections::BTreeMap; use std::fmt; diff --git a/zokrates_core/src/typed_absy/uint.rs b/zokrates_ast/src/typed/uint.rs similarity index 99% rename from zokrates_core/src/typed_absy/uint.rs rename to zokrates_ast/src/typed/uint.rs index 09c34689..51579e6b 100644 --- a/zokrates_core/src/typed_absy/uint.rs +++ b/zokrates_ast/src/typed/uint.rs @@ -1,5 +1,5 @@ -use crate::typed_absy::types::UBitwidth; -use crate::typed_absy::*; +use crate::typed::types::UBitwidth; +use crate::typed::*; use std::ops::{Add, Div, Mul, Neg, Not, Rem, Sub}; use zokrates_field::Field; diff --git a/zokrates_core/src/typed_absy/variable.rs b/zokrates_ast/src/typed/variable.rs similarity index 89% rename from zokrates_core/src/typed_absy/variable.rs rename to zokrates_ast/src/typed/variable.rs index 6ca12915..d47d4872 100644 --- a/zokrates_core/src/typed_absy/variable.rs +++ b/zokrates_ast/src/typed/variable.rs @@ -1,8 +1,8 @@ -use crate::typed_absy::types::{DeclarationConstant, GStructType, UBitwidth}; -use crate::typed_absy::types::{GType, SpecializationError}; -use crate::typed_absy::Identifier; -use crate::typed_absy::UExpression; -use crate::typed_absy::{TryFrom, TryInto}; +use crate::typed::types::{DeclarationConstant, GStructType, UBitwidth}; +use crate::typed::types::{GType, SpecializationError}; +use crate::typed::Identifier; +use crate::typed::UExpression; +use crate::typed::{TryFrom, TryInto}; use std::fmt; #[derive(Clone, PartialEq, Hash, Eq, PartialOrd, Ord, Debug)] @@ -45,7 +45,7 @@ impl<'ast, T> From> for Variable<'ast, T> { pub fn try_from_g_variable, U>( v: GVariable, ) -> Result, SpecializationError> { - let _type = crate::typed_absy::types::try_from_g_type(v._type)?; + let _type = crate::typed::types::try_from_g_type(v._type)?; Ok(GVariable { _type, diff --git a/zokrates_ast/src/untyped/from_ast.rs b/zokrates_ast/src/untyped/from_ast.rs new file mode 100644 index 00000000..430ce7c4 --- /dev/null +++ b/zokrates_ast/src/untyped/from_ast.rs @@ -0,0 +1,1249 @@ +use crate::untyped::{self, ConditionalExpression, SymbolDefinition}; +use num_bigint::BigUint; +use std::path::Path; +use zokrates_pest_ast as pest; + +impl<'ast> From> for untyped::Module<'ast> { + fn from(file: pest::File<'ast>) -> untyped::Module<'ast> { + untyped::Module::with_symbols(file.declarations.into_iter().flat_map(|d| match d { + pest::SymbolDeclaration::Import(i) => import_directive_to_symbol_vec(i), + pest::SymbolDeclaration::Constant(c) => vec![c.into()], + pest::SymbolDeclaration::Struct(s) => vec![s.into()], + pest::SymbolDeclaration::Type(t) => vec![t.into()], + pest::SymbolDeclaration::Function(f) => vec![f.into()], + })) + } +} + +fn import_directive_to_symbol_vec( + import: pest::ImportDirective, +) -> Vec { + use crate::untyped::NodeValue; + + match import { + pest::ImportDirective::Main(import) => { + let span = import.span; + let source = Path::new(import.source.span.as_str()); + let id = "main"; + let alias = import.alias.map(|a| a.span.as_str()); + + let import = untyped::CanonicalImport { + source, + id: untyped::SymbolIdentifier::from(id).alias(alias), + } + .span(span.clone()); + + vec![untyped::SymbolDeclaration { + id: alias.unwrap_or(id), + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Import(import)), + } + .span(span.clone())] + } + pest::ImportDirective::From(import) => { + let span = import.span; + let source = Path::new(import.source.span.as_str()); + import + .symbols + .into_iter() + .map(|symbol| { + let alias = symbol + .alias + .as_ref() + .map(|a| a.span.as_str()) + .unwrap_or_else(|| symbol.id.span.as_str()); + + let import = untyped::CanonicalImport { + source, + id: untyped::SymbolIdentifier::from(symbol.id.span.as_str()) + .alias(Some(alias)), + } + .span(span.clone()); + + untyped::SymbolDeclaration { + id: alias, + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Import(import)), + } + .span(span.clone()) + }) + .collect() + } + } +} + +impl<'ast> From> for untyped::SymbolDeclarationNode<'ast> { + fn from(definition: pest::StructDefinition<'ast>) -> untyped::SymbolDeclarationNode<'ast> { + use crate::untyped::NodeValue; + + let span = definition.span; + + let id = definition.id.span.as_str(); + + let ty = untyped::StructDefinition { + generics: definition + .generics + .into_iter() + .map(untyped::ConstantGenericNode::from) + .collect(), + fields: definition + .fields + .into_iter() + .map(untyped::StructDefinitionFieldNode::from) + .collect(), + } + .span(span.clone()); + + untyped::SymbolDeclaration { + id, + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Struct(ty)), + } + .span(span) + } +} + +impl<'ast> From> for untyped::StructDefinitionFieldNode<'ast> { + fn from(field: pest::StructField<'ast>) -> untyped::StructDefinitionFieldNode<'ast> { + use crate::untyped::NodeValue; + + let span = field.span; + + let id = field.id.identifier.span.as_str(); + + let ty = untyped::UnresolvedTypeNode::from(field.id.ty); + + untyped::StructDefinitionField { id, ty }.span(span) + } +} + +impl<'ast> From> for untyped::SymbolDeclarationNode<'ast> { + fn from(definition: pest::ConstantDefinition<'ast>) -> untyped::SymbolDeclarationNode<'ast> { + use crate::untyped::NodeValue; + + let span = definition.span; + let id = definition.id.identifier.span.as_str(); + + let ty = untyped::ConstantDefinition { + ty: definition.id.ty.into(), + expression: definition.expression.into(), + } + .span(span.clone()); + + untyped::SymbolDeclaration { + id, + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Constant(ty)), + } + .span(span) + } +} + +impl<'ast> From> for untyped::SymbolDeclarationNode<'ast> { + fn from(definition: pest::TypeDefinition<'ast>) -> untyped::SymbolDeclarationNode<'ast> { + use crate::untyped::NodeValue; + + let span = definition.span; + let id = definition.id.span.as_str(); + + let ty = untyped::TypeDefinition { + generics: definition + .generics + .into_iter() + .map(untyped::ConstantGenericNode::from) + .collect(), + ty: definition.ty.into(), + } + .span(span.clone()); + + untyped::SymbolDeclaration { + id, + symbol: untyped::Symbol::Here(SymbolDefinition::Type(ty)), + } + .span(span) + } +} + +impl<'ast> From> for untyped::SymbolDeclarationNode<'ast> { + fn from(function: pest::FunctionDefinition<'ast>) -> untyped::SymbolDeclarationNode<'ast> { + use crate::untyped::NodeValue; + + let span = function.span; + + let signature = untyped::UnresolvedSignature::new() + .generics( + function + .generics + .into_iter() + .map(untyped::ConstantGenericNode::from) + .collect(), + ) + .inputs( + function + .parameters + .clone() + .into_iter() + .map(|p| untyped::UnresolvedTypeNode::from(p.ty)) + .collect(), + ); + + let signature = match function.return_type { + Some(ret_ty) => signature.output(untyped::UnresolvedTypeNode::from(ret_ty)), + None => signature, + }; + + let id = function.id.span.as_str(); + + let function = untyped::Function { + arguments: function + .parameters + .into_iter() + .map(untyped::ParameterNode::from) + .collect(), + statements: function.statements.into_iter().map(|s| s.into()).collect(), + signature, + } + .span(span.clone()); + + untyped::SymbolDeclaration { + id, + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function(function)), + } + .span(span) + } +} + +impl<'ast> From> for untyped::ConstantGenericNode<'ast> { + fn from(g: pest::IdentifierExpression<'ast>) -> untyped::ConstantGenericNode<'ast> { + use untyped::NodeValue; + + let name = g.span.as_str(); + + name.span(g.span) + } +} + +impl<'ast> From> for untyped::ParameterNode<'ast> { + fn from(param: pest::Parameter<'ast>) -> untyped::ParameterNode<'ast> { + use crate::untyped::NodeValue; + + let is_private = param + .visibility + .map(|v| match v { + pest::Visibility::Private(_) => true, + pest::Visibility::Public(_) => false, + }) + .unwrap_or(false); + + let is_mutable = param.mutable.is_some(); + + let variable = untyped::Variable::new( + param.id.span.as_str(), + untyped::UnresolvedTypeNode::from(param.ty), + is_mutable, + ) + .span(param.id.span); + + untyped::Parameter::new(variable, is_private).span(param.span) + } +} + +impl<'ast> From> for untyped::VariableNode<'ast> { + fn from(i: pest::TypedIdentifier<'ast>) -> Self { + use crate::untyped::NodeValue; + + untyped::Variable::new( + i.identifier.span.as_str(), + untyped::UnresolvedTypeNode::from(i.ty), + i.mutable.is_some(), + ) + .span(i.span) + } +} + +impl<'ast> From> for untyped::StatementNode<'ast> { + fn from(statement: pest::Statement<'ast>) -> Self { + match statement { + pest::Statement::Definition(s) => untyped::StatementNode::from(s), + pest::Statement::Iteration(s) => untyped::StatementNode::from(s), + pest::Statement::Assertion(s) => untyped::StatementNode::from(s), + pest::Statement::Return(s) => untyped::StatementNode::from(s), + } + } +} + +impl<'ast> From> for untyped::StatementNode<'ast> { + fn from(definition: pest::DefinitionStatement<'ast>) -> Self { + use crate::untyped::NodeValue; + + let lhs = definition.lhs; + let e: untyped::ExpressionNode = untyped::ExpressionNode::from(definition.expression); + + match lhs { + pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => untyped::Statement::Definition( + untyped::Variable::new( + i.identifier.span.as_str(), + untyped::UnresolvedTypeNode::from(i.ty), + i.mutable.is_some(), + ) + .span(i.span.clone()), + e, + ), + pest::TypedIdentifierOrAssignee::Assignee(a) => { + untyped::Statement::Assignment(untyped::AssigneeNode::from(a), e) + } + } + .span(definition.span.clone()) + } +} + +impl<'ast> From> for untyped::StatementNode<'ast> { + fn from(statement: pest::ReturnStatement<'ast>) -> untyped::StatementNode<'ast> { + use crate::untyped::NodeValue; + + untyped::Statement::Return(statement.expression.map(untyped::ExpressionNode::from)) + .span(statement.span) + } +} + +impl<'ast> From> for untyped::StatementNode<'ast> { + fn from(statement: pest::AssertionStatement<'ast>) -> untyped::StatementNode<'ast> { + use crate::untyped::NodeValue; + + untyped::Statement::Assertion( + untyped::ExpressionNode::from(statement.expression), + statement.message.map(|m| m.value), + ) + .span(statement.span) + } +} + +impl<'ast> From> for untyped::StatementNode<'ast> { + fn from(statement: pest::IterationStatement<'ast>) -> untyped::StatementNode<'ast> { + use crate::untyped::NodeValue; + let index = untyped::VariableNode::from(statement.index); + let from = untyped::ExpressionNode::from(statement.from); + let to = untyped::ExpressionNode::from(statement.to); + let statements: Vec> = + statement.statements.into_iter().map(|s| s.into()).collect(); + + untyped::Statement::For(index, from, to, statements).span(statement.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::Expression<'ast>) -> untyped::ExpressionNode<'ast> { + match expression { + pest::Expression::Binary(e) => untyped::ExpressionNode::from(e), + pest::Expression::Ternary(e) => untyped::ExpressionNode::from(e), + pest::Expression::IfElse(e) => untyped::ExpressionNode::from(e), + pest::Expression::Literal(e) => untyped::ExpressionNode::from(e), + pest::Expression::Identifier(e) => untyped::ExpressionNode::from(e), + pest::Expression::Postfix(e) => untyped::ExpressionNode::from(e), + pest::Expression::InlineArray(e) => untyped::ExpressionNode::from(e), + pest::Expression::InlineTuple(e) => untyped::ExpressionNode::from(e), + pest::Expression::InlineStruct(e) => untyped::ExpressionNode::from(e), + pest::Expression::ArrayInitializer(e) => untyped::ExpressionNode::from(e), + pest::Expression::Unary(e) => untyped::ExpressionNode::from(e), + } + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::BinaryExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + match expression.op { + pest::BinaryOperator::Add => untyped::Expression::Add( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Sub => untyped::Expression::Sub( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Mul => untyped::Expression::Mult( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Div => untyped::Expression::Div( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Rem => untyped::Expression::Rem( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Eq => untyped::Expression::Eq( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Lt => untyped::Expression::Lt( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Lte => untyped::Expression::Le( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Gt => untyped::Expression::Gt( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Gte => untyped::Expression::Ge( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::And => untyped::Expression::And( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Or => untyped::Expression::Or( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Pow => untyped::Expression::Pow( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::BitXor => untyped::Expression::BitXor( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::LeftShift => untyped::Expression::LeftShift( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::RightShift => untyped::Expression::RightShift( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::BitAnd => untyped::Expression::BitAnd( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::BitOr => untyped::Expression::BitOr( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + // rewrite (a != b)` as `!(a == b)` + pest::BinaryOperator::NotEq => untyped::Expression::Not( + box untyped::Expression::Eq( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ) + .span(expression.span.clone()), + ), + } + .span(expression.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::IfElseExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + untyped::Expression::Conditional(box ConditionalExpression { + condition: box untyped::ExpressionNode::from(*expression.condition), + consequence_statements: expression + .consequence_statements + .into_iter() + .map(untyped::StatementNode::from) + .collect(), + consequence: box untyped::ExpressionNode::from(*expression.consequence), + alternative_statements: expression + .alternative_statements + .into_iter() + .map(untyped::StatementNode::from) + .collect(), + alternative: box untyped::ExpressionNode::from(*expression.alternative), + kind: untyped::ConditionalKind::IfElse, + }) + .span(expression.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::TernaryExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + untyped::Expression::Conditional(box ConditionalExpression { + condition: box untyped::ExpressionNode::from(*expression.condition), + consequence_statements: vec![], + consequence: box untyped::ExpressionNode::from(*expression.consequence), + alternative_statements: vec![], + alternative: box untyped::ExpressionNode::from(*expression.alternative), + kind: untyped::ConditionalKind::Ternary, + }) + .span(expression.span) + } +} + +impl<'ast> From> for untyped::SpreadNode<'ast> { + fn from(spread: pest::Spread<'ast>) -> untyped::SpreadNode<'ast> { + use crate::untyped::NodeValue; + untyped::Spread { + expression: untyped::ExpressionNode::from(spread.expression), + } + .span(spread.span) + } +} + +impl<'ast> From> for untyped::RangeNode<'ast> { + fn from(range: pest::Range<'ast>) -> untyped::RangeNode<'ast> { + use crate::untyped::NodeValue; + + let from = range.from.map(|e| untyped::ExpressionNode::from(e.0)); + + let to = range.to.map(|e| untyped::ExpressionNode::from(e.0)); + + untyped::Range { from, to }.span(range.span) + } +} + +impl<'ast> From> for untyped::RangeOrExpression<'ast> { + fn from( + range_or_expression: pest::RangeOrExpression<'ast>, + ) -> untyped::RangeOrExpression<'ast> { + match range_or_expression { + pest::RangeOrExpression::Expression(e) => { + untyped::RangeOrExpression::Expression(untyped::ExpressionNode::from(e)) + } + pest::RangeOrExpression::Range(r) => { + untyped::RangeOrExpression::Range(untyped::RangeNode::from(r)) + } + } + } +} + +impl<'ast> From> for untyped::SpreadOrExpression<'ast> { + fn from( + spread_or_expression: pest::SpreadOrExpression<'ast>, + ) -> untyped::SpreadOrExpression<'ast> { + match spread_or_expression { + pest::SpreadOrExpression::Expression(e) => { + untyped::SpreadOrExpression::Expression(untyped::ExpressionNode::from(e)) + } + pest::SpreadOrExpression::Spread(s) => { + untyped::SpreadOrExpression::Spread(untyped::SpreadNode::from(s)) + } + } + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(array: pest::InlineArrayExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + untyped::Expression::InlineArray( + array + .expressions + .into_iter() + .map(untyped::SpreadOrExpression::from) + .collect(), + ) + .span(array.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(tuple: pest::InlineTupleExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + untyped::Expression::InlineTuple( + tuple + .elements + .into_iter() + .map(untyped::ExpressionNode::from) + .collect(), + ) + .span(tuple.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(s: pest::InlineStructExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + untyped::Expression::InlineStruct( + s.ty.span.as_str().to_string(), + s.members + .into_iter() + .map(|member| { + ( + member.id.span.as_str(), + untyped::ExpressionNode::from(member.expression), + ) + }) + .collect(), + ) + .span(s.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(initializer: pest::ArrayInitializerExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + + let value = untyped::ExpressionNode::from(*initializer.value); + let count = untyped::ExpressionNode::from(*initializer.count); + untyped::Expression::ArrayInitializer(box value, box count).span(initializer.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(unary: pest::UnaryExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + + let expression = Box::new(untyped::ExpressionNode::from(*unary.expression)); + + match unary.op { + pest::UnaryOperator::Not(..) => untyped::Expression::Not(expression), + pest::UnaryOperator::Neg(..) => untyped::Expression::Neg(expression), + pest::UnaryOperator::Pos(..) => untyped::Expression::Pos(expression), + } + .span(unary.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::PostfixExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + + let base = untyped::ExpressionNode::from(*expression.base); + + // pest::PostFixExpression contains an array of "accesses": `a(34)[42]` is represented as `[a, [Call(34), Select(42)]]`, but untyped::ExpressionNode + // is recursive, so it is `Select(Call(a, 34), 42)`. We apply this transformation here + // we start with the base, and we fold the array of accesses by wrapping the current value + expression + .accesses + .into_iter() + .fold(base, |acc, a| match a { + pest::Access::Call(a) => untyped::Expression::FunctionCall( + Box::new(acc), + a.explicit_generics.map(|explicit_generics| { + explicit_generics + .values + .into_iter() + .map(|i| match i { + pest::ConstantGenericValue::Underscore(_) => None, + pest::ConstantGenericValue::Value(v) => { + Some(untyped::ExpressionNode::from(v)) + } + pest::ConstantGenericValue::Identifier(i) => Some( + untyped::Expression::Identifier(i.span.as_str()).span(i.span), + ), + }) + .collect() + }), + a.arguments + .expressions + .into_iter() + .map(untyped::ExpressionNode::from) + .collect(), + ) + .span(a.span), + pest::Access::Select(a) => untyped::Expression::Select( + box acc, + box untyped::RangeOrExpression::from(a.expression), + ) + .span(a.span), + pest::Access::Dot(m) => match m.inner { + pest::IdentifierOrDecimal::Identifier(id) => { + untyped::Expression::Member(box acc, box id.span.as_str()).span(m.span) + } + pest::IdentifierOrDecimal::Decimal(id) => { + untyped::Expression::Element(box acc, id.span.as_str().parse().unwrap()) + .span(m.span) + } + }, + }) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::DecimalLiteralExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + + match expression.suffix { + Some(suffix) => match suffix { + pest::DecimalSuffix::Field(_) => untyped::Expression::FieldConstant( + BigUint::parse_bytes(expression.value.span.as_str().as_bytes(), 10).unwrap(), + ), + pest::DecimalSuffix::U64(_) => untyped::Expression::U64Constant( + expression.value.span.as_str().parse().unwrap(), + ), + pest::DecimalSuffix::U32(_) => untyped::Expression::U32Constant( + expression.value.span.as_str().parse().unwrap(), + ), + pest::DecimalSuffix::U16(_) => untyped::Expression::U16Constant( + expression.value.span.as_str().parse().unwrap(), + ), + pest::DecimalSuffix::U8(_) => { + untyped::Expression::U8Constant(expression.value.span.as_str().parse().unwrap()) + } + } + .span(expression.span), + None => untyped::Expression::IntConstant( + BigUint::parse_bytes(expression.value.span.as_str().as_bytes(), 10).unwrap(), + ) + .span(expression.span), + } + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::HexLiteralExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + + match expression.value { + pest::HexNumberExpression::U64(e) => { + untyped::Expression::U64Constant(u64::from_str_radix(e.span.as_str(), 16).unwrap()) + } + pest::HexNumberExpression::U32(e) => { + untyped::Expression::U32Constant(u32::from_str_radix(e.span.as_str(), 16).unwrap()) + } + pest::HexNumberExpression::U16(e) => { + untyped::Expression::U16Constant(u16::from_str_radix(e.span.as_str(), 16).unwrap()) + } + pest::HexNumberExpression::U8(e) => { + untyped::Expression::U8Constant(u8::from_str_radix(e.span.as_str(), 16).unwrap()) + } + } + .span(expression.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::LiteralExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + + match expression { + pest::LiteralExpression::BooleanLiteral(c) => { + untyped::Expression::BooleanConstant(c.value.parse().unwrap()).span(c.span) + } + pest::LiteralExpression::DecimalLiteral(n) => untyped::ExpressionNode::from(n), + pest::LiteralExpression::HexLiteral(n) => untyped::ExpressionNode::from(n), + } + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::IdentifierExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + untyped::Expression::Identifier(expression.span.as_str()).span(expression.span) + } +} + +impl<'ast> From> for untyped::AssigneeNode<'ast> { + fn from(expression: pest::IdentifierExpression<'ast>) -> untyped::AssigneeNode<'ast> { + use crate::untyped::NodeValue; + + untyped::Assignee::Identifier(expression.span.as_str()).span(expression.span) + } +} + +impl<'ast> From> for untyped::AssigneeNode<'ast> { + fn from(assignee: pest::Assignee<'ast>) -> untyped::AssigneeNode<'ast> { + use crate::untyped::NodeValue; + + let a = untyped::AssigneeNode::from(assignee.id); + let span = assignee.span; + + assignee.accesses.into_iter().fold(a, |acc, s| { + match s { + pest::AssigneeAccess::Select(s) => untyped::Assignee::Select( + box acc, + box untyped::RangeOrExpression::from(s.expression), + ), + pest::AssigneeAccess::Dot(a) => match a.inner { + pest::IdentifierOrDecimal::Identifier(id) => { + untyped::Assignee::Member(box acc, box id.span.as_str()) + } + pest::IdentifierOrDecimal::Decimal(id) => { + untyped::Assignee::Element(box acc, id.span.as_str().parse().unwrap()) + } + }, + } + .span(span.clone()) + }) + } +} + +impl<'ast> From> for untyped::UnresolvedTypeNode<'ast> { + fn from(t: pest::Type<'ast>) -> untyped::UnresolvedTypeNode<'ast> { + use crate::untyped::types::UnresolvedType; + use crate::untyped::NodeValue; + + match t { + pest::Type::Basic(t) => match t { + pest::BasicType::Field(t) => UnresolvedType::FieldElement.span(t.span), + pest::BasicType::Boolean(t) => UnresolvedType::Boolean.span(t.span), + pest::BasicType::U8(t) => UnresolvedType::Uint(8).span(t.span), + pest::BasicType::U16(t) => UnresolvedType::Uint(16).span(t.span), + pest::BasicType::U32(t) => UnresolvedType::Uint(32).span(t.span), + pest::BasicType::U64(t) => UnresolvedType::Uint(64).span(t.span), + }, + pest::Type::Array(t) => { + let inner_type = match t.ty { + pest::BasicOrStructOrTupleType::Basic(t) => match t { + pest::BasicType::Field(t) => UnresolvedType::FieldElement.span(t.span), + pest::BasicType::Boolean(t) => UnresolvedType::Boolean.span(t.span), + pest::BasicType::U8(t) => UnresolvedType::Uint(8).span(t.span), + pest::BasicType::U16(t) => UnresolvedType::Uint(16).span(t.span), + pest::BasicType::U32(t) => UnresolvedType::Uint(32).span(t.span), + pest::BasicType::U64(t) => UnresolvedType::Uint(64).span(t.span), + }, + pest::BasicOrStructOrTupleType::Struct(t) => UnresolvedType::User( + t.id.span.as_str().to_string(), + t.explicit_generics.map(|explicit_generics| { + explicit_generics + .values + .into_iter() + .map(|i| match i { + pest::ConstantGenericValue::Underscore(_) => None, + pest::ConstantGenericValue::Value(v) => { + Some(untyped::ExpressionNode::from(v)) + } + pest::ConstantGenericValue::Identifier(i) => Some( + untyped::Expression::Identifier(i.span.as_str()) + .span(i.span), + ), + }) + .collect() + }), + ) + .span(t.span), + pest::BasicOrStructOrTupleType::Tuple(t) => UnresolvedType::Tuple( + t.elements + .into_iter() + .map(untyped::UnresolvedTypeNode::from) + .collect(), + ) + .span(t.span), + }; + + let span = t.span; + + t.dimensions + .into_iter() + .map(untyped::ExpressionNode::from) + .rev() + .fold(None, |acc, s| match acc { + None => Some(UnresolvedType::array(inner_type.clone(), s)), + Some(acc) => Some(UnresolvedType::array(acc.span(span.clone()), s)), + }) + .unwrap() + .span(span.clone()) + } + pest::Type::Struct(s) => UnresolvedType::User( + s.id.span.as_str().to_string(), + s.explicit_generics.map(|explicit_generics| { + explicit_generics + .values + .into_iter() + .map(|i| match i { + pest::ConstantGenericValue::Underscore(_) => None, + pest::ConstantGenericValue::Value(v) => { + Some(untyped::ExpressionNode::from(v)) + } + pest::ConstantGenericValue::Identifier(i) => { + Some(untyped::Expression::Identifier(i.span.as_str()).span(i.span)) + } + }) + .collect() + }), + ) + .span(s.span), + pest::Type::Tuple(t) => UnresolvedType::Tuple( + t.elements + .into_iter() + .map(untyped::UnresolvedTypeNode::from) + .collect(), + ) + .span(t.span), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::untyped::types::{UnresolvedSignature, UnresolvedType}; + use crate::untyped::NodeValue; + + #[test] + fn return_forty_two() { + let source = "def main() -> field { return 42; }"; + let ast = pest::generate_ast(source).unwrap(); + let expected: untyped::Module = untyped::Module { + symbols: vec![untyped::SymbolDeclaration { + id: &source[4..8], + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function( + untyped::Function { + arguments: vec![], + statements: vec![untyped::Statement::Return(Some( + untyped::Expression::IntConstant(42usize.into()).into(), + )) + .into()], + signature: UnresolvedSignature::new() + .inputs(vec![]) + .output(UnresolvedType::FieldElement.mock()), + } + .into(), + )), + } + .into()], + }; + assert_eq!(untyped::Module::from(ast), expected); + } + + #[test] + fn return_true() { + let source = "def main() -> bool { return true; }"; + let ast = pest::generate_ast(source).unwrap(); + let expected: untyped::Module = untyped::Module { + symbols: vec![untyped::SymbolDeclaration { + id: &source[4..8], + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function( + untyped::Function { + arguments: vec![], + statements: vec![untyped::Statement::Return(Some( + untyped::Expression::BooleanConstant(true).into(), + )) + .into()], + signature: UnresolvedSignature::new() + .inputs(vec![]) + .output(UnresolvedType::Boolean.mock()), + } + .into(), + )), + } + .into()], + }; + assert_eq!(untyped::Module::from(ast), expected); + } + + #[test] + fn arguments() { + let source = "def main(private field a, bool mut b) -> field { return 42; }"; + let ast = pest::generate_ast(source).unwrap(); + + let expected: untyped::Module = untyped::Module { + symbols: vec![untyped::SymbolDeclaration { + id: &source[4..8], + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function( + untyped::Function { + arguments: vec![ + untyped::Parameter::private( + untyped::Variable::immutable( + "a", + UnresolvedType::FieldElement.mock(), + ) + .into(), + ) + .into(), + untyped::Parameter::public( + untyped::Variable::mutable("b", UnresolvedType::Boolean.mock()) + .into(), + ) + .into(), + ], + statements: vec![untyped::Statement::Return(Some( + untyped::Expression::IntConstant(42usize.into()).into(), + )) + .into()], + signature: UnresolvedSignature::new() + .inputs(vec![ + UnresolvedType::FieldElement.mock(), + UnresolvedType::Boolean.mock(), + ]) + .output(UnresolvedType::FieldElement.mock()), + } + .into(), + )), + } + .into()], + }; + + assert_eq!(untyped::Module::from(ast), expected); + } + + mod types { + use super::*; + + /// Helper method to generate the ast for `def main(private {ty} a) { return; }` which we use to check ty + fn wrap(ty: UnresolvedType<'static>) -> untyped::Module<'static> { + untyped::Module { + symbols: vec![untyped::SymbolDeclaration { + id: "main", + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function( + untyped::Function { + arguments: vec![untyped::Parameter::private( + untyped::Variable::new("a", ty.clone().mock(), false).into(), + ) + .into()], + statements: vec![untyped::Statement::Return(None).into()], + signature: UnresolvedSignature::new().inputs(vec![ty.mock()]), + } + .into(), + )), + } + .into()], + } + } + + #[test] + fn array() { + let vectors = vec![ + ("field", UnresolvedType::FieldElement), + ("bool", UnresolvedType::Boolean), + ( + "field[2]", + untyped::UnresolvedType::Array( + box untyped::UnresolvedType::FieldElement.mock(), + untyped::Expression::IntConstant(2usize.into()).mock(), + ), + ), + ( + "field[2][3]", + untyped::UnresolvedType::Array( + box untyped::UnresolvedType::Array( + box untyped::UnresolvedType::FieldElement.mock(), + untyped::Expression::IntConstant(3usize.into()).mock(), + ) + .mock(), + untyped::Expression::IntConstant(2usize.into()).mock(), + ), + ), + ( + "bool[2][3u32]", + untyped::UnresolvedType::Array( + box untyped::UnresolvedType::Array( + box untyped::UnresolvedType::Boolean.mock(), + untyped::Expression::U32Constant(3u32).mock(), + ) + .mock(), + untyped::Expression::IntConstant(2usize.into()).mock(), + ), + ), + ]; + + for (ty, expected) in vectors { + let source = format!("def main(private {} a) {{ return; }}", ty); + let expected = wrap(expected); + let ast = pest::generate_ast(&source).unwrap(); + assert_eq!(untyped::Module::from(ast), expected); + } + } + } + + mod postfix { + use super::*; + fn wrap(expression: untyped::Expression<'static>) -> untyped::Module { + untyped::Module { + symbols: vec![untyped::SymbolDeclaration { + id: "main", + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function( + untyped::Function { + arguments: vec![], + statements: vec![ + untyped::Statement::Return(Some(expression.into())).into() + ], + signature: UnresolvedSignature::new(), + } + .into(), + )), + } + .into()], + } + } + + #[test] + fn success() { + // we basically accept `()?[]*` : an optional call at first, then only array accesses + + let vectors = vec![ + ("a", untyped::Expression::Identifier("a")), + ( + "a[3]", + untyped::Expression::Select( + box untyped::Expression::Identifier("a").into(), + box untyped::RangeOrExpression::Expression( + untyped::Expression::IntConstant(3usize.into()).into(), + ), + ), + ), + ( + "a[3][4]", + untyped::Expression::Select( + box untyped::Expression::Select( + box untyped::Expression::Identifier("a").into(), + box untyped::RangeOrExpression::Expression( + untyped::Expression::IntConstant(3usize.into()).into(), + ), + ) + .into(), + box untyped::RangeOrExpression::Expression( + untyped::Expression::IntConstant(4usize.into()).into(), + ), + ), + ), + ( + "a(3)[4]", + untyped::Expression::Select( + box untyped::Expression::FunctionCall( + box untyped::Expression::Identifier("a").mock(), + None, + vec![untyped::Expression::IntConstant(3usize.into()).into()], + ) + .into(), + box untyped::RangeOrExpression::Expression( + untyped::Expression::IntConstant(4usize.into()).into(), + ), + ), + ), + ( + "a(3)[4][5]", + untyped::Expression::Select( + box untyped::Expression::Select( + box untyped::Expression::FunctionCall( + box untyped::Expression::Identifier("a").mock(), + None, + vec![untyped::Expression::IntConstant(3usize.into()).into()], + ) + .into(), + box untyped::RangeOrExpression::Expression( + untyped::Expression::IntConstant(4usize.into()).into(), + ), + ) + .into(), + box untyped::RangeOrExpression::Expression( + untyped::Expression::IntConstant(5usize.into()).into(), + ), + ), + ), + ]; + + for (source, expected) in vectors { + let source = format!("def main() {{ return {}; }}", source); + let expected = wrap(expected); + let ast = pest::generate_ast(&source).unwrap(); + assert_eq!(untyped::Module::from(ast), expected); + } + } + + #[test] + fn call_array_element() { + // a call after an array access should be accepted + let source = "def main() { return a[2](3); }"; + let ast = pest::generate_ast(source).unwrap(); + assert_eq!( + untyped::Module::from(ast), + wrap(untyped::Expression::FunctionCall( + box untyped::Expression::Select( + box untyped::Expression::Identifier("a").mock(), + box untyped::RangeOrExpression::Expression( + untyped::Expression::IntConstant(2u32.into()).mock() + ) + ) + .mock(), + None, + vec![untyped::Expression::IntConstant(3u32.into()).mock()], + )) + ); + } + + #[test] + fn call_call_result() { + // a call after a call should be accepted + let source = "def main() { return a(2)(3); }"; + + let ast = pest::generate_ast(source).unwrap(); + assert_eq!( + untyped::Module::from(ast), + wrap(untyped::Expression::FunctionCall( + box untyped::Expression::FunctionCall( + box untyped::Expression::Identifier("a").mock(), + None, + vec![untyped::Expression::IntConstant(2u32.into()).mock()] + ) + .mock(), + None, + vec![untyped::Expression::IntConstant(3u32.into()).mock()], + )) + ); + } + } + #[test] + fn declarations() { + use self::pest::Span; + + let span = Span::new("", 0, 0).unwrap(); + + // Case 1: `id = expr` + // A simple assignment to an already defined variable + + let definition = pest::DefinitionStatement { + lhs: pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee { + id: pest::IdentifierExpression { + value: String::from("a"), + span: span.clone(), + }, + accesses: vec![], + span: span.clone(), + }), + expression: pest::Expression::Literal(pest::LiteralExpression::DecimalLiteral( + pest::DecimalLiteralExpression { + value: pest::DecimalNumber { + span: Span::new("1", 0, 1).unwrap(), + }, + suffix: None, + span: span.clone(), + }, + )), + span: span.clone(), + }; + + let statement = untyped::StatementNode::from(definition); + + match statement.value { + untyped::Statement::Assignment(..) => {} + s => { + panic!("should be an Assignment, found {}", s); + } + }; + + // Case 2: `type id = expr` + // A definition statement is generated + + let definition = pest::DefinitionStatement { + lhs: pest::TypedIdentifierOrAssignee::TypedIdentifier(pest::TypedIdentifier { + ty: pest::Type::Basic(pest::BasicType::Field(pest::FieldType { + span: span.clone(), + })), + identifier: pest::IdentifierExpression { + value: String::from("a"), + span: span.clone(), + }, + mutable: None, + span: span.clone(), + }), + expression: pest::Expression::Postfix(pest::PostfixExpression { + base: box pest::Expression::Identifier(pest::IdentifierExpression { + value: String::from("foo"), + span: span.clone(), + }), + accesses: vec![pest::Access::Call(pest::CallAccess { + explicit_generics: None, + arguments: pest::Arguments { + expressions: vec![], + span: span.clone(), + }, + span: span.clone(), + })], + span: span.clone(), + }), + span: span.clone(), + }; + + let statement = untyped::StatementNode::from(definition); + + match statement.value { + untyped::Statement::Definition(..) => {} + s => { + panic!("should be a Definition, found {}", s); + } + }; + } +} diff --git a/zokrates_core/src/absy/mod.rs b/zokrates_ast/src/untyped/mod.rs similarity index 98% rename from zokrates_core/src/absy/mod.rs rename to zokrates_ast/src/untyped/mod.rs index 7ec3c83d..b77e2fbc 100644 --- a/zokrates_core/src/absy/mod.rs +++ b/zokrates_ast/src/untyped/mod.rs @@ -8,14 +8,16 @@ mod from_ast; mod node; pub mod parameter; +mod position; pub mod types; pub mod variable; -pub use crate::absy::node::{Node, NodeValue}; -pub use crate::absy::parameter::{Parameter, ParameterNode}; -use crate::absy::types::{UnresolvedSignature, UnresolvedType, UserTypeId}; -pub use crate::absy::variable::{Variable, VariableNode}; -use crate::embed::FlatEmbed; +pub use self::node::{Node, NodeValue}; +pub use self::parameter::{Parameter, ParameterNode}; +pub use self::position::Position; +use self::types::{UnresolvedSignature, UnresolvedType, UserTypeId}; +pub use self::variable::{Variable, VariableNode}; +use crate::common::FlatEmbed; use std::path::{Path, PathBuf}; use std::fmt; diff --git a/zokrates_core/src/absy/node.rs b/zokrates_ast/src/untyped/node.rs similarity index 96% rename from zokrates_core/src/absy/node.rs rename to zokrates_ast/src/untyped/node.rs index 3010f041..44cda49f 100644 --- a/zokrates_core/src/absy/node.rs +++ b/zokrates_ast/src/untyped/node.rs @@ -1,4 +1,3 @@ -use crate::parser::Position; use std::fmt; use zokrates_pest_ast::Span; @@ -53,7 +52,6 @@ pub trait NodeValue: fmt::Display + fmt::Debug + Sized + PartialEq { Node::new(start, end, self) } - #[cfg(test)] fn mock(self) -> Node { Node::new(Position::mock(), Position::mock(), self) } @@ -81,8 +79,7 @@ impl From for Node { } } -use crate::absy::types::UnresolvedType; -use crate::absy::*; +use super::*; impl<'ast> NodeValue for Expression<'ast> {} impl<'ast> NodeValue for Assignee<'ast> {} diff --git a/zokrates_core/src/absy/parameter.rs b/zokrates_ast/src/untyped/parameter.rs similarity index 96% rename from zokrates_core/src/absy/parameter.rs rename to zokrates_ast/src/untyped/parameter.rs index 8645de4d..af6e4ae5 100644 --- a/zokrates_core/src/absy/parameter.rs +++ b/zokrates_ast/src/untyped/parameter.rs @@ -1,4 +1,4 @@ -use crate::absy::{Node, VariableNode}; +use super::{Node, VariableNode}; use std::fmt; #[derive(Clone, PartialEq)] diff --git a/zokrates_core/src/parser/tokenize/position.rs b/zokrates_ast/src/untyped/position.rs similarity index 100% rename from zokrates_core/src/parser/tokenize/position.rs rename to zokrates_ast/src/untyped/position.rs diff --git a/zokrates_core/src/absy/types.rs b/zokrates_ast/src/untyped/types.rs similarity index 96% rename from zokrates_core/src/absy/types.rs rename to zokrates_ast/src/untyped/types.rs index 1bb1f765..0f6c4ba4 100644 --- a/zokrates_core/src/absy/types.rs +++ b/zokrates_ast/src/untyped/types.rs @@ -1,5 +1,5 @@ -use crate::absy::ExpressionNode; -use crate::absy::UnresolvedTypeNode; +use super::ExpressionNode; +use super::UnresolvedTypeNode; use std::fmt; pub type Identifier<'ast> = &'ast str; @@ -76,10 +76,10 @@ impl<'ast> UnresolvedType<'ast> { pub use self::signature::UnresolvedSignature; mod signature { - use crate::absy::ConstantGenericNode; + use crate::untyped::ConstantGenericNode; use std::fmt; - use crate::absy::UnresolvedTypeNode; + use crate::untyped::UnresolvedTypeNode; #[derive(Clone, PartialEq, Default)] pub struct UnresolvedSignature<'ast> { diff --git a/zokrates_core/src/absy/variable.rs b/zokrates_ast/src/untyped/variable.rs similarity index 91% rename from zokrates_core/src/absy/variable.rs rename to zokrates_ast/src/untyped/variable.rs index 3c646ac4..edbc7f4c 100644 --- a/zokrates_core/src/absy/variable.rs +++ b/zokrates_ast/src/untyped/variable.rs @@ -1,8 +1,8 @@ -use crate::absy::types::UnresolvedType; -use crate::absy::{Node, UnresolvedTypeNode}; +use super::types::UnresolvedType; +use super::{Node, UnresolvedTypeNode}; use std::fmt; -use crate::absy::Identifier; +use super::Identifier; #[derive(Clone, PartialEq)] pub struct Variable<'ast> { diff --git a/zokrates_core/src/zir/folder.rs b/zokrates_ast/src/zir/folder.rs similarity index 100% rename from zokrates_core/src/zir/folder.rs rename to zokrates_ast/src/zir/folder.rs diff --git a/zokrates_core/src/zir/from_typed.rs b/zokrates_ast/src/zir/from_typed.rs similarity index 97% rename from zokrates_core/src/zir/from_typed.rs rename to zokrates_ast/src/zir/from_typed.rs index 24f1b6ea..170c23b4 100644 --- a/zokrates_core/src/zir/from_typed.rs +++ b/zokrates_ast/src/zir/from_typed.rs @@ -1,4 +1,4 @@ -use crate::typed_absy; +use crate::typed as typed_absy; use crate::zir; impl From for zir::types::Signature { diff --git a/zokrates_core/src/zir/identifier.rs b/zokrates_ast/src/zir/identifier.rs similarity index 95% rename from zokrates_core/src/zir/identifier.rs rename to zokrates_ast/src/zir/identifier.rs index 5d379c2a..f010f2f8 100644 --- a/zokrates_core/src/zir/identifier.rs +++ b/zokrates_ast/src/zir/identifier.rs @@ -1,7 +1,7 @@ use crate::zir::types::MemberId; use std::fmt; -use crate::typed_absy::Identifier as CoreIdentifier; +use crate::typed::Identifier as CoreIdentifier; #[derive(Debug, PartialEq, Clone, Hash, Eq)] pub enum Identifier<'ast> { diff --git a/zokrates_core/src/zir/mod.rs b/zokrates_ast/src/zir/mod.rs similarity index 99% rename from zokrates_core/src/zir/mod.rs rename to zokrates_ast/src/zir/mod.rs index 0d6190cf..0356cfef 100644 --- a/zokrates_core/src/zir/mod.rs +++ b/zokrates_ast/src/zir/mod.rs @@ -10,9 +10,9 @@ mod variable; pub use self::parameter::Parameter; pub use self::types::Type; pub use self::variable::Variable; +use crate::common::FlatEmbed; pub use crate::zir::uint::{ShouldReduce, UExpression, UExpressionInner, UMetadata}; -use crate::embed::FlatEmbed; use crate::zir::types::Signature; use std::convert::TryFrom; use std::fmt; @@ -102,6 +102,12 @@ impl fmt::Display for RuntimeError { } } +impl RuntimeError { + pub fn mock() -> Self { + RuntimeError::SourceAssertion(String::default()) + } +} + /// A statement in a `ZirFunction` #[derive(Clone, PartialEq, Hash, Eq, Debug)] pub enum ZirStatement<'ast, T> { diff --git a/zokrates_core/src/zir/parameter.rs b/zokrates_ast/src/zir/parameter.rs similarity index 100% rename from zokrates_core/src/zir/parameter.rs rename to zokrates_ast/src/zir/parameter.rs diff --git a/zokrates_core/src/zir/result_folder.rs b/zokrates_ast/src/zir/result_folder.rs similarity index 100% rename from zokrates_core/src/zir/result_folder.rs rename to zokrates_ast/src/zir/result_folder.rs diff --git a/zokrates_core/src/zir/types.rs b/zokrates_ast/src/zir/types.rs similarity index 100% rename from zokrates_core/src/zir/types.rs rename to zokrates_ast/src/zir/types.rs diff --git a/zokrates_core/src/zir/uint.rs b/zokrates_ast/src/zir/uint.rs similarity index 96% rename from zokrates_core/src/zir/uint.rs rename to zokrates_ast/src/zir/uint.rs index 47474adb..0198ba71 100644 --- a/zokrates_core/src/zir/uint.rs +++ b/zokrates_ast/src/zir/uint.rs @@ -4,12 +4,14 @@ use crate::zir::BooleanExpression; use zokrates_field::Field; impl<'ast, T: Field> UExpression<'ast, T> { + #[allow(clippy::should_implement_trait)] pub fn add(self, other: Self) -> UExpression<'ast, T> { let bitwidth = self.bitwidth; assert_eq!(bitwidth, other.bitwidth); UExpressionInner::Add(box self, box other).annotate(bitwidth) } + #[allow(clippy::should_implement_trait)] pub fn sub(self, other: Self) -> UExpression<'ast, T> { let bitwidth = self.bitwidth; assert_eq!(bitwidth, other.bitwidth); @@ -27,12 +29,14 @@ impl<'ast, T: Field> UExpression<'ast, T> { UExpressionInner::Mult(box self, box other).annotate(bitwidth) } + #[allow(clippy::should_implement_trait)] pub fn div(self, other: Self) -> UExpression<'ast, T> { let bitwidth = self.bitwidth; assert_eq!(bitwidth, other.bitwidth); UExpressionInner::Div(box self, box other).annotate(bitwidth) } + #[allow(clippy::should_implement_trait)] pub fn rem(self, other: Self) -> UExpression<'ast, T> { let bitwidth = self.bitwidth; assert_eq!(bitwidth, other.bitwidth); @@ -45,6 +49,7 @@ impl<'ast, T: Field> UExpression<'ast, T> { UExpressionInner::Xor(box self, box other).annotate(bitwidth) } + #[allow(clippy::should_implement_trait)] pub fn not(self) -> UExpression<'ast, T> { let bitwidth = self.bitwidth; UExpressionInner::Not(box self).annotate(bitwidth) diff --git a/zokrates_core/src/zir/variable.rs b/zokrates_ast/src/zir/variable.rs similarity index 100% rename from zokrates_core/src/zir/variable.rs rename to zokrates_ast/src/zir/variable.rs diff --git a/zokrates_bellman/Cargo.toml b/zokrates_bellman/Cargo.toml new file mode 100644 index 00000000..852b1fbe --- /dev/null +++ b/zokrates_bellman/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "zokrates_bellman" +version = "0.1.0" +edition = "2021" + +[features] +wasm = ["bellman/nolog", "bellman/wasm"] +multicore = ["bellman/multicore", "phase2/multicore"] + +[dependencies] +zokrates_field = { version = "0.5", path = "../zokrates_field", default-features = false } +zokrates_ast = { version = "0.1", path = "../zokrates_ast", default-features = false } +zokrates_proof_systems = { version = "0.1", path = "../zokrates_proof_systems", default-features = false } + +bellman = { package = "bellman_ce", version = "^0.3", default-features = false } +pairing = { package = "pairing_ce", version = "^0.21" } +phase2 = { git = "https://github.com/Zokrates/phase2", default-features = false } +rand_0_4 = { version = "0.4", package = "rand" }# +getrandom = { version = "0.2", features = ["js", "wasm-bindgen"] } +hex = "0.4.2" + +[dev-dependencies] +zokrates_interpreter = { version = "0.1", path = "../zokrates_interpreter", features = ["bellman"] } + + + + + diff --git a/zokrates_core/src/proof_system/bellman/groth16.rs b/zokrates_bellman/src/groth16.rs similarity index 87% rename from zokrates_core/src/proof_system/bellman/groth16.rs rename to zokrates_bellman/src/groth16.rs index de3da565..c918ccf5 100644 --- a/zokrates_core/src/proof_system/bellman/groth16.rs +++ b/zokrates_bellman/src/groth16.rs @@ -4,19 +4,19 @@ use bellman::groth16::{ }; use pairing::{ff::to_hex, CurveAffine, Engine}; -use crate::proof_system::{Backend, MpcBackend, NonUniversalBackend, Proof, SetupKeypair}; use zokrates_field::BellmanFieldExtensions; use zokrates_field::Field; +use zokrates_proof_systems::{Backend, MpcBackend, NonUniversalBackend, Proof, SetupKeypair}; -use crate::ir::{ProgIterator, Statement, Witness}; -use crate::proof_system::bellman::Bellman; -use crate::proof_system::bellman::Computation; -use crate::proof_system::bellman::{parse_g1, parse_g2}; -use crate::proof_system::groth16::{ProofPoints, VerificationKey, G16}; -use crate::proof_system::Scheme; +use crate::Bellman; +use crate::Computation; +use crate::{parse_g1, parse_g2}; use phase2::MPCParameters; use rand_0_4::Rng; use std::io::{Read, Write}; +use zokrates_ast::ir::{ProgIterator, Statement, Witness}; +use zokrates_proof_systems::groth16::{ProofPoints, VerificationKey, G16}; +use zokrates_proof_systems::Scheme; const G16_WARNING: &str = "WARNING: You are using the G16 scheme which is subject to malleability. See zokrates.github.io/toolbox/proving_schemes.html#g16-malleability for implications."; @@ -155,8 +155,8 @@ impl MpcBackend for Bellman { pub mod serialization { use super::*; - use crate::proof_system::{G1Affine, G2Affine}; use pairing::from_hex; + use zokrates_proof_systems::{G1Affine, G2Affine}; pub fn parameters_to_verification_key( parameters: &Parameters, @@ -186,29 +186,32 @@ pub mod serialization { pub fn to_g2( g2: G2Affine, ) -> ::G2Affine { - let x = T::new_fq2(&(g2.0).0, &(g2.0).1); - let y = T::new_fq2(&(g2.1).0, &(g2.1).1); - ::G2Affine::from_xy_unchecked(x, y) + match g2 { + G2Affine::Fq2(g2) => { + let x = T::new_fq2(&(g2.0).0, &(g2.0).1); + let y = T::new_fq2(&(g2.1).0, &(g2.1).1); + ::G2Affine::from_xy_unchecked(x, y) + } + _ => unreachable!(), + } } } #[cfg(test)] mod tests { use zokrates_field::Bn128Field; + use zokrates_interpreter::Interpreter; use super::*; - use crate::flat_absy::{FlatParameter, FlatVariable}; - use crate::ir::{Interpreter, Prog, Statement}; + use zokrates_ast::common::{Parameter, Variable}; + use zokrates_ast::ir::{Prog, Statement}; #[test] fn verify() { let program: Prog = Prog { - arguments: vec![FlatParameter::public(FlatVariable::new(0))], + arguments: vec![Parameter::public(Variable::new(0))], return_count: 1, - statements: vec![Statement::constraint( - FlatVariable::new(0), - FlatVariable::public(0), - )], + statements: vec![Statement::constraint(Variable::new(0), Variable::public(0))], }; let keypair = >::setup(program.clone()); diff --git a/zokrates_core/src/proof_system/bellman/mod.rs b/zokrates_bellman/src/lib.rs similarity index 81% rename from zokrates_core/src/proof_system/bellman/mod.rs rename to zokrates_bellman/src/lib.rs index 3e3cd2fc..f6413f18 100644 --- a/zokrates_core/src/proof_system/bellman/mod.rs +++ b/zokrates_bellman/src/lib.rs @@ -1,18 +1,20 @@ pub mod groth16; -use crate::ir::{CanonicalLinComb, ProgIterator, Statement, Witness}; use bellman::groth16::Proof; use bellman::groth16::{ create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof, Parameters, }; use bellman::pairing::ff::ScalarEngine; -use bellman::{Circuit, ConstraintSystem, LinearCombination, SynthesisError, Variable}; +use bellman::{ + Circuit, ConstraintSystem, LinearCombination, SynthesisError, Variable as BellmanVariable, +}; use std::collections::BTreeMap; +use zokrates_ast::common::Variable; +use zokrates_ast::ir::{CanonicalLinComb, ProgIterator, Statement, Witness}; use zokrates_field::BellmanFieldExtensions; use zokrates_field::Field; -use crate::flat_absy::FlatVariable; use rand_0_4::ChaChaRng; pub use self::parse::*; @@ -44,7 +46,7 @@ impl>> Computation { fn bellman_combination>( l: CanonicalLinComb, cs: &mut CS, - symbols: &mut BTreeMap, + symbols: &mut BTreeMap, witness: &mut Witness, ) -> LinearCombination { l.0.into_iter() @@ -81,20 +83,21 @@ fn bellman_combination>> ProgIterator { - pub fn synthesize>( +impl>> + Circuit for Computation +{ + fn synthesize>( self, cs: &mut CS, - witness: Option>, ) -> Result<(), SynthesisError> { // mapping from IR variables let mut symbols = BTreeMap::new(); - let mut witness = witness.unwrap_or_else(Witness::empty); + let mut witness = self.witness.unwrap_or_else(Witness::empty); - assert!(symbols.insert(FlatVariable::one(), CS::one()).is_none()); + assert!(symbols.insert(Variable::one(), CS::one()).is_none()); - symbols.extend(self.arguments.iter().enumerate().map(|(index, p)| { + symbols.extend(self.program.arguments.iter().enumerate().map(|(index, p)| { let wire = match p.private { true => cs.alloc( || format!("PRIVATE_INPUT_{}", index), @@ -121,7 +124,7 @@ impl>> Pr (p.id, wire) })); - for statement in self.statements { + for statement in self.program.statements { if let Statement::Constraint(quad, lin, _) = statement { let a = &bellman_combination( quad.left.into_canonical(), @@ -192,21 +195,10 @@ impl>> Co } } -impl>> - Circuit for Computation -{ - fn synthesize>( - self, - cs: &mut CS, - ) -> Result<(), SynthesisError> { - self.program.synthesize(cs, self.witness) - } -} - mod parse { use super::*; - use crate::proof_system::{G1Affine, G2Affine}; - use pairing_ce::CurveAffine; + use pairing::CurveAffine; + use zokrates_proof_systems::{G1Affine, G2Affine, G2AffineFq2}; fn to_hex(bytes: &[u8]) -> String { let mut hex = hex::encode(bytes); @@ -239,21 +231,21 @@ mod parse { let y1 = to_hex(iter.next().unwrap()); let y0 = to_hex(iter.next().unwrap()); - G2Affine((x0, x1), (y0, y1)) + G2Affine::Fq2(G2AffineFq2((x0, x1), (y0, y1))) } } #[cfg(test)] mod tests { use super::*; - use crate::ir::Interpreter; - use crate::ir::LinComb; + use zokrates_ast::ir::LinComb; use zokrates_field::Bn128Field; + use zokrates_interpreter::Interpreter; mod prove { use super::*; - use crate::flat_absy::FlatParameter; - use crate::ir::Prog; + use zokrates_ast::flat::Parameter; + use zokrates_ast::ir::Prog; #[test] fn empty() { @@ -271,12 +263,9 @@ mod tests { #[test] fn identity() { let program: Prog = Prog { - arguments: vec![FlatParameter::private(FlatVariable::new(0))], + arguments: vec![Parameter::private(Variable::new(0))], return_count: 1, - statements: vec![Statement::constraint( - FlatVariable::new(0), - FlatVariable::public(0), - )], + statements: vec![Statement::constraint(Variable::new(0), Variable::public(0))], }; let interpreter = Interpreter::default(); @@ -294,12 +283,9 @@ mod tests { #[test] fn public_identity() { let program: Prog = Prog { - arguments: vec![FlatParameter::public(FlatVariable::new(0))], + arguments: vec![Parameter::public(Variable::new(0))], return_count: 1, - statements: vec![Statement::constraint( - FlatVariable::new(0), - FlatVariable::public(0), - )], + statements: vec![Statement::constraint(Variable::new(0), Variable::public(0))], }; let interpreter = Interpreter::default(); @@ -319,10 +305,7 @@ mod tests { let program: Prog = Prog { arguments: vec![], return_count: 1, - statements: vec![Statement::constraint( - FlatVariable::one(), - FlatVariable::public(0), - )], + statements: vec![Statement::constraint(Variable::one(), Variable::public(0))], }; let interpreter = Interpreter::default(); @@ -340,18 +323,18 @@ mod tests { // private variables can be unordered let program: Prog = Prog { arguments: vec![ - FlatParameter::private(FlatVariable::new(42)), - FlatParameter::public(FlatVariable::new(51)), + Parameter::private(Variable::new(42)), + Parameter::public(Variable::new(51)), ], return_count: 2, statements: vec![ Statement::constraint( - LinComb::from(FlatVariable::new(42)) + LinComb::from(FlatVariable::new(51)), - FlatVariable::public(0), + LinComb::from(Variable::new(42)) + LinComb::from(Variable::new(51)), + Variable::public(0), ), Statement::constraint( - LinComb::from(FlatVariable::one()) + LinComb::from(FlatVariable::new(42)), - FlatVariable::public(1), + LinComb::from(Variable::one()) + LinComb::from(Variable::new(42)), + Variable::public(1), ), ], }; @@ -370,11 +353,11 @@ mod tests { #[test] fn one() { let program: Prog = Prog { - arguments: vec![FlatParameter::public(FlatVariable::new(42))], + arguments: vec![Parameter::public(Variable::new(42))], return_count: 1, statements: vec![Statement::constraint( - LinComb::from(FlatVariable::new(42)) + LinComb::one(), - FlatVariable::public(0), + LinComb::from(Variable::new(42)) + LinComb::one(), + Variable::public(0), )], }; @@ -394,13 +377,13 @@ mod tests { fn with_directives() { let program: Prog = Prog { arguments: vec![ - FlatParameter::private(FlatVariable::new(42)), - FlatParameter::public(FlatVariable::new(51)), + Parameter::private(Variable::new(42)), + Parameter::public(Variable::new(51)), ], return_count: 1, statements: vec![Statement::constraint( - LinComb::from(FlatVariable::new(42)) + LinComb::from(FlatVariable::new(51)), - FlatVariable::public(0), + LinComb::from(Variable::new(42)) + LinComb::from(Variable::new(51)), + Variable::public(0), )], }; diff --git a/zokrates_book/src/toolbox/proving_schemes.md b/zokrates_book/src/toolbox/proving_schemes.md index a5274c8c..07096975 100644 --- a/zokrates_book/src/toolbox/proving_schemes.md +++ b/zokrates_book/src/toolbox/proving_schemes.md @@ -48,7 +48,6 @@ ZoKrates supports multiple backends. The options are the following: | Backend | CLI flag | Proving schemes | Curves | | ---- | -------- |-------------------|------------------------------------------| | Bellman | `--backend bellman` | G16 | ALTBN_128, BLS12_381 | -| Libsnark | `--backend libsnark` | GM17, PGHR13 | ALTBN_128 | | Ark | `--backend ark` | G16, GM17, MARLIN | ALTBN_128, BLS12_381, BLS12_377, BW6_761 | Default: `bellman` @@ -59,12 +58,6 @@ When not using the default, the CLI flag has to be provided for the following co - `generate-proof` - `verify` -To include libsnark in the build, compile ZoKrates from [source](https://github.com/ZoKrates/ZoKrates/) with the `libsnark` feature: -```bash -cargo +nightly -Z package-features build --release --package zokrates_cli --features="libsnark" -``` - Note, that this is only tested for Linux. If you are on another OS, consider using our Docker container, which includes a libsnark installation. - ## G16 malleability When using G16, developers should pay attention to the fact that an attacker, seeing a valid proof, can very easily generate a different but still valid proof. Therefore, depending on the use case, making sure on chain that the same proof cannot be submitted twice may *not* be enough to guarantee that attackers cannot replay proofs. Mechanisms to solve this issue include: diff --git a/zokrates_cli/Cargo.toml b/zokrates_cli/Cargo.toml index 5109b5bc..dfbcc3b6 100644 --- a/zokrates_cli/Cargo.toml +++ b/zokrates_cli/Cargo.toml @@ -7,9 +7,8 @@ edition = "2018" [features] default = ["bellman", "ark"] -libsnark = ["zokrates_core/libsnark", "zokrates_common/libsnark"] -bellman = ["zokrates_core/bellman", "zokrates_common/bellman"] -ark = ["zokrates_core/ark", "zokrates_common/ark"] +bellman = ["zokrates_bellman", "zokrates_core/bellman", "zokrates_common/bellman"] +ark = ["zokrates_ark", "zokrates_core/ark", "zokrates_common/ark"] [dependencies] log = "0.4" @@ -21,9 +20,11 @@ regex = "0.2" zokrates_field = { version = "0.5", path = "../zokrates_field", default-features = false } zokrates_abi = { version = "0.1", path = "../zokrates_abi" } zokrates_core = { version = "0.6", path = "../zokrates_core", default-features = false } +zokrates_ast = { version = "0.1", path = "../zokrates_ast", default-features = false } +zokrates_interpreter = { version = "0.1", path = "../zokrates_interpreter", default-features = false } typed-arena = "1.4.1" zokrates_fs_resolver = { version = "0.5", path = "../zokrates_fs_resolver"} -zokrates_common = { version = "0.1", path = "../zokrates_common" } +zokrates_common = { version = "0.1", path = "../zokrates_common", default-features = false } serde_json = { version = "1.0", features = ["preserve_order"] } serde = { version = "1.0", features = ["derive"] } dirs = "3.0.1" @@ -35,6 +36,11 @@ hex = "0.3.1" blake2 = "0.8.1" sha2 = "0.10.0" +# Backends +zokrates_proof_systems = { version = "0.1", path = "../zokrates_proof_systems", default-features = false } +zokrates_ark = { version = "0.1", path = "../zokrates_ark", default-features = false, optional = true } +zokrates_bellman = { version = "0.1", path = "../zokrates_bellman", default-features = false, optional = true } + [dev-dependencies] glob = "0.2.11" assert_cli = "0.5" diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs index cca7d11e..99a1b083 100644 --- a/zokrates_cli/src/bin.rs +++ b/zokrates_cli/src/bin.rs @@ -49,14 +49,14 @@ fn cli() -> Result<(), String> { universal_setup::subcommand(), #[cfg(feature = "bellman")] mpc::subcommand(), - #[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))] + #[cfg(any(feature = "bellman", feature = "ark"))] setup::subcommand(), export_verifier::subcommand(), - #[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))] + #[cfg(any(feature = "bellman", feature = "ark"))] generate_proof::subcommand(), generate_smtlib2::subcommand(), print_proof::subcommand(), - #[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))] + #[cfg(any(feature = "bellman", feature = "ark"))] verify::subcommand()]) .get_matches(); @@ -69,14 +69,14 @@ fn cli() -> Result<(), String> { ("universal-setup", Some(sub_matches)) => universal_setup::exec(sub_matches), #[cfg(feature = "bellman")] ("mpc", Some(sub_matches)) => mpc::exec(sub_matches), - #[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))] + #[cfg(any(feature = "bellman", feature = "ark"))] ("setup", Some(sub_matches)) => setup::exec(sub_matches), ("export-verifier", Some(sub_matches)) => export_verifier::exec(sub_matches), - #[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))] + #[cfg(any(feature = "bellman", feature = "ark"))] ("generate-proof", Some(sub_matches)) => generate_proof::exec(sub_matches), ("generate-smtlib2", Some(sub_matches)) => generate_smtlib2::exec(sub_matches), ("print-proof", Some(sub_matches)) => print_proof::exec(sub_matches), - #[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))] + #[cfg(any(feature = "bellman", feature = "ark"))] ("verify", Some(sub_matches)) => verify::exec(sub_matches), _ => unreachable!(), } @@ -122,7 +122,6 @@ mod tests { use std::string::String; use typed_arena::Arena; use zokrates_core::compile::{compile, CompilationArtifacts, CompileConfig}; - use zokrates_core::ir; use zokrates_field::Bn128Field; use zokrates_fs_resolver::FileSystemResolver; @@ -217,7 +216,7 @@ mod tests { ) .unwrap(); - let interpreter = ir::Interpreter::default(); + let interpreter = zokrates_interpreter::Interpreter::default(); let _ = interpreter .execute(artifacts.prog(), &[Bn128Field::from(0)]) @@ -257,7 +256,7 @@ mod tests { ) .unwrap(); - let interpreter = ir::Interpreter::default(); + let interpreter = zokrates_interpreter::Interpreter::default(); let res = interpreter.execute(artifacts.prog(), &[Bn128Field::from(0)]); diff --git a/zokrates_cli/src/cli_constants.rs b/zokrates_cli/src/cli_constants.rs index b9c372d1..31e5867f 100644 --- a/zokrates_cli/src/cli_constants.rs +++ b/zokrates_cli/src/cli_constants.rs @@ -21,20 +21,8 @@ lazy_static! { .unwrap(); } -#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))] -pub const BACKENDS: &[&str] = if cfg!(feature = "libsnark") { - if cfg!(feature = "ark") { - if cfg!(feature = "bellman") { - &[BELLMAN, LIBSNARK, ARK] - } else { - &[LIBSNARK, ARK] - } - } else if cfg!(feature = "bellman") { - &[BELLMAN, LIBSNARK] - } else { - &[LIBSNARK] - } -} else if cfg!(feature = "ark") { +#[cfg(any(feature = "bellman", feature = "ark"))] +pub const BACKENDS: &[&str] = if cfg!(feature = "ark") { if cfg!(feature = "bellman") { &[BELLMAN, ARK] } else { @@ -48,10 +36,6 @@ pub const BACKENDS: &[&str] = if cfg!(feature = "libsnark") { pub const CURVES: &[&str] = &[BN128, BLS12_381, BLS12_377, BW6_761]; -pub const SCHEMES: &[&str] = if cfg!(feature = "libsnark") { - &[G16, GM17, PGHR13, MARLIN] -} else { - &[G16, GM17, MARLIN] -}; +pub const SCHEMES: &[&str] = &[G16, GM17, MARLIN]; pub const UNIVERSAL_SCHEMES: &[&str] = &[MARLIN]; diff --git a/zokrates_cli/src/ops/compute_witness.rs b/zokrates_cli/src/ops/compute_witness.rs index cb224bb0..6a29a872 100644 --- a/zokrates_cli/src/ops/compute_witness.rs +++ b/zokrates_cli/src/ops/compute_witness.rs @@ -5,10 +5,11 @@ use std::fs::File; use std::io::{stdin, BufReader, BufWriter, Read}; use std::path::Path; use zokrates_abi::Encode; -use zokrates_core::ir; -use zokrates_core::ir::ProgEnum; -use zokrates_core::typed_absy::abi::Abi; -use zokrates_core::typed_absy::types::{ConcreteSignature, ConcreteType, GTupleType}; +use zokrates_ast::ir::{self, ProgEnum}; +use zokrates_ast::typed::{ + abi::Abi, + types::{ConcreteSignature, ConcreteType, GTupleType}, +}; use zokrates_field::Field; pub fn subcommand() -> App<'static, 'static> { @@ -158,7 +159,7 @@ fn cli_compute>>( } .map_err(|e| format!("Could not parse argument: {}", e))?; - let interpreter = ir::Interpreter::default(); + let interpreter = zokrates_interpreter::Interpreter::default(); let witness = interpreter .execute(ir_prog, &arguments.encode()) diff --git a/zokrates_cli/src/ops/export_verifier.rs b/zokrates_cli/src/ops/export_verifier.rs index bf5a1adb..08b35a44 100644 --- a/zokrates_cli/src/ops/export_verifier.rs +++ b/zokrates_cli/src/ops/export_verifier.rs @@ -5,8 +5,8 @@ use std::fs::File; use std::io::{BufReader, BufWriter, Write}; use std::path::Path; use zokrates_common::helpers::{CurveParameter, SchemeParameter}; -use zokrates_core::proof_system::*; use zokrates_field::Bn128Field; +use zokrates_proof_systems::*; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("export-verifier") @@ -65,10 +65,6 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { (CurveParameter::Bn128, SchemeParameter::GM17) => { cli_export_verifier::(sub_matches, vk) } - #[cfg(feature = "libsnark")] - (CurveParameter::Bn128, SchemeParameter::PGHR13) => { - cli_export_verifier::(sub_matches, vk) - } (CurveParameter::Bn128, SchemeParameter::MARLIN) => { cli_export_verifier::(sub_matches, vk) } diff --git a/zokrates_cli/src/ops/generate_proof.rs b/zokrates_cli/src/ops/generate_proof.rs index 6dba4fef..2a62042a 100644 --- a/zokrates_cli/src/ops/generate_proof.rs +++ b/zokrates_cli/src/ops/generate_proof.rs @@ -4,19 +4,16 @@ use std::convert::TryFrom; use std::fs::File; use std::io::{BufReader, Read, Write}; use std::path::Path; +#[cfg(feature = "ark")] +use zokrates_ark::Ark; +use zokrates_ast::ir::{self, ProgEnum}; +#[cfg(feature = "bellman")] +use zokrates_bellman::Bellman; use zokrates_common::constants; use zokrates_common::helpers::*; -use zokrates_core::ir; -use zokrates_core::ir::ProgEnum; -#[cfg(feature = "ark")] -use zokrates_core::proof_system::ark::Ark; -#[cfg(feature = "bellman")] -use zokrates_core::proof_system::bellman::Bellman; -#[cfg(feature = "libsnark")] -use zokrates_core::proof_system::libsnark::Libsnark; -#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))] -use zokrates_core::proof_system::*; use zokrates_field::Field; +#[cfg(any(feature = "bellman", feature = "ark"))] +use zokrates_proof_systems::*; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("generate-proof") @@ -134,24 +131,6 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { } ProgEnum::Bw6_761Program(p) => cli_generate_proof::<_, _, Marlin, Ark>(p, sub_matches), }, - #[cfg(feature = "libsnark")] - Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::GM17) => { - match prog { - ProgEnum::Bn128Program(p) => { - cli_generate_proof::<_, _, GM17, Libsnark>(p, sub_matches) - } - _ => unreachable!(), - } - } - #[cfg(feature = "libsnark")] - Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::PGHR13) => { - match prog { - ProgEnum::Bn128Program(p) => { - cli_generate_proof::<_, _, PGHR13, Libsnark>(p, sub_matches) - } - _ => unreachable!(), - } - } _ => unreachable!(), } } diff --git a/zokrates_cli/src/ops/generate_smtlib2.rs b/zokrates_cli/src/ops/generate_smtlib2.rs index 127dc6ad..b1bf6f6a 100644 --- a/zokrates_cli/src/ops/generate_smtlib2.rs +++ b/zokrates_cli/src/ops/generate_smtlib2.rs @@ -3,9 +3,7 @@ use clap::{App, Arg, ArgMatches, SubCommand}; use std::fs::File; use std::io::{BufReader, Write}; use std::path::Path; -use zokrates_core::ir; -use zokrates_core::ir::smtlib2::SMTLib2Display; -use zokrates_core::ir::ProgEnum; +use zokrates_ast::ir::{self, smtlib2::SMTLib2Display, ProgEnum}; use zokrates_field::Field; pub fn subcommand() -> App<'static, 'static> { diff --git a/zokrates_cli/src/ops/inspect.rs b/zokrates_cli/src/ops/inspect.rs index 571ba5c3..523d664a 100644 --- a/zokrates_cli/src/ops/inspect.rs +++ b/zokrates_cli/src/ops/inspect.rs @@ -3,8 +3,7 @@ use clap::{App, Arg, ArgMatches, SubCommand}; use std::fs::File; use std::io::{BufReader, BufWriter, Write}; use std::path::{Path, PathBuf}; -use zokrates_core::ir; -use zokrates_core::ir::ProgEnum; +use zokrates_ast::ir::{self, ProgEnum}; use zokrates_field::Field; pub fn subcommand() -> App<'static, 'static> { diff --git a/zokrates_cli/src/ops/mod.rs b/zokrates_cli/src/ops/mod.rs index 2a25ee69..e82dd506 100644 --- a/zokrates_cli/src/ops/mod.rs +++ b/zokrates_cli/src/ops/mod.rs @@ -2,16 +2,16 @@ pub mod check; pub mod compile; pub mod compute_witness; pub mod export_verifier; -#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))] +#[cfg(any(feature = "bellman", feature = "ark"))] pub mod generate_proof; pub mod generate_smtlib2; pub mod inspect; #[cfg(feature = "bellman")] pub mod mpc; pub mod print_proof; -#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))] +#[cfg(any(feature = "bellman", feature = "ark"))] pub mod setup; #[cfg(feature = "ark")] pub mod universal_setup; -#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))] +#[cfg(any(feature = "bellman", feature = "ark"))] pub mod verify; diff --git a/zokrates_cli/src/ops/mpc/beacon.rs b/zokrates_cli/src/ops/mpc/beacon.rs index 0e3e39c8..b5af669e 100644 --- a/zokrates_cli/src/ops/mpc/beacon.rs +++ b/zokrates_cli/src/ops/mpc/beacon.rs @@ -3,10 +3,10 @@ use clap::{App, Arg, ArgMatches, SubCommand}; use std::fs::File; use std::io::{BufReader, BufWriter}; use std::path::Path; +use zokrates_bellman::Bellman; use zokrates_common::constants::{BLS12_381, BN128}; -use zokrates_core::proof_system::bellman::Bellman; -use zokrates_core::proof_system::{MpcBackend, MpcScheme, G16}; use zokrates_field::{BellmanFieldExtensions, Bls12_381Field, Bn128Field, Field}; +use zokrates_proof_systems::{MpcBackend, MpcScheme, G16}; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("beacon") diff --git a/zokrates_cli/src/ops/mpc/contribute.rs b/zokrates_cli/src/ops/mpc/contribute.rs index f5820949..3490f381 100644 --- a/zokrates_cli/src/ops/mpc/contribute.rs +++ b/zokrates_cli/src/ops/mpc/contribute.rs @@ -3,10 +3,10 @@ use clap::{App, Arg, ArgMatches, SubCommand}; use std::fs::File; use std::io::{BufReader, BufWriter}; use std::path::Path; +use zokrates_bellman::Bellman; use zokrates_common::constants::{BLS12_381, BN128}; -use zokrates_core::proof_system::bellman::Bellman; -use zokrates_core::proof_system::{MpcBackend, MpcScheme, G16}; use zokrates_field::{BellmanFieldExtensions, Bls12_381Field, Bn128Field, Field}; +use zokrates_proof_systems::{MpcBackend, MpcScheme, G16}; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("contribute") diff --git a/zokrates_cli/src/ops/mpc/export.rs b/zokrates_cli/src/ops/mpc/export.rs index f81dbf82..cf640fa1 100644 --- a/zokrates_cli/src/ops/mpc/export.rs +++ b/zokrates_cli/src/ops/mpc/export.rs @@ -3,10 +3,10 @@ use clap::{App, Arg, ArgMatches, SubCommand}; use std::fs::File; use std::io::{BufReader, Write}; use std::path::Path; +use zokrates_bellman::Bellman; use zokrates_common::constants::{BLS12_381, BN128}; -use zokrates_core::proof_system::bellman::Bellman; -use zokrates_core::proof_system::{MpcBackend, MpcScheme, TaggedVerificationKey, G16}; use zokrates_field::{BellmanFieldExtensions, Bls12_381Field, Bn128Field, Field}; +use zokrates_proof_systems::{MpcBackend, MpcScheme, TaggedVerificationKey, G16}; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("export") diff --git a/zokrates_cli/src/ops/mpc/init.rs b/zokrates_cli/src/ops/mpc/init.rs index 465b68e0..71136366 100644 --- a/zokrates_cli/src/ops/mpc/init.rs +++ b/zokrates_cli/src/ops/mpc/init.rs @@ -3,11 +3,10 @@ use clap::{App, Arg, ArgMatches, SubCommand}; use std::fs::File; use std::io::{BufReader, BufWriter}; use std::path::Path; -use zokrates_core::ir; -use zokrates_core::ir::ProgEnum; -use zokrates_core::proof_system::bellman::Bellman; -use zokrates_core::proof_system::{MpcBackend, MpcScheme, G16}; +use zokrates_ast::ir::{self, ProgEnum}; +use zokrates_bellman::Bellman; use zokrates_field::{BellmanFieldExtensions, Field}; +use zokrates_proof_systems::{MpcBackend, MpcScheme, G16}; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("init") diff --git a/zokrates_cli/src/ops/mpc/verify.rs b/zokrates_cli/src/ops/mpc/verify.rs index b734991f..6beca03d 100644 --- a/zokrates_cli/src/ops/mpc/verify.rs +++ b/zokrates_cli/src/ops/mpc/verify.rs @@ -3,11 +3,10 @@ use clap::{App, Arg, ArgMatches, SubCommand}; use std::fs::File; use std::io::BufReader; use std::path::Path; -use zokrates_core::ir; -use zokrates_core::ir::ProgEnum; -use zokrates_core::proof_system::bellman::Bellman; -use zokrates_core::proof_system::{MpcBackend, MpcScheme, G16}; +use zokrates_ast::ir::{self, ProgEnum}; +use zokrates_bellman::Bellman; use zokrates_field::{BellmanFieldExtensions, Field}; +use zokrates_proof_systems::{MpcBackend, MpcScheme, G16}; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("verify") diff --git a/zokrates_cli/src/ops/print_proof.rs b/zokrates_cli/src/ops/print_proof.rs index a1f65e05..9c2e54f5 100644 --- a/zokrates_cli/src/ops/print_proof.rs +++ b/zokrates_cli/src/ops/print_proof.rs @@ -5,10 +5,10 @@ use std::fs::File; use std::io::BufReader; use std::path::Path; use zokrates_common::helpers::{CurveParameter, SchemeParameter}; -use zokrates_core::proof_system::{ +use zokrates_field::Bn128Field; +use zokrates_proof_systems::{ Marlin, Proof, SolidityCompatibleField, SolidityCompatibleScheme, G16, GM17, PGHR13, }; -use zokrates_field::Bn128Field; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("print-proof") diff --git a/zokrates_cli/src/ops/setup.rs b/zokrates_cli/src/ops/setup.rs index fb1d6fcc..e9e8a216 100644 --- a/zokrates_cli/src/ops/setup.rs +++ b/zokrates_cli/src/ops/setup.rs @@ -4,19 +4,16 @@ use std::convert::TryFrom; use std::fs::File; use std::io::{BufReader, Write}; use std::path::Path; +#[cfg(feature = "ark")] +use zokrates_ark::Ark; +use zokrates_ast::ir::{self, ProgEnum}; +#[cfg(feature = "bellman")] +use zokrates_bellman::Bellman; use zokrates_common::constants; use zokrates_common::helpers::*; -use zokrates_core::ir; -use zokrates_core::ir::ProgEnum; -#[cfg(feature = "ark")] -use zokrates_core::proof_system::ark::Ark; -#[cfg(feature = "bellman")] -use zokrates_core::proof_system::bellman::Bellman; -#[cfg(feature = "libsnark")] -use zokrates_core::proof_system::libsnark::Libsnark; -#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))] -use zokrates_core::proof_system::*; use zokrates_field::Field; +#[cfg(any(feature = "bellman", feature = "ark"))] +use zokrates_proof_systems::*; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("setup") @@ -165,24 +162,6 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { } } } - #[cfg(feature = "libsnark")] - Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::GM17) => { - match prog { - ProgEnum::Bn128Program(p) => { - cli_setup_non_universal::<_, _, GM17, Libsnark>(p, sub_matches) - } - _ => unreachable!(), - } - } - #[cfg(feature = "libsnark")] - Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::PGHR13) => { - match prog { - ProgEnum::Bn128Program(p) => { - cli_setup_non_universal::<_, _, PGHR13, Libsnark>(p, sub_matches) - } - _ => unreachable!(), - } - } _ => unreachable!(), } } diff --git a/zokrates_cli/src/ops/universal_setup.rs b/zokrates_cli/src/ops/universal_setup.rs index ac1a9b04..98bc8892 100644 --- a/zokrates_cli/src/ops/universal_setup.rs +++ b/zokrates_cli/src/ops/universal_setup.rs @@ -4,13 +4,13 @@ use std::convert::TryFrom; use std::fs::File; use std::io::Write; use std::path::Path; +#[cfg(feature = "ark")] +use zokrates_ark::Ark; use zokrates_common::constants; use zokrates_common::helpers::*; -#[cfg(feature = "ark")] -use zokrates_core::proof_system::ark::Ark; -#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))] -use zokrates_core::proof_system::*; use zokrates_field::{Bls12_377Field, Bls12_381Field, Bn128Field, Bw6_761Field, Field}; +#[cfg(any(feature = "bellman", feature = "ark"))] +use zokrates_proof_systems::*; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("universal-setup") diff --git a/zokrates_cli/src/ops/verify.rs b/zokrates_cli/src/ops/verify.rs index 8f48a79f..24a96c38 100644 --- a/zokrates_cli/src/ops/verify.rs +++ b/zokrates_cli/src/ops/verify.rs @@ -4,17 +4,15 @@ use std::convert::TryFrom; use std::fs::File; use std::io::BufReader; use std::path::Path; +#[cfg(feature = "ark")] +use zokrates_ark::Ark; +#[cfg(feature = "bellman")] +use zokrates_bellman::Bellman; use zokrates_common::constants; use zokrates_common::helpers::*; -#[cfg(feature = "ark")] -use zokrates_core::proof_system::ark::Ark; -#[cfg(feature = "bellman")] -use zokrates_core::proof_system::bellman::Bellman; -#[cfg(feature = "libsnark")] -use zokrates_core::proof_system::libsnark::Libsnark; -#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))] -use zokrates_core::proof_system::*; use zokrates_field::{Bls12_377Field, Bls12_381Field, Bn128Field, Bw6_761Field, Field}; +#[cfg(any(feature = "bellman", feature = "ark"))] +use zokrates_proof_systems::*; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("verify") @@ -170,14 +168,6 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { Parameters(BackendParameter::Ark, CurveParameter::Bw6_761, SchemeParameter::MARLIN) => { cli_verify::(vk, proof) } - #[cfg(feature = "libsnark")] - Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::GM17) => { - cli_verify::(vk, proof) - } - #[cfg(feature = "libsnark")] - Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::PGHR13) => { - cli_verify::(vk, proof) - } _ => unreachable!(), } } diff --git a/zokrates_cli/tests/integration.rs b/zokrates_cli/tests/integration.rs index 7234a886..8408ccc6 100644 --- a/zokrates_cli/tests/integration.rs +++ b/zokrates_cli/tests/integration.rs @@ -19,12 +19,12 @@ mod integration { use std::path::Path; use tempdir::TempDir; use zokrates_abi::{parse_strict, Encode}; - use zokrates_core::proof_system::{ + use zokrates_ast::typed::abi::Abi; + use zokrates_field::Bn128Field; + use zokrates_proof_systems::{ to_token::ToToken, Marlin, Proof, SolidityCompatibleScheme, G16, GM17, PGHR13, SOLIDITY_G2_ADDITION_LIB, }; - use zokrates_core::typed_absy::abi::Abi; - use zokrates_field::Bn128Field; macro_rules! map( { @@ -233,14 +233,6 @@ mod integration { ); } - #[cfg(feature = "libsnark")] - let backends = map! { - "bellman" => vec!["g16"], - "libsnark" => vec!["pghr13"], - "ark" => vec!["g16", "gm17", "marlin"] - }; - - #[cfg(not(feature = "libsnark"))] let backends = map! { "bellman" => vec!["g16"], "ark" => vec!["g16", "gm17", "marlin"] diff --git a/zokrates_common/Cargo.toml b/zokrates_common/Cargo.toml index bb36776b..f9c688b0 100644 --- a/zokrates_common/Cargo.toml +++ b/zokrates_common/Cargo.toml @@ -10,7 +10,6 @@ edition = "2018" default = ["bellman", "ark"] bellman = [] ark = [] -libsnark = [] [dependencies] \ No newline at end of file diff --git a/zokrates_common/src/constants.rs b/zokrates_common/src/constants.rs index 3279ba56..0ef486b0 100644 --- a/zokrates_common/src/constants.rs +++ b/zokrates_common/src/constants.rs @@ -1,6 +1,5 @@ pub const BELLMAN: &str = "bellman"; pub const ARK: &str = "ark"; -pub const LIBSNARK: &str = "libsnark"; pub const BN128: &str = "bn128"; pub const BLS12_381: &str = "bls12_381"; diff --git a/zokrates_common/src/helpers.rs b/zokrates_common/src/helpers.rs index 3bed0a0c..683ce615 100644 --- a/zokrates_common/src/helpers.rs +++ b/zokrates_common/src/helpers.rs @@ -28,8 +28,6 @@ pub enum BackendParameter { Bellman, #[cfg(feature = "ark")] Ark, - #[cfg(feature = "libsnark")] - Libsnark, } impl std::fmt::Display for BackendParameter { @@ -92,8 +90,6 @@ impl TryFrom<&str> for BackendParameter { BELLMAN => Ok(BackendParameter::Bellman), #[cfg(feature = "ark")] ARK => Ok(BackendParameter::Ark), - #[cfg(feature = "libsnark")] - LIBSNARK => Ok(BackendParameter::Libsnark), _ => Err(format!("Unknown backend {}", s)), } } @@ -157,10 +153,6 @@ impl TryFrom<(&str, &str, &str)> for Parameters { (BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::MARLIN) => Ok(()), #[cfg(feature = "ark")] (BackendParameter::Ark, CurveParameter::Bw6_761, SchemeParameter::MARLIN) => Ok(()), - #[cfg(feature = "libsnark")] - (BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::GM17) => Ok(()), - #[cfg(feature = "libsnark")] - (BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::PGHR13) => Ok(()), _ => Err(format!( "Unsupported combination of parameters (backend: {}, curve: {}, proving scheme: {})", s.0, s.1, s.2 diff --git a/zokrates_core/Cargo.toml b/zokrates_core/Cargo.toml index 67176eb2..1f46cecf 100644 --- a/zokrates_core/Cargo.toml +++ b/zokrates_core/Cargo.toml @@ -5,15 +5,11 @@ edition = "2018" authors = ["Jacob Eberhardt ", "Dennis Kuhnert "] repository = "https://github.com/Zokrates/ZoKrates" readme = "README.md" -build = "build.rs" [features] -default = ["bellman", "ark"] -libsnark = ["cc", "cmake"] -bellman = ["bellman_ce", "pairing_ce", "ff_ce", "zokrates_field/bellman"] -wasm = ["bellman_ce/nolog", "bellman_ce/wasm"] -multicore = ["bellman_ce/multicore", "phase2/multicore"] -ark = ["ark-ff", "ark-ec", "ark-bls12-377", "ark-bw6-761", "ark-gm17", "ark-groth16", "ark-crypto-primitives", "ark-serialize", "ark-relations", "ark-marlin", "ark-poly", "ark-poly-commit", "sha3", "digest"] +default = ["ark", "bellman"] +ark = ["zokrates_ast/ark", "zokrates_embed/ark", "zokrates_common/ark", "zokrates_interpreter/ark"] +bellman = ["zokrates_ast/bellman", "zokrates_embed/bellman", "zokrates_common/bellman", "zokrates_interpreter/bellman"] [dependencies] log = "0.4" @@ -26,48 +22,14 @@ reduce = "0.1.1" # serialization and deserialization serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", features = ["preserve_order"] } -serde_cbor = "0.11.2" -hex = "0.4.2" -regex = "0.2" zokrates_field = { version = "0.5.0", path = "../zokrates_field", default-features = false } zokrates_pest_ast = { version = "0.2.0", path = "../zokrates_pest_ast" } -zokrates_common = { path = "../zokrates_common" } -zokrates_embed = { version = "0.1.0", path = "../zokrates_embed" } -getrandom = { version = "0.2", features = ["js", "wasm-bindgen"] } -rand_0_4 = { version = "0.4", package = "rand" } -rand_0_8 = { version = "0.8", package = "rand" } +zokrates_common = { version = "0.1", path = "../zokrates_common", default-features = false } +zokrates_embed = { version = "0.1.0", path = "../zokrates_embed", default-features = false } +zokrates_interpreter = { version = "0.1", path = "../zokrates_interpreter", default-features = false } +zokrates_ast = { version = "0.1", path = "../zokrates_ast", default-features = false } csv = "1" -phase2 = { git = "https://github.com/Zokrates/phase2", default-features = false } - -# bellman -bellman_ce = { version = "^0.3", default-features = false, optional = true } -pairing_ce = { version = "^0.21", optional = true } -ff_ce = { version = "^0.9", optional = true } - -# ark -ark-ff = { version = "^0.3.0", default-features = false, optional = true } -ark-ec = { version = "^0.3.0", default-features = false, optional = true } -ark-bn254 = { version = "^0.3.0", features = ["curve"], default-features = false, optional = true } -ark-bls12-377 = { version = "^0.3.0", features = ["curve"], default-features = false, optional = true } -ark-bw6-761 = { version = "^0.3.0", default-features = false, optional = true } -ark-gm17 = { version = "^0.3.0", default-features = false, optional = true } -ark-groth16 = { version = "^0.3.0", default-features = false, optional = true } -ark-serialize = { version = "^0.3.0", default-features = false, optional = true } -ark-relations = { version = "^0.3.0", default-features = false, optional = true } -ark-marlin = { git = "https://github.com/arkworks-rs/marlin", rev = "63cfd82", default-features = false, optional = true } -ark-poly = { version = "^0.3.0", default-features = false, optional = true } -ark-poly-commit = { version = "^0.3.0", default-features = false, optional = true } -ark-crypto-primitives = { version = "^0.3.0", default-features = false, optional = true } -sha3 = { version = "0.9", optional = true } -digest = { version = "0.9", optional = true } -ethabi = "17.0.0" -primitive-types = { version = "0.11", features = ["rlp"] } [dev-dependencies] -wasm-bindgen-test = "^0.3.0" pretty_assertions = "0.6.1" zokrates_fs_resolver = { version = "0.5", path = "../zokrates_fs_resolver"} - -[build-dependencies] -cc = { version = "1.0", features = ["parallel"], optional = true } -cmake = { version = "=0.1.45", optional = true } diff --git a/zokrates_core/build.rs b/zokrates_core/build.rs deleted file mode 100644 index 7f48be14..00000000 --- a/zokrates_core/build.rs +++ /dev/null @@ -1,97 +0,0 @@ -#[cfg(feature = "libsnark")] -extern crate cc; -#[cfg(feature = "libsnark")] -extern crate cmake; - -fn main() { - #[cfg(feature = "libsnark")] - { - use std::env; - use std::path::PathBuf; - use std::process::Command; - - // fetch libsnark source - const LIBSNARK_URL: &'static str = "https://github.com/scipr-lab/libsnark.git"; - const LIBSNARK_COMMIT: &'static str = "f7c87b88744ecfd008126d415494d9b34c4c1b20"; - - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - let libsnark_source_path = &out_path.join("libsnark"); - - if !libsnark_source_path.exists() { - // Clone the repository - let _ = Command::new("git") - .current_dir(out_path) - .args(&["clone", "--no-checkout", LIBSNARK_URL]) - .status() - .unwrap(); - - // Checkout the specific commit - let _ = Command::new("git") - .current_dir(libsnark_source_path) - .args(&["checkout", "-f", LIBSNARK_COMMIT]) - .status() - .unwrap(); - - // Unencrypted `git://` protocol is no longer supported on GitHub - // so we replace all submodule urls to use `https://` - let gitmodules_path = libsnark_source_path.join(".gitmodules"); - let gitmodules = std::fs::read_to_string(&gitmodules_path) - .unwrap() - .replace("git://", "https://"); - - std::fs::write(&gitmodules_path, gitmodules).unwrap(); - - // Update all submodules recursively - let _ = Command::new("git") - .current_dir(libsnark_source_path) - .args(&["submodule", "update", "--init", "--recursive"]) - .status() - .unwrap(); - } - - // build libsnark - let libsnark = cmake::Config::new(libsnark_source_path) - .define("WITH_SUPERCOP", "OFF") - .define("WITH_PROCPS", "OFF") - .define("WITH_SUPERCOP", "OFF") - .define("CURVE", "ALT_BN128") - .define("USE_PT_COMPRESSION", "OFF") - .define("MONTGOMERY_OUTPUT", "ON") - .define("BINARY_OUTPUT", "ON") - .define("DMULTICORE", "ON") - .build(); - - // build backends - cc::Build::new() - .cpp(true) - .debug(cfg!(debug_assertions)) - .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/ffi.cpp") - .file("lib/gm17.cpp") - .file("lib/pghr13.cpp") - .compile("libsnark_wrapper.a"); - - println!( - "cargo:rustc-link-search=native={}", - libsnark.join("lib").display() - ); - - println!("cargo:rustc-link-lib=gmp"); - println!("cargo:rustc-link-lib=gmpxx"); - - #[cfg(debug_assertions)] - { - println!("cargo:rustc-link-lib=static=snarkd"); - println!("cargo:rustc-link-lib=static=ffd"); - } - #[cfg(not(debug_assertions))] - { - println!("cargo:rustc-link-lib=static=snark"); - println!("cargo:rustc-link-lib=static=ff"); - } - } -} diff --git a/zokrates_core/lib/ffi.cpp b/zokrates_core/lib/ffi.cpp deleted file mode 100644 index a4e0f72a..00000000 --- a/zokrates_core/lib/ffi.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "ffi.hpp" - -void c_free(uint8_t* ptr) -{ - free(ptr); -} \ No newline at end of file diff --git a/zokrates_core/lib/ffi.hpp b/zokrates_core/lib/ffi.hpp deleted file mode 100644 index b1c32ea6..00000000 --- a/zokrates_core/lib/ffi.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct buffer_t { - uint8_t* data; - int32_t length; -}; - -struct setup_result_t { - buffer_t vk; - buffer_t pk; - setup_result_t(buffer_t& vk_buf, buffer_t& pk_buf) - : vk(vk_buf) - , pk(pk_buf) - { - } -}; - -struct proof_result_t { - buffer_t proof; - proof_result_t(buffer_t& proof_buf) - : proof(proof_buf) - { - } -}; - -void c_free(uint8_t* ptr); - -#ifdef __cplusplus -} // extern "C" -#endif \ No newline at end of file diff --git a/zokrates_core/lib/gm17.cpp b/zokrates_core/lib/gm17.cpp deleted file mode 100644 index 12d2540a..00000000 --- a/zokrates_core/lib/gm17.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/** - * @file gm17.cpp - * @author Jacob Eberhardt - * @date 2017 - */ - -#include "gm17.hpp" - -#include -#include -#include - -// contains definition of alt_bn128 ec public parameters -#include "libff/algebra/curves/alt_bn128/alt_bn128_pp.hpp" - -// contains required interfaces and types (keypair, proof, generator, prover, verifier) -#include - -using namespace libsnark; - -#include "util.tcc" - -namespace gm17 { - -template -buffer_t serialize_verification_key(r1cs_se_ppzksnark_verification_key* vk) -{ - const size_t QUERY_COUNT = vk->query.size(); - - const size_t G1_SIZE = Q * sizeof(mp_limb_t) * 2; // [x, y] - const size_t G2_SIZE = Q * sizeof(mp_limb_t) * 4; // [[x0, x1], [y0, y1]] - - const size_t LENGTH = (G1_SIZE * 2) + (G2_SIZE * 3) + (QUERY_COUNT * G1_SIZE); - - // [ ----------------- LENGTH ------------------ ] - // [ h, G_alpha, H_beta, G_gamma, H_gamma, query ] - - buffer_t buffer; - buffer.data = (uint8_t*)malloc(LENGTH); - buffer.length = LENGTH; - - uint8_t* ptr = buffer.data; - serialize_g2_affine(vk->H, ptr); - serialize_g1_affine(vk->G_alpha, ptr); - serialize_g2_affine(vk->H_beta, ptr); - serialize_g1_affine(vk->G_gamma, ptr); - serialize_g2_affine(vk->H_gamma, ptr); - - for (size_t i = 0; i < QUERY_COUNT; ++i) - serialize_g1_affine(vk->query[i], ptr); - - assert(ptr == buffer.data + buffer.length); - return buffer; -} - -template -buffer_t serialize_proof(r1cs_se_ppzksnark_proof* proof) -{ - const size_t G1_SIZE = Q * sizeof(mp_limb_t) * 2; // [x, y] - const size_t G2_SIZE = Q * sizeof(mp_limb_t) * 4; // [[x0, x1], [y0, y1]] - - const size_t LENGTH = (G1_SIZE * 2) + G2_SIZE; - - // [ ---------- LENGTH ---------- ] - // [ G1_SIZE, G2_SIZE, G1_SIZE ] - // [ a, b, c ] - - buffer_t buffer; - buffer.data = (uint8_t*)malloc(LENGTH); - buffer.length = LENGTH; - - uint8_t* ptr = buffer.data; - serialize_g1_affine(proof->A, ptr); - serialize_g2_affine(proof->B, ptr); - serialize_g1_affine(proof->C, ptr); - - assert(ptr == buffer.data + buffer.length); - return buffer; -} - -template -setup_result_t setup(const uint8_t* a, const uint8_t* b, const uint8_t* c, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs) -{ - libff::inhibit_profiling_info = true; - libff::inhibit_profiling_counters = true; - - // initialize curve parameters - ppT::init_public_params(); - - auto cs = create_constraint_system(a, b, c, a_len, b_len, c_len, constraints, variables, inputs); - assert(cs.num_variables() >= (unsigned)inputs); - assert(cs.num_inputs() == (unsigned)inputs); - assert(cs.num_constraints() == (unsigned)constraints); - - r1cs_se_ppzksnark_keypair keypair = r1cs_se_ppzksnark_generator(cs); - - buffer_t vk_buf = serialize_verification_key(&keypair.vk); - buffer_t pk_buf = create_buffer(keypair.pk); - - setup_result_t result(vk_buf, pk_buf); - return result; -} - -template -proof_result_t generate_proof(buffer_t* pk_buf, const uint8_t* public_inputs, int32_t public_inputs_length, const uint8_t* private_inputs, int32_t private_inputs_length) -{ - libff::inhibit_profiling_info = true; - libff::inhibit_profiling_counters = true; - - // initialize curve parameters - ppT::init_public_params(); - - r1cs_se_ppzksnark_proving_key proving_key; - from_buffer>(pk_buf, proving_key); - - r1cs_variable_assignment> full_variable_assignment; - for (int i = 1; i < public_inputs_length; i++) { - full_variable_assignment.push_back(libff::Fr(to_libff_bigint(public_inputs + (i * R * sizeof(mp_limb_t))))); - } - for (int i = 0; i < private_inputs_length; i++) { - full_variable_assignment.push_back(libff::Fr(to_libff_bigint(private_inputs + (i * R * sizeof(mp_limb_t))))); - } - - r1cs_primary_input> primary_input( - full_variable_assignment.begin(), - full_variable_assignment.begin() + public_inputs_length - 1); - - r1cs_primary_input> auxiliary_input( - full_variable_assignment.begin() + public_inputs_length - 1, - full_variable_assignment.end()); - - r1cs_se_ppzksnark_proof proof = r1cs_se_ppzksnark_prover(proving_key, primary_input, auxiliary_input); - buffer_t proof_buf = serialize_proof(&proof); - proof_result_t result(proof_buf); - return result; -} - -template -bool verify(buffer_t* vk_buf, buffer_t* proof_buf, const uint8_t* public_inputs, int32_t public_inputs_length) -{ - libff::inhibit_profiling_info = true; - libff::inhibit_profiling_counters = true; - - // initialize curve parameters - ppT::init_public_params(); - - uint8_t* ptr = vk_buf->data; - const G2 H = deserialize_g2_affine(ptr); - const G1 G_alpha = deserialize_g1_affine(ptr); - const G2 H_beta = deserialize_g2_affine(ptr); - const G1 G_gamma = deserialize_g1_affine(ptr); - const G2 H_gamma = deserialize_g2_affine(ptr); - - libff::G1_vector query_G1_vector; - - const size_t query_count = ((vk_buf->data + vk_buf->length) - ptr) / (Q * sizeof(mp_limb_t) * 2); - for (size_t i = 0; i < query_count; i++) { - auto query = deserialize_g1_affine(ptr); - query_G1_vector.push_back(query); - } - - const r1cs_se_ppzksnark_verification_key vk(H, G_alpha, H_beta, G_gamma, H_gamma, std::move(query_G1_vector)); - - ptr = proof_buf->data; - G1 a = deserialize_g1_affine(ptr); - G2 b = deserialize_g2_affine(ptr); - G1 c = deserialize_g1_affine(ptr); - r1cs_se_ppzksnark_proof proof( - std::move(a), - std::move(b), - std::move(c)); - - r1cs_primary_input> primary_input; - for (int i = 0; i < public_inputs_length; i++) { - primary_input.push_back(libff::Fr(to_libff_bigint(public_inputs + (i * R * sizeof(mp_limb_t))))); - } - - return r1cs_se_ppzksnark_verifier_strong_IC(vk, primary_input, proof); -} -} - -setup_result_t gm17_bn128_setup(const uint8_t* a, const uint8_t* b, const uint8_t* c, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs) -{ - return gm17::setup(a, b, c, a_len, b_len, c_len, constraints, variables, inputs); -} - -proof_result_t gm17_bn128_generate_proof(buffer_t* pk_buf, - const uint8_t* public_inputs, - int32_t public_inputs_length, - const uint8_t* private_inputs, - int32_t private_inputs_length) -{ - return gm17::generate_proof(pk_buf, - public_inputs, - public_inputs_length, - private_inputs, - private_inputs_length); -} - -bool gm17_bn128_verify(buffer_t* vk_buf, buffer_t* proof_buf, const uint8_t* public_inputs, int32_t public_inputs_length) -{ - return gm17::verify(vk_buf, proof_buf, public_inputs, public_inputs_length); -} \ No newline at end of file diff --git a/zokrates_core/lib/gm17.hpp b/zokrates_core/lib/gm17.hpp deleted file mode 100644 index 96e8cf97..00000000 --- a/zokrates_core/lib/gm17.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file gm17.hpp - * @author Jacob Eberhardt - * @date 2017 - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include "ffi.hpp" - -setup_result_t gm17_bn128_setup( - const uint8_t* a, - const uint8_t* b, - const uint8_t* c, - int32_t a_len, - int32_t b_len, - int32_t c_len, - int32_t constraints, - int32_t variables, - int32_t inputs); - -proof_result_t gm17_bn128_generate_proof( - buffer_t* pk_buf, - const uint8_t* public_inputs, - int32_t public_inputs_length, - const uint8_t* private_inputs, - int32_t private_inputs_length); - -bool gm17_bn128_verify( - buffer_t* vk_buf, - buffer_t* proof_buf, - const uint8_t* public_inputs, - int32_t public_inputs_length); - -#ifdef __cplusplus -} // extern "C" -#endif \ No newline at end of file diff --git a/zokrates_core/lib/pghr13.cpp b/zokrates_core/lib/pghr13.cpp deleted file mode 100644 index de222398..00000000 --- a/zokrates_core/lib/pghr13.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/** - * @file pghr13.cpp - * @author Jacob Eberhardt - * @date 2017 - */ - -#include "pghr13.hpp" - -#include -#include -#include - -// contains definition of alt_bn128 ec public parameters -#include "libff/algebra/curves/alt_bn128/alt_bn128_pp.hpp" -// contains required interfaces and types (keypair, proof, generator, prover, verifier) -#include -#include -#include - -using namespace libsnark; - -#include "util.tcc" - -namespace pghr13 { - -template -buffer_t serialize_verification_key(r1cs_ppzksnark_verification_key* vk) -{ - const size_t QUERY_COUNT = vk->encoded_IC_query.rest.indices.size(); - - const size_t G1_SIZE = Q * sizeof(mp_limb_t) * 2; // [x, y] - const size_t G2_SIZE = Q * sizeof(mp_limb_t) * 4; // [[x0, x1], [y0, y1]] - - const size_t LENGTH = (G1_SIZE * 3) + (G2_SIZE * 5) + (QUERY_COUNT * G1_SIZE); - - // [ -------------------- LENGTH --------------------- ] - // [ a, b, c, gamma, gamma_beta_1, gamma_beta_2, z, ic ] - - buffer_t buffer; - buffer.data = (uint8_t*)malloc(LENGTH); - buffer.length = LENGTH; - - uint8_t* ptr = buffer.data; - serialize_g2_affine(vk->alphaA_g2, ptr); - serialize_g1_affine(vk->alphaB_g1, ptr); - serialize_g2_affine(vk->alphaC_g2, ptr); - serialize_g2_affine(vk->gamma_g2, ptr); - serialize_g1_affine(vk->gamma_beta_g1, ptr); - serialize_g2_affine(vk->gamma_beta_g2, ptr); - serialize_g2_affine(vk->rC_Z_g2, ptr); - serialize_g1_affine(vk->encoded_IC_query.first, ptr); - - for (size_t i = 0; i < QUERY_COUNT; ++i) - serialize_g1_affine(vk->encoded_IC_query.rest.values[i], ptr); - - assert(ptr == buffer.data + buffer.length); - return buffer; -} - -template -buffer_t serialize_proof(r1cs_ppzksnark_proof* proof) -{ - const size_t G1_SIZE = Q * sizeof(mp_limb_t) * 2; // [x, y] - const size_t G2_SIZE = Q * sizeof(mp_limb_t) * 4; // [[x0, x1], [y0, y1]] - - const size_t LENGTH = (G1_SIZE * 7) + G2_SIZE; - - // [ ------------- LENGTH -------------- ] - // [ a, a_p, b, b_p, c, c_p, h, k ] - - buffer_t buffer; - buffer.data = (uint8_t*)malloc(LENGTH); - buffer.length = LENGTH; - - uint8_t* ptr = buffer.data; - serialize_g1_affine(proof->g_A.g, ptr); - serialize_g1_affine(proof->g_A.h, ptr); - serialize_g2_affine(proof->g_B.g, ptr); - serialize_g1_affine(proof->g_B.h, ptr); - serialize_g1_affine(proof->g_C.g, ptr); - serialize_g1_affine(proof->g_C.h, ptr); - serialize_g1_affine(proof->g_H, ptr); - serialize_g1_affine(proof->g_K, ptr); - - assert(ptr == buffer.data + buffer.length); - return buffer; -} - -template -setup_result_t setup(const uint8_t* a, const uint8_t* b, const uint8_t* c, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs) -{ - libff::inhibit_profiling_info = true; - libff::inhibit_profiling_counters = true; - - // initialize curve parameters - ppT::init_public_params(); - - auto cs = create_constraint_system(a, b, c, a_len, b_len, c_len, constraints, variables, inputs); - assert(cs.num_variables() >= (unsigned)inputs); - assert(cs.num_inputs() == (unsigned)inputs); - assert(cs.num_constraints() == (unsigned)constraints); - - r1cs_ppzksnark_keypair keypair = r1cs_ppzksnark_generator(cs); - - buffer_t vk_buf = serialize_verification_key(&keypair.vk); - buffer_t pk_buf = create_buffer(keypair.pk); - - setup_result_t result(vk_buf, pk_buf); - return result; -} - -template -proof_result_t generate_proof(buffer_t* pk_buf, const uint8_t* public_inputs, int32_t public_inputs_length, const uint8_t* private_inputs, int32_t private_inputs_length) -{ - libff::inhibit_profiling_info = true; - libff::inhibit_profiling_counters = true; - - // initialize curve parameters - ppT::init_public_params(); - - r1cs_ppzksnark_proving_key proving_key; - from_buffer>(pk_buf, proving_key); - - // assign variables based on witness values, excludes ~one - r1cs_variable_assignment> full_variable_assignment; - for (int i = 1; i < public_inputs_length; i++) { - full_variable_assignment.push_back(libff::Fr(to_libff_bigint(public_inputs + (i * R * sizeof(mp_limb_t))))); - } - for (int i = 0; i < private_inputs_length; i++) { - full_variable_assignment.push_back(libff::Fr(to_libff_bigint(private_inputs + (i * R * sizeof(mp_limb_t))))); - } - - r1cs_primary_input> primary_input( - full_variable_assignment.begin(), - full_variable_assignment.begin() + public_inputs_length - 1); - - r1cs_primary_input> auxiliary_input( - full_variable_assignment.begin() + public_inputs_length - 1, - full_variable_assignment.end()); - - r1cs_ppzksnark_proof proof = r1cs_ppzksnark_prover(proving_key, primary_input, auxiliary_input); - buffer_t proof_buf = serialize_proof(&proof); - proof_result_t result(proof_buf); - return result; -} - -template -bool verify(buffer_t* vk_buf, buffer_t* proof_buf, const uint8_t* public_inputs, int32_t public_inputs_length) -{ - libff::inhibit_profiling_info = true; - libff::inhibit_profiling_counters = true; - - // initialize curve parameters - ppT::init_public_params(); - - uint8_t* ptr = vk_buf->data; - const G2 alphaA_g2 = deserialize_g2_affine(ptr); - const G1 alphaB_g1 = deserialize_g1_affine(ptr); - const G2 alphaC_g2 = deserialize_g2_affine(ptr); - const G2 gamma_g2 = deserialize_g2_affine(ptr); - const G1 gamma_beta_g1 = deserialize_g1_affine(ptr); - const G2 gamma_beta_g2 = deserialize_g2_affine(ptr); - const G2 rC_Z_g2 = deserialize_g2_affine(ptr); - G1 ic_first = deserialize_g1_affine(ptr); - - std::vector ic_rest; - const size_t ic_rest_count = ((vk_buf->data + vk_buf->length) - ptr) / (Q * sizeof(mp_limb_t) * 2); - for (size_t i = 0; i < ic_rest_count; i++) { - auto ic_query = deserialize_g1_affine(ptr); - ic_rest.push_back(ic_query); - } - - accumulation_vector eIC(std::move(ic_first), std::move(ic_rest)); - const r1cs_ppzksnark_verification_key vk(alphaA_g2, alphaB_g1, alphaC_g2, gamma_g2, gamma_beta_g1, gamma_beta_g2, rC_Z_g2, eIC); - - ptr = proof_buf->data; - const G1 g_A_g = deserialize_g1_affine(ptr); - const G1 g_A_h = deserialize_g1_affine(ptr); - const G2 g_B_g = deserialize_g2_affine(ptr); - const G1 g_B_h = deserialize_g1_affine(ptr); - const G1 g_C_g = deserialize_g1_affine(ptr); - const G1 g_C_h = deserialize_g1_affine(ptr); - - knowledge_commitment g_A(g_A_g, g_A_h); - knowledge_commitment g_B(g_B_g, g_B_h); - knowledge_commitment g_C(g_C_g, g_C_h); - - G1 g_H = deserialize_g1_affine(ptr); - G1 g_K = deserialize_g1_affine(ptr); - - const r1cs_ppzksnark_proof proof( - std::move(g_A), - std::move(g_B), - std::move(g_C), - std::move(g_H), - std::move(g_K)); - - r1cs_primary_input> primary_input; - for (int i = 0; i < public_inputs_length; i++) { - primary_input.push_back(libff::Fr(to_libff_bigint(public_inputs + (i * R * sizeof(mp_limb_t))))); - } - return r1cs_ppzksnark_verifier_strong_IC(vk, primary_input, proof); -} -} - -setup_result_t pghr13_bn128_setup(const uint8_t* a, const uint8_t* b, const uint8_t* c, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs) -{ - return pghr13::setup(a, b, c, a_len, b_len, c_len, constraints, variables, inputs); -} - -proof_result_t pghr13_bn128_generate_proof(buffer_t* pk_buf, - const uint8_t* public_inputs, - int32_t public_inputs_length, - const uint8_t* private_inputs, - int32_t private_inputs_length) -{ - return pghr13::generate_proof(pk_buf, - public_inputs, - public_inputs_length, - private_inputs, - private_inputs_length); -} - -bool pghr13_bn128_verify(buffer_t* vk_buf, buffer_t* proof_buf, const uint8_t* public_inputs, int32_t public_inputs_length) -{ - return pghr13::verify(vk_buf, proof_buf, public_inputs, public_inputs_length); -} \ No newline at end of file diff --git a/zokrates_core/lib/pghr13.hpp b/zokrates_core/lib/pghr13.hpp deleted file mode 100644 index 9f88cc56..00000000 --- a/zokrates_core/lib/pghr13.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file pghr13.hpp - * @author Jacob Eberhardt - * @date 2017 - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include "ffi.hpp" - -setup_result_t pghr13_bn128_setup( - const uint8_t* a, - const uint8_t* b, - const uint8_t* c, - int32_t a_len, - int32_t b_len, - int32_t c_len, - int32_t constraints, - int32_t variables, - int32_t inputs); - -proof_result_t pghr13_bn128_generate_proof( - buffer_t* pk_buf, - const uint8_t* public_inputs, - int32_t public_inputs_length, - const uint8_t* private_inputs, - int32_t private_inputs_length); - -bool pghr13_bn128_verify( - buffer_t* vk_buf, - buffer_t* proof_buf, - const uint8_t* public_inputs, - int32_t public_inputs_length); - -#ifdef __cplusplus -} // extern "C" -#endif \ No newline at end of file diff --git a/zokrates_core/lib/util.tcc b/zokrates_core/lib/util.tcc deleted file mode 100644 index 53d11bfd..00000000 --- a/zokrates_core/lib/util.tcc +++ /dev/null @@ -1,187 +0,0 @@ -#pragma once - -#include "ffi.hpp" - -#include -#include -#include -#include -#include - -// conversion byte[N] -> libsnark bigint -template -libff::bigint to_libff_bigint(const uint8_t* input) -{ - libff::bigint x; - for (unsigned i = 0; i < N; i++) { - for (unsigned j = 0; j < 8; j++) { - x.data[N - 1 - i] |= uint64_t(input[i * 8 + j]) << (8 * (7 - j)); - } - } - return x; -} - -// conversion libsnark bigint -> byte[N] -template -void from_libff_bigint(libff::bigint x, uint8_t* out) -{ - for (unsigned i = 0; i < N; i++) { - for (unsigned j = 0; j < 8; j++) { - out[i * 8 + j] = uint8_t(uint64_t(x.data[N - 1 - i]) >> (8 * (7 - j))); - } - } -} - -template -void serialize_g1_affine(G1 point, uint8_t*& buffer) -{ - const size_t ELEMENT_SIZE = Q * sizeof(mp_limb_t); - - G1 aff = point; - aff.to_affine_coordinates(); - - auto x = aff.X.as_bigint(); - auto y = aff.Y.as_bigint(); - - from_libff_bigint(x, buffer); - buffer += ELEMENT_SIZE; - from_libff_bigint(y, buffer); - buffer += ELEMENT_SIZE; -} - -template -void serialize_g2_affine(G2 point, uint8_t*& buffer) -{ - const size_t ELEMENT_SIZE = Q * sizeof(mp_limb_t); - - G2 aff = point; - aff.to_affine_coordinates(); - - auto x0 = aff.X.c0.as_bigint(); - auto x1 = aff.X.c1.as_bigint(); - auto y0 = aff.Y.c0.as_bigint(); - auto y1 = aff.Y.c1.as_bigint(); - - from_libff_bigint(x0, buffer); - buffer += ELEMENT_SIZE; - from_libff_bigint(x1, buffer); - buffer += ELEMENT_SIZE; - from_libff_bigint(y0, buffer); - buffer += ELEMENT_SIZE; - from_libff_bigint(y1, buffer); - buffer += ELEMENT_SIZE; -} - -template -G1 deserialize_g1_affine(uint8_t*& buffer) -{ - const size_t ELEMENT_SIZE = Q * sizeof(mp_limb_t); - - auto x = to_libff_bigint(buffer); - buffer += ELEMENT_SIZE; - auto y = to_libff_bigint(buffer); - buffer += ELEMENT_SIZE; - - return G1(Fq(x), Fq(y), Fq::one()); -} - -template -G2 deserialize_g2_affine(uint8_t*& buffer) -{ - const size_t ELEMENT_SIZE = Q * sizeof(mp_limb_t); - - auto x0 = to_libff_bigint(buffer); - buffer += ELEMENT_SIZE; - auto x1 = to_libff_bigint(buffer); - buffer += ELEMENT_SIZE; - auto y0 = to_libff_bigint(buffer); - buffer += ELEMENT_SIZE; - auto y1 = to_libff_bigint(buffer); - buffer += ELEMENT_SIZE; - - auto x = Fq2(x0, x1); - auto y = Fq2(y0, y1); - return G2(x, y, Fq2::one()); -} - -template