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

Merge branch 'develop' of github.com:Zokrates/ZoKrates into add-magic-square

This commit is contained in:
schaeff 2022-09-02 10:45:29 +02:00
commit 4cef8756fd
39 changed files with 970 additions and 523 deletions

178
Cargo.lock generated
View file

@ -323,7 +323,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8dd4e5f0bf8285d5ed538d27fab7411f3e297908fd93c62195de8bee3f199e82"
dependencies = [
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
]
@ -402,7 +402,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a8c1df849285fbacd587de7818cc7d13be6cd2cbcd47a04fb1801b0e2706e33"
dependencies = [
"proc-macro-error 1.0.4",
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
]
@ -415,9 +415,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.66"
version = "0.3.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61"
dependencies = [
"addr2line",
"cc",
@ -470,9 +470,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitvec"
version = "1.0.1"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
checksum = "1489fcb93a5bb47da0462ca93ad252ad6af2145cce58d10d46a83931ba9f016b"
dependencies = [
"funty",
"radium",
@ -614,9 +614,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
version = "1.2.0"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0b3de4a0c5e67e16066a0715723abd91edc2f9001d09c46e1dca929351e130e"
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
[[package]]
name = "camino"
@ -708,7 +708,7 @@ checksum = "c6dd675567eb3e35787bd2583d129e85fabc7503b0a093d08c51198a307e2091"
dependencies = [
"heck",
"proc-macro-error 0.4.12",
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
]
@ -838,9 +838,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "crypto-common"
version = "0.1.6"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
checksum = "5999502d32b9c48d492abe66392408144895020ec4709e549e840799f3bb74c0"
dependencies = [
"generic-array 0.14.5",
"typenum",
@ -904,7 +904,7 @@ version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
dependencies = [
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
]
@ -1084,7 +1084,7 @@ version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
dependencies = [
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
"synstructure",
@ -1098,9 +1098,9 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "fastrand"
version = "1.8.0"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
dependencies = [
"instant",
]
@ -1126,7 +1126,7 @@ dependencies = [
"num-bigint 0.2.6",
"num-integer",
"num-traits 0.2.15",
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
]
@ -1283,9 +1283,9 @@ dependencies = [
[[package]]
name = "gimli"
version = "0.26.2"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
[[package]]
name = "glob"
@ -1322,9 +1322,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.12.3"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3"
dependencies = [
"ahash",
]
@ -1417,7 +1417,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb"
dependencies = [
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
]
@ -1473,9 +1473,9 @@ checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
[[package]]
name = "js-sys"
version = "0.3.59"
version = "0.3.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2"
checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27"
dependencies = [
"wasm-bindgen",
]
@ -1692,16 +1692,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce"
dependencies = [
"proc-macro-crate",
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
]
[[package]]
name = "object"
version = "0.29.0"
version = "0.28.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424"
dependencies = [
"memchr",
]
@ -1765,7 +1765,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9299338969a3d2f491d65f140b00ddec470858402f888af98e8642fb5e8965cd"
dependencies = [
"proc-macro-crate",
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
]
@ -1816,7 +1816,7 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
dependencies = [
"pest",
"pest_meta",
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
]
@ -1920,7 +1920,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7"
dependencies = [
"proc-macro-error-attr 0.4.12",
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
"version_check",
@ -1933,7 +1933,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr 1.0.4",
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
"version_check",
@ -1945,7 +1945,7 @@ version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de"
dependencies = [
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
"syn-mid",
@ -1958,7 +1958,7 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"version_check",
]
@ -1980,9 +1980,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.42"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b"
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
dependencies = [
"unicode-ident",
]
@ -2013,7 +2013,7 @@ version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
dependencies = [
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
]
[[package]]
@ -2091,9 +2091,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.2.15"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534cfe58d6a18cc17120fbf4635d53d14691c1fe4d951064df9bd326178d7d5a"
checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
dependencies = [
"bitflags",
]
@ -2171,14 +2171,14 @@ dependencies = [
[[package]]
name = "revm"
version = "1.7.0"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "455988f0a9920c91f192268ee31d79fcb980006058514d1e6b543af3d71670f3"
checksum = "b60030444003ac25474f5281e7e91f15e8475c173b729aac1c10aced56b3adac"
dependencies = [
"arrayref",
"auto_impl",
"bytes",
"hashbrown 0.12.3",
"hashbrown 0.12.1",
"num_enum",
"primitive-types",
"revm_precompiles",
@ -2188,9 +2188,9 @@ dependencies = [
[[package]]
name = "revm_precompiles"
version = "1.1.0"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af88e7e9feb30cc4ed64645f09b966e84a1f6be56551ce5f1691105def45705d"
checksum = "cd6aae8f44783ef6ff39fc22c9c999dfa0e17b79d663b752730c02a025935185"
dependencies = [
"bytes",
"num 0.4.0",
@ -2288,18 +2288,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "secp256k1"
version = "0.23.4"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ece73253dd9e1fb540ff324eae554113a31c25fb598d22fd13b088a6a03f90d"
checksum = "26947345339603ae8395f68e2f3d85a6b0a8ddfe6315818e80b8504415099db0"
dependencies = [
"secp256k1-sys",
]
[[package]]
name = "secp256k1-sys"
version = "0.6.0"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7058dc8eaf3f2810d7828680320acda0b25a288f6d288e19278e249bbf74226b"
checksum = "152e20a0fd0519390fc43ab404663af8a0b794273d2a91d60ad4a39f13ffe110"
dependencies = [
"cc",
]
@ -2333,9 +2333,9 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.140"
version = "1.0.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03"
checksum = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47"
dependencies = [
"serde_derive",
]
@ -2352,11 +2352,11 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.140"
version = "1.0.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da"
checksum = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c"
dependencies = [
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
]
@ -2432,9 +2432,9 @@ dependencies = [
[[package]]
name = "single"
version = "1.0.1"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9db45bb685b486eec37e0271dcc0dac76eae5e893125f8a4f0511d0a1d29543b"
checksum = "bd5add732a1ab689845591a1b50339cf5310b563e08dc5813c65991f30369ea2"
dependencies = [
"failure",
]
@ -2456,12 +2456,9 @@ dependencies = [
[[package]]
name = "slab"
version = "0.4.7"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
dependencies = [
"autocfg",
]
checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
[[package]]
name = "solc"
@ -2538,7 +2535,7 @@ version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
dependencies = [
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"unicode-ident",
]
@ -2549,7 +2546,7 @@ version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baa8e7560a164edb1621a55d18a0c59abf49d360f47aa7b821061dd7eea7fac9"
dependencies = [
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
]
@ -2560,7 +2557,7 @@ version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
"unicode-xid 0.2.3",
@ -2629,7 +2626,7 @@ version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
dependencies = [
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
]
@ -2679,7 +2676,7 @@ version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2"
dependencies = [
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
]
@ -2737,9 +2734,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.2"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
[[package]]
name = "unicode-segmentation"
@ -2808,9 +2805,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.82"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d"
checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994"
dependencies = [
"cfg-if 1.0.0",
"serde",
@ -2820,14 +2817,14 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.82"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f"
checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"once_cell",
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
"wasm-bindgen-shared",
@ -2835,9 +2832,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.32"
version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa76fb221a1f8acddf5b54ace85912606980ad661ac7a503b4570ffd3a624dad"
checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f"
dependencies = [
"cfg-if 1.0.0",
"js-sys",
@ -2847,9 +2844,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.82"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602"
checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa"
dependencies = [
"quote 1.0.20",
"wasm-bindgen-macro-support",
@ -2857,11 +2854,11 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.82"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da"
checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048"
dependencies = [
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
"wasm-bindgen-backend",
@ -2870,15 +2867,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.82"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a"
checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be"
[[package]]
name = "wasm-bindgen-test"
version = "0.3.32"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "513df541345bb9fcc07417775f3d51bbb677daf307d8035c0afafd87dc2e6599"
checksum = "68b30cf2cba841a812f035c40c50f53eb9c56181192a9dd2c71b65e6a87a05ba"
dependencies = [
"console_error_panic_hook",
"js-sys",
@ -2890,19 +2887,19 @@ dependencies = [
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.32"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6150d36a03e90a3cf6c12650be10626a9902d70c5270fd47d7a47e5389a10d56"
checksum = "88ad594bf33e73cafcac2ae9062fc119d4f75f9c77e25022f91c9a64bd5b6463"
dependencies = [
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
]
[[package]]
name = "web-sys"
version = "0.3.59"
version = "0.3.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1"
checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90"
dependencies = [
"js-sys",
"wasm-bindgen",
@ -2950,9 +2947,9 @@ dependencies = [
[[package]]
name = "zeroize"
version = "1.5.7"
version = "1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"
checksum = "20b578acffd8516a6c3f2a1bdefc1ec37e547bb4e0fb8b6b01a4cafc886b4442"
dependencies = [
"zeroize_derive",
]
@ -2963,7 +2960,7 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17"
dependencies = [
"proc-macro2 1.0.42",
"proc-macro2 1.0.40",
"quote 1.0.20",
"syn 1.0.98",
"synstructure",
@ -3090,6 +3087,7 @@ dependencies = [
"hex 0.3.2",
"lazy_static",
"log",
"pretty_assertions 1.2.1",
"primitive-types",
"rand 0.4.6",
"rand 0.8.5",

View file

@ -51,5 +51,5 @@ We enforce strict formatting of `.{js,json,ts}` files in CI. This check is not i
```
npm i -g prettier
prettier --write ./**/*.{js,ts,json}
prettier --write "./**/*.{js,ts,json}"
```

View file

@ -0,0 +1 @@
Introduce dead code elimination

View file

@ -0,0 +1 @@
Make return statement optional if no returns are expected

View file

@ -16,13 +16,11 @@ pub enum RuntimeError {
BranchIsolation,
ConstantLtBitness,
ConstantLtSum,
LtBitness,
LtSum,
LtFinalBitness,
LtFinalSum,
LtSymetric,
Or,
Xor,
IncompleteDynamicRange,
Inverse,
Euclidean,
ShaXor,
@ -37,6 +35,10 @@ impl From<crate::zir::RuntimeError> for RuntimeError {
match error {
crate::zir::RuntimeError::SourceAssertion(s) => RuntimeError::SourceAssertion(s),
crate::zir::RuntimeError::SelectRangeCheck => RuntimeError::SelectRangeCheck,
crate::zir::RuntimeError::DivisionByZero => RuntimeError::Inverse,
crate::zir::RuntimeError::IncompleteDynamicRange => {
RuntimeError::IncompleteDynamicRange
}
}
}
}
@ -47,7 +49,11 @@ impl RuntimeError {
!matches!(
self,
SourceAssertion(_) | Inverse | LtSum | SelectRangeCheck | ArgumentBitness
SourceAssertion(_)
| Inverse
| SelectRangeCheck
| ArgumentBitness
| IncompleteDynamicRange
)
}
}
@ -70,13 +76,13 @@ impl fmt::Display for RuntimeError {
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",
IncompleteDynamicRange => {
"Failed to compare field elements because dynamic comparison is incomplete"
}
Inverse => "Division by zero",
Euclidean => "Euclidean check failed",
ShaXor => "Internal Sha check failed",

View file

@ -188,15 +188,6 @@ impl<T: Field> fmt::Display for Prog<T> {
for s in &self.statements {
writeln!(f, "\t{}", s)?;
}
writeln!(
f,
"\treturn {}",
(0..self.return_count)
.map(Variable::public)
.map(|e| format!("{}", e))
.collect::<Vec<_>>()
.join(", ")
)?;
writeln!(f, "\treturn {}", returns)?;
writeln!(f, "}}")

View file

@ -264,6 +264,10 @@ pub trait Folder<'ast, T: Field>: Sized {
fold_statement(self, s)
}
fn fold_definition_rhs(&mut self, rhs: DefinitionRhs<'ast, T>) -> DefinitionRhs<'ast, T> {
fold_definition_rhs(self, rhs)
}
fn fold_embed_call(&mut self, e: EmbedCall<'ast, T>) -> EmbedCall<'ast, T> {
fold_embed_call(self, e)
}
@ -491,6 +495,16 @@ pub fn fold_constant_symbol_declaration<'ast, T: Field, F: Folder<'ast, T>>(
}
}
pub fn fold_definition_rhs<'ast, T: Field, F: Folder<'ast, T>>(
f: &mut F,
rhs: DefinitionRhs<'ast, T>,
) -> DefinitionRhs<'ast, T> {
match rhs {
DefinitionRhs::EmbedCall(c) => DefinitionRhs::EmbedCall(f.fold_embed_call(c)),
DefinitionRhs::Expression(e) => DefinitionRhs::Expression(f.fold_expression(e)),
}
}
pub fn fold_statement<'ast, T: Field, F: Folder<'ast, T>>(
f: &mut F,
s: TypedStatement<'ast, T>,
@ -498,7 +512,7 @@ pub fn fold_statement<'ast, T: Field, F: Folder<'ast, T>>(
let res = match s {
TypedStatement::Return(e) => TypedStatement::Return(f.fold_expression(e)),
TypedStatement::Definition(a, e) => {
TypedStatement::Definition(f.fold_assignee(a), f.fold_expression(e))
TypedStatement::Definition(f.fold_assignee(a), f.fold_definition_rhs(e))
}
TypedStatement::Assertion(e, error) => {
TypedStatement::Assertion(f.fold_boolean_expression(e), error)
@ -515,12 +529,6 @@ pub fn fold_statement<'ast, T: Field, F: Folder<'ast, T>>(
TypedStatement::Log(s, e) => {
TypedStatement::Log(s, e.into_iter().map(|e| f.fold_expression(e)).collect())
}
TypedStatement::EmbedCallDefinition(assignee, embed_call) => {
TypedStatement::EmbedCallDefinition(
f.fold_assignee(assignee),
f.fold_embed_call(embed_call),
)
}
s => s,
};
vec![res]

View file

@ -588,6 +588,7 @@ impl fmt::Display for AssertionMetadata {
pub enum RuntimeError {
SourceAssertion(AssertionMetadata),
SelectRangeCheck,
DivisionByZero,
}
impl fmt::Display for RuntimeError {
@ -595,6 +596,7 @@ impl fmt::Display for RuntimeError {
match self {
RuntimeError::SourceAssertion(metadata) => write!(f, "{}", metadata),
RuntimeError::SelectRangeCheck => write!(f, "Range check on array access"),
RuntimeError::DivisionByZero => write!(f, "Division by zero"),
}
}
}
@ -646,12 +648,39 @@ impl<'ast, T: fmt::Display> fmt::Display for EmbedCall<'ast, T> {
}
}
#[derive(Clone, PartialEq, Debug, Hash, Eq, PartialOrd, Ord)]
pub enum DefinitionRhs<'ast, T> {
Expression(TypedExpression<'ast, T>),
EmbedCall(EmbedCall<'ast, T>),
}
impl<'ast, T> From<TypedExpression<'ast, T>> for DefinitionRhs<'ast, T> {
fn from(e: TypedExpression<'ast, T>) -> Self {
Self::Expression(e)
}
}
impl<'ast, T> From<EmbedCall<'ast, T>> for DefinitionRhs<'ast, T> {
fn from(c: EmbedCall<'ast, T>) -> Self {
Self::EmbedCall(c)
}
}
impl<'ast, T: fmt::Display> fmt::Display for DefinitionRhs<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
DefinitionRhs::EmbedCall(c) => write!(f, "{}", c),
DefinitionRhs::Expression(e) => write!(f, "{}", e),
}
}
}
/// A statement in a `TypedFunction`
#[allow(clippy::large_enum_variant)]
#[derive(Clone, PartialEq, Debug, Hash, Eq, PartialOrd, Ord)]
pub enum TypedStatement<'ast, T> {
Return(TypedExpression<'ast, T>),
Definition(TypedAssignee<'ast, T>, TypedExpression<'ast, T>),
Definition(TypedAssignee<'ast, T>, DefinitionRhs<'ast, T>),
Assertion(BooleanExpression<'ast, T>, RuntimeError),
For(
Variable<'ast, T>,
@ -660,7 +689,6 @@ pub enum TypedStatement<'ast, T> {
Vec<TypedStatement<'ast, T>>,
),
Log(FormatString, Vec<TypedExpression<'ast, T>>),
EmbedCallDefinition(TypedAssignee<'ast, T>, EmbedCall<'ast, T>),
// Aux
PushCallLog(
DeclarationFunctionKey<'ast, T>,
@ -669,6 +697,16 @@ pub enum TypedStatement<'ast, T> {
PopCallLog,
}
impl<'ast, T> TypedStatement<'ast, T> {
pub fn definition(a: TypedAssignee<'ast, T>, e: TypedExpression<'ast, T>) -> Self {
Self::Definition(a, e.into())
}
pub fn embed_call_definition(a: TypedAssignee<'ast, T>, c: EmbedCall<'ast, T>) -> Self {
Self::Definition(a, c.into())
}
}
impl<'ast, T: fmt::Display> TypedStatement<'ast, T> {
fn fmt_indented(&self, f: &mut fmt::Formatter, depth: usize) -> fmt::Result {
match self {
@ -710,9 +748,6 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedStatement<'ast, T> {
}
write!(f, "\t}}")
}
TypedStatement::EmbedCallDefinition(ref lhs, ref rhs) => {
write!(f, "{} = {};", lhs, rhs)
}
TypedStatement::Log(ref l, ref expressions) => write!(
f,
"log({}, {})",
@ -752,6 +787,12 @@ pub enum TypedExpression<'ast, T> {
Int(IntExpression<'ast, T>),
}
impl<'ast, T> TypedExpression<'ast, T> {
pub fn empty_tuple() -> TypedExpression<'ast, T> {
TypedExpression::Tuple(TupleExpressionInner::Value(vec![]).annotate(TupleType::new(vec![])))
}
}
impl<'ast, T> From<BooleanExpression<'ast, T>> for TypedExpression<'ast, T> {
fn from(e: BooleanExpression<'ast, T>) -> TypedExpression<T> {
TypedExpression::Boolean(e)
@ -909,7 +950,7 @@ impl<E> EqExpression<E> {
impl<E: fmt::Display> fmt::Display for EqExpression<E> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} == {}", self.left, self.right)
write!(f, "({} == {})", self.left, self.right)
}
}
@ -1659,22 +1700,22 @@ impl<'ast, T: fmt::Display> fmt::Display for BooleanExpression<'ast, T> {
match *self {
BooleanExpression::Block(ref block) => write!(f, "{}", block,),
BooleanExpression::Identifier(ref var) => write!(f, "{}", var),
BooleanExpression::FieldLt(ref lhs, ref rhs) => write!(f, "{} < {}", lhs, rhs),
BooleanExpression::FieldLe(ref lhs, ref rhs) => write!(f, "{} <= {}", lhs, rhs),
BooleanExpression::FieldGe(ref lhs, ref rhs) => write!(f, "{} >= {}", lhs, rhs),
BooleanExpression::FieldGt(ref lhs, ref rhs) => write!(f, "{} > {}", lhs, rhs),
BooleanExpression::UintLt(ref lhs, ref rhs) => write!(f, "{} < {}", lhs, rhs),
BooleanExpression::UintLe(ref lhs, ref rhs) => write!(f, "{} <= {}", lhs, rhs),
BooleanExpression::UintGe(ref lhs, ref rhs) => write!(f, "{} >= {}", lhs, rhs),
BooleanExpression::UintGt(ref lhs, ref rhs) => write!(f, "{} > {}", lhs, rhs),
BooleanExpression::FieldLt(ref lhs, ref rhs) => write!(f, "({} < {})", lhs, rhs),
BooleanExpression::FieldLe(ref lhs, ref rhs) => write!(f, "({} <= {})", lhs, rhs),
BooleanExpression::FieldGe(ref lhs, ref rhs) => write!(f, "({} >= {})", lhs, rhs),
BooleanExpression::FieldGt(ref lhs, ref rhs) => write!(f, "({} > {})", lhs, rhs),
BooleanExpression::UintLt(ref lhs, ref rhs) => write!(f, "({} < {})", lhs, rhs),
BooleanExpression::UintLe(ref lhs, ref rhs) => write!(f, "({} <= {})", lhs, rhs),
BooleanExpression::UintGe(ref lhs, ref rhs) => write!(f, "({} >= {})", lhs, rhs),
BooleanExpression::UintGt(ref lhs, ref rhs) => write!(f, "({} > {})", lhs, rhs),
BooleanExpression::FieldEq(ref e) => write!(f, "{}", e),
BooleanExpression::BoolEq(ref e) => write!(f, "{}", e),
BooleanExpression::ArrayEq(ref e) => write!(f, "{}", e),
BooleanExpression::StructEq(ref e) => write!(f, "{}", e),
BooleanExpression::TupleEq(ref e) => write!(f, "{}", e),
BooleanExpression::UintEq(ref e) => write!(f, "{}", e),
BooleanExpression::Or(ref lhs, ref rhs) => write!(f, "{} || {}", lhs, rhs),
BooleanExpression::And(ref lhs, ref rhs) => write!(f, "{} && {}", lhs, rhs),
BooleanExpression::Or(ref lhs, ref rhs) => write!(f, "({} || {})", lhs, rhs),
BooleanExpression::And(ref lhs, ref rhs) => write!(f, "({} && {})", lhs, rhs),
BooleanExpression::Not(ref exp) => write!(f, "!{}", exp),
BooleanExpression::Value(b) => write!(f, "{}", b),
BooleanExpression::FunctionCall(ref function_call) => write!(f, "{}", function_call),

View file

@ -385,6 +385,13 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
fold_statement(self, s)
}
fn fold_definition_rhs(
&mut self,
rhs: DefinitionRhs<'ast, T>,
) -> Result<DefinitionRhs<'ast, T>, Self::Error> {
fold_definition_rhs(self, rhs)
}
fn fold_embed_call(
&mut self,
e: EmbedCall<'ast, T>,
@ -508,7 +515,7 @@ pub fn fold_statement<'ast, T: Field, F: ResultFolder<'ast, T>>(
let res = match s {
TypedStatement::Return(e) => TypedStatement::Return(f.fold_expression(e)?),
TypedStatement::Definition(a, e) => {
TypedStatement::Definition(f.fold_assignee(a)?, f.fold_expression(e)?)
TypedStatement::Definition(f.fold_assignee(a)?, f.fold_definition_rhs(e)?)
}
TypedStatement::Assertion(e, error) => {
TypedStatement::Assertion(f.fold_boolean_expression(e)?, error)
@ -531,17 +538,21 @@ pub fn fold_statement<'ast, T: Field, F: ResultFolder<'ast, T>>(
.map(|e| f.fold_expression(e))
.collect::<Result<Vec<_>, _>>()?,
),
TypedStatement::EmbedCallDefinition(assignee, embed_call) => {
TypedStatement::EmbedCallDefinition(
f.fold_assignee(assignee)?,
f.fold_embed_call(embed_call)?,
)
}
s => s,
};
Ok(vec![res])
}
pub fn fold_definition_rhs<'ast, T: Field, F: ResultFolder<'ast, T>>(
f: &mut F,
rhs: DefinitionRhs<'ast, T>,
) -> Result<DefinitionRhs<'ast, T>, F::Error> {
Ok(match rhs {
DefinitionRhs::EmbedCall(c) => DefinitionRhs::EmbedCall(f.fold_embed_call(c)?),
DefinitionRhs::Expression(e) => DefinitionRhs::Expression(f.fold_expression(e)?),
})
}
pub fn fold_embed_call<'ast, T: Field, F: ResultFolder<'ast, T>>(
f: &mut F,
e: EmbedCall<'ast, T>,

View file

@ -895,6 +895,10 @@ impl<S> GType<S> {
pub fn uint<W: Into<UBitwidth>>(b: W) -> Self {
GType::Uint(b.into())
}
pub fn is_empty_tuple(&self) -> bool {
matches!(self, GType::Tuple(ty) if ty.elements.is_empty())
}
}
impl<'ast, T: fmt::Display + PartialEq + fmt::Debug> Type<'ast, T> {

View file

@ -92,6 +92,8 @@ pub type ZirAssignee<'ast> = Variable<'ast>;
pub enum RuntimeError {
SourceAssertion(String),
SelectRangeCheck,
DivisionByZero,
IncompleteDynamicRange,
}
impl fmt::Display for RuntimeError {
@ -99,6 +101,8 @@ impl fmt::Display for RuntimeError {
match self {
RuntimeError::SourceAssertion(message) => write!(f, "{}", message),
RuntimeError::SelectRangeCheck => write!(f, "Range check on array access"),
RuntimeError::DivisionByZero => write!(f, "Division by zero"),
RuntimeError::IncompleteDynamicRange => write!(f, "Dynamic comparison is incomplete"),
}
}
}
@ -716,7 +720,6 @@ impl<'ast, T> Conditional<'ast, T> for UExpression<'ast, T> {
.annotate(bitwidth)
}
}
pub trait Select<'ast, T>: Sized {
fn select(array: Vec<Self>, index: UExpression<'ast, T>) -> Self;
}
@ -745,7 +748,6 @@ impl<'ast, T> Select<'ast, T> for UExpression<'ast, T> {
UExpressionInner::Select(SelectExpression::new(array, index)).annotate(bitwidth)
}
}
pub trait IntoType {
fn into_type(self) -> Type;
}

View file

@ -1,13 +1,15 @@
## Functions
Functions are declared using the `def` keyword. A function's signature has to be explicitly provided.
Its arguments are type annotated, just like variables, and, if the function returns a value,
the return type must be specified after an arrow `->`.
A function has to be declared at the top level before it is called.
```zokrates
{{#include ../../../zokrates_cli/examples/book/function_declaration.zok}}
```
A function's signature has to be explicitly provided.
A function can be generic over any number of values of type `u32`.
```zokrates
@ -18,4 +20,10 @@ The generic parameters can be provided explicitly, especially when they cannot b
```zokrates
{{#include ../../../zokrates_cli/examples/book/explicit_generic_parameters.zok}}
```
If the return type of a function is the empty tuple `()`, the return type as well as the return statement can be omitted.
```zokrates
{{#include ../../../zokrates_cli/examples/book/no_return.zok}}
```

View file

@ -50,6 +50,7 @@ zokrates_solidity_test = { version = "0.1", path = "../zokrates_solidity_test",
ethabi = "17.0.0"
primitive-types = { version = "0.11", features = ["rlp"] }
fs_extra = "1.1.0"
pretty_assertions = "1.2.1"
[build-dependencies]
fs_extra = "1.1.0"

View file

@ -0,0 +1 @@
def main() {}

View file

@ -1,5 +1 @@
def foo() {}
def main() {
return;
}
def main() -> field {}

View file

@ -4,9 +4,10 @@ from "field" import FIELD_SIZE_IN_BITS;
// It should not work for the maxvalue = 2^(pbits - 2) - 1 augmented by one
// /!\ should be called with a = 0
def main(field a) -> bool {
def main(field a) {
u32 pbits = FIELD_SIZE_IN_BITS;
// we added a = 0 to prevent the condition to be evaluated at compile time
field maxvalue = a + (2**(pbits - 2) - 1);
return a < maxvalue + 1;
bool c = a < maxvalue + 1;
return;
}

View file

@ -4,9 +4,10 @@ from "field" import FIELD_SIZE_IN_BITS;
// It should not work for the maxvalue = 2^(pbits - 2) - 1 augmented by one
// /!\ should be called with a = 0
def main(field a) -> bool {
def main(field a) {
u32 pbits = FIELD_SIZE_IN_BITS;
// we added a = 0 to prevent the condition to be evaluated at compile time
field maxvalue = a + (2**(pbits - 2) - 1);
return maxvalue + 1 < a;
bool c = maxvalue + 1 < a;
return;
}

View file

@ -523,7 +523,7 @@
(= (mod (* (+ (* |~one| 14651237294507013008273219182214280847718990358813499091232105186081237893121) (* |_0| 1) (* |_1| 21888242871839275222246405745257275088548364400416034343698204186575808495616)) (* |_258| 1)) |~prime|) (mod (* |_257| 1) |~prime|))
(= (mod (* (+ (* |~one| 1) (* |_257| 21888242871839275222246405745257275088548364400416034343698204186575808495616)) (+ (* |~one| 14651237294507013008273219182214280847718990358813499091232105186081237893121) (* |_0| 1) (* |_1| 21888242871839275222246405745257275088548364400416034343698204186575808495616))) |~prime|) (mod 0 |~prime|))
(= (mod (* (* |~one| 1) 0) |~prime|) (mod (+ (* |~one| 1) (* |_257| 21888242871839275222246405745257275088548364400416034343698204186575808495616)) |~prime|))
(= (mod (* (* |~one| 1) (* |~one| 1)) |~prime|) (mod (* |_257| 1) |~prime|))
(= (mod (* (* |_2| 1) (+ (* |_0| 21888242871839275222246405745257275088548364400416034343698204186575808495616) (* |_1| 1))) |~prime|) (mod (* |_264| 1) |~prime|))
(= (mod (* (* |~one| 1) (* |_264| 1)) |~prime|) (mod (* |~out_0| 1) |~prime|))
))

View file

@ -10,6 +10,7 @@ extern crate zokrates_solidity_test;
mod integration {
use fs_extra::copy_items;
use fs_extra::dir::CopyOptions;
use pretty_assertions::assert_eq;
use primitive_types::U256;
use serde_json::from_reader;
use std::fs;
@ -452,6 +453,8 @@ mod integration {
program_path: &Path,
expected_smtlib2_path: &Path,
) {
println!("test smtlib2 for {}", program_path.display());
let tmp_dir = TempDir::new(program_name).unwrap();
let tmp_base = tmp_dir.path();
let test_case_path = tmp_base.join(program_name);

View file

@ -280,9 +280,29 @@ impl<'ast, T: Field> Flattener<'ast, T> {
a: &[FlatExpression<T>],
b: &[bool],
) -> Vec<FlatExpression<T>> {
let len = b.len();
assert_eq!(a.len(), b.len());
let is_power_of_two_minus_one = b.iter().all(|b| *b);
// if `b` is all ones, then the check is always verified because that's the maximum possible value
if is_power_of_two_minus_one {
let statements: Vec<_> = a
.iter()
.map(|e| {
let e_id = self.define(e.clone(), statements_flattened);
FlatStatement::Condition(
e_id.into(),
FlatExpression::Mult(box e_id.into(), box e_id.into()),
RuntimeError::Bitness,
)
})
.collect();
statements_flattened.extend(statements);
return vec![];
}
let len = b.len();
let mut is_not_smaller_run = vec![];
let mut size_unknown = vec![];
@ -778,66 +798,17 @@ impl<'ast, T: Field> Flattener<'ast, T> {
let sub_width = bit_width + 1;
// define variables for the bits
let shifted_sub_bits_be: Vec<Variable> =
(0..sub_width).map(|_| self.use_sym()).collect();
// add a directive to get the bits
statements_flattened.push_back(FlatStatement::Directive(FlatDirective::new(
shifted_sub_bits_be.clone(),
Solver::bits(sub_width),
vec![shifted_sub.clone()],
)));
// bitness checks
for bit in shifted_sub_bits_be.iter() {
statements_flattened.push_back(FlatStatement::Condition(
FlatExpression::Identifier(*bit),
FlatExpression::Mult(
box FlatExpression::Identifier(*bit),
box FlatExpression::Identifier(*bit),
),
RuntimeError::LtFinalBitness,
));
}
// sum(sym_b{i} * 2**i)
let mut expr = FlatExpression::Number(T::from(0));
for (i, bit) in shifted_sub_bits_be.iter().take(sub_width).enumerate() {
expr = FlatExpression::Add(
box expr,
box FlatExpression::Mult(
box FlatExpression::Identifier(*bit),
box FlatExpression::Number(T::from(2).pow(sub_width - i - 1)),
),
);
}
statements_flattened.push_back(FlatStatement::Condition(
shifted_sub,
expr,
RuntimeError::LtFinalSum,
));
// to make this check symetric, we ban the value `a - b == -2**N`, as the value `a - b == 2**N` is already banned
let fail = self.eq_check(
let shifted_sub_bits_be = self.get_bits_unchecked(
&FlatUExpression::with_field(shifted_sub),
sub_width,
sub_width,
statements_flattened,
FlatExpression::Sub(
box FlatExpression::Identifier(rhs_id),
box FlatExpression::Identifier(lhs_id),
),
FlatExpression::Number(T::from(2).pow(bit_width)),
RuntimeError::IncompleteDynamicRange,
);
statements_flattened.push_back(FlatStatement::Condition(
fail,
FlatExpression::Number(T::from(0)),
RuntimeError::LtSymetric,
));
FlatExpression::Sub(
box FlatExpression::Number(T::one()),
box FlatExpression::Identifier(shifted_sub_bits_be[0]),
box shifted_sub_bits_be[0].clone(),
)
}
}
@ -1351,24 +1322,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
FlatExpression::Identifier(id)
};
// first check that the d is not 0 by giving its inverse
let invd = self.use_sym();
// # invd = 1/d
statements_flattened.push_back(FlatStatement::Directive(FlatDirective::new(
vec![invd],
Solver::Div,
vec![FlatExpression::Number(T::one()), d.clone()],
)));
// assert(invd * d == 1)
statements_flattened.push_back(FlatStatement::Condition(
FlatExpression::Number(T::one()),
FlatExpression::Mult(box invd.into(), box d.clone()),
RuntimeError::Inverse,
));
// now introduce the quotient and remainder
// introduce the quotient and remainder
let q = self.use_sym();
let r = self.use_sym();
@ -2163,23 +2117,11 @@ impl<'ast, T: Field> Flattener<'ast, T> {
id.into()
};
let invb = self.use_sym();
// `right` is assumed to already be non-zero so this is an unchecked division
// TODO: we could save one constraint here by reusing the inverse of `right` computed earlier
let inverse = self.use_sym();
// # invb = 1/b
statements_flattened.push_back(FlatStatement::Directive(FlatDirective::new(
vec![invb],
Solver::Div,
vec![FlatExpression::Number(T::one()), new_right.clone()],
)));
// assert(invb * b == 1)
statements_flattened.push_back(FlatStatement::Condition(
FlatExpression::Number(T::one()),
FlatExpression::Mult(box invb.into(), box new_right.clone()),
RuntimeError::Inverse,
));
// # c = a/b
statements_flattened.push_back(FlatStatement::Directive(FlatDirective::new(
vec![inverse],
@ -2458,6 +2400,40 @@ impl<'ast, T: Field> Flattener<'ast, T> {
}
}
}
BooleanExpression::UintLe(box lhs, box rhs) => {
let lhs = self
.flatten_uint_expression(statements_flattened, lhs)
.get_field_unchecked();
let rhs = self
.flatten_uint_expression(statements_flattened, rhs)
.get_field_unchecked();
match (lhs, rhs) {
(e, FlatExpression::Number(c)) => self.enforce_constant_le_check(
statements_flattened,
e,
c,
error.into(),
),
// c <= e <=> p - 1 - e <= p - 1 - c
(FlatExpression::Number(c), e) => self.enforce_constant_le_check(
statements_flattened,
FlatExpression::Sub(box T::max_value().into(), box e),
T::max_value() - c,
error.into(),
),
(lhs, rhs) => {
let bit_width = T::get_required_bits();
let safe_width = bit_width - 2; // dynamic comparison is not complete
let e = self.le_check(statements_flattened, lhs, rhs, safe_width);
statements_flattened.push_back(FlatStatement::Condition(
e,
FlatExpression::Number(T::one()),
error.into(),
));
}
}
}
BooleanExpression::UintEq(box lhs, box rhs) => {
let lhs = self
.flatten_uint_expression(statements_flattened, lhs)
@ -2484,6 +2460,80 @@ impl<'ast, T: Field> Flattener<'ast, T> {
error.into(),
)
}
// `!(x == 0)` can be asserted by giving the inverse of `x`
BooleanExpression::Not(box BooleanExpression::UintEq(
box UExpression {
inner: UExpressionInner::Value(0),
..
},
box x,
))
| BooleanExpression::Not(box BooleanExpression::UintEq(
box x,
box UExpression {
inner: UExpressionInner::Value(0),
..
},
)) => {
let x = self
.flatten_uint_expression(statements_flattened, x)
.get_field_unchecked();
// introduce intermediate variable
let x_id = self.define(x, statements_flattened);
// check that `x` is not 0 by giving its inverse
let invx = self.use_sym();
// # invx = 1/x
statements_flattened.push_back(FlatStatement::Directive(
FlatDirective::new(
vec![invx],
Solver::Div,
vec![FlatExpression::Number(T::one()), x_id.into()],
),
));
// assert(invx * x == 1)
statements_flattened.push_back(FlatStatement::Condition(
FlatExpression::Number(T::one()),
FlatExpression::Mult(box invx.into(), box x_id.into()),
RuntimeError::Inverse,
));
}
// `!(x == 0)` can be asserted by giving the inverse of `x`
BooleanExpression::Not(box BooleanExpression::FieldEq(
box FieldElementExpression::Number(zero),
box x,
))
| BooleanExpression::Not(box BooleanExpression::FieldEq(
box x,
box FieldElementExpression::Number(zero),
)) if zero == T::from(0) => {
let x = self.flatten_field_expression(statements_flattened, x);
// introduce intermediate variable
let x_id = self.define(x, statements_flattened);
// check that `x` is not 0 by giving its inverse
let invx = self.use_sym();
// # invx = 1/x
statements_flattened.push_back(FlatStatement::Directive(
FlatDirective::new(
vec![invx],
Solver::Div,
vec![FlatExpression::Number(T::one()), x_id.into()],
),
));
// assert(invx * x == 1)
statements_flattened.push_back(FlatStatement::Condition(
FlatExpression::Number(T::one()),
FlatExpression::Mult(box invx.into(), box x_id.into()),
RuntimeError::Inverse,
));
}
e => {
// naive approach: flatten the boolean to a single field element and constrain it to 1
let e = self.flatten_boolean_expression(statements_flattened, e);
@ -3580,18 +3630,14 @@ mod tests {
// define new wires for members of Div
let five = Variable::new(1);
let b0 = Variable::new(2);
// Define inverse of denominator to prevent div by 0
let invb0 = Variable::new(3);
// Define inverse
let sym_0 = Variable::new(4);
let sym_0 = Variable::new(3);
// Define result, which is first member to next Div
let sym_1 = Variable::new(5);
let sym_1 = Variable::new(4);
// Define second member
let b1 = Variable::new(6);
// Define inverse of denominator to prevent div by 0
let invb1 = Variable::new(7);
let b1 = Variable::new(5);
// Define inverse
let sym_2 = Variable::new(8);
let sym_2 = Variable::new(6);
assert_eq!(
statements_flattened,
@ -3600,17 +3646,6 @@ mod tests {
// inputs to first div (5/b)
FlatStatement::Definition(five, FlatExpression::Number(Bn128Field::from(5))),
FlatStatement::Definition(b0, b.into()),
// check div by 0
FlatStatement::Directive(FlatDirective::new(
vec![invb0],
Solver::Div,
vec![FlatExpression::Number(Bn128Field::from(1)), b0.into()]
)),
FlatStatement::Condition(
FlatExpression::Number(Bn128Field::from(1)),
FlatExpression::Mult(box invb0.into(), box b0.into()),
RuntimeError::Inverse,
),
// execute div
FlatStatement::Directive(FlatDirective::new(
vec![sym_0],
@ -3625,17 +3660,6 @@ mod tests {
// inputs to second div (res/b)
FlatStatement::Definition(sym_1, sym_0.into()),
FlatStatement::Definition(b1, b.into()),
// check div by 0
FlatStatement::Directive(FlatDirective::new(
vec![invb1],
Solver::Div,
vec![FlatExpression::Number(Bn128Field::from(1)), b1.into()]
)),
FlatStatement::Condition(
FlatExpression::Number(Bn128Field::from(1)),
FlatExpression::Mult(box invb1.into(), box b1.into()),
RuntimeError::Inverse
),
// execute div
FlatStatement::Directive(FlatDirective::new(
vec![sym_2],

View file

@ -1204,10 +1204,16 @@ impl<'ast, T: Field> Checker<'ast, T> {
}
if !found_return {
errors.push(ErrorInner {
pos: Some(pos),
message: "Expected a return statement".to_string(),
});
match (&*s.output).is_empty_tuple() {
true => statements_checked
.push(TypedStatement::Return(TypedExpression::empty_tuple())),
false => {
errors.push(ErrorInner {
pos: Some(pos),
message: "Expected a return statement".to_string(),
});
}
}
}
signature = Some(s);
@ -1843,11 +1849,7 @@ impl<'ast, T: Field> Checker<'ast, T> {
}
.map_err(|e| vec![e])
})
.unwrap_or_else(|| {
Ok(TupleExpressionInner::Value(vec![])
.annotate(TupleType::new(vec![]))
.into())
})?;
.unwrap_or_else(|| Ok(TypedExpression::empty_tuple()))?;
let res = match TypedExpression::align_to_type(e_checked.clone(), &return_type)
.map_err(|e| {
@ -1939,7 +1941,7 @@ impl<'ast, T: Field> Checker<'ast, T> {
var_ty
),
})
.map(|e| TypedStatement::Definition(var.into(), e))
.map(|e| TypedStatement::Definition(var.into(), e.into()))
.map_err(|e| vec![e])
}
Statement::Assignment(assignee, expr) => {
@ -1986,7 +1988,7 @@ impl<'ast, T: Field> Checker<'ast, T> {
assignee_ty
),
})
.map(|e| TypedStatement::Definition(assignee, e))
.map(|e| TypedStatement::Definition(assignee, e.into()))
.map_err(|e| vec![e])
}
Statement::Assertion(e, message) => {
@ -4483,7 +4485,7 @@ mod tests {
checker.enter_scope();
assert_eq!(
checker.check_statement(statement, &*MODULE_ID, &TypeMap::new()),
Ok(TypedStatement::Definition(
Ok(TypedStatement::definition(
typed::Variable::field_element("a").into(),
FieldElementExpression::Identifier("b".into()).into()
))
@ -4712,7 +4714,7 @@ mod tests {
Statement::Return(None).mock(),
];
let for_statements_checked = vec![TypedStatement::Definition(
let for_statements_checked = vec![TypedStatement::definition(
typed::Variable::uint(
CoreIdentifier::Source(ShadowedIdentifier::shadow("a", 1)),
UBitwidth::B32,
@ -4735,11 +4737,7 @@ mod tests {
10u32.into(),
for_statements_checked,
),
TypedStatement::Return(
TupleExpressionInner::Value(vec![])
.annotate(TupleType::new(vec![]))
.into(),
),
TypedStatement::Return(TypedExpression::empty_tuple()),
];
let foo = Function {
@ -5334,7 +5332,7 @@ mod tests {
];
let expected = vec![
TypedStatement::Definition(
TypedStatement::definition(
typed::Variable::new(
CoreIdentifier::from(ShadowedIdentifier::shadow("a", 0)),
Type::FieldElement,
@ -5352,7 +5350,7 @@ mod tests {
0u32.into(),
0u32.into(),
vec![
TypedStatement::Definition(
TypedStatement::definition(
typed::Variable::new(
CoreIdentifier::from(ShadowedIdentifier::shadow("a", 0)),
Type::FieldElement,
@ -5361,7 +5359,7 @@ mod tests {
.into(),
FieldElementExpression::Number(3.into()).into(),
),
TypedStatement::Definition(
TypedStatement::definition(
typed::Variable::new(
CoreIdentifier::from(ShadowedIdentifier::shadow("a", 1)),
Type::FieldElement,
@ -5372,7 +5370,7 @@ mod tests {
),
],
),
TypedStatement::Definition(
TypedStatement::definition(
typed::Variable::new(
CoreIdentifier::from(ShadowedIdentifier::shadow("a", 0)),
Type::FieldElement,

View file

@ -1,7 +1,7 @@
use zokrates_ast::typed::{
folder::*, BlockExpression, BooleanExpression, Conditional, ConditionalExpression,
ConditionalOrExpression, CoreIdentifier, Expr, Identifier, Type, TypedProgram, TypedStatement,
Variable,
ConditionalOrExpression, CoreIdentifier, Expr, Identifier, Type, TypedExpression, TypedProgram,
TypedStatement, Variable,
};
use zokrates_field::Field;
@ -65,9 +65,9 @@ impl<'ast, T: Field> Folder<'ast, T> for ConditionRedefiner<'ast, T> {
| condition @ BooleanExpression::Identifier(_) => condition,
condition => {
let condition_id = Identifier::from(CoreIdentifier::Condition(self.index));
self.buffer.push(TypedStatement::Definition(
self.buffer.push(TypedStatement::definition(
Variable::immutable(condition_id.clone(), Type::Boolean).into(),
condition.into(),
TypedExpression::from(condition),
));
self.index += 1;
BooleanExpression::Identifier(condition_id)
@ -99,7 +99,7 @@ mod tests {
// field foo = if true { 1 } else { 2 };
// should be left unchanged
let s = TypedStatement::Definition(
let s = TypedStatement::definition(
Variable::field_element("foo").into(),
FieldElementExpression::conditional(
BooleanExpression::Value(true),
@ -120,7 +120,7 @@ mod tests {
// field foo = if c { 1 } else { 2 };
// should be left unchanged
let s = TypedStatement::Definition(
let s = TypedStatement::definition(
Variable::field_element("foo").into(),
FieldElementExpression::conditional(
BooleanExpression::Identifier("c".into()),
@ -148,7 +148,7 @@ mod tests {
box BooleanExpression::Identifier("d".into()),
);
let s = TypedStatement::Definition(
let s = TypedStatement::definition(
Variable::field_element("foo").into(),
FieldElementExpression::conditional(
condition.clone(),
@ -163,12 +163,12 @@ mod tests {
let expected = vec![
// define condition
TypedStatement::Definition(
TypedStatement::definition(
Variable::immutable(CoreIdentifier::Condition(0), Type::Boolean).into(),
condition.into(),
),
// rewrite statement
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element("foo").into(),
FieldElementExpression::conditional(
BooleanExpression::Identifier(CoreIdentifier::Condition(0).into()),
@ -212,7 +212,7 @@ mod tests {
box BooleanExpression::Identifier("f".into()),
);
let s = TypedStatement::Definition(
let s = TypedStatement::definition(
Variable::field_element("foo").into(),
FieldElementExpression::conditional(
condition_0.clone(),
@ -232,16 +232,16 @@ mod tests {
let expected = vec![
// define conditions
TypedStatement::Definition(
TypedStatement::definition(
Variable::immutable(CoreIdentifier::Condition(0), Type::Boolean).into(),
condition_0.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::immutable(CoreIdentifier::Condition(1), Type::Boolean).into(),
condition_1.into(),
),
// rewrite statement
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element("foo").into(),
FieldElementExpression::conditional(
BooleanExpression::Identifier(CoreIdentifier::Condition(0).into()),
@ -303,12 +303,12 @@ mod tests {
let condition_id_1 = BooleanExpression::Identifier(CoreIdentifier::Condition(1).into());
let condition_id_2 = BooleanExpression::Identifier(CoreIdentifier::Condition(2).into());
let s = TypedStatement::Definition(
let s = TypedStatement::definition(
Variable::field_element("foo").into(),
FieldElementExpression::conditional(
condition_0.clone(),
FieldElementExpression::block(
vec![TypedStatement::Definition(
vec![TypedStatement::definition(
Variable::field_element("a").into(),
FieldElementExpression::Number(Bn128Field::from(1)).into(),
)],
@ -320,7 +320,7 @@ mod tests {
),
),
FieldElementExpression::block(
vec![TypedStatement::Definition(
vec![TypedStatement::definition(
Variable::field_element("b").into(),
FieldElementExpression::Number(Bn128Field::from(2)).into(),
)],
@ -340,22 +340,22 @@ mod tests {
let expected = vec![
// define conditions
TypedStatement::Definition(
TypedStatement::definition(
Variable::immutable(CoreIdentifier::Condition(0), Type::Boolean).into(),
condition_0.into(),
),
// rewrite statement
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element("foo").into(),
FieldElementExpression::conditional(
condition_id_0.clone(),
FieldElementExpression::block(
vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element("a").into(),
FieldElementExpression::Number(Bn128Field::from(1)).into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::immutable(CoreIdentifier::Condition(1), Type::Boolean)
.into(),
condition_1.into(),
@ -370,11 +370,11 @@ mod tests {
),
FieldElementExpression::block(
vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element("b").into(),
FieldElementExpression::Number(Bn128Field::from(2)).into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::immutable(CoreIdentifier::Condition(2), Type::Boolean)
.into(),
condition_2.into(),

View file

@ -1,11 +1,11 @@
use std::fmt;
use zokrates_ast::common::FlatEmbed;
use zokrates_ast::typed::TypedProgram;
use zokrates_ast::typed::{
result_folder::ResultFolder,
result_folder::{fold_statement, fold_uint_expression_inner},
Constant, EmbedCall, TypedStatement, UBitwidth, UExpressionInner,
};
use zokrates_ast::typed::{DefinitionRhs, TypedProgram};
use zokrates_field::Field;
pub struct ConstantArgumentChecker;
@ -33,37 +33,41 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ConstantArgumentChecker {
s: TypedStatement<'ast, T>,
) -> Result<Vec<TypedStatement<'ast, T>>, Self::Error> {
match s {
TypedStatement::EmbedCallDefinition(assignee, embed_call) => match embed_call {
EmbedCall {
embed: FlatEmbed::BitArrayLe,
..
} => {
let arguments = embed_call
.arguments
.into_iter()
.map(|a| self.fold_expression(a))
.collect::<Result<Vec<_>, _>>()?;
TypedStatement::Definition(assignee, DefinitionRhs::EmbedCall(embed_call)) => {
match embed_call {
EmbedCall {
embed: FlatEmbed::BitArrayLe,
..
} => {
let arguments = embed_call
.arguments
.into_iter()
.map(|a| self.fold_expression(a))
.collect::<Result<Vec<_>, _>>()?;
if arguments[1].is_constant() {
Ok(vec![TypedStatement::EmbedCallDefinition(
assignee,
EmbedCall {
embed: FlatEmbed::BitArrayLe,
generics: embed_call.generics,
arguments,
},
)])
} else {
Err(Error(format!(
"Cannot compare to a variable value, found `{}`",
arguments[1]
)))
if arguments[1].is_constant() {
Ok(vec![TypedStatement::Definition(
assignee,
EmbedCall {
embed: FlatEmbed::BitArrayLe,
generics: embed_call.generics,
arguments,
}
.into(),
)])
} else {
Err(Error(format!(
"Cannot compare to a variable value, found `{}`",
arguments[1]
)))
}
}
embed_call => Ok(vec![TypedStatement::Definition(
assignee,
embed_call.into(),
)]),
}
embed_call => Ok(vec![TypedStatement::EmbedCallDefinition(
assignee, embed_call,
)]),
},
}
s => fold_statement(self, s),
}
}

View file

@ -0,0 +1,68 @@
use std::collections::HashSet;
use zokrates_ast::zir::{folder::*, Identifier, ZirFunction, ZirProgram, ZirStatement};
use zokrates_field::Field;
#[derive(Default)]
pub struct DeadCodeEliminator<'ast> {
used: HashSet<Identifier<'ast>>,
}
impl<'ast> DeadCodeEliminator<'ast> {
pub fn eliminate<T: Field>(p: ZirProgram<'ast, T>) -> ZirProgram<'ast, T> {
Self::default().fold_program(p)
}
}
impl<'ast, T: Field> Folder<'ast, T> for DeadCodeEliminator<'ast> {
fn fold_function(&mut self, f: ZirFunction<'ast, T>) -> ZirFunction<'ast, T> {
// iterate on the statements starting from the end, as we want to see usage before definition
let mut statements: Vec<_> = f
.statements
.into_iter()
.rev()
.flat_map(|s| self.fold_statement(s))
.collect();
statements.reverse();
ZirFunction { statements, ..f }
}
fn fold_statement(&mut self, s: ZirStatement<'ast, T>) -> Vec<ZirStatement<'ast, T>> {
match s {
ZirStatement::Definition(v, e) => {
// if the lhs is used later in the program
if self.used.remove(&v.id) {
// include this statement
fold_statement(self, ZirStatement::Definition(v, e))
} else {
// otherwise remove it
vec![]
}
}
ZirStatement::IfElse(condition, consequence, alternative) => {
let condition = self.fold_boolean_expression(condition);
let mut consequence: Vec<_> = consequence
.into_iter()
.rev()
.flat_map(|e| self.fold_statement(e))
.collect();
consequence.reverse();
let mut alternative: Vec<_> = alternative
.into_iter()
.rev()
.flat_map(|e| self.fold_statement(e))
.collect();
alternative.reverse();
vec![ZirStatement::IfElse(condition, consequence, alternative)]
}
s => fold_statement(self, s),
}
}
fn fold_name(&mut self, n: Identifier<'ast>) -> Identifier<'ast> {
self.used.insert(n.clone());
n
}
}

View file

@ -402,7 +402,7 @@ fn fold_statement<'ast, T: Field>(
typed::TypedStatement::Return(expression) => vec![zir::ZirStatement::Return(
f.fold_expression(statements_buffer, expression),
)],
typed::TypedStatement::Definition(a, e) => {
typed::TypedStatement::Definition(a, typed::DefinitionRhs::Expression(e)) => {
let a = f.fold_assignee(a);
let e = f.fold_expression(statements_buffer, e);
assert_eq!(a.len(), e.len());
@ -418,10 +418,14 @@ fn fold_statement<'ast, T: Field>(
zir::RuntimeError::SourceAssertion(metadata.to_string())
}
typed::RuntimeError::SelectRangeCheck => zir::RuntimeError::SelectRangeCheck,
typed::RuntimeError::DivisionByZero => zir::RuntimeError::DivisionByZero,
};
vec![zir::ZirStatement::Assertion(e, error)]
}
typed::TypedStatement::EmbedCallDefinition(assignee, embed_call) => {
typed::TypedStatement::Definition(
assignee,
typed::DefinitionRhs::EmbedCall(embed_call),
) => {
vec![zir::ZirStatement::MultipleDefinition(
f.fold_assignee(assignee),
zir::ZirExpressionList::EmbedCall(

View file

@ -8,10 +8,12 @@ mod branch_isolator;
mod condition_redefiner;
mod constant_argument_checker;
mod constant_resolver;
mod dead_code;
mod flat_propagation;
mod flatten_complex_types;
mod log_ignorer;
mod out_of_bounds;
mod panic_extractor;
mod propagation;
mod reducer;
mod struct_concretizer;
@ -32,6 +34,8 @@ use self::uint_optimizer::UintOptimizer;
use self::variable_write_remover::VariableWriteRemover;
use crate::compile::CompileConfig;
use crate::static_analysis::constant_resolver::ConstantResolver;
use crate::static_analysis::dead_code::DeadCodeEliminator;
use crate::static_analysis::panic_extractor::PanicExtractor;
use crate::static_analysis::zir_propagation::ZirPropagator;
use std::fmt;
use zokrates_ast::typed::{abi::Abi, TypedProgram};
@ -172,6 +176,14 @@ pub fn analyse<'ast, T: Field>(
let zir = ZirPropagator::propagate(zir).map_err(Error::from)?;
log::trace!("\n{}", zir);
log::debug!("Static analyser: Extract panics");
let zir = PanicExtractor::extract(zir);
log::trace!("\n{}", zir);
log::debug!("Static analyser: Remove dead code");
let zir = DeadCodeEliminator::eliminate(zir);
log::trace!("\n{}", zir);
// optimize uint expressions
log::debug!("Static analyser: Optimize uints");
let zir = UintOptimizer::optimize(zir);

View file

@ -0,0 +1,190 @@
use zokrates_ast::zir::{
folder::*, BooleanExpression, Conditional, ConditionalExpression, ConditionalOrExpression,
FieldElementExpression, RuntimeError, UBitwidth, UExpressionInner, ZirProgram, ZirStatement,
};
use zokrates_field::Field;
// a static analyser pass to extract the failure modes into separate assert statements, so that a statement can panic iff it's an assertion
#[derive(Default)]
pub struct PanicExtractor<'ast, T> {
panic_buffer: Vec<ZirStatement<'ast, T>>,
}
impl<'ast, T: Field> PanicExtractor<'ast, T> {
pub fn extract(p: ZirProgram<'ast, T>) -> ZirProgram<'ast, T> {
Self::default().fold_program(p)
}
}
impl<'ast, T: Field> Folder<'ast, T> for PanicExtractor<'ast, T> {
fn fold_statement(&mut self, s: ZirStatement<'ast, T>) -> Vec<ZirStatement<'ast, T>> {
match s {
ZirStatement::IfElse(condition, consequence, alternative) => {
let condition = self.fold_boolean_expression(condition);
let mut consequence_extractor = Self::default();
let consequence = consequence
.into_iter()
.flat_map(|s| consequence_extractor.fold_statement(s))
.collect();
assert!(consequence_extractor.panic_buffer.is_empty());
let mut alternative_extractor = Self::default();
let alternative = alternative
.into_iter()
.flat_map(|s| alternative_extractor.fold_statement(s))
.collect();
assert!(alternative_extractor.panic_buffer.is_empty());
self.panic_buffer
.drain(..)
.chain(std::iter::once(ZirStatement::IfElse(
condition,
consequence,
alternative,
)))
.collect()
}
s => {
let s = fold_statement(self, s);
self.panic_buffer.drain(..).chain(s).collect()
}
}
}
fn fold_field_expression(
&mut self,
e: FieldElementExpression<'ast, T>,
) -> FieldElementExpression<'ast, T> {
match e {
FieldElementExpression::Div(box n, box d) => {
let n = self.fold_field_expression(n);
let d = self.fold_field_expression(d);
self.panic_buffer.push(ZirStatement::Assertion(
BooleanExpression::Not(box BooleanExpression::FieldEq(
box d.clone(),
box FieldElementExpression::Number(T::zero()),
)),
RuntimeError::DivisionByZero,
));
FieldElementExpression::Div(box n, box d)
}
e => fold_field_expression(self, e),
}
}
fn fold_conditional_expression<
E: zokrates_ast::zir::Expr<'ast, T> + Fold<'ast, T> + Conditional<'ast, T>,
>(
&mut self,
_: &E::Ty,
e: ConditionalExpression<'ast, T, E>,
) -> ConditionalOrExpression<'ast, T, E> {
let condition = self.fold_boolean_expression(*e.condition);
let mut consequence_extractor = Self::default();
let consequence = e.consequence.fold(&mut consequence_extractor);
let mut alternative_extractor = Self::default();
let alternative = e.alternative.fold(&mut alternative_extractor);
let consequence_panics: Vec<_> = consequence_extractor.panic_buffer.drain(..).collect();
let alternative_panics: Vec<_> = alternative_extractor.panic_buffer.drain(..).collect();
if !(consequence_panics.is_empty() && alternative_panics.is_empty()) {
self.panic_buffer.push(ZirStatement::IfElse(
condition.clone(),
consequence_panics,
alternative_panics,
));
}
ConditionalOrExpression::Conditional(ConditionalExpression::new(
condition,
consequence,
alternative,
))
}
fn fold_uint_expression_inner(
&mut self,
b: UBitwidth,
e: UExpressionInner<'ast, T>,
) -> UExpressionInner<'ast, T> {
match e {
UExpressionInner::Div(box n, box d) => {
let n = self.fold_uint_expression(n);
let d = self.fold_uint_expression(d);
self.panic_buffer.push(ZirStatement::Assertion(
BooleanExpression::Not(box BooleanExpression::UintEq(
box d.clone(),
box UExpressionInner::Value(0).annotate(b),
)),
RuntimeError::DivisionByZero,
));
UExpressionInner::Div(box n, box d)
}
e => fold_uint_expression_inner(self, b, e),
}
}
fn fold_boolean_expression(
&mut self,
e: BooleanExpression<'ast, T>,
) -> BooleanExpression<'ast, T> {
match e {
// constant range checks are complete, so no panic needs to be extracted
e @ BooleanExpression::FieldLt(box FieldElementExpression::Number(_), _)
| e @ BooleanExpression::FieldLt(_, box FieldElementExpression::Number(_)) => {
fold_boolean_expression(self, e)
}
BooleanExpression::FieldLt(box left, box right) => {
let left = self.fold_field_expression(left);
let right = self.fold_field_expression(right);
let bit_width = T::get_required_bits();
let safe_width = bit_width - 2; // dynamic comparison is not complete, it only applies to field elements whose difference is strictly smaller than 2**(bitwidth - 2)
let offset = FieldElementExpression::Number(T::from(2).pow(safe_width));
let max = FieldElementExpression::Number(T::from(2).pow(safe_width + 1));
// `|left - right|` must be of bitwidth at most `safe_bitwidth`
// this means we need to guarantee the following: `-2**(safe_width) < left - right < 2**(safe_width)`
// adding an offset of `2**(safe_width)` we turn this into:
// require `0 < 2**(safe_width) + left - right < 2**(safe_width + 1)`
// we split this check in two:
// `2**(safe_width) + left - right < 2**(safe_width + 1)`
self.panic_buffer.push(ZirStatement::Assertion(
BooleanExpression::FieldLt(
box FieldElementExpression::Add(
box offset.clone(),
box FieldElementExpression::Sub(box left.clone(), box right.clone()),
),
box max,
),
RuntimeError::IncompleteDynamicRange,
));
// and
// `2**(safe_width) + left - right != 0`
self.panic_buffer.push(ZirStatement::Assertion(
BooleanExpression::Not(box BooleanExpression::FieldEq(
box FieldElementExpression::Sub(box right.clone(), box left.clone()),
box offset,
)),
RuntimeError::IncompleteDynamicRange,
));
// NOTE:
// instead of splitting the check in two, we could have used a single `Lt` here, by simply subtracting 1 from all sides:
// `let x = 2**(safe_width) + left - right`
// `0 <= x - 1 < 2**(safe_width + 1) - 1` which is a single constant `Lt`
// however, the *result* of `left < right` requires knowing the bits of `x`
// if we use `x - 1` here, we end up having to calculate the bits of both `x` and `x - 1`, which is expensive
// by splitting, we can reuse the bits of `x` needed for this completeness check when computing the result
BooleanExpression::FieldLt(box left, box right)
}
e => fold_boolean_expression(self, e),
}
}
}

View file

@ -221,9 +221,9 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> {
) -> Result<Vec<TypedStatement<'ast, T>>, Error> {
match s {
// propagation to the defined variable if rhs is a constant
TypedStatement::Definition(assignee, expr) => {
let expr = self.fold_expression(expr)?;
TypedStatement::Definition(assignee, DefinitionRhs::Expression(expr)) => {
let assignee = self.fold_assignee(assignee)?;
let expr = self.fold_expression(expr)?;
if let (Ok(a), Ok(e)) = (
ConcreteType::try_from(assignee.get_type()),
@ -255,10 +255,10 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> {
// invalidate the cache for this identifier, and define the latest
// version of the constant in the program, if any
Some(c) => Ok(vec![
TypedStatement::Definition(v.clone().into(), c),
TypedStatement::Definition(assignee, expr),
TypedStatement::Definition(v.clone().into(), c.into()),
TypedStatement::Definition(assignee, expr.into()),
]),
None => Ok(vec![TypedStatement::Definition(assignee, expr)]),
None => Ok(vec![TypedStatement::Definition(assignee, expr.into())]),
},
},
}
@ -271,10 +271,10 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> {
match self.constants.remove(&v.id) {
Some(c) => Ok(vec![
TypedStatement::Definition(v.clone().into(), c),
TypedStatement::Definition(assignee, expr),
TypedStatement::Definition(v.clone().into(), c.into()),
TypedStatement::Definition(assignee, expr.into()),
]),
None => Ok(vec![TypedStatement::Definition(assignee, expr)]),
None => Ok(vec![TypedStatement::Definition(assignee, expr.into())]),
}
}
}
@ -285,7 +285,7 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> {
Ok(vec![TypedStatement::For(v, from, to, statements)])
}
TypedStatement::EmbedCallDefinition(assignee, embed_call) => {
TypedStatement::Definition(assignee, DefinitionRhs::EmbedCall(embed_call)) => {
let assignee = self.fold_assignee(assignee)?;
let embed_call = self.fold_embed_call(embed_call)?;
@ -299,37 +299,37 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> {
let argument = argument.into_canonical_constant();
match ArrayExpression::try_from(argument)
.unwrap()
.into_inner()
{
ArrayExpressionInner::Value(v) =>
UExpressionInner::Value(
v.into_iter()
.map(|v| match v {
TypedExpressionOrSpread::Expression(
TypedExpression::Boolean(
BooleanExpression::Value(v),
),
) => v,
_ => unreachable!("Should be a constant boolean expression. Spreads are not expected here, as in their presence the argument isn't constant"),
})
.enumerate()
.fold(0, |acc, (i, v)| {
if v {
acc + 2u128.pow(
(bitwidth.to_usize() - i - 1)
.try_into()
.unwrap(),
)
} else {
acc
}
}),
)
.annotate(bitwidth)
.into(),
_ => unreachable!("should be an array value"),
}
.unwrap()
.into_inner()
{
ArrayExpressionInner::Value(v) =>
UExpressionInner::Value(
v.into_iter()
.map(|v| match v {
TypedExpressionOrSpread::Expression(
TypedExpression::Boolean(
BooleanExpression::Value(v),
),
) => v,
_ => unreachable!("Should be a constant boolean expression. Spreads are not expected here, as in their presence the argument isn't constant"),
})
.enumerate()
.fold(0, |acc, (i, v)| {
if v {
acc + 2u128.pow(
(bitwidth.to_usize() - i - 1)
.try_into()
.unwrap(),
)
} else {
acc
}
}),
)
.annotate(bitwidth)
.into(),
_ => unreachable!("should be an array value"),
}
}
fn process_u_to_bits<'ast, T: Field>(
@ -471,11 +471,11 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> {
}
Err(v) => match self.constants.remove(&v.id) {
Some(c) => vec![
TypedStatement::Definition(v.clone().into(), c),
TypedStatement::Definition(assignee, expr),
TypedStatement::Definition(v.clone().into(), c.into()),
TypedStatement::Definition(assignee, expr.into()),
],
None => {
vec![TypedStatement::Definition(assignee, expr)]
vec![TypedStatement::Definition(assignee, expr.into())]
}
},
},
@ -491,11 +491,12 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> {
match self.constants.remove(&v.id) {
Some(c) => vec![
TypedStatement::Definition(v.clone().into(), c),
TypedStatement::EmbedCallDefinition(assignee, embed_call),
TypedStatement::Definition(v.clone().into(), c.into()),
TypedStatement::Definition(assignee, embed_call.into()),
],
None => vec![TypedStatement::EmbedCallDefinition(
assignee, embed_call,
None => vec![TypedStatement::Definition(
assignee,
embed_call.into(),
)],
}
}
@ -504,7 +505,7 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> {
false => {
// if the function arguments are not constant, invalidate the cache
// for the return assignees
let def = TypedStatement::EmbedCallDefinition(assignee.clone(), embed_call);
let def = TypedStatement::Definition(assignee.clone(), embed_call.into());
let v = self
.try_get_constant_mut(&assignee)
@ -513,7 +514,7 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> {
Ok(match self.constants.remove(&v.id) {
Some(c) => {
vec![TypedStatement::Definition(v.clone().into(), c), def]
vec![TypedStatement::Definition(v.clone().into(), c.into()), def]
}
None => vec![def],
})
@ -524,9 +525,10 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> {
let e_str = e.to_string();
let expr = self.fold_boolean_expression(e)?;
match expr {
BooleanExpression::Value(v) if !v => {
BooleanExpression::Value(false) => {
Err(Error::AssertionFailed(format!("{}: ({})", ty, e_str)))
}
BooleanExpression::Value(true) => Ok(vec![]),
_ => Ok(vec![TypedStatement::Assertion(expr, ty)]),
}
}

View file

@ -177,7 +177,7 @@ pub fn inline_call<'a, 'ast, T: Field, E: Expr<'ast, T>>(
.zip(inferred_signature.inputs.clone())
.map(|(p, t)| ConcreteVariable::new(p.id.id, t, false))
.zip(arguments.clone())
.map(|(v, a)| TypedStatement::Definition(Variable::from(v).into(), a))
.map(|(v, a)| TypedStatement::definition(Variable::from(v).into(), a))
.collect();
let (statements, mut returns): (Vec<_>, Vec<_>) = ssa_f
@ -205,7 +205,7 @@ pub fn inline_call<'a, 'ast, T: Field, E: Expr<'ast, T>>(
let expression = TypedExpression::from(Variable::from(v.clone()));
let output_binding = TypedStatement::Definition(Variable::from(v).into(), return_expression);
let output_binding = TypedStatement::definition(Variable::from(v).into(), return_expression);
let pop_log = TypedStatement::PopCallLog;

View file

@ -278,7 +278,7 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Reducer<'ast, 'a, T> {
let v = var.clone().into();
self.statement_buffer
.push(TypedStatement::EmbedCallDefinition(
.push(TypedStatement::embed_call_definition(
v,
EmbedCall::new(embed, generics, arguments),
));
@ -352,7 +352,7 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Reducer<'ast, 'a, T> {
for index in *from..*to {
let statements: Vec<TypedStatement<_>> =
std::iter::once(TypedStatement::Definition(
std::iter::once(TypedStatement::definition(
v.clone().into(),
UExpression::from(index as u32).into(),
))
@ -611,21 +611,21 @@ mod tests {
let main: TypedFunction<Bn128Field> = TypedFunction {
arguments: vec![DeclarationVariable::field_element("a").into()],
statements: vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("n", UBitwidth::B32).into(),
TypedExpression::Uint(42u32.into()),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("n", UBitwidth::B32).into(),
UExpressionInner::Identifier("n".into())
.annotate(UBitwidth::B32)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element("a").into(),
FieldElementExpression::Identifier("a".into()).into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element("a").into(),
FieldElementExpression::function_call(
DeclarationFunctionKey::with_location("main", "foo").signature(
@ -638,7 +638,7 @@ mod tests {
)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("n", UBitwidth::B32).into(),
UExpressionInner::Identifier("n".into())
.annotate(UBitwidth::B32)
@ -687,7 +687,7 @@ mod tests {
let expected_main = TypedFunction {
arguments: vec![DeclarationVariable::field_element("a").into()],
statements: vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element(Identifier::from("a").version(1)).into(),
FieldElementExpression::Identifier("a".into()).into(),
),
@ -699,17 +699,17 @@ mod tests {
),
GGenericsAssignment::default(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element(Identifier::from("a").version(3)).into(),
FieldElementExpression::Identifier(Identifier::from("a").version(1)).into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element(Identifier::from(CoreIdentifier::Call(0)).version(0))
.into(),
FieldElementExpression::Identifier(Identifier::from("a").version(3)).into(),
),
TypedStatement::PopCallLog,
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element(Identifier::from("a").version(2)).into(),
FieldElementExpression::Identifier(
Identifier::from(CoreIdentifier::Call(0)).version(0),
@ -804,17 +804,17 @@ mod tests {
let main: TypedFunction<Bn128Field> = TypedFunction {
arguments: vec![DeclarationVariable::field_element("a").into()],
statements: vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("n", UBitwidth::B32).into(),
TypedExpression::Uint(42u32.into()),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("n", UBitwidth::B32).into(),
UExpressionInner::Identifier("n".into())
.annotate(UBitwidth::B32)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::array("b", Type::FieldElement, 1u32).into(),
ArrayExpressionInner::Value(
vec![FieldElementExpression::Identifier("a".into()).into()].into(),
@ -822,7 +822,7 @@ mod tests {
.annotate(Type::FieldElement, 1u32)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::array("b", Type::FieldElement, 1u32).into(),
ArrayExpression::function_call(
DeclarationFunctionKey::with_location("main", "foo")
@ -835,7 +835,7 @@ mod tests {
.annotate(Type::FieldElement, 1u32)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("n", UBitwidth::B32).into(),
UExpressionInner::Identifier("n".into())
.annotate(UBitwidth::B32)
@ -889,7 +889,7 @@ mod tests {
let expected_main = TypedFunction {
arguments: vec![DeclarationVariable::field_element("a").into()],
statements: vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::array("b", Type::FieldElement, 1u32).into(),
ArrayExpressionInner::Value(
vec![FieldElementExpression::Identifier("a".into()).into()].into(),
@ -906,14 +906,14 @@ mod tests {
.collect(),
),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::array(Identifier::from("a").version(1), Type::FieldElement, 1u32)
.into(),
ArrayExpressionInner::Identifier("b".into())
.annotate(Type::FieldElement, 1u32)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::array(
Identifier::from(CoreIdentifier::Call(0)).version(0),
Type::FieldElement,
@ -925,7 +925,7 @@ mod tests {
.into(),
),
TypedStatement::PopCallLog,
TypedStatement::Definition(
TypedStatement::definition(
Variable::array(Identifier::from("b").version(1), Type::FieldElement, 1u32)
.into(),
ArrayExpressionInner::Identifier(
@ -1028,17 +1028,17 @@ mod tests {
let main: TypedFunction<Bn128Field> = TypedFunction {
arguments: vec![DeclarationVariable::field_element("a").into()],
statements: vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("n", UBitwidth::B32).into(),
TypedExpression::Uint(2u32.into()),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("n", UBitwidth::B32).into(),
UExpressionInner::Identifier("n".into())
.annotate(UBitwidth::B32)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::array(
"b",
Type::FieldElement,
@ -1055,7 +1055,7 @@ mod tests {
.annotate(Type::FieldElement, 1u32)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::array("b", Type::FieldElement, 1u32).into(),
ArrayExpression::function_call(
DeclarationFunctionKey::with_location("main", "foo")
@ -1068,7 +1068,7 @@ mod tests {
.annotate(Type::FieldElement, 1u32)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("n", UBitwidth::B32).into(),
UExpressionInner::Identifier("n".into())
.annotate(UBitwidth::B32)
@ -1122,7 +1122,7 @@ mod tests {
let expected_main = TypedFunction {
arguments: vec![DeclarationVariable::field_element("a").into()],
statements: vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::array("b", Type::FieldElement, 1u32).into(),
ArrayExpressionInner::Value(
vec![FieldElementExpression::Identifier("a".into()).into()].into(),
@ -1139,14 +1139,14 @@ mod tests {
.collect(),
),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::array(Identifier::from("a").version(1), Type::FieldElement, 1u32)
.into(),
ArrayExpressionInner::Identifier("b".into())
.annotate(Type::FieldElement, 1u32)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::array(
Identifier::from(CoreIdentifier::Call(0)).version(0),
Type::FieldElement,
@ -1158,7 +1158,7 @@ mod tests {
.into(),
),
TypedStatement::PopCallLog,
TypedStatement::Definition(
TypedStatement::definition(
Variable::array(Identifier::from("b").version(1), Type::FieldElement, 1u32)
.into(),
ArrayExpressionInner::Identifier(
@ -1254,7 +1254,7 @@ mod tests {
)
.into()],
statements: vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::array(
"ret",
Type::FieldElement,
@ -1333,7 +1333,7 @@ mod tests {
let main: TypedFunction<Bn128Field> = TypedFunction {
arguments: vec![],
statements: vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::array("b", Type::FieldElement, 1u32).into(),
ArrayExpression::function_call(
DeclarationFunctionKey::with_location("main", "foo")
@ -1485,7 +1485,7 @@ mod tests {
let main: TypedFunction<Bn128Field> = TypedFunction {
arguments: vec![],
statements: vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::array("b", Type::FieldElement, 1u32).into(),
ArrayExpression::function_call(
DeclarationFunctionKey::with_location("main", "foo")

View file

@ -106,7 +106,7 @@ impl<'ast, 'a> ShallowTransformer<'ast, 'a> {
.clone()
.into_iter()
.map(|(g, v)| {
TypedStatement::Definition(
TypedStatement::definition(
Variable::new(CoreIdentifier::from(g), Type::Uint(UBitwidth::B32), false)
.into(),
UExpression::from(v as u32).into(),
@ -126,7 +126,7 @@ impl<'ast, 'a> ShallowTransformer<'ast, 'a> {
impl<'ast, 'a, T: Field> Folder<'ast, T> for ShallowTransformer<'ast, 'a> {
fn fold_statement(&mut self, s: TypedStatement<'ast, T>) -> Vec<TypedStatement<'ast, T>> {
match s {
TypedStatement::Definition(a, e) => {
TypedStatement::Definition(a, DefinitionRhs::Expression(e)) => {
let e = self.fold_expression(e);
let a = match a {
@ -137,9 +137,9 @@ impl<'ast, 'a, T: Field> Folder<'ast, T> for ShallowTransformer<'ast, 'a> {
a => fold_assignee(self, a),
};
vec![TypedStatement::Definition(a, e)]
vec![TypedStatement::definition(a, e)]
}
TypedStatement::EmbedCallDefinition(assignee, embed_call) => {
TypedStatement::Definition(assignee, DefinitionRhs::EmbedCall(embed_call)) => {
let assignee = match assignee {
TypedAssignee::Identifier(v) => {
let v = self.issue_next_ssa_variable(v);
@ -148,7 +148,7 @@ impl<'ast, 'a, T: Field> Folder<'ast, T> for ShallowTransformer<'ast, 'a> {
a => fold_assignee(self, a),
};
let embed_call = self.fold_embed_call(embed_call);
vec![TypedStatement::EmbedCallDefinition(assignee, embed_call)]
vec![TypedStatement::embed_call_definition(assignee, embed_call)]
}
TypedStatement::For(v, from, to, stats) => {
let from = self.fold_uint_expression(from);
@ -236,13 +236,13 @@ mod tests {
let mut u = ShallowTransformer::with_versions(&mut versions);
let s = TypedStatement::Definition(
let s = TypedStatement::definition(
TypedAssignee::Identifier(Variable::field_element("a")),
FieldElementExpression::Number(Bn128Field::from(5)).into(),
);
assert_eq!(
u.fold_statement(s),
vec![TypedStatement::Definition(
vec![TypedStatement::definition(
TypedAssignee::Identifier(Variable::field_element(
Identifier::from("a").version(0)
)),
@ -250,13 +250,13 @@ mod tests {
)]
);
let s = TypedStatement::Definition(
let s = TypedStatement::definition(
TypedAssignee::Identifier(Variable::field_element("a")),
FieldElementExpression::Number(Bn128Field::from(6)).into(),
);
assert_eq!(
u.fold_statement(s),
vec![TypedStatement::Definition(
vec![TypedStatement::definition(
TypedAssignee::Identifier(Variable::field_element(
Identifier::from("a").version(1)
)),
@ -286,13 +286,13 @@ mod tests {
let mut u = ShallowTransformer::with_versions(&mut versions);
let s = TypedStatement::Definition(
let s = TypedStatement::definition(
TypedAssignee::Identifier(Variable::field_element("a")),
FieldElementExpression::Number(Bn128Field::from(5)).into(),
);
assert_eq!(
u.fold_statement(s),
vec![TypedStatement::Definition(
vec![TypedStatement::definition(
TypedAssignee::Identifier(Variable::field_element(
Identifier::from("a").version(0)
)),
@ -300,7 +300,7 @@ mod tests {
)]
);
let s = TypedStatement::Definition(
let s = TypedStatement::definition(
TypedAssignee::Identifier(Variable::field_element("a")),
FieldElementExpression::Add(
box FieldElementExpression::Identifier("a".into()),
@ -310,7 +310,7 @@ mod tests {
);
assert_eq!(
u.fold_statement(s),
vec![TypedStatement::Definition(
vec![TypedStatement::definition(
TypedAssignee::Identifier(Variable::field_element(
Identifier::from("a").version(1)
)),
@ -337,13 +337,13 @@ mod tests {
let mut u = ShallowTransformer::with_versions(&mut versions);
let s = TypedStatement::Definition(
let s = TypedStatement::definition(
TypedAssignee::Identifier(Variable::field_element("a")),
FieldElementExpression::Number(Bn128Field::from(2)).into(),
);
assert_eq!(
u.fold_statement(s),
vec![TypedStatement::Definition(
vec![TypedStatement::definition(
TypedAssignee::Identifier(Variable::field_element(
Identifier::from("a").version(0)
)),
@ -351,7 +351,7 @@ mod tests {
)]
);
let s: TypedStatement<Bn128Field> = TypedStatement::Definition(
let s: TypedStatement<Bn128Field> = TypedStatement::definition(
Variable::field_element("a").into(),
FieldElementExpression::function_call(
DeclarationFunctionKey::with_location("main", "foo").signature(
@ -366,7 +366,7 @@ mod tests {
);
assert_eq!(
u.fold_statement(s),
vec![TypedStatement::Definition(
vec![TypedStatement::definition(
Variable::field_element(Identifier::from("a").version(1)).into(),
FieldElementExpression::function_call(
DeclarationFunctionKey::with_location("main", "foo").signature(
@ -398,7 +398,7 @@ mod tests {
let mut u = ShallowTransformer::with_versions(&mut versions);
let s = TypedStatement::Definition(
let s = TypedStatement::definition(
TypedAssignee::Identifier(Variable::array("a", Type::FieldElement, 2u32)),
ArrayExpressionInner::Value(
vec![
@ -413,7 +413,7 @@ mod tests {
assert_eq!(
u.fold_statement(s),
vec![TypedStatement::Definition(
vec![TypedStatement::definition(
TypedAssignee::Identifier(Variable::array(
Identifier::from("a").version(0),
Type::FieldElement,
@ -431,7 +431,7 @@ mod tests {
)]
);
let s: TypedStatement<Bn128Field> = TypedStatement::Definition(
let s: TypedStatement<Bn128Field> = TypedStatement::definition(
TypedAssignee::Select(
box TypedAssignee::Identifier(Variable::array("a", Type::FieldElement, 2u32)),
box UExpression::from(1u32),
@ -457,7 +457,7 @@ mod tests {
let array_of_array_ty = Type::array((Type::array((Type::FieldElement, 2u32)), 2u32));
let s = TypedStatement::Definition(
let s = TypedStatement::definition(
TypedAssignee::Identifier(Variable::new("a", array_of_array_ty.clone(), true)),
ArrayExpressionInner::Value(
vec![
@ -488,7 +488,7 @@ mod tests {
assert_eq!(
u.fold_statement(s),
vec![TypedStatement::Definition(
vec![TypedStatement::definition(
TypedAssignee::Identifier(Variable::new(
Identifier::from("a").version(0),
array_of_array_ty.clone(),
@ -522,7 +522,7 @@ mod tests {
)]
);
let s: TypedStatement<Bn128Field> = TypedStatement::Definition(
let s: TypedStatement<Bn128Field> = TypedStatement::definition(
TypedAssignee::Select(
box TypedAssignee::Identifier(Variable::new(
"a",
@ -588,17 +588,17 @@ mod tests {
let f: TypedFunction<Bn128Field> = TypedFunction {
arguments: vec![DeclarationVariable::field_element("a").into()],
statements: vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("n", UBitwidth::B32).into(),
TypedExpression::Uint(42u32.into()),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("n", UBitwidth::B32).into(),
UExpressionInner::Identifier("n".into())
.annotate(UBitwidth::B32)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element("a").into(),
FieldElementExpression::Identifier("a".into()).into(),
),
@ -607,12 +607,12 @@ mod tests {
UExpressionInner::Identifier("n".into()).annotate(UBitwidth::B32),
UExpressionInner::Identifier("n".into()).annotate(UBitwidth::B32)
* UExpressionInner::Identifier("n".into()).annotate(UBitwidth::B32),
vec![TypedStatement::Definition(
vec![TypedStatement::definition(
Variable::field_element("a").into(),
FieldElementExpression::Identifier("a".into()).into(),
)],
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element("a").into(),
FieldElementExpression::Identifier("a".into()).into(),
),
@ -621,12 +621,12 @@ mod tests {
UExpressionInner::Identifier("n".into()).annotate(UBitwidth::B32),
UExpressionInner::Identifier("n".into()).annotate(UBitwidth::B32)
* UExpressionInner::Identifier("n".into()).annotate(UBitwidth::B32),
vec![TypedStatement::Definition(
vec![TypedStatement::definition(
Variable::field_element("a").into(),
FieldElementExpression::Identifier("a".into()).into(),
)],
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element("a").into(),
FieldElementExpression::Identifier("a".into()).into(),
),
@ -655,21 +655,21 @@ mod tests {
let expected = TypedFunction {
arguments: vec![DeclarationVariable::field_element("a").into()],
statements: vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("K", UBitwidth::B32).into(),
TypedExpression::Uint(1u32.into()),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("n", UBitwidth::B32).into(),
TypedExpression::Uint(42u32.into()),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint(Identifier::from("n").version(1), UBitwidth::B32).into(),
UExpressionInner::Identifier("n".into())
.annotate(UBitwidth::B32)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element(Identifier::from("a").version(1)).into(),
FieldElementExpression::Identifier("a".into()).into(),
),
@ -681,12 +681,12 @@ mod tests {
.annotate(UBitwidth::B32)
* UExpressionInner::Identifier(Identifier::from("n").version(1))
.annotate(UBitwidth::B32),
vec![TypedStatement::Definition(
vec![TypedStatement::definition(
Variable::field_element("a").into(),
FieldElementExpression::Identifier("a".into()).into(),
)],
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element(Identifier::from("a").version(3)).into(),
FieldElementExpression::Identifier(Identifier::from("a").version(2)).into(),
),
@ -698,12 +698,12 @@ mod tests {
.annotate(UBitwidth::B32)
* UExpressionInner::Identifier(Identifier::from("n").version(2))
.annotate(UBitwidth::B32),
vec![TypedStatement::Definition(
vec![TypedStatement::definition(
Variable::field_element("a").into(),
FieldElementExpression::Identifier("a".into()).into(),
)],
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element(Identifier::from("a").version(5)).into(),
FieldElementExpression::Identifier(Identifier::from("a").version(4)).into(),
),
@ -766,11 +766,11 @@ mod tests {
let f: TypedFunction<Bn128Field> = TypedFunction {
arguments: vec![DeclarationVariable::field_element("a").into()],
statements: vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element("a").into(),
TypedExpression::Uint(42u32.into()),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::boolean("a").into(),
BooleanExpression::Value(true).into(),
),
@ -788,11 +788,11 @@ mod tests {
let expected: TypedFunction<Bn128Field> = TypedFunction {
arguments: vec![DeclarationVariable::field_element("a").into()],
statements: vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element(Identifier::from("a").version(1)).into(),
TypedExpression::Uint(42u32.into()),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::boolean(Identifier::from("a").version(2)).into(),
BooleanExpression::Value(true).into(),
),
@ -844,11 +844,11 @@ mod tests {
0u32.into(),
1u32.into(),
vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element(Identifier::from("a")).into(),
FieldElementExpression::Identifier("a".into()).into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element(Identifier::from("a")).into(),
FieldElementExpression::Number(42usize.into()).into(),
),
@ -877,11 +877,11 @@ mod tests {
0u32.into(),
1u32.into(),
vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element(Identifier::from("a")).into(),
FieldElementExpression::Identifier(Identifier::from("a")).into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element(Identifier::from("a")).into(),
FieldElementExpression::Number(42usize.into()).into(),
),
@ -945,21 +945,21 @@ mod tests {
let f: TypedFunction<Bn128Field> = TypedFunction {
arguments: vec![DeclarationVariable::field_element("a").into()],
statements: vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("n", UBitwidth::B32).into(),
TypedExpression::Uint(42u32.into()),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("n", UBitwidth::B32).into(),
UExpressionInner::Identifier("n".into())
.annotate(UBitwidth::B32)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element("a").into(),
FieldElementExpression::Identifier("a".into()).into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element("a").into(),
FieldElementExpression::function_call(
DeclarationFunctionKey::with_location("main", "foo"),
@ -970,13 +970,13 @@ mod tests {
)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("n", UBitwidth::B32).into(),
UExpressionInner::Identifier("n".into())
.annotate(UBitwidth::B32)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element("a").into(),
(FieldElementExpression::Identifier("a".into())
* FieldElementExpression::function_call(
@ -1014,25 +1014,25 @@ mod tests {
let expected = TypedFunction {
arguments: vec![DeclarationVariable::field_element("a").into()],
statements: vec![
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("K", UBitwidth::B32).into(),
TypedExpression::Uint(1u32.into()),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint("n", UBitwidth::B32).into(),
TypedExpression::Uint(42u32.into()),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint(Identifier::from("n").version(1), UBitwidth::B32).into(),
UExpressionInner::Identifier("n".into())
.annotate(UBitwidth::B32)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element(Identifier::from("a").version(1)).into(),
FieldElementExpression::Identifier("a".into()).into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element(Identifier::from("a").version(2)).into(),
FieldElementExpression::function_call(
DeclarationFunctionKey::with_location("main", "foo"),
@ -1047,13 +1047,13 @@ mod tests {
)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::uint(Identifier::from("n").version(2), UBitwidth::B32).into(),
UExpressionInner::Identifier(Identifier::from("n").version(1))
.annotate(UBitwidth::B32)
.into(),
),
TypedStatement::Definition(
TypedStatement::definition(
Variable::field_element(Identifier::from("a").version(3)).into(),
(FieldElementExpression::Identifier(Identifier::from("a").version(2))
* FieldElementExpression::function_call(

View file

@ -457,11 +457,11 @@ fn is_constant<T>(assignee: &TypedAssignee<T>) -> bool {
impl<'ast, T: Field> Folder<'ast, T> for VariableWriteRemover {
fn fold_statement(&mut self, s: TypedStatement<'ast, T>) -> Vec<TypedStatement<'ast, T>> {
match s {
TypedStatement::Definition(assignee, expr) => {
TypedStatement::Definition(assignee, DefinitionRhs::Expression(expr)) => {
let expr = self.fold_expression(expr);
if is_constant(&assignee) {
vec![TypedStatement::Definition(assignee, expr)]
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]`
@ -511,7 +511,7 @@ impl<'ast, T: Field> Folder<'ast, T> for VariableWriteRemover {
range_checks
.into_iter()
.chain(std::iter::once(TypedStatement::Definition(
.chain(std::iter::once(TypedStatement::definition(
TypedAssignee::Identifier(variable),
e,
)))

View file

@ -1,18 +1,10 @@
use std::collections::HashMap;
use std::fmt;
use zokrates_ast::zir::result_folder::fold_boolean_expression;
use zokrates_ast::zir::result_folder::fold_field_expression;
use zokrates_ast::zir::result_folder::fold_statement;
use zokrates_ast::zir::result_folder::fold_uint_expression_inner;
use zokrates_ast::zir::result_folder::ResultFold;
use zokrates_ast::zir::result_folder::ResultFolder;
use zokrates_ast::zir::types::UBitwidth;
use zokrates_ast::zir::Conditional;
use zokrates_ast::zir::ConditionalExpression;
use zokrates_ast::zir::ConditionalOrExpression;
use zokrates_ast::zir::Expr;
use zokrates_ast::zir::SelectExpression;
use zokrates_ast::zir::SelectOrExpression;
use zokrates_ast::zir::{
result_folder::*, Conditional, ConditionalExpression, ConditionalOrExpression, Expr,
SelectExpression, SelectOrExpression,
};
use zokrates_ast::zir::{
BooleanExpression, FieldElementExpression, Identifier, RuntimeError, UExpression,
UExpressionInner, ZirExpression, ZirProgram, ZirStatement,
@ -667,6 +659,7 @@ mod tests {
#[cfg(test)]
mod field {
use zokrates_ast::zir::Conditional;
use zokrates_ast::zir::Select;
use super::*;
@ -868,6 +861,7 @@ mod tests {
#[cfg(test)]
mod bool {
use zokrates_ast::zir::Conditional;
use zokrates_ast::zir::Select;
use super::*;
@ -1174,6 +1168,8 @@ mod tests {
#[cfg(test)]
mod uint {
use zokrates_ast::zir::Conditional;
use super::*;
#[test]

View file

@ -0,0 +1,65 @@
{
"entry_point": "./tests/tests/div.zok",
"max_constraint_count": 3,
"curves": ["Bn128", "Bls12_381", "Bls12_377", "Bw6_761"],
"tests": [
{
"input": {
"values": ["0", "0"]
},
"output": {
"Err": {
"UnsatisfiedConstraint": {
"left": "4",
"right": "2",
"error": "Inverse"
}
}
}
},
{
"input": {
"values": ["1", "0"]
},
"output": {
"Err": {
"UnsatisfiedConstraint": {
"left": "4",
"right": "2",
"error": "Inverse"
}
}
}
},
{
"input": {
"values": ["0", "1"]
},
"output": {
"Ok": {
"value": "0"
}
}
},
{
"input": {
"values": ["2", "2"]
},
"output": {
"Ok": {
"value": "1"
}
}
},
{
"input": {
"values": ["4", "2"]
},
"output": {
"Ok": {
"value": "2"
}
}
}
]
}

View file

@ -0,0 +1,3 @@
def main(field x, field y) -> field {
return x / y;
}

View file

@ -0,0 +1,4 @@
{
"entry_point": "./tests/tests/no_return.zok",
"tests": []
}

View file

@ -0,0 +1,9 @@
def foo() {
return;
}
def bar() {
return foo();
}
def main() {}

View file

@ -1,15 +1,15 @@
{
"entry_point": "./tests/tests/shadowing.zok",
"tests": [
{
"input": {
"values": []
},
"output": {
"Ok": {
"value": ["2", "84"]
}
}
"entry_point": "./tests/tests/shadowing.zok",
"tests": [
{
"input": {
"values": []
},
"output": {
"Ok": {
"value": ["2", "84"]
}
]
}
}
]
}

View file

@ -76,10 +76,7 @@ impl Evm {
pub fn create_account(&mut self, address: &Address, balance: impl Into<U256>) {
let acc = AccountInfo::from_balance(balance.into());
self.vm
.db()
.unwrap()
.insert_account_info(*address.as_ref(), acc);
self.vm.db().unwrap().insert_cache(*address.as_ref(), acc);
}
pub fn set_account_balance(
@ -89,10 +86,7 @@ impl Evm {
) -> Result<(), Error> {
let mut acc = self.vm.db().unwrap().basic(*address.as_ref());
acc.balance = balance.into();
self.vm
.db()
.unwrap()
.insert_account_info(*address.as_ref(), acc);
self.vm.db().unwrap().insert_cache(*address.as_ref(), acc);
Ok(())
}