diff --git a/Cargo.lock b/Cargo.lock index e66b612c..b9fb937c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,7 +36,7 @@ dependencies = [ [[package]] name = "ark-bls12-377" version = "0.1.0" -source = "git+https://github.com/arkworks-rs/curves#23e87bf224c23be5c5bccc6084aae31fff8bb83f" +source = "git+https://github.com/arkworks-rs/curves#7f1fcd66967328a1c5a3d12f8b148d69f7d86888" dependencies = [ "ark-ec", "ark-ff", @@ -46,7 +46,7 @@ dependencies = [ [[package]] name = "ark-bn254" version = "0.1.0" -source = "git+https://github.com/arkworks-rs/curves#23e87bf224c23be5c5bccc6084aae31fff8bb83f" +source = "git+https://github.com/arkworks-rs/curves#7f1fcd66967328a1c5a3d12f8b148d69f7d86888" dependencies = [ "ark-ec", "ark-ff", @@ -56,7 +56,7 @@ dependencies = [ [[package]] name = "ark-bw6-761" version = "0.1.0" -source = "git+https://github.com/arkworks-rs/curves#23e87bf224c23be5c5bccc6084aae31fff8bb83f" +source = "git+https://github.com/arkworks-rs/curves#7f1fcd66967328a1c5a3d12f8b148d69f7d86888" dependencies = [ "ark-bls12-377", "ark-ec", @@ -84,7 +84,7 @@ dependencies = [ [[package]] name = "ark-ec" version = "0.1.0" -source = "git+https://github.com/arkworks-rs/algebra#902c8c2882a8aa6f87395df888b50090e2705cac" +source = "git+https://github.com/arkworks-rs/algebra#eac2dd72fd048ea7eac00dabe2ba8bda84287a64" dependencies = [ "ark-ff", "ark-serialize", @@ -92,35 +92,49 @@ dependencies = [ "derivative", "num-traits 0.2.14", "rand 0.7.3", + "zeroize", ] [[package]] name = "ark-ff" version = "0.1.0" -source = "git+https://github.com/arkworks-rs/algebra#902c8c2882a8aa6f87395df888b50090e2705cac" +source = "git+https://github.com/arkworks-rs/algebra#eac2dd72fd048ea7eac00dabe2ba8bda84287a64" dependencies = [ "ark-ff-asm", + "ark-ff-macros", "ark-serialize", "ark-std", "derivative", "num-traits 0.2.14", "rand 0.7.3", "rustc_version", + "zeroize", ] [[package]] name = "ark-ff-asm" version = "0.1.0" -source = "git+https://github.com/arkworks-rs/algebra#902c8c2882a8aa6f87395df888b50090e2705cac" +source = "git+https://github.com/arkworks-rs/algebra#eac2dd72fd048ea7eac00dabe2ba8bda84287a64" dependencies = [ "quote 1.0.7", - "syn 1.0.50", + "syn 1.0.54", +] + +[[package]] +name = "ark-ff-macros" +version = "0.1.0" +source = "git+https://github.com/arkworks-rs/algebra#eac2dd72fd048ea7eac00dabe2ba8bda84287a64" +dependencies = [ + "num-bigint 0.3.1", + "num-traits 0.2.14", + "quote 1.0.7", + "syn 1.0.54", ] [[package]] name = "ark-gm17" version = "0.1.0" -source = "git+https://github.com/arkworks-rs/gm17#4382f9103a18c50cc84dc673740286a7604a2ae5" +source = "git+https://github.com/arkworks-rs/gm17#f74debdb0557af2a873c8261970617e6aad7211d" dependencies = [ "ark-crypto-primitives", "ark-ec", @@ -136,7 +150,7 @@ dependencies = [ [[package]] name = "ark-poly" version = "0.1.0" -source = "git+https://github.com/arkworks-rs/algebra#902c8c2882a8aa6f87395df888b50090e2705cac" +source = "git+https://github.com/arkworks-rs/algebra#eac2dd72fd048ea7eac00dabe2ba8bda84287a64" dependencies = [ "ark-ff", "ark-serialize", @@ -148,7 +162,7 @@ dependencies = [ [[package]] name = "ark-relations" version = "0.1.0" -source = "git+https://github.com/arkworks-rs/snark#f074e77ab35489da12f2f6cb97d24b7d992b8a35" +source = "git+https://github.com/arkworks-rs/snark#0648c547e4f9fda46a40ad0a4896652b87c2316b" dependencies = [ "ark-ff", "ark-std", @@ -158,7 +172,7 @@ dependencies = [ [[package]] name = "ark-serialize" version = "0.1.0" -source = "git+https://github.com/arkworks-rs/algebra#902c8c2882a8aa6f87395df888b50090e2705cac" +source = "git+https://github.com/arkworks-rs/algebra#eac2dd72fd048ea7eac00dabe2ba8bda84287a64" dependencies = [ "ark-serialize-derive", "ark-std", @@ -167,17 +181,17 @@ dependencies = [ [[package]] name = "ark-serialize-derive" version = "0.1.1-alpha.0" -source = "git+https://github.com/arkworks-rs/algebra#902c8c2882a8aa6f87395df888b50090e2705cac" +source = "git+https://github.com/arkworks-rs/algebra#eac2dd72fd048ea7eac00dabe2ba8bda84287a64" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.50", + "syn 1.0.54", ] [[package]] name = "ark-snark" version = "0.1.0" -source = "git+https://github.com/arkworks-rs/snark#f074e77ab35489da12f2f6cb97d24b7d992b8a35" +source = "git+https://github.com/arkworks-rs/snark#0648c547e4f9fda46a40ad0a4896652b87c2316b" dependencies = [ "ark-ff", "ark-relations", @@ -188,7 +202,7 @@ dependencies = [ [[package]] name = "ark-std" version = "0.1.0" -source = "git+https://github.com/arkworks-rs/utils#0825eeafe7a3fb54be5ca9b90b02b6057adca964" +source = "git+https://github.com/arkworks-rs/utils#f6974ac72f59339b7ab798a728a84c5a7b8bac45" [[package]] name = "arrayref" @@ -249,9 +263,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.12.3" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bellman_ce" @@ -272,8 +286,8 @@ dependencies = [ [[package]] name = "bench-utils" -version = "0.1.1-alpha.0" -source = "git+https://github.com/arkworks-rs/utils#0825eeafe7a3fb54be5ca9b90b02b6057adca964" +version = "0.1.0" +source = "git+https://github.com/arkworks-rs/utils#f6974ac72f59339b7ab798a728a84c5a7b8bac45" [[package]] name = "bincode" @@ -288,9 +302,9 @@ dependencies = [ [[package]] name = "bit-vec" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0dc55f2d8a1a85650ac47858bb001b4c0dd73d79e3c455a842925e68d29cd3" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitflags" @@ -368,9 +382,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytecount" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39a773ba75db12126d8d383f1bdbf7eb92ea47ec27dd0557aff1fedf172764c" +checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e" [[package]] name = "byteorder" @@ -392,9 +406,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.65" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95752358c8f7552394baf48cd82695b345628ad3f170d607de3ca03b8dacca15" +checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" dependencies = [ "jobserver", ] @@ -473,7 +487,7 @@ dependencies = [ "crossbeam-deque", "crossbeam-epoch", "crossbeam-queue", - "crossbeam-utils", + "crossbeam-utils 0.7.2", ] [[package]] @@ -482,7 +496,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" dependencies = [ - "crossbeam-utils", + "crossbeam-utils 0.7.2", "maybe-uninit", ] @@ -493,7 +507,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" dependencies = [ "crossbeam-epoch", - "crossbeam-utils", + "crossbeam-utils 0.7.2", "maybe-uninit", ] @@ -505,7 +519,7 @@ checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ "autocfg", "cfg-if 0.1.10", - "crossbeam-utils", + "crossbeam-utils 0.7.2", "lazy_static", "maybe-uninit", "memoffset", @@ -519,7 +533,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" dependencies = [ "cfg-if 0.1.10", - "crossbeam-utils", + "crossbeam-utils 0.7.2", "maybe-uninit", ] @@ -534,6 +548,17 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crossbeam-utils" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" +dependencies = [ + "autocfg", + "cfg-if 1.0.0", + "lazy_static", +] + [[package]] name = "crypto-mac" version = "0.7.0" @@ -546,9 +571,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4666154fd004af3fd6f1da2e81a96fd5a81927fe8ddb6ecc79e2aa6e138b54" +checksum = "f9d58633299b24b515ac72a3f869f8b91306a3cec616a602843a383acd6f9e97" dependencies = [ "bstr", "csv-core", @@ -573,7 +598,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484" dependencies = [ "quote 1.0.7", - "syn 1.0.50", + "syn 1.0.54", ] [[package]] @@ -584,7 +609,7 @@ checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.50", + "syn 1.0.54", ] [[package]] @@ -676,7 +701,7 @@ checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.50", + "syn 1.0.54", "synstructure", ] @@ -715,12 +740,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50c052fa6d4c2f12305ec364bfb8ef884836f3f61ea015b202372ff996d1ac4b" dependencies = [ - "num-bigint", + "num-bigint 0.2.6", "num-integer", "num-traits 0.2.14", "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.50", + "syn 1.0.54", ] [[package]] @@ -941,9 +966,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.45" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" +checksum = "cf3d7383929f7c9c7c2d0fa596f325832df98c3704f2c60553080f7127a58175" dependencies = [ "wasm-bindgen", ] @@ -956,9 +981,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" +checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" [[package]] name = "libgit2-sys" @@ -1075,6 +1100,17 @@ dependencies = [ "serde", ] +[[package]] +name = "num-bigint" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e9a41747ae4633fce5adffb4d2e81ffc5e89593cb19917f8fb2cc5ff76507bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits 0.2.14", +] + [[package]] name = "num-integer" version = "0.1.44" @@ -1150,9 +1186,9 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-sys" -version = "0.9.58" +version = "0.9.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de" +checksum = "de52d8eabd217311538a39bba130d7dea1f1e118010fee7a033d966845e7d5fe" dependencies = [ "autocfg", "cc", @@ -1229,7 +1265,7 @@ dependencies = [ "pest_meta", "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.50", + "syn 1.0.54", ] [[package]] @@ -1260,14 +1296,14 @@ checksum = "f8e8d2bf0b23038a4424865103a4df472855692821aab4e4f5c3312d461d9e5f" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.50", + "syn 1.0.54", ] [[package]] name = "pin-project-lite" -version = "0.1.11" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" +checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c" [[package]] name = "pin-utils" @@ -1487,14 +1523,14 @@ dependencies = [ [[package]] name = "rust-argon2" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dab61250775933275e84053ac235621dfb739556d5c54a2f2e9313b7cf43a19" +checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" dependencies = [ "base64", "blake2b_simd", "constant_time_eq", - "crossbeam-utils", + "crossbeam-utils 0.8.1", ] [[package]] @@ -1575,29 +1611,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.117" +version = "1.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a" +checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.117" +version = "1.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e" +checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.50", + "syn 1.0.54", ] [[package]] name = "serde_json" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95" +checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779" dependencies = [ "itoa", "ryu", @@ -1683,9 +1719,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.50" +version = "1.0.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443b4178719c5a851e1bde36ce12da21d74a0e60b4d982ec3385a933c812f0f6" +checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", @@ -1700,7 +1736,7 @@ checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.50", + "syn 1.0.54", "unicode-xid 0.2.1", ] @@ -1763,11 +1799,11 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tracing" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27" +checksum = "9f47026cdc4080c07e49b37087de021820269d996f581aac150ef9e5583eefe3" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "pin-project-lite", "tracing-core", ] @@ -1858,9 +1894,9 @@ checksum = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" [[package]] name = "vcpkg" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" +checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" [[package]] name = "vec_map" @@ -1899,36 +1935,36 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasm-bindgen" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" +checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" +checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62" dependencies = [ "bumpalo", "lazy_static", "log", "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.50", + "syn 1.0.54", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.18" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da" +checksum = "1fe9756085a84584ee9457a002b7cdfe0bfff169f45d2591d8be1345a6780e35" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -1936,9 +1972,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" +checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084" dependencies = [ "quote 1.0.7", "wasm-bindgen-macro-support", @@ -1946,28 +1982,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" +checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.50", + "syn 1.0.54", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" +checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158" [[package]] name = "wasm-bindgen-test" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34d1cdc8b98a557f24733d50a1199c4b0635e465eecba9c45b214544da197f64" +checksum = "0355fa0c1f9b792a09b6dcb6a8be24d51e71e6d74972f9eb4a44c4c004d24a25" dependencies = [ "console_error_panic_hook", "js-sys", @@ -1979,9 +2015,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8fb9c67be7439ee8ab1b7db502a49c05e51e2835b66796c705134d9b8e1a585" +checksum = "27e07b46b98024c2ba2f9e83a10c2ef0515f057f2da299c1762a2017de80438b" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", @@ -1989,9 +2025,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.45" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d" +checksum = "222b1ef9334f92a21d3fb53dc3fd80f30836959a90f9274a626d7e06315ba3c3" dependencies = [ "js-sys", "wasm-bindgen", @@ -2028,6 +2064,27 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "zeroize" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81a974bcdd357f0dca4d41677db03436324d45a4c9ed2d0b873a5a360ce41c36" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.7", + "syn 1.0.54", + "synstructure", +] + [[package]] name = "zokrates_abi" version = "0.1.3" @@ -2087,7 +2144,7 @@ dependencies = [ "hex", "lazy_static", "num", - "num-bigint", + "num-bigint 0.2.6", "pairing_ce", "pretty_assertions", "rand 0.4.6", @@ -2123,7 +2180,7 @@ dependencies = [ "bellman_ce", "bincode", "lazy_static", - "num-bigint", + "num-bigint 0.2.6", "num-integer", "num-traits 0.2.14", "rand 0.4.6", diff --git a/zokrates_core/src/flatten/mod.rs b/zokrates_core/src/flatten/mod.rs index 03be4800..e240a826 100644 --- a/zokrates_core/src/flatten/mod.rs +++ b/zokrates_core/src/flatten/mod.rs @@ -2144,17 +2144,14 @@ impl<'ast, T: Field> Flattener<'ast, T> { } } - /// Checks if the given name is a not used variable and returns a fresh variable. + /// Returns a fresh FlatVariable for a given Variable /// # Arguments /// /// * `variable` - a variable in the program being flattened fn use_variable(&mut self, variable: &Variable<'ast>) -> FlatVariable { let var = self.issue_new_variable(); - assert!(self - .layout - .insert(variable.id.clone(), var.clone()) - .is_none()); + self.layout.insert(variable.id.clone(), var.clone()); var } @@ -2632,16 +2629,4 @@ mod tests { ] ); } - - #[test] - #[should_panic] - fn next_variable() { - let mut flattener: Flattener = Flattener::new(); - assert_eq!( - FlatVariable::new(0), - flattener.use_variable(&Variable::field_element("a")) - ); - // using the same variable a second time should panic - flattener.use_variable(&Variable::field_element("a")); - } } diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index f13d7cfc..51720451 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -973,22 +973,9 @@ impl<'ast> Checker<'ast> { return Err(errors.into_iter().map(|e| e.unwrap_err()).collect()); } - // constrain assignees to being identifiers - let (variables, errors): (Vec<_>, Vec<_>) = assignees.into_iter().map(|a| match a.unwrap() { - TypedAssignee::Identifier(v) => Ok(v), - a => Err(ErrorInner { - pos: Some(pos), - message: format!("Only assignment to identifiers is supported, found {}", a) - }) - }).partition(|r| r.is_ok()); + let assignees: Vec<_> = assignees.into_iter().map(|a| a.unwrap()).collect(); - if errors.len() > 0 { - return Err(errors.into_iter().map(|e| e.unwrap_err()).collect()); - } - - let variables: Vec<_> = variables.into_iter().map(|v| v.unwrap()).collect(); - - let vars_types = variables.iter().map(|a| Some(a.get_type().clone())).collect(); + let assignee_types = assignees.iter().map(|a| Some(a.get_type().clone())).collect(); // find argument types let mut arguments_checked = vec![]; @@ -1000,7 +987,7 @@ impl<'ast> Checker<'ast> { let arguments_types = arguments_checked.iter().map(|a| a.get_type()).collect(); - let query = FunctionQuery::new(&fun_id, &arguments_types, &vars_types); + let query = FunctionQuery::new(&fun_id, &arguments_types, &assignee_types); let f = self.find_function(&query); @@ -1010,7 +997,7 @@ impl<'ast> Checker<'ast> { let call = TypedExpressionList::FunctionCall(f.clone(), arguments_checked, f.signature.outputs.clone()); - Ok(TypedStatement::MultipleDefinition(variables, call)) + Ok(TypedStatement::MultipleDefinition(assignees, call)) }, None => Err(ErrorInner { pos: Some(pos), message: format!("Function definition for function {} with signature {} not found.", fun_id, query) }), @@ -3617,14 +3604,14 @@ mod tests { } #[test] - fn assign_to_non_variable() { + fn assign_to_select() { // def foo() -> field: // return 1 // def main(): // field[1] a = [0] // a[0] = foo() // return - // should fail + // should succeed let foo_statements: Vec = vec![Statement::Return( ExpressionList { @@ -3711,16 +3698,7 @@ mod tests { State::::new(vec![("main".into(), module)].into_iter().collect()); let mut checker = new_with_args(HashSet::new(), 0, HashSet::new()); - assert_eq!( - checker.check_module(&"main".into(), &mut state), - Err(vec![Error { - inner: ErrorInner { - pos: Some((Position::mock(), Position::mock())), - message: "Only assignment to identifiers is supported, found a[0]".into() - }, - module_id: "main".into() - }]) - ); + assert!(checker.check_module(&"main".into(), &mut state).is_ok()); } #[test] @@ -3848,8 +3826,8 @@ mod tests { TypedStatement::Declaration(typed_absy::Variable::field_element("b")), TypedStatement::MultipleDefinition( vec![ - typed_absy::Variable::field_element("a"), - typed_absy::Variable::field_element("b"), + typed_absy::Variable::field_element("a").into(), + typed_absy::Variable::field_element("b").into(), ], TypedExpressionList::FunctionCall( FunctionKey::with_id("foo").signature( diff --git a/zokrates_core/src/static_analysis/flatten_complex_types.rs b/zokrates_core/src/static_analysis/flatten_complex_types.rs index d89ed43a..708bd68d 100644 --- a/zokrates_core/src/static_analysis/flatten_complex_types.rs +++ b/zokrates_core/src/static_analysis/flatten_complex_types.rs @@ -100,7 +100,47 @@ impl<'ast, T: Field> Flattener { ) -> Vec> { match a { typed_absy::TypedAssignee::Identifier(v) => self.fold_variable(v), - _ => unreachable!(), + typed_absy::TypedAssignee::Select(box a, box i) => { + use typed_absy::Typed; + let count = match a.get_type() { + typed_absy::Type::Array(array_ty) => array_ty.ty.get_primitive_count(), + _ => unreachable!(), + }; + let a = self.fold_assignee(a); + + match i { + typed_absy::FieldElementExpression::Number(n) => { + let index = n.to_dec_string().parse::().unwrap(); + a[index * count..(index + 1) * count].to_vec() + } + i => unreachable!("index {} not allowed, should be a constant", i), + } + } + typed_absy::TypedAssignee::Member(box a, m) => { + use typed_absy::Typed; + + let (offset, size) = match a.get_type() { + typed_absy::Type::Struct(struct_type) => { + struct_type + .members + .iter() + .fold((0, None), |(offset, size), member| match size { + Some(_) => (offset, size), + None => match m == member.id { + true => (offset, Some(member.ty.get_primitive_count())), + false => (offset + member.ty.get_primitive_count(), None), + }, + }) + } + _ => unreachable!(), + }; + + let size = size.unwrap(); + + let a = self.fold_assignee(a); + + a[offset..offset + size].to_vec() + } } } @@ -257,7 +297,7 @@ pub fn fold_statement<'ast, T: Field>( vec![zir::ZirStatement::MultipleDefinition( variables .into_iter() - .flat_map(|v| f.fold_variable(v)) + .flat_map(|v| f.fold_assignee(v)) .collect(), f.fold_expression_list(elist), )] diff --git a/zokrates_core/src/static_analysis/inline.rs b/zokrates_core/src/static_analysis/inline.rs index 104b0109..889f4646 100644 --- a/zokrates_core/src/static_analysis/inline.rs +++ b/zokrates_core/src/static_analysis/inline.rs @@ -290,24 +290,22 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { // add extra statements before the modified statement fn fold_statement(&mut self, s: TypedStatement<'ast, T>) -> Vec> { let folded = match s { - TypedStatement::MultipleDefinition(variables, elist) => match elist { + TypedStatement::MultipleDefinition(assignees, elist) => match elist { TypedExpressionList::FunctionCall(key, exps, types) => { - let variables: Vec<_> = variables + let assignees: Vec<_> = assignees .into_iter() - .map(|a| self.fold_variable(a)) + .map(|a| self.fold_assignee(a)) .collect(); let exps: Vec<_> = exps.into_iter().map(|e| self.fold_expression(e)).collect(); match self.try_inline_call(&key, exps) { - Ok(ret) => variables + Ok(ret) => assignees .into_iter() .zip(ret.into_iter()) - .map(|(v, e)| { - TypedStatement::Definition(TypedAssignee::Identifier(v), e) - }) + .map(|(a, e)| TypedStatement::Definition(a, e)) .collect(), Err((key, expressions)) => vec![TypedStatement::MultipleDefinition( - variables, + assignees, TypedExpressionList::FunctionCall(key, expressions, types), )], } @@ -356,7 +354,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { }; self.statement_buffer .push(TypedStatement::MultipleDefinition( - vec![Variable::with_id_and_type(id.clone(), tys[0].clone())], + vec![Variable::with_id_and_type(id.clone(), tys[0].clone()).into()], TypedExpressionList::FunctionCall( key.clone(), expressions.clone(), @@ -410,7 +408,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { }; self.statement_buffer .push(TypedStatement::MultipleDefinition( - vec![Variable::with_id_and_type(id.clone(), tys[0].clone())], + vec![Variable::with_id_and_type(id.clone(), tys[0].clone()).into()], TypedExpressionList::FunctionCall( key.clone(), expressions.clone(), @@ -466,7 +464,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { }; self.statement_buffer .push(TypedStatement::MultipleDefinition( - vec![Variable::with_id_and_type(id.clone(), tys[0].clone())], + vec![Variable::with_id_and_type(id.clone(), tys[0].clone()).into()], TypedExpressionList::FunctionCall( embed_key.clone(), expressions.clone(), @@ -523,7 +521,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { }; self.statement_buffer .push(TypedStatement::MultipleDefinition( - vec![Variable::with_id_and_type(id.clone(), tys[0].clone())], + vec![Variable::with_id_and_type(id.clone(), tys[0].clone()).into()], TypedExpressionList::FunctionCall( key.clone(), expressions.clone(), @@ -577,7 +575,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { }; self.statement_buffer .push(TypedStatement::MultipleDefinition( - vec![Variable::with_id_and_type(id.clone(), tys[0].clone())], + vec![Variable::with_id_and_type(id.clone(), tys[0].clone()).into()], TypedExpressionList::FunctionCall( embed_key.clone(), expressions.clone(), @@ -1259,7 +1257,7 @@ mod tests { arguments: vec![], statements: vec![ TypedStatement::MultipleDefinition( - vec![Variable::field_element("a")], + vec![Variable::field_element("a").into()], TypedExpressionList::FunctionCall( FunctionKey::with_id("foo").signature( Signature::new().outputs(vec![Type::FieldElement]), @@ -1368,7 +1366,7 @@ mod tests { arguments: vec![], statements: vec![ TypedStatement::MultipleDefinition( - vec![Variable::field_element("a")], + vec![Variable::field_element("a").into()], TypedExpressionList::FunctionCall( FunctionKey::with_id("foo").signature( Signature::new().outputs(vec![Type::FieldElement]), diff --git a/zokrates_core/src/static_analysis/mod.rs b/zokrates_core/src/static_analysis/mod.rs index d7f25b6f..1f245890 100644 --- a/zokrates_core/src/static_analysis/mod.rs +++ b/zokrates_core/src/static_analysis/mod.rs @@ -14,7 +14,8 @@ mod return_binder; mod uint_optimizer; mod unconstrained_vars; mod unroll; -mod variable_access_remover; +mod variable_read_remover; +mod variable_write_remover; use self::flatten_complex_types::Flattener; use self::inline::Inliner; @@ -24,7 +25,8 @@ use self::redefinition::RedefinitionOptimizer; use self::return_binder::ReturnBinder; use self::uint_optimizer::UintOptimizer; use self::unconstrained_vars::UnconstrainedVariableDetector; -use self::variable_access_remover::VariableAccessRemover; +use self::variable_read_remover::VariableReadRemover; +use self::variable_write_remover::VariableWriteRemover; use crate::flat_absy::FlatProg; use crate::ir::Prog; use crate::typed_absy::TypedProgram; @@ -52,8 +54,11 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { // optimize redefinitions let r = RedefinitionOptimizer::optimize(r); + // remove assignment to variable index + let r = VariableWriteRemover::apply(r); + // remove variable access to complex types - let r = VariableAccessRemover::apply(r); + let r = VariableReadRemover::apply(r); // convert to zir, removing complex types let zir = Flattener::flatten(r); diff --git a/zokrates_core/src/static_analysis/propagation.rs b/zokrates_core/src/static_analysis/propagation.rs index 71c8b8b8..2f2993ce 100644 --- a/zokrates_core/src/static_analysis/propagation.rs +++ b/zokrates_core/src/static_analysis/propagation.rs @@ -20,7 +20,7 @@ use zokrates_field::Field; pub struct Propagator<'ast, T: Field> { // constants keeps track of constant expressions // we currently do not support partially constant expressions: `field [x, 1][1]` is not considered constant, `field [0, 1][1]` is - constants: HashMap, TypedExpression<'ast, T>>, + constants: HashMap, TypedExpression<'ast, T>>, // the verbose mode doesn't remove statements which assign constants to variables // it's required when using propagation in combination with unrolling verbose: bool, @@ -48,6 +48,63 @@ impl<'ast, T: Field> Propagator<'ast, T> { pub fn propagate_verbose(p: TypedProgram<'ast, T>) -> TypedProgram<'ast, T> { Propagator::verbose().fold_program(p) } + + // get a mutable reference to the constant corresponding to a given assignee if any, otherwise + // return the identifier at the root of this assignee + fn try_get_constant_mut<'a>( + &mut self, + assignee: &'a TypedAssignee<'ast, T>, + ) -> Result<(&'a Variable<'ast>, &mut TypedExpression<'ast, T>), &'a Variable<'ast>> { + match assignee { + TypedAssignee::Identifier(var) => self + .constants + .get_mut(&var.id) + .map(|c| Ok((var, c))) + .unwrap_or(Err(var)), + TypedAssignee::Select(box assignee, box index) => { + match self.try_get_constant_mut(&assignee) { + Ok((v, c)) => match index { + FieldElementExpression::Number(n) => { + let n = n.to_dec_string().parse::().unwrap(); + + match c { + TypedExpression::Array(a) => match a.as_inner_mut() { + ArrayExpressionInner::Value(value) => Ok((v, &mut value[n])), + _ => unreachable!(), + }, + _ => unreachable!(), + } + } + _ => Err(v), + }, + e => e, + } + } + TypedAssignee::Member(box assignee, m) => match self.try_get_constant_mut(&assignee) { + Ok((v, c)) => { + let ty = assignee.get_type(); + + let index = match ty { + Type::Struct(struct_ty) => struct_ty + .members + .iter() + .position(|member| *m == member.id) + .unwrap(), + _ => unreachable!(), + }; + + match c { + TypedExpression::Struct(a) => match a.as_inner_mut() { + StructExpressionInner::Value(value) => Ok((v, &mut value[index])), + _ => unreachable!(), + }, + _ => unreachable!(), + } + } + e => e, + }, + } + } } fn is_constant<'ast, T: Field>(e: &TypedExpression<'ast, T>) -> bool { @@ -78,44 +135,81 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { fn fold_statement(&mut self, s: TypedStatement<'ast, T>) -> Vec> { let res = match s { - TypedStatement::Declaration(v) => Some(TypedStatement::Declaration(v)), - TypedStatement::Return(expressions) => Some(TypedStatement::Return( + TypedStatement::Declaration(v) => vec![TypedStatement::Declaration(v)], + TypedStatement::Return(expressions) => vec![TypedStatement::Return( expressions .into_iter() .map(|e| self.fold_expression(e)) .collect(), - )), + )], // propagation to the defined variable if rhs is a constant - TypedStatement::Definition(TypedAssignee::Identifier(var), expr) => { + TypedStatement::Definition(assignee, expr) => { let expr = self.fold_expression(expr); + let assignee = self.fold_assignee(assignee); if is_constant(&expr) { - self.constants - .insert(TypedAssignee::Identifier(var.clone()), expr.clone()); - match self.verbose { - true => Some(TypedStatement::Definition( - TypedAssignee::Identifier(var), - expr, - )), - false => None, + let verbose = self.verbose; + + match assignee { + TypedAssignee::Identifier(var) => match verbose { + true => { + assert!(self + .constants + .insert(var.id.clone(), expr.clone()) + .is_none()); + vec![TypedStatement::Definition( + TypedAssignee::Identifier(var), + expr, + )] + } + false => { + assert!(self.constants.insert(var.id, expr).is_none()); + + vec![] + } + }, + assignee => match self.try_get_constant_mut(&assignee) { + Ok((_, c)) => match verbose { + true => { + *c = expr.clone(); + vec![TypedStatement::Definition(assignee, expr)] + } + false => { + *c = expr; + vec![] + } + }, + Err(v) => match self.constants.remove(&v.id) { + // invalidate the cache for this identifier, and define the latest + // version of the constant in the program, if any + Some(c) => vec![ + TypedStatement::Definition(v.clone().into(), c), + TypedStatement::Definition(assignee, expr), + ], + None => vec![TypedStatement::Definition(assignee, expr)], + }, + }, } } else { - Some(TypedStatement::Definition( - TypedAssignee::Identifier(var), - expr, - )) + // the expression being assigned is not constant, invalidate the cache + let v = self + .try_get_constant_mut(&assignee) + .map(|(v, _)| v) + .unwrap_or_else(|v| v); + + match self.constants.remove(&v.id) { + Some(c) => vec![ + TypedStatement::Definition(v.clone().into(), c), + TypedStatement::Definition(assignee, expr), + ], + None => vec![TypedStatement::Definition(assignee, expr)], + } } } - TypedStatement::Definition(TypedAssignee::Select(..), _) => { - unreachable!("array updates should have been replaced with full array redef") - } - TypedStatement::Definition(TypedAssignee::Member(..), _) => { - unreachable!("struct update should have been replaced with full struct redef") - } // propagate the boolean TypedStatement::Assertion(e) => { // could stop execution here if condition is known to fail - Some(TypedStatement::Assertion(self.fold_boolean_expression(e))) + vec![TypedStatement::Assertion(self.fold_boolean_expression(e))] } // only loops with variable bounds are expected here // we stop propagation here as constants maybe be modified inside the loop body @@ -127,10 +221,15 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { // invalidate the constants map as any constant could be modified inside the loop body, which we don't visit self.constants.clear(); - Some(TypedStatement::For(v, from, to, statements)) + vec![TypedStatement::For(v, from, to, statements)] } - TypedStatement::MultipleDefinition(variables, expression_list) => { + TypedStatement::MultipleDefinition(assignees, expression_list) => { + let assignees: Vec> = assignees + .into_iter() + .map(|a| self.fold_assignee(a)) + .collect(); let expression_list = self.fold_expression_list(expression_list); + match expression_list { TypedExpressionList::FunctionCall(key, arguments, types) => { let arguments: Vec<_> = arguments @@ -139,7 +238,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { .collect(); fn process_u_from_bits<'ast, T: Field>( - variables: Vec>, + variables: Vec>, arguments: Vec>, bitwidth: UBitwidth, ) -> TypedExpression<'ast, T> { @@ -183,7 +282,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { } fn process_u_to_bits<'ast, T: Field>( - variables: Vec>, + variables: Vec>, arguments: Vec>, bitwidth: UBitwidth, ) -> TypedExpression<'ast, T> { @@ -224,37 +323,37 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { true => { let r: Option> = match key.id { "_U32_FROM_BITS" => Some(process_u_from_bits( - variables.clone(), + assignees.clone(), arguments.clone(), UBitwidth::B32, )), "_U16_FROM_BITS" => Some(process_u_from_bits( - variables.clone(), + assignees.clone(), arguments.clone(), UBitwidth::B16, )), "_U8_FROM_BITS" => Some(process_u_from_bits( - variables.clone(), + assignees.clone(), arguments.clone(), UBitwidth::B8, )), "_U32_TO_BITS" => Some(process_u_to_bits( - variables.clone(), + assignees.clone(), arguments.clone(), UBitwidth::B32, )), "_U16_TO_BITS" => Some(process_u_to_bits( - variables.clone(), + assignees.clone(), arguments.clone(), UBitwidth::B16, )), "_U8_TO_BITS" => Some(process_u_to_bits( - variables.clone(), + assignees.clone(), arguments.clone(), UBitwidth::B8, )), "_UNPACK" => { - assert_eq!(variables.len(), 1); + assert_eq!(assignees.len(), 1); assert_eq!(arguments.len(), 1); match FieldElementExpression::try_from(arguments[0].clone()) @@ -294,32 +393,120 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { }; match r { + // if the function call returns a constant Some(expr) => { - self.constants.insert( - TypedAssignee::Identifier(variables[0].clone()), - expr.clone(), - ); - match self.verbose { - true => Some(TypedStatement::MultipleDefinition( - variables, - TypedExpressionList::FunctionCall( - key, arguments, types, - ), - )), - false => None, + let verbose = self.verbose; + + let mut assignees = assignees; + + match assignees.pop().unwrap() { + TypedAssignee::Identifier(var) => match verbose { + true => { + self.constants + .insert(var.id.clone(), expr.clone()); + vec![TypedStatement::Definition( + TypedAssignee::Identifier(var), + expr, + )] + } + false => { + self.constants.insert(var.id, expr); + + vec![] + } + }, + assignee => { + match self.try_get_constant_mut(&assignee) { + Ok((_, c)) => match verbose { + true => { + *c = expr.clone(); + vec![TypedStatement::Definition( + assignee, expr, + )] + } + false => { + *c = expr; + vec![] + } + }, + Err(v) => match self.constants.remove(&v.id) { + Some(c) => vec![ + TypedStatement::Definition( + v.clone().into(), + c, + ), + TypedStatement::Definition( + assignee, expr, + ), + ], + None => vec![TypedStatement::Definition( + assignee, expr, + )], + }, + } + } } } None => { - let l = TypedExpressionList::FunctionCall( - key, arguments, types, - ); - Some(TypedStatement::MultipleDefinition(variables, l)) + // if the function call does not return a constant, invalidate the cache + // this happpens because we only propagate certain calls here + let mut assignees = assignees; + + let assignee = assignees.pop().unwrap(); + + let v = self + .try_get_constant_mut(&assignee) + .map(|(v, _)| v) + .unwrap_or_else(|v| v); + + match self.constants.remove(&v.id) { + Some(c) => vec![ + TypedStatement::Definition(v.clone().into(), c), + TypedStatement::MultipleDefinition( + vec![assignee], + TypedExpressionList::FunctionCall( + key, arguments, types, + ), + ), + ], + None => vec![TypedStatement::MultipleDefinition( + vec![assignee], + TypedExpressionList::FunctionCall( + key, arguments, types, + ), + )], + } } } } false => { + // if the function arguments are not constant, invalidate the cache + // for the return assignees + + let invalidations = assignees + .iter() + .flat_map(|assignee| { + let v = self + .try_get_constant_mut(&assignee) + .map(|(v, _)| v) + .unwrap_or_else(|v| v); + match self.constants.remove(&v.id) { + Some(c) => vec![TypedStatement::Definition( + v.clone().into(), + c, + )], + None => vec![], + } + }) + .collect::>(); + let l = TypedExpressionList::FunctionCall(key, arguments, types); - Some(TypedStatement::MultipleDefinition(variables, l)) + invalidations + .into_iter() + .chain(std::iter::once(TypedStatement::MultipleDefinition( + assignees, l, + ))) + .collect() } } } @@ -327,13 +514,10 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { } }; - // In verbose mode, we always return a statement - assert!(res.is_some() || !self.verbose); + // In verbose mode, we always return at least a statement + assert!(res.len() > 0 || !self.verbose); - match res { - Some(v) => vec![v], - None => vec![], - } + res } fn fold_uint_expression_inner( @@ -342,20 +526,13 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { e: UExpressionInner<'ast, T>, ) -> UExpressionInner<'ast, T> { match e { - UExpressionInner::Identifier(id) => { - match self - .constants - .get(&TypedAssignee::Identifier(Variable::uint( - id.clone(), - bitwidth, - ))) { - Some(e) => match e { - TypedExpression::Uint(e) => e.as_inner().clone(), - _ => unreachable!("constant stored for a uint should be a uint"), - }, - None => UExpressionInner::Identifier(id), - } - } + UExpressionInner::Identifier(id) => match self.constants.get(&id) { + Some(e) => match e { + TypedExpression::Uint(e) => e.as_inner().clone(), + _ => unreachable!("constant stored for a uint should be a uint"), + }, + None => UExpressionInner::Identifier(id), + }, UExpressionInner::Add(box e1, box e2) => match ( self.fold_uint_expression(e1).into_inner(), self.fold_uint_expression(e2).into_inner(), @@ -567,16 +744,16 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { } } (ArrayExpressionInner::Identifier(id), FieldElementExpression::Number(n)) => { - match self.constants.get(&TypedAssignee::Select( - box TypedAssignee::Identifier(Variable::array( - id.clone(), - inner_type.clone(), - size, - )), - box FieldElementExpression::Number(n.clone()).into(), - )) { - Some(e) => match e { - TypedExpression::Uint(e) => e.clone().into_inner(), + match self.constants.get(&id) { + Some(a) => match a { + TypedExpression::Array(a) => match a.as_inner() { + ArrayExpressionInner::Value(v) => UExpression::try_from( + v[n.to_dec_string().parse::().unwrap()].clone(), + ) + .unwrap() + .into_inner(), + _ => unreachable!(), + }, _ => unreachable!(""), }, None => UExpressionInner::Select( @@ -608,21 +785,15 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { e: FieldElementExpression<'ast, T>, ) -> FieldElementExpression<'ast, T> { match e { - FieldElementExpression::Identifier(id) => { - match self - .constants - .get(&TypedAssignee::Identifier(Variable::field_element( - id.clone(), - ))) { - Some(e) => match e { - TypedExpression::FieldElement(e) => e.clone(), - _ => unreachable!( - "constant stored for a field element should be a field element" - ), - }, - None => FieldElementExpression::Identifier(id), - } - } + FieldElementExpression::Identifier(id) => match self.constants.get(&id) { + Some(e) => match e { + TypedExpression::FieldElement(e) => e.clone(), + _ => unreachable!( + "constant stored for a field element should be a field element" + ), + }, + None => FieldElementExpression::Identifier(id), + }, FieldElementExpression::Add(box e1, box e2) => match ( self.fold_field_expression(e1), self.fold_field_expression(e2), @@ -707,17 +878,18 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { } } (ArrayExpressionInner::Identifier(id), FieldElementExpression::Number(n)) => { - match self.constants.get(&TypedAssignee::Select( - box TypedAssignee::Identifier(Variable::array( - id.clone(), - inner_type.clone(), - size, - )), - box FieldElementExpression::Number(n.clone()).into(), - )) { - Some(e) => match e { - TypedExpression::FieldElement(e) => e.clone(), - _ => unreachable!("??"), + match self.constants.get(&id) { + Some(a) => match a { + TypedExpression::Array(a) => match a.as_inner() { + ArrayExpressionInner::Value(v) => { + FieldElementExpression::try_from( + v[n.to_dec_string().parse::().unwrap()].clone(), + ) + .unwrap() + } + _ => unreachable!(), + }, + _ => unreachable!(""), }, None => FieldElementExpression::Select( box ArrayExpressionInner::Identifier(id).annotate(inner_type, size), @@ -772,21 +944,13 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { e: ArrayExpressionInner<'ast, T>, ) -> ArrayExpressionInner<'ast, T> { match e { - ArrayExpressionInner::Identifier(id) => { - match self - .constants - .get(&TypedAssignee::Identifier(Variable::array( - id.clone(), - ty.clone(), - size, - ))) { - Some(e) => match e { - TypedExpression::Array(e) => e.as_inner().clone(), - _ => panic!("constant stored for an array should be an array"), - }, - None => ArrayExpressionInner::Identifier(id), - } - } + ArrayExpressionInner::Identifier(id) => match self.constants.get(&id) { + Some(e) => match e { + TypedExpression::Array(e) => e.as_inner().clone(), + _ => panic!("constant stored for an array should be an array"), + }, + None => ArrayExpressionInner::Identifier(id), + }, ArrayExpressionInner::Select(box array, box index) => { let array = self.fold_array_expression(array); let index = self.fold_field_expression(index); @@ -809,17 +973,17 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { } } (ArrayExpressionInner::Identifier(id), FieldElementExpression::Number(n)) => { - match self.constants.get(&TypedAssignee::Select( - box TypedAssignee::Identifier(Variable::array( - id.clone(), - inner_type.clone(), - size, - )), - box FieldElementExpression::Number(n.clone()).into(), - )) { - Some(e) => match e { - TypedExpression::Array(e) => e.clone().into_inner(), - _ => unreachable!("should be an array"), + match self.constants.get(&id) { + Some(a) => match a { + TypedExpression::Array(a) => match a.as_inner() { + ArrayExpressionInner::Value(v) => ArrayExpression::try_from( + v[n.to_dec_string().parse::().unwrap()].clone(), + ) + .unwrap() + .into_inner(), + _ => unreachable!(), + }, + _ => unreachable!(""), }, None => ArrayExpressionInner::Select( box ArrayExpressionInner::Identifier(id).annotate(inner_type, size), @@ -885,20 +1049,13 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { e: StructExpressionInner<'ast, T>, ) -> StructExpressionInner<'ast, T> { match e { - StructExpressionInner::Identifier(id) => { - match self - .constants - .get(&TypedAssignee::Identifier(Variable::struc( - id.clone(), - ty.clone(), - ))) { - Some(e) => match e { - TypedExpression::Struct(e) => e.as_inner().clone(), - _ => panic!("constant stored for an array should be an array"), - }, - None => StructExpressionInner::Identifier(id), - } - } + StructExpressionInner::Identifier(id) => match self.constants.get(&id) { + Some(e) => match e { + TypedExpression::Struct(e) => e.as_inner().clone(), + _ => panic!("constant stored for an array should be an array"), + }, + None => StructExpressionInner::Identifier(id), + }, StructExpressionInner::Select(box array, box index) => { let array = self.fold_array_expression(array); let index = self.fold_field_expression(index); @@ -921,17 +1078,17 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { } } (ArrayExpressionInner::Identifier(id), FieldElementExpression::Number(n)) => { - match self.constants.get(&TypedAssignee::Select( - box TypedAssignee::Identifier(Variable::array( - id.clone(), - inner_type.clone(), - size, - )), - box FieldElementExpression::Number(n.clone()).into(), - )) { - Some(e) => match e { - TypedExpression::Struct(e) => e.clone().into_inner(), - _ => unreachable!("should be a struct"), + match self.constants.get(&id) { + Some(a) => match a { + TypedExpression::Array(a) => match a.as_inner() { + ArrayExpressionInner::Value(v) => StructExpression::try_from( + v[n.to_dec_string().parse::().unwrap()].clone(), + ) + .unwrap() + .into_inner(), + _ => unreachable!(), + }, + _ => unreachable!(""), }, None => StructExpressionInner::Select( box ArrayExpressionInner::Identifier(id).annotate(inner_type, size), @@ -1002,10 +1159,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { // These kind of reduction rules are easier to apply later in the process, when we have canonical representations // of expressions, ie `a + a` would always be written `2 * a` match e { - BooleanExpression::Identifier(id) => match self - .constants - .get(&TypedAssignee::Identifier(Variable::boolean(id.clone()))) - { + BooleanExpression::Identifier(id) => match self.constants.get(&id) { Some(e) => match e { TypedExpression::Boolean(e) => e.clone(), _ => panic!("constant stored for a boolean should be a boolean"), @@ -1152,17 +1306,16 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { } } (ArrayExpressionInner::Identifier(id), FieldElementExpression::Number(n)) => { - match self.constants.get(&TypedAssignee::Select( - box TypedAssignee::Identifier(Variable::array( - id.clone(), - inner_type.clone(), - size, - )), - box FieldElementExpression::Number(n.clone()).into(), - )) { - Some(e) => match e { - TypedExpression::Boolean(e) => e.clone(), - _ => unreachable!("Should be a boolean"), + match self.constants.get(&id) { + Some(a) => match a { + TypedExpression::Array(a) => match a.as_inner() { + ArrayExpressionInner::Value(v) => BooleanExpression::try_from( + v[n.to_dec_string().parse::().unwrap()].clone(), + ) + .unwrap(), + _ => unreachable!(), + }, + _ => unreachable!(""), }, None => BooleanExpression::Select( box ArrayExpressionInner::Identifier(id).annotate(inner_type, size), diff --git a/zokrates_core/src/static_analysis/unroll.rs b/zokrates_core/src/static_analysis/unroll.rs index 94fb00ba..567c4f7b 100644 --- a/zokrates_core/src/static_analysis/unroll.rs +++ b/zokrates_core/src/static_analysis/unroll.rs @@ -6,10 +6,8 @@ use crate::typed_absy::folder::*; use crate::typed_absy::identifier::CoreIdentifier; -use crate::typed_absy::types::{MemberId, Type}; use crate::typed_absy::*; use std::collections::HashMap; -use std::collections::HashSet; use zokrates_field::Field; pub enum Output<'ast, T: Field> { @@ -63,320 +61,6 @@ impl<'ast> Unroller<'ast> { false => Output::Incomplete(p, unroller.statement_count), } } - - fn choose_many( - base: TypedExpression<'ast, T>, - indices: Vec>, - new_expression: TypedExpression<'ast, T>, - statements: &mut HashSet>, - ) -> TypedExpression<'ast, T> { - let mut indices = indices; - - match indices.len() { - 0 => new_expression, - _ => match base { - TypedExpression::Array(base) => { - let inner_ty = base.inner_type(); - let size = base.size(); - - let head = indices.remove(0); - let tail = indices; - - match head { - Access::Select(head) => { - statements.insert(TypedStatement::Assertion( - BooleanExpression::Lt( - box head.clone(), - box FieldElementExpression::Number(T::from(size)), - ) - .into(), - )); - - ArrayExpressionInner::Value( - (0..size) - .map(|i| match inner_ty { - Type::Array(..) => ArrayExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(T::from(i)), - box head.clone(), - ), - match Self::choose_many( - ArrayExpression::select( - base.clone(), - FieldElementExpression::Number(T::from(i)), - ) - .into(), - tail.clone(), - new_expression.clone(), - statements, - ) { - TypedExpression::Array(e) => e, - e => unreachable!( - "the interior was expected to be an array, was {}", - e.get_type() - ), - }, - ArrayExpression::select( - base.clone(), - FieldElementExpression::Number(T::from(i)), - ), - ) - .into(), - Type::Struct(..) => StructExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(T::from(i)), - box head.clone(), - ), - match Self::choose_many( - StructExpression::select( - base.clone(), - FieldElementExpression::Number(T::from(i)), - ) - .into(), - tail.clone(), - new_expression.clone(), - statements, - ) { - TypedExpression::Struct(e) => e, - e => unreachable!( - "the interior was expected to be a struct, was {}", - e.get_type() - ), - }, - StructExpression::select( - base.clone(), - FieldElementExpression::Number(T::from(i)), - ), - ) - .into(), - Type::FieldElement => FieldElementExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(T::from(i)), - box head.clone(), - ), - match Self::choose_many( - FieldElementExpression::select( - base.clone(), - FieldElementExpression::Number(T::from(i)), - ) - .into(), - tail.clone(), - new_expression.clone(), - statements, - ) { - TypedExpression::FieldElement(e) => e, - e => unreachable!( - "the interior was expected to be a field, was {}", - e.get_type() - ), - }, - FieldElementExpression::select( - base.clone(), - FieldElementExpression::Number(T::from(i)), - ), - ) - .into(), - Type::Boolean => BooleanExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(T::from(i)), - box head.clone(), - ), - match Self::choose_many( - BooleanExpression::select( - base.clone(), - FieldElementExpression::Number(T::from(i)), - ) - .into(), - tail.clone(), - new_expression.clone(), - statements, - ) { - TypedExpression::Boolean(e) => e, - e => unreachable!( - "the interior was expected to be a boolean, was {}", - e.get_type() - ), - }, - BooleanExpression::select( - base.clone(), - FieldElementExpression::Number(T::from(i)), - ), - ) - .into(), - Type::Uint(..) => UExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(T::from(i)), - box head.clone(), - ), - match Self::choose_many( - UExpression::select( - base.clone(), - FieldElementExpression::Number(T::from(i)), - ) - .into(), - tail.clone(), - new_expression.clone(), - statements, - ) { - TypedExpression::Uint(e) => e, - e => unreachable!( - "the interior was expected to be a uint, was {}", - e.get_type() - ), - }, - UExpression::select( - base.clone(), - FieldElementExpression::Number(T::from(i)), - ), - ) - .into(), - }) - .collect(), - ) - .annotate(inner_ty.clone(), size) - .into() - } - Access::Member(..) => unreachable!("can't get a member from an array"), - } - } - TypedExpression::Struct(base) => { - let members = match base.get_type() { - Type::Struct(members) => members.clone(), - _ => unreachable!(), - }; - - let head = indices.remove(0); - let tail = indices; - - match head { - Access::Member(head) => StructExpressionInner::Value( - members - .clone() - .into_iter() - .map(|member| match *member.ty { - Type::FieldElement => { - if member.id == head { - Self::choose_many( - FieldElementExpression::member( - base.clone(), - head.clone(), - ) - .into(), - tail.clone(), - new_expression.clone(), - statements, - ) - } else { - FieldElementExpression::member( - base.clone(), - member.id.clone(), - ) - .into() - } - } - Type::Uint(..) => { - if member.id == head { - Self::choose_many( - UExpression::member(base.clone(), head.clone()) - .into(), - tail.clone(), - new_expression.clone(), - statements, - ) - } else { - UExpression::member(base.clone(), member.id.clone()) - .into() - } - } - Type::Boolean => { - if member.id == head { - Self::choose_many( - BooleanExpression::member( - base.clone(), - head.clone(), - ) - .into(), - tail.clone(), - new_expression.clone(), - statements, - ) - } else { - BooleanExpression::member( - base.clone(), - member.id.clone(), - ) - .into() - } - } - Type::Array(..) => { - if member.id == head { - Self::choose_many( - ArrayExpression::member(base.clone(), head.clone()) - .into(), - tail.clone(), - new_expression.clone(), - statements, - ) - } else { - ArrayExpression::member(base.clone(), member.id.clone()) - .into() - } - } - Type::Struct(..) => { - if member.id == head { - Self::choose_many( - StructExpression::member( - base.clone(), - head.clone(), - ) - .into(), - tail.clone(), - new_expression.clone(), - statements, - ) - } else { - StructExpression::member( - base.clone(), - member.id.clone(), - ) - .into() - } - } - }) - .collect(), - ) - .annotate(members) - .into(), - Access::Select(..) => unreachable!("can't get a element from a struct"), - } - } - e => unreachable!("can't make an access on a {}", e.get_type()), - }, - } - } -} - -#[derive(Clone, Debug)] -enum Access<'ast, T: Field> { - Select(FieldElementExpression<'ast, T>), - Member(MemberId), -} -/// Turn an assignee into its representation as a base variable and a list accesses -/// a[2][3][4] -> (a, [2, 3, 4]) -fn linear<'ast, T: Field>(a: TypedAssignee<'ast, T>) -> (Variable, Vec>) { - match a { - TypedAssignee::Identifier(v) => (v, vec![]), - TypedAssignee::Select(box array, box index) => { - let (v, mut indices) = linear(array); - indices.push(Access::Select(index)); - (v, indices) - } - TypedAssignee::Member(box s, m) => { - let (v, mut indices) = linear(s); - indices.push(Access::Member(m)); - (v, indices) - } - } } impl<'ast, T: Field> Folder<'ast, T> for Unroller<'ast> { @@ -384,64 +68,31 @@ impl<'ast, T: Field> Folder<'ast, T> for Unroller<'ast> { self.statement_count += 1; match s { TypedStatement::Declaration(_) => vec![], - TypedStatement::Definition(assignee, expr) => { - let expr = self.fold_expression(expr); + TypedStatement::Definition(a, e) => { + let e = self.fold_expression(e); - let (variable, indices) = linear(assignee); - - let base = match variable.get_type() { - Type::FieldElement => { - FieldElementExpression::Identifier(variable.id.clone().into()).into() - } - Type::Boolean => { - BooleanExpression::Identifier(variable.id.clone().into()).into() - } - Type::Uint(bitwidth) => { - UExpressionInner::Identifier(variable.id.clone().into()) - .annotate(bitwidth) - .into() - } - Type::Array(array_type) => { - ArrayExpressionInner::Identifier(variable.id.clone().into()) - .annotate(*array_type.ty, array_type.size) - .into() - } - Type::Struct(members) => { - StructExpressionInner::Identifier(variable.id.clone().into()) - .annotate(members) - .into() + let a = match a { + TypedAssignee::Identifier(v) => { + TypedAssignee::Identifier(self.issue_next_ssa_variable(v)) } + a => fold_assignee(self, a), }; - let base = self.fold_expression(base); - - let indices = indices + vec![TypedStatement::Definition(a, e)] + } + TypedStatement::MultipleDefinition(assignees, exprs) => { + let exprs = self.fold_expression_list(exprs); + let assignees = assignees .into_iter() .map(|a| match a { - Access::Select(i) => Access::Select(self.fold_field_expression(i)), - a => a, + TypedAssignee::Identifier(v) => { + TypedAssignee::Identifier(self.issue_next_ssa_variable(v)) + } + a => fold_assignee(self, a), }) .collect(); - let mut range_checks = HashSet::new(); - let e = Self::choose_many(base, indices, expr, &mut range_checks); - - range_checks - .into_iter() - .chain(std::iter::once(TypedStatement::Definition( - TypedAssignee::Identifier(self.issue_next_ssa_variable(variable)), - e, - ))) - .collect() - } - TypedStatement::MultipleDefinition(variables, exprs) => { - let exprs = self.fold_expression_list(exprs); - let variables = variables - .into_iter() - .map(|v| self.issue_next_ssa_variable(v)) - .collect(); - - vec![TypedStatement::MultipleDefinition(variables, exprs)] + vec![TypedStatement::MultipleDefinition(assignees, exprs)] } TypedStatement::For(v, from, to, stats) => { let from = self.fold_field_expression(from); @@ -510,246 +161,6 @@ mod tests { use super::*; use zokrates_field::Bn128Field; - #[test] - fn ssa_array() { - let a0 = ArrayExpressionInner::Identifier("a".into()).annotate(Type::FieldElement, 3); - - let e = FieldElementExpression::Number(Bn128Field::from(42)).into(); - - let index = FieldElementExpression::Number(Bn128Field::from(1)); - - let a1 = Unroller::choose_many( - a0.clone().into(), - vec![Access::Select(index)], - e, - &mut HashSet::new(), - ); - - // a[1] = 42 - // -> a = [0 == 1 ? 42 : a[0], 1 == 1 ? 42 : a[1], 2 == 1 ? 42 : a[2]] - - assert_eq!( - a1, - ArrayExpressionInner::Value(vec![ - FieldElementExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(Bn128Field::from(0)), - box FieldElementExpression::Number(Bn128Field::from(1)) - ), - FieldElementExpression::Number(Bn128Field::from(42)), - FieldElementExpression::select( - a0.clone(), - FieldElementExpression::Number(Bn128Field::from(0)) - ) - ) - .into(), - FieldElementExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(Bn128Field::from(1)), - box FieldElementExpression::Number(Bn128Field::from(1)) - ), - FieldElementExpression::Number(Bn128Field::from(42)), - FieldElementExpression::select( - a0.clone(), - FieldElementExpression::Number(Bn128Field::from(1)) - ) - ) - .into(), - FieldElementExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(Bn128Field::from(2)), - box FieldElementExpression::Number(Bn128Field::from(1)) - ), - FieldElementExpression::Number(Bn128Field::from(42)), - FieldElementExpression::select( - a0.clone(), - FieldElementExpression::Number(Bn128Field::from(2)) - ) - ) - .into() - ]) - .annotate(Type::FieldElement, 3) - .into() - ); - - let a0 = ArrayExpressionInner::Identifier("a".into()) - .annotate(Type::array(Type::FieldElement, 3), 3); - - let e = ArrayExpressionInner::Identifier("b".into()).annotate(Type::FieldElement, 3); - - let index = FieldElementExpression::Number(Bn128Field::from(1)); - - let a1 = Unroller::choose_many( - a0.clone().into(), - vec![Access::Select(index)], - e.clone().into(), - &mut HashSet::new(), - ); - - // a[0] = b - // -> a = [0 == 1 ? b : a[0], 1 == 1 ? b : a[1], 2 == 1 ? b : a[2]] - - assert_eq!( - a1, - ArrayExpressionInner::Value(vec![ - ArrayExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(Bn128Field::from(0)), - box FieldElementExpression::Number(Bn128Field::from(1)) - ), - e.clone(), - ArrayExpression::select( - a0.clone(), - FieldElementExpression::Number(Bn128Field::from(0)) - ) - ) - .into(), - ArrayExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(Bn128Field::from(1)), - box FieldElementExpression::Number(Bn128Field::from(1)) - ), - e.clone(), - ArrayExpression::select( - a0.clone(), - FieldElementExpression::Number(Bn128Field::from(1)) - ) - ) - .into(), - ArrayExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(Bn128Field::from(2)), - box FieldElementExpression::Number(Bn128Field::from(1)) - ), - e.clone(), - ArrayExpression::select( - a0.clone(), - FieldElementExpression::Number(Bn128Field::from(2)) - ) - ) - .into() - ]) - .annotate(Type::array(Type::FieldElement, 3), 3) - .into() - ); - - let a0 = ArrayExpressionInner::Identifier("a".into()) - .annotate(Type::array(Type::FieldElement, 2), 2); - - let e = FieldElementExpression::Number(Bn128Field::from(42)); - - let indices = vec![ - Access::Select(FieldElementExpression::Number(Bn128Field::from(0))), - Access::Select(FieldElementExpression::Number(Bn128Field::from(0))), - ]; - - let a1 = Unroller::choose_many( - a0.clone().into(), - indices, - e.clone().into(), - &mut HashSet::new(), - ); - - // a[0][0] = 42 - // -> a = [0 == 0 ? [0 == 0 ? 42 : a[0][0], 1 == 0 ? 42 : a[0][1]] : a[0], 1 == 0 ? [0 == 0 ? 42 : a[1][0], 1 == 0 ? 42 : a[1][1]] : a[1]] - - assert_eq!( - a1, - ArrayExpressionInner::Value(vec![ - ArrayExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(Bn128Field::from(0)), - box FieldElementExpression::Number(Bn128Field::from(0)) - ), - ArrayExpressionInner::Value(vec![ - FieldElementExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(Bn128Field::from(0)), - box FieldElementExpression::Number(Bn128Field::from(0)) - ), - e.clone(), - FieldElementExpression::select( - ArrayExpression::select( - a0.clone(), - FieldElementExpression::Number(Bn128Field::from(0)) - ), - FieldElementExpression::Number(Bn128Field::from(0)) - ) - ) - .into(), - FieldElementExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(Bn128Field::from(1)), - box FieldElementExpression::Number(Bn128Field::from(0)) - ), - e.clone(), - FieldElementExpression::select( - ArrayExpression::select( - a0.clone(), - FieldElementExpression::Number(Bn128Field::from(0)) - ), - FieldElementExpression::Number(Bn128Field::from(1)) - ) - ) - .into() - ]) - .annotate(Type::FieldElement, 2), - ArrayExpression::select( - a0.clone(), - FieldElementExpression::Number(Bn128Field::from(0)) - ) - ) - .into(), - ArrayExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(Bn128Field::from(1)), - box FieldElementExpression::Number(Bn128Field::from(0)) - ), - ArrayExpressionInner::Value(vec![ - FieldElementExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(Bn128Field::from(0)), - box FieldElementExpression::Number(Bn128Field::from(0)) - ), - e.clone(), - FieldElementExpression::select( - ArrayExpression::select( - a0.clone(), - FieldElementExpression::Number(Bn128Field::from(1)) - ), - FieldElementExpression::Number(Bn128Field::from(0)) - ) - ) - .into(), - FieldElementExpression::if_else( - BooleanExpression::FieldEq( - box FieldElementExpression::Number(Bn128Field::from(1)), - box FieldElementExpression::Number(Bn128Field::from(0)) - ), - e.clone(), - FieldElementExpression::select( - ArrayExpression::select( - a0.clone(), - FieldElementExpression::Number(Bn128Field::from(1)) - ), - FieldElementExpression::Number(Bn128Field::from(1)) - ) - ) - .into() - ]) - .annotate(Type::FieldElement, 2), - ArrayExpression::select( - a0.clone(), - FieldElementExpression::Number(Bn128Field::from(1)) - ) - ) - .into(), - ]) - .annotate(Type::array(Type::FieldElement, 2), 2) - .into() - ); - } - #[cfg(test)] mod statement { use super::*; @@ -829,17 +240,45 @@ mod tests { fn idempotence() { // an already unrolled program should not be modified by unrolling again + // b = [5] + // b[0] = 1 // a = 5 // a_1 = 6 // a_2 = 7 // should be turned into + // b = [5] + // b[0] = 1 // a = 5 // a_1 = 6 // a_2 = 7 let mut u = Unroller::new(); + let s = TypedStatement::Definition( + TypedAssignee::Identifier(Variable::array( + Identifier::from("b").version(0), + Type::FieldElement, + 1, + )), + ArrayExpressionInner::Value(vec![FieldElementExpression::from(Bn128Field::from( + 5, + )) + .into()]) + .annotate(Type::FieldElement, 1) + .into(), + ); + assert_eq!(u.fold_statement(s.clone()), vec![s]); + + let s = TypedStatement::Definition( + TypedAssignee::Select( + box Variable::field_element(Identifier::from("b").version(0)).into(), + box FieldElementExpression::Number(Bn128Field::from(0)), + ), + FieldElementExpression::Number(Bn128Field::from(1)).into(), + ); + assert_eq!(u.fold_statement(s.clone()), vec![s]); + let s = TypedStatement::Definition( TypedAssignee::Identifier(Variable::field_element( Identifier::from("a").version(0), @@ -1005,7 +444,7 @@ mod tests { ); let s: TypedStatement = TypedStatement::MultipleDefinition( - vec![Variable::field_element("a")], + vec![Variable::field_element("a").into()], TypedExpressionList::FunctionCall( FunctionKey::with_id("foo").signature( Signature::new() @@ -1019,7 +458,7 @@ mod tests { assert_eq!( u.fold_statement(s), vec![TypedStatement::MultipleDefinition( - vec![Variable::field_element(Identifier::from("a").version(1))], + vec![Variable::field_element(Identifier::from("a").version(1)).into()], TypedExpressionList::FunctionCall( FunctionKey::with_id("foo").signature( Signature::new() @@ -1043,7 +482,7 @@ mod tests { // should be turned into // a_0 = [1, 1] - // a_1 = [if 0 == 1 then 2 else a_0[0], if 1 == 1 then 2 else a_0[1]] + // a_0[1] = 2 let mut u = Unroller::new(); @@ -1085,58 +524,7 @@ mod tests { FieldElementExpression::Number(Bn128Field::from(2)).into(), ); - assert_eq!( - u.fold_statement(s), - vec![ - TypedStatement::Assertion( - BooleanExpression::Lt( - box FieldElementExpression::Number(Bn128Field::from(1)), - box FieldElementExpression::Number(Bn128Field::from(2)) - ) - .into(), - ), - TypedStatement::Definition( - TypedAssignee::Identifier(Variable::field_array( - Identifier::from("a").version(1), - 2 - )), - ArrayExpressionInner::Value(vec![ - FieldElementExpression::IfElse( - box BooleanExpression::FieldEq( - box FieldElementExpression::Number(Bn128Field::from(0)), - box FieldElementExpression::Number(Bn128Field::from(1)) - ), - box FieldElementExpression::Number(Bn128Field::from(2)), - box FieldElementExpression::Select( - box ArrayExpressionInner::Identifier( - Identifier::from("a").version(0) - ) - .annotate(Type::FieldElement, 2), - box FieldElementExpression::Number(Bn128Field::from(0)) - ), - ) - .into(), - FieldElementExpression::IfElse( - box BooleanExpression::FieldEq( - box FieldElementExpression::Number(Bn128Field::from(1)), - box FieldElementExpression::Number(Bn128Field::from(1)) - ), - box FieldElementExpression::Number(Bn128Field::from(2)), - box FieldElementExpression::Select( - box ArrayExpressionInner::Identifier( - Identifier::from("a").version(0) - ) - .annotate(Type::FieldElement, 2), - box FieldElementExpression::Number(Bn128Field::from(1)) - ), - ) - .into(), - ]) - .annotate(Type::FieldElement, 2) - .into() - ) - ] - ); + assert_eq!(u.fold_statement(s.clone()), vec![s]); } #[test] @@ -1146,7 +534,7 @@ mod tests { // should be turned into // a_0 = [[0, 1], [2, 3]] - // a_1 = [if 0 == 1 then [4, 5] else a_0[0], if 1 == 1 then [4, 5] else a_0[1]] + // a_0 = [4, 5] let mut u = Unroller::new(); @@ -1222,72 +610,7 @@ mod tests { .into(), ); - assert_eq!( - u.fold_statement(s), - vec![ - TypedStatement::Assertion( - BooleanExpression::Lt( - box FieldElementExpression::Number(Bn128Field::from(1)), - box FieldElementExpression::Number(Bn128Field::from(2)) - ) - .into(), - ), - TypedStatement::Definition( - TypedAssignee::Identifier(Variable::with_id_and_type( - Identifier::from("a").version(1), - array_of_array_ty.clone() - )), - ArrayExpressionInner::Value(vec![ - ArrayExpressionInner::IfElse( - box BooleanExpression::FieldEq( - box FieldElementExpression::Number(Bn128Field::from(0)), - box FieldElementExpression::Number(Bn128Field::from(1)) - ), - box ArrayExpressionInner::Value(vec![ - FieldElementExpression::Number(Bn128Field::from(4)).into(), - FieldElementExpression::Number(Bn128Field::from(5)).into(), - ]) - .annotate(Type::FieldElement, 2) - .into(), - box ArrayExpressionInner::Select( - box ArrayExpressionInner::Identifier( - Identifier::from("a").version(0) - ) - .annotate(Type::array(Type::FieldElement, 2), 2), - box FieldElementExpression::Number(Bn128Field::from(0)) - ) - .annotate(Type::FieldElement, 2), - ) - .annotate(Type::FieldElement, 2) - .into(), - ArrayExpressionInner::IfElse( - box BooleanExpression::FieldEq( - box FieldElementExpression::Number(Bn128Field::from(1)), - box FieldElementExpression::Number(Bn128Field::from(1)) - ), - box ArrayExpressionInner::Value(vec![ - FieldElementExpression::Number(Bn128Field::from(4)).into(), - FieldElementExpression::Number(Bn128Field::from(5)).into(), - ]) - .annotate(Type::FieldElement, 2) - .into(), - box ArrayExpressionInner::Select( - box ArrayExpressionInner::Identifier( - Identifier::from("a").version(0) - ) - .annotate(Type::array(Type::FieldElement, 2), 2), - box FieldElementExpression::Number(Bn128Field::from(1)) - ) - .annotate(Type::FieldElement, 2), - ) - .annotate(Type::FieldElement, 2) - .into(), - ]) - .annotate(Type::array(Type::FieldElement, 2), 2) - .into() - ) - ] - ); + assert_eq!(u.fold_statement(s.clone()), vec![s]); } } } diff --git a/zokrates_core/src/static_analysis/variable_access_remover.rs b/zokrates_core/src/static_analysis/variable_read_remover.rs similarity index 96% rename from zokrates_core/src/static_analysis/variable_access_remover.rs rename to zokrates_core/src/static_analysis/variable_read_remover.rs index e3fde6f6..563dcb4e 100644 --- a/zokrates_core/src/static_analysis/variable_access_remover.rs +++ b/zokrates_core/src/static_analysis/variable_read_remover.rs @@ -13,11 +13,11 @@ use crate::typed_absy::{folder::*, *}; use zokrates_field::Field; -pub struct VariableAccessRemover<'ast, T: Field> { +pub struct VariableReadRemover<'ast, T: Field> { statements: Vec>, } -impl<'ast, T: Field> VariableAccessRemover<'ast, T> { +impl<'ast, T: Field> VariableReadRemover<'ast, T> { fn new() -> Self { Self { statements: vec![] } } @@ -76,7 +76,7 @@ impl<'ast, T: Field> VariableAccessRemover<'ast, T> { } } -impl<'ast, T: Field> Folder<'ast, T> for VariableAccessRemover<'ast, T> { +impl<'ast, T: Field> Folder<'ast, T> for VariableReadRemover<'ast, T> { fn fold_field_expression( &mut self, e: FieldElementExpression<'ast, T>, @@ -167,7 +167,7 @@ mod tests { ); assert_eq!( - VariableAccessRemover::new().fold_statement(access), + VariableReadRemover::new().fold_statement(access), vec![ TypedStatement::Assertion( BooleanExpression::Or( diff --git a/zokrates_core/src/static_analysis/variable_write_remover.rs b/zokrates_core/src/static_analysis/variable_write_remover.rs new file mode 100644 index 00000000..24aa8f57 --- /dev/null +++ b/zokrates_core/src/static_analysis/variable_write_remover.rs @@ -0,0 +1,413 @@ +//! Module containing SSA reduction, including for-loop unrolling +//! +//! @file unroll.rs +//! @author Thibaut Schaeffer +//! @date 2018 + +use crate::typed_absy::folder::*; +use crate::typed_absy::types::{MemberId, Type}; +use crate::typed_absy::*; +use std::collections::HashSet; +use zokrates_field::Field; + +pub struct VariableWriteRemover; + +impl<'ast> VariableWriteRemover { + fn new() -> Self { + VariableWriteRemover + } + + pub fn apply(p: TypedProgram) -> TypedProgram { + let mut remover = VariableWriteRemover::new(); + remover.fold_program(p) + } + + fn choose_many( + base: TypedExpression<'ast, T>, + indices: Vec>, + new_expression: TypedExpression<'ast, T>, + statements: &mut HashSet>, + ) -> TypedExpression<'ast, T> { + let mut indices = indices; + + match indices.len() { + 0 => new_expression, + _ => match base { + TypedExpression::Array(base) => { + let inner_ty = base.inner_type(); + let size = base.size(); + + let head = indices.remove(0); + let tail = indices; + + match head { + Access::Select(head) => { + statements.insert(TypedStatement::Assertion( + BooleanExpression::Lt( + box head.clone(), + box FieldElementExpression::Number(T::from(size)), + ) + .into(), + )); + + ArrayExpressionInner::Value( + (0..size) + .map(|i| match inner_ty { + Type::Array(..) => ArrayExpression::if_else( + BooleanExpression::FieldEq( + box FieldElementExpression::Number(T::from(i)), + box head.clone(), + ), + match Self::choose_many( + ArrayExpression::select( + base.clone(), + FieldElementExpression::Number(T::from(i)), + ) + .into(), + tail.clone(), + new_expression.clone(), + statements, + ) { + TypedExpression::Array(e) => e, + e => unreachable!( + "the interior was expected to be an array, was {}", + e.get_type() + ), + }, + ArrayExpression::select( + base.clone(), + FieldElementExpression::Number(T::from(i)), + ), + ) + .into(), + Type::Struct(..) => StructExpression::if_else( + BooleanExpression::FieldEq( + box FieldElementExpression::Number(T::from(i)), + box head.clone(), + ), + match Self::choose_many( + StructExpression::select( + base.clone(), + FieldElementExpression::Number(T::from(i)), + ) + .into(), + tail.clone(), + new_expression.clone(), + statements, + ) { + TypedExpression::Struct(e) => e, + e => unreachable!( + "the interior was expected to be a struct, was {}", + e.get_type() + ), + }, + StructExpression::select( + base.clone(), + FieldElementExpression::Number(T::from(i)), + ), + ) + .into(), + Type::FieldElement => FieldElementExpression::if_else( + BooleanExpression::FieldEq( + box FieldElementExpression::Number(T::from(i)), + box head.clone(), + ), + match Self::choose_many( + FieldElementExpression::select( + base.clone(), + FieldElementExpression::Number(T::from(i)), + ) + .into(), + tail.clone(), + new_expression.clone(), + statements, + ) { + TypedExpression::FieldElement(e) => e, + e => unreachable!( + "the interior was expected to be a field, was {}", + e.get_type() + ), + }, + FieldElementExpression::select( + base.clone(), + FieldElementExpression::Number(T::from(i)), + ), + ) + .into(), + Type::Boolean => BooleanExpression::if_else( + BooleanExpression::FieldEq( + box FieldElementExpression::Number(T::from(i)), + box head.clone(), + ), + match Self::choose_many( + BooleanExpression::select( + base.clone(), + FieldElementExpression::Number(T::from(i)), + ) + .into(), + tail.clone(), + new_expression.clone(), + statements, + ) { + TypedExpression::Boolean(e) => e, + e => unreachable!( + "the interior was expected to be a boolean, was {}", + e.get_type() + ), + }, + BooleanExpression::select( + base.clone(), + FieldElementExpression::Number(T::from(i)), + ), + ) + .into(), + Type::Uint(..) => UExpression::if_else( + BooleanExpression::FieldEq( + box FieldElementExpression::Number(T::from(i)), + box head.clone(), + ), + match Self::choose_many( + UExpression::select( + base.clone(), + FieldElementExpression::Number(T::from(i)), + ) + .into(), + tail.clone(), + new_expression.clone(), + statements, + ) { + TypedExpression::Uint(e) => e, + e => unreachable!( + "the interior was expected to be a uint, was {}", + e.get_type() + ), + }, + UExpression::select( + base.clone(), + FieldElementExpression::Number(T::from(i)), + ), + ) + .into(), + }) + .collect(), + ) + .annotate(inner_ty.clone(), size) + .into() + } + Access::Member(..) => unreachable!("can't get a member from an array"), + } + } + TypedExpression::Struct(base) => { + let members = match base.get_type() { + Type::Struct(members) => members.clone(), + _ => unreachable!(), + }; + + let head = indices.remove(0); + let tail = indices; + + match head { + Access::Member(head) => StructExpressionInner::Value( + members + .clone() + .into_iter() + .map(|member| match *member.ty { + Type::FieldElement => { + if member.id == head { + Self::choose_many( + FieldElementExpression::member( + base.clone(), + head.clone(), + ) + .into(), + tail.clone(), + new_expression.clone(), + statements, + ) + } else { + FieldElementExpression::member( + base.clone(), + member.id.clone(), + ) + .into() + } + } + Type::Uint(..) => { + if member.id == head { + Self::choose_many( + UExpression::member(base.clone(), head.clone()) + .into(), + tail.clone(), + new_expression.clone(), + statements, + ) + } else { + UExpression::member(base.clone(), member.id.clone()) + .into() + } + } + Type::Boolean => { + if member.id == head { + Self::choose_many( + BooleanExpression::member( + base.clone(), + head.clone(), + ) + .into(), + tail.clone(), + new_expression.clone(), + statements, + ) + } else { + BooleanExpression::member( + base.clone(), + member.id.clone(), + ) + .into() + } + } + Type::Array(..) => { + if member.id == head { + Self::choose_many( + ArrayExpression::member(base.clone(), head.clone()) + .into(), + tail.clone(), + new_expression.clone(), + statements, + ) + } else { + ArrayExpression::member(base.clone(), member.id.clone()) + .into() + } + } + Type::Struct(..) => { + if member.id == head { + Self::choose_many( + StructExpression::member( + base.clone(), + head.clone(), + ) + .into(), + tail.clone(), + new_expression.clone(), + statements, + ) + } else { + StructExpression::member( + base.clone(), + member.id.clone(), + ) + .into() + } + } + }) + .collect(), + ) + .annotate(members) + .into(), + Access::Select(..) => unreachable!("can't get a element from a struct"), + } + } + e => unreachable!("can't make an access on a {}", e.get_type()), + }, + } + } +} + +#[derive(Clone, Debug)] +enum Access<'ast, T: Field> { + Select(FieldElementExpression<'ast, T>), + Member(MemberId), +} +/// Turn an assignee into its representation as a base variable and a list accesses +/// a[2][3][4] -> (a, [2, 3, 4]) +fn linear<'ast, T: Field>(a: TypedAssignee<'ast, T>) -> (Variable, Vec>) { + match a { + TypedAssignee::Identifier(v) => (v, vec![]), + TypedAssignee::Select(box array, box index) => { + let (v, mut indices) = linear(array); + indices.push(Access::Select(index)); + (v, indices) + } + TypedAssignee::Member(box s, m) => { + let (v, mut indices) = linear(s); + indices.push(Access::Member(m)); + (v, indices) + } + } +} + +fn is_constant<'ast, T>(assignee: &TypedAssignee<'ast, T>) -> bool { + match assignee { + TypedAssignee::Identifier(_) => true, + TypedAssignee::Select(box assignee, box index) => match index { + FieldElementExpression::Number(_) => is_constant(assignee), + _ => false, + }, + TypedAssignee::Member(box assignee, _) => is_constant(assignee), + } +} + +impl<'ast, T: Field> Folder<'ast, T> for VariableWriteRemover { + fn fold_statement(&mut self, s: TypedStatement<'ast, T>) -> Vec> { + match s { + TypedStatement::Definition(assignee, expr) => { + if is_constant(&assignee) { + vec![TypedStatement::Definition(assignee, expr)] + } else { + // Note: here we redefine the whole object, ideally we would only redefine some of it + // Example: `a[0][i] = 42` we redefine `a` but we could redefine just `a[0]` + let expr = self.fold_expression(expr); + + let (variable, indices) = linear(assignee); + + let base = match variable.get_type() { + Type::FieldElement => { + FieldElementExpression::Identifier(variable.id.clone().into()).into() + } + Type::Boolean => { + BooleanExpression::Identifier(variable.id.clone().into()).into() + } + Type::Uint(bitwidth) => { + UExpressionInner::Identifier(variable.id.clone().into()) + .annotate(bitwidth) + .into() + } + Type::Array(array_type) => { + ArrayExpressionInner::Identifier(variable.id.clone().into()) + .annotate(*array_type.ty, array_type.size) + .into() + } + Type::Struct(members) => { + StructExpressionInner::Identifier(variable.id.clone().into()) + .annotate(members) + .into() + } + }; + + let base = self.fold_expression(base); + + let indices = indices + .into_iter() + .map(|a| match a { + Access::Select(i) => Access::Select(self.fold_field_expression(i)), + a => a, + }) + .collect(); + + let mut range_checks = HashSet::new(); + let e = Self::choose_many(base, indices, expr, &mut range_checks); + + range_checks + .into_iter() + .chain(std::iter::once(TypedStatement::Definition( + TypedAssignee::Identifier(variable), + e, + ))) + .collect() + } + } + s => fold_statement(self, s), + } + } +} diff --git a/zokrates_core/src/typed_absy/folder.rs b/zokrates_core/src/typed_absy/folder.rs index d9dcb5bf..76a81ff2 100644 --- a/zokrates_core/src/typed_absy/folder.rs +++ b/zokrates_core/src/typed_absy/folder.rs @@ -42,14 +42,7 @@ pub trait Folder<'ast, T: Field>: Sized { } fn fold_assignee(&mut self, a: TypedAssignee<'ast, T>) -> TypedAssignee<'ast, T> { - match a { - TypedAssignee::Identifier(v) => TypedAssignee::Identifier(self.fold_variable(v)), - TypedAssignee::Select(box a, box index) => TypedAssignee::Select( - box self.fold_assignee(a), - box self.fold_field_expression(index), - ), - TypedAssignee::Member(box s, m) => TypedAssignee::Member(box self.fold_assignee(s), m), - } + fold_assignee(self, a) } fn fold_statement(&mut self, s: TypedStatement<'ast, T>) -> Vec> { @@ -175,8 +168,8 @@ pub fn fold_statement<'ast, T: Field, F: Folder<'ast, T>>( .flat_map(|s| f.fold_statement(s)) .collect(), ), - TypedStatement::MultipleDefinition(variables, elist) => TypedStatement::MultipleDefinition( - variables.into_iter().map(|v| f.fold_variable(v)).collect(), + TypedStatement::MultipleDefinition(assignees, elist) => TypedStatement::MultipleDefinition( + assignees.into_iter().map(|a| f.fold_assignee(a)).collect(), f.fold_expression_list(elist), ), }; @@ -548,6 +541,19 @@ pub fn fold_function_symbol<'ast, T: Field, F: Folder<'ast, T>>( } } +pub fn fold_assignee<'ast, T: Field, F: Folder<'ast, T>>( + f: &mut F, + a: TypedAssignee<'ast, T>, +) -> TypedAssignee<'ast, T> { + match a { + TypedAssignee::Identifier(v) => TypedAssignee::Identifier(f.fold_variable(v)), + TypedAssignee::Select(box a, box index) => { + TypedAssignee::Select(box f.fold_assignee(a), box f.fold_field_expression(index)) + } + TypedAssignee::Member(box s, m) => TypedAssignee::Member(box f.fold_assignee(s), m), + } +} + pub fn fold_program<'ast, T: Field, F: Folder<'ast, T>>( f: &mut F, p: TypedProgram<'ast, T>, diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index a293e16b..0bb7f7c9 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -259,6 +259,12 @@ pub enum TypedAssignee<'ast, T> { Member(Box>, MemberId), } +impl<'ast, T> From> for TypedAssignee<'ast, T> { + fn from(v: Variable<'ast>) -> Self { + TypedAssignee::Identifier(v) + } +} + impl<'ast, T> Typed for TypedAssignee<'ast, T> { fn get_type(&self) -> Type { match *self { @@ -319,7 +325,7 @@ pub enum TypedStatement<'ast, T> { FieldElementExpression<'ast, T>, Vec>, ), - MultipleDefinition(Vec>, TypedExpressionList<'ast, T>), + MultipleDefinition(Vec>, TypedExpressionList<'ast, T>), } impl<'ast, T: fmt::Debug> fmt::Debug for TypedStatement<'ast, T> { @@ -628,6 +634,12 @@ pub enum FieldElementExpression<'ast, T> { ), } +impl<'ast, T> From for FieldElementExpression<'ast, T> { + fn from(n: T) -> Self { + FieldElementExpression::Number(n) + } +} + /// An expression of type `bool` #[derive(Clone, PartialEq, Hash, Eq)] pub enum BooleanExpression<'ast, T> { @@ -737,6 +749,10 @@ impl<'ast, T> ArrayExpression<'ast, T> { &self.inner } + pub fn as_inner_mut(&mut self) -> &mut ArrayExpressionInner<'ast, T> { + &mut self.inner + } + pub fn into_inner(self) -> ArrayExpressionInner<'ast, T> { self.inner } @@ -757,6 +773,10 @@ impl<'ast, T> StructExpression<'ast, T> { &self.inner } + pub fn as_inner_mut(&mut self) -> &mut StructExpressionInner<'ast, T> { + &mut self.inner + } + pub fn into_inner(self) -> StructExpressionInner<'ast, T> { self.inner } diff --git a/zokrates_core/src/zir/mod.rs b/zokrates_core/src/zir/mod.rs index 96a3a543..73199e3a 100644 --- a/zokrates_core/src/zir/mod.rs +++ b/zokrates_core/src/zir/mod.rs @@ -192,7 +192,7 @@ pub enum ZirStatement<'ast, T> { Definition(ZirAssignee<'ast>, ZirExpression<'ast, T>), Declaration(Variable<'ast>), Assertion(BooleanExpression<'ast, T>), - MultipleDefinition(Vec>, ZirExpressionList<'ast, T>), + MultipleDefinition(Vec>, ZirExpressionList<'ast, T>), } impl<'ast, T: fmt::Debug> fmt::Debug for ZirStatement<'ast, T> { diff --git a/zokrates_stdlib/stdlib/hashes/sha256/shaRound.zok b/zokrates_stdlib/stdlib/hashes/sha256/shaRound.zok index 00349c3e..725d4ed8 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/shaRound.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/shaRound.zok @@ -85,8 +85,7 @@ def main(u32[16] input, u32[8] current) -> u32[8]: u32[64] w = [...input, ...[0x00000000; 48]] for field i in 16..64 do - u32 r = extend(w, i) - w[i] = r + w[i] = extend(w, i) endfor u32 a = h0 diff --git a/zokrates_stdlib/tests/tests/utils/casts/to_bits.zok b/zokrates_stdlib/tests/tests/utils/casts/to_bits.zok index 9785fcb0..6e445704 100644 --- a/zokrates_stdlib/tests/tests/utils/casts/to_bits.zok +++ b/zokrates_stdlib/tests/tests/utils/casts/to_bits.zok @@ -8,12 +8,9 @@ def main(u32[4] a, u16[4] b, u8[4] c) -> (bool[4][32], bool[4][16], bool[4][8]): bool[4][8] f = [[false; 8]; 4] for field i in 0..4 do - bool[32] g = u32_to_bits(a[i]) - d[i] = g - bool[16] h = u16_to_bits(b[i]) - e[i] = h - bool[8] j = u8_to_bits(c[i]) - f[i] = j + d[i] = u32_to_bits(a[i]) + e[i] = u16_to_bits(b[i]) + f[i] = u8_to_bits(c[i]) endfor return d, e, f \ No newline at end of file