diff --git a/.circleci/config.yml b/.circleci/config.yml index c2235d45..27511643 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -57,6 +57,14 @@ jobs: # - run: # name: Generate code coverage report # command: ./scripts/cov.sh + cpp_format: + docker: + - image: dark64/clang-format-checker:env + steps: + - checkout + - run: + name: Check cpp format (clang-format) + command: run-clang-format.py -r $(pwd)/zokrates_core/lib wasm_test: docker: - image: rustlang/rust:nightly-slim @@ -72,14 +80,11 @@ jobs: keys: - v4-cargo-cache-{{ arch }}-{{ checksum "Cargo.lock" }} - run: - name: Download wasm32 target - command: rustup target add wasm32-unknown-unknown + name: Install wasm testing env + command: ./scripts/install_wasm_testing.sh - run: - name: Install libsnark prerequisites - command: ./scripts/install_libsnark_prerequisites.sh - - run: - name: Run tests with WASM enabled - command: cd zokrates_core && cargo test --release --features wasm -- --test-threads=1 + name: Test on firefox + command: ZOKRATES_HOME=$(pwd)/zokrates_stdlib/stdlib/ cd zokrates_core && wasm-pack test --firefox --headless -- --features wasm integration_test: docker: - image: rustlang/rust:nightly-slim @@ -107,7 +112,7 @@ jobs: command: ZOKRATES_HOME=$(pwd)/zokrates_stdlib/stdlib/ WITH_LIBSNARK=1 RUSTFLAGS="-D warnings" ./full_test.sh deploy: docker: - - image: circleci/python + - image: circleci/python:latest-node steps: - checkout - setup_remote_docker: @@ -115,15 +120,32 @@ jobs: - run: name: Release command: ./scripts/release.sh - + zokrates_js_build: + docker: + - image: dark64/rust-wasm-env:latest + steps: + - checkout + - run: + name: Build + command: cd zokrates_js && npm run build + zokrates_js_test: + docker: + - image: circleci/node + steps: + - checkout + - run: + command: cd zokrates_js && npm run test workflows: version: 2 build-test-and-deploy: jobs: - build - test + - cpp_format - wasm_test - integration_test + - zokrates_js_build + - zokrates_js_test - deploy: filters: branches: @@ -132,6 +154,8 @@ workflows: requires: - build - test + - cpp_format + - wasm_test - integration_test - - + - zokrates_js_build + - zokrates_js_test diff --git a/.gitignore b/.gitignore index 30082090..364c0a1b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ # ZoKrates default files out out.ztf +abi.json proof.json proving.key verification.key @@ -18,3 +19,5 @@ witness .DS_Store .idea +.vscode +*.iml diff --git a/.travis.yml b/.travis.yml index 40676197..54333de9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,8 +21,8 @@ matrix: - env: TARGET=x86_64-unknown-linux-gnu # OSX - - env: TARGET=i686-apple-darwin - os: osx + # - env: TARGET=i686-apple-darwin + # os: osx - env: TARGET=x86_64-apple-darwin os: osx diff --git a/Cargo.lock b/Cargo.lock index e080fb14..868dd8f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,1769 +4,1814 @@ name = "aho-corasick" version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" dependencies = [ - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi", ] -[[package]] -name = "approx" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "arrayvec" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" dependencies = [ - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop", ] [[package]] name = "assert_cli" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72342c21057a3cb5f7c2d849bf7999a83795434dd36d74fa8c24680581bd1930" dependencies = [ - "colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", + "colored", + "difference", + "environment", + "error-chain 0.11.0", + "serde_json", + "skeptic", ] [[package]] name = "atty" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi", + "libc", + "winapi", ] [[package]] name = "autocfg" -version = "0.1.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" [[package]] name = "backtrace" -version = "0.3.38" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" dependencies = [ - "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys", + "cfg-if", + "libc", + "rustc-demangle", ] [[package]] name = "backtrace-sys" -version = "0.1.31" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78848718ee1255a2485d1309ad9cdecfc2e7d0362dd11c6829364c6b35ae1bc7" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", ] [[package]] name = "bellman_ce" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0300152b8d0c0220c70a39d6da08adff84352f5dd28d91944bc60e9dc8cbebb9" dependencies = [ - "bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pairing_ce 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bit-vec", + "byteorder", + "cfg-if", + "crossbeam", + "futures", + "num_cpus", + "pairing_ce", + "rand 0.4.6", + "web-sys", ] [[package]] name = "bincode" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e103c8b299b28a9c6990458b7013dc4a8356a9b854c51b9883241f5866fac36e" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "num-traits 0.1.43", + "serde", ] [[package]] name = "bit-vec" -version = "0.4.4" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4523a10839ffae575fb08aa3423026c8cb4687eef43952afb956229d4f246f7" [[package]] name = "bitflags" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "blake2-rfc_bellman_edition" version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc60350286c7c3db13b98e91dbe5c8b6830a6821bc20af5b0c310ce94d74915" dependencies = [ - "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec", + "byteorder", + "constant_time_eq", ] [[package]] name = "block-buffer" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" dependencies = [ - "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "block-padding", + "byte-tools", + "byteorder", + "generic-array", ] [[package]] name = "block-padding" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools", ] [[package]] name = "bstr" -version = "0.2.8" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "memchr", + "regex-automata", + "serde", ] +[[package]] +name = "bumpalo" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187" + [[package]] name = "byte-tools" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytecount" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" [[package]] name = "byteorder" -version = "1.3.2" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "c2-chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" [[package]] name = "cargo_metadata" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" dependencies = [ - "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.2", + "semver", + "serde", + "serde_derive", + "serde_json", ] [[package]] name = "cc" -version = "1.0.45" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" dependencies = [ - "jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver", ] [[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cgmath" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "clap" version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", ] [[package]] name = "cmake" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", ] [[package]] name = "colored" -version = "1.8.0" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winconsole 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty", + "lazy_static", + "winapi", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211" +dependencies = [ + "cfg-if", + "wasm-bindgen", ] [[package]] name = "constant_time_eq" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "crossbeam" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69323bff1fb41c635347b8ead484a5ca6c3f11914d784170b158d8449ab07f8e" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", ] [[package]] name = "crossbeam-channel" -version = "0.3.9" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils", + "maybe-uninit", ] [[package]] name = "crossbeam-deque" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" dependencies = [ - "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch", + "crossbeam-utils", + "maybe-uninit", ] [[package]] name = "crossbeam-epoch" -version = "0.7.2" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ - "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "maybe-uninit", + "memoffset", + "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.1.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.6.6" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", + "cfg-if", + "lazy_static", ] [[package]] name = "crunchy" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "csv" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279" dependencies = [ - "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr", + "csv-core", + "itoa", + "ryu", + "serde", ] [[package]] name = "csv-core" -version = "0.1.6" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" dependencies = [ - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] name = "curl-sys" -version = "0.4.22" +version = "0.4.30+curl-7.69.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "923b38e423a8f47a4058e96f2a1fa2865a6231097ee860debd678d244277d50c" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.50 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", + "winapi", ] [[package]] name = "difference" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "digest" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" [[package]] name = "digest" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array", ] [[package]] name = "either" version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" [[package]] name = "environment" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee" [[package]] name = "error-chain" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" dependencies = [ - "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace", ] [[package]] name = "error-chain" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d371106cc88ffdfb1eabd7111e432da544f16f3e2d7bf1dfe8bf575f1df045cd" dependencies = [ - "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace", + "version_check", ] [[package]] name = "failure" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b" dependencies = [ - "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace", + "failure_derive", ] [[package]] name = "failure_derive" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", + "synstructure", ] [[package]] name = "fake-simd" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "ff_ce" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83c0a6a2c53b0bd6d8cae976816dc8a171e0554c03f304e3dac110473e0219fd" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ff_derive_ce 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "ff_derive_ce", + "hex", + "rand 0.4.6", ] [[package]] name = "ff_derive_ce" -version = "0.5.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7543567f0c51910363eb5706ee2f5368a64e79a8ae607d0332aa60bae03a1bb1" dependencies = [ - "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.6", + "num-integer", + "num-traits 0.2.11", + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", ] [[package]] name = "from-pest" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aba9389cedcba1fb3a2aa2ed00f584f2606bce8e0106614a17327a24513bc60f" dependencies = [ - "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pest", + "void", ] [[package]] name = "fs_extra" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" [[package]] name = "fuchsia-cprng" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "futures" -version = "0.1.29" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-cpupool" -version = "0.1.8" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", ] [[package]] -name = "gcc" -version = "0.3.55" +name = "futures-channel" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8" +dependencies = [ + "futures-core", + "futures-sink", +] [[package]] -name = "generic-array" -version = "0.9.0" +name = "futures-core" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" + +[[package]] +name = "futures-executor" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba" dependencies = [ - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6" + +[[package]] +name = "futures-sink" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6" + +[[package]] +name = "futures-task" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27" + +[[package]] +name = "futures-util" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "memchr", + "pin-utils", + "slab", ] [[package]] name = "generic-array" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" dependencies = [ - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum", ] [[package]] name = "getrandom" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "wasi", ] [[package]] name = "git2" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7339329bfa14a00223244311560d11f8f489b453fb90092af97f267a6090ab0" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.50 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "libc", + "libgit2-sys", + "log", + "openssl-probe", + "openssl-sys", + "url", ] [[package]] name = "glob" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" [[package]] name = "glob" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "hermit-abi" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d737e0f947a1864e93d33fdef4af8445a00d1ed8dc0c8ddb73139ea6abf15" +dependencies = [ + "libc", +] [[package]] name = "hex" -version = "0.3.2" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" [[package]] name = "idna" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "matches", + "unicode-bidi", + "unicode-normalization", ] [[package]] name = "itertools" version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" dependencies = [ - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "either", ] [[package]] name = "itoa" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" [[package]] name = "jobserver" -version = "0.1.17" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055" +dependencies = [ + "wasm-bindgen", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.62" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" [[package]] name = "libgit2-sys" version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48441cb35dc255da8ae72825689a95368bf510659ae1ad55dc4aa88cb1789bf1" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "curl-sys 0.4.22 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "libssh2-sys 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.50 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "curl-sys", + "libc", + "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", ] [[package]] name = "libssh2-sys" -version = "0.2.12" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb70f29dc7c31d32c97577f13f41221af981b31248083e347b7f2c39225a6bc" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.50 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", ] [[package]] name = "libz-sys" version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", + "pkg-config", + "vcpkg", ] [[package]] name = "log" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "maplit" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" + +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.2.1" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" [[package]] name = "memoffset" -version = "0.5.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", ] -[[package]] -name = "memory_units" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "nodrop" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" [[package]] name = "num" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" dependencies = [ - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer", + "num-iter", + "num-traits 0.2.11", ] [[package]] name = "num-bigint" version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" dependencies = [ - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer", + "num-traits 0.2.11", ] [[package]] name = "num-bigint" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", + "num-integer", + "num-traits 0.2.11", + "serde", ] [[package]] name = "num-integer" -version = "0.1.41" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", + "num-traits 0.2.11", ] [[package]] name = "num-iter" -version = "0.1.39" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", + "num-integer", + "num-traits 0.2.11", ] [[package]] name = "num-traits" version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" dependencies = [ - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11", ] [[package]] name = "num-traits" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", ] [[package]] name = "num_cpus" -version = "1.10.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi", + "libc", ] [[package]] name = "opaque-debug" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "openssl-probe" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-sys" -version = "0.9.50" +version = "0.9.55" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7717097d810a0f2e2323f9e5d11e71608355e24828410b55b9d4f18aa5f9a5d8" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", ] [[package]] name = "pairing_ce" -version = "0.18.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c7b23aa7f0489d9a5e8e15cc5b7cb4f3e9b9d64812b8875fb91d25b640b0939" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ff_ce 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-wasm" -version = "0.31.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-wasm" -version = "0.35.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "ff_ce", + "rand 0.4.6", ] [[package]] name = "percent-encoding" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" [[package]] name = "pest" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" dependencies = [ - "ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-trie", ] [[package]] name = "pest-ast" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbf404899169771dd6a32c84248b83cd67a26cc7cc957aac87661490e1227e4" dependencies = [ - "itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "single 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools", + "proc-macro2 0.4.30", + "quote 0.6.13", + "single", + "syn 0.15.44", ] [[package]] name = "pest_derive" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" dependencies = [ - "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pest", + "pest_generator", ] [[package]] name = "pest_generator" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ - "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "pest", + "pest_meta", + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", ] [[package]] name = "pest_meta" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" dependencies = [ - "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "maplit", + "pest", + "sha-1", ] [[package]] -name = "pkg-config" -version = "0.3.16" +name = "pin-utils" +version = "0.1.0-alpha.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" + +[[package]] +name = "pkg-config" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" [[package]] name = "ppv-lite86" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" [[package]] name = "proc-macro2" version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0", ] [[package]] name = "proc-macro2" -version = "1.0.5" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3" dependencies = [ - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0", ] [[package]] name = "pulldown-cmark" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", ] [[package]] name = "quote" version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30", ] [[package]] name = "quote" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" dependencies = [ - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.10", ] [[package]] name = "rand" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" dependencies = [ - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", ] [[package]] name = "rand" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", + "libc", + "rand_chacha", + "rand_core 0.5.1", + "rand_hc", ] [[package]] name = "rand_chacha" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ - "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] name = "rand_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" dependencies = [ - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2", ] [[package]] name = "rand_core" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" [[package]] name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", ] [[package]] name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1", ] [[package]] name = "rdrand" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", ] [[package]] name = "redox_syscall" version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" [[package]] name = "reduce" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b1fa5668b02f2a69746bba558f8f98cc087b123a587fd959122872ad9a3f3c" [[package]] name = "regex" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" dependencies = [ - "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", + "utf8-ranges", ] [[package]] name = "regex-automata" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", ] [[package]] name = "regex-syntax" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" dependencies = [ - "ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-util", ] [[package]] name = "remove_dir_all" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rgb" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rust-crypto" -version = "0.2.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi", ] [[package]] name = "rustc-demangle" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc-hex" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc-serialize" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" [[package]] name = "ryu" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" [[package]] name = "same-file" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util", ] [[package]] name = "sapling-crypto_ce" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec318b68765114e578fe42446b6861565b302bc93089aa01669d19417a6de993" dependencies = [ - "bellman_ce 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2-rfc_bellman_edition 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bellman_ce", + "blake2-rfc_bellman_edition", + "byteorder", + "digest", + "rand 0.4.6", + "serde", + "serde_derive", + "sha2", + "tiny-keccak", ] [[package]] -name = "scopeguard" +name = "scoped-tls" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "semver" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "semver-parser", + "serde", ] [[package]] name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.101" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399" [[package]] name = "serde_bytes" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defbb8a83d7f34cc8380751eeb892b825944222888aff18996ea7901f24aec88" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", ] [[package]] name = "serde_derive" -version = "1.0.101" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" dependencies = [ - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", ] [[package]] name = "serde_json" -version = "1.0.41" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da07b57ee2623368351e9a0488bb0b261322a15a6e0ae53e243cbdc0f4208da9" dependencies = [ - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa", + "ryu", + "serde", ] [[package]] name = "sha-1" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer", + "digest", + "fake-simd", + "opaque-debug", ] [[package]] name = "sha2" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer", + "digest", + "fake-simd", + "opaque-debug", ] [[package]] name = "single" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd5add732a1ab689845591a1b50339cf5310b563e08dc5813c65991f30369ea2" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure", ] [[package]] name = "skeptic" version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" dependencies = [ - "bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "bytecount", + "cargo_metadata", + "error-chain 0.12.2", + "glob 0.2.11", + "pulldown-cmark", + "serde_json", + "tempdir", + "walkdir", ] [[package]] -name = "smallvec" -version = "0.6.10" +name = "slab" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" + +[[package]] +name = "smallvec" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a" [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "syn" -version = "0.14.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "syn" version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", ] [[package]] name = "syn" -version = "1.0.5" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" dependencies = [ - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.10", + "quote 1.0.3", + "unicode-xid 0.2.0", ] [[package]] name = "synstructure" -version = "0.10.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", + "unicode-xid 0.2.0", ] [[package]] name = "tempdir" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" dependencies = [ - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6", + "remove_dir_all", ] [[package]] name = "tempfile" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "rand 0.7.3", + "redox_syscall", + "remove_dir_all", + "winapi", ] [[package]] name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width", ] [[package]] name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "time" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", ] [[package]] name = "tiny-keccak" -version = "1.5.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" dependencies = [ - "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy", ] [[package]] name = "typed-arena" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d" [[package]] name = "typenum" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "ucd-trie" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" [[package]] name = "ucd-util" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85f514e095d348c279b1e5cd76795082cf15bd59b93207832abe0b1d8fed236" [[package]] name = "unicode-bidi" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "matches", ] [[package]] name = "unicode-normalization" -version = "0.1.8" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" dependencies = [ - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", ] [[package]] name = "unicode-width" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" [[package]] name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" [[package]] name = "url" version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" dependencies = [ - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "idna", + "matches", + "percent-encoding", ] [[package]] name = "utf8-ranges" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" [[package]] name = "vcpkg" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" [[package]] name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" [[package]] name = "version_check" -version = "0.1.5" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" [[package]] name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "walkdir" -version = "2.2.9" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" dependencies = [ - "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file", + "winapi", + "winapi-util", ] [[package]] name = "wasi" -version = "0.7.0" +version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] -name = "wasmi" -version = "0.4.5" +name = "wasm-bindgen" +version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f" dependencies = [ - "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi-validation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "wasm-bindgen-macro", ] [[package]] -name = "wasmi-validation" -version = "0.1.0" +name = "wasm-bindgen-backend" +version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd" dependencies = [ - "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bumpalo", + "lazy_static", + "log", + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7add542ea1ac7fdaa9dc25e031a6af33b7d63376292bd24140c637d00d1c312a" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4" +dependencies = [ + "quote 1.0.3", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931" +dependencies = [ + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.17", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639" + +[[package]] +name = "wasm-bindgen-test" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "648da3460c6d2aa04b715a936329e2e311180efe650b2127d6267f4193ccac14" +dependencies = [ + "console_error_panic_hook", + "js-sys", + "scoped-tls", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf2f86cd78a2aa7b1fb4bb6ed854eccb7f9263089c79542dca1576a1518a8467" +dependencies = [ + "proc-macro2 1.0.10", + "quote 1.0.3", +] + +[[package]] +name = "web-sys" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb" +dependencies = [ + "js-sys", + "wasm-bindgen", ] [[package]] name = "winapi" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi", ] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winconsole" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rgb 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "zokrates_abi" -version = "0.1.0" +version = "0.1.1" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "zokrates_core 0.4.0", - "zokrates_field 0.3.4", + "serde", + "serde_derive", + "serde_json", + "zokrates_core", + "zokrates_field", ] [[package]] name = "zokrates_cli" -version = "0.5.0" +version = "0.5.2" dependencies = [ - "assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "zokrates_abi 0.1.0", - "zokrates_core 0.4.0", - "zokrates_field 0.3.4", - "zokrates_fs_resolver 0.4.2", + "assert_cli", + "bincode", + "clap", + "fs_extra", + "glob 0.2.11", + "regex", + "serde_json", + "tempdir", + "zokrates_abi", + "zokrates_core", + "zokrates_field", + "zokrates_fs_resolver", ] +[[package]] +name = "zokrates_common" +version = "0.1.0" + [[package]] name = "zokrates_core" -version = "0.4.0" +version = "0.4.2" dependencies = [ - "assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bellman_ce 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ff_ce 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", - "pairing_ce 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.35.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "reduce 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "typed-arena 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "zokrates_embed 0.1.0", - "zokrates_field 0.3.4", - "zokrates_pest_ast 0.1.3", + "assert_cli", + "bellman_ce", + "bincode", + "cc", + "cmake", + "csv", + "ff_ce", + "git2", + "glob 0.2.11", + "lazy_static", + "num", + "num-bigint 0.1.44", + "pairing_ce", + "rand 0.4.6", + "reduce", + "regex", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "typed-arena", + "wasm-bindgen-test", + "zokrates_common", + "zokrates_embed", + "zokrates_field", + "zokrates_pest_ast", ] [[package]] name = "zokrates_core_test" -version = "0.1.0" +version = "0.1.1" dependencies = [ - "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zokrates_test 0.1.0", + "fs_extra", + "zokrates_test", ] [[package]] name = "zokrates_embed" -version = "0.1.0" +version = "0.1.1" dependencies = [ - "bellman_ce 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sapling-crypto_ce 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bellman_ce", + "sapling-crypto_ce", ] [[package]] name = "zokrates_field" -version = "0.3.4" +version = "0.3.5" dependencies = [ - "bellman_ce 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bellman_ce", + "bincode", + "ff_ce", + "lazy_static", + "num-bigint 0.2.6", + "num-integer", + "num-traits 0.2.11", + "pairing_ce", + "rand 0.4.6", + "serde", + "serde_derive", + "serde_json", + "sha2", ] [[package]] name = "zokrates_fs_resolver" -version = "0.4.2" +version = "0.5.0" dependencies = [ - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile", + "zokrates_common", ] [[package]] name = "zokrates_parser" -version = "0.1.3" +version = "0.1.4" dependencies = [ - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11", + "pest", + "pest_derive", ] [[package]] name = "zokrates_pest_ast" version = "0.1.3" dependencies = [ - "from-pest 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pest-ast 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "zokrates_field 0.3.4", - "zokrates_parser 0.1.3", + "from-pest", + "glob 0.2.11", + "lazy_static", + "pest", + "pest-ast", + "zokrates_field", + "zokrates_parser", ] [[package]] name = "zokrates_stdlib" -version = "0.1.4" +version = "0.1.5" dependencies = [ - "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zokrates_test 0.1.0", + "fs_extra", + "zokrates_test", ] [[package]] name = "zokrates_test" -version = "0.1.0" +version = "0.1.1" dependencies = [ - "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "zokrates_core 0.4.0", - "zokrates_field 0.3.4", - "zokrates_fs_resolver 0.4.2", + "fs_extra", + "glob 0.3.0", + "serde", + "serde_derive", + "serde_json", + "zokrates_core", + "zokrates_field", + "zokrates_fs_resolver", ] - -[metadata] -"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08abcc3b4e9339e33a3d0a5ed15d84a687350c05689d825e0f6655eef9e76a94" -"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" -"checksum assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72342c21057a3cb5f7c2d849bf7999a83795434dd36d74fa8c24680581bd1930" -"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" -"checksum backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5" -"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" -"checksum bellman_ce 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "938ec0feff00f9dfda0e7cbfe8db8b717966a84f6a12e63ed0943c4a90d6a5de" -"checksum bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e103c8b299b28a9c6990458b7013dc4a8356a9b854c51b9883241f5866fac36e" -"checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" -"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" -"checksum blake2-rfc_bellman_edition 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fdc60350286c7c3db13b98e91dbe5c8b6830a6821bc20af5b0c310ce94d74915" -"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" -"checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" -"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -"checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" -"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" -"checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" -"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" -"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64a4b57c8f4e3a2e9ac07e0f6abc9c24b6fc9e1b54c3478cfb598f3d0023e51c" -"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -"checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" -"checksum colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cdb90b60f2927f8d76139c72dbde7e10c3a2bc47c8594c9c7a66529f2687c03" -"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" -"checksum crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2d818a4990769aac0c7ff1360e233ef3a41adcb009ebb2036bf6915eb0f6b23c" -"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" -"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" -"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" -"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" -"checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -"checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d" -"checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" -"checksum curl-sys 0.4.22 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9a9a4e417722876332136a00cacf92c2ceb331fab4b52b6a1ad16c6cd79255" -"checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" -"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" -"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -"checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee" -"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" -"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" -"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" -"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" -"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" -"checksum ff_ce 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "18af1ea1b80a4b474fae13af4c58cf0a5a2bc33832d5fa70f68a4b286178fdb5" -"checksum ff_derive_ce 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d245b4e76c5b36bb7721ea15b7fbc61bebf0c5d2890eaf49fe1e2a3eed36db9" -"checksum from-pest 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aba9389cedcba1fb3a2aa2ed00f584f2606bce8e0106614a17327a24513bc60f" -"checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" -"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" -"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" -"checksum git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7339329bfa14a00223244311560d11f8f489b453fb90092af97f267a6090ab0" -"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" -"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" -"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -"checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" -"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b1d42ef453b30b7387e113da1c83ab1605d90c5b4e0eb8e96d016ed3b8c160" -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" -"checksum libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "48441cb35dc255da8ae72825689a95368bf510659ae1ad55dc4aa88cb1789bf1" -"checksum libssh2-sys 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8914d10b159fc288f2b6f253c94bd0c15a777fd5a297691141d89674b87e66fd" -"checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" -"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" -"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" -"checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" -"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" -"checksum num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" -"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" -"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" -"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" -"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" -"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" -"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.50 (registry+https://github.com/rust-lang/crates.io-index)" = "2c42dcccb832556b5926bc9ae61e8775f2a61e725ab07ab3d1e7fcf8ae62c3b6" -"checksum pairing_ce 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f075a9c570e2026111cb6dddf6a320e5163c42aa32500b315ec34acbcf7c9b36" -"checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc" -"checksum parity-wasm 0.35.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3e1e076c4e01399b6cd0793a8df42f90bba3ae424671ef421d1608a943155d93" -"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e4fb201c5c22a55d8b24fef95f78be52738e5e1361129be1b5e862ecdb6894a" -"checksum pest-ast 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3fbf404899169771dd6a32c84248b83cd67a26cc7cc957aac87661490e1227e4" -"checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" -"checksum pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9fcf299b5712d06ee128a556c94709aaa04512c4dffb8ead07c5c998447fc0" -"checksum pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df43fd99896fd72c485fe47542c7b500e4ac1e8700bf995544d1317a60ded547" -"checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea" -"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" -"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0" -"checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" -"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" -"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" -"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" -"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum reduce 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "75b1fa5668b02f2a69746bba558f8f98cc087b123a587fd959122872ad9a3f3c" -"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" -"checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" -"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" -"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -"checksum rgb 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2089e4031214d129e201f8c3c8c2fe97cd7322478a0d1cdf78e7029b0042efdb" -"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" -"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" -"checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" -"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" -"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" -"checksum sapling-crypto_ce 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d385cebab4241e694ca5979b0cbf9b353ba12fe6a17d66643a958b397362d56d" -"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" -"checksum serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "defbb8a83d7f34cc8380751eeb892b825944222888aff18996ea7901f24aec88" -"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" -"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" -"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" -"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" -"checksum single 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5add732a1ab689845591a1b50339cf5310b563e08dc5813c65991f30369ea2" -"checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" -"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" -"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" -"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" -"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" -"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" -"checksum typed-arena 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9c0704a799d314795d3d847d519b284bae681ef9b1f3da99f7ebc7b47ba2e607" -"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" -"checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" -"checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" -"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" -"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" -"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" -"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" -"checksum wasmi 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aebbaef470840d157a5c47c8c49f024da7b1b80e90ff729ca982b2b80447e78b" -"checksum wasmi-validation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab380192444b3e8522ae79c0a1976e42a82920916ccdfbce3def89f456ea33f3" -"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum winconsole 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef84b96d10db72dd980056666d7f1e7663ce93d82fa33b63e71c966f4cf5032" diff --git a/Cargo.toml b/Cargo.toml index e802801d..45bebfe0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ + "zokrates_common", "zokrates_core", "zokrates_cli", "zokrates_fs_resolver", @@ -9,4 +10,6 @@ members = [ "zokrates_abi", "zokrates_test", "zokrates_core_test", -] \ No newline at end of file +] + +exclude = ["zokrates_js"] \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 90b4e01c..f22d41fd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ MAINTAINER JacobEberhardt , Thibaut Schaeffer "] edition = "2018" @@ -9,4 +9,4 @@ zokrates_field = { version = "0.3", path = "../zokrates_field" } zokrates_core = { version = "0.4", path = "../zokrates_core" } serde = "1.0" serde_derive = "1.0" -serde_json = "1.0" +serde_json = "1.0" \ No newline at end of file diff --git a/zokrates_abi/src/lib.rs b/zokrates_abi/src/lib.rs index 5988a53e..3286233d 100644 --- a/zokrates_abi/src/lib.rs +++ b/zokrates_abi/src/lib.rs @@ -89,17 +89,17 @@ impl Value { match (self, ty) { (Value::Field(f), Type::FieldElement) => Ok(CheckedValue::Field(f)), (Value::Boolean(b), Type::Boolean) => Ok(CheckedValue::Boolean(b)), - (Value::Array(a), Type::Array(box inner_ty, size)) => { - if a.len() != size { + (Value::Array(a), Type::Array(array_type)) => { + if a.len() != array_type.size { Err(format!( "Expected array of size {}, found array of size {}", - size, + array_type.size, a.len() )) } else { let a = a .into_iter() - .map(|val| val.check(inner_ty.clone())) + .map(|val| val.check(*array_type.ty.clone())) .collect::, _>>()?; Ok(CheckedValue::Array(a)) } @@ -114,10 +114,10 @@ impl Value { } else { let s = members .into_iter() - .map(|(id, ty)| { - s.remove(&id) - .ok_or_else(|| format!("Member with id `{}` not found", id)) - .map(|v| v.check(ty).map(|v| (id, v))) + .map(|member| { + s.remove(&member.id) + .ok_or_else(|| format!("Member with id `{}` not found", member.id)) + .map(|v| v.check(*member.ty.clone()).map(|v| (member.id, v))) }) .collect::, _>>()? .into_iter() @@ -187,19 +187,19 @@ impl + PartialEq + Clone> Decode for CheckedValue { unreachable!() }) } - Type::Array(box inner_ty, _) => CheckedValue::Array( - raw.chunks(inner_ty.get_primitive_count()) - .map(|c| CheckedValue::decode(c.to_vec(), inner_ty.clone())) + Type::Array(array_type) => CheckedValue::Array( + raw.chunks(array_type.ty.get_primitive_count()) + .map(|c| CheckedValue::decode(c.to_vec(), *array_type.ty.clone())) .collect(), ), Type::Struct(members) => CheckedValue::Struct( members .into_iter() - .scan(0, |state, (id, ty)| { - let new_state = *state + ty.get_primitive_count(); - let res = CheckedValue::decode(raw[*state..new_state].to_vec(), ty); + .scan(0, |state, member| { + let new_state = *state + member.ty.get_primitive_count(); + let res = CheckedValue::decode(raw[*state..new_state].to_vec(), *member.ty); *state = new_state; - Some((id, res)) + Some((member.id, res)) }) .collect(), ), @@ -365,6 +365,7 @@ mod tests { mod strict { use super::*; + use zokrates_core::typed_absy::types::StructMember; #[test] fn fields() { @@ -409,7 +410,10 @@ mod tests { assert_eq!( parse_strict::( s, - vec![Type::Struct(vec![("a".into(), Type::FieldElement)])] + vec![Type::Struct(vec![StructMember::new( + "a".into(), + Type::FieldElement + )])] ) .unwrap(), CheckedValues(vec![CheckedValue::Struct( @@ -423,7 +427,10 @@ mod tests { assert_eq!( parse_strict::( s, - vec![Type::Struct(vec![("a".into(), Type::FieldElement)])] + vec![Type::Struct(vec![StructMember::new( + "a".into(), + Type::FieldElement + )])] ) .unwrap_err(), Error::Type("Member with id `a` not found".into()) @@ -433,7 +440,10 @@ mod tests { assert_eq!( parse_strict::( s, - vec![Type::Struct(vec![("a".into(), Type::FieldElement)])] + vec![Type::Struct(vec![StructMember::new( + "a".into(), + Type::FieldElement + )])] ) .unwrap_err(), Error::Type("Expected 1 member(s), found 0".into()) @@ -443,7 +453,10 @@ mod tests { assert_eq!( parse_strict::( s, - vec![Type::Struct(vec![("a".into(), Type::FieldElement)])] + vec![Type::Struct(vec![StructMember::new( + "a".into(), + Type::FieldElement + )])] ) .unwrap_err(), Error::Type("Value `false` doesn't match expected type `field`".into()) diff --git a/zokrates_book/src/SUMMARY.md b/zokrates_book/src/SUMMARY.md index 66a36ace..5fc05b52 100644 --- a/zokrates_book/src/SUMMARY.md +++ b/zokrates_book/src/SUMMARY.md @@ -18,6 +18,8 @@ - [Proving schemes](reference/proving_schemes.md) - [Verification](reference/verification.md) - [ZIR](reference/ir.md) + - [JSON ABI](reference/abi.md) - [Testing](reference/testing.md) - [Tutorial: Proof of preimage](./sha256example.md) +- [zokrates.js](./zokrates_js.md) diff --git a/zokrates_book/src/concepts/control_flow.md b/zokrates_book/src/concepts/control_flow.md index bfebf346..b799a249 100644 --- a/zokrates_book/src/concepts/control_flow.md +++ b/zokrates_book/src/concepts/control_flow.md @@ -14,7 +14,7 @@ Arguments are passed by value. ### If expressions -An if expression allows you to branch your code depending on a condition. +An if-expression allows you to branch your code depending on a condition. ```zokrates {{#include ../../../zokrates_cli/examples/book/if_else.zok}} @@ -32,5 +32,5 @@ For loops are available with the following syntax: {{#include ../../../zokrates_cli/examples/book/for.zok}} ``` -The bounds have to be known at compile time, so only constants are allowed. +The bounds have to be known at compile-time, so only constants are allowed. For-loops define their own scope. \ No newline at end of file diff --git a/zokrates_book/src/concepts/functions.md b/zokrates_book/src/concepts/functions.md index be307bae..cde731fd 100644 --- a/zokrates_book/src/concepts/functions.md +++ b/zokrates_book/src/concepts/functions.md @@ -21,7 +21,7 @@ When defining a variable as the return value of a function, types are optional: {{#include ../../../zokrates_cli/examples/book/multi_def.zok}} ``` -If there is an ambiguity, providing the types of some of the assigned variables is necessary. +If there is any ambiguity, providing the types of some of the assigned variables is necessary. ```zokrates {{#include ../../../zokrates_cli/examples/book/type_annotations.zok}} diff --git a/zokrates_book/src/concepts/imports.md b/zokrates_book/src/concepts/imports.md index 2472030a..e78c810c 100644 --- a/zokrates_book/src/concepts/imports.md +++ b/zokrates_book/src/concepts/imports.md @@ -35,13 +35,13 @@ from "./path/to/my/module" import main as module // `main` is now in scope under the alias `module`. ``` -Note that this legacy method is likely to be become deprecated, so it is recommended to use the preferred way instead. +Note that this legacy method is likely to become deprecated, so it is recommended to use the preferred way instead. ### Symbols -Two type of symbols can be imported +Two types of symbols can be imported #### Functions -Functions are imported by name. If many functions have the same name but different signatures, all of them get imported, and which one to use in a particular call is infered. +Functions are imported by name. If many functions have the same name but different signatures, all of them get imported, and which one to use in a particular call is inferred. #### User-defined types User-defined types declared with the `struct` keyword are imported by name. @@ -58,12 +58,11 @@ There also is a handy syntax to import from the parent directory: from "../mycode" import foo ``` -Also imports further up the file-system are supported: +Also, imports further up the file-system are supported: ```zokrates from "../../../mycode" import foo ``` ### Absolute Imports -Absolute imports don't start with `./` or `../` in the path and are used to import components from the ZoKrates standard library. Please check the according [section](./stdlib.html) for more details. -` \ No newline at end of file +Absolute imports don't start with `./` or `../` in the path and are used to import components from the ZoKrates standard library. Please check the according [section](./stdlib.html) for more details. \ No newline at end of file diff --git a/zokrates_book/src/concepts/stdlib.md b/zokrates_book/src/concepts/stdlib.md index 150afd97..92f710ac 100644 --- a/zokrates_book/src/concepts/stdlib.md +++ b/zokrates_book/src/concepts/stdlib.md @@ -23,7 +23,7 @@ import "hashes/sha256/512bit.zok" A function that takes 2 `field[256]` arrays as inputs and returns their sha256 compression function as an array of 256 field elements. The difference with `sha256` is that no padding is added at the end of the message, which makes it more efficient but also less compatible with Solidity. -There also is support for 2-round (1024-bit input) and and 3-round (1536-bit input) variants, using `hashes/1024bit.zok` or `hashes/1536bit.zok` respectively. +There also is support for 2-round (1024-bit input) and 3-round (1536-bit input) variants, using `hashes/1024bit.zok` and `hashes/1536bit.zok` respectively. #### sha256packed @@ -31,9 +31,9 @@ There also is support for 2-round (1024-bit input) and and 3-round (1536-bit inp import "hashes/sha256/512bitPacked.zok" ``` -A function that takes an array of 4 field elements as inputs, unpacks each of them to 128 bits (big endian), concatenates them and applies sha256. It then returns an array of 2 field elements, each representing 128 bits of the result. +A function that takes an array of 4 field elements as inputs, unpacks each of them to 128 bits (big-endian), concatenates them and applies sha256. It then returns an array of 2 field elements, each representing 128 bits of the result. -### Public-key Cryptography +### Public-key Cryptography #### Proof of private-key ownership @@ -41,8 +41,8 @@ A function that takes an array of 4 field elements as inputs, unpacks each of th import "ecc/proofOfOwnership.zok" ``` -Verifies match of a given public/private keypair. Checks if the following equation holds for the provided keypair: -`pk = sk*G` +Verifies match of a given public/private keypair. Checks if the following equation holds for the provided keypair: +`pk = sk*G` where `G` is the chosen base point of the subgroup and `*` denotes scalar multiplication in the subgroup. #### Signature verification @@ -85,5 +85,5 @@ Packs 256 field elements as one. Overflows can occur. import "utils/pack/nonStrictUnpack256" ``` -Unpacks a field element to 256 field elements. Uniqueness of the output is not guaranteed. +Unpacks a field element into 256 field elements. Uniqueness of the output is not guaranteed. diff --git a/zokrates_book/src/concepts/types.md b/zokrates_book/src/concepts/types.md index 657917f5..23d7beff 100644 --- a/zokrates_book/src/concepts/types.md +++ b/zokrates_book/src/concepts/types.md @@ -20,9 +20,9 @@ While `field` values mostly behave like unsigned integers, one should keep in mi ZoKrates has limited support for booleans, to the extent that they can only be used as the condition in `if ... else ... endif` expressions. -You can use them for equality checks and inequality checks between `field` values. +You can use them for equality and inequality checks between `field` values. -Note that while equality checks are cheap, inequality checks should be use wisely as they are orders of magnitude more expensive. +Note that while equality checks are cheap, inequality checks should be used wisely as they are orders of magnitude more expensive. ## Complex Types @@ -33,18 +33,18 @@ ZoKrates provides two complex types, Arrays and Structs. ZoKrates supports static arrays, i.e., their length needs to be known at compile time. Arrays can contain elements of any type and have arbitrary dimensions. -The following examples code shows examples of how to use arrays: +The following example code shows examples of how to use arrays: ```zokrates {{#include ../../../zokrates_cli/examples/book/array.zok}} ``` #### Declaration and Initialization -An array is defined by appending `[]` to a type literal representing the type of the array's elements. +An array is defined by appending `[]` to a type literal representing the type of the array's elements. -Initialization always needs to happen in the same statement as declaration, unless the array is declared within a function's signature. +Initialization always needs to happen in the same statement as a declaration, unless the array is declared within a function's signature. -For initialization, a list of comma-separated values is provided within brackets `[]`. +For initialization, a list of comma-separated values is provided within brackets `[]`. ZoKrates offers a special shorthand syntax to initialize an array with a constant value: `[value;repetitions]` @@ -60,7 +60,7 @@ The following code provides examples for declaration and initialization: As an array can contain any type of elements, it can contain arrays again. There is a special syntax to declare such multi-dimensional arrays, i.e., arrays of arrays. -To declare an array of an inner array, i.e., and array of elements of a type, prepend brackets `[size]` to the declaration of the inner array. +To declare an array of an inner array, i.e., and an array of elements of a type, prepend brackets `[size]` to the declaration of the inner array. In summary, this leads to the following scheme for array declarations: `data_type[size of 1st dimension][size of 2nd dimension]`. Consider the following example: @@ -76,7 +76,7 @@ ZoKrates provides some syntactic sugar to retrieve subsets of arrays. The spread operator `...` applied to an array copies the elements of the existing array. This can be used to conveniently compose new arrays, as shown in the following example: ``` -field[3] = [1, 2, 3] +field[3] a = [1, 2, 3] field[4] c = [...a, 4] // initialize an array copying values from `a`, followed by 4 ``` @@ -89,8 +89,8 @@ field[2] b = a[1..3] // initialize an array copying a slice from `a` ``` ### Structs -A struct is a composite datatype representing a named collection of variables. -The contained variables can be of any type. +A struct is a composite datatype representing a named collection of variables. +The contained variables can be of any type. The following code shows an example of how to use structs. @@ -111,7 +111,7 @@ struct Point { #### Declaration and Initialization -Initialization of a variable of a struct type always needs to happen in the same statement as declaration, unless the struct-typed variable is declared within a function's signature. +Initialization of a variable of a struct type always needs to happen in the same statement as a declaration, unless the struct-typed variable is declared within a function's signature. The following example shows declaration and initialization of a variable of the `Point` struct type: diff --git a/zokrates_book/src/gettingstarted.md b/zokrates_book/src/gettingstarted.md index 6e0bad85..52477193 100644 --- a/zokrates_book/src/gettingstarted.md +++ b/zokrates_book/src/gettingstarted.md @@ -2,6 +2,10 @@ ## Installation +### Remix online IDE + +To write your first SNARK program, check out the ZoKrates plugin in the [Remix online IDE](https://remix.ethereum.org)! + ### One-line install We provide a one-line install for Linux, MacOS and FreeBSD: @@ -22,7 +26,7 @@ From there on, you can use the `zokrates` CLI. ### From source -You can build the container yourself from [source](https://github.com/ZoKrates/ZoKrates/) with the following commands: +You can build ZoKrates from [source](https://github.com/ZoKrates/ZoKrates/) with the following commands: ```bash git clone https://github.com/ZoKrates/ZoKrates @@ -47,15 +51,15 @@ Then run the different phases of the protocol: ```bash # compile -./zokrates compile -i root.zok +zokrates compile -i root.zok # perform the setup phase -./zokrates setup +zokrates setup # execute the program -./zokrates compute-witness -a 337 113569 +zokrates compute-witness -a 337 113569 # generate a proof of computation -./zokrates generate-proof +zokrates generate-proof # export a solidity verifier -./zokrates export-verifier +zokrates export-verifier ``` The CLI commands are explained in more detail in the [CLI reference](reference/cli.md). diff --git a/zokrates_book/src/introduction.md b/zokrates_book/src/introduction.md index 779373ce..69bcc28d 100644 --- a/zokrates_book/src/introduction.md +++ b/zokrates_book/src/introduction.md @@ -6,7 +6,7 @@ ZoKrates is a toolbox for zkSNARKs on Ethereum. It helps you use verifiable comp ## Background on zkSNARKs Zero-knowledge proofs (ZKPs) are a family of probabilistic protocols, first described by [Goldwasser, Micali and Rackoff](http://people.csail.mit.edu/silvio/Selected%20Scientific%20Papers/Proof%20Systems/The_Knowledge_Complexity_Of_Interactive_Proof_Systems.pdf) in 1985. - + One particular family of ZKPs is described as zero-knowledge **S**uccinct **N**on-interactive **AR**guments of **K**nowledge, a.k.a. zkSNARKs. zkSNARKs are the most widely used zero-knowledge protocols, with the anonymous cryptocurrency Zcash and the smart-contract platform Ethereum among the notable early adopters. For further details we refer the reader to some introductory material provided by the community: [[1]](https://z.cash/technology/zksnarks/),[[2]](https://medium.com/@VitalikButerin/zkSNARKs-under-the-hood-b33151a013f6), [[3]](https://blog.decentriq.ch/zk-SNARKs-primer-part-one/). diff --git a/zokrates_book/src/reference/abi.md b/zokrates_book/src/reference/abi.md new file mode 100644 index 00000000..bfd03c05 --- /dev/null +++ b/zokrates_book/src/reference/abi.md @@ -0,0 +1,96 @@ +# ZoKrates ABI + +In order to interact programatically with compiled ZoKrates programs, ZoKrates supports passing arguments using an ABI. + +To illustrate this, we'll use the following example program: + +``` +struct Bar { + field a +} + +struct Foo { + field a + Bar b +} + +def main(private Foo foo, bool[2] bar, field num) -> (field): + return 42 +``` + +## ABI specification + +When compiling a program, an ABI specification is generated and describes the interface of the program. + +In this example, the ABI specification is: + +```json +{ + "inputs": [ + { + "name": "foo", + "public": false, + "type": "struct", + "components": [ + { + "name": "a", + "type": "field" + }, + { + "name": "b", + "type": "struct", + "components": [ + { + "name": "a", + "type": "field" + } + ] + } + ] + }, + { + "name": "bar", + "public": "true", + "type": "array", + "components": { + "size": 2, + "type": "bool" + } + }, + { + "name": "num", + "public": "true", + "type": "field" + } + ], + "outputs": [ + { + "type": "field" + } + ] +} +``` + + +## ABI input format + +When executing a program, arguments can be passed as a JSON object of the following form: + +```json +[ + { + "a": "42", + "b": + { + "a": "42" + } + }, + [ + true, + false + ], + "42" +] +``` + +Note that field elements are passed as JSON strings in order to support arbitrary large numbers. \ No newline at end of file diff --git a/zokrates_book/src/reference/cli.md b/zokrates_book/src/reference/cli.md index f097e663..c443422e 100644 --- a/zokrates_book/src/reference/cli.md +++ b/zokrates_book/src/reference/cli.md @@ -5,23 +5,28 @@ You can see an overview of the available subcommands by running ```sh zokrates +<<<<<<< HEAD ``` You can get help about a particular subcommand with `--help`, for example: ```sh zokrates compile --help +======= +>>>>>>> develop ``` +For each command, you can get the list of expected arguments using `--help`. + ## `compile` ```sh zokrates compile -i /path/to/add.zok ``` -Compiles a `.zok` source code file into ZoKrates internal representation of arithmetic circuits. +Compiles a `.zok` source code file into ZoKrates internal representation of arithmetic circuits. Creates a compiled binary file at `./out`. -Unless the `--light` flag is set, a human readable `.ztf` file is generated, which displays the compilation output in ZoKrates Text Format. +Unless the `--light` flag is set, a human-readable `.ztf` file is generated, which displays the compilation output in ZoKrates Text Format. ## `compute-witness` @@ -29,9 +34,15 @@ Unless the `--light` flag is set, a human readable `.ztf` file is generated, whi zokrates compute-witness -a 1 2 3 ``` -Computes a witness for the compiled program found at `./out` and arguments to the program. -A witness is a valid assignment of the variables, which include the results of the computation. -Arguments to the program are passed as a space-separated list with the `-a` flag, or over `stdin`. +Computes a witness for the compiled program found at `./out` and computes arguments of the program. +A witness is a valid assignment of the variables, including the results of the computation. +Arguments of the program are passed as a space-separated list with the `-a` flag, or over `stdin` with the `--stdin` flag. + +With the `--abi` flag, arguments are passed in the ZoKrates JSON ABI format described [here](reference/abi.md): + +```sh +cat arguments.json | zokrates compute-witness --stdin --abi +``` Creates a witness file at `./witness` @@ -44,7 +55,7 @@ zokrates setup Generates a trusted setup for the compiled program found at `./out`. Creates a proving key and a verifying key at `./proving.key` and `./verifying.key`. -These keys are derived from a source of randomness, commonly referred to as “toxic waste”. Anyone having access to the source of randomness can produce fake proofs that will be accepted by a verifier following the protocol. +These keys are derived from a source of randomness, commonly referred to as "toxic waste". Anyone having access to the source of randomness can produce fake proofs that will be accepted by a verifier following the protocol. The [proving scheme](proving_schemes.md) and curve can be chosen with the `proving-scheme` and `curve` flags. @@ -54,7 +65,7 @@ The [proving scheme](proving_schemes.md) and curve can be chosen with the `provi zokrates export-verifier ``` -Using the verifying key at `./verifying.key`, generates a Solidity contract which contains the generated verification key and a public function to verify a solution to the compiled program at `./out`. +Using the verifying key at `./verifying.key`, generates a Solidity contract that contains the generated verification key and a public function to verify a solution to the compiled program at `./out`. Creates a verifier contract at `./verifier.sol`. diff --git a/zokrates_book/src/reference/index.md b/zokrates_book/src/reference/index.md index cb033c11..0d4cc1e3 100644 --- a/zokrates_book/src/reference/index.md +++ b/zokrates_book/src/reference/index.md @@ -7,4 +7,5 @@ The reference covers the details of various areas of ZoKrates. - [Proving schemes](proving_schemes.md) - [Verification](verification.md) - [ZIR](ir.md) + - [JSON ABI](abi.md) - [Testing](testing.md) \ No newline at end of file diff --git a/zokrates_book/src/reference/proving_schemes.md b/zokrates_book/src/reference/proving_schemes.md index 318f554f..a938f217 100644 --- a/zokrates_book/src/reference/proving_schemes.md +++ b/zokrates_book/src/reference/proving_schemes.md @@ -39,7 +39,7 @@ cargo +nightly -Z package-features build --release --package zokrates_cli --feat ## G16 malleability -When using G16, developers should pay attention to the fact that an attacker seeing a valid proof can very easily generate a different but still valid proof. Therefore, depending on the use case, making sure on chain that the same proof cannot be submitted twice may *not* be enough to guarantee that attackers cannot replay proofs. Mechanisms to solve this issue include: +When using G16, developers should pay attention to the fact that an attacker, seeing a valid proof, can very easily generate a different but still valid proof. Therefore, depending on the use case, making sure on chain that the same proof cannot be submitted twice may *not* be enough to guarantee that attackers cannot replay proofs. Mechanisms to solve this issue include: - signed proofs - nullifiers - usage of an ethereum address as a public input to the program diff --git a/zokrates_book/src/reference/testing.md b/zokrates_book/src/reference/testing.md index 6526dbe9..0af9706f 100644 --- a/zokrates_book/src/reference/testing.md +++ b/zokrates_book/src/reference/testing.md @@ -1,10 +1,10 @@ # Testing -Before running any tests, make sure make sure your `ZOKRATES_HOME` environment variable is set correctly. +Before running any tests, make sure your `ZOKRATES_HOME` environment variable is set correctly. It has to point to `zokrates_stdlib/stdlib/` ## Unit tests -In ZoKrates, unit tests comprise +In ZoKrates, unit tests comprise of - internal tests for all zokrates crates - compilation tests for all examples in `zokrates_cli/examples`. These tests only ensure that the examples compile. - compilation + witness-computation tests. These tests compile the test cases, compute a witness and compare the result with a pre-defined expected result. @@ -24,10 +24,10 @@ Integration tests are excluded from `cargo test` by default. They are defined in the `zokrates_cli` crate in `integration.rs` and use the test cases specified in `zokrates_cli/tests/code`. Before running integration tests: -1. Make sure your `$ZOKRATES_HOME` is set correctly +1. Make sure your `$ZOKRATES_HOME` is set correctly 2. You have [solc](https://github.com/ethereum/solc-js) installed and in your `$PATH`. - Solc can conveniently be installed through `npm` by running + Solc can conveniently be installed through `npm` by running ``` npm install -g solc ``` diff --git a/zokrates_book/src/sha256example.md b/zokrates_book/src/sha256example.md index 38572546..021df987 100644 --- a/zokrates_book/src/sha256example.md +++ b/zokrates_book/src/sha256example.md @@ -1,9 +1,9 @@ # Tutorial: Proving knowledge of a hash preimage -Let’s jump into ZoKrates by working through a hands-on project together! +Let's jump into ZoKrates by working through a hands-on project together! -We’ll implement an operation that's very typical in blockchain use-cases: proving knowledge of the preimage for a given hash digest. -In particular, we'll show how ZoKrates and the Ethereum blockchain can be used to allow a prover, let’s call her Peggy, to demonstrate beyond any reasonable doubt to a verifier, let’s call him Victor, that she knows a hash preimage for a digest chosen by Victor, without revealing what the preimage is. +We'll implement an operation that's very typical in blockchain use-cases: proving knowledge of the preimage for a given hash digest. +In particular, we'll show how ZoKrates and the Ethereum blockchain can be used to allow a prover, let's call her Peggy, to demonstrate beyond any reasonable doubt to a verifier, let's call him Victor, that she knows a hash preimage for a digest chosen by Victor, without revealing what the preimage is. ## Pre-requisites @@ -21,9 +21,9 @@ First, we create a new file named `hashexample.zok` with the following content: The first line imports the `sha256packed` function from the ZoKrates standard library. -`sha256packed` is a SHA256 implementation that is optimized for the use in the ZoKrates DSL. Here is how it works: We want to pass 512 bits of input to sha256. However, a `field` value can only hold 254 bits due to the size of the underlying prime field we are using. As a consequence, we use four field elements, each one encoding 128 bits, to represent our input. The four elements are then concatenated in ZoKrates and passed to SHA256. Given that the resulting hash is 256 bit long, we split it in two and return each value as a 128 bit number. +`sha256packed` is a SHA256 implementation that is optimized for the use in the ZoKrates DSL. Here is how it works: We want to pass 512 bits of input to SHA256. However, a `field` value can only hold 254 bits due to the size of the underlying prime field we are using. As a consequence, we use four field elements, each one encoding 128 bits, to represent our input. The four elements are then concatenated in ZoKrates and passed to SHA256. Given that the resulting hash is 256 bit long, we split it in two and return each value as a 128 bit number. -In case you are interested in an example that is fully compliant with existing SHA256 implementations in Python or Solidity you can have a look at this [blog](https://blog.decentriq.ch/proving-hash-pre-image-zksnarks-zokrates) post. +In case you are interested in an example that is fully compliant with existing SHA256 implementations in Python or Solidity, you can have a look at this [blog](https://blog.decentriq.ch/proving-hash-pre-image-zksnarks-zokrates) post. Our code is really just using the `sha256packed`, returning the computed hash. @@ -63,7 +63,7 @@ Hence, by concatenating the outputs as 128 bit numbers, we arrive at the followi For now, we have seen that we can compute a hash using ZoKrates. -Let's recall our goal: Peggy wants to prove that she knows a preimage for a digest chosen by Victor, without revealing what the preimage is. Without loss of generality, let's now assume that Victor choses the digest to be the one we found in our example above. +Let's recall our goal: Peggy wants to prove that she knows a preimage for a digest chosen by Victor, without revealing what the preimage is. Without loss of generality, let's now assume that Victor chooses the digest to be the one we found in our example above. To make it work, the two parties have to follow their roles in the protocol: @@ -81,7 +81,7 @@ So, having defined the program, Victor is now ready to compile the code: ./zokrates compile -i hashexample.zok ``` -Based on that Victor can run the setup phase and export verifier smart contract as a Solidity file: +Based on that Victor can run the setup phase and export a verifier smart contract as a Solidity file: ```sh ./zokrates setup @@ -104,14 +104,14 @@ Finally, Peggy can run the command to construct the proof: ./zokrates generate-proof ``` -As the inputs were declared as private in the program, they do not appear in the proof thanks to the zero knowledge property of the protocol. +As the inputs were declared as private in the program, they do not appear in the proof thanks to the zero-knowledge property of the protocol. ZoKrates creates a file, `proof.json`, consisting of the three elliptic curve points that make up the zkSNARKs proof. The `verifyTx` function in the smart contract deployed by Victor accepts these three values, along with an array of public inputs. The array of public inputs consists of: * any public inputs to the main function, declared without the `private` keyword * the return values of the ZoKrates function -In the example we're considering, all inputs are private and there is a single return value of `1`, hence Peggy has to define her public input array as follows: `[1]` +In the example we're considering, all inputs are private and there is a single return value of `1`, hence Peggy has to define her public input array as follows: `[1]`. Peggy can then submit her proof by calling `verifyTx`. @@ -119,10 +119,10 @@ Victor monitors the verification smart contract for the `Verified` event, which ## Conclusion -At this point, you’ve successfully ran you first zkSNARK on the Ethereum blockchain. Congratulations! +At this point, you've successfully ran you first zkSNARK on the Ethereum blockchain. Congratulations! >Remember that in this example only two parties were involved. This special case makes it easy to deal with the trust assumptions of zkSNARKs: only Victor was interested in verifying the claim by Peggy, hence he can trust his execution of the setup phase. > ->In general, multiple parties may be interested in verifying the correctness of Peggy's statement. For example, in the zero-knowledge based cryptocurrency Zcash, each node needs to be able to validate the correctness of transactions. In order to generalize the setup phase to these multi-party use-cases a tricky process, commonly referred to as “trusted setup” or "ceremony" needs to be conducted. +>In general, multiple parties may be interested in verifying the correctness of Peggy's statement. For example, in the zero-knowledge based cryptocurrency Zcash, each node needs to be able to validate the correctness of transactions. In order to generalize the setup phase to these multi-party use-cases a tricky process, commonly referred to as "trusted setup" or "ceremony" needs to be conducted. > >ZoKrates would welcome ideas to add support for such ceremonies! diff --git a/zokrates_book/src/zokrates_js.md b/zokrates_book/src/zokrates_js.md new file mode 100644 index 00000000..8d162c74 --- /dev/null +++ b/zokrates_book/src/zokrates_js.md @@ -0,0 +1,37 @@ +# zokrates.js + +You can get JavaScript bindings for ZoKrates by running + +```bash +npm install zokrates-js +``` + +## API + +| Function | Description | +| ------ | ------ | +| initialize | Loads binding wasm module and returns a promise with ZoKrates provider | +| compile | Compiles source code into ZoKrates internal representation of arithmetic circuits | +| computeWitness | Computes a valid assignment of the variables, which include the results of the computation | +| setup | Generates a trusted setup for the compiled program | +| exportSolidityVerifier | Generates a Solidity contract which contains the generated verification key and a public function to verify a solution to the compiled program | +| generateProof | Generates a proof for a computation of the compiled program | + +## Usage + +```js +import { initialize } from 'zokrates-js'; + +function importResolver(location, path) { + // implement your resolving logic here + return { + source: "def main() -> (): return", + location: path + }; +} + +initialize().then((zokratesProvider) => { + // we have to initialize the wasm module before calling api functions + zokratesProvider.compile("def main(private field a) -> (field): return a", "main", importResolver) +}); +``` diff --git a/zokrates_cli/Cargo.toml b/zokrates_cli/Cargo.toml index 60dcabca..f5dcb6f0 100644 --- a/zokrates_cli/Cargo.toml +++ b/zokrates_cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_cli" -version = "0.5.0" +version = "0.5.2" authors = ["Jacob Eberhardt ", "Dennis Kuhnert ", "Thibaut Schaeffer "] repository = "https://github.com/JacobEberhardt/ZoKrates.git" edition = "2018" @@ -8,7 +8,6 @@ edition = "2018" [features] default = [] libsnark = ["zokrates_core/libsnark"] -wasm = ["zokrates_core/wasm"] [dependencies] clap = "2.26.2" @@ -17,7 +16,7 @@ regex = "0.2" zokrates_field = { version = "0.3", path = "../zokrates_field" } zokrates_abi = { version = "0.1", path = "../zokrates_abi" } zokrates_core = { version = "0.4", path = "../zokrates_core" } -zokrates_fs_resolver = { version = "0.4", path = "../zokrates_fs_resolver"} +zokrates_fs_resolver = { version = "0.5", path = "../zokrates_fs_resolver"} serde_json = "1.0" [dev-dependencies] diff --git a/zokrates_cli/examples/arrays/update.zok b/zokrates_cli/examples/arrays/update.zok index de92cda1..ef660b33 100644 --- a/zokrates_cli/examples/arrays/update.zok +++ b/zokrates_cli/examples/arrays/update.zok @@ -4,6 +4,6 @@ def foo(field[3] a) -> (field): def main() -> (field, field): field[3] a = [0, 0, 0] - res = foo(a) + field res = foo(a) a[1] == 0 return res, a[1] diff --git a/zokrates_cli/examples/book/hashexample.zok b/zokrates_cli/examples/book/hashexample.zok index ba90147e..24f1e824 100644 --- a/zokrates_cli/examples/book/hashexample.zok +++ b/zokrates_cli/examples/book/hashexample.zok @@ -1,5 +1,5 @@ import "hashes/sha256/512bitPacked" as sha256packed def main(private field a, private field b, private field c, private field d) -> (field[2]): - h = sha256packed([a, b, c, d]) + field[2] h = sha256packed([a, b, c, d]) return h \ No newline at end of file diff --git a/zokrates_cli/examples/book/hashexample_updated.zok b/zokrates_cli/examples/book/hashexample_updated.zok index b7daee58..c231f72e 100644 --- a/zokrates_cli/examples/book/hashexample_updated.zok +++ b/zokrates_cli/examples/book/hashexample_updated.zok @@ -1,7 +1,7 @@ import "hashes/sha256/512bitPacked" as sha256packed def main(private field a, private field b, private field c, private field d) -> (field): - h = sha256packed([a, b, c, d]) + field[2] h = sha256packed([a, b, c, d]) h[0] == 263561599766550617289250058199814760685 h[1] == 65303172752238645975888084098459749904 return 1 \ No newline at end of file diff --git a/zokrates_cli/examples/book/multi_def.zok b/zokrates_cli/examples/book/multi_def.zok index fca062f0..55e58055 100644 --- a/zokrates_cli/examples/book/multi_def.zok +++ b/zokrates_cli/examples/book/multi_def.zok @@ -2,5 +2,5 @@ def foo() -> (field, field): return 21, 42 def main() -> (field): - a, b = foo() + field a, field b = foo() return 1 \ No newline at end of file diff --git a/zokrates_cli/examples/book/struct_assign.code b/zokrates_cli/examples/book/struct_assign.zok similarity index 100% rename from zokrates_cli/examples/book/struct_assign.code rename to zokrates_cli/examples/book/struct_assign.zok diff --git a/zokrates_cli/examples/book/struct_init.code b/zokrates_cli/examples/book/struct_init.zok similarity index 100% rename from zokrates_cli/examples/book/struct_init.code rename to zokrates_cli/examples/book/struct_init.zok diff --git a/zokrates_cli/examples/book/structs.code b/zokrates_cli/examples/book/structs.zok similarity index 96% rename from zokrates_cli/examples/book/structs.code rename to zokrates_cli/examples/book/structs.zok index a08399ba..7cca5707 100644 --- a/zokrates_cli/examples/book/structs.code +++ b/zokrates_cli/examples/book/structs.zok @@ -5,7 +5,7 @@ struct Bar { struct Foo { Bar a - bool b + bool b } def main() -> (Foo): diff --git a/zokrates_cli/examples/book/type_annotations.zok b/zokrates_cli/examples/book/type_annotations.zok index cb71575b..8cff31e1 100644 --- a/zokrates_cli/examples/book/type_annotations.zok +++ b/zokrates_cli/examples/book/type_annotations.zok @@ -5,5 +5,5 @@ def foo() -> (field, field): return 1, 2 def main() -> (field): - a, field[3] b = foo() + field a, field[3] b = foo() return 1 \ No newline at end of file diff --git a/zokrates_cli/examples/bool_or.zok b/zokrates_cli/examples/bool_or.zok index a698347f..664b7eea 100644 --- a/zokrates_cli/examples/bool_or.zok +++ b/zokrates_cli/examples/bool_or.zok @@ -3,5 +3,5 @@ def main(field a, field b) -> (field): field y = if a + 2 == 4 || b * 2 == 2 then 1 else 0 fi field z = if y == 1 || y == 0 then y else 1 fi z == 1 - return z + return z diff --git a/zokrates_cli/examples/dex/decodeOrder.zok b/zokrates_cli/examples/dex/decodeOrder.zok index db917f29..5ed9bdaf 100644 --- a/zokrates_cli/examples/dex/decodeOrder.zok +++ b/zokrates_cli/examples/dex/decodeOrder.zok @@ -9,6 +9,7 @@ def main(field order) -> (field, field, field, field): // LSB field amount = 0 field exponent = 1 + field bit = 0 for field i in 0..120 do bit, order = popLeastSignificantBit(order) amount = amount + (bit * exponent) diff --git a/zokrates_cli/examples/dex/ringtrade_example.zok b/zokrates_cli/examples/dex/ringtrade_example.zok index 44f50479..b966ead1 100644 --- a/zokrates_cli/examples/dex/ringtrade_example.zok +++ b/zokrates_cli/examples/dex/ringtrade_example.zok @@ -43,20 +43,20 @@ def checkConstraints(field[3] amount, field[3] sourceToken, field[3] targetToken field[3] sourceTokenPriceOrder = [0, 0, 0] field[3] targetTokenPriceOrder = [0, 0, 0] - + for field i in 0..3 do sourceTokenPriceOrder[i] = priceToken[sourceToken[i]] targetTokenPriceOrder[i] = priceToken[targetToken[i]] endfor - // orders are only touched, if the limit price is below the calculated price: + // orders are only touched if the limit price is below the calculated price: for field i in 0..3 do 1 == if volume[i] == 0 then 1 else limitLessThanPrice(sourceTokenPriceOrder[i], targetTokenPriceOrder[i], limit[i]) fi endfor // the amount of sell volume for a token equals its buy volume: - buyVolumeToken = tupleForTokensWithValue(0) - sellVolumeToken = tupleForTokensWithValue(0) + field[3] buyVolumeToken = tupleForTokensWithValue(0) + field[3] sellVolumeToken = tupleForTokensWithValue(0) for field i in 0..3 do buyVolumeToken = addVolumesForOrder(buyVolumeToken, targetToken[i], volume[i] * sourceTokenPriceOrder[i]) @@ -66,9 +66,9 @@ def checkConstraints(field[3] amount, field[3] sourceToken, field[3] targetToken buyVolumeToken == sellVolumeToken // If an order σ ∈ Oi→j with a limit price p has a positive trading volume, then every order in Oi→j with a lower limit price should be completely fulfilled. - highestTouchedOrder = tupleForTokenPairsWithValue(0) + field[9] highestTouchedOrder = tupleForTokenPairsWithValue(0) - for field i in 0..3 do + for field i in 0..3 do highestTouchedOrder = updateHighestTouchedOrder(highestTouchedOrder, sourceToken[i], targetToken[i], limit[i], volume[i]) endfor @@ -76,7 +76,7 @@ def checkConstraints(field[3] amount, field[3] sourceToken, field[3] targetToken 1 == verifyCompletelyFulfilledIfLimitLowerHighestTouchedOrder(highestTouchedOrder, amount[i], sourceToken[i], targetToken[i], limit[i], volume[i]) endfor - return 1 // Could return total volume to maximize for + return 1 // Could return the total volume to maximize for def main(private field[3] encodedOrder, private field[3] bitmapOrder, private field[3] volume, private field[3] priceToken) -> (field): // Remove orders that are not double signed @@ -88,8 +88,8 @@ def main(private field[3] encodedOrder, private field[3] bitmapOrder, private fi field[3] limit = [0, 0, 0] // Decode orders - for field i in 0..3 do - a, s, t, l = decodeOrder(encodedOrder[i]) + for field i in 0..3 do + field a, field s, field t, field l = decodeOrder(encodedOrder[i]) amount[i] = a sourceToken[i] = s targetToken[i] = t diff --git a/zokrates_cli/examples/functions/expressions.zok b/zokrates_cli/examples/functions/expressions.zok index 71340136..9d650213 100644 --- a/zokrates_cli/examples/functions/expressions.zok +++ b/zokrates_cli/examples/functions/expressions.zok @@ -4,7 +4,7 @@ def add(field a,field b) -> (field): // Expected for inputs 1,1: c=4, d=7, e=10 def main(field a,field b) -> (field): - c = add(a*2+3*b-a,b-1) - d = add(a*b+2, a*b*c) - e = add(add(a,d),add(a,b)) + field c = add(a*2+3*b-a,b-1) + field d = add(a*b+2, a*b*c) + field e = add(add(a,d),add(a,b)) return e diff --git a/zokrates_cli/examples/functions/functions.zok b/zokrates_cli/examples/functions/functions.zok index ab0d8c91..7a0b4cc9 100644 --- a/zokrates_cli/examples/functions/functions.zok +++ b/zokrates_cli/examples/functions/functions.zok @@ -2,5 +2,5 @@ def add(field f,field g) -> (field): return f+g def main(field a, field b) -> (field): - c = add(a,b) + field c = add(a,b) return c diff --git a/zokrates_cli/examples/functions/lt_comparison b/zokrates_cli/examples/functions/lt_comparison.zok similarity index 94% rename from zokrates_cli/examples/functions/lt_comparison rename to zokrates_cli/examples/functions/lt_comparison.zok index b32a33fa..edeb29d9 100644 --- a/zokrates_cli/examples/functions/lt_comparison +++ b/zokrates_cli/examples/functions/lt_comparison.zok @@ -4,7 +4,7 @@ def lt(field a,field b) -> (field): def cutoff() -> (field): return 31337 -def getThing(index) -> (field): +def getThing(field index) -> (field): field result = 3 result = if index == 0 then 13 else result fi result = if index == 1 then 23 else result fi diff --git a/zokrates_cli/examples/functions/multi_functions.zok b/zokrates_cli/examples/functions/multi_functions.zok index d43ad5eb..9a0ce961 100644 --- a/zokrates_cli/examples/functions/multi_functions.zok +++ b/zokrates_cli/examples/functions/multi_functions.zok @@ -4,8 +4,8 @@ def add(field a, field b) -> (field): def main(field a, field b,field c, field d) -> (field): field g = a + b - x = add(a,b) - y = add(c,d) + field x = add(a,b) + field y = add(c,d) g = add(x, g) g = add(x, g) field f = c + d + a diff --git a/zokrates_cli/examples/functions/multi_shadowing.zok b/zokrates_cli/examples/functions/multi_shadowing.zok index ca4edcd6..dea0b545 100644 --- a/zokrates_cli/examples/functions/multi_shadowing.zok +++ b/zokrates_cli/examples/functions/multi_shadowing.zok @@ -6,6 +6,6 @@ def sub(field a, field b) -> (field): return a-b def main(field a, field b) -> (field): - c = add(a,b) - d = sub(a,b) + field c = add(a,b) + field d = sub(a,b) return 0 diff --git a/zokrates_cli/examples/merkleTree/pedersenPathProof3.zok b/zokrates_cli/examples/merkleTree/pedersenPathProof3.zok index 4f8fdaed..1ac9251f 100644 --- a/zokrates_cli/examples/merkleTree/pedersenPathProof3.zok +++ b/zokrates_cli/examples/merkleTree/pedersenPathProof3.zok @@ -1,18 +1,19 @@ import "hashes/pedersen/512bit" as hash import "ecc/edwardsCompress" as edwardsCompress import "ecc/babyjubjubParams" as context +from "ecc/babyjubjubParams" import BabyJubJubParams import "hashes/utils/256bitsDirectionHelper" as multiplex import "utils/binary/not" as NOT -// Merke-Tree inclusion proof for tree depth 3 using SNARK efficient pedersen hashes +// Merke-Tree inclusion proof for tree depth 3 using SNARK efficient pedersen hashes // directionSelector=> 1/true if current digest is on the rhs of the hash def main(field[256] rootDigest, private field[256] leafDigest, private field[3] directionSelector, field[256] PathDigest0, private field[256] PathDigest1, private field[256] PathDigest2) -> (field): - context = context() + BabyJubJubParams context = context() //Setup field[256] currentDigest = leafDigest //Loop up the tree - preimage = multiplex(directionSelector[0], currentDigest, PathDigest0) + field[512] preimage = multiplex(directionSelector[0], currentDigest, PathDigest0) currentDigest = hash(preimage) preimage = multiplex(directionSelector[1], currentDigest, PathDigest1) @@ -23,5 +24,5 @@ def main(field[256] rootDigest, private field[256] leafDigest, private field[3] rootDigest == currentDigest - return 1 //return true in success + return 1 //return true in success diff --git a/zokrates_cli/examples/merkleTree/sha256PathProof3.zok b/zokrates_cli/examples/merkleTree/sha256PathProof3.zok index f8f570c6..8d9bd0f3 100644 --- a/zokrates_cli/examples/merkleTree/sha256PathProof3.zok +++ b/zokrates_cli/examples/merkleTree/sha256PathProof3.zok @@ -2,7 +2,7 @@ import "hashes/sha256/512bit" as sha256 import "utils/multiplexer/256bit" as multiplex import "utils/binary/not" as NOT -// Merke-Tree inclusion proof for tree depth 3 +// Merkle-Tree inclusion proof for tree depth 3 def main(field treeDepth, field[256] rootDigest, private field[256] leafDigest, private field[2] directionSelector, field[256] PathDigest0, private field[256] PathDigest1) -> (field): @@ -13,8 +13,8 @@ def main(field treeDepth, field[256] rootDigest, private field[256] leafDigest, //Loop up the tree currentDirection = directionSelector[0] - lhs = multiplex(currentDirection, currentDigest, PathDigest0) - rhs = multiplex(NOT(currentDirection), currentDigest, PathDigest0) + field[256] lhs = multiplex(currentDirection, currentDigest, PathDigest0) + field[256] rhs = multiplex(NOT(currentDirection), currentDigest, PathDigest0) currentDigest = sha256(lhs, rhs) counter = counter + 1 @@ -28,4 +28,4 @@ def main(field treeDepth, field[256] rootDigest, private field[256] leafDigest, counter == treeDepth rootDigest == currentDigest - return 1 //return true in success \ No newline at end of file + return 1 //return true in success \ No newline at end of file diff --git a/zokrates_cli/examples/merkleTree/testpedersenPathProof3.zok b/zokrates_cli/examples/merkleTree/testpedersenPathProof3.zok index c71b809c..29b2c4c2 100644 --- a/zokrates_cli/examples/merkleTree/testpedersenPathProof3.zok +++ b/zokrates_cli/examples/merkleTree/testpedersenPathProof3.zok @@ -1,5 +1,5 @@ import "./pedersenPathProof3" -// Merke-Tree inclusion proof for tree depth 3 +// Merke-Tree inclusion proof for tree depth 3 // def main(field treeDepth, field[256] rootDigest, private field[256] leafDigest, private field[2] directionSelector, field[256] PathDigest0, private field[256] PathDigest1) -> (field): def main() -> (field): @@ -16,5 +16,5 @@ def main() -> (field): field success = pedersenPathProof3(rootDigest, leafDigest, [0, 0, 0], PathDigest0, PathDigest1, PathDigest2) - return 1 //return true in success + return 1 //return true in success diff --git a/zokrates_cli/examples/merkleTree/testsha256PathProof3.zok b/zokrates_cli/examples/merkleTree/testsha256PathProof3.zok index 586e082c..bd12492b 100644 --- a/zokrates_cli/examples/merkleTree/testsha256PathProof3.zok +++ b/zokrates_cli/examples/merkleTree/testsha256PathProof3.zok @@ -4,8 +4,8 @@ def main() -> (field): field treeDepth = 3 field[256] rootDigest = [1 ,1 ,1 ,1 ,1 ,0 ,1 ,1 ,1 ,1 ,0 ,1 ,1 ,0 ,0 ,0 ,0 ,1 ,0 ,1 ,1 ,0 ,1 ,1 ,0 ,1 ,1 ,1 ,1 ,1 ,0 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,1 ,1 ,1 ,1 ,0 ,0 ,1 ,1 ,1 ,1 ,0 ,0 ,1 ,0 ,1 ,0 ,1 ,0 ,0 ,1 ,1 ,0 ,0 ,0 ,1 ,1 ,0 ,1 ,0 ,1 ,1 ,0 ,1 ,0 ,1 ,1 ,0 ,0 ,0 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,1 ,1 ,1 ,1 ,1 ,0 ,1 ,1 ,1 ,0 ,1 ,1 ,0 ,0 ,0 ,0 ,1 ,0 ,0 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,1 ,0 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,1 ,1 ,0 ,1 ,0 ,0 ,0 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,1 ,1 ,1 ,0 ,1 ,0 ,1 ,0 ,0 ,0 ,0 ,1 ,0 ,1 ,1 ,0 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,1 ,1 ,0 ,1 ,0 ,1 ,1 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,1 ,0 ,1 ,1 ,0 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,1 ,0 ,0 ,1 ,0 ,0 ,0 ,0 ,0 ,1 ,0 ,1 ,1 ,1 ,1 ,1 ,1 ,0] field[256] leafDigest = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1] - field[2] directionSelector = [0, 0] - field[256] PathDigest0 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1] + field[2] directionSelector = [0, 0] + field[256] PathDigest0 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1] field[256] PathDigest1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1] field out = merkleTreeProof(treeDepth,rootDigest,leafDigest,directionSelector,PathDigest0,PathDigest1) diff --git a/zokrates_cli/examples/propagate_call.zok b/zokrates_cli/examples/propagate_call.zok index 111d0155..ea3435d4 100644 --- a/zokrates_cli/examples/propagate_call.zok +++ b/zokrates_cli/examples/propagate_call.zok @@ -3,5 +3,5 @@ def foo(field a, field b) -> (field, field): return a, b def main() -> (field): - a, b = foo(1, 1) + field a, field b = foo(1, 1) return a + b \ No newline at end of file diff --git a/zokrates_cli/examples/runtime_errors/lt_overflow_max_plus_1.zok b/zokrates_cli/examples/runtime_errors/lt_overflow_max_plus_1.zok index d0ddcae4..90aff11f 100644 --- a/zokrates_cli/examples/runtime_errors/lt_overflow_max_plus_1.zok +++ b/zokrates_cli/examples/runtime_errors/lt_overflow_max_plus_1.zok @@ -1,5 +1,5 @@ // we can compare numbers up to 2^(pbits - 2) - 1, ie any number which fits in (pbits - 2) bits -// lt should not work for the maxvalue = 2^(pbits - 2) - 1 augmented by one +// It should not work for the maxvalue = 2^(pbits - 2) - 1 augmented by one // /!\ should be called with a = 0 def main(field a) -> (field): diff --git a/zokrates_cli/examples/sha256/binary/andxorandxorand.zok b/zokrates_cli/examples/sha256/binary/andxorandxorand.zok deleted file mode 100644 index 5094c306..00000000 --- a/zokrates_cli/examples/sha256/binary/andxorandxorand.zok +++ /dev/null @@ -1,7 +0,0 @@ -// ANDXORANDXORAND - -import "utils/binary/xor" as XOR -import "utils/binary/and" as AND - -def main(field a, field b, field c) -> (field): - return XOR(XOR(AND(a, b), AND(a, c)), AND(b, c)) \ No newline at end of file diff --git a/zokrates_cli/examples/sha256/binary/andxornotand.zok b/zokrates_cli/examples/sha256/binary/andxornotand.zok deleted file mode 100644 index fcb5b462..00000000 --- a/zokrates_cli/examples/sha256/binary/andxornotand.zok +++ /dev/null @@ -1,8 +0,0 @@ -// ANDXORNOTAND - -import "utils/binary/and" as AND -import "utils/binary/xor" as XOR -import "utils/binary/not" as NOT - -def main(field a, field b, field c) -> (field): - return XOR(AND(a, b), AND(NOT(a), c)) diff --git a/zokrates_cli/examples/sha256/binary/fulladd.zok b/zokrates_cli/examples/sha256/binary/fulladd.zok deleted file mode 100644 index fbf13de5..00000000 --- a/zokrates_cli/examples/sha256/binary/fulladd.zok +++ /dev/null @@ -1,10 +0,0 @@ -// FULLADD - -import "./halfadd" as HALFADD -import "utils/binary/or" as OR - -def main(field a, field b, field car) -> (field, field): - out1, car1 = HALFADD(a, b) - out2, car2 = HALFADD(out1, car) - car3 = OR(car1, car2) - return out2, car3 \ No newline at end of file diff --git a/zokrates_cli/examples/sha256/binary/halfadd.zok b/zokrates_cli/examples/sha256/binary/halfadd.zok deleted file mode 100644 index 15f0e6ec..00000000 --- a/zokrates_cli/examples/sha256/binary/halfadd.zok +++ /dev/null @@ -1,7 +0,0 @@ -// HALFADD - -import "utils/binary/xor" as XOR -import "utils/binary/and" as AND - -def main(field a, field b) -> (field, field): - return XOR(a, b), AND(a, b) \ No newline at end of file diff --git a/zokrates_cli/examples/sha256/bitwise/32/and.zok b/zokrates_cli/examples/sha256/bitwise/32/and.zok deleted file mode 100644 index 7a36796f..00000000 --- a/zokrates_cli/examples/sha256/bitwise/32/and.zok +++ /dev/null @@ -1,11 +0,0 @@ -// AND - -import "utils/binary/and" as AND - -def main(field[32] b, field[32] c) -> (field[32]): - field[32] result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - for field i in 0..32 do - r = AND(b[i], c[i]) - result[i] = r - endfor - return result \ No newline at end of file diff --git a/zokrates_cli/examples/sha256/bitwise/32/andxorandxorand.zok b/zokrates_cli/examples/sha256/bitwise/32/andxorandxorand.zok deleted file mode 100644 index 334c5ba1..00000000 --- a/zokrates_cli/examples/sha256/bitwise/32/andxorandxorand.zok +++ /dev/null @@ -1,11 +0,0 @@ -// ANDXORANDXORAND - -import "./../../binary/andxorandxorand" as ANDXORANDXORAND - -def main(field[32] b, field[32] c, field[32] d) -> (field[32]): - field[32] result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - for field i in 0..32 do - r = ANDXORANDXORAND(b[i], c[i], d[i]) - result[i] = r - endfor - return result \ No newline at end of file diff --git a/zokrates_cli/examples/sha256/bitwise/32/andxornotand.zok b/zokrates_cli/examples/sha256/bitwise/32/andxornotand.zok deleted file mode 100644 index f053e5aa..00000000 --- a/zokrates_cli/examples/sha256/bitwise/32/andxornotand.zok +++ /dev/null @@ -1,11 +0,0 @@ -// ANDXORNOTAND - -import "./../../binary/andxornotand" as ANDXORNOTAND - -def main(field[32] b, field[32] c, field[32] d) -> (field[32]): - field[32] result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - for field i in 0..32 do - r = ANDXORNOTAND(b[i], c[i], d[i]) - result[i] = r - endfor - return result \ No newline at end of file diff --git a/zokrates_cli/examples/sha256/bitwise/32/not.zok b/zokrates_cli/examples/sha256/bitwise/32/not.zok deleted file mode 100644 index 32fcddec..00000000 --- a/zokrates_cli/examples/sha256/bitwise/32/not.zok +++ /dev/null @@ -1,11 +0,0 @@ -// NOT - -import "utils/binary/not" as NOT - -def main(field[32] b) -> (field[32]): - field[32] result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - for field i in 0..32 do - r = NOT(b[i]) - result[i] = r - endfor - return result \ No newline at end of file diff --git a/zokrates_cli/examples/sha256/bitwise/32/xor.zok b/zokrates_cli/examples/sha256/bitwise/32/xor.zok deleted file mode 100644 index 036c74f0..00000000 --- a/zokrates_cli/examples/sha256/bitwise/32/xor.zok +++ /dev/null @@ -1,11 +0,0 @@ -// XOR - -import "utils/binary/xor" as XOR - -def main(field[32] b, field[32] c) -> (field[32]): - field[32] result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - for field i in 0..32 do - r = XOR(b[i], c[i]) - result[i] = r - endfor - return result \ No newline at end of file diff --git a/zokrates_cli/examples/sha256/utils/32/add.zok b/zokrates_cli/examples/sha256/utils/32/add.zok deleted file mode 100644 index f7b6c7c4..00000000 --- a/zokrates_cli/examples/sha256/utils/32/add.zok +++ /dev/null @@ -1,13 +0,0 @@ -// ADD - -import "../../binary/fulladd" as FULLADD - -def main(field[32] b, field[32] c) -> (field[32]): - field[33] car = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - field[32] d = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - for field i in 0..32 do - d0, car0 = FULLADD(b[i], c[i], car[i]) - d[i] = d0 - car[i + 1] = car0 - endfor - return d diff --git a/zokrates_cli/examples/sha256/utils/32/ar17xar19xars10.zok b/zokrates_cli/examples/sha256/utils/32/ar17xar19xars10.zok deleted file mode 100644 index b736d169..00000000 --- a/zokrates_cli/examples/sha256/utils/32/ar17xar19xars10.zok +++ /dev/null @@ -1,21 +0,0 @@ -// AR17XAR19XAR10 - -import "../../bitwise/32/xor" as XOR - -def RR17(field[32] b) -> (field[32]): - return [b[15], b[16], b[17], b[18], b[19], b[20], b[21], b[22], b[23], b[24], b[25], b[26], b[27], b[28], b[29], b[30], b[31], b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14]] - -def RR19(field[32] b) -> (field[32]): - return [b[13], b[14], b[15], b[16], b[17], b[18], b[19], b[20], b[21], b[22], b[23], b[24], b[25], b[26], b[27], b[28], b[29], b[30], b[31], b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12]] - -def RS10(field[32] b) -> (field[32]): - return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19], b[20], b[21]] - -def main(field[32] a) -> (field[32]): - u = RR17(a) - v = RR19(a) - w = RS10(a) - x = XOR(u, v) - z = XOR(w, x) - return z - diff --git a/zokrates_cli/examples/sha256/utils/32/ar2xar13xar22.zok b/zokrates_cli/examples/sha256/utils/32/ar2xar13xar22.zok deleted file mode 100644 index 57f5e319..00000000 --- a/zokrates_cli/examples/sha256/utils/32/ar2xar13xar22.zok +++ /dev/null @@ -1,21 +0,0 @@ -// AR2XAR13XAR22 - -import "../../bitwise/32/xor" as XOR - -def RR2(field[32] b) -> (field[32]): - return [b[30], b[31], b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19], b[20], b[21], b[22], b[23], b[24], b[25], b[26], b[27], b[28], b[29]] - -def RR13(field[32] b) -> (field[32]): - return [b[19], b[20], b[21], b[22], b[23], b[24], b[25], b[26], b[27], b[28], b[29], b[30], b[31], b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18]] - -def RR22(field[32] b) -> (field[32]): - return [b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19], b[20], b[21], b[22], b[23], b[24], b[25], b[26], b[27], b[28], b[29], b[30], b[31], b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9]] - -def main(field[32] a) -> (field[32]): - u = RR2(a) - v = RR13(a) - w = RR22(a) - x = XOR(u, v) - z = XOR(w, x) - return z - diff --git a/zokrates_cli/examples/sha256/utils/32/ar6xar11xar25.zok b/zokrates_cli/examples/sha256/utils/32/ar6xar11xar25.zok deleted file mode 100644 index a23c9134..00000000 --- a/zokrates_cli/examples/sha256/utils/32/ar6xar11xar25.zok +++ /dev/null @@ -1,20 +0,0 @@ -// AR6XAR11XAR25 - -import "../../bitwise/32/xor" as XOR - -def RR6(field[32] b) -> (field[32]): - return [b[26], b[27], b[28], b[29], b[30], b[31], b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19], b[20], b[21], b[22], b[23], b[24], b[25]] - -def RR11(field[32] b) -> (field[32]): - return [b[21], b[22], b[23], b[24], b[25], b[26], b[27], b[28], b[29], b[30], b[31], b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19], b[20]] - -def RR25(field[32] b) -> (field[32]): - return [b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19], b[20], b[21], b[22], b[23], b[24], b[25], b[26], b[27], b[28], b[29], b[30], b[31], b[0], b[1], b[2], b[3], b[4], b[5], b[6]] - -def main(field[32] a) -> (field[32]): - u = RR6(a) - v = RR11(a) - w = RR25(a) - x = XOR(u, v) - z = XOR(w, x) - return z \ No newline at end of file diff --git a/zokrates_cli/examples/sha256/utils/32/ar7xar18xars3.zok b/zokrates_cli/examples/sha256/utils/32/ar7xar18xars3.zok deleted file mode 100644 index 6c523303..00000000 --- a/zokrates_cli/examples/sha256/utils/32/ar7xar18xars3.zok +++ /dev/null @@ -1,20 +0,0 @@ -// AR7XAR18XAR3 - -import "../../bitwise/32/xor" as XOR - -def RR7(field[32] b) -> (field[32]): - return [b[25], b[26], b[27], b[28], b[29], b[30], b[31], b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19], b[20], b[21], b[22], b[23], b[24]] - -def RR18(field[32] b) -> (field[32]): - return [b[14], b[15], b[16], b[17], b[18], b[19], b[20], b[21], b[22], b[23], b[24], b[25], b[26], b[27], b[28], b[29], b[30], b[31], b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13]] - -def RS3(field[32] b) -> (field[32]): - return [0, 0, 0, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19], b[20], b[21], b[22], b[23], b[24], b[25], b[26], b[27], b[28]] - -def main(field[32] a) -> (field[32]): - u = RR7(a) - v = RR18(a) - w = RS3(a) - x = XOR(u, v) - z = XOR(w, x) - return z \ No newline at end of file diff --git a/zokrates_cli/examples/sha256/utils/32/compression_round.zok b/zokrates_cli/examples/sha256/utils/32/compression_round.zok deleted file mode 100644 index 100c2cd8..00000000 --- a/zokrates_cli/examples/sha256/utils/32/compression_round.zok +++ /dev/null @@ -1,42 +0,0 @@ -// COMPRESSION ROUND - -import "./ar6xar11xar25" as AR6XAR11XAR25 -import "./ar2xar13xar22" as AR2XAR13XAR22 -import "../../bitwise/32/andxornotand" as ANDXORNOTAND -import "../../bitwise/32/andxorandxorand" as ANDXORANDXORAND -import "./add" as ADD2 - -def ADD5(field[32] a, field[32] b, field[32] c, field[32] d, field[32] e) -> (field[32]): - ab = ADD2(a, b) - cd = ADD2(c, d) - abcd = ADD2(ab, cd) - abcde = ADD2(abcd, e) - return abcde - -def main(field[32] k, field[32] w, field[32] a, field[32] b, field[32] c, field[32] d, field[32] e, field[32] f, field[32] g, field[32] h) -> (field[32], field[32], field[32], field[32], field[32], field[32], field[32], field[32]): - - // S1 := (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25) - SOne = AR6XAR11XAR25(e) - - // ch := (e and f) xor ((not e) and g) - ch = ANDXORNOTAND(e, f, g) - - // temp1 := h + S1 + ch + k[i] + w[i] - tempOne = ADD5(h, SOne, ch, k, w) - - // S0 := (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22) - SZero = AR2XAR13XAR22(a) - - // maj := (a and b) xor (a and c) xor (b and c) - maj = ANDXORANDXORAND(a, b, c) - - // temp2 := S0 + maj - tempTwo = ADD2(SZero, maj) - - // en := d + temp1 - en = ADD2(d, tempOne) - - // an := temp1 + temp2 - an = ADD2(tempOne, tempTwo) - - return an, a, b, c, en, e, f, g \ No newline at end of file diff --git a/zokrates_cli/examples/sha256/utils/32/extend.zok b/zokrates_cli/examples/sha256/utils/32/extend.zok deleted file mode 100644 index f6964efa..00000000 --- a/zokrates_cli/examples/sha256/utils/32/extend.zok +++ /dev/null @@ -1,20 +0,0 @@ -// EXTEND - -import "./ar7xar18xars3" as AR7XAR18XAR3 -import "./ar17xar19xars10" as AR17XAR19XAR10 -import "./add" as ADD - -def ADD(field[32] a, field[32] b, field[32] c, field[32] d) -> (field[32]): - ab = ADD(a, b) - cd = ADD(c, d) - abcd = ADD(ab, cd) - return abcd - -def main(field[32] wm15, field[32] wm2, field[32] wm16, field[32] wm7) -> (field[32]): - // s0 := (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift 3) - szero = AR7XAR18XAR3(wm15) - // s1 := (w[i-2] rightrotate 17) xor (w[i-2] rightrotate 19) xor (w[i-2] rightshift 10) - sone = AR17XAR19XAR10(wm2) - // w[i] := w[i-16] + s0 + w[i-7] + s1 - wfb = ADD(wm16, szero, wm7, sone) - return wfb \ No newline at end of file diff --git a/zokrates_cli/examples/structs/add.code b/zokrates_cli/examples/structs/add.zok similarity index 100% rename from zokrates_cli/examples/structs/add.code rename to zokrates_cli/examples/structs/add.zok diff --git a/zokrates_cli/examples/structs/set_member.code b/zokrates_cli/examples/structs/set_member.zok similarity index 100% rename from zokrates_cli/examples/structs/set_member.code rename to zokrates_cli/examples/structs/set_member.zok diff --git a/zokrates_cli/examples/waldo.zok b/zokrates_cli/examples/waldo.zok index 6158dca0..20a94e13 100644 --- a/zokrates_cli/examples/waldo.zok +++ b/zokrates_cli/examples/waldo.zok @@ -18,8 +18,8 @@ def isWaldo(field a, field p, field q) -> (field): // define all def main(field a0, field a1, field a2, field a3, private field index, private field p, private field q) -> (field): // prover provides the index of Waldo - field waldo = if index == 0 then a0 else 0 fi - waldo = waldo + if index == 1 then a1 else 0 fi - waldo = waldo + if index == 2 then a2 else 0 fi + field waldo = if index == 0 then a0 else 0 fi + waldo = waldo + if index == 1 then a1 else 0 fi + waldo = waldo + if index == 2 then a2 else 0 fi waldo = waldo + if index == 3 then a3 else 0 fi return isWaldo(waldo, p, q) \ No newline at end of file diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs index 7f917d15..7151b7da 100644 --- a/zokrates_cli/src/bin.rs +++ b/zokrates_cli/src/bin.rs @@ -4,19 +4,22 @@ // @author Dennis Kuhnert // @date 2017 +use bincode::{serialize_into, Infinite}; use clap::{App, AppSettings, Arg, ArgMatches, SubCommand}; -use serde_json::Value; +use serde_json::{from_reader, to_writer_pretty, Value}; +use std::env; use std::fs::File; use std::io::{stdin, BufReader, BufWriter, Read, Write}; use std::path::{Path, PathBuf}; use std::string::String; -use std::{env, io}; use zokrates_abi::Encode; -use zokrates_core::compile::compile; +use zokrates_core::compile::{compile, CompilationArtifacts, CompileError}; use zokrates_core::ir::{self, ProgEnum}; use zokrates_core::proof_system::*; +use zokrates_core::typed_absy::abi::Abi; +use zokrates_core::typed_absy::{types::Signature, Type}; use zokrates_field::{Bls12Field, Bn128Field, Field}; -use zokrates_fs_resolver::resolve as fs_resolve; +use zokrates_fs_resolver::FileSystemResolver; const CURVES: &[&str] = &["bn128", "bls12_381"]; #[cfg(feature = "libsnark")] @@ -31,19 +34,6 @@ fn main() { }) } -fn resolve<'a>( - location: Option, - source: &'a str, -) -> Result<(BufReader, String, &'a str), io::Error> { - #[cfg(feature = "github")] - { - if is_github_import(source) { - return github_resolve(location, source); - }; - } - fs_resolve(location, source) -} - fn cli_generate_proof>( program: ir::Prog, sub_matches: &ArgMatches, @@ -60,29 +50,48 @@ fn cli_generate_proof>( let witness = ir::Witness::read(witness_file) .map_err(|why| format!("could not load witness: {:?}", why))?; - let pk_path = sub_matches.value_of("provingkey").unwrap(); - let proof_path = sub_matches.value_of("proofpath").unwrap(); + let pk_path = Path::new(sub_matches.value_of("provingkey").unwrap()); + let proof_path = Path::new(sub_matches.value_of("proofpath").unwrap()); + + let pk_file = File::open(&pk_path) + .map_err(|why| format!("couldn't open {}: {}", pk_path.display(), why))?; + + let mut pk: Vec = Vec::new(); + let mut pk_reader = BufReader::new(pk_file); + pk_reader + .read_to_end(&mut pk) + .map_err(|why| format!("couldn't read {}: {}", pk_path.display(), why))?; + + let proof = P::generate_proof(program, witness, pk); + let mut proof_file = File::create(proof_path).unwrap(); + + proof_file + .write(proof.as_ref()) + .map_err(|why| format!("couldn't write to {}: {}", proof_path.display(), why))?; + + println!("generate-proof successful: {}", format!("{}", proof)); - println!( - "generate-proof successful: {:?}", - P::generate_proof(program, witness, pk_path, proof_path) - ); Ok(()) } fn cli_export_verifier>( sub_matches: &ArgMatches, ) -> Result<(), String> { - let is_abiv2 = sub_matches.value_of("abi").unwrap() == "v2"; + let is_abiv2 = sub_matches.value_of("solidity-abi").unwrap() == "v2"; println!("Exporting verifier..."); // read vk file let input_path = Path::new(sub_matches.value_of("input").unwrap()); let input_file = File::open(&input_path) .map_err(|why| format!("couldn't open {}: {}", input_path.display(), why))?; - let reader = BufReader::new(input_file); + let mut reader = BufReader::new(input_file); - let verifier = P::export_solidity_verifier(reader, is_abiv2); + let mut vk = String::new(); + reader + .read_to_string(&mut vk) + .map_err(|why| format!("couldn't read {}: {}", input_path.display(), why))?; + + let verifier = P::export_solidity_verifier(vk, is_abiv2); //write output file let output_path = Path::new(sub_matches.value_of("output").unwrap()); @@ -110,11 +119,27 @@ fn cli_setup>( } // get paths for proving and verification keys - let pk_path = sub_matches.value_of("proving-key-path").unwrap(); - let vk_path = sub_matches.value_of("verification-key-path").unwrap(); + let pk_path = Path::new(sub_matches.value_of("proving-key-path").unwrap()); + let vk_path = Path::new(sub_matches.value_of("verification-key-path").unwrap()); // run setup phase - P::setup(program, pk_path, vk_path); + let keypair = P::setup(program); + + // write verification key + let mut vk_file = File::create(vk_path) + .map_err(|why| format!("couldn't create {}: {}", vk_path.display(), why))?; + vk_file + .write(keypair.vk.as_ref()) + .map_err(|why| format!("couldn't write to {}: {}", vk_path.display(), why))?; + + // write proving key + let mut pk_file = File::create(pk_path) + .map_err(|why| format!("couldn't create {}: {}", pk_path.display(), why))?; + pk_file + .write(keypair.pk.as_ref()) + .map_err(|why| format!("couldn't write to {}: {}", pk_path.display(), why))?; + + println!("Setup completed."); Ok(()) } @@ -127,8 +152,6 @@ fn cli_compute(ir_prog: ir::Prog, sub_matches: &ArgMatches) -> Resu println!("{}", ir_prog); } - let signature = ir_prog.signature.clone(); - let is_stdin = sub_matches.is_present("stdin"); let is_abi = sub_matches.is_present("abi"); @@ -136,6 +159,22 @@ fn cli_compute(ir_prog: ir::Prog, sub_matches: &ArgMatches) -> Resu return Err("ABI input as inline argument is not supported. Please use `--stdin`.".into()); } + let signature = match is_abi { + true => { + let path = Path::new(sub_matches.value_of("abi_spec").unwrap()); + let file = File::open(&path) + .map_err(|why| format!("couldn't open {}: {}", path.display(), why))?; + let mut reader = BufReader::new(file); + + let abi: Abi = from_reader(&mut reader).map_err(|why| why.to_string())?; + + abi.signature() + } + false => Signature::new() + .inputs(vec![Type::FieldElement; ir_prog.main.arguments.len()]) + .outputs(vec![Type::FieldElement; ir_prog.main.returns.len()]), + }; + use zokrates_abi::Inputs; // get arguments @@ -195,7 +234,7 @@ fn cli_compute(ir_prog: ir::Prog, sub_matches: &ArgMatches) -> Resu let results_json_value: serde_json::Value = zokrates_abi::CheckedValues::decode(witness.return_values(), signature.outputs).into(); - println!("\nWitness: \n\n{}", results_json_value.to_string()); + println!("\nWitness: \n\n{}", results_json_value); // write witness to file let output_path = Path::new(sub_matches.value_of("output").unwrap()); @@ -215,37 +254,69 @@ fn cli_compile(sub_matches: &ArgMatches) -> Result<(), String> { println!("Compiling {}\n", sub_matches.value_of("input").unwrap()); let path = PathBuf::from(sub_matches.value_of("input").unwrap()); - let location = path - .parent() - .unwrap() - .to_path_buf() - .into_os_string() - .into_string() - .unwrap(); - let light = sub_matches.occurrences_of("light") > 0; let bin_output_path = Path::new(sub_matches.value_of("output").unwrap()); + let abi_spec_path = Path::new(sub_matches.value_of("abi_spec").unwrap()); + let hr_output_path = bin_output_path.to_path_buf().with_extension("ztf"); - let file = File::open(path.clone()).unwrap(); + let file = File::open(path.clone()) + .map_err(|why| format!("Couldn't open input file {}: {}", path.display(), why))?; let mut reader = BufReader::new(file); + let mut source = String::new(); + reader.read_to_string(&mut source).unwrap(); - let program_flattened: ir::Prog = compile(&mut reader, Some(location), Some(resolve)) - .map_err(|e| format!("Compilation failed:\n\n {}", e))?; + let fmt_error = |e: &CompileError| { + format!( + "{}:{}", + e.file() + .canonicalize() + .unwrap() + .strip_prefix(std::env::current_dir().unwrap()) + .unwrap() + .display(), + e.value() + ) + }; + + let resolver = FileSystemResolver::new(); + let artifacts: CompilationArtifacts = + compile(source, path, Some(&resolver)).map_err(|e| { + format!( + "Compilation failed:\n\n{}", + e.0.iter() + .map(|e| fmt_error(e)) + .collect::>() + .join("\n\n") + ) + })?; + + let program_flattened = artifacts.prog(); // number of constraints the flattened program will translate to. let num_constraints = program_flattened.constraint_count(); // serialize flattened program and write to binary file let bin_output_file = File::create(&bin_output_path) - .map_err(|why| format!("couldn't create {}: {}", bin_output_path.display(), why))?; + .map_err(|why| format!("Couldn't create {}: {}", bin_output_path.display(), why))?; let mut writer = BufWriter::new(bin_output_file); - program_flattened.serialize(&mut writer); + serialize_into(&mut writer, &program_flattened, Infinite) + .map_err(|_| "Unable to write data to file.".to_string())?; + + // serialize ABI spec and write to JSON file + let abi_spec_file = File::create(&abi_spec_path) + .map_err(|why| format!("Couldn't create {}: {}", abi_spec_path.display(), why))?; + + let abi = artifacts.abi(); + + let mut writer = BufWriter::new(abi_spec_file); + + to_writer_pretty(&mut writer, &abi).map_err(|_| "Unable to write data to file.".to_string())?; if !light { // write human-readable output file @@ -277,6 +348,7 @@ fn cli_compile(sub_matches: &ArgMatches) -> Result<(), String> { fn cli() -> Result<(), String> { const FLATTENED_CODE_DEFAULT_PATH: &str = "out"; + const ABI_SPEC_DEFAULT_PATH: &str = "abi.json"; const VERIFICATION_KEY_DEFAULT_PATH: &str = "verification.key"; const PROVING_KEY_DEFAULT_PATH: &str = "proving.key"; const VERIFICATION_CONTRACT_DEFAULT_PATH: &str = "verifier.sol"; @@ -301,10 +373,18 @@ fn cli() -> Result<(), String> { .value_name("FILE") .takes_value(true) .required(true) + ).arg(Arg::with_name("abi_spec") + .short("s") + .long("abi_spec") + .help("Path of the ABI specification") + .value_name("FILE") + .takes_value(true) + .required(false) + .default_value(ABI_SPEC_DEFAULT_PATH) ).arg(Arg::with_name("output") .short("o") .long("output") - .help("Path of the output file") + .help("Path of the output binary") .value_name("FILE") .takes_value(true) .required(false) @@ -328,7 +408,7 @@ fn cli() -> Result<(), String> { .arg(Arg::with_name("input") .short("i") .long("input") - .help("Path of compiled code") + .help("Path of the binary") .value_name("FILE") .takes_value(true) .required(false) @@ -399,9 +479,9 @@ fn cli() -> Result<(), String> { .required(false) .possible_values(SCHEMES) .default_value(&default_scheme) - ).arg(Arg::with_name("abi") + ).arg(Arg::with_name("solidity-abi") .short("a") - .long("abi") + .long("solidity-abi") .help("Flag for setting the version of the ABI Encoder used in the contract") .takes_value(true) .possible_values(&["v1", "v2"]) @@ -414,11 +494,19 @@ fn cli() -> Result<(), String> { .arg(Arg::with_name("input") .short("i") .long("input") - .help("Path of compiled code") + .help("Path of the binary") .value_name("FILE") .takes_value(true) .required(false) .default_value(FLATTENED_CODE_DEFAULT_PATH) + ).arg(Arg::with_name("abi_spec") + .short("s") + .long("abi_spec") + .help("Path of the ABI specification") + .value_name("FILE") + .takes_value(true) + .required(false) + .default_value(ABI_SPEC_DEFAULT_PATH) ).arg(Arg::with_name("output") .short("o") .long("output") @@ -478,7 +566,7 @@ fn cli() -> Result<(), String> { ).arg(Arg::with_name("input") .short("i") .long("input") - .help("Path of compiled code") + .help("Path of the binary") .value_name("FILE") .takes_value(true) .required(false) @@ -595,12 +683,11 @@ fn cli() -> Result<(), String> { ("generate-proof", Some(sub_matches)) => { let proof_system = sub_matches.value_of("proving-scheme").unwrap(); - // read compiled program - let path = Path::new(sub_matches.value_of("input").unwrap()); - let file = File::open(&path) - .map_err(|why| format!("couldn't open {}: {}", path.display(), why))?; + let program_path = Path::new(sub_matches.value_of("input").unwrap()); + let program_file = File::open(&program_path) + .map_err(|why| format!("couldn't open {}: {}", program_path.display(), why))?; - let mut reader = BufReader::new(file); + let mut reader = BufReader::new(program_file); let prog = ProgEnum::deserialize(&mut reader).map_err(|_| "wrong file".to_string())?; @@ -672,12 +759,18 @@ mod tests { #[test] fn examples() { - for p in glob("./examples/**/*.zok").expect("Failed to read glob pattern") { + for p in glob("./examples/**/*").expect("Failed to read glob pattern") { let path = match p { Ok(x) => x, Err(why) => panic!("Error: {:?}", why), }; + if !path.is_file() { + continue; + } + + assert!(path.extension().expect("extension expected") == "zok"); + if path.to_str().unwrap().contains("error") { continue; } @@ -687,23 +780,20 @@ mod tests { let file = File::open(path.clone()).unwrap(); let mut reader = BufReader::new(file); - let location = path - .parent() - .unwrap() - .to_path_buf() - .into_os_string() - .into_string() - .unwrap(); - let _: ir::Prog = - compile(&mut reader, Some(location), Some(resolve)).unwrap(); + let mut source = String::new(); + reader.read_to_string(&mut source).unwrap(); + + let resolver = FileSystemResolver::new(); + let _: CompilationArtifacts = + compile(source, path, Some(&resolver)).unwrap(); } } #[test] fn examples_with_input_success() { //these examples should compile and run - for p in glob("./examples/test*.zok").expect("Failed to read glob pattern") { + for p in glob("./examples/test*").expect("Failed to read glob pattern") { let path = match p { Ok(x) => x, Err(why) => panic!("Error: {:?}", why), @@ -712,20 +802,16 @@ mod tests { let file = File::open(path.clone()).unwrap(); - let location = path - .parent() - .unwrap() - .to_path_buf() - .into_os_string() - .into_string() - .unwrap(); - let mut reader = BufReader::new(file); + let mut source = String::new(); + reader.read_to_string(&mut source).unwrap(); - let program_flattened: ir::Prog = - compile(&mut reader, Some(location), Some(resolve)).unwrap(); + let resolver = FileSystemResolver::new(); + let artifacts: CompilationArtifacts = + compile(source, path, Some(&resolver)).unwrap(); - let _ = program_flattened + let _ = artifacts + .prog() .execute(&vec![Bn128Field::from(0)]) .unwrap(); } @@ -734,29 +820,26 @@ mod tests { #[test] #[should_panic] fn examples_with_input_failure() { - println!("something"); //these examples should compile but not run - for p in glob("./examples/runtime_errors/*.zok").expect("Failed to read glob pattern") { - let path = p.unwrap(); - + for p in glob("./examples/runtime_errors/*").expect("Failed to read glob pattern") { + let path = match p { + Ok(x) => x, + Err(why) => panic!("Error: {:?}", why), + }; println!("Testing {:?}", path); let file = File::open(path.clone()).unwrap(); - let location = path - .parent() - .unwrap() - .to_path_buf() - .into_os_string() - .into_string() - .unwrap(); - let mut reader = BufReader::new(file); + let mut source = String::new(); + reader.read_to_string(&mut source).unwrap(); - let program_flattened: ir::Prog = - compile(&mut reader, Some(location), Some(resolve)).unwrap(); + let resolver = FileSystemResolver::new(); + let artifacts: CompilationArtifacts = + compile(source, path, Some(&resolver)).unwrap(); - let _ = program_flattened + let _ = artifacts + .prog() .execute(&vec![Bn128Field::from(0)]) .unwrap(); } diff --git a/zokrates_cli/tests/code/sha_round.zok b/zokrates_cli/tests/code/sha_round.zok index 9d64e581..eba97306 100644 --- a/zokrates_cli/tests/code/sha_round.zok +++ b/zokrates_cli/tests/code/sha_round.zok @@ -5,7 +5,7 @@ def main(private field[256] expected) -> (field): field[256] a = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] field[256] b = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1] field[256] IV = [0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1] - + expected == sha256([a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], a[16], a[17], a[18], a[19], a[20], a[21], a[22], a[23], a[24], a[25], a[26], a[27], a[28], a[29], a[30], a[31], a[32], a[33], a[34], a[35], a[36], a[37], a[38], a[39], a[40], a[41], a[42], a[43], a[44], a[45], a[46], a[47], a[48], a[49], a[50], a[51], a[52], a[53], a[54], a[55], a[56], a[57], a[58], a[59], a[60], a[61], a[62], a[63], a[64], a[65], a[66], a[67], a[68], a[69], a[70], a[71], a[72], a[73], a[74], a[75], a[76], a[77], a[78], a[79], a[80], a[81], a[82], a[83], a[84], a[85], a[86], a[87], a[88], a[89], a[90], a[91], a[92], a[93], a[94], a[95], a[96], a[97], a[98], a[99], a[100], a[101], a[102], a[103], a[104], a[105], a[106], a[107], a[108], a[109], a[110], a[111], a[112], a[113], a[114], a[115], a[116], a[117], a[118], a[119], a[120], a[121], a[122], a[123], a[124], a[125], a[126], a[127], a[128], a[129], a[130], a[131], a[132], a[133], a[134], a[135], a[136], a[137], a[138], a[139], a[140], a[141], a[142], a[143], a[144], a[145], a[146], a[147], a[148], a[149], a[150], a[151], a[152], a[153], a[154], a[155], a[156], a[157], a[158], a[159], a[160], a[161], a[162], a[163], a[164], a[165], a[166], a[167], a[168], a[169], a[170], a[171], a[172], a[173], a[174], a[175], a[176], a[177], a[178], a[179], a[180], a[181], a[182], a[183], a[184], a[185], a[186], a[187], a[188], a[189], a[190], a[191], a[192], a[193], a[194], a[195], a[196], a[197], a[198], a[199], a[200], a[201], a[202], a[203], a[204], a[205], a[206], a[207], a[208], a[209], a[210], a[211], a[212], a[213], a[214], a[215], a[216], a[217], a[218], a[219], a[220], a[221], a[222], a[223], a[224], a[225], a[226], a[227], a[228], a[229], a[230], a[231], a[232], a[233], a[234], a[235], a[236], a[237], a[238], a[239], a[240], a[241], a[242], a[243], a[244], a[245], a[246], a[247], a[248], a[249], a[250], a[251], a[252], a[253], a[254], a[255], b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19], b[20], b[21], b[22], b[23], b[24], b[25], b[26], b[27], b[28], b[29], b[30], b[31], b[32], b[33], b[34], b[35], b[36], b[37], b[38], b[39], b[40], b[41], b[42], b[43], b[44], b[45], b[46], b[47], b[48], b[49], b[50], b[51], b[52], b[53], b[54], b[55], b[56], b[57], b[58], b[59], b[60], b[61], b[62], b[63], b[64], b[65], b[66], b[67], b[68], b[69], b[70], b[71], b[72], b[73], b[74], b[75], b[76], b[77], b[78], b[79], b[80], b[81], b[82], b[83], b[84], b[85], b[86], b[87], b[88], b[89], b[90], b[91], b[92], b[93], b[94], b[95], b[96], b[97], b[98], b[99], b[100], b[101], b[102], b[103], b[104], b[105], b[106], b[107], b[108], b[109], b[110], b[111], b[112], b[113], b[114], b[115], b[116], b[117], b[118], b[119], b[120], b[121], b[122], b[123], b[124], b[125], b[126], b[127], b[128], b[129], b[130], b[131], b[132], b[133], b[134], b[135], b[136], b[137], b[138], b[139], b[140], b[141], b[142], b[143], b[144], b[145], b[146], b[147], b[148], b[149], b[150], b[151], b[152], b[153], b[154], b[155], b[156], b[157], b[158], b[159], b[160], b[161], b[162], b[163], b[164], b[165], b[166], b[167], b[168], b[169], b[170], b[171], b[172], b[173], b[174], b[175], b[176], b[177], b[178], b[179], b[180], b[181], b[182], b[183], b[184], b[185], b[186], b[187], b[188], b[189], b[190], b[191], b[192], b[193], b[194], b[195], b[196], b[197], b[198], b[199], b[200], b[201], b[202], b[203], b[204], b[205], b[206], b[207], b[208], b[209], b[210], b[211], b[212], b[213], b[214], b[215], b[216], b[217], b[218], b[219], b[220], b[221], b[222], b[223], b[224], b[225], b[226], b[227], b[228], b[229], b[230], b[231], b[232], b[233], b[234], b[235], b[236], b[237], b[238], b[239], b[240], b[241], b[242], b[243], b[244], b[245], b[246], b[247], b[248], b[249], b[250], b[251], b[252], b[253], b[254], b[255]], IV) return 1 \ No newline at end of file diff --git a/zokrates_cli/tests/contract/package.json b/zokrates_cli/tests/contract/package.json index 071da50a..f7b05075 100644 --- a/zokrates_cli/tests/contract/package.json +++ b/zokrates_cli/tests/contract/package.json @@ -9,7 +9,7 @@ "author": "Paul Etscheit", "license": "LGPL-3.0-only", "dependencies": { - "solc": "^0.5.9", + "solc": "^0.6.1", "web3": "^1.0.0" } } diff --git a/zokrates_cli/tests/contract/test.js b/zokrates_cli/tests/contract/test.js index 8af4fcbd..cb222406 100644 --- a/zokrates_cli/tests/contract/test.js +++ b/zokrates_cli/tests/contract/test.js @@ -31,8 +31,8 @@ let jsonInterface = JSON.parse(solc.compile(jsonContractSource)); let abi = jsonInterface.contracts[contractPath]["Verifier"].abi let bytecode = jsonInterface.contracts[contractPath]["Verifier"].evm.bytecode - //There is a solc issue, that for unknown reasons wont link the BN256G2 Library automatically for gm17 v1 and v2 contracts. I dont know why this is happening, - //the contracts compile and deploy without any issue on remix. To fix this, the the BN256G2 Library must be compiled and deployed by itself, after that, + //There is a solc issue, that for unknown reasons wont link the BN256G2 Library automatically for gm17 v1 and v2 contracts. I dont know why this is happening, + //the contracts compile and deploy without any issue on remix. To fix this, the the BN256G2 Library must be compiled and deployed by itself, after that, //the library placeholder must be replaced with the library address in the contracts bytecode if (format == "gm17") { let library = await deployLibrary(); diff --git a/zokrates_cli/tests/integration.rs b/zokrates_cli/tests/integration.rs index 298d0eeb..60c0a4d9 100644 --- a/zokrates_cli/tests/integration.rs +++ b/zokrates_cli/tests/integration.rs @@ -4,6 +4,7 @@ extern crate serde_json; #[cfg(test)] mod integration { use assert_cli; + use serde_json::from_reader; use std::fs; use std::fs::File; use std::io::{BufReader, Read}; @@ -11,8 +12,7 @@ mod integration { use std::path::Path; use tempdir::TempDir; use zokrates_abi::{parse_strict, Encode}; - use zokrates_core::ir; - use zokrates_field::Bn128Field; + use zokrates_core::typed_absy::abi::Abi; #[test] #[ignore] @@ -60,6 +60,7 @@ mod integration { let tmp_base = tmp_dir.path(); let test_case_path = tmp_base.join(program_name); let flattened_path = tmp_base.join(program_name).join("out"); + let abi_spec_path = tmp_base.join(program_name).join("abi.json"); let witness_path = tmp_base.join(program_name).join("witness"); let inline_witness_path = tmp_base.join(program_name).join("inline_witness"); let proof_path = tmp_base.join(program_name).join("proof.json"); @@ -85,6 +86,8 @@ mod integration { "compile", "-i", program_path.to_str().unwrap(), + "-s", + abi_spec_path.to_str().unwrap(), "-o", flattened_path.to_str().unwrap(), "--light", @@ -95,40 +98,42 @@ mod integration { // COMPUTE_WITNESS - // derive program signature from IR program representation - let file = File::open(&flattened_path) - .map_err(|why| format!("couldn't open {}: {}", flattened_path.display(), why)) - .unwrap(); - - let mut reader = BufReader::new(file); - - let ir_prog: ir::Prog = match ir::ProgEnum::deserialize(&mut reader).unwrap() { - ir::ProgEnum::Bn128Program(p) => p, - _ => unreachable!(), - }; - - let signature = ir_prog.signature.clone(); - - // run witness-computation for ABI-encoded inputs through stdin - let json_input_str = fs::read_to_string(inputs_path).unwrap(); - let compute = vec![ "../target/release/zokrates", "compute-witness", "-i", flattened_path.to_str().unwrap(), + "-s", + abi_spec_path.to_str().unwrap(), "-o", witness_path.to_str().unwrap(), "--stdin", "--abi", ]; + // run witness-computation for ABI-encoded inputs through stdin + let json_input_str = fs::read_to_string(inputs_path).unwrap(); + assert_cli::Assert::command(&compute) .stdin(&json_input_str) .succeeds() .unwrap(); // run witness-computation for raw-encoded inputs (converted) with `-a ` + + // First we need to convert our test input into raw field elements. We need to ABI spec for that + let file = File::open(&abi_spec_path) + .map_err(|why| format!("couldn't open {}: {}", flattened_path.display(), why)) + .unwrap(); + + let mut reader = BufReader::new(file); + + let abi: Abi = from_reader(&mut reader) + .map_err(|why| why.to_string()) + .unwrap(); + + let signature = abi.signature().clone(); + let inputs_abi: zokrates_abi::Inputs = parse_strict(&json_input_str, signature.inputs) .map(|parsed| zokrates_abi::Inputs::Abi(parsed)) diff --git a/zokrates_common/Cargo.toml b/zokrates_common/Cargo.toml new file mode 100644 index 00000000..7caea4b8 --- /dev/null +++ b/zokrates_common/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "zokrates_common" +version = "0.1.0" +authors = ["dark64 "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] \ No newline at end of file diff --git a/zokrates_common/src/lib.rs b/zokrates_common/src/lib.rs new file mode 100644 index 00000000..17da58d7 --- /dev/null +++ b/zokrates_common/src/lib.rs @@ -0,0 +1,9 @@ +use std::path::PathBuf; + +pub trait Resolver { + fn resolve( + &self, + current_location: PathBuf, + import_location: PathBuf, + ) -> Result<(String, PathBuf), E>; +} diff --git a/zokrates_core/Cargo.toml b/zokrates_core/Cargo.toml index 7ad8d3ad..1ad7f52c 100644 --- a/zokrates_core/Cargo.toml +++ b/zokrates_core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_core" -version = "0.4.0" +version = "0.4.2" authors = ["Jacob Eberhardt ", "Dennis Kuhnert "] repository = "https://github.com/JacobEberhardt/ZoKrates" readme = "README.md" @@ -9,10 +9,10 @@ build = "build.rs" [features] default = [] libsnark = ["cc", "cmake", "git2"] -wasm = ["wasmi", "parity-wasm", "rustc-hex"] +wasm = ["bellman_ce/wasm", "zokrates_embed/wasm"] +multicore = ["bellman_ce/multicore"] [dependencies] -libc = "0.2.0" num = {version = "0.1.36", default-features = false} num-bigint = {version = "0.1.36", default-features = false} lazy_static = "1.4" @@ -25,21 +25,20 @@ serde_json = "1.0" serde_bytes = "0.10" bincode = "0.8.0" regex = "0.2" -bellman_ce = "0.3" -pairing_ce = "0.18" -ff_ce = "0.7" +pairing_ce = "0.20" +ff_ce = "0.9" zokrates_field = { version = "0.3.0", path = "../zokrates_field" } zokrates_pest_ast = { version = "0.1.0", path = "../zokrates_pest_ast" } zokrates_embed = { path = "../zokrates_embed" } +zokrates_common = { path = "../zokrates_common" } rand = "0.4" -wasmi = { version = "=0.4.5", optional = true } -parity-wasm = { version = "0.35.3", optional = true } -rustc-hex = { version = "1.0", optional = true } csv = "1" +bellman_ce = { version = "0.3.3", default-features = false} [dev-dependencies] glob = "0.2.11" assert_cli = "0.5" +wasm-bindgen-test = "0.3.0" [build-dependencies] cc = { version = "1.0", features = ["parallel"], optional = true } diff --git a/zokrates_core/build.rs b/zokrates_core/build.rs index b0f01587..eb4ff4dd 100644 --- a/zokrates_core/build.rs +++ b/zokrates_core/build.rs @@ -14,11 +14,11 @@ fn main() { use std::path::PathBuf; // fetch libsnark source - const LIBSNARK_URL: &'static str = "https://github.com/scipr-lab/libsnark.git"; const LIBSNARK_COMMIT: &'static str = "f7c87b88744ecfd008126d415494d9b34c4c1b20"; - let libsnark_source_path = &PathBuf::from(env::var("OUT_DIR").unwrap()).join("LIBSNARK"); + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + let libsnark_source_path = &out_path.join("libsnark"); let repo = Repository::open(libsnark_source_path).unwrap_or_else(|_| { remove_dir(libsnark_source_path).ok(); @@ -36,9 +36,10 @@ fn main() { } // build libsnark - let libsnark = cmake::Config::new(libsnark_source_path) + .define("WITH_SUPERCOP", "OFF") .define("WITH_PROCPS", "OFF") + .define("WITH_SUPERCOP", "OFF") .define("CURVE", "ALT_BN128") .define("USE_PT_COMPRESSION", "OFF") .define("MONTGOMERY_OUTPUT", "ON") @@ -46,7 +47,6 @@ fn main() { .build(); // build backends - cc::Build::new() .cpp(true) .debug(cfg!(debug_assertions)) @@ -55,10 +55,11 @@ fn main() { .include(libsnark_source_path.join("depends/libff")) .include(libsnark_source_path.join("depends/libfqfft")) .define("CURVE_ALT_BN128", None) + .file("lib/ffi.cpp") .file("lib/util.cpp") .file("lib/gm17.cpp") .file("lib/pghr13.cpp") - .compile("libwraplibsnark.a"); + .compile("libsnark_wrapper.a"); println!( "cargo:rustc-link-search=native={}", diff --git a/zokrates_core/lib/ffi.cpp b/zokrates_core/lib/ffi.cpp new file mode 100644 index 00000000..3ea355bb --- /dev/null +++ b/zokrates_core/lib/ffi.cpp @@ -0,0 +1,6 @@ +#include "ffi.hpp" + +void __free(uint8_t* ptr) +{ + free(ptr); +} \ No newline at end of file diff --git a/zokrates_core/lib/ffi.hpp b/zokrates_core/lib/ffi.hpp new file mode 100644 index 00000000..2483af22 --- /dev/null +++ b/zokrates_core/lib/ffi.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct buffer_t { + uint8_t* data; + int32_t length; +}; + +struct setup_result_t { + buffer_t vk; + buffer_t pk; + setup_result_t(buffer_t& vk_buf, buffer_t& pk_buf) + : vk(vk_buf) + , pk(pk_buf) + { + } +}; + +struct proof_result_t { + buffer_t proof; + proof_result_t(buffer_t& proof_buf) + : proof(proof_buf) + { + } +}; + +void __free(uint8_t* ptr); + +#ifdef __cplusplus +} // extern "C" +#endif + +static inline void __alloc(buffer_t* buffer, size_t length) +{ + buffer->data = (uint8_t*)malloc(length); + buffer->length = length; +} \ No newline at end of file diff --git a/zokrates_core/lib/gm17.cpp b/zokrates_core/lib/gm17.cpp index 61bd0da1..ba449ad4 100644 --- a/zokrates_core/lib/gm17.cpp +++ b/zokrates_core/lib/gm17.cpp @@ -1,210 +1,210 @@ /** - * @file wraplibsnark.cpp + * @file gm17.cpp * @author Jacob Eberhardt * @date 2017 */ -#include "util.hpp" #include "gm17.hpp" -#include -#include +#include "util.hpp" #include -#include +#include +#include // contains definition of alt_bn128 ec public parameters #include "libff/algebra/curves/alt_bn128/alt_bn128_pp.hpp" + // contains required interfaces and types (keypair, proof, generator, prover, verifier) #include typedef long integer_coeff_t; -using namespace std; using namespace libsnark; +using std::cout; +using std::endl; namespace gm17 { - -//takes input and puts it into constraint system -r1cs_se_ppzksnark_constraint_system createConstraintSystem(const uint8_t* A, const uint8_t* B, const uint8_t* C, int A_len, int B_len, int C_len, int constraints, int variables, int inputs) +r1cs_se_ppzksnark_constraint_system createConstraintSystem(const uint8_t* A, const uint8_t* B, const uint8_t* C, int32_t A_len, int32_t B_len, int32_t C_len, int32_t constraints, int32_t variables, int32_t inputs) { - r1cs_se_ppzksnark_constraint_system cs; - cs.primary_input_size = inputs; - cs.auxiliary_input_size = variables - inputs - 1; // ~one not included + r1cs_se_ppzksnark_constraint_system cs; + cs.primary_input_size = inputs; + cs.auxiliary_input_size = variables - inputs - 1; // ~one not included - cout << "num variables: " << variables < > lin_comb_A, lin_comb_B, lin_comb_C; + // initialize curve parameters + libff::alt_bn128_pp::init_public_params(); - while (A_id < A_len && A_vvmap[A_id].constraint_id == row) { - libff::bigint value = libsnarkBigintFromBytes(A_vvmap[A_id].variable_value); - if (!value.is_zero()) - lin_comb_A.add_term(A_vvmap[A_id].variable_id, value); - A_id++; - } - while (B_id < B_len && B_vvmap[B_id].constraint_id == row) { - libff::bigint value = libsnarkBigintFromBytes(B_vvmap[B_id].variable_value); - if (!value.is_zero()) - lin_comb_B.add_term(B_vvmap[B_id].variable_id, value); - B_id++; - } - while (C_id < C_len && C_vvmap[C_id].constraint_id == row) { - libff::bigint value = libsnarkBigintFromBytes(C_vvmap[C_id].variable_value); - if (!value.is_zero()) - lin_comb_C.add_term(C_vvmap[C_id].variable_id, value); - C_id++; - } - - cs.add_constraint(r1cs_constraint >(lin_comb_A, lin_comb_B, lin_comb_C)); - } - - return cs; -} - -// keypair generateKeypair(constraints) -r1cs_se_ppzksnark_keypair generateKeypair(const r1cs_se_ppzksnark_constraint_system &cs){ - // from r1cs_se_ppzksnark.hpp - return r1cs_se_ppzksnark_generator(cs); -} - -void serializeProvingKeyToFile(r1cs_se_ppzksnark_proving_key pk, const char* pk_path){ - writeToFile(pk_path, pk); -} - -r1cs_se_ppzksnark_proving_key deserializeProvingKeyFromFile(const char* pk_path){ - return loadFromFile>(pk_path); -} - -void serializeVerificationKeyToFile(r1cs_se_ppzksnark_verification_key vk, const char* vk_path){ - std::stringstream ss; - - unsigned queryLength = vk.query.size(); - - ss << "\t\tvk.h = " << outputPointG2AffineAsHex(vk.H) << endl; - ss << "\t\tvk.g_alpha = " << outputPointG1AffineAsHex(vk.G_alpha) << endl; - ss << "\t\tvk.h_beta = " << outputPointG2AffineAsHex(vk.H_beta) << endl; - ss << "\t\tvk.g_gamma = " << outputPointG1AffineAsHex(vk.G_gamma) << endl; - ss << "\t\tvk.h_gamma = " << outputPointG2AffineAsHex(vk.H_gamma) << endl; - ss << "\t\tvk.query.len() = " << queryLength << endl; - for (size_t i = 0; i < queryLength; ++i) - { - auto vkqueryi = outputPointG1AffineAsHex(vk.query[i]); - ss << "\t\tvk.query[" << i << "] = " << vkqueryi << endl; - } - - std::ofstream fh; - fh.open(vk_path, std::ios::binary); - ss.rdbuf()->pubseekpos(0, std::ios_base::out); - fh << ss.rdbuf(); - fh.flush(); - fh.close(); -} - -void exportProof(r1cs_se_ppzksnark_proof proof, const char* proof_path, const uint8_t* public_inputs, - int public_inputs_length){ - //create JSON file - std::stringstream ss; - ss << "{" << "\n"; - ss << "\t\"proof\":" << "\n"; - ss << "\t{" << "\n"; - ss << "\t\t\"a\":" <> lin_comb_A, lin_comb_B, lin_comb_C; + while (A_id < A_len && A_vvmap[A_id].constraint_id == row) { + libff::bigint value = libsnarkBigintFromBytes(A_vvmap[A_id].variable_value); + if (!value.is_zero()) { + lin_comb_A.add_term(A_vvmap[A_id].variable_id, value); + } + A_id++; } - ss << outputInputAsHex(libsnarkBigintFromBytes(public_inputs + i*32)); - } - ss << "]" << "\n"; - ss << "}" << "\n"; - - std::string s = ss.str(); - //write json string to proof_path - writeToFile(proof_path, s); + while (B_id < B_len && B_vvmap[B_id].constraint_id == row) { + libff::bigint value = libsnarkBigintFromBytes(B_vvmap[B_id].variable_value); + if (!value.is_zero()) { + lin_comb_B.add_term(B_vvmap[B_id].variable_id, value); + } + B_id++; + } + while (C_id < C_len && C_vvmap[C_id].constraint_id == row) { + libff::bigint value = libsnarkBigintFromBytes(C_vvmap[C_id].variable_value); + if (!value.is_zero()) { + lin_comb_C.add_term(C_vvmap[C_id].variable_id, value); + } + C_id++; + } + cs.add_constraint(r1cs_constraint>(lin_comb_A, lin_comb_B, lin_comb_C)); + } + return cs; } -} - -bool _gm17_setup(const uint8_t* A, const uint8_t* B, const uint8_t* C, int A_len, int B_len, int C_len, int constraints, int variables, int inputs, const char* pk_path, const char* vk_path) +r1cs_se_ppzksnark_keypair generateKeypair(const r1cs_se_ppzksnark_constraint_system& cs) { - libff::inhibit_profiling_info = true; - libff::inhibit_profiling_counters = true; - - //initialize curve parameters - libff::alt_bn128_pp::init_public_params(); - - auto cs = gm17::createConstraintSystem(A, B, C, A_len, B_len, C_len, constraints, variables, inputs); - - assert(cs.num_variables() >= (unsigned)inputs); - assert(cs.num_inputs() == (unsigned)inputs); - assert(cs.num_constraints() == (unsigned)constraints); - - // create keypair - auto keypair = r1cs_se_ppzksnark_generator(cs); - - // Export vk and pk to files - gm17::serializeProvingKeyToFile(keypair.pk, pk_path); - gm17::serializeVerificationKeyToFile(keypair.vk, vk_path); - - return true; + return r1cs_se_ppzksnark_generator(cs); //from r1cs_se_ppzksnark.hpp } -bool _gm17_generate_proof(const char* pk_path, const char* proof_path, const uint8_t* public_inputs, int public_inputs_length, const uint8_t* private_inputs, int private_inputs_length) +std::string serializeVerificationKey(r1cs_se_ppzksnark_verification_key* vk) { - libff::inhibit_profiling_info = true; - libff::inhibit_profiling_counters = true; + std::stringstream ss; + unsigned queryLength = vk->query.size(); - //initialize curve parameters - libff::alt_bn128_pp::init_public_params(); - auto pk = gm17::deserializeProvingKeyFromFile(pk_path); - - // assign variables based on witness values, excludes ~one - r1cs_variable_assignment > full_variable_assignment; - for (int i = 1; i < public_inputs_length; i++) { - full_variable_assignment.push_back(libff::Fr(libsnarkBigintFromBytes(public_inputs + i*32))); - } - for (int i = 0; i < private_inputs_length; i++) { - full_variable_assignment.push_back(libff::Fr(libsnarkBigintFromBytes(private_inputs + i*32))); - } - - // split up variables into primary and auxiliary inputs. Does *NOT* include the constant 1 - // Public variables belong to primary input, private variables are auxiliary input. - r1cs_primary_input> primary_input(full_variable_assignment.begin(), full_variable_assignment.begin() + public_inputs_length-1); - r1cs_primary_input> auxiliary_input(full_variable_assignment.begin() + public_inputs_length-1, full_variable_assignment.end()); - - // for debugging - // cout << "full variable assignment:"<< endl << full_variable_assignment; - // cout << "primary input:"<< endl << primary_input; - // cout << "auxiliary input:"<< endl << auxiliary_input; - - // Proof Generation - auto proof = r1cs_se_ppzksnark_prover(pk, primary_input, auxiliary_input); - - gm17::exportProof(proof, proof_path, public_inputs, public_inputs_length); - - return true; + ss << "vk.h = " << outputPointG2AffineAsHex(vk->H) << endl; + ss << "vk.g_alpha = " << outputPointG1AffineAsHex(vk->G_alpha) << endl; + ss << "vk.h_beta = " << outputPointG2AffineAsHex(vk->H_beta) << endl; + ss << "vk.g_gamma = " << outputPointG1AffineAsHex(vk->G_gamma) << endl; + ss << "vk.h_gamma = " << outputPointG2AffineAsHex(vk->H_gamma) << endl; + ss << "vk.query.len() = " << queryLength << endl; + for (size_t i = 0; i < queryLength; ++i) { + auto vk_query_i = outputPointG1AffineAsHex(vk->query[i]); + ss << "vk.query[" << i << "] = " << vk_query_i << endl; + } + return ss.str(); } +std::string serializeProof(r1cs_se_ppzksnark_proof* proof, const uint8_t* public_inputs, int32_t public_inputs_length) +{ + std::stringstream ss; + ss << "{" + << "\n"; + ss << "\t\"proof\": {" + << "\n"; + ss << "\t\t\"a\": " << outputPointG1AffineAsHexJson(proof->A) << ",\n"; + ss << "\t\t\"b\": " << outputPointG2AffineAsHexJson(proof->B) << ",\n"; + ss << "\t\t\"c\": " << outputPointG1AffineAsHexJson(proof->C) << "\n"; + ss << "\t}," + << "\n"; + ss << "\t\"inputs\": " + << "["; + for (int i = 1; i < public_inputs_length; i++) { + if (i != 1) { + ss << ","; + } + ss << outputInputAsHex(libsnarkBigintFromBytes(public_inputs + i * 32)); + } + ss << "]" + << "\n"; + ss << "}" + << "\n"; + std::string str = ss.str(); + return str; +} +} + +setup_result_t gm17_setup(const uint8_t* A, const uint8_t* B, const uint8_t* C, int32_t A_len, int32_t B_len, int32_t C_len, int32_t constraints, int32_t variables, int32_t inputs) +{ + libff::inhibit_profiling_info = true; + libff::inhibit_profiling_counters = true; + + // initialize curve parameters + libff::alt_bn128_pp::init_public_params(); + + auto cs = gm17::createConstraintSystem(A, B, C, A_len, B_len, C_len, constraints, variables, inputs); + assert(cs.num_variables() >= (unsigned)inputs); + assert(cs.num_inputs() == (unsigned)inputs); + assert(cs.num_constraints() == (unsigned)constraints); + + // create keypair + auto keypair = r1cs_se_ppzksnark_generator(cs); + auto vk = gm17::serializeVerificationKey(&keypair.vk); + + std::stringstream ss; + ss << keypair.pk; + + std::string pk = ss.str(); + + buffer_t vk_buf, pk_buf; + __alloc(&vk_buf, vk.size()); + __alloc(&pk_buf, pk.size()); + + vk.copy(reinterpret_cast(vk_buf.data), vk_buf.length); + pk.copy(reinterpret_cast(pk_buf.data), pk_buf.length); + + setup_result_t result(vk_buf, pk_buf); + return result; +} + +proof_result_t gm17_generate_proof(buffer_t* pk_buf, const uint8_t* public_inputs, int32_t public_inputs_length, const uint8_t* private_inputs, int32_t private_inputs_length) +{ + libff::inhibit_profiling_info = true; + libff::inhibit_profiling_counters = true; + + //initialize curve parameters + libff::alt_bn128_pp::init_public_params(); + r1cs_se_ppzksnark_proving_key proving_key; + + std::stringstream ss; + ss.write(reinterpret_cast(pk_buf->data), pk_buf->length); + ss.rdbuf()->pubseekpos(0, std::ios_base::in); + ss >> proving_key; + + // assign variables based on witness values, excludes ~one + r1cs_variable_assignment> full_variable_assignment; + for (int i = 1; i < public_inputs_length; i++) { + full_variable_assignment.push_back(libff::Fr(libsnarkBigintFromBytes(public_inputs + i * 32))); + } + for (int i = 0; i < private_inputs_length; i++) { + full_variable_assignment.push_back(libff::Fr(libsnarkBigintFromBytes(private_inputs + i * 32))); + } + + // split up variables into primary and auxiliary inputs. Does *NOT* include the constant 1 + // Public variables belong to primary input, private variables are auxiliary input. + r1cs_primary_input> primary_input(full_variable_assignment.begin(), full_variable_assignment.begin() + public_inputs_length - 1); + r1cs_primary_input> auxiliary_input(full_variable_assignment.begin() + public_inputs_length - 1, full_variable_assignment.end()); + + // for debugging + // cout << "full variable assignment:" << endl << full_variable_assignment; + // cout << "primary input:" << endl << primary_input; + // cout << "auxiliary input:" << endl << auxiliary_input; + + // Proof Generation + auto proof = r1cs_se_ppzksnark_prover(proving_key, primary_input, auxiliary_input); + auto proof_json = gm17::serializeProof(&proof, public_inputs, public_inputs_length); + + buffer_t proof_buf; + __alloc(&proof_buf, proof_json.size()); + + proof_json.copy(reinterpret_cast(proof_buf.data), proof_buf.length); + proof_result_t result(proof_buf); + return result; +} \ No newline at end of file diff --git a/zokrates_core/lib/gm17.hpp b/zokrates_core/lib/gm17.hpp index 05637d79..e449c2db 100644 --- a/zokrates_core/lib/gm17.hpp +++ b/zokrates_core/lib/gm17.hpp @@ -11,29 +11,25 @@ extern "C" { #endif -#include -#include +#include "ffi.hpp" -bool _gm17_setup(const uint8_t* A, - const uint8_t* B, - const uint8_t* C, - int A_len, - int B_len, - int C_len, - int constraints, - int variables, - int inputs, - const char* pk_path, - const char* vk_path - ); +setup_result_t gm17_setup( + const uint8_t* A, + const uint8_t* B, + const uint8_t* C, + int32_t A_len, + int32_t B_len, + int32_t C_len, + int32_t constraints, + int32_t variables, + int32_t inputs); -bool _gm17_generate_proof(const char* pk_path, - const char* proof_path, - const uint8_t* public_inputs, - int public_inputs_length, - const uint8_t* private_inputs, - int private_inputs_length - ); +proof_result_t gm17_generate_proof( + buffer_t* pk_buf, + const uint8_t* public_inputs, + int32_t public_inputs_length, + const uint8_t* private_inputs, + int32_t private_inputs_length); #ifdef __cplusplus } // extern "C" diff --git a/zokrates_core/lib/pghr13.cpp b/zokrates_core/lib/pghr13.cpp index 9fd2782d..db7fb692 100644 --- a/zokrates_core/lib/pghr13.cpp +++ b/zokrates_core/lib/pghr13.cpp @@ -1,217 +1,220 @@ /** - * @file wraplibsnark.cpp + * @file pghr13.cpp * @author Jacob Eberhardt * @date 2017 */ -#include "util.hpp" #include "pghr13.hpp" -#include -#include +#include "util.hpp" #include -#include +#include +#include -// contains definition of alt_bn128 ec public parameters +// contains definitions of alt_bn128 ec public parameters #include "libff/algebra/curves/alt_bn128/alt_bn128_pp.hpp" + // contains required interfaces and types (keypair, proof, generator, prover, verifier) #include typedef long integer_coeff_t; -using namespace std; using namespace libsnark; +using std::cout; +using std::endl; namespace pghr13 { - -//takes input and puts it into constraint system r1cs_ppzksnark_constraint_system createConstraintSystem(const uint8_t* A, const uint8_t* B, const uint8_t* C, int A_len, int B_len, int C_len, int constraints, int variables, int inputs) { - r1cs_ppzksnark_constraint_system cs; - cs.primary_input_size = inputs; - cs.auxiliary_input_size = variables - inputs - 1; // ~one not included + r1cs_ppzksnark_constraint_system cs; + cs.primary_input_size = inputs; + cs.auxiliary_input_size = variables - inputs - 1; // ~one not included - cout << "num variables: " << variables < > lin_comb_A, lin_comb_B, lin_comb_C; + // initialize curve parameters + libff::alt_bn128_pp::init_public_params(); - while (A_id < A_len && A_vvmap[A_id].constraint_id == row) { - libff::bigint value = libsnarkBigintFromBytes(A_vvmap[A_id].variable_value); - if (!value.is_zero()) - lin_comb_A.add_term(A_vvmap[A_id].variable_id, value); - A_id++; + for (int row = 0; row < constraints; row++) { + linear_combination> lin_comb_A, lin_comb_B, lin_comb_C; + while (A_id < A_len && A_vvmap[A_id].constraint_id == row) { + libff::bigint value = libsnarkBigintFromBytes(A_vvmap[A_id].variable_value); + if (!value.is_zero()) { + lin_comb_A.add_term(A_vvmap[A_id].variable_id, value); + } + A_id++; + } + while (B_id < B_len && B_vvmap[B_id].constraint_id == row) { + libff::bigint value = libsnarkBigintFromBytes(B_vvmap[B_id].variable_value); + if (!value.is_zero()) { + lin_comb_B.add_term(B_vvmap[B_id].variable_id, value); + } + B_id++; + } + while (C_id < C_len && C_vvmap[C_id].constraint_id == row) { + libff::bigint value = libsnarkBigintFromBytes(C_vvmap[C_id].variable_value); + if (!value.is_zero()) { + lin_comb_C.add_term(C_vvmap[C_id].variable_id, value); + } + C_id++; + } + cs.add_constraint(r1cs_constraint>(lin_comb_A, lin_comb_B, lin_comb_C)); } - while (B_id < B_len && B_vvmap[B_id].constraint_id == row) { - libff::bigint value = libsnarkBigintFromBytes(B_vvmap[B_id].variable_value); - if (!value.is_zero()) - lin_comb_B.add_term(B_vvmap[B_id].variable_id, value); - B_id++; - } - while (C_id < C_len && C_vvmap[C_id].constraint_id == row) { - libff::bigint value = libsnarkBigintFromBytes(C_vvmap[C_id].variable_value); - if (!value.is_zero()) - lin_comb_C.add_term(C_vvmap[C_id].variable_id, value); - C_id++; - } - - cs.add_constraint(r1cs_constraint >(lin_comb_A, lin_comb_B, lin_comb_C)); - } - - return cs; + return cs; } -// keypair generateKeypair(constraints) -r1cs_ppzksnark_keypair generateKeypair(const r1cs_ppzksnark_constraint_system &cs){ - // from r1cs_ppzksnark.hpp - return r1cs_ppzksnark_generator(cs); -} - -void serializeProvingKeyToFile(r1cs_ppzksnark_proving_key pk, const char* pk_path){ - writeToFile(pk_path, pk); -} - -r1cs_ppzksnark_proving_key deserializeProvingKeyFromFile(const char* pk_path){ - return loadFromFile>(pk_path); -} - -void serializeVerificationKeyToFile(r1cs_ppzksnark_verification_key vk, const char* vk_path){ - std::stringstream ss; - - unsigned icLength = vk.encoded_IC_query.rest.indices.size() + 1; - - ss << "\t\tvk.a = " << outputPointG2AffineAsHex(vk.alphaA_g2) << endl; - ss << "\t\tvk.b = " << outputPointG1AffineAsHex(vk.alphaB_g1) << endl; - ss << "\t\tvk.c = " << outputPointG2AffineAsHex(vk.alphaC_g2) << endl; - ss << "\t\tvk.gamma = " << outputPointG2AffineAsHex(vk.gamma_g2) << endl; - ss << "\t\tvk.gamma_beta_1 = " << outputPointG1AffineAsHex(vk.gamma_beta_g1) << endl; - ss << "\t\tvk.gamma_beta_2 = " << outputPointG2AffineAsHex(vk.gamma_beta_g2) << endl; - ss << "\t\tvk.z = " << outputPointG2AffineAsHex(vk.rC_Z_g2) << endl; - ss << "\t\tvk.ic.len() = " << icLength << endl; - ss << "\t\tvk.ic[0] = " << outputPointG1AffineAsHex(vk.encoded_IC_query.first) << endl; - for (size_t i = 1; i < icLength; ++i) - { - auto vkICi = outputPointG1AffineAsHex(vk.encoded_IC_query.rest.values[i - 1]); - ss << "\t\tvk.IC[" << i << "] = " << vkICi << endl; - } - - std::ofstream fh; - fh.open(vk_path, std::ios::binary); - ss.rdbuf()->pubseekpos(0, std::ios_base::out); - fh << ss.rdbuf(); - fh.flush(); - fh.close(); -} - -void exportProof(r1cs_ppzksnark_proof proof, const char* proof_path, const uint8_t* public_inputs, - int public_inputs_length){ - //create JSON file - std::stringstream ss; - ss << "{" << "\n"; - ss << "\t\"proof\":" << "\n"; - ss << "\t{" << "\n"; - ss << "\t\t\"a\":" < generateKeypair(const r1cs_ppzksnark_constraint_system& cs) { - libff::inhibit_profiling_info = true; - libff::inhibit_profiling_counters = true; - - //initialize curve parameters - libff::alt_bn128_pp::init_public_params(); - - auto cs = pghr13::createConstraintSystem(A, B, C, A_len, B_len, C_len, constraints, variables, inputs); - - assert(cs.num_variables() >= (unsigned)inputs); - assert(cs.num_inputs() == (unsigned)inputs); - assert(cs.num_constraints() == (unsigned)constraints); - - // create keypair - auto keypair = r1cs_ppzksnark_generator(cs); - - // Export vk and pk to files - pghr13::serializeProvingKeyToFile(keypair.pk, pk_path); - pghr13::serializeVerificationKeyToFile(keypair.vk, vk_path); - - return true; + return r1cs_ppzksnark_generator(cs); // from r1cs_ppzksnark.hpp } -bool _pghr13_generate_proof(const char* pk_path, const char* proof_path, const uint8_t* public_inputs, int public_inputs_length, const uint8_t* private_inputs, int private_inputs_length) +std::string serializeVerificationKey(r1cs_ppzksnark_verification_key* vk) { - libff::inhibit_profiling_info = true; - libff::inhibit_profiling_counters = true; + std::stringstream ss; + unsigned icLength = vk->encoded_IC_query.rest.indices.size() + 1; - //initialize curve parameters - libff::alt_bn128_pp::init_public_params(); - auto pk = pghr13::deserializeProvingKeyFromFile(pk_path); - - // assign variables based on witness values, excludes ~one - r1cs_variable_assignment > full_variable_assignment; - for (int i = 1; i < public_inputs_length; i++) { - full_variable_assignment.push_back(libff::Fr(libsnarkBigintFromBytes(public_inputs + i*32))); - } - for (int i = 0; i < private_inputs_length; i++) { - full_variable_assignment.push_back(libff::Fr(libsnarkBigintFromBytes(private_inputs + i*32))); - } - - // split up variables into primary and auxiliary inputs. Does *NOT* include the constant 1 - // Public variables belong to primary input, private variables are auxiliary input. - r1cs_primary_input> primary_input(full_variable_assignment.begin(), full_variable_assignment.begin() + public_inputs_length-1); - r1cs_primary_input> auxiliary_input(full_variable_assignment.begin() + public_inputs_length-1, full_variable_assignment.end()); - - // for debugging - // cout << "full variable assignment:"<< endl << full_variable_assignment; - // cout << "primary input:"<< endl << primary_input; - // cout << "auxiliary input:"<< endl << auxiliary_input; - - // Proof Generation - auto proof = r1cs_ppzksnark_prover(pk, primary_input, auxiliary_input); - - pghr13::exportProof(proof, proof_path, public_inputs, public_inputs_length); - - return true; + ss << "vk.a = " << outputPointG2AffineAsHex(vk->alphaA_g2) << endl; + ss << "vk.b = " << outputPointG1AffineAsHex(vk->alphaB_g1) << endl; + ss << "vk.c = " << outputPointG2AffineAsHex(vk->alphaC_g2) << endl; + ss << "vk.gamma = " << outputPointG2AffineAsHex(vk->gamma_g2) << endl; + ss << "vk.gamma_beta_1 = " << outputPointG1AffineAsHex(vk->gamma_beta_g1) << endl; + ss << "vk.gamma_beta_2 = " << outputPointG2AffineAsHex(vk->gamma_beta_g2) << endl; + ss << "vk.z = " << outputPointG2AffineAsHex(vk->rC_Z_g2) << endl; + ss << "vk.ic.len() = " << icLength << endl; + ss << "vk.ic[0] = " << outputPointG1AffineAsHex(vk->encoded_IC_query.first) << endl; + for (size_t i = 1; i < icLength; ++i) { + auto vk_ic_i = outputPointG1AffineAsHex(vk->encoded_IC_query.rest.values[i - 1]); + ss << "vk.ic[" << i << "] = " << vk_ic_i << endl; + } + std::string str = ss.str(); + return str; +} + +std::string serializeProof(r1cs_ppzksnark_proof* proof, const uint8_t* public_inputs, int public_inputs_length) +{ + std::stringstream ss; + ss << "{" + << "\n"; + ss << "\t\"proof\": {" + << "\n"; + ss << "\t\t\"a\": " << outputPointG1AffineAsHexJson(proof->g_A.g) << ",\n"; + ss << "\t\t\"a_p\": " << outputPointG1AffineAsHexJson(proof->g_A.h) << ",\n"; + ss << "\t\t\"b\": " << outputPointG2AffineAsHexJson(proof->g_B.g) << ",\n"; + ss << "\t\t\"b_p\": " << outputPointG1AffineAsHexJson(proof->g_B.h) << ",\n"; + ss << "\t\t\"c\": " << outputPointG1AffineAsHexJson(proof->g_C.g) << ",\n"; + ss << "\t\t\"c_p\": " << outputPointG1AffineAsHexJson(proof->g_C.h) << ",\n"; + ss << "\t\t\"h\": " << outputPointG1AffineAsHexJson(proof->g_H) << ",\n"; + ss << "\t\t\"k\": " << outputPointG1AffineAsHexJson(proof->g_K) << "\n"; + ss << "\t}," + << "\n"; + ss << "\t\"inputs\": " + << "["; + for (int i = 1; i < public_inputs_length; i++) { + if (i != 1) { + ss << ","; + } + ss << outputInputAsHex(libsnarkBigintFromBytes(public_inputs + i * 32)); + } + ss << "]" + << "\n"; + ss << "}" + << "\n"; + std::string str = ss.str(); + return str; +} +} + +setup_result_t pghr13_setup(const uint8_t* A, const uint8_t* B, const uint8_t* C, int32_t A_len, int32_t B_len, int32_t C_len, int32_t constraints, int32_t variables, int32_t inputs) +{ + libff::inhibit_profiling_info = true; + libff::inhibit_profiling_counters = true; + + // initialize curve parameters + libff::alt_bn128_pp::init_public_params(); + + auto cs = pghr13::createConstraintSystem(A, B, C, A_len, B_len, C_len, constraints, variables, inputs); + + assert(cs.num_variables() >= (unsigned)inputs); + assert(cs.num_inputs() == (unsigned)inputs); + assert(cs.num_constraints() == (unsigned)constraints); + + // create keypair + auto keypair = r1cs_ppzksnark_generator(cs); + auto vk = pghr13::serializeVerificationKey(&keypair.vk); + + std::stringstream ss; + ss << keypair.pk; + + std::string pk = ss.str(); + + buffer_t vk_buf, pk_buf; + __alloc(&vk_buf, vk.size()); + __alloc(&pk_buf, pk.size()); + + vk.copy(reinterpret_cast(vk_buf.data), vk_buf.length); + pk.copy(reinterpret_cast(pk_buf.data), pk_buf.length); + + setup_result_t result(vk_buf, pk_buf); + return result; +} + +proof_result_t pghr13_generate_proof(buffer_t* pk_buf, const uint8_t* public_inputs, int32_t public_inputs_length, const uint8_t* private_inputs, int32_t private_inputs_length) +{ + libff::inhibit_profiling_info = true; + libff::inhibit_profiling_counters = true; + + // initialize curve parameters + libff::alt_bn128_pp::init_public_params(); + r1cs_ppzksnark_proving_key proving_key; + + std::stringstream ss; + ss.write(reinterpret_cast(pk_buf->data), pk_buf->length); + ss.rdbuf()->pubseekpos(0, std::ios_base::in); + ss >> proving_key; + + // assign variables based on witness values, excludes ~one + r1cs_variable_assignment> full_variable_assignment; + for (int i = 1; i < public_inputs_length; i++) { + full_variable_assignment.push_back(libff::Fr(libsnarkBigintFromBytes(public_inputs + i * 32))); + } + for (int i = 0; i < private_inputs_length; i++) { + full_variable_assignment.push_back(libff::Fr(libsnarkBigintFromBytes(private_inputs + i * 32))); + } + + // split up variables into primary and auxiliary inputs. Does *NOT* include the constant 1 + // Public variables belong to primary input, private variables are auxiliary input. + r1cs_primary_input> primary_input(full_variable_assignment.begin(), full_variable_assignment.begin() + public_inputs_length - 1); + r1cs_primary_input> auxiliary_input(full_variable_assignment.begin() + public_inputs_length - 1, full_variable_assignment.end()); + + // for debugging + // cout << "full variable assignment:" << endl << full_variable_assignment; + // cout << "primary input:" << endl << primary_input; + // cout << "auxiliary input:" << endl << auxiliary_input; + + // Proof Generation + auto proof = r1cs_ppzksnark_prover(proving_key, primary_input, auxiliary_input); + auto proof_json = pghr13::serializeProof(&proof, public_inputs, public_inputs_length); + + buffer_t proof_buf; + __alloc(&proof_buf, proof_json.size()); + + proof_json.copy(reinterpret_cast(proof_buf.data), proof_buf.length); + proof_result_t result(proof_buf); + return result; } diff --git a/zokrates_core/lib/pghr13.hpp b/zokrates_core/lib/pghr13.hpp index f6dbefba..83ff70aa 100644 --- a/zokrates_core/lib/pghr13.hpp +++ b/zokrates_core/lib/pghr13.hpp @@ -7,36 +7,30 @@ #pragma once -#include "util.hpp" - #ifdef __cplusplus extern "C" { #endif -#include -#include +#include "ffi.hpp" -bool _pghr13_setup(const uint8_t* A, - const uint8_t* B, - const uint8_t* C, - int A_len, - int B_len, - int C_len, - int constraints, - int variables, - int inputs, - const char* pk_path, - const char* vk_path - ); +setup_result_t pghr13_setup( + const uint8_t* A, + const uint8_t* B, + const uint8_t* C, + int32_t A_len, + int32_t B_len, + int32_t C_len, + int32_t constraints, + int32_t variables, + int32_t inputs); -bool _pghr13_generate_proof(const char* pk_path, - const char* proof_path, - const uint8_t* public_inputs, - int public_inputs_length, - const uint8_t* private_inputs, - int private_inputs_length - ); +proof_result_t pghr13_generate_proof( + buffer_t* pk_buf, + const uint8_t* public_inputs, + int32_t public_inputs_length, + const uint8_t* private_inputs, + int32_t private_inputs_length); #ifdef __cplusplus } // extern "C" -#endif +#endif \ No newline at end of file diff --git a/zokrates_core/lib/util.cpp b/zokrates_core/lib/util.cpp index 291db61c..8ed82fe1 100644 --- a/zokrates_core/lib/util.cpp +++ b/zokrates_core/lib/util.cpp @@ -1,5 +1,5 @@ /** - * @file wraplibsnark.cpp + * @file util.cpp * @author Jacob Eberhardt * @date 2017 @@ -7,83 +7,64 @@ #include "util.hpp" -using namespace std; - // conversion byte[32] <-> libsnark bigint. libff::bigint libsnarkBigintFromBytes(const uint8_t* _x) { - libff::bigint x; - - for (unsigned i = 0; i < 4; i++) { - for (unsigned j = 0; j < 8; j++) { - x.data[3 - i] |= uint64_t(_x[i * 8 + j]) << (8 * (7-j)); + libff::bigint x; + for (unsigned i = 0; i < 4; i++) { + for (unsigned j = 0; j < 8; j++) { + x.data[3 - i] |= uint64_t(_x[i * 8 + j]) << (8 * (7 - j)); + } } - } - - return x; + + return x; } -std::string HexStringFromLibsnarkBigint(libff::bigint _x){ +std::string HexStringFromLibsnarkBigint(libff::bigint _x) +{ uint8_t x[32]; - for (unsigned i = 0; i < 4; i++) - for (unsigned j = 0; j < 8; j++) - x[i * 8 + j] = uint8_t(uint64_t(_x.data[3 - i]) >> (8 * (7 - j))); - + for (unsigned i = 0; i < 4; i++) { + for (unsigned j = 0; j < 8; j++) { + x[i * 8 + j] = uint8_t(uint64_t(_x.data[3 - i]) >> (8 * (7 - j))); + } + } std::stringstream ss; ss << std::setfill('0'); - for (unsigned i = 0; i<32; i++) { - ss << std::hex << std::setw(2) << (int)x[i]; + for (unsigned i = 0; i < 32; i++) { + ss << std::hex << std::setw(2) << (int)x[i]; } - return ss.str(); } -std::string outputInputAsHex(libff::bigint _x){ - return "\"0x" + HexStringFromLibsnarkBigint(_x) + "\""; +std::string outputInputAsHex(libff::bigint _x) +{ + return "\"0x" + HexStringFromLibsnarkBigint(_x) + "\""; } std::string outputPointG1AffineAsHex(libff::alt_bn128_G1 _p) { - libff::alt_bn128_G1 aff = _p; - aff.to_affine_coordinates(); - return - "0x" + - HexStringFromLibsnarkBigint(aff.X.as_bigint()) + - ", 0x" + - HexStringFromLibsnarkBigint(aff.Y.as_bigint()); + libff::alt_bn128_G1 aff = _p; + aff.to_affine_coordinates(); + return "0x" + HexStringFromLibsnarkBigint(aff.X.as_bigint()) + ", 0x" + HexStringFromLibsnarkBigint(aff.Y.as_bigint()); } std::string outputPointG1AffineAsHexJson(libff::alt_bn128_G1 _p) { - libff::alt_bn128_G1 aff = _p; - aff.to_affine_coordinates(); - return - "[\"0x" + - HexStringFromLibsnarkBigint(aff.X.as_bigint()) + - "\", \"0x" + - HexStringFromLibsnarkBigint(aff.Y.as_bigint())+"\"]"; + libff::alt_bn128_G1 aff = _p; + aff.to_affine_coordinates(); + return "[\"0x" + HexStringFromLibsnarkBigint(aff.X.as_bigint()) + "\", \"0x" + HexStringFromLibsnarkBigint(aff.Y.as_bigint()) + "\"]"; } std::string outputPointG2AffineAsHex(libff::alt_bn128_G2 _p) { - libff::alt_bn128_G2 aff = _p; - aff.to_affine_coordinates(); - return - "[0x" + - HexStringFromLibsnarkBigint(aff.X.c1.as_bigint()) + ", 0x" + - HexStringFromLibsnarkBigint(aff.X.c0.as_bigint()) + "], [0x" + - HexStringFromLibsnarkBigint(aff.Y.c1.as_bigint()) + ", 0x" + - HexStringFromLibsnarkBigint(aff.Y.c0.as_bigint()) + "]"; + libff::alt_bn128_G2 aff = _p; + aff.to_affine_coordinates(); + return "[0x" + HexStringFromLibsnarkBigint(aff.X.c1.as_bigint()) + ", 0x" + HexStringFromLibsnarkBigint(aff.X.c0.as_bigint()) + "], [0x" + HexStringFromLibsnarkBigint(aff.Y.c1.as_bigint()) + ", 0x" + HexStringFromLibsnarkBigint(aff.Y.c0.as_bigint()) + "]"; } std::string outputPointG2AffineAsHexJson(libff::alt_bn128_G2 _p) { - libff::alt_bn128_G2 aff = _p; - aff.to_affine_coordinates(); - return - "[[\"0x" + - HexStringFromLibsnarkBigint(aff.X.c1.as_bigint()) + "\", \"0x" + - HexStringFromLibsnarkBigint(aff.X.c0.as_bigint()) + "\"], [\"0x" + - HexStringFromLibsnarkBigint(aff.Y.c1.as_bigint()) + "\", \"0x" + - HexStringFromLibsnarkBigint(aff.Y.c0.as_bigint()) + "\"]]"; + libff::alt_bn128_G2 aff = _p; + aff.to_affine_coordinates(); + return "[[\"0x" + HexStringFromLibsnarkBigint(aff.X.c1.as_bigint()) + "\", \"0x" + HexStringFromLibsnarkBigint(aff.X.c0.as_bigint()) + "\"], [\"0x" + HexStringFromLibsnarkBigint(aff.Y.c1.as_bigint()) + "\", \"0x" + HexStringFromLibsnarkBigint(aff.Y.c0.as_bigint()) + "\"]]"; } diff --git a/zokrates_core/lib/util.hpp b/zokrates_core/lib/util.hpp index 1fe3891c..b206d59e 100644 --- a/zokrates_core/lib/util.hpp +++ b/zokrates_core/lib/util.hpp @@ -1,52 +1,18 @@ #pragma once -// contains definition of alt_bn128 ec public parameters +// contains definitions of alt_bn128 ec public parameters #include "libff/algebra/curves/alt_bn128/alt_bn128_pp.hpp" -#include -#include + #include #include +#include +#include +#include libff::bigint libsnarkBigintFromBytes(const uint8_t* _x); - std::string HexStringFromLibsnarkBigint(libff::bigint _x); - std::string outputInputAsHex(libff::bigint _x); - std::string outputPointG1AffineAsHex(libff::alt_bn128_G1 _p); - std::string outputPointG1AffineAsHexJson(libff::alt_bn128_G1 _p); - std::string outputPointG2AffineAsHex(libff::alt_bn128_G2 _p); - -std::string outputPointG2AffineAsHexJson(libff::alt_bn128_G2 _p); - -template -void writeToFile(std::string path, T& obj) { - std::stringstream ss; - ss << obj; - std::ofstream fh; - fh.open(path, std::ios::binary); - ss.rdbuf()->pubseekpos(0, std::ios_base::out); - fh << ss.rdbuf(); - fh.flush(); - fh.close(); -} - -template -T loadFromFile(std::string path) { - std::stringstream ss; - std::ifstream fh(path, std::ios::binary); - - assert(fh.is_open()); - - ss << fh.rdbuf(); - fh.close(); - - ss.rdbuf()->pubseekpos(0, std::ios_base::in); - - T obj; - ss >> obj; - - return obj; -} \ No newline at end of file +std::string outputPointG2AffineAsHexJson(libff::alt_bn128_G2 _p); \ No newline at end of file diff --git a/zokrates_core/src/absy/from_ast.rs b/zokrates_core/src/absy/from_ast.rs index 6b9b6135..7542e134 100644 --- a/zokrates_core/src/absy/from_ast.rs +++ b/zokrates_core/src/absy/from_ast.rs @@ -25,13 +25,13 @@ impl<'ast> From> for absy::ImportNode<'ast> { match import { pest::ImportDirective::Main(import) => { - imports::Import::new(None, import.source.span.as_str()) + imports::Import::new(None, std::path::Path::new(import.source.span.as_str())) .alias(import.alias.map(|a| a.span.as_str())) .span(import.span) } pest::ImportDirective::From(import) => imports::Import::new( Some(import.symbol.span.as_str()), - import.source.span.as_str(), + std::path::Path::new(import.source.span.as_str()), ) .alias(import.alias.map(|a| a.span.as_str())) .span(import.span), @@ -156,76 +156,83 @@ fn statements_from_statement<'ast, T: Field>( pest::Statement::Definition(s) => statements_from_definition(s), pest::Statement::Iteration(s) => vec![absy::StatementNode::from(s)], pest::Statement::Assertion(s) => vec![absy::StatementNode::from(s)], - pest::Statement::Assignment(s) => vec![absy::StatementNode::from(s)], pest::Statement::Return(s) => vec![absy::StatementNode::from(s)], - pest::Statement::MultiAssignment(s) => statements_from_multi_assignment(s), } } -fn statements_from_multi_assignment<'ast, T: Field>( - assignment: pest::MultiAssignmentStatement<'ast>, -) -> Vec> { - use absy::NodeValue; - - let declarations = assignment - .lhs - .clone() - .into_iter() - .filter(|i| i.ty.is_some()) - .map(|i| { - absy::Statement::Declaration( - absy::Variable::new( - i.id.span.as_str(), - absy::UnresolvedTypeNode::from(i.ty.unwrap()), - ) - .span(i.id.span), - ) - .span(i.span) - }); - - let lhs = assignment - .lhs - .into_iter() - .map(|i| absy::Assignee::Identifier(i.id.span.as_str()).span(i.id.span)) - .collect(); - - let multi_def = absy::Statement::MultipleDefinition( - lhs, - absy::Expression::FunctionCall( - &assignment.function_id.span.as_str(), - assignment - .arguments - .into_iter() - .map(|e| absy::ExpressionNode::from(e)) - .collect(), - ) - .span(assignment.function_id.span), - ) - .span(assignment.span); - - declarations.chain(std::iter::once(multi_def)).collect() -} - fn statements_from_definition<'ast, T: Field>( definition: pest::DefinitionStatement<'ast>, ) -> Vec> { use absy::NodeValue; - vec![ - absy::Statement::Declaration( - absy::Variable::new( - definition.id.span.as_str(), - absy::UnresolvedTypeNode::from(definition.ty), + let lhs = definition.lhs; + + match lhs.len() { + 1 => { + // Definition or assignment + let a = lhs[0].clone(); + + let e: absy::ExpressionNode = absy::ExpressionNode::from(definition.expression); + + let s = match e.value { + absy::Expression::FunctionCall(..) => absy::Statement::MultipleDefinition( + vec![absy::AssigneeNode::from(a.a.clone())], + e, + ), + _ => absy::Statement::Definition(absy::AssigneeNode::from(a.a.clone()), e), + }; + + match a.ty { + Some(ty) => { + assert_eq!(a.a.accesses.len(), 0); + + let declaration = absy::Statement::Declaration( + absy::Variable::new( + a.a.id.span.as_str(), + absy::UnresolvedTypeNode::from(ty), + ) + .span(a.a.id.span.clone()), + ) + .span(definition.span.clone()); + + vec![declaration, s.span(definition.span)] + } + None => { + // Assignment + vec![s.span(definition.span)] + } + } + } + _ => { + // Multidefinition + let declarations = lhs.clone().into_iter().filter(|i| i.ty.is_some()).map(|a| { + let ty = a.ty; + let a = a.a; + + assert_eq!(a.accesses.len(), 0); + absy::Statement::Declaration( + absy::Variable::new( + a.id.span.as_str(), + absy::UnresolvedTypeNode::from(ty.unwrap()), + ) + .span(a.id.span), + ) + .span(a.span) + }); + let lhs = lhs + .into_iter() + .map(|i| absy::Assignee::Identifier(i.a.id.span.as_str()).span(i.a.id.span)) + .collect(); + + let multi_def = absy::Statement::MultipleDefinition( + lhs, + absy::ExpressionNode::from(definition.expression), ) - .span(definition.id.span.clone()), - ) - .span(definition.span.clone()), - absy::Statement::Definition( - absy::AssigneeNode::from(definition.id), - absy::ExpressionNode::from(definition.expression), - ) - .span(definition.span), - ] + .span(definition.span); + + declarations.chain(std::iter::once(multi_def)).collect() + } + } } impl<'ast, T: Field> From> for absy::StatementNode<'ast, T> { @@ -283,34 +290,12 @@ impl<'ast, T: Field> From> for absy::StatementNod .flat_map(|s| statements_from_statement(s)) .collect(); - let from = match from.value { - absy::Expression::FieldConstant(n) => n, - e => unimplemented!("For loop bounds should be constants, found {}", e), - }; - - let to = match to.value { - absy::Expression::FieldConstant(n) => n, - e => unimplemented!("For loop bounds should be constants, found {}", e), - }; - let var = absy::Variable::new(index, ty).span(statement.index.span); absy::Statement::For(var, from, to, statements).span(statement.span) } } -impl<'ast, T: Field> From> for absy::StatementNode<'ast, T> { - fn from(statement: pest::AssignmentStatement<'ast>) -> absy::StatementNode { - use absy::NodeValue; - - absy::Statement::Definition( - absy::AssigneeNode::from(statement.assignee), - absy::ExpressionNode::from(statement.expression), - ) - .span(statement.span) - } -} - impl<'ast, T: Field> From> for absy::ExpressionNode<'ast, T> { fn from(expression: pest::Expression<'ast>) -> absy::ExpressionNode<'ast, T> { match expression { @@ -981,4 +966,147 @@ mod tests { absy::Module::::from(ast); } } + #[test] + fn declarations() { + use self::pest::Span; + + let span = Span::new(&"", 0, 0).unwrap(); + + // For different definitions, we generate declarations + // Case 1: `id = expr` where `expr` is not a function call + // This is a simple assignment, doesn't implicitely declare a variable + // A `Definition` is generatedm and no `Declaration`s + + let definition = pest::DefinitionStatement { + lhs: vec![pest::OptionallyTypedAssignee { + ty: None, + a: pest::Assignee { + id: pest::IdentifierExpression { + value: String::from("a"), + span: span.clone(), + }, + accesses: vec![], + span: span.clone(), + }, + span: span.clone(), + }], + expression: pest::Expression::Constant(pest::ConstantExpression::DecimalNumber( + pest::DecimalNumberExpression { + value: String::from("42"), + span: span.clone(), + }, + )), + span: span.clone(), + }; + + let statements: Vec> = + statements_from_definition(definition); + + assert_eq!(statements.len(), 1); + match &statements[0].value { + absy::Statement::Definition(..) => {} + s => { + panic!("should be a Definition, found {}", s); + } + }; + + // Case 2: `id = expr` where `expr` is a function call + // A MultiDef is generated + + let definition = pest::DefinitionStatement { + lhs: vec![pest::OptionallyTypedAssignee { + ty: None, + a: pest::Assignee { + id: pest::IdentifierExpression { + value: String::from("a"), + span: span.clone(), + }, + accesses: vec![], + span: span.clone(), + }, + span: span.clone(), + }], + expression: pest::Expression::Postfix(pest::PostfixExpression { + id: pest::IdentifierExpression { + value: String::from("foo"), + span: span.clone(), + }, + accesses: vec![pest::Access::Call(pest::CallAccess { + expressions: vec![], + span: span.clone(), + })], + span: span.clone(), + }), + span: span.clone(), + }; + + let statements: Vec> = + statements_from_definition(definition); + + assert_eq!(statements.len(), 1); + match &statements[0].value { + absy::Statement::MultipleDefinition(..) => {} + s => { + panic!("should be a Definition, found {}", s); + } + }; + // Case 3: `ids = expr` where `expr` is a function call + // This implicitely declares all variables which are type annotated + + // `field a, b = foo()` + + let definition = pest::DefinitionStatement { + lhs: vec![ + pest::OptionallyTypedAssignee { + ty: Some(pest::Type::Basic(pest::BasicType::Field(pest::FieldType { + span: span.clone(), + }))), + a: pest::Assignee { + id: pest::IdentifierExpression { + value: String::from("a"), + span: span.clone(), + }, + accesses: vec![], + span: span.clone(), + }, + span: span.clone(), + }, + pest::OptionallyTypedAssignee { + ty: None, + a: pest::Assignee { + id: pest::IdentifierExpression { + value: String::from("b"), + span: span.clone(), + }, + accesses: vec![], + span: span.clone(), + }, + span: span.clone(), + }, + ], + expression: pest::Expression::Postfix(pest::PostfixExpression { + id: pest::IdentifierExpression { + value: String::from("foo"), + span: span.clone(), + }, + accesses: vec![pest::Access::Call(pest::CallAccess { + expressions: vec![], + span: span.clone(), + })], + span: span.clone(), + }), + span: span.clone(), + }; + + let statements: Vec> = + statements_from_definition(definition); + + assert_eq!(statements.len(), 2); + match &statements[1].value { + absy::Statement::MultipleDefinition(..) => {} + s => { + panic!("should be a Definition, found {}", s); + } + }; + } } diff --git a/zokrates_core/src/absy/mod.rs b/zokrates_core/src/absy/mod.rs index 8d8bcfe5..f05a6437 100644 --- a/zokrates_core/src/absy/mod.rs +++ b/zokrates_core/src/absy/mod.rs @@ -16,6 +16,7 @@ pub use crate::absy::parameter::{Parameter, ParameterNode}; use crate::absy::types::{FunctionIdentifier, UnresolvedSignature, UnresolvedType, UserTypeId}; pub use crate::absy::variable::{Variable, VariableNode}; use embed::FlatEmbed; +use std::path::PathBuf; use crate::imports::ImportNode; use std::fmt; @@ -27,7 +28,7 @@ use std::collections::HashMap; pub type Identifier<'ast> = &'ast str; /// The identifier of a `Module`, typically a path or uri -pub type ModuleId = String; +pub type ModuleId = PathBuf; /// A collection of `Module`s pub type Modules<'ast, T> = HashMap>; @@ -171,7 +172,12 @@ impl<'ast> SymbolImport<'ast> { impl<'ast> fmt::Display for SymbolImport<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} from {}", self.symbol_id, self.module_id) + write!( + f, + "{} from {}", + self.symbol_id, + self.module_id.display().to_string() + ) } } @@ -297,7 +303,12 @@ pub enum Statement<'ast, T> { Declaration(VariableNode<'ast>), Definition(AssigneeNode<'ast, T>, ExpressionNode<'ast, T>), Condition(ExpressionNode<'ast, T>, ExpressionNode<'ast, T>), - For(VariableNode<'ast>, T, T, Vec>), + For( + VariableNode<'ast>, + ExpressionNode<'ast, T>, + ExpressionNode<'ast, T>, + Vec>, + ), MultipleDefinition(Vec>, ExpressionNode<'ast, T>), } diff --git a/zokrates_core/src/compile.rs b/zokrates_core/src/compile.rs index c25de528..c4ffe8a2 100644 --- a/zokrates_core/src/compile.rs +++ b/zokrates_core/src/compile.rs @@ -13,13 +13,31 @@ use static_analysis::Analyse; use std::collections::HashMap; use std::fmt; use std::io; -use std::io::BufRead; +use std::path::PathBuf; +use typed_absy::abi::Abi; use typed_arena::Arena; +use zokrates_common::Resolver; use zokrates_field::Field; use zokrates_pest_ast as pest; #[derive(Debug)] -pub struct CompileErrors(Vec); +pub struct CompilationArtifacts { + prog: ir::Prog, + abi: Abi, +} + +impl CompilationArtifacts { + pub fn prog(&self) -> &ir::Prog { + &self.prog + } + + pub fn abi(&self) -> &Abi { + &self.abi + } +} + +#[derive(Debug)] +pub struct CompileErrors(pub Vec); impl From for CompileErrors { fn from(e: CompileError) -> CompileErrors { @@ -27,50 +45,46 @@ impl From for CompileErrors { } } -impl fmt::Display for CompileErrors { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{}", - self.0 - .iter() - .map(|e| format!("{}", e)) - .collect::>() - .join("\n\n") - ) - } -} - #[derive(Debug)] pub enum CompileErrorInner { ParserError(pest::Error), ImportError(imports::Error), - SemanticError(semantics::Error), + SemanticError(semantics::ErrorInner), ReadError(io::Error), } impl CompileErrorInner { - pub fn with_context(self, context: &Option) -> CompileError { + pub fn in_file(self, context: &PathBuf) -> CompileError { CompileError { value: self, - context: context.clone(), + file: context.clone(), } } } #[derive(Debug)] pub struct CompileError { - context: Option, + file: PathBuf, value: CompileErrorInner, } +impl CompileError { + pub fn file(&self) -> &PathBuf { + &self.file + } + + pub fn value(&self) -> &CompileErrorInner { + &self.value + } +} + impl CompileErrors { - pub fn with_context(self, context: Option) -> Self { + pub fn with_context(self, file: PathBuf) -> Self { CompileErrors( self.0 .into_iter() .map(|e| CompileError { - context: context.clone(), + file: file.clone(), ..e }) .collect(), @@ -78,16 +92,6 @@ impl CompileErrors { } } -impl fmt::Display for CompileError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let context = match self.context { - Some(ref x) => x.clone(), - None => "???".to_string(), - }; - write!(f, "{}:{}", context, self.value) - } -} - impl From for CompileErrorInner { fn from(error: pest::Error) -> Self { CompileErrorInner::ParserError(error) @@ -106,50 +110,45 @@ impl From for CompileErrorInner { } } -impl From for CompileErrorInner { +impl From for CompileError { fn from(error: semantics::Error) -> Self { - CompileErrorInner::SemanticError(error) + CompileError { + value: CompileErrorInner::SemanticError(error.inner), + file: error.module_id, + } } } impl fmt::Display for CompileErrorInner { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let res = match *self { - CompileErrorInner::ParserError(ref e) => format!("{}", e), - CompileErrorInner::SemanticError(ref e) => format!("{}", e), - CompileErrorInner::ReadError(ref e) => format!("{}", e), - CompileErrorInner::ImportError(ref e) => format!("{}", e), - }; - write!(f, "{}", res) + match *self { + CompileErrorInner::ParserError(ref e) => write!(f, "{}", e), + CompileErrorInner::SemanticError(ref e) => write!(f, "{}", e), + CompileErrorInner::ReadError(ref e) => write!(f, "{}", e), + CompileErrorInner::ImportError(ref e) => write!(f, "{}", e), + } } } -pub type Resolve = fn(Option, &str) -> Result<(S, String, &str), E>; +type FilePath = PathBuf; -pub fn compile>( - reader: &mut R, - location: Option, - resolve_option: Option>, -) -> Result, CompileErrors> { +pub fn compile>( + source: String, + location: FilePath, + resolver: Option<&dyn Resolver>, +) -> Result, CompileErrors> { let arena = Arena::new(); - let mut source = String::new(); - reader.read_to_string(&mut source).unwrap(); - let source = arena.alloc(source); - - let compiled = compile_program(source, location.clone(), resolve_option, &arena)?; + let compiled = compile_program(source, location.clone(), resolver, &arena)?; // check semantics let typed_ast = Checker::check(compiled).map_err(|errors| { - CompileErrors( - errors - .into_iter() - .map(|e| CompileErrorInner::from(e).with_context(&location)) - .collect(), - ) + CompileErrors(errors.into_iter().map(|e| CompileError::from(e)).collect()) })?; + let abi = typed_ast.abi(); + // analyse (unroll and constant propagation) let typed_ast = typed_ast.analyse(); @@ -165,26 +164,24 @@ pub fn compile>( // optimize let optimized_ir_prog = ir_prog.optimize(); - Ok(optimized_ir_prog) + // analyse (check for unused constraints) + let optimized_ir_prog = optimized_ir_prog.analyse(); + + Ok(CompilationArtifacts { + prog: optimized_ir_prog, + abi, + }) } -pub fn compile_program<'ast, T: Field, S: BufRead, E: Into>( +pub fn compile_program<'ast, T: Field, E: Into>( source: &'ast str, - location: Option, - resolve_option: Option>, + location: FilePath, + resolver: Option<&dyn Resolver>, arena: &'ast Arena, ) -> Result, CompileErrors> { let mut modules = HashMap::new(); - let main = compile_module( - &source, - location.clone(), - resolve_option, - &mut modules, - &arena, - )?; - - let location = location.unwrap_or("???".to_string()); + let main = compile_module(&source, location.clone(), resolver, &mut modules, &arena)?; modules.insert(location.clone(), main); @@ -194,21 +191,21 @@ pub fn compile_program<'ast, T: Field, S: BufRead, E: Into>( }) } -pub fn compile_module<'ast, T: Field, S: BufRead, E: Into>( +pub fn compile_module<'ast, T: Field, E: Into>( source: &'ast str, - location: Option, - resolve_option: Option>, + location: FilePath, + resolver: Option<&dyn Resolver>, modules: &mut HashMap>, arena: &'ast Arena, ) -> Result, CompileErrors> { let ast = pest::generate_ast(&source) - .map_err(|e| CompileErrors::from(CompileErrorInner::from(e).with_context(&location)))?; + .map_err(|e| CompileErrors::from(CompileErrorInner::from(e).in_file(&location)))?; let module_without_imports: Module = Module::from(ast); Importer::new().apply_imports( module_without_imports, location.clone(), - resolve_option, + resolver, modules, &arena, ) @@ -217,44 +214,38 @@ pub fn compile_module<'ast, T: Field, S: BufRead, E: Into>( #[cfg(test)] mod test { use super::*; - use std::io::{BufReader, Empty}; use zokrates_field::Bn128Field; #[test] fn no_resolver_with_imports() { - let mut r = BufReader::new( - r#" + let source = r#" import "./path/to/file" as foo def main() -> (field): return foo() "# - .as_bytes(), + .to_string(); + let res: Result, CompileErrors> = compile( + source, + "./path/to/file".into(), + None::<&dyn Resolver>, ); - let res: Result, CompileErrors> = compile( - &mut r, - Some(String::from("./path/to/file")), - None::, io::Error>>, - ); - - assert!(res - .unwrap_err() + assert!(res.unwrap_err().0[0] + .value() .to_string() .contains(&"Can't resolve import without a resolver")); } #[test] fn no_resolver_without_imports() { - let mut r = BufReader::new( - r#" + let source = r#" def main() -> (field): return 1 "# - .as_bytes(), - ); - let res: Result, CompileErrors> = compile( - &mut r, - Some(String::from("./path/to/file")), - None::, io::Error>>, + .to_string(); + let res: Result, CompileErrors> = compile( + source, + "./path/to/file".into(), + None::<&dyn Resolver>, ); assert!(res.is_ok()); } diff --git a/zokrates_core/src/embed.rs b/zokrates_core/src/embed.rs index dfb7a58e..6f63c666 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_core/src/embed.rs @@ -1,17 +1,17 @@ -use crate::helpers::{DirectiveStatement, Helper, RustHelper}; +use crate::solvers::Solver; use bellman::pairing::ff::ScalarEngine; use flat_absy::{ - FlatExpression, FlatExpressionList, FlatFunction, FlatParameter, FlatStatement, FlatVariable, + FlatDirective, FlatExpression, FlatExpressionList, FlatFunction, FlatParameter, FlatStatement, + FlatVariable, }; -use reduce::Reduce; use std::collections::HashMap; use typed_absy::types::{FunctionKey, Signature, Type}; use zokrates_embed::{generate_sha256_round_constraints, BellmanConstraint}; use zokrates_field::Field; -/// A low level function that contains non-deterministic introduction of variables. It is carried as is until +/// A low level function that contains non-deterministic introduction of variables. It is carried out as is until /// the flattening step when it can be inlined. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Hash)] pub enum FlatEmbed { Sha256Round, Unpack, @@ -56,32 +56,34 @@ impl FlatEmbed { } // util to convert a vector of `(variable_id, coefficient)` to a flat_expression +// we build a binary tree of additions by splitting the vector recursively fn flat_expression_from_vec( - v: Vec<(usize, <::BellmanEngine as ScalarEngine>::Fr)>, + v: &[(usize, <::BellmanEngine as ScalarEngine>::Fr)], ) -> FlatExpression { - match v - .into_iter() - .map(|(key, val)| { + match v.len() { + 0 => FlatExpression::Number(T::zero()), + 1 => { + let (key, val) = v[0].clone(); FlatExpression::Mult( box FlatExpression::Number(T::from_bellman(val)), box FlatExpression::Identifier(FlatVariable::new(key)), ) - }) - .reduce(|acc, e| FlatExpression::Add(box acc, box e)) - { - Some(e @ FlatExpression::Mult(..)) => { - FlatExpression::Add(box FlatExpression::Number(T::zero()), box e) - } // the R1CS serializer only recognizes Add - Some(e) => e, - None => FlatExpression::Number(T::zero()), + } + n => { + let (u, v) = v.split_at(n / 2); + FlatExpression::Add( + box flat_expression_from_vec(u), + box flat_expression_from_vec(v), + ) + } } } impl From> for FlatStatement { fn from(c: zokrates_embed::BellmanConstraint) -> FlatStatement { - let rhs_a = flat_expression_from_vec(c.a); - let rhs_b = flat_expression_from_vec(c.b); - let lhs = flat_expression_from_vec(c.c); + let rhs_a = flat_expression_from_vec(&c.a); + let rhs_b = flat_expression_from_vec(&c.b); + let lhs = flat_expression_from_vec(&c.c); FlatStatement::Condition(lhs, FlatExpression::Mult(box rhs_a, box rhs_b)) } @@ -123,15 +125,6 @@ pub fn sha256_round() -> FlatFunction { .into_iter() .map(|i| i + variable_count); - // define the signature of the resulting function - let signature = Signature { - inputs: vec![ - Type::array(Type::FieldElement, input_indices.len()), - Type::array(Type::FieldElement, current_hash_indices.len()), - ], - outputs: vec![Type::array(Type::FieldElement, output_indices.len())], - }; - // define parameters to the function based on the variables let arguments = input_argument_indices .clone() @@ -166,13 +159,13 @@ pub fn sha256_round() -> FlatFunction { .collect(); // insert a directive to set the witness based on the bellman gadget and inputs - let directive_statement = FlatStatement::Directive(DirectiveStatement { + let directive_statement = FlatStatement::Directive(FlatDirective { outputs: cs_indices.map(|i| FlatVariable::new(i)).collect(), inputs: input_argument_indices .chain(current_hash_argument_indices) .map(|i| FlatVariable::new(i).into()) .collect(), - helper: Helper::Rust(RustHelper::Sha256Round), + solver: Solver::Sha256Round, }); // insert a statement to return the subset of the witness @@ -190,7 +183,6 @@ pub fn sha256_round() -> FlatFunction { FlatFunction { arguments, statements, - signature, } } @@ -211,7 +203,7 @@ fn use_variable( /// * the return value of the `FlatFunction` is not deterministic: as we decompose over log_2(p) + 1 bits, some /// elements can have multiple representations: For example, `unpack(0)` is `[0, ..., 0]` but also `unpack(p)` pub fn unpack() -> FlatFunction { - let nbits = T::get_required_bits(); + let bit_width = T::get_required_bits(); let mut counter = 0; @@ -229,28 +221,23 @@ pub fn unpack() -> FlatFunction { format!("i0"), &mut counter, ))]; - let directive_outputs: Vec = (0..T::get_required_bits()) + let directive_outputs: Vec = (0..bit_width) .map(|index| use_variable(&mut layout, format!("o{}", index), &mut counter)) .collect(); - let helper = Helper::bits(); - - let signature = Signature { - inputs: vec![Type::FieldElement], - outputs: vec![Type::array(Type::FieldElement, nbits)], - }; + let solver = Solver::bits(bit_width); let outputs = directive_outputs .iter() .enumerate() - .filter(|(index, _)| *index >= T::get_required_bits() - nbits) + .filter(|(index, _)| *index >= T::get_required_bits() - bit_width) .map(|(_, o)| FlatExpression::Identifier(o.clone())) .collect(); - // o253, o252, ... o{253 - (nbits - 1)} are bits - let mut statements: Vec> = (0..nbits) + // o253, o252, ... o{253 - (bit_width - 1)} are bits + let mut statements: Vec> = (0..bit_width) .map(|index| { - let bit = FlatExpression::Identifier(FlatVariable::new(T::get_required_bits() - index)); + let bit = FlatExpression::Identifier(FlatVariable::new(bit_width - index)); FlatStatement::Condition( bit.clone(), FlatExpression::Mult(box bit.clone(), box bit.clone()), @@ -258,14 +245,14 @@ pub fn unpack() -> FlatFunction { }) .collect(); - // sum check: o253 + o252 * 2 + ... + o{253 - (nbits - 1)} * 2**(nbits - 1) + // sum check: o253 + o252 * 2 + ... + o{253 - (bit_width - 1)} * 2**(bit_width - 1) let mut lhs_sum = FlatExpression::Number(T::from(0)); - for i in 0..nbits { + for i in 0..bit_width { lhs_sum = FlatExpression::Add( box lhs_sum, box FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(T::get_required_bits() - i)), + box FlatExpression::Identifier(FlatVariable::new(bit_width - i)), box FlatExpression::Number(T::from(2).pow(i)), ), ); @@ -281,10 +268,10 @@ pub fn unpack() -> FlatFunction { statements.insert( 0, - FlatStatement::Directive(DirectiveStatement { + FlatStatement::Directive(FlatDirective { inputs: directive_inputs, outputs: directive_outputs, - helper: helper, + solver: solver, }), ); @@ -295,7 +282,6 @@ pub fn unpack() -> FlatFunction { FlatFunction { arguments, statements, - signature, } } @@ -322,11 +308,11 @@ mod tests { ); // 128 bit checks, 1 directive, 1 sum check, 1 return assert_eq!( unpack.statements[0], - FlatStatement::Directive(DirectiveStatement::new( + FlatStatement::Directive(FlatDirective::new( (0..Bn128Field::get_required_bits()) .map(|i| FlatVariable::new(i + 1)) .collect(), - Helper::bits(), + Solver::bits(Bn128Field::get_required_bits()), vec![FlatVariable::new(0)] )) ); @@ -349,17 +335,6 @@ mod tests { fn generate_sha256_constraints() { let compiled = sha256_round(); - // function should have a signature of 768 inputs and 256 outputs - assert_eq!( - compiled.signature, - Signature::new() - .inputs(vec![ - Type::array(Type::FieldElement, 512), - Type::array(Type::FieldElement, 256) - ]) - .outputs(vec![Type::array(Type::FieldElement, 256)]) - ); - // function should have 768 inputs assert_eq!(compiled.arguments.len(), 768,); @@ -419,12 +394,6 @@ mod tests { let prog = crate::ir::Prog { main: f, private: vec![true; 768], - signature: Signature::new() - .inputs(vec![ - Type::array(Type::FieldElement, 512), - Type::array(Type::FieldElement, 256), - ]) - .outputs(vec![Type::array(Type::FieldElement, 256)]), }; let input = (0..512) diff --git a/zokrates_core/src/flat_absy/mod.rs b/zokrates_core/src/flat_absy/mod.rs index 29edf731..d7695301 100644 --- a/zokrates_core/src/flat_absy/mod.rs +++ b/zokrates_core/src/flat_absy/mod.rs @@ -11,8 +11,7 @@ pub mod flat_variable; pub use self::flat_parameter::FlatParameter; pub use self::flat_variable::FlatVariable; -use crate::helpers::DirectiveStatement; -use crate::typed_absy::types::Signature; +use solvers::{Signed, Solver}; use std::collections::HashMap; use std::fmt; use zokrates_field::Field; @@ -41,8 +40,6 @@ pub struct FlatFunction { pub arguments: Vec, /// Vector of statements that are executed when running the function pub statements: Vec>, - /// Typed signature - pub signature: Signature, } impl fmt::Display for FlatFunction { @@ -68,9 +65,8 @@ impl fmt::Debug for FlatFunction { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, - "FlatFunction(arguments: {:?}, signature: {:?}):\n{}", + "FlatFunction(arguments: {:?}):\n{}", self.arguments, - self.signature, self.statements .iter() .map(|x| format!("\t{:?}", x)) @@ -95,7 +91,7 @@ pub enum FlatStatement { Return(FlatExpressionList), Condition(FlatExpression, FlatExpression), Definition(FlatVariable, FlatExpression), - Directive(DirectiveStatement), + Directive(FlatDirective), } impl fmt::Display for FlatStatement { @@ -149,7 +145,7 @@ impl FlatStatement { .map(|i| i.apply_substitution(substitution)) .collect(); - FlatStatement::Directive(DirectiveStatement { + FlatStatement::Directive(FlatDirective { outputs, inputs, ..d @@ -159,7 +155,51 @@ impl FlatStatement { } } -#[derive(Clone, PartialEq)] +impl FlatDirective { + pub fn new>>( + outputs: Vec, + solver: Solver, + inputs: Vec, + ) -> Self { + let (in_len, out_len) = solver.get_signature(); + assert_eq!(in_len, inputs.len()); + assert_eq!(out_len, outputs.len()); + FlatDirective { + solver, + inputs: inputs.into_iter().map(|i| i.into()).collect(), + outputs, + } + } +} + +impl fmt::Display for FlatDirective { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "# {} = {}({})", + self.outputs + .iter() + .map(|o| o.to_string()) + .collect::>() + .join(", "), + self.solver, + self.inputs + .iter() + .map(|i| i.to_string()) + .collect::>() + .join(", ") + ) + } +} + +#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] +pub struct FlatDirective { + pub inputs: Vec>, + pub outputs: Vec, + pub solver: Solver, +} + +#[derive(Clone, PartialEq, Serialize, Deserialize)] pub enum FlatExpression { Number(T), Identifier(FlatVariable), @@ -221,10 +261,10 @@ impl fmt::Display for FlatExpression { } } -impl fmt::Debug for FlatExpression { +impl fmt::Debug for FlatExpression { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - FlatExpression::Number(ref i) => write!(f, "Num({})", i), + FlatExpression::Number(ref i) => write!(f, "Num({:?})", i), FlatExpression::Identifier(ref var) => write!(f, "Ide({})", var), FlatExpression::Add(ref lhs, ref rhs) => write!(f, "Add({:?}, {:?})", lhs, rhs), FlatExpression::Sub(ref lhs, ref rhs) => write!(f, "Sub({:?}, {:?})", lhs, rhs), diff --git a/zokrates_core/src/flatten/mod.rs b/zokrates_core/src/flatten/mod.rs index f741b529..0350d3e2 100644 --- a/zokrates_core/src/flatten/mod.rs +++ b/zokrates_core/src/flatten/mod.rs @@ -1,4 +1,4 @@ -//! Module containing the `Flattener` to process a program that it is R1CS-able. +//! Module containing the `Flattener` to process a program that is R1CS-able. //! //! @file flatten.rs //! @author Dennis Kuhnert @@ -6,7 +6,7 @@ //! @date 2017 use crate::flat_absy::*; -use crate::helpers::{DirectiveStatement, Helper, RustHelper}; +use crate::solvers::Solver; use crate::typed_absy::types::{FunctionIdentifier, FunctionKey, MemberId, Signature, Type}; use crate::typed_absy::*; use std::collections::HashMap; @@ -122,7 +122,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { /// /// # Arguments /// - /// * `symbols` - Available functions in in this context + /// * `symbols` - Available functions in this context /// * `statements_flattened` - Vector where new flattened statements can be added. /// * `condition` - the condition as a `BooleanExpression`. /// * `consequence` - the consequence of type U. @@ -218,9 +218,9 @@ impl<'ast, T: Field> Flattener<'ast, T> { let members = s.ty().clone(); let expected_output_size = members .iter() - .find(|(id, _)| *id == member_id) + .find(|member| *member.id == member_id) .unwrap() - .1 + .ty .get_primitive_count(); let res = @@ -231,8 +231,8 @@ impl<'ast, T: Field> Flattener<'ast, T> { values .into_iter() .zip(members.into_iter()) - .filter(|(_, (id, _))| *id == member_id) - .flat_map(|(v, (_, t))| match t { + .filter(|(_, member)| *member.id == member_id) + .flat_map(|(v, member)| match *member.ty { Type::FieldElement => FieldElementExpression::try_from(v) .unwrap() .flatten(self, symbols, statements_flattened), @@ -259,16 +259,16 @@ impl<'ast, T: Field> Flattener<'ast, T> { // the struct is encoded as a sequence, so we need to identify the offset at which this member starts let offset = members .iter() - .take_while(|(id, _)| *id != member_id) - .map(|(_, ty)| ty.get_primitive_count()) + .take_while(|member| *member.id != member_id) + .map(|member| member.ty.get_primitive_count()) .sum(); // we also need the size of this member let size = members .iter() - .find(|(id, _)| *id == member_id) + .find(|member| *member.id == member_id) .unwrap() - .1 + .ty .get_primitive_count(); self.layout.get(&id).unwrap()[offset..(offset + size)] .into_iter() @@ -278,16 +278,16 @@ impl<'ast, T: Field> Flattener<'ast, T> { StructExpressionInner::Select(box array, box index) => { let offset = members .iter() - .take_while(|(id, _)| *id != member_id) - .map(|(_, ty)| ty.get_primitive_count()) + .take_while(|member| *member.id != member_id) + .map(|member| member.ty.get_primitive_count()) .sum(); // we also need the size of this member let size = members .iter() - .find(|(id, _)| *id == member_id) + .find(|member| *member.id == member_id) .unwrap() - .1 + .ty .get_primitive_count(); self.flatten_select_expression::>( @@ -302,12 +302,12 @@ impl<'ast, T: Field> Flattener<'ast, T> { StructExpressionInner::IfElse(box condition, box consequence, box alternative) => { // if the struct is `(if c then a else b)`, we want to access `(if c then a else b).member` // we reduce to `if c then a.member else b.member` - let ty = members + let ty = *members .clone() .into_iter() - .find(|(id, _)| *id == member_id) + .find(|member| *member.id == member_id) .unwrap() - .1; + .ty; match ty { Type::FieldElement => self.flatten_if_else_expression( @@ -345,16 +345,16 @@ impl<'ast, T: Field> Flattener<'ast, T> { let offset = members .iter() - .take_while(|(id, _)| *id != member_id) - .map(|(_, ty)| ty.get_primitive_count()) + .take_while(|member| *member.id != member_id) + .map(|member| member.ty.get_primitive_count()) .sum(); // we also need the size of this member let size = members .iter() - .find(|(id, _)| *id == member_id) + .find(|member| *member.id == member_id) .unwrap() - .1 + .ty .get_primitive_count(); e[offset..(offset + size)].into() @@ -466,7 +466,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { e => { // we have array[e] with e an arbitrary expression // first we check that e is in 0..array.len(), so we check that sum(if e == i then 1 else 0) == 1 - // here depending on the size, we could use a proper range check based on bits + // here, depending on the size, we could use a proper range check based on bits let range_check = (0..size) .map(|i| { FieldElementExpression::IfElse( @@ -546,7 +546,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { /// /// # Arguments /// - /// * `symbols` - Available functions in in this context + /// * `symbols` - Available functions in this context /// * `statements_flattened` - Vector where new flattened statements can be added. /// * `expression` - `BooleanExpression` that will be flattened. /// @@ -566,8 +566,9 @@ impl<'ast, T: Field> Flattener<'ast, T> { FlatExpression::Identifier(self.layout.get(&x).unwrap().clone()[0]) } BooleanExpression::Lt(box lhs, box rhs) => { - // Get the bitwidth to know the size of the binary decompsitions for this Field - let bitwidth = T::get_required_bits(); + // Get the bit width to know the size of the binary decompositions for this Field + let bit_width = T::get_required_bits(); + let safe_width = bit_width - 2; // making sure we don't overflow, assert here? // We know from semantic checking that lhs and rhs have the same type // What the expression will flatten to depends on that type @@ -581,28 +582,28 @@ impl<'ast, T: Field> Flattener<'ast, T> { let lhs_id = self.use_sym(); statements_flattened.push(FlatStatement::Definition(lhs_id, lhs_flattened)); - // check that lhs and rhs are within the right range, ie, their higher two bits are zero. We use big-endian so they are at positions 0 and 1 + // check that lhs and rhs are within the right range, i.e., their higher two bits are zero. We use big-endian so they are at positions 0 and 1 // lhs { // define variables for the bits let lhs_bits_be: Vec = - (0..bitwidth).map(|_| self.use_sym()).collect(); + (0..safe_width).map(|_| self.use_sym()).collect(); // add a directive to get the bits - statements_flattened.push(FlatStatement::Directive(DirectiveStatement::new( + statements_flattened.push(FlatStatement::Directive(FlatDirective::new( lhs_bits_be.clone(), - Helper::bits(), + Solver::bits(safe_width), vec![lhs_id], ))); // bitness checks - for i in 0..bitwidth - 2 { + for i in 0..safe_width { statements_flattened.push(FlatStatement::Condition( - FlatExpression::Identifier(lhs_bits_be[i + 2]), + FlatExpression::Identifier(lhs_bits_be[i]), FlatExpression::Mult( - box FlatExpression::Identifier(lhs_bits_be[i + 2]), - box FlatExpression::Identifier(lhs_bits_be[i + 2]), + box FlatExpression::Identifier(lhs_bits_be[i]), + box FlatExpression::Identifier(lhs_bits_be[i]), ), )); } @@ -610,12 +611,12 @@ impl<'ast, T: Field> Flattener<'ast, T> { // bit decomposition check let mut lhs_sum = FlatExpression::Number(T::from(0)); - for i in 0..bitwidth - 2 { + for i in 0..safe_width { lhs_sum = FlatExpression::Add( box lhs_sum, box FlatExpression::Mult( - box FlatExpression::Identifier(lhs_bits_be[i + 2]), - box FlatExpression::Number(T::from(2).pow(bitwidth - 2 - i - 1)), + box FlatExpression::Identifier(lhs_bits_be[i]), + box FlatExpression::Number(T::from(2).pow(safe_width - i - 1)), ), ); } @@ -634,22 +635,22 @@ impl<'ast, T: Field> Flattener<'ast, T> { { // define variables for the bits let rhs_bits_be: Vec = - (0..bitwidth).map(|_| self.use_sym()).collect(); + (0..safe_width).map(|_| self.use_sym()).collect(); // add a directive to get the bits - statements_flattened.push(FlatStatement::Directive(DirectiveStatement::new( + statements_flattened.push(FlatStatement::Directive(FlatDirective::new( rhs_bits_be.clone(), - Helper::bits(), + Solver::bits(safe_width), vec![rhs_id], ))); // bitness checks - for i in 0..bitwidth - 2 { + for i in 0..safe_width { statements_flattened.push(FlatStatement::Condition( - FlatExpression::Identifier(rhs_bits_be[i + 2]), + FlatExpression::Identifier(rhs_bits_be[i]), FlatExpression::Mult( - box FlatExpression::Identifier(rhs_bits_be[i + 2]), - box FlatExpression::Identifier(rhs_bits_be[i + 2]), + box FlatExpression::Identifier(rhs_bits_be[i]), + box FlatExpression::Identifier(rhs_bits_be[i]), ), )); } @@ -657,12 +658,12 @@ impl<'ast, T: Field> Flattener<'ast, T> { // bit decomposition check let mut rhs_sum = FlatExpression::Number(T::from(0)); - for i in 0..bitwidth - 2 { + for i in 0..safe_width { rhs_sum = FlatExpression::Add( box rhs_sum, box FlatExpression::Mult( - box FlatExpression::Identifier(rhs_bits_be[i + 2]), - box FlatExpression::Number(T::from(2).pow(bitwidth - 2 - i - 1)), + box FlatExpression::Identifier(rhs_bits_be[i]), + box FlatExpression::Number(T::from(2).pow(safe_width - i - 1)), ), ); } @@ -687,17 +688,17 @@ impl<'ast, T: Field> Flattener<'ast, T> { // define variables for the bits let sub_bits_be: Vec = - (0..bitwidth).map(|_| self.use_sym()).collect(); + (0..bit_width).map(|_| self.use_sym()).collect(); // add a directive to get the bits - statements_flattened.push(FlatStatement::Directive(DirectiveStatement::new( + statements_flattened.push(FlatStatement::Directive(FlatDirective::new( sub_bits_be.clone(), - Helper::bits(), + Solver::bits(bit_width), vec![subtraction_result.clone()], ))); // bitness checks - for i in 0..bitwidth { + for i in 0..bit_width { statements_flattened.push(FlatStatement::Condition( FlatExpression::Identifier(sub_bits_be[i]), FlatExpression::Mult( @@ -710,19 +711,19 @@ impl<'ast, T: Field> Flattener<'ast, T> { // sum(sym_b{i} * 2**i) let mut expr = FlatExpression::Number(T::from(0)); - for i in 0..bitwidth { + for i in 0..bit_width { expr = FlatExpression::Add( box expr, box FlatExpression::Mult( box FlatExpression::Identifier(sub_bits_be[i]), - box FlatExpression::Number(T::from(2).pow(bitwidth - i - 1)), + box FlatExpression::Number(T::from(2).pow(bit_width - i - 1)), ), ); } statements_flattened.push(FlatStatement::Condition(subtraction_result, expr)); - FlatExpression::Identifier(sub_bits_be[bitwidth - 1]) + FlatExpression::Identifier(sub_bits_be[bit_width - 1]) } BooleanExpression::BoolEq(box lhs, box rhs) => { // lhs and rhs are booleans, they flatten to 0 or 1 @@ -776,9 +777,9 @@ impl<'ast, T: Field> Flattener<'ast, T> { FieldElementExpression::Sub(box lhs, box rhs), ); - statements_flattened.push(FlatStatement::Directive(DirectiveStatement::new( + statements_flattened.push(FlatStatement::Directive(FlatDirective::new( vec![name_y, name_m], - Helper::Rust(RustHelper::ConditionEq), + Solver::ConditionEq, vec![x.clone()], ))); statements_flattened.push(FlatStatement::Condition( @@ -856,6 +857,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { true => T::from(1), false => T::from(0), }), + BooleanExpression::FunctionCall(..) => unreachable!(), BooleanExpression::IfElse(box condition, box consequence, box alternative) => self .flatten_if_else_expression( symbols, @@ -923,8 +925,8 @@ impl<'ast, T: Field> Flattener<'ast, T> { replacement_map.insert(formal_argument.id, new_var); } - // Ensure Renaming and correct returns: - // add all flattened statements, adapt return statement + // Ensure renaming and correct returns: + // add all flattened statements, adapt return statements let (mut return_statements, statements): (Vec<_>, Vec<_>) = funct.statements.into_iter().partition(|s| match s { @@ -963,9 +965,9 @@ impl<'ast, T: Field> Flattener<'ast, T> { .into_iter() .map(|i| i.apply_substitution(&replacement_map)) .collect(); - FlatStatement::Directive(DirectiveStatement { + FlatStatement::Directive(FlatDirective { outputs: new_outputs, - helper: d.helper, + solver: d.solver, inputs: new_inputs, }) } @@ -990,7 +992,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { /// /// # Arguments /// - /// * `symbols` - Available functions in in this context + /// * `symbols` - Available functions in this context /// * `statements_flattened` - Vector where new flattened statements can be added. /// * `expr` - `TypedExpression` that will be flattened. fn flatten_expression( @@ -1039,7 +1041,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { /// /// # Arguments /// - /// * `symbols` - Available functions in in this context + /// * `symbols` - Available functions in this context /// * `statements_flattened` - Vector where new flattened statements can be added. /// * `expr` - `FieldElementExpression` that will be flattened. fn flatten_field_expression( @@ -1138,9 +1140,9 @@ impl<'ast, T: Field> Flattener<'ast, T> { let inverse = self.use_sym(); // # invb = 1/b - statements_flattened.push(FlatStatement::Directive(DirectiveStatement::new( + statements_flattened.push(FlatStatement::Directive(FlatDirective::new( vec![invb], - Helper::Rust(RustHelper::Div), + Solver::Div, vec![FlatExpression::Number(T::one()), new_right.clone()], ))); @@ -1151,9 +1153,9 @@ impl<'ast, T: Field> Flattener<'ast, T> { )); // # c = a/b - statements_flattened.push(FlatStatement::Directive(DirectiveStatement::new( + statements_flattened.push(FlatStatement::Directive(FlatDirective::new( vec![inverse], - Helper::Rust(RustHelper::Div), + Solver::Div, vec![new_left.clone(), new_right.clone()], ))); @@ -1226,7 +1228,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { // construct the result iterating through the bits, multiplying by the associated power iff the bit is true ebits_le.into_iter().zip(powers).fold( - FlatExpression::Number(T::from(1)), // initialise the result at 1. If we have no bits to iterate through, we're computing x**0 == 1 + FlatExpression::Number(T::from(1)), // initialise the result at 1. If we have no bits to itegrate through, we're computing x**0 == 1 |acc, (bit, power)| match bit { true => { // update the result by introducing a new variable @@ -1282,7 +1284,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { /// /// # Arguments /// - /// * `symbols` - Available functions in in this context + /// * `symbols` - Available functions in this context /// * `statements_flattened` - Vector where new flattened statements can be added. /// * `expr` - `StructExpression` that will be flattened. fn flatten_struct_expression( @@ -1320,29 +1322,29 @@ impl<'ast, T: Field> Flattener<'ast, T> { StructExpressionInner::IfElse(box condition, box consequence, box alternative) => { members .into_iter() - .flat_map(|(id, ty)| match ty { + .flat_map(|member| match ty { Type::FieldElement => FieldElementExpression::if_else( condition.clone(), - FieldElementExpression::member(consequence.clone(), id.clone()), - FieldElementExpression::member(alternative.clone(), id.clone()), + FieldElementExpression::member(consequence.clone(), member.id.clone()), + FieldElementExpression::member(alternative.clone(), member.id.clone()), ) .flatten(self, symbols, statements_flattened), Type::Boolean => BooleanExpression::if_else( condition.clone(), - BooleanExpression::member(consequence.clone(), id.clone()), - BooleanExpression::member(alternative.clone(), id.clone()), + BooleanExpression::member(consequence.clone(), member.id.clone()), + BooleanExpression::member(alternative.clone(), member.id.clone()), ) .flatten(self, symbols, statements_flattened), Type::Struct(..) => StructExpression::if_else( condition.clone(), - StructExpression::member(consequence.clone(), id.clone()), - StructExpression::member(alternative.clone(), id.clone()), + StructExpression::member(consequence.clone(), member.id.clone()), + StructExpression::member(alternative.clone(), member.id.clone()), ) .flatten(self, symbols, statements_flattened), Type::Array(..) => ArrayExpression::if_else( condition.clone(), - ArrayExpression::member(consequence.clone(), id.clone()), - ArrayExpression::member(alternative.clone(), id.clone()), + ArrayExpression::member(consequence.clone(), member.id.clone()), + ArrayExpression::member(alternative.clone(), member.id.clone()), ) .flatten(self, symbols, statements_flattened), }) @@ -1368,7 +1370,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { /// /// # Arguments /// - /// * `symbols` - Available functions in in this context + /// * `symbols` - Available functions in this context /// * `statements_flattened` - Vector where new flattened statements can be added. /// * `expr` - `ArrayExpression` that will be flattened. /// # Remarks @@ -1447,7 +1449,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { /// /// # Arguments /// - /// * `symbols` - Available functions in in this context + /// * `symbols` - Available functions in this context /// * `statements_flattened` - Vector where new flattened statements can be added. /// * `stat` - `TypedStatement` that will be flattened. fn flatten_statement( @@ -1564,7 +1566,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { /// /// # Arguments /// - /// * `symbols` - Available functions in in this context + /// * `symbols` - Available functions in this context /// * `funct` - `TypedFunction` that will be flattened fn flatten_function( &mut self, @@ -1591,7 +1593,6 @@ impl<'ast, T: Field> Flattener<'ast, T> { FlatFunction { arguments: arguments_flattened, statements: statements_flattened, - signature: funct.signature, } } @@ -1735,7 +1736,6 @@ mod tests { expressions: vec![FlatExpression::Identifier(FlatVariable::new(1))], }), ], - signature: Signature::new().outputs(vec![Type::FieldElement]), }; let flattened = flattener.flatten_function(&mut HashMap::new(), function); @@ -1802,7 +1802,6 @@ mod tests { expressions: vec![FlatExpression::Identifier(FlatVariable::new(2))], }), ], - signature: Signature::new().outputs(vec![Type::FieldElement]), }; let flattened = flattener.flatten_function(&mut HashMap::new(), function); @@ -1922,7 +1921,6 @@ mod tests { expressions: vec![FlatExpression::Identifier(FlatVariable::new(7))], }), ], - signature: Signature::new().outputs(vec![Type::FieldElement]), }; let flattened = flattener.flatten_function(&mut HashMap::new(), function); @@ -2041,9 +2039,9 @@ mod tests { FlatStatement::Definition(five, FlatExpression::Number(Bn128Field::from(5))), FlatStatement::Definition(b0, b.into()), // check div by 0 - FlatStatement::Directive(DirectiveStatement::new( + FlatStatement::Directive(FlatDirective::new( vec![invb0], - Helper::Rust(RustHelper::Div), + Solver::Div, vec![FlatExpression::Number(Bn128Field::from(1)), b0.into()] )), FlatStatement::Condition( @@ -2051,9 +2049,9 @@ mod tests { FlatExpression::Mult(box invb0.into(), box b0.into()), ), // execute div - FlatStatement::Directive(DirectiveStatement::new( + FlatStatement::Directive(FlatDirective::new( vec![sym_0], - Helper::Rust(RustHelper::Div), + Solver::Div, vec![five, b0] )), FlatStatement::Condition( @@ -2064,9 +2062,9 @@ mod tests { FlatStatement::Definition(sym_1, sym_0.into()), FlatStatement::Definition(b1, b.into()), // check div by 0 - FlatStatement::Directive(DirectiveStatement::new( + FlatStatement::Directive(FlatDirective::new( vec![invb1], - Helper::Rust(RustHelper::Div), + Solver::Div, vec![FlatExpression::Number(Bn128Field::from(1)), b1.into()] )), FlatStatement::Condition( @@ -2074,9 +2072,9 @@ mod tests { FlatExpression::Mult(box invb1.into(), box b1.into()), ), // execute div - FlatStatement::Directive(DirectiveStatement::new( + FlatStatement::Directive(FlatDirective::new( vec![sym_2], - Helper::Rust(RustHelper::Div), + Solver::Div, vec![sym_1, b1] )), FlatStatement::Condition( diff --git a/zokrates_core/src/imports.rs b/zokrates_core/src/imports.rs index 03c401a9..e895d77d 100644 --- a/zokrates_core/src/imports.rs +++ b/zokrates_core/src/imports.rs @@ -6,14 +6,16 @@ use crate::absy::*; use crate::compile::compile_module; -use crate::compile::{CompileErrorInner, CompileErrors, Resolve}; +use crate::compile::{CompileErrorInner, CompileErrors}; use crate::embed::FlatEmbed; use crate::parser::Position; use std::collections::HashMap; use std::fmt; use std::io; -use std::io::BufRead; +use std::path::{Path, PathBuf}; + use typed_arena::Arena; +use zokrates_common::Resolver; use zokrates_field::Field; #[derive(PartialEq, Debug)] @@ -54,9 +56,11 @@ impl From for Error { } } +type ImportPath<'ast> = &'ast Path; + #[derive(PartialEq, Clone)] pub struct Import<'ast> { - source: Identifier<'ast>, + source: ImportPath<'ast>, symbol: Option>, alias: Option>, } @@ -64,7 +68,7 @@ pub struct Import<'ast> { pub type ImportNode<'ast> = Node>; impl<'ast> Import<'ast> { - pub fn new(symbol: Option>, source: Identifier<'ast>) -> Import<'ast> { + pub fn new(symbol: Option>, source: ImportPath<'ast>) -> Import<'ast> { Import { symbol, source, @@ -78,7 +82,7 @@ impl<'ast> Import<'ast> { pub fn new_with_alias( symbol: Option>, - source: Identifier<'ast>, + source: ImportPath<'ast>, alias: Identifier<'ast>, ) -> Import<'ast> { Import { @@ -93,7 +97,7 @@ impl<'ast> Import<'ast> { self } - pub fn get_source(&self) -> &Identifier<'ast> { + pub fn get_source(&self) -> &ImportPath<'ast> { &self.source } } @@ -101,8 +105,8 @@ impl<'ast> Import<'ast> { impl<'ast> fmt::Display for Import<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.alias { - Some(ref alias) => write!(f, "import {} as {}", self.source, alias), - None => write!(f, "import {}", self.source), + Some(ref alias) => write!(f, "import {} as {}", self.source.display(), alias), + None => write!(f, "import {}", self.source.display()), } } } @@ -110,8 +114,13 @@ impl<'ast> fmt::Display for Import<'ast> { impl<'ast> fmt::Debug for Import<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.alias { - Some(ref alias) => write!(f, "import(source: {}, alias: {})", self.source, alias), - None => write!(f, "import(source: {})", self.source), + Some(ref alias) => write!( + f, + "import(source: {}, alias: {})", + self.source.display(), + alias + ), + None => write!(f, "import(source: {})", self.source.display()), } } } @@ -123,11 +132,11 @@ impl Importer { Importer {} } - pub fn apply_imports<'ast, T: Field, S: BufRead, E: Into>( + pub fn apply_imports<'ast, T: Field, E: Into>( &self, destination: Module<'ast, T>, - location: Option, - resolve_option: Option>, + location: PathBuf, + resolver: Option<&dyn Resolver>, modules: &mut HashMap>, arena: &'ast Arena, ) -> Result, CompileErrors> { @@ -139,7 +148,7 @@ impl Importer { let alias = import.alias; // handle the case of special bellman and packing imports if import.source.starts_with("EMBED") { - match import.source.as_ref() { + match import.source.to_str().unwrap() { "EMBED/sha256round" => { let alias = alias.unwrap_or("sha256round"); @@ -166,31 +175,48 @@ impl Importer { return Err(CompileErrorInner::ImportError( Error::new(format!("Embed {} not found. Options are \"EMBED/sha256round\", \"EMBED/unpack\"", s)).with_pos(Some(pos)), ) - .with_context(&location) + .in_file(&location) .into()); } } } else { // to resolve imports, we need a resolver - match resolve_option { - Some(resolve) => match resolve(location.clone(), &import.source) { - Ok((mut reader, location, alias)) => { - let mut source = String::new(); - reader.read_to_string(&mut source).unwrap(); + match resolver { + Some(res) => match res.resolve(location.clone(), import.source.to_path_buf()) { + Ok((source, new_location)) => { + // generate an alias from the imported path if none was given explicitely + let alias = import.alias.unwrap_or( + std::path::Path::new(import.source) + .file_stem() + .ok_or(CompileErrors::from( + CompileErrorInner::ImportError(Error::new(format!( + "Could not determine alias for import {}", + import.source.display() + ))) + .in_file(&location), + ))? + .to_str() + .unwrap(), + ); - let source = arena.alloc(source); + match modules.get(&new_location) { + Some(_) => {} + None => { + let source = arena.alloc(source); - let compiled = compile_module( - source, - Some(location), - resolve_option, - modules, - &arena, - ) - .map_err(|e| e.with_context(Some(import.source.to_string())))?; - let alias = import.alias.clone().unwrap_or(alias); + let compiled = compile_module( + source, + new_location.clone(), + resolver, + modules, + &arena, + )?; - modules.insert(import.source.to_string(), compiled); + assert!(modules + .insert(new_location.clone(), compiled) + .is_none()); + } + }; symbols.push( SymbolDeclaration { @@ -198,7 +224,7 @@ impl Importer { symbol: Symbol::There( SymbolImport::with_id_in_module( import.symbol.unwrap_or("main"), - import.source.clone(), + new_location.display().to_string(), ) .start_end(pos.0, pos.1), ), @@ -210,7 +236,7 @@ impl Importer { return Err(CompileErrorInner::ImportError( err.into().with_pos(Some(pos)), ) - .with_context(&location) + .in_file(&location) .into()); } }, @@ -218,7 +244,7 @@ impl Importer { return Err(CompileErrorInner::from(Error::new( "Can't resolve import without a resolver", )) - .with_context(&location) + .in_file(&location) .into()); } } @@ -243,10 +269,10 @@ mod tests { #[test] fn create_with_no_alias() { assert_eq!( - Import::new(None, "./foo/bar/baz.zok"), + Import::new(None, Path::new("./foo/bar/baz.zok")), Import { symbol: None, - source: "./foo/bar/baz.zok", + source: Path::new("./foo/bar/baz.zok"), alias: None, } ); @@ -255,10 +281,10 @@ mod tests { #[test] fn create_with_alias() { assert_eq!( - Import::new_with_alias(None, "./foo/bar/baz.zok", &"myalias"), + Import::new_with_alias(None, Path::new("./foo/bar/baz.zok"), &"myalias"), Import { symbol: None, - source: "./foo/bar/baz.zok", + source: Path::new("./foo/bar/baz.zok"), alias: Some("myalias"), } ); diff --git a/zokrates_core/src/ir/from_flat.rs b/zokrates_core/src/ir/from_flat.rs index 28e115cf..96519a49 100644 --- a/zokrates_core/src/ir/from_flat.rs +++ b/zokrates_core/src/ir/from_flat.rs @@ -1,5 +1,6 @@ -use crate::flat_absy::{FlatExpression, FlatFunction, FlatProg, FlatStatement, FlatVariable}; -use crate::helpers; +use crate::flat_absy::{ + FlatDirective, FlatExpression, FlatFunction, FlatProg, FlatStatement, FlatVariable, +}; use crate::ir::{Directive, Function, LinComb, Prog, QuadComb, Statement}; use zokrates_field::Field; @@ -65,19 +66,12 @@ impl From> for Prog { // get the main function let main = flat_prog.main; - // get the signature to keep high level information in the low level representation - let signature = main.signature.clone(); - - // get the interface of the program, ie which inputs are private and public + // get the interface of the program, i.e. which inputs are private and public let private = main.arguments.iter().map(|p| p.private).collect(); let main = main.into(); - Prog { - private, - main, - signature, - } + Prog { private, main } } } @@ -125,11 +119,11 @@ impl From> for Statement { } } -impl From> for Directive { - fn from(ds: helpers::DirectiveStatement) -> Directive { +impl From> for Directive { + fn from(ds: FlatDirective) -> Directive { Directive { inputs: ds.inputs.into_iter().map(|i| i.into()).collect(), - helper: ds.helper, + solver: ds.solver, outputs: ds.outputs, } } diff --git a/zokrates_core/src/ir/interpreter.rs b/zokrates_core/src/ir/interpreter.rs index f0688c59..54981b5c 100644 --- a/zokrates_core/src/ir/interpreter.rs +++ b/zokrates_core/src/ir/interpreter.rs @@ -1,6 +1,6 @@ use crate::flat_absy::flat_variable::FlatVariable; -use crate::helpers::Executable; use crate::ir::{LinComb, Prog, QuadComb, Statement, Witness}; +use crate::solvers::Executable; use std::collections::BTreeMap; use std::fmt; use zokrates_field::Field; @@ -41,7 +41,7 @@ impl Prog { .iter() .map(|i| i.evaluate(&witness).unwrap()) .collect(); - match d.helper.execute(&input_values) { + match d.solver.execute(&input_values) { Ok(res) => { for (i, o) in d.outputs.iter().enumerate() { witness.insert(o.clone(), res[i].clone()); diff --git a/zokrates_core/src/ir/mod.rs b/zokrates_core/src/ir/mod.rs index 9a27c7b1..b0365a05 100644 --- a/zokrates_core/src/ir/mod.rs +++ b/zokrates_core/src/ir/mod.rs @@ -1,8 +1,7 @@ use crate::flat_absy::flat_parameter::FlatParameter; use crate::flat_absy::FlatVariable; -use crate::helpers::Helper; +use crate::solvers::Solver; use std::fmt; -use typed_absy::types::signature::Signature; use zokrates_field::Field; mod expression; @@ -53,14 +52,14 @@ impl Statement { pub struct Directive { pub inputs: Vec>, pub outputs: Vec, - pub helper: Helper, + pub solver: Solver, } impl PartialEq for Directive { fn eq(&self, other: &Self) -> bool { self.inputs.eq(&other.inputs) && self.outputs.eq(&other.outputs) - && self.helper.eq(&other.helper) + && self.solver.eq(&other.solver) } } @@ -76,7 +75,7 @@ impl fmt::Display for Directive { .map(|o| format!("{}", o)) .collect::>() .join(", "), - self.helper, + self.solver, self.inputs .iter() .map(|i| format!("{}", i)) @@ -140,16 +139,13 @@ impl fmt::Display for Function { #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Prog { - pub signature: Signature, pub main: Function, pub private: Vec, } impl PartialEq for Prog { fn eq(&self, other: &Self) -> bool { - self.signature.eq(&other.signature) - && self.main.eq(&other.main) - && self.private.eq(&other.private) + self.main.eq(&other.main) && self.private.eq(&other.private) } } diff --git a/zokrates_core/src/ir/serialize.rs b/zokrates_core/src/ir/serialize.rs index 571a5230..78134d5a 100644 --- a/zokrates_core/src/ir/serialize.rs +++ b/zokrates_core/src/ir/serialize.rs @@ -61,7 +61,6 @@ mod tests { use super::*; use ir; use std::io::{Cursor, Seek, SeekFrom}; - use typed_absy::types::Signature; use zokrates_field::{Bls12Field, Bn128Field}; #[test] @@ -74,7 +73,6 @@ mod tests { statements: vec![], }, private: vec![], - signature: Signature::new(), }; let mut buffer = Cursor::new(vec![]); @@ -96,7 +94,6 @@ mod tests { statements: vec![], }, private: vec![], - signature: Signature::new(), }; let mut buffer = Cursor::new(vec![]); diff --git a/zokrates_core/src/lib.rs b/zokrates_core/src/lib.rs index a387e875..323c96ec 100644 --- a/zokrates_core/src/lib.rs +++ b/zokrates_core/src/lib.rs @@ -13,26 +13,19 @@ extern crate bincode; extern crate ff_ce as ff; extern crate lazy_static; extern crate pairing_ce as pairing; -#[cfg(feature = "wasm")] -extern crate parity_wasm; extern crate regex; -#[cfg(feature = "wasm")] -extern crate rustc_hex; -#[cfg(feature = "wasm")] -extern crate serde_bytes; -#[cfg(feature = "wasm")] -extern crate wasmi; +extern crate zokrates_common; extern crate zokrates_embed; extern crate zokrates_field; extern crate zokrates_pest_ast; mod embed; mod flatten; -mod helpers; -mod imports; +pub mod imports; mod optimizer; mod parser; mod semantics; +mod solvers; mod static_analysis; pub mod absy; diff --git a/zokrates_core/src/optimizer/duplicate.rs b/zokrates_core/src/optimizer/duplicate.rs index 760f5af2..763e9ac4 100644 --- a/zokrates_core/src/optimizer/duplicate.rs +++ b/zokrates_core/src/optimizer/duplicate.rs @@ -49,7 +49,6 @@ impl Folder for DuplicateOptimizer { mod tests { use super::*; use flat_absy::FlatVariable; - use typed_absy::types::Signature; use zokrates_field::Bn128Field; #[test] @@ -77,7 +76,6 @@ mod tests { returns: vec![], arguments: vec![], }, - signature: Signature::new(), }; let expected = p.clone(); @@ -115,7 +113,6 @@ mod tests { returns: vec![], arguments: vec![], }, - signature: Signature::new(), }; let expected = Prog { @@ -135,7 +132,6 @@ mod tests { returns: vec![], arguments: vec![], }, - signature: Signature::new(), }; assert_eq!(DuplicateOptimizer::optimize(p), expected); diff --git a/zokrates_core/src/optimizer/redefinition.rs b/zokrates_core/src/optimizer/redefinition.rs index 29bdcd65..e550a91d 100644 --- a/zokrates_core/src/optimizer/redefinition.rs +++ b/zokrates_core/src/optimizer/redefinition.rs @@ -8,6 +8,30 @@ // c := a // ``` +// # Redefinition rules + +// ## Defined variables + +// We say that a variable `v` is defined in constraint `c_n` or an ir program if there exists a constraint `c_i` with `i < n` of the form: +// ``` +// q == k * v +// where: +// - q is quadratic and does not contain `v` +// - k is a scalar +// ``` + +// ## Optimization rules + +// We maintain, `s` a set of substitutions as a mapping of `(variable => linear_combination)`. It starts empty. + +// - input variables are inserted in the substitution as `(v, [(1, v)])` +// - the `~one` variable is inserted as `(~one, [(1, ~one)])` +// - For each directive, for each variable `v` introduced, insert `(v, [(1, v)])` +// - For each constraint `c`, we replace all variables by their value in `s` if any, otherwise leave them unchanged. Let's call `c_0` the resulting constraint. We either return `c_0` or nothing based on the form of `c_0`: +// - `~one * lin == k * v if v isn't defined`: insert `(v, lin / k)` and return nothing +// - `q == k * v if v isn't defined`: insert `(v, [(1, v)])` and return `c_0` +// - otherwise return `c_0` + use crate::flat_absy::flat_variable::FlatVariable; use crate::ir::folder::{fold_function, Folder}; use crate::ir::LinComb; @@ -36,36 +60,40 @@ impl RedefinitionOptimizer { impl Folder for RedefinitionOptimizer { fn fold_statement(&mut self, s: Statement) -> Vec> { match s { - // Detect constraints of the form `lincomb * ~ONE == x` where x is not in the map yet Statement::Constraint(quad, lin) => { let quad = self.fold_quadratic_combination(quad); let lin = self.fold_linear_combination(lin); - let to_insert = match quad.try_linear() { - // left side must be linear - Some(l) => match lin.try_summand() { - // right side must be a single variable - Some((variable, coefficient)) => { - match variable == FlatVariable::one() { - // variable must not be ~ONE - false => match self.substitution.get(&variable) { - Some(_) => None, - None => Some((variable, l / &coefficient)), - }, - true => None, - } + let (keep_constraint, to_insert) = match lin.try_summand() { + // if the right side is a single variable + Some((variable, coefficient)) => { + match self.substitution.get(&variable) { + // if the variable is already defined + Some(_) => (true, None), + // if the variable is not defined yet + None => match quad.try_linear() { + // if the left side is linear + Some(l) => (false, Some((variable, l / &coefficient))), + // if the left side isn't linear + None => (true, Some((variable, variable.into()))), + }, } - None => None, - }, - None => None, + } + None => (true, None), }; + // insert into the substitution map match to_insert { Some((k, v)) => { self.substitution.insert(k, v); - vec![] } - None => vec![Statement::Constraint(quad, lin)], + None => {} + }; + + // decide whether the constraint should be kept + match keep_constraint { + false => vec![], + true => vec![Statement::Constraint(quad, lin)], } } Statement::Directive(d) => { @@ -82,12 +110,12 @@ impl Folder for RedefinitionOptimizer { fn fold_linear_combination(&mut self, lc: LinComb) -> LinComb { // for each summand, check if it is equal to a linear term in our substitution, otherwise keep it as is lc.0.into_iter() - .map( - |(variable, coefficient)| match self.substitution.get(&variable) { - Some(l) => l.clone() * &coefficient, // we only clone in the case that we found a value in the map - None => LinComb::summand(coefficient, variable), - }, - ) + .map(|(variable, coefficient)| { + self.substitution + .get(&variable) + .map(|l| l.clone() * &coefficient) + .unwrap_or(LinComb::summand(coefficient, variable)) + }) .fold(LinComb::zero(), |acc, x| acc + x) } @@ -104,6 +132,10 @@ impl Folder for RedefinitionOptimizer { self.substitution .extend(fun.returns.iter().map(|x| (x.clone(), x.clone().into()))); + // to prevent the optimiser from replacing ~one, add it to the substitution + self.substitution + .insert(FlatVariable::one(), FlatVariable::one().into()); + fold_function(self, fun) } } @@ -142,6 +174,28 @@ mod tests { assert_eq!(optimizer.fold_function(f), optimized); } + #[test] + fn keep_one() { + // def main(x): + // one = x + // return one + + let one = FlatVariable::one(); + let x = FlatVariable::new(1); + + let f: Function = Function { + id: "foo".to_string(), + arguments: vec![x], + statements: vec![Statement::definition(one, x)], + returns: vec![x.into()], + }; + + let optimized = f.clone(); + + let mut optimizer = RedefinitionOptimizer::new(); + assert_eq!(optimizer.fold_function(f), optimized); + } + #[test] fn remove_synonyms_in_condition() { // def main(x) -> (1): @@ -288,6 +342,43 @@ mod tests { assert_eq!(optimized, expected); } + #[test] + fn keep_existing_quadratic_variable() { + // def main(x, y) -> (): + // z = x * y + // z = x + // return + + // -> + + // def main(x, y) -> (): + // z = x * y + // z = x + // return + + let x = FlatVariable::new(0); + let y = FlatVariable::new(1); + let z = FlatVariable::new(2); + + let f: Function = Function { + id: "main".to_string(), + arguments: vec![x, y], + statements: vec![ + Statement::definition( + z, + QuadComb::from_linear_combinations(LinComb::from(x), LinComb::from(y)), + ), + Statement::definition(z, LinComb::from(x)), + ], + returns: vec![], + }; + + let optimized = f.clone(); + + let mut optimizer = RedefinitionOptimizer::new(); + assert_eq!(optimizer.fold_function(f), optimized); + } + #[test] fn keep_existing_variable() { // def main(x) -> (1): diff --git a/zokrates_core/src/proof_system/bn128/g16.rs b/zokrates_core/src/proof_system/bn128/g16.rs index 6a3f7c14..58635e58 100644 --- a/zokrates_core/src/proof_system/bn128/g16.rs +++ b/zokrates_core/src/proof_system/bn128/g16.rs @@ -3,61 +3,58 @@ use crate::proof_system::bn128::utils::bellman::Computation; use crate::proof_system::bn128::utils::solidity::{ SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB, SOLIDITY_PAIRING_LIB_V2, }; -use crate::proof_system::ProofSystem; +use crate::proof_system::{ProofSystem, SetupKeypair}; use bellman::groth16::Parameters; use regex::Regex; -use std::fs::File; -use std::io::{BufRead, BufReader, Write}; -use std::path::PathBuf; +use std::io::{Cursor, Read}; use zokrates_field::Field; const G16_WARNING: &str = "WARNING: You are using the G16 scheme which is subject to malleability. See zokrates.github.io/reference/proving_schemes.html#g16-malleability for implications."; pub struct G16 {} -impl ProofSystem for G16 { - fn setup(program: ir::Prog, pk_path: &str, vk_path: &str) { - std::env::set_var("BELLMAN_VERBOSE", "0"); +impl ProofSystem for G16 { + fn setup(program: ir::Prog) -> SetupKeypair { + #[cfg(not(target_arch = "wasm32"))] + std::env::set_var("BELLMAN_VERBOSE", "0"); println!("{}", G16_WARNING); let parameters = Computation::without_witness(program).setup(); - let parameters_file = File::create(PathBuf::from(pk_path)).unwrap(); - parameters.write(parameters_file).unwrap(); - let mut vk_file = File::create(PathBuf::from(vk_path)).unwrap(); - vk_file - .write(serialize::serialize_vk::(parameters.vk).as_ref()) - .unwrap(); + + let mut cursor = Cursor::new(Vec::new()); + + parameters.write(&mut cursor).unwrap(); + cursor.set_position(0); + + let vk: String = serialize::serialize_vk::(parameters.vk); + let mut pk: Vec = Vec::new(); + cursor + .read_to_end(&mut pk) + .expect("Could not read cursor buffer"); + + SetupKeypair::from(vk, pk) } fn generate_proof( program: ir::Prog, witness: ir::Witness, - pk_path: &str, - proof_path: &str, - ) -> bool { + proving_key: Vec, + ) -> String { + #[cfg(not(target_arch = "wasm32"))] std::env::set_var("BELLMAN_VERBOSE", "0"); println!("{}", G16_WARNING); let computation = Computation::with_witness(program, witness); - let parameters_file = File::open(PathBuf::from(pk_path)).unwrap(); - - let params = Parameters::read(parameters_file, true).unwrap(); + let params = Parameters::read(proving_key.as_slice(), true).unwrap(); let proof = computation.clone().prove(¶ms); - let mut proof_file = File::create(PathBuf::from(proof_path)).unwrap(); - write!( - proof_file, - "{}", - serialize::serialize_proof::(&proof, &computation.public_inputs_values()) - ) - .unwrap(); - true + serialize::serialize_proof::(&proof, &computation.public_inputs_values()) } - fn export_solidity_verifier(reader: BufReader, is_abiv2: bool) -> String { - let mut lines = reader.lines(); + fn export_solidity_verifier(vk: String, is_abiv2: bool) -> String { + let mut lines = vk.lines(); let (mut template_text, solidity_pairing_lib) = if is_abiv2 { ( @@ -82,10 +79,9 @@ impl ProofSystem for G16 { let vk_input_len_regex = Regex::new(r#"(<%vk_input_length%>)"#).unwrap(); for _ in 0..4 { - let current_line: String = lines + let current_line: &str = lines .next() - .expect("Unexpected end of file in verification key!") - .unwrap(); + .expect("Unexpected end of file in verification key!"); let current_line_split: Vec<&str> = current_line.split("=").collect(); assert_eq!(current_line_split.len(), 2); template_text = vk_regex @@ -93,10 +89,9 @@ impl ProofSystem for G16 { .into_owned(); } - let current_line: String = lines + let current_line: &str = lines .next() - .expect("Unexpected end of file in verification key!") - .unwrap(); + .expect("Unexpected end of file in verification key!"); let current_line_split: Vec<&str> = current_line.split("=").collect(); assert_eq!(current_line_split.len(), 2); let gamma_abc_count: i32 = current_line_split[1].trim().parse().unwrap(); @@ -117,10 +112,9 @@ impl ProofSystem for G16 { let mut gamma_abc_repeat_text = String::new(); for x in 0..gamma_abc_count { let mut curr_template = gamma_abc_template.clone(); - let current_line: String = lines + let current_line: &str = lines .next() - .expect("Unexpected end of file in verification key!") - .unwrap(); + .expect("Unexpected end of file in verification key!"); let current_line_split: Vec<&str> = current_line.split("=").collect(); assert_eq!(current_line_split.len(), 2); curr_template = vk_gamma_abc_index_regex @@ -341,7 +335,6 @@ mod tests { use crate::flat_absy::FlatVariable; use crate::ir::*; use crate::proof_system::bn128::g16::serialize::serialize_proof; - use typed_absy::types::{Signature, Type}; use zokrates_field::Bn128Field; #[allow(dead_code)] @@ -372,9 +365,6 @@ mod tests { )], }, private: vec![false], - signature: Signature::new() - .inputs(vec![Type::FieldElement]) - .outputs(vec![Type::FieldElement]), }; let witness = program diff --git a/zokrates_core/src/proof_system/bn128/gm17.rs b/zokrates_core/src/proof_system/bn128/gm17.rs index f121efac..c853f613 100644 --- a/zokrates_core/src/proof_system/bn128/gm17.rs +++ b/zokrates_core/src/proof_system/bn128/gm17.rs @@ -1,15 +1,11 @@ -extern crate libc; - -use self::libc::{c_char, c_int}; use ir; +use proof_system::bn128::utils::ffi::{Buffer, ProofResult, SetupResult}; use proof_system::bn128::utils::libsnark::{prepare_generate_proof, prepare_setup}; use proof_system::bn128::utils::solidity::{ SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB, SOLIDITY_PAIRING_LIB_V2, }; -use proof_system::ProofSystem; +use proof_system::{ProofSystem, SetupKeypair}; use regex::Regex; -use std::fs::File; -use std::io::{BufRead, BufReader}; use zokrates_field::Bn128Field; @@ -22,48 +18,34 @@ impl GM17 { } extern "C" { - fn _gm17_setup( + fn gm17_setup( A: *const u8, B: *const u8, C: *const u8, - A_len: c_int, - B_len: c_int, - C_len: c_int, - constraints: c_int, - variables: c_int, - inputs: c_int, - pk_path: *const c_char, - vk_path: *const c_char, - ) -> bool; + A_len: i32, + B_len: i32, + C_len: i32, + constraints: i32, + variables: i32, + inputs: i32, + ) -> SetupResult; - fn _gm17_generate_proof( - pk_path: *const c_char, - proof_path: *const c_char, + fn gm17_generate_proof( + pk_buf: *mut Buffer, publquery_inputs: *const u8, - publquery_inputs_length: c_int, + publquery_inputs_length: i32, private_inputs: *const u8, - private_inputs_length: c_int, - ) -> bool; + private_inputs_length: i32, + ) -> ProofResult; } impl ProofSystem for GM17 { - fn setup(program: ir::Prog, pk_path: &str, vk_path: &str) { - let ( - a_arr, - b_arr, - c_arr, - a_vec, - b_vec, - c_vec, - num_constraints, - num_variables, - num_inputs, - pk_path_cstring, - vk_path_cstring, - ) = prepare_setup(program, pk_path, vk_path); + fn setup(program: ir::Prog) -> SetupKeypair { + let (a_arr, b_arr, c_arr, a_vec, b_vec, c_vec, num_constraints, num_variables, num_inputs) = + prepare_setup(program); - unsafe { - _gm17_setup( + let keypair = unsafe { + let result: SetupResult = gm17_setup( a_arr.as_ptr(), b_arr.as_ptr(), c_arr.as_ptr(), @@ -73,41 +55,59 @@ impl ProofSystem for GM17 { num_constraints as i32, num_variables as i32, num_inputs as i32, - pk_path_cstring.as_ptr(), - vk_path_cstring.as_ptr(), ); - } + + let vk: Vec = + std::slice::from_raw_parts(result.vk.data, result.vk.length as usize).to_vec(); + let pk: Vec = + std::slice::from_raw_parts(result.pk.data, result.pk.length as usize).to_vec(); + + // Memory is allocated in C and raw pointers are returned to Rust. The caller has to manually + // free the memory. + result.vk.free(); + result.pk.free(); + + (vk, pk) + }; + + SetupKeypair::from(String::from_utf8(keypair.0).unwrap(), keypair.1) } fn generate_proof( program: ir::Prog, witness: ir::Witness, - pk_path: &str, - proof_path: &str, - ) -> bool { - let ( - pk_path_cstring, - proof_path_cstring, - public_inputs_arr, - public_inputs_length, - private_inputs_arr, - private_inputs_length, - ) = prepare_generate_proof(program, witness, pk_path, proof_path); + proving_key: Vec, + ) -> String { + let (public_inputs_arr, public_inputs_length, private_inputs_arr, private_inputs_length) = + prepare_generate_proof(program, witness); - unsafe { - _gm17_generate_proof( - pk_path_cstring.as_ptr(), - proof_path_cstring.as_ptr(), + let mut pk = proving_key.clone(); + let mut pk_buf = Buffer::from_vec(pk.as_mut()); + + let proof_vec = unsafe { + let result = gm17_generate_proof( + &mut pk_buf as *mut _, public_inputs_arr[0].as_ptr(), public_inputs_length as i32, private_inputs_arr[0].as_ptr(), private_inputs_length as i32, - ) - } + ); + + // Memory is allocated in C and raw pointers are returned to Rust. The caller has to manually + // free the memory. + let proof_vec: Vec = + std::slice::from_raw_parts(result.proof.data, result.proof.length as usize) + .to_vec(); + result.proof.free(); + + proof_vec + }; + + String::from_utf8(proof_vec).unwrap() } - fn export_solidity_verifier(reader: BufReader, is_abiv2: bool) -> String { - let mut lines = reader.lines(); + fn export_solidity_verifier(vk: String, is_abiv2: bool) -> String { + let mut lines = vk.lines(); let (mut template_text, solidity_pairing_lib) = if is_abiv2 { ( @@ -132,10 +132,9 @@ impl ProofSystem for GM17 { let vk_input_len_regex = Regex::new(r#"(<%vk_input_length%>)"#).unwrap(); for _ in 0..5 { - let current_line: String = lines + let current_line: &str = lines .next() - .expect("Unexpected end of file in verification key!") - .unwrap(); + .expect("Unexpected end of file in verification key!"); let current_line_split: Vec<&str> = current_line.split("=").collect(); assert_eq!(current_line_split.len(), 2); template_text = vk_regex @@ -143,10 +142,9 @@ impl ProofSystem for GM17 { .into_owned(); } - let current_line: String = lines + let current_line: &str = lines .next() - .expect("Unexpected end of file in verification key!") - .unwrap(); + .expect("Unexpected end of file in verification key!"); let current_line_split: Vec<&str> = current_line.split("=").collect(); assert_eq!(current_line_split.len(), 2); let query_count: i32 = current_line_split[1].trim().parse().unwrap(); @@ -164,10 +162,9 @@ impl ProofSystem for GM17 { let mut query_repeat_text = String::new(); for x in 0..query_count { let mut curr_template = query_template.clone(); - let current_line: String = lines + let current_line: &str = lines .next() - .expect("Unexpected end of file in verification key!") - .unwrap(); + .expect("Unexpected end of file in verification key!"); let current_line_split: Vec<&str> = current_line.split("=").collect(); assert_eq!(current_line_split.len(), 2); curr_template = vk_query_index_regex diff --git a/zokrates_core/src/proof_system/bn128/pghr13.rs b/zokrates_core/src/proof_system/bn128/pghr13.rs index a34b4758..29d97fdd 100644 --- a/zokrates_core/src/proof_system/bn128/pghr13.rs +++ b/zokrates_core/src/proof_system/bn128/pghr13.rs @@ -1,16 +1,11 @@ -extern crate libc; - -use self::libc::{c_char, c_int}; use ir; +use proof_system::bn128::utils::ffi::{Buffer, ProofResult, SetupResult}; use proof_system::bn128::utils::libsnark::{prepare_generate_proof, prepare_setup}; use proof_system::bn128::utils::solidity::{ SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB, SOLIDITY_PAIRING_LIB_V2, }; -use proof_system::ProofSystem; - +use proof_system::{ProofSystem, SetupKeypair}; use regex::Regex; -use std::fs::File; -use std::io::{BufRead, BufReader}; use zokrates_field::Bn128Field; @@ -23,48 +18,34 @@ impl PGHR13 { } extern "C" { - fn _pghr13_setup( + fn pghr13_setup( A: *const u8, B: *const u8, C: *const u8, - A_len: c_int, - B_len: c_int, - C_len: c_int, - constraints: c_int, - variables: c_int, - inputs: c_int, - pk_path: *const c_char, - vk_path: *const c_char, - ) -> bool; + A_len: i32, + B_len: i32, + C_len: i32, + constraints: i32, + variables: i32, + inputs: i32, + ) -> SetupResult; - fn _pghr13_generate_proof( - pk_path: *const c_char, - proof_path: *const c_char, - public_inputs: *const u8, - public_inputs_length: c_int, + fn pghr13_generate_proof( + pk_buf: *mut Buffer, + publquery_inputs: *const u8, + publquery_inputs_length: i32, private_inputs: *const u8, - private_inputs_length: c_int, - ) -> bool; + private_inputs_length: i32, + ) -> ProofResult; } impl ProofSystem for PGHR13 { - fn setup(program: ir::Prog, pk_path: &str, vk_path: &str) { - let ( - a_arr, - b_arr, - c_arr, - a_vec, - b_vec, - c_vec, - num_constraints, - num_variables, - num_inputs, - pk_path_cstring, - vk_path_cstring, - ) = prepare_setup(program, pk_path, vk_path); + fn setup(program: ir::Prog) -> SetupKeypair { + let (a_arr, b_arr, c_arr, a_vec, b_vec, c_vec, num_constraints, num_variables, num_inputs) = + prepare_setup(program); - unsafe { - _pghr13_setup( + let keypair = unsafe { + let result: SetupResult = pghr13_setup( a_arr.as_ptr(), b_arr.as_ptr(), c_arr.as_ptr(), @@ -74,46 +55,60 @@ impl ProofSystem for PGHR13 { num_constraints as i32, num_variables as i32, num_inputs as i32, - pk_path_cstring.as_ptr(), - vk_path_cstring.as_ptr(), ); - } + + let vk: Vec = + std::slice::from_raw_parts(result.vk.data, result.vk.length as usize).to_vec(); + let pk: Vec = + std::slice::from_raw_parts(result.pk.data, result.pk.length as usize).to_vec(); + + // Memory is allocated in C and raw pointers are returned to Rust. The caller has to manually + // free the memory. + result.vk.free(); + result.pk.free(); + + (vk, pk) + }; + + SetupKeypair::from(String::from_utf8(keypair.0).unwrap(), keypair.1) } fn generate_proof( program: ir::Prog, witness: ir::Witness, - pk_path: &str, - proof_path: &str, - ) -> bool { - let ( - pk_path_cstring, - proof_path_cstring, - public_inputs_arr, - public_inputs_length, - private_inputs_arr, - private_inputs_length, - ) = prepare_generate_proof(program, witness, pk_path, proof_path); + proving_key: Vec, + ) -> String { + let (public_inputs_arr, public_inputs_length, private_inputs_arr, private_inputs_length) = + prepare_generate_proof(program, witness); - println!( - "{:?}", - (pk_path_cstring.clone(), proof_path_cstring.clone(),) - ); + let mut pk = proving_key.clone(); + let mut pk_buf = Buffer::from_vec(pk.as_mut()); - unsafe { - _pghr13_generate_proof( - pk_path_cstring.as_ptr(), - proof_path_cstring.as_ptr(), + let proof_vec = unsafe { + let result = pghr13_generate_proof( + &mut pk_buf as *mut _, public_inputs_arr[0].as_ptr(), public_inputs_length as i32, private_inputs_arr[0].as_ptr(), private_inputs_length as i32, - ) - } + ); + + let proof_vec: Vec = + std::slice::from_raw_parts(result.proof.data, result.proof.length as usize) + .to_vec(); + + // Memory is allocated in C and raw pointers are returned to Rust. The caller has to manually + // free the memory. + result.proof.free(); + + proof_vec + }; + + String::from_utf8(proof_vec).unwrap() } - fn export_solidity_verifier(reader: BufReader, is_abiv2: bool) -> String { - let mut lines = reader.lines(); + fn export_solidity_verifier(vk: String, is_abiv2: bool) -> String { + let mut lines = vk.lines(); let (mut template_text, solidity_pairing_lib) = if is_abiv2 { ( @@ -138,10 +133,9 @@ impl ProofSystem for PGHR13 { let vk_input_len_regex = Regex::new(r#"(<%vk_input_length%>)"#).unwrap(); for _ in 0..7 { - let current_line: String = lines + let current_line: &str = lines .next() - .expect("Unexpected end of file in verification key!") - .unwrap(); + .expect("Unexpected end of file in verification key!"); let current_line_split: Vec<&str> = current_line.split("=").collect(); assert_eq!(current_line_split.len(), 2); template_text = vk_regex @@ -149,10 +143,9 @@ impl ProofSystem for PGHR13 { .into_owned(); } - let current_line: String = lines + let current_line: &str = lines .next() - .expect("Unexpected end of file in verification key!") - .unwrap(); + .expect("Unexpected end of file in verification key!"); let current_line_split: Vec<&str> = current_line.split("=").collect(); assert_eq!(current_line_split.len(), 2); let ic_count: i32 = current_line_split[1].trim().parse().unwrap(); @@ -167,10 +160,9 @@ impl ProofSystem for PGHR13 { let mut ic_repeat_text = String::new(); for x in 0..ic_count { let mut curr_template = ic_template.clone(); - let current_line: String = lines + let current_line: &str = lines .next() - .expect("Unexpected end of file in verification key!") - .unwrap(); + .expect("Unexpected end of file in verification key!"); let current_line_split: Vec<&str> = current_line.split("=").collect(); assert_eq!(current_line_split.len(), 2); curr_template = vk_ic_index_regex diff --git a/zokrates_core/src/proof_system/bn128/utils/bellman.rs b/zokrates_core/src/proof_system/bn128/utils/bellman.rs index fc5b8ee8..b45c85f6 100644 --- a/zokrates_core/src/proof_system/bn128/utils/bellman.rs +++ b/zokrates_core/src/proof_system/bn128/utils/bellman.rs @@ -11,7 +11,7 @@ use bellman::{Circuit, ConstraintSystem, LinearCombination, SynthesisError, Vari use std::collections::BTreeMap; use zokrates_field::Field; -use self::rand::*; +use self::rand::ChaChaRng; use crate::flat_absy::FlatVariable; pub use self::parse::*; @@ -160,7 +160,8 @@ impl Prog { impl Computation { pub fn prove(self, params: &Parameters) -> Proof { - let rng = &mut thread_rng(); + let rng = &mut ChaChaRng::new_unseeded(); + let proof = create_random_proof(self.clone(), params, rng).unwrap(); let pvk = prepare_verifying_key(¶ms.vk); @@ -189,7 +190,7 @@ impl Computation { } pub fn setup(self) -> Parameters { - let rng = &mut thread_rng(); + let rng = &mut ChaChaRng::new_unseeded(); // run setup phase generate_random_parameters(self, rng).unwrap() } @@ -306,7 +307,6 @@ mod parse { mod tests { use super::*; use crate::ir::{Function, LinComb}; - use typed_absy::types::{Signature, Type}; use zokrates_field::Bn128Field; mod prove { @@ -322,7 +322,6 @@ mod tests { statements: vec![], }, private: vec![], - signature: Signature::new(), }; let witness = program.clone().execute(&vec![]).unwrap(); @@ -345,9 +344,6 @@ mod tests { )], }, private: vec![true], - signature: Signature::new() - .inputs(vec![Type::FieldElement]) - .outputs(vec![Type::FieldElement]), }; let witness = program.clone().execute(&vec![Bn128Field::from(0)]).unwrap(); @@ -370,9 +366,6 @@ mod tests { )], }, private: vec![false], - signature: Signature::new() - .inputs(vec![Type::FieldElement]) - .outputs(vec![Type::FieldElement]), }; let witness = program.clone().execute(&vec![Bn128Field::from(0)]).unwrap(); @@ -395,7 +388,6 @@ mod tests { )], }, private: vec![], - signature: Signature::new().outputs(vec![Type::FieldElement]), }; let witness = program.clone().execute(&vec![]).unwrap(); @@ -430,9 +422,6 @@ mod tests { ], }, private: vec![true, false], - signature: Signature::new() - .inputs(vec![Type::FieldElement, Type::FieldElement]) - .outputs(vec![Type::FieldElement, Type::FieldElement]), }; let witness = program @@ -458,9 +447,6 @@ mod tests { )], }, private: vec![false], - signature: Signature::new() - .inputs(vec![Type::FieldElement]) - .outputs(vec![Type::FieldElement]), }; let witness = program.clone().execute(&vec![Bn128Field::from(3)]).unwrap(); @@ -485,9 +471,6 @@ mod tests { )], }, private: vec![true, false], - signature: Signature::new() - .inputs(vec![Type::FieldElement, Type::FieldElement]) - .outputs(vec![Type::FieldElement]), }; let witness = program diff --git a/zokrates_core/src/proof_system/bn128/utils/ffi.rs b/zokrates_core/src/proof_system/bn128/utils/ffi.rs new file mode 100644 index 00000000..5dd0fc51 --- /dev/null +++ b/zokrates_core/src/proof_system/bn128/utils/ffi.rs @@ -0,0 +1,36 @@ +#[repr(C)] +pub struct Buffer { + pub data: *mut u8, + pub length: i32, +} + +#[repr(C)] +pub struct SetupResult { + pub vk: Buffer, + pub pk: Buffer, +} + +#[repr(C)] +pub struct ProofResult { + pub proof: Buffer, +} + +extern "C" { + fn __free(ptr: *mut u8); +} + +impl Buffer { + pub fn from_vec(v: &mut Vec) -> Buffer { + let length = v.len() as i32; + Buffer { + data: v.as_mut_ptr(), + length, + } + } + + /// The purpose of this function is to free memory previously allocated by "malloc" + /// from C standard library. Do not use otherwise. + pub fn free(self) { + unsafe { __free(self.data) }; + } +} diff --git a/zokrates_core/src/proof_system/bn128/utils/libsnark.rs b/zokrates_core/src/proof_system/bn128/utils/libsnark.rs index 2d18770f..a0bb2d52 100644 --- a/zokrates_core/src/proof_system/bn128/utils/libsnark.rs +++ b/zokrates_core/src/proof_system/bn128/utils/libsnark.rs @@ -2,10 +2,9 @@ use flat_absy::FlatVariable; use ir::{self, Statement}; use std::cmp::max; use std::collections::HashMap; -use std::ffi::CString; use zokrates_field::Field; -// utility function. Converts a Fields vector-based byte representation to fixed size array. +// utility function. Converts a Field's vector-based byte representation to fixed size array. fn vec_as_u8_32_array(vec: &Vec) -> [u8; 32] { assert!(vec.len() <= 32); let mut array = [0u8; 32]; @@ -18,8 +17,6 @@ fn vec_as_u8_32_array(vec: &Vec) -> [u8; 32] { // proof-system-independent preparation for the setup phase pub fn prepare_setup( program: ir::Prog, - pk_path: &str, - vk_path: &str, ) -> ( Vec, Vec, @@ -30,8 +27,6 @@ pub fn prepare_setup( usize, usize, usize, - CString, - CString, ) { // transform to R1CS let (variables, public_variables_count, a, b, c) = r1cs_program(program); @@ -129,10 +124,6 @@ pub fn prepare_setup( } } - // convert String slices to 'CString's - let pk_path_cstring = CString::new(pk_path).unwrap(); - let vk_path_cstring = CString::new(vk_path).unwrap(); - ( a_arr, b_arr, @@ -143,8 +134,6 @@ pub fn prepare_setup( num_constraints, num_variables, num_inputs, - pk_path_cstring, - vk_path_cstring, ) } @@ -152,9 +141,7 @@ pub fn prepare_setup( pub fn prepare_generate_proof( program: ir::Prog, witness: ir::Witness, - pk_path: &str, - proof_path: &str, -) -> (CString, CString, Vec<[u8; 32]>, usize, Vec<[u8; 32]>, usize) { +) -> (Vec<[u8; 32]>, usize, Vec<[u8; 32]>, usize) { // recover variable order from the program let (variables, public_variables_count, _, _, _) = r1cs_program(program); @@ -164,9 +151,6 @@ pub fn prepare_generate_proof( let mut public_inputs: Vec<_> = witness.clone(); let private_inputs: Vec<_> = public_inputs.split_off(public_variables_count); - let pk_path_cstring = CString::new(pk_path).unwrap(); - let proof_path_cstring = CString::new(proof_path).unwrap(); - let public_inputs_length = public_inputs.len(); let private_inputs_length = private_inputs.len(); @@ -183,8 +167,6 @@ pub fn prepare_generate_proof( } ( - pk_path_cstring, - proof_path_cstring, public_inputs_arr, public_inputs_length, private_inputs_arr, @@ -192,7 +174,7 @@ pub fn prepare_generate_proof( ) } -/// Returns the index of `var` in `variables`, adding `var` with incremented index if it not yet exists. +/// Returns the index of `var` in `variables`, adding `var` with incremented index if it does not yet exists. /// /// # Arguments /// @@ -238,7 +220,7 @@ pub fn r1cs_program( //Only the main function is relevant in this step, since all calls to other functions were resolved during flattening let main = prog.main; - //~out are added after main's arguments as we want variables (columns) + //~out are added after main's arguments, since we want variables (columns) //in the r1cs to be aligned like "public inputs | private inputs" let main_return_count = main.returns.len(); diff --git a/zokrates_core/src/proof_system/bn128/utils/mod.rs b/zokrates_core/src/proof_system/bn128/utils/mod.rs index e20b86bf..1aa80a4e 100644 --- a/zokrates_core/src/proof_system/bn128/utils/mod.rs +++ b/zokrates_core/src/proof_system/bn128/utils/mod.rs @@ -1,4 +1,6 @@ pub mod bellman; #[cfg(feature = "libsnark")] +pub mod ffi; +#[cfg(feature = "libsnark")] pub mod libsnark; pub mod solidity; diff --git a/zokrates_core/src/proof_system/bn128/utils/solidity.rs b/zokrates_core/src/proof_system/bn128/utils/solidity.rs index dc453d98..7dfa99f3 100644 --- a/zokrates_core/src/proof_system/bn128/utils/solidity.rs +++ b/zokrates_core/src/proof_system/bn128/utils/solidity.rs @@ -1,4 +1,5 @@ pub const SOLIDITY_G2_ADDITION_LIB: &str = r#"// This file is LGPL3 Licensed +pragma solidity ^0.6.1; /** * @title Elliptic curve operations on twist points for alt_bn128 @@ -234,7 +235,7 @@ library BN256G2 { mstore(add(freemem,0x60), a) mstore(add(freemem,0x80), sub(n, 2)) mstore(add(freemem,0xA0), n) - success := staticcall(sub(gas, 2000), 5, freemem, 0xC0, freemem, 0x20) + success := staticcall(sub(gas(), 2000), 5, freemem, 0xC0, freemem, 0x20) result := mload(freemem) } require(success); @@ -400,7 +401,7 @@ pub const SOLIDITY_PAIRING_LIB_V2: &str = r#"// This file is MIT Licensed. // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -pragma solidity ^0.5.0; +pragma solidity ^0.6.1; pragma experimental ABIEncoderV2; library Pairing { struct G1Point { @@ -433,7 +434,7 @@ library Pairing { return G1Point(0, 0); return G1Point(p.X, q - (p.Y % q)); } - /// @return the sum of two points of G1 + /// @return r the sum of two points of G1 function addition(G1Point memory p1, G1Point memory p2) internal returns (G1Point memory r) { uint[4] memory input; input[0] = p1.X; @@ -442,17 +443,17 @@ library Pairing { input[3] = p2.Y; bool success; assembly { - success := call(sub(gas, 2000), 6, 0, input, 0xc0, r, 0x60) + success := call(sub(gas(), 2000), 6, 0, input, 0xc0, r, 0x60) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } require(success); } - /// @return the sum of two points of G2 + /// @return r the sum of two points of G2 function addition(G2Point memory p1, G2Point memory p2) internal returns (G2Point memory r) { (r.X[1], r.X[0], r.Y[1], r.Y[0]) = BN256G2.ECTwistAdd(p1.X[1],p1.X[0],p1.Y[1],p1.Y[0],p2.X[1],p2.X[0],p2.Y[1],p2.Y[0]); } - /// @return the product of a point on G1 and a scalar, i.e. + /// @return r the product of a point on G1 and a scalar, i.e. /// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p. function scalar_mul(G1Point memory p, uint s) internal returns (G1Point memory r) { uint[3] memory input; @@ -461,7 +462,7 @@ library Pairing { input[2] = s; bool success; assembly { - success := call(sub(gas, 2000), 7, 0, input, 0x80, r, 0x60) + success := call(sub(gas(), 2000), 7, 0, input, 0x80, r, 0x60) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } @@ -488,7 +489,7 @@ library Pairing { uint[1] memory out; bool success; assembly { - success := call(sub(gas, 2000), 8, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) + success := call(sub(gas(), 2000), 8, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } @@ -549,7 +550,7 @@ pub const SOLIDITY_PAIRING_LIB: &str = r#"// This file is MIT Licensed. // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -pragma solidity ^0.5.0; +pragma solidity ^0.6.1; library Pairing { struct G1Point { uint X; @@ -581,7 +582,7 @@ library Pairing { return G1Point(0, 0); return G1Point(p.X, q - (p.Y % q)); } - /// @return the sum of two points of G1 + /// @return r the sum of two points of G1 function addition(G1Point memory p1, G1Point memory p2) internal returns (G1Point memory r) { uint[4] memory input; input[0] = p1.X; @@ -590,17 +591,17 @@ library Pairing { input[3] = p2.Y; bool success; assembly { - success := call(sub(gas, 2000), 6, 0, input, 0xc0, r, 0x60) + success := call(sub(gas(), 2000), 6, 0, input, 0xc0, r, 0x60) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } require(success); } - /// @return the sum of two points of G2 + /// @return r the sum of two points of G2 function addition(G2Point memory p1, G2Point memory p2) internal returns (G2Point memory r) { (r.X[1], r.X[0], r.Y[1], r.Y[0]) = BN256G2.ECTwistAdd(p1.X[1],p1.X[0],p1.Y[1],p1.Y[0],p2.X[1],p2.X[0],p2.Y[1],p2.Y[0]); } - /// @return the product of a point on G1 and a scalar, i.e. + /// @return r the product of a point on G1 and a scalar, i.e. /// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p. function scalar_mul(G1Point memory p, uint s) internal returns (G1Point memory r) { uint[3] memory input; @@ -609,7 +610,7 @@ library Pairing { input[2] = s; bool success; assembly { - success := call(sub(gas, 2000), 7, 0, input, 0x80, r, 0x60) + success := call(sub(gas(), 2000), 7, 0, input, 0x80, r, 0x60) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } @@ -636,7 +637,7 @@ library Pairing { uint[1] memory out; bool success; assembly { - success := call(sub(gas, 2000), 8, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) + success := call(sub(gas(), 2000), 8, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } diff --git a/zokrates_core/src/proof_system/mod.rs b/zokrates_core/src/proof_system/mod.rs index 3e4e7baa..deb7b186 100644 --- a/zokrates_core/src/proof_system/mod.rs +++ b/zokrates_core/src/proof_system/mod.rs @@ -1,6 +1,5 @@ mod bn128; -use std::fs::File; use zokrates_field::Field; pub use self::bn128::G16; @@ -10,17 +9,29 @@ pub use self::bn128::GM17; pub use self::bn128::PGHR13; use crate::ir; -use std::io::BufReader; + +// We only need to serialize this struct, there is no need for deserialization as keys are +// used separetely in other use cases +#[derive(Serialize)] +pub struct SetupKeypair { + pub vk: String, + pub pk: Vec, +} + +impl SetupKeypair { + pub fn from(vk: String, pk: Vec) -> SetupKeypair { + SetupKeypair { vk, pk } + } +} pub trait ProofSystem { - fn setup(program: ir::Prog, pk_path: &str, vk_path: &str); + fn setup(program: ir::Prog) -> SetupKeypair; fn generate_proof( program: ir::Prog, witness: ir::Witness, - pk_path: &str, - proof_path: &str, - ) -> bool; + proving_key: Vec, + ) -> String; - fn export_solidity_verifier(reader: BufReader, is_abiv2: bool) -> String; + fn export_solidity_verifier(vk: String, is_abiv2: bool) -> String; } diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 0834a7e5..dad2d637 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -10,6 +10,7 @@ use crate::typed_absy::*; use crate::typed_absy::{Parameter, Variable}; use std::collections::{hash_map::Entry, BTreeSet, HashMap, HashSet}; use std::fmt; +use std::path::PathBuf; use zokrates_field::Field; use crate::parser::Position; @@ -18,11 +19,27 @@ use crate::absy::types::{UnresolvedSignature, UnresolvedType, UserTypeId}; use crate::typed_absy::types::{FunctionKey, Signature, Type}; use std::hash::{Hash, Hasher}; +use typed_absy::types::{ArrayType, StructMember}; + +#[derive(PartialEq, Debug)] +pub struct ErrorInner { + pos: Option<(Position, Position)>, + message: String, +} #[derive(PartialEq, Debug)] pub struct Error { - pos: Option<(Position, Position)>, - message: String, + pub inner: ErrorInner, + pub module_id: PathBuf, +} + +impl ErrorInner { + fn in_file(self, id: &ModuleId) -> Error { + Error { + inner: self, + module_id: id.clone(), + } + } } type TypeMap = HashMap>; @@ -38,7 +55,7 @@ struct State<'ast, T: Field> { types: TypeMap, } -/// A symbol for a given name: either a type, or a group of functions. Not both! +/// A symbol for a given name: either a type or a group of functions. Not both! #[derive(PartialEq, Hash, Eq, Debug)] enum SymbolType { Type, @@ -96,7 +113,7 @@ impl<'ast, T: Field> State<'ast, T> { } } -impl fmt::Display for Error { +impl fmt::Display for ErrorInner { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let location = self .pos @@ -162,12 +179,8 @@ impl<'ast> FunctionQuery<'ast> { }) } - fn match_funcs(&self, funcs: &HashSet>) -> Vec> { - funcs - .iter() - .filter(|func| self.match_func(func)) - .cloned() - .collect() + fn match_funcs(&self, funcs: &HashSet>) -> Option> { + funcs.iter().find(|func| self.match_func(func)).cloned() } } @@ -193,7 +206,7 @@ impl<'ast> Hash for ScopedVariable<'ast> { impl<'ast> Eq for ScopedVariable<'ast> {} -/// Checker, checks the semantics of a program, keeping track of functions and variables in scope +/// Checker checks the semantics of a program, keeping track of functions and variables in scope pub struct Checker<'ast> { scope: HashSet>, functions: HashSet>, @@ -236,8 +249,16 @@ impl<'ast> Checker<'ast> { return Err(errors); } - Checker::check_single_main(state.typed_modules.get(&program.main).unwrap()) - .map_err(|e| vec![e])?; + let main_id = program.main.clone(); + + Checker::check_single_main(state.typed_modules.get(&program.main).unwrap()).map_err( + |inner| { + vec![Error { + inner, + module_id: main_id, + }] + }, + )?; Ok(TypedProgram { main: program.main, @@ -250,7 +271,7 @@ impl<'ast> Checker<'ast> { s: StructTypeNode<'ast>, module_id: &ModuleId, types: &TypeMap, - ) -> Result> { + ) -> Result> { let pos = s.pos(); let s = s.value; @@ -266,7 +287,7 @@ impl<'ast> Checker<'ast> { { Ok(f) => match fields_set.insert(f.0.clone()) { true => fields.push(f), - false => errors.push(Error { + false => errors.push(ErrorInner { pos: Some(pos), message: format!("Duplicate key {} in struct definition", f.0,), }), @@ -281,7 +302,12 @@ impl<'ast> Checker<'ast> { return Err(errors); } - Ok(Type::Struct(fields)) + Ok(Type::Struct( + fields + .iter() + .map(|f| StructMember::new(f.0.clone(), f.1.clone())) + .collect(), + )) } fn check_symbol_declaration( @@ -292,7 +318,7 @@ impl<'ast> Checker<'ast> { functions: &mut HashMap, TypedFunctionSymbol<'ast, T>>, symbol_unifier: &mut SymbolUnifier, ) -> Result<(), Vec> { - let mut errors = vec![]; + let mut errors: Vec = vec![]; let pos = declaration.pos(); let declaration = declaration.value; @@ -302,13 +328,16 @@ impl<'ast> Checker<'ast> { match self.check_struct_type_declaration(t.clone(), module_id, &state.types) { Ok(ty) => { match symbol_unifier.insert_type(declaration.id) { - false => errors.push(Error { - pos: Some(pos), - message: format!( - "{} conflicts with another symbol", - declaration.id, - ), - }), + false => errors.push( + ErrorInner { + pos: Some(pos), + message: format!( + "{} conflicts with another symbol", + declaration.id, + ), + } + .in_file(module_id), + ), true => {} }; state @@ -317,16 +346,25 @@ impl<'ast> Checker<'ast> { .or_default() .insert(declaration.id.to_string(), ty); } - Err(e) => errors.extend(e), + Err(e) => errors.extend(e.into_iter().map(|inner| Error { + inner, + module_id: module_id.clone(), + })), } } Symbol::HereFunction(f) => match self.check_function(f, module_id, &state.types) { Ok(funct) => { match symbol_unifier.insert_function(declaration.id, funct.signature.clone()) { - false => errors.push(Error { - pos: Some(pos), - message: format!("{} conflicts with another symbol", declaration.id,), - }), + false => errors.push( + ErrorInner { + pos: Some(pos), + message: format!( + "{} conflicts with another symbol", + declaration.id, + ), + } + .in_file(module_id), + ), true => {} }; @@ -341,7 +379,7 @@ impl<'ast> Checker<'ast> { ); } Err(e) => { - errors.extend(e); + errors.extend(e.into_iter().map(|inner| inner.in_file(module_id))); } }, Symbol::There(import) => { @@ -378,12 +416,14 @@ impl<'ast> Checker<'ast> { match symbol_unifier.insert_type(declaration.id) { false => { errors.push(Error { + module_id: module_id.clone(), + inner: ErrorInner { pos: Some(pos), message: format!( "{} conflicts with another symbol", declaration.id, ), - }); + }}); } true => {} }; @@ -394,13 +434,13 @@ impl<'ast> Checker<'ast> { .insert(import.symbol_id.to_string(), t.clone()); } (0, None) => { - errors.push(Error { + errors.push(ErrorInner { pos: Some(pos), message: format!( "Could not find symbol {} in module {}", - import.symbol_id, import.module_id, + import.symbol_id, import.module_id.display(), ), - }); + }.in_file(module_id)); } (_, Some(_)) => unreachable!("collision in module we're importing from should have been caught when checking it"), _ => { @@ -408,13 +448,13 @@ impl<'ast> Checker<'ast> { match symbol_unifier.insert_function(declaration.id, candidate.signature.clone()) { false => { - errors.push(Error { + errors.push(ErrorInner { pos: Some(pos), message: format!( "{} conflicts with another symbol", declaration.id, ), - }); + }.in_file(module_id)); }, true => {} }; @@ -439,10 +479,16 @@ impl<'ast> Checker<'ast> { Symbol::Flat(funct) => { match symbol_unifier.insert_function(declaration.id, funct.signature::()) { false => { - errors.push(Error { - pos: Some(pos), - message: format!("{} conflicts with another symbol", declaration.id,), - }); + errors.push( + ErrorInner { + pos: Some(pos), + message: format!( + "{} conflicts with another symbol", + declaration.id, + ), + } + .in_file(module_id), + ); } true => {} }; @@ -531,7 +577,7 @@ impl<'ast> Checker<'ast> { Ok(()) } - fn check_single_main(module: &TypedModule) -> Result<(), Error> { + fn check_single_main(module: &TypedModule) -> Result<(), ErrorInner> { match module .functions .iter() @@ -539,21 +585,21 @@ impl<'ast> Checker<'ast> { .count() { 1 => Ok(()), - 0 => Err(Error { + 0 => Err(ErrorInner { pos: None, message: format!("No main function found"), }), - n => Err(Error { + n => Err(ErrorInner { pos: None, message: format!("Only one main function allowed, found {}", n), }), } } - fn check_for_var(&self, var: &VariableNode) -> Result<(), Error> { + fn check_for_var(&self, var: &VariableNode) -> Result<(), ErrorInner> { match var.value.get_type() { UnresolvedType::FieldElement => Ok(()), - t => Err(Error { + t => Err(ErrorInner { pos: Some(var.pos()), message: format!("Variable in for loop cannot have type {}", t), }), @@ -565,7 +611,7 @@ impl<'ast> Checker<'ast> { funct_node: FunctionNode<'ast, T>, module_id: &ModuleId, types: &TypeMap, - ) -> Result, Vec> { + ) -> Result, Vec> { self.enter_scope(); let mut errors = vec![]; @@ -600,7 +646,7 @@ impl<'ast> Checker<'ast> { == s.outputs { true => {} - false => errors.push(Error { + false => errors.push(ErrorInner { pos: Some(pos), message: format!( "Expected ({}) in return statement, found ({})", @@ -652,7 +698,7 @@ impl<'ast> Checker<'ast> { p: ParameterNode<'ast>, module_id: &ModuleId, types: &TypeMap, - ) -> Result, Vec> { + ) -> Result, Vec> { let var = self.check_variable(p.value.id, module_id, types)?; Ok(Parameter { @@ -666,7 +712,7 @@ impl<'ast> Checker<'ast> { signature: UnresolvedSignature, module_id: &ModuleId, types: &TypeMap, - ) -> Result> { + ) -> Result> { let mut errors = vec![]; let mut inputs = vec![]; let mut outputs = vec![]; @@ -705,24 +751,24 @@ impl<'ast> Checker<'ast> { ty: UnresolvedTypeNode, module_id: &ModuleId, types: &TypeMap, - ) -> Result { + ) -> Result { let pos = ty.pos(); let ty = ty.value; match ty { UnresolvedType::FieldElement => Ok(Type::FieldElement), UnresolvedType::Boolean => Ok(Type::Boolean), - UnresolvedType::Array(t, size) => Ok(Type::Array( - box self.check_type(*t, module_id, types)?, + UnresolvedType::Array(t, size) => Ok(Type::Array(ArrayType::new( + self.check_type(*t, module_id, types)?, size, - )), + ))), UnresolvedType::User(id) => { types .get(module_id) .unwrap() .get(&id) .cloned() - .ok_or_else(|| Error { + .ok_or_else(|| ErrorInner { pos: Some(pos), message: format!("Undefined type {}", id), }) @@ -735,7 +781,7 @@ impl<'ast> Checker<'ast> { v: crate::absy::VariableNode<'ast>, module_id: &ModuleId, types: &TypeMap, - ) -> Result, Vec> { + ) -> Result, Vec> { Ok(Variable::with_id_and_type( v.value.id.into(), self.check_type(v.value._type, module_id, types) @@ -748,7 +794,7 @@ impl<'ast> Checker<'ast> { stat: StatementNode<'ast, T>, module_id: &ModuleId, types: &TypeMap, - ) -> Result, Vec> { + ) -> Result, Vec> { let pos = stat.pos(); match stat.value { @@ -767,7 +813,7 @@ impl<'ast> Checker<'ast> { let var = self.check_variable(var, module_id, types)?; match self.insert_into_scope(var.clone()) { true => Ok(TypedStatement::Declaration(var)), - false => Err(Error { + false => Err(ErrorInner { pos: Some(pos), message: format!("Duplicate declaration for variable named {}", var.id), }), @@ -798,7 +844,7 @@ impl<'ast> Checker<'ast> { // make sure the assignee has the same type as the rhs match var_type == expression_type { true => Ok(TypedStatement::Definition(var, checked_expr)), - false => Err(Error { + false => Err(ErrorInner { pos: Some(pos), message: format!( "Expression {} of type {} cannot be assigned to {} of type {}", @@ -819,7 +865,7 @@ impl<'ast> Checker<'ast> { if checked_lhs.get_type() == checked_rhs.get_type() { Ok(TypedStatement::Condition(checked_lhs, checked_rhs)) } else { - Err(Error { + Err(ErrorInner { pos: Some(pos), message: format!( "Cannot compare {} of type {:?} to {} of type {:?}", @@ -839,6 +885,37 @@ impl<'ast> Checker<'ast> { let var = self.check_variable(var, module_id, types).unwrap(); + let from = self + .check_expression(from, module_id, &types) + .map_err(|e| vec![e])?; + let to = self + .check_expression(to, module_id, &types) + .map_err(|e| vec![e])?; + + let from = match from { + TypedExpression::FieldElement(e) => Ok(e), + e => Err(ErrorInner { + pos: Some(pos), + message: format!( + "Expected lower loop bound to be of type field, found {}", + e.get_type() + ), + }), + } + .map_err(|e| vec![e])?; + + let to = match to { + TypedExpression::FieldElement(e) => Ok(e), + e => Err(ErrorInner { + pos: Some(pos), + message: format!( + "Expected higher loop bound to be of type field, found {}", + e.get_type() + ), + }), + } + .map_err(|e| vec![e])?; + self.insert_into_scope(var.clone()); let mut checked_statements = vec![]; @@ -855,25 +932,32 @@ impl<'ast> Checker<'ast> { match rhs.value { // Right side has to be a function call Expression::FunctionCall(fun_id, arguments) => { - // find lhs types - let mut vars_types: Vec> = vec![]; - let mut var_names = vec![]; - for assignee in assignees { - let (name, t) = match assignee.value { - Assignee::Identifier(name) => { - Ok((name, match self.get_scope(&name) { - None => None, - Some(sv) => Some(sv.id.get_type()) - })) - } - ref a => Err(Error { - pos: Some(pos), - message: format!("Left hand side of function return assignment must be a list of identifiers, found {}", a)}) - }.map_err(|e| vec![e])?; - vars_types.push(t); - var_names.push(name); + + // check lhs assignees are defined + let (assignees, errors): (Vec<_>, Vec<_>) = assignees.into_iter().map(|a| self.check_assignee(a, module_id, types)).partition(|r| r.is_ok()); + + if errors.len() > 0 { + return Err(errors.into_iter().map(|e| e.unwrap_err()).collect()); } - // find arguments types + + // constrain assignees to being identifiers + let (variables, errors): (Vec<_>, Vec<_>) = assignees.into_iter().map(|a| match a.unwrap() { + TypedAssignee::Identifier(v) => Ok(v), + a => Err(ErrorInner { + pos: Some(pos), + message: format!("Only assignment to identifiers is supported, found {}", a) + }) + }).partition(|r| r.is_ok()); + + if errors.len() > 0 { + return Err(errors.into_iter().map(|e| e.unwrap_err()).collect()); + } + + let variables: Vec<_> = variables.into_iter().map(|v| v.unwrap()).collect(); + + let vars_types = variables.iter().map(|a| Some(a.get_type().clone())).collect(); + + // find argument types let mut arguments_checked = vec![]; for arg in arguments { let arg_checked = self.check_expression(arg, module_id, &types).map_err(|e| vec![e])?; @@ -884,37 +968,23 @@ impl<'ast> Checker<'ast> { arguments_checked.iter().map(|a| a.get_type()).collect(); let query = FunctionQuery::new(&fun_id, &arguments_types, &vars_types); - let candidates = self.find_candidates(&query); + let f = self.find_function(&query); - match candidates.len() { + match f { // the function has to be defined - 1 => { - let f = &candidates[0]; - - // we can infer the left hand side to be typed as the return values - let lhs: Vec = var_names.iter().zip(f.signature.outputs.iter()).map(|(name, ty)| - Variable::with_id_and_type(crate::typed_absy::Identifier::from(*name), ty.clone()) - ).collect(); - - let assignees: Vec<_> = lhs.iter().map(|v| v.clone().into()).collect(); + Some(f) => { let call = TypedExpressionList::FunctionCall(f.clone(), arguments_checked, f.signature.outputs.clone()); - for var in lhs { - self.insert_into_scope(var); - } - - Ok(TypedStatement::MultipleDefinition(assignees, call)) + Ok(TypedStatement::MultipleDefinition(variables, call)) }, - 0 => Err(Error { pos: Some(pos), + None => Err(ErrorInner { pos: Some(pos), message: format!("Function definition for function {} with signature {} not found.", fun_id, query) }), - _ => Err(Error { pos: Some(pos), - message: format!("Function call for function {} with arguments {:?} is ambiguous.", fun_id, arguments_types) }), } } - _ => Err(Error { + _ => Err(ErrorInner { pos: Some(pos), - message: format!("{} should be a FunctionCall", rhs), + message: format!("{} should be a function call", rhs), }), }.map_err(|e| vec![e]) } @@ -926,7 +996,7 @@ impl<'ast> Checker<'ast> { assignee: AssigneeNode<'ast, T>, module_id: &ModuleId, types: &TypeMap, - ) -> Result, Error> { + ) -> Result, ErrorInner> { let pos = assignee.pos(); // check that the assignee is declared match assignee.value { @@ -935,9 +1005,9 @@ impl<'ast> Checker<'ast> { variable_name.into(), var.id._type.clone(), ))), - None => Err(Error { + None => Err(ErrorInner { pos: Some(assignee.pos()), - message: format!("Undeclared variable: {:?}", variable_name), + message: format!("Variable `{}` is undeclared", variable_name), }), }, Assignee::Select(box assignee, box index) => { @@ -958,7 +1028,7 @@ impl<'ast> Checker<'ast> { let checked_typed_index = match checked_index { TypedExpression::FieldElement(e) => Ok(e), - e => Err(Error { + e => Err(ErrorInner { pos: Some(pos), message: format!( @@ -974,7 +1044,7 @@ impl<'ast> Checker<'ast> { box checked_typed_index, )) } - ty => Err(Error { + ty => Err(ErrorInner { pos: Some(pos), message: format!( @@ -989,14 +1059,14 @@ impl<'ast> Checker<'ast> { let ty = checked_assignee.get_type(); match &ty { - Type::Struct(members) => match members.iter().find(|(id, _)| id == member) { + Type::Struct(members) => match members.iter().find(|m| m.id == member) { Some(_) => Ok(TypedAssignee::Member(box checked_assignee, member.into())), - None => Err(Error { + None => Err(ErrorInner { pos: Some(pos), message: format!("{} doesn't have member {}", ty, member), }), }, - ty => Err(Error { + ty => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1014,7 +1084,7 @@ impl<'ast> Checker<'ast> { spread_or_expression: SpreadOrExpression<'ast, T>, module_id: &ModuleId, types: &TypeMap, - ) -> Result>, Error> { + ) -> Result>, ErrorInner> { match spread_or_expression { SpreadOrExpression::Spread(s) => { let pos = s.pos(); @@ -1042,25 +1112,25 @@ impl<'ast> Checker<'ast> { box FieldElementExpression::Number(T::from(i)), ) .into(), - Type::Array(box ty, s) => ArrayExpressionInner::Select( + Type::Array(array_type) => ArrayExpressionInner::Select( box e .clone() - .annotate(Type::Array(box ty.clone(), *s), size), + .annotate(Type::Array(array_type.clone()), size), box FieldElementExpression::Number(T::from(i)), ) - .annotate(ty.clone(), *s) + .annotate(*array_type.ty.clone(), array_type.size) .into(), - Type::Struct(fields) => StructExpressionInner::Select( - box e.clone().annotate(Type::Struct(fields.clone()), size), + Type::Struct(members) => StructExpressionInner::Select( + box e.clone().annotate(Type::Struct(members.clone()), size), box FieldElementExpression::Number(T::from(i)), ) - .annotate(fields.clone()) + .annotate(members.clone()) .into(), }) .collect()), } } - e => Err(Error { + e => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1081,7 +1151,7 @@ impl<'ast> Checker<'ast> { expr: ExpressionNode<'ast, T>, module_id: &ModuleId, types: &TypeMap, - ) -> Result, Error> { + ) -> Result, ErrorInner> { let pos = expr.pos(); match expr.value { @@ -1094,14 +1164,16 @@ impl<'ast> Checker<'ast> { Type::FieldElement => { Ok(FieldElementExpression::Identifier(name.into()).into()) } - Type::Array(ty, size) => Ok(ArrayExpressionInner::Identifier(name.into()) - .annotate(*ty, size) - .into()), + Type::Array(array_type) => { + Ok(ArrayExpressionInner::Identifier(name.into()) + .annotate(*array_type.ty, array_type.size) + .into()) + } Type::Struct(members) => Ok(StructExpressionInner::Identifier(name.into()) .annotate(members) .into()), }, - None => Err(Error { + None => Err(ErrorInner { pos: Some(pos), message: format!("Identifier \"{}\" is undefined", name), }), @@ -1115,7 +1187,7 @@ impl<'ast> Checker<'ast> { (TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => { Ok(FieldElementExpression::Add(box e1, box e2).into()) } - (t1, t2) => Err(Error { + (t1, t2) => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1134,7 +1206,7 @@ impl<'ast> Checker<'ast> { (TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => { Ok(FieldElementExpression::Sub(box e1, box e2).into()) } - (t1, t2) => Err(Error { + (t1, t2) => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1153,7 +1225,7 @@ impl<'ast> Checker<'ast> { (TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => { Ok(FieldElementExpression::Mult(box e1, box e2).into()) } - (t1, t2) => Err(Error { + (t1, t2) => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1172,7 +1244,7 @@ impl<'ast> Checker<'ast> { (TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => { Ok(FieldElementExpression::Div(box e1, box e2).into()) } - (t1, t2) => Err(Error { + (t1, t2) => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1191,7 +1263,7 @@ impl<'ast> Checker<'ast> { (TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => Ok( TypedExpression::FieldElement(FieldElementExpression::Pow(box e1, box e2)), ), - (t1, t2) => Err(Error { + (t1, t2) => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1234,13 +1306,13 @@ impl<'ast> Checker<'ast> { }, _ => unreachable!("types should match here as we checked them explicitly") } - false => Err(Error { + false => Err(ErrorInner { pos: Some(pos), message: format!("{{consequence}} and {{alternative}} in `if/else` expression should have the same type, found {}, {}", consequence_type, alternative_type) }) } } - c => Err(Error { + c => Err(ErrorInner { pos: Some(pos), message: format!( "{{condition}} after `if` should be a boolean, found {}", @@ -1267,12 +1339,11 @@ impl<'ast> Checker<'ast> { // we use type inference to determine the type of the return, so we don't specify it let query = FunctionQuery::new(&fun_id, &arguments_types, &vec![None]); - let candidates = self.find_candidates(&query); + let f = self.find_function(&query); - match candidates.len() { + match f { // the function has to be defined - 1 => { - let f = &candidates[0]; + Some(f) => { // the return count has to be 1 match f.signature.outputs.len() { 1 => match &f.signature.outputs[0] { @@ -1284,6 +1355,14 @@ impl<'ast> Checker<'ast> { arguments_checked, ) .into()), + Type::Boolean => Ok(BooleanExpression::FunctionCall( + FunctionKey { + id: f.id.clone(), + signature: f.signature.clone(), + }, + arguments_checked, + ) + .into()), Type::Struct(members) => Ok(StructExpressionInner::FunctionCall( FunctionKey { id: f.id.clone(), @@ -1293,20 +1372,17 @@ impl<'ast> Checker<'ast> { ) .annotate(members.clone()) .into()), - Type::Array(box ty, size) => { - Ok(ArrayExpressionInner::FunctionCall( - FunctionKey { - id: f.id.clone(), - signature: f.signature.clone(), - }, - arguments_checked, - ) - .annotate(ty.clone(), size.clone()) - .into()) - } - _ => unimplemented!(), + Type::Array(array_type) => Ok(ArrayExpressionInner::FunctionCall( + FunctionKey { + id: f.id.clone(), + signature: f.signature.clone(), + }, + arguments_checked, + ) + .annotate(*array_type.ty.clone(), array_type.size.clone()) + .into()), }, - n => Err(Error { + n => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1316,7 +1392,7 @@ impl<'ast> Checker<'ast> { }), } } - 0 => Err(Error { + None => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1324,9 +1400,6 @@ impl<'ast> Checker<'ast> { fun_id, query ), }), - _ => { - unreachable!("duplicate definition should have been caught before the call") - } } } Expression::Lt(box e1, box e2) => { @@ -1336,7 +1409,7 @@ impl<'ast> Checker<'ast> { (TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => { Ok(BooleanExpression::Lt(box e1, box e2).into()) } - (e1, e2) => Err(Error { + (e1, e2) => Err(ErrorInner { pos: Some(pos), message: format!( "Cannot compare {} of type {} to {} of type {}", @@ -1355,7 +1428,7 @@ impl<'ast> Checker<'ast> { (TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => { Ok(BooleanExpression::Le(box e1, box e2).into()) } - (e1, e2) => Err(Error { + (e1, e2) => Err(ErrorInner { pos: Some(pos), message: format!( "Cannot compare {} of type {} to {} of type {}", @@ -1377,7 +1450,7 @@ impl<'ast> Checker<'ast> { (TypedExpression::Boolean(e1), TypedExpression::Boolean(e2)) => { Ok(BooleanExpression::BoolEq(box e1, box e2).into()) } - (e1, e2) => Err(Error { + (e1, e2) => Err(ErrorInner { pos: Some(pos), message: format!( "Cannot compare {} of type {} to {} of type {}", @@ -1396,7 +1469,7 @@ impl<'ast> Checker<'ast> { (TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => { Ok(BooleanExpression::Ge(box e1, box e2).into()) } - (e1, e2) => Err(Error { + (e1, e2) => Err(ErrorInner { pos: Some(pos), message: format!( "Cannot compare {} of type {} to {} of type {}", @@ -1415,7 +1488,7 @@ impl<'ast> Checker<'ast> { (TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => { Ok(BooleanExpression::Gt(box e1, box e2).into()) } - (e1, e2) => Err(Error { + (e1, e2) => Err(ErrorInner { pos: Some(pos), message: format!( "Cannot compare {} of type {} to {} of type {}", @@ -1449,21 +1522,21 @@ impl<'ast> Checker<'ast> { .unwrap_or(array_size); match (from, to, array_size) { - (f, _, s) if f > s => Err(Error { + (f, _, s) if f > s => Err(ErrorInner { pos: Some(pos), message: format!( "Lower range bound {} is out of array bounds [0, {}]", f, s, ), }), - (_, t, s) if t > s => Err(Error { + (_, t, s) if t > s => Err(ErrorInner { pos: Some(pos), message: format!( "Higher range bound {} is out of array bounds [0, {}]", t, s, ), }), - (f, t, _) if f > t => Err(Error { + (f, t, _) if f > t => Err(ErrorInner { pos: Some(pos), message: format!( "Lower range bound {} is larger than higher range bound {}", @@ -1472,12 +1545,31 @@ impl<'ast> Checker<'ast> { }), (f, t, _) => Ok(ArrayExpressionInner::Value( (f..t) - .map(|i| { - FieldElementExpression::Select( + .map(|i| match inner_type.clone() { + Type::FieldElement => FieldElementExpression::Select( box array.clone(), box FieldElementExpression::Number(T::from(i)), ) - .into() + .into(), + Type::Boolean => BooleanExpression::Select( + box array.clone(), + box FieldElementExpression::Number(T::from(i)), + ) + .into(), + Type::Struct(struct_ty) => { + StructExpressionInner::Select( + box array.clone(), + box FieldElementExpression::Number(T::from(i)), + ) + .annotate(struct_ty) + .into() + } + Type::Array(array_ty) => ArrayExpressionInner::Select( + box array.clone(), + box FieldElementExpression::Number(T::from(i)), + ) + .annotate(*array_ty.ty, array_ty.size) + .into(), }) .collect(), ) @@ -1485,7 +1577,7 @@ impl<'ast> Checker<'ast> { .into()), } } - e => Err(Error { + e => Err(ErrorInner { pos: Some(pos), message: format!( "Cannot access slice of expression {} of type {}", @@ -1504,9 +1596,12 @@ impl<'ast> Checker<'ast> { Type::Boolean => { Ok(BooleanExpression::Select(box a, box i).into()) } - Type::Array(box ty, size) => { + Type::Array(array_type) => { Ok(ArrayExpressionInner::Select(box a, box i) - .annotate(ty.clone(), size.clone()) + .annotate( + *array_type.ty.clone(), + array_type.size.clone(), + ) .into()) } Type::Struct(members) => { @@ -1516,7 +1611,7 @@ impl<'ast> Checker<'ast> { } } } - (a, e) => Err(Error { + (a, e) => Err(ErrorInner { pos: Some(pos), message: format!( "Cannot access element {} on expression of type {}", @@ -1534,11 +1629,7 @@ impl<'ast> Checker<'ast> { match e { TypedExpression::Struct(s) => { // check that the struct has that field and return the type if it does - let ty = s - .ty() - .iter() - .find(|(member_id, _)| member_id == id) - .map(|(_, ty)| ty); + let ty = s.ty().iter().find(|m| m.id == id).map(|m| *m.ty.clone()); match ty { Some(ty) => match ty { @@ -1548,9 +1639,9 @@ impl<'ast> Checker<'ast> { Type::Boolean => { Ok(BooleanExpression::Member(box s, id.to_string()).into()) } - Type::Array(box ty, size) => { + Type::Array(array_type) => { Ok(ArrayExpressionInner::Member(box s.clone(), id.to_string()) - .annotate(ty.clone(), *size) + .annotate(*array_type.ty.clone(), array_type.size) .into()) } Type::Struct(members) => { @@ -1559,13 +1650,13 @@ impl<'ast> Checker<'ast> { .into()) } }, - None => Err(Error { + None => Err(ErrorInner { pos: Some(pos), message: format!("{} doesn't have member {}", s.get_type(), id,), }), } } - e => Err(Error { + e => Err(ErrorInner { pos: Some(pos), message: format!( "Cannot access member {} on expression of type {}", @@ -1594,7 +1685,7 @@ impl<'ast> Checker<'ast> { for e in expressions_checked { let unwrapped_e = match e { TypedExpression::FieldElement(e) => Ok(e), - e => Err(Error { + e => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1621,7 +1712,7 @@ impl<'ast> Checker<'ast> { for e in expressions_checked { let unwrapped_e = match e { TypedExpression::Boolean(e) => Ok(e), - e => Err(Error { + e => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1651,7 +1742,7 @@ impl<'ast> Checker<'ast> { if e.get_type() == ty { Ok(e) } else { - Err(Error { + Err(ErrorInner { pos: Some(pos), message: format!( @@ -1663,7 +1754,7 @@ impl<'ast> Checker<'ast> { }) } } - e => Err(Error { + e => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1693,7 +1784,7 @@ impl<'ast> Checker<'ast> { if e.get_type() == ty { Ok(e) } else { - Err(Error { + Err(ErrorInner { pos: Some(pos), message: format!( @@ -1705,7 +1796,7 @@ impl<'ast> Checker<'ast> { }) } } - e => Err(Error { + e => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1741,7 +1832,7 @@ impl<'ast> Checker<'ast> { // check that we provided the required number of values if members.len() != inline_members.len() { - return Err(Error { + return Err(ErrorInner { pos: Some(pos), message: format!( "Inline struct {} does not match {} : {}", @@ -1762,20 +1853,20 @@ impl<'ast> Checker<'ast> { .collect::>(); let mut result: Vec> = vec![]; - for (member_id, ty) in &members { - match inline_members_map.remove(member_id) { + for member in &members { + match inline_members_map.remove(member.id.as_str()) { Some(value) => { let expression_checked = self.check_expression(value, module_id, &types)?; let checked_type = expression_checked.get_type(); - if checked_type != *ty { - return Err(Error { + if checked_type != *member.ty { + return Err(ErrorInner { pos: Some(pos), message: format!( "Member {} of struct {} has type {}, found {} of type {}", - member_id, + member.id, id.clone(), - ty, + member.ty, expression_checked, checked_type, ), @@ -1785,11 +1876,11 @@ impl<'ast> Checker<'ast> { } } None => { - return Err(Error { + return Err(ErrorInner { pos: Some(pos), message: format!( "Member {} of struct {} : {} not found in value {}", - member_id, + member.id, id.clone(), Type::Struct(members.clone()), Expression::InlineStruct(id.clone(), inline_members), @@ -1810,7 +1901,7 @@ impl<'ast> Checker<'ast> { (TypedExpression::Boolean(e1), TypedExpression::Boolean(e2)) => { Ok(BooleanExpression::And(box e1, box e2).into()) } - (e1, e2) => Err(Error { + (e1, e2) => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1828,7 +1919,7 @@ impl<'ast> Checker<'ast> { (TypedExpression::Boolean(e1), TypedExpression::Boolean(e2)) => { Ok(BooleanExpression::Or(box e1, box e2).into()) } - (e1, e2) => Err(Error { + (e1, e2) => Err(ErrorInner { pos: Some(pos), message: format!("cannot compare {} to {}", e1.get_type(), e2.get_type()), @@ -1839,7 +1930,7 @@ impl<'ast> Checker<'ast> { let e_checked = self.check_expression(e, module_id, &types)?; match e_checked { TypedExpression::Boolean(e) => Ok(BooleanExpression::Not(box e).into()), - e => Err(Error { + e => Err(ErrorInner { pos: Some(pos), message: format!("cannot negate {}", e.get_type()), @@ -1866,7 +1957,7 @@ impl<'ast> Checker<'ast> { }) } - fn find_candidates(&self, query: &FunctionQuery<'ast>) -> Vec> { + fn find_function(&self, query: &FunctionQuery<'ast>) -> Option> { query.match_funcs(&self.functions) } @@ -1897,7 +1988,7 @@ mod tests { #[test] fn element_type_mismatch() { let types = HashMap::new(); - let module_id = String::from(""); + let module_id = "".into(); // [3, true] let a = Expression::InlineArray(vec![ Expression::FieldConstant(Bn128Field::from(3)).mock().into(), @@ -2059,25 +2150,22 @@ mod tests { }; let mut state = State::new( - vec![(String::from("foo"), foo), (String::from("bar"), bar)] + vec![("foo".into(), foo), ("bar".into(), bar)] .into_iter() .collect(), ); let mut checker = Checker::new(); + assert_eq!(checker.check_module(&"bar".into(), &mut state), Ok(())); assert_eq!( - checker.check_module(&String::from("bar"), &mut state), - Ok(()) - ); - assert_eq!( - state.typed_modules.get(&String::from("bar")), + state.typed_modules.get(&PathBuf::from("bar")), Some(&TypedModule { functions: vec![( FunctionKey::with_id("main").signature(Signature::new()), TypedFunctionSymbol::There( FunctionKey::with_id("main").signature(Signature::new()), - "foo".to_string() + "foo".into() ) )] .into_iter() @@ -2111,13 +2199,18 @@ mod tests { imports: vec![], }; - let mut state = State::new(vec![(MODULE_ID.to_string(), module)].into_iter().collect()); + let mut state = State::new( + vec![(PathBuf::from(MODULE_ID).into(), module)] + .into_iter() + .collect(), + ); let mut checker = Checker::new(); assert_eq!( checker - .check_module(&MODULE_ID.to_string(), &mut state) + .check_module(&PathBuf::from(MODULE_ID).into(), &mut state) .unwrap_err()[0] + .inner .message, "foo conflicts with another symbol" ); @@ -2148,22 +2241,26 @@ mod tests { imports: vec![], }; - let mut state = State::new(vec![(MODULE_ID.to_string(), module)].into_iter().collect()); + let mut state = State::new( + vec![(PathBuf::from(MODULE_ID), module)] + .into_iter() + .collect(), + ); let mut checker = Checker::new(); assert_eq!( - checker.check_module(&MODULE_ID.to_string(), &mut state), + checker.check_module(&PathBuf::from(MODULE_ID), &mut state), Ok(()) ); assert!(state .typed_modules - .get(&MODULE_ID.to_string()) + .get(&PathBuf::from(MODULE_ID)) .unwrap() .functions .contains_key(&FunctionKey::with_id("foo").signature(Signature::new()))); assert!(state .typed_modules - .get(&MODULE_ID.to_string()) + .get(&PathBuf::from(MODULE_ID)) .unwrap() .functions .contains_key( @@ -2195,13 +2292,14 @@ mod tests { imports: vec![], }; - let mut state = State::new(vec![(String::from("main"), module)].into_iter().collect()); + let mut state = State::new(vec![("main".into(), module)].into_iter().collect()); let mut checker = Checker::new(); assert_eq!( checker - .check_module(&String::from("main"), &mut state) + .check_module(&"main".into(), &mut state) .unwrap_err()[0] + .inner .message, "foo conflicts with another symbol" ); @@ -2231,13 +2329,14 @@ mod tests { imports: vec![], }; - let mut state = State::new(vec![(String::from("main"), module)].into_iter().collect()); + let mut state = State::new(vec![("main".into(), module)].into_iter().collect()); let mut checker = Checker::new(); assert_eq!( checker - .check_module(&String::from("main"), &mut state) + .check_module(&"main".into(), &mut state) .unwrap_err()[0] + .inner .message, "foo conflicts with another symbol" ); @@ -2267,7 +2366,7 @@ mod tests { SymbolDeclaration { id: "foo", symbol: Symbol::There( - SymbolImport::with_id_in_module("main", "bar".to_string()).mock(), + SymbolImport::with_id_in_module("main", "bar").mock(), ), } .mock(), @@ -2281,7 +2380,7 @@ mod tests { }; let mut state = State::new( - vec![(MODULE_ID.to_string(), main), ("bar".to_string(), bar)] + vec![(PathBuf::from(MODULE_ID), main), ("bar".into(), bar)] .into_iter() .collect(), ); @@ -2289,8 +2388,9 @@ mod tests { let mut checker = Checker::new(); assert_eq!( checker - .check_module(&MODULE_ID.to_string(), &mut state) + .check_module(&PathBuf::from(MODULE_ID), &mut state) .unwrap_err()[0] + .inner .message, "foo conflicts with another symbol" ); @@ -2322,7 +2422,7 @@ mod tests { SymbolDeclaration { id: "foo", symbol: Symbol::There( - SymbolImport::with_id_in_module("main", "bar".to_string()).mock(), + SymbolImport::with_id_in_module("main", "bar").mock(), ), } .mock(), @@ -2331,7 +2431,7 @@ mod tests { }; let mut state = State::new( - vec![(MODULE_ID.to_string(), main), ("bar".to_string(), bar)] + vec![(PathBuf::from(MODULE_ID), main), ("bar".into(), bar)] .into_iter() .collect(), ); @@ -2339,8 +2439,9 @@ mod tests { let mut checker = Checker::new(); assert_eq!( checker - .check_module(&MODULE_ID.to_string(), &mut state) + .check_module(&PathBuf::from(MODULE_ID), &mut state) .unwrap_err()[0] + .inner .message, "foo conflicts with another symbol" ); @@ -2370,14 +2471,14 @@ mod tests { .mock(); let types = HashMap::new(); - let module_id = String::from(""); + let module_id = "".into(); let mut checker = Checker::new(); assert_eq!( checker.check_statement(statement, &module_id, &types), - Err(vec![Error { + Err(vec![ErrorInner { pos: Some((Position::mock(), Position::mock())), - message: "Identifier \"b\" is undefined".to_string() + message: "Identifier \"b\" is undefined".into() }]) ); } @@ -2393,7 +2494,7 @@ mod tests { .mock(); let types = HashMap::new(); - let module_id = String::from(""); + let module_id = "".into(); let mut scope = HashSet::new(); scope.insert(ScopedVariable { @@ -2479,14 +2580,17 @@ mod tests { imports: vec![], }; - let mut state = State::new(vec![(String::from("main"), module)].into_iter().collect()); + let mut state = State::new(vec![("main".into(), module)].into_iter().collect()); let mut checker = Checker::new(); assert_eq!( - checker.check_module(&String::from("main"), &mut state), + checker.check_module(&"main".into(), &mut state), Err(vec![Error { - pos: Some((Position::mock(), Position::mock())), - message: "Identifier \"a\" is undefined".to_string() + inner: ErrorInner { + pos: Some((Position::mock(), Position::mock())), + message: "Identifier \"a\" is undefined".into() + }, + module_id: "main".into() }]) ); } @@ -2594,12 +2698,10 @@ mod tests { imports: vec![], }; - let mut state = State::new(vec![(String::from("main"), module)].into_iter().collect()); + let mut state = State::new(vec![("main".into(), module)].into_iter().collect()); let mut checker = Checker::new(); - assert!(checker - .check_module(&String::from("main"), &mut state) - .is_ok()); + assert!(checker.check_module(&"main".into(), &mut state).is_ok()); } #[test] @@ -2612,8 +2714,8 @@ mod tests { let foo_statements = vec![ Statement::For( absy::Variable::new("i", UnresolvedType::FieldElement.mock()).mock(), - Bn128Field::from(0), - Bn128Field::from(10), + Expression::FieldConstant(Bn128Field::from(0)).mock(), + Expression::FieldConstant(Bn128Field::from(10)).mock(), vec![], ) .mock(), @@ -2636,14 +2738,14 @@ mod tests { .mock(); let types = HashMap::new(); - let module_id = String::from(""); + let module_id = "".into(); let mut checker = Checker::new(); assert_eq!( checker.check_function(foo, &module_id, &types), - Err(vec![Error { + Err(vec![ErrorInner { pos: Some((Position::mock(), Position::mock())), - message: "Identifier \"i\" is undefined".to_string() + message: "Identifier \"i\" is undefined".into() }]) ); } @@ -2670,8 +2772,8 @@ mod tests { let foo_statements = vec![Statement::For( absy::Variable::new("i", UnresolvedType::FieldElement.mock()).mock(), - Bn128Field::from(0), - Bn128Field::from(10), + Expression::FieldConstant(Bn128Field::from(0)).mock(), + Expression::FieldConstant(Bn128Field::from(10)).mock(), for_statements, ) .mock()]; @@ -2686,8 +2788,8 @@ mod tests { let foo_statements_checked = vec![TypedStatement::For( typed_absy::Variable::field_element("i".into()), - Bn128Field::from(0), - Bn128Field::from(10), + FieldElementExpression::Number(Bn128Field::from(0)), + FieldElementExpression::Number(Bn128Field::from(10)), for_statements_checked, )]; @@ -2711,7 +2813,7 @@ mod tests { }; let types = HashMap::new(); - let module_id = String::from(""); + let module_id = "".into(); let mut checker = Checker::new(); assert_eq!( @@ -2760,16 +2862,16 @@ mod tests { .mock(); let types = HashMap::new(); - let module_id = String::from(""); + let module_id = "".into(); let mut checker = new_with_args(HashSet::new(), 0, functions); assert_eq!( checker.check_function(bar, &module_id, &types), - Err(vec![Error { + Err(vec![ErrorInner { pos: Some((Position::mock(), Position::mock())), message: "Function definition for function foo with signature () -> (field) not found." - .to_string() + .into() }]) ); } @@ -2808,15 +2910,15 @@ mod tests { .mock(); let types = HashMap::new(); - let module_id = String::from(""); + let module_id = "".into(); let mut checker = new_with_args(HashSet::new(), 0, functions); assert_eq!( checker.check_function(bar, &module_id, &types), - Err(vec![Error { + Err(vec![ErrorInner { pos: Some((Position::mock(), Position::mock())), message: "Function definition for function foo with signature () -> (_) not found." - .to_string() + .into() }]) ); } @@ -2849,17 +2951,17 @@ mod tests { .mock(); let types = HashMap::new(); - let module_id = String::from(""); + let module_id = "".into(); let mut checker = new_with_args(HashSet::new(), 0, HashSet::new()); assert_eq!( checker.check_function(bar, &module_id, &types), - Err(vec![Error { + Err(vec![ErrorInner { pos: Some((Position::mock(), Position::mock())), message: "Function definition for function foo with signature () -> (field) not found." - .to_string() + .into() }]) ); } @@ -2953,14 +3055,224 @@ mod tests { imports: vec![], }; - let mut state = State::new(vec![(String::from("main"), module)].into_iter().collect()); + let mut state = State::new(vec![("main".into(), module)].into_iter().collect()); let mut checker = new_with_args(HashSet::new(), 0, HashSet::new()); assert_eq!( - checker.check_module(&String::from("main"), &mut state), + checker.check_module(&"main".into(), &mut state), Err(vec![Error { - pos: Some((Position::mock(), Position::mock())), - message: "Identifier \"x\" is undefined".to_string() + inner: ErrorInner { + pos: Some((Position::mock(), Position::mock())), + message: "Identifier \"x\" is undefined".into() + }, + module_id: "main".into() + }]) + ); + } + + #[test] + fn undeclared_variables() { + // def foo() -> (field, field): + // return 1, 2 + // def main(): + // a, b = foo() + // return 1 + // should fail + + let foo_statements: Vec> = vec![Statement::Return( + ExpressionList { + expressions: vec![ + Expression::FieldConstant(Bn128Field::from(1)).mock(), + Expression::FieldConstant(Bn128Field::from(2)).mock(), + ], + } + .mock(), + ) + .mock()]; + + let foo = Function { + arguments: vec![], + statements: foo_statements, + signature: UnresolvedSignature { + inputs: vec![], + outputs: vec![ + UnresolvedType::FieldElement.mock(), + UnresolvedType::FieldElement.mock(), + ], + }, + } + .mock(); + + let main_statements: Vec> = vec![ + Statement::MultipleDefinition( + vec![ + Assignee::Identifier("a").mock(), + Assignee::Identifier("b").mock(), + ], + Expression::FunctionCall("foo", vec![]).mock(), + ) + .mock(), + Statement::Return( + ExpressionList { + expressions: vec![], + } + .mock(), + ) + .mock(), + ]; + + let main = Function { + arguments: vec![], + statements: main_statements, + signature: UnresolvedSignature { + inputs: vec![], + outputs: vec![], + }, + } + .mock(); + + let module = Module { + symbols: vec![ + SymbolDeclaration { + id: "foo", + symbol: Symbol::HereFunction(foo), + } + .mock(), + SymbolDeclaration { + id: "main", + symbol: Symbol::HereFunction(main), + } + .mock(), + ], + imports: vec![], + }; + + let mut state = State::new(vec![("main".into(), module)].into_iter().collect()); + + let mut checker = new_with_args(HashSet::new(), 0, HashSet::new()); + assert_eq!( + checker.check_module(&"main".into(), &mut state), + Err(vec![ + Error { + inner: ErrorInner { + pos: Some((Position::mock(), Position::mock())), + message: "Variable `a` is undeclared".into() + }, + module_id: "main".into() + }, + Error { + inner: ErrorInner { + pos: Some((Position::mock(), Position::mock())), + message: "Variable `b` is undeclared".into() + }, + module_id: "main".into() + } + ]) + ); + } + + #[test] + fn assign_to_non_variable() { + // def foo() -> (field): + // return 1 + // def main(): + // field[1] a = [0] + // a[0] = foo() + // return + // should fail + + let foo_statements: Vec> = vec![Statement::Return( + ExpressionList { + expressions: vec![Expression::FieldConstant(Bn128Field::from(1)).mock()], + } + .mock(), + ) + .mock()]; + + let foo = Function { + arguments: vec![], + statements: foo_statements, + signature: UnresolvedSignature { + inputs: vec![], + outputs: vec![UnresolvedType::FieldElement.mock()], + }, + } + .mock(); + + let main_statements: Vec> = vec![ + Statement::Declaration( + absy::Variable::new( + "a", + UnresolvedType::array(UnresolvedType::FieldElement.mock(), 1).mock(), + ) + .mock(), + ) + .mock(), + Statement::Definition( + Assignee::Identifier("a".into()).mock(), + Expression::InlineArray(vec![absy::SpreadOrExpression::Expression( + Expression::FieldConstant(Bn128Field::from(0)).mock(), + )]) + .mock(), + ) + .mock(), + Statement::MultipleDefinition( + vec![Assignee::Select( + box Assignee::Identifier("a").mock(), + box RangeOrExpression::Expression( + absy::Expression::FieldConstant(Bn128Field::from(0)).mock(), + ), + ) + .mock()], + Expression::FunctionCall("foo", vec![]).mock(), + ) + .mock(), + Statement::Return( + ExpressionList { + expressions: vec![], + } + .mock(), + ) + .mock(), + ]; + + let main = Function { + arguments: vec![], + statements: main_statements, + signature: UnresolvedSignature { + inputs: vec![], + outputs: vec![], + }, + } + .mock(); + + let module = Module { + symbols: vec![ + SymbolDeclaration { + id: "foo", + symbol: Symbol::HereFunction(foo), + } + .mock(), + SymbolDeclaration { + id: "main", + symbol: Symbol::HereFunction(main), + } + .mock(), + ], + imports: vec![], + }; + + let mut state = State::new(vec![("main".into(), module)].into_iter().collect()); + + let mut checker = new_with_args(HashSet::new(), 0, HashSet::new()); + assert_eq!( + checker.check_module(&"main".into(), &mut state), + Err(vec![Error { + inner: ErrorInner { + pos: Some((Position::mock(), Position::mock())), + message: "Only assignment to identifiers is supported, found a[0]".into() + }, + module_id: "main".into() }]) ); } @@ -2987,16 +3299,16 @@ mod tests { .mock(); let types = HashMap::new(); - let module_id = String::from(""); + let module_id = "".into(); let mut checker = new_with_args(HashSet::new(), 0, HashSet::new()); assert_eq!( checker.check_function(bar, &module_id, &types), - Err(vec![Error { + Err(vec![ErrorInner { pos: Some((Position::mock(), Position::mock())), message: "Function definition for function foo with signature () -> (_) not found." - .to_string() + .into() }]) ); } @@ -3031,14 +3343,14 @@ mod tests { .mock(); let types = HashMap::new(); - let module_id = String::from(""); + let module_id = "".into(); let mut checker = new_with_args(HashSet::new(), 0, HashSet::new()); assert_eq!( checker.check_function(bar, &module_id, &types), - Err(vec![Error { + Err(vec![ErrorInner { pos: Some((Position::mock(), Position::mock())), - message: "Identifier \"a\" is undefined".to_string() + message: "Identifier \"a\" is undefined".into() }]) ); } @@ -3136,7 +3448,7 @@ mod tests { }; let types = HashMap::new(); - let module_id = String::from(""); + let module_id = "".into(); let mut checker = new_with_args(HashSet::new(), 0, functions); assert_eq!( @@ -3216,18 +3528,19 @@ mod tests { }; let program = Program { - modules: vec![(String::from("main"), main_module)] - .into_iter() - .collect(), - main: String::from("main"), + modules: vec![("main".into(), main_module)].into_iter().collect(), + main: "main".into(), }; let mut checker = Checker::new(); assert_eq!( checker.check_program(program), Err(vec![Error { - pos: None, - message: "Only one main function allowed, found 2".to_string() + inner: ErrorInner { + pos: None, + message: "Only one main function allowed, found 2".into() + }, + module_id: "main".into() }]) ); } @@ -3240,17 +3553,9 @@ mod tests { // should fail let types = HashMap::new(); - let module_id = String::from(""); + let module_id = "".into(); let mut checker = Checker::new(); - let _: Result, Vec> = checker.check_statement( - Statement::Declaration( - absy::Variable::new("a", UnresolvedType::FieldElement.mock()).mock(), - ) - .mock(), - &module_id, - &types, - ); - let s2_checked: Result, Vec> = checker.check_statement( + let _: Result, Vec> = checker.check_statement( Statement::Declaration( absy::Variable::new("a", UnresolvedType::FieldElement.mock()).mock(), ) @@ -3258,11 +3563,20 @@ mod tests { &module_id, &types, ); + let s2_checked: Result, Vec> = checker + .check_statement( + Statement::Declaration( + absy::Variable::new("a", UnresolvedType::FieldElement.mock()).mock(), + ) + .mock(), + &module_id, + &types, + ); assert_eq!( s2_checked, - Err(vec![Error { + Err(vec![ErrorInner { pos: Some((Position::mock(), Position::mock())), - message: "Duplicate declaration for variable named a".to_string() + message: "Duplicate declaration for variable named a".into() }]) ); } @@ -3275,10 +3589,10 @@ mod tests { // should fail let types = HashMap::new(); - let module_id = String::from(""); + let module_id = "".into(); let mut checker = Checker::new(); - let _: Result, Vec> = checker.check_statement( + let _: Result, Vec> = checker.check_statement( Statement::Declaration( absy::Variable::new("a", UnresolvedType::FieldElement.mock()).mock(), ) @@ -3286,17 +3600,20 @@ mod tests { &module_id, &types, ); - let s2_checked: Result, Vec> = checker.check_statement( - Statement::Declaration(absy::Variable::new("a", UnresolvedType::Boolean.mock()).mock()) + let s2_checked: Result, Vec> = checker + .check_statement( + Statement::Declaration( + absy::Variable::new("a", UnresolvedType::Boolean.mock()).mock(), + ) .mock(), - &module_id, - &types, - ); + &module_id, + &types, + ); assert_eq!( s2_checked, - Err(vec![Error { + Err(vec![ErrorInner { pos: Some((Position::mock(), Position::mock())), - message: "Duplicate declaration for variable named a".to_string() + message: "Duplicate declaration for variable named a".into() }]) ); } @@ -3304,11 +3621,11 @@ mod tests { mod structs { use super::*; - /// helper function to create a module at location "" with a single symbol `Foo { foo: field }` + /// solver function to create a module at location "" with a single symbol `Foo { foo: field }` fn create_module_with_foo( s: StructType<'static>, ) -> (Checker<'static>, State<'static, Bn128Field>) { - let module_id = "".to_string(); + let module_id: PathBuf = "".into(); let module: Module = Module { imports: vec![], @@ -3335,7 +3652,7 @@ mod tests { #[test] fn empty_def() { // an empty struct should be allowed to be defined - let module_id = "".to_string(); + let module_id = "".into(); let types = HashMap::new(); let declaration = StructType { fields: vec![] }.mock(); @@ -3350,7 +3667,7 @@ mod tests { #[test] fn valid_def() { // a valid struct should be allowed to be defined - let module_id = "".to_string(); + let module_id = "".into(); let types = HashMap::new(); let declaration = StructType { fields: vec![ @@ -3369,8 +3686,8 @@ mod tests { .mock(); let expected_type = Type::Struct(vec![ - ("foo".to_string(), Type::FieldElement), - ("bar".to_string(), Type::Boolean), + StructMember::new("foo".into(), Type::FieldElement), + StructMember::new("bar".into(), Type::Boolean), ]); assert_eq!( @@ -3382,7 +3699,7 @@ mod tests { #[test] fn preserve_order() { // two structs with inverted members are not equal - let module_id = "".to_string(); + let module_id = "".into(); let types = HashMap::new(); let declaration0 = StructType { @@ -3417,20 +3734,16 @@ mod tests { } .mock(); - assert!( - Checker::new().check_struct_type_declaration(declaration0, &module_id, &types) - != Checker::new().check_struct_type_declaration( - declaration1, - &module_id, - &types - ) + assert_ne!( + Checker::new().check_struct_type_declaration(declaration0, &module_id, &types), + Checker::new().check_struct_type_declaration(declaration1, &module_id, &types) ); } #[test] fn duplicate_member_def() { // definition of a struct with a duplicate member should be rejected - let module_id = "".to_string(); + let module_id = "".into(); let types = HashMap::new(); let declaration = StructType { @@ -3465,7 +3778,7 @@ mod tests { // struct Foo = { foo: field } // struct Bar = { foo: Foo } - let module_id = "".to_string(); + let module_id: PathBuf = "".into(); let module: Module = Module { imports: vec![], @@ -3490,7 +3803,7 @@ mod tests { StructType { fields: vec![StructField { id: "foo", - ty: UnresolvedType::User("Foo".to_string()).mock(), + ty: UnresolvedType::User("Foo".into()).mock(), } .mock()], } @@ -3507,13 +3820,13 @@ mod tests { assert_eq!( state .types - .get(&"".to_string()) + .get(&module_id) .unwrap() .get(&"Bar".to_string()) .unwrap(), - &Type::Struct(vec![( - "foo".to_string(), - Type::Struct(vec![("foo".to_string(), Type::FieldElement)]) + &Type::Struct(vec![StructMember::new( + "foo".into(), + Type::Struct(vec![StructMember::new("foo".into(), Type::FieldElement)]) )]) ); } @@ -3524,7 +3837,7 @@ mod tests { // struct Bar = { foo: Foo } - let module_id = "".to_string(); + let module_id: PathBuf = "".into(); let module: Module = Module { imports: vec![], @@ -3534,7 +3847,7 @@ mod tests { StructType { fields: vec![StructField { id: "foo", - ty: UnresolvedType::User("Foo".to_string()).mock(), + ty: UnresolvedType::User("Foo".into()).mock(), } .mock()], } @@ -3555,7 +3868,7 @@ mod tests { // struct Foo = { foo: Foo } - let module_id = "".to_string(); + let module_id: PathBuf = "".into(); let module: Module = Module { imports: vec![], @@ -3565,7 +3878,7 @@ mod tests { StructType { fields: vec![StructField { id: "foo", - ty: UnresolvedType::User("Foo".to_string()).mock(), + ty: UnresolvedType::User("Foo".into()).mock(), } .mock()], } @@ -3587,7 +3900,7 @@ mod tests { // struct Foo = { bar: Bar } // struct Bar = { foo: Foo } - let module_id = "".to_string(); + let module_id: PathBuf = "".into(); let module: Module = Module { imports: vec![], @@ -3598,7 +3911,7 @@ mod tests { StructType { fields: vec![StructField { id: "bar", - ty: UnresolvedType::User("Bar".to_string()).mock(), + ty: UnresolvedType::User("Bar".into()).mock(), } .mock()], } @@ -3612,7 +3925,7 @@ mod tests { StructType { fields: vec![StructField { id: "foo", - ty: UnresolvedType::User("Foo".to_string()).mock(), + ty: UnresolvedType::User("Foo".into()).mock(), } .mock()], } @@ -3652,18 +3965,21 @@ mod tests { assert_eq!( checker.check_type( - UnresolvedType::User("Foo".to_string()).mock(), - &MODULE_ID.to_string(), + UnresolvedType::User("Foo".into()).mock(), + &PathBuf::from(MODULE_ID).into(), &state.types ), - Ok(Type::Struct(vec![("foo".to_string(), Type::FieldElement)])) + Ok(Type::Struct(vec![StructMember::new( + "foo".into(), + Type::FieldElement + )])) ); assert_eq!( checker .check_type( - UnresolvedType::User("Bar".to_string()).mock(), - &MODULE_ID.to_string(), + UnresolvedType::User("Bar".into()).mock(), + &PathBuf::from(MODULE_ID).into(), &state.types ) .unwrap_err() @@ -3689,21 +4005,19 @@ mod tests { assert_eq!( checker.check_parameter( absy::Parameter { - id: absy::Variable::new( - "a", - UnresolvedType::User("Foo".to_string()).mock(), - ) - .mock(), + id: + absy::Variable::new("a", UnresolvedType::User("Foo".into()).mock(),) + .mock(), private: true, } .mock(), - &MODULE_ID.to_string(), + &PathBuf::from(MODULE_ID).into(), &state.types, ), Ok(Parameter { id: Variable::with_id_and_type( "a".into(), - Type::Struct(vec![("foo".to_string(), Type::FieldElement)]) + Type::Struct(vec![StructMember::new("foo".into(), Type::FieldElement)]) ), private: true }) @@ -3715,13 +4029,13 @@ mod tests { absy::Parameter { id: absy::Variable::new( "a", - UnresolvedType::User("Bar".to_string()).mock(), + UnresolvedType::User("Bar".into()).mock(), ) .mock(), private: true, } .mock(), - &MODULE_ID.to_string(), + &PathBuf::from(MODULE_ID).into(), &state.types, ) .unwrap_err()[0] @@ -3747,19 +4061,16 @@ mod tests { assert_eq!( checker.check_statement::( Statement::Declaration( - absy::Variable::new( - "a", - UnresolvedType::User("Foo".to_string()).mock(), - ) - .mock() + absy::Variable::new("a", UnresolvedType::User("Foo".into()).mock(),) + .mock() ) .mock(), - &MODULE_ID.to_string(), + &PathBuf::from(MODULE_ID).into(), &state.types, ), Ok(TypedStatement::Declaration(Variable::with_id_and_type( "a".into(), - Type::Struct(vec![("foo".to_string(), Type::FieldElement)]) + Type::Struct(vec![StructMember::new("foo".into(), Type::FieldElement)]) ))) ); @@ -3769,13 +4080,13 @@ mod tests { absy::Parameter { id: absy::Variable::new( "a", - UnresolvedType::User("Bar".to_string()).mock(), + UnresolvedType::User("Bar".into()).mock(), ) .mock(), private: true, } .mock(), - &MODULE_ID.to_string(), + &PathBuf::from(MODULE_ID).into(), &state.types, ) .unwrap_err()[0] @@ -3808,7 +4119,7 @@ mod tests { checker.check_expression( Expression::Member( box Expression::InlineStruct( - "Foo".to_string(), + "Foo".into(), vec![( "foo", Expression::FieldConstant(Bn128Field::from(42)).mock() @@ -3818,7 +4129,7 @@ mod tests { "foo".into() ) .mock(), - &MODULE_ID.to_string(), + &PathBuf::from(MODULE_ID).into(), &state.types ), Ok(FieldElementExpression::Member( @@ -3826,8 +4137,8 @@ mod tests { Bn128Field::from(42) ) .into()]) - .annotate(vec![("foo".to_string(), Type::FieldElement)]), - "foo".to_string() + .annotate(vec![StructMember::new("foo".into(), Type::FieldElement)]), + "foo".into() ) .into()) ); @@ -3853,7 +4164,7 @@ mod tests { .check_expression( Expression::Member( box Expression::InlineStruct( - "Foo".to_string(), + "Foo".into(), vec![( "foo", Expression::FieldConstant(Bn128Field::from(42)).mock() @@ -3863,7 +4174,7 @@ mod tests { "bar".into() ) .mock(), - &MODULE_ID.to_string(), + &PathBuf::from(MODULE_ID).into(), &state.types ) .unwrap_err() @@ -3893,14 +4204,14 @@ mod tests { checker .check_expression( Expression::InlineStruct( - "Bar".to_string(), + "Bar".into(), vec![( "foo", Expression::FieldConstant(Bn128Field::from(42)).mock() )] ) .mock(), - &MODULE_ID.to_string(), + &PathBuf::from(MODULE_ID).into(), &state.types ) .unwrap_err() @@ -3934,7 +4245,7 @@ mod tests { assert_eq!( checker.check_expression( Expression::InlineStruct( - "Foo".to_string(), + "Foo".into(), vec![ ( "foo", @@ -3944,7 +4255,7 @@ mod tests { ] ) .mock(), - &MODULE_ID.to_string(), + &PathBuf::from(MODULE_ID).into(), &state.types ), Ok(StructExpressionInner::Value(vec![ @@ -3952,8 +4263,8 @@ mod tests { BooleanExpression::Value(true).into() ]) .annotate(vec![ - ("foo".to_string(), Type::FieldElement), - ("bar".to_string(), Type::Boolean) + StructMember::new("foo".into(), Type::FieldElement), + StructMember::new("bar".into(), Type::Boolean) ]) .into()) ); @@ -3984,7 +4295,7 @@ mod tests { assert_eq!( checker.check_expression( Expression::InlineStruct( - "Foo".to_string(), + "Foo".into(), vec![ ("bar", Expression::BooleanConstant(true).mock()), ( @@ -3994,7 +4305,7 @@ mod tests { ] ) .mock(), - &MODULE_ID.to_string(), + &PathBuf::from(MODULE_ID).into(), &state.types ), Ok(StructExpressionInner::Value(vec![ @@ -4002,8 +4313,8 @@ mod tests { BooleanExpression::Value(true).into() ]) .annotate(vec![ - ("foo".to_string(), Type::FieldElement), - ("bar".to_string(), Type::Boolean) + StructMember::new("foo".into(), Type::FieldElement), + StructMember::new("bar".into(), Type::Boolean) ]) .into()) ); @@ -4011,7 +4322,7 @@ mod tests { #[test] fn subset() { - // a A value cannot be defined with A as id but members being a subset of the declaration + // a A value cannot be defined with A as id if members are a subset of the declaration // struct Foo = { foo: field, bar: bool } // Foo foo = Foo { foo: 42 } @@ -4035,14 +4346,14 @@ mod tests { checker .check_expression( Expression::InlineStruct( - "Foo".to_string(), + "Foo".into(), vec![( "foo", Expression::FieldConstant(Bn128Field::from(42)).mock() )] ) .mock(), - &MODULE_ID.to_string(), + &PathBuf::from(MODULE_ID).into(), &state.types ) .unwrap_err() @@ -4053,8 +4364,8 @@ mod tests { #[test] fn invalid() { - // a A value cannot be defined with A as id but members being different ids than the declaration - // a A value cannot be defined with A as id but members being different types than the declaration + // a A value cannot be defined with A as id if members are different ids than the declaration + // a A value cannot be defined with A as id if members are different types than the declaration // struct Foo = { foo: field, bar: bool } // Foo { foo: 42, baz: bool } // error @@ -4079,7 +4390,7 @@ mod tests { checker .check_expression( Expression::InlineStruct( - "Foo".to_string(), + "Foo".into(), vec![( "baz", Expression::BooleanConstant(true).mock() @@ -4089,7 +4400,7 @@ mod tests { )] ) .mock(), - &MODULE_ID.to_string(), + &PathBuf::from(MODULE_ID).into(), &state.types ).unwrap_err() .message, @@ -4100,7 +4411,7 @@ mod tests { checker .check_expression( Expression::InlineStruct( - "Foo".to_string(), + "Foo".into(), vec![ ( "bar", @@ -4113,7 +4424,7 @@ mod tests { ] ) .mock(), - &MODULE_ID.to_string(), + &PathBuf::from(MODULE_ID).into(), &state.types ) .unwrap_err() @@ -4133,7 +4444,7 @@ mod tests { let a = Assignee::Identifier::("a").mock(); let types = HashMap::new(); - let module_id = String::from(""); + let module_id = "".into(); let mut checker: Checker = Checker::new(); checker .check_statement::( @@ -4167,7 +4478,7 @@ mod tests { .mock(); let types = HashMap::new(); - let module_id = String::from(""); + let module_id = "".into(); let mut checker: Checker = Checker::new(); checker @@ -4216,7 +4527,7 @@ mod tests { .mock(); let types = HashMap::new(); - let module_id = String::from(""); + let module_id = "".into(); let mut checker: Checker = Checker::new(); checker .check_statement::( diff --git a/zokrates_core/src/solvers/mod.rs b/zokrates_core/src/solvers/mod.rs new file mode 100644 index 00000000..74331d18 --- /dev/null +++ b/zokrates_core/src/solvers/mod.rs @@ -0,0 +1,151 @@ +use std::fmt; +use zokrates_embed::generate_sha256_round_witness; +use zokrates_field::Field; + +#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, Hash, Eq)] +pub enum Solver { + ConditionEq, + Bits(usize), + Div, + Sha256Round, +} + +impl fmt::Display for Solver { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self) + } +} + +impl Signed for Solver { + fn get_signature(&self) -> (usize, usize) { + match self { + Solver::ConditionEq => (1, 2), + Solver::Bits(bit_width) => (1, *bit_width), + Solver::Div => (2, 1), + Solver::Sha256Round => (768, 26935), + } + } +} + +impl Executable for Solver { + fn execute(&self, inputs: &Vec) -> Result, String> { + let (expected_input_count, expected_output_count) = self.get_signature(); + assert!(inputs.len() == expected_input_count); + + let res = match self { + Solver::ConditionEq => match inputs[0].is_zero() { + true => vec![T::zero(), T::one()], + false => vec![T::one(), T::one() / inputs[0].clone()], + }, + Solver::Bits(bit_width) => { + let mut num = inputs[0].clone(); + let mut res = vec![]; + + for i in (0..*bit_width).rev() { + if T::from(2).pow(i) <= num { + num = num - T::from(2).pow(i); + res.push(T::one()); + } else { + res.push(T::zero()); + } + } + assert_eq!(num, T::zero()); + res + } + Solver::Div => vec![inputs[0].clone() / inputs[1].clone()], + Solver::Sha256Round => { + let i = &inputs[0..512]; + let h = &inputs[512..]; + let i: Vec<_> = i.iter().map(|x| x.clone().into_bellman()).collect(); + let h: Vec<_> = h.iter().map(|x| x.clone().into_bellman()).collect(); + assert!(h.len() == 256); + generate_sha256_round_witness::(&i, &h) + .into_iter() + .map(|x| T::from_bellman(x)) + .collect() + } + }; + + assert_eq!(res.len(), expected_output_count); + + Ok(res) + } +} + +impl Solver { + pub fn bits(width: usize) -> Self { + Solver::Bits(width) + } +} + +pub trait Executable: Signed { + fn execute(&self, inputs: &Vec) -> Result, String>; +} + +pub trait Signed { + fn get_signature(&self) -> (usize, usize); +} + +#[cfg(test)] +mod tests { + use super::*; + use zokrates_field::Bn128Field; + + mod eq_condition { + + // Wanted: (Y = (X != 0) ? 1 : 0) + // # Y = if X == 0 then 0 else 1 fi + // # M = if X == 0 then 1 else 1/X fi + + use super::*; + + #[test] + fn execute() { + let cond_eq = Solver::ConditionEq; + let inputs = vec![0]; + let r = cond_eq + .execute(&inputs.iter().map(|&i| Bn128Field::from(i)).collect()) + .unwrap(); + let res: Vec = vec![0, 1].iter().map(|&i| Bn128Field::from(i)).collect(); + assert_eq!(r, &res[..]); + } + + #[test] + fn execute_non_eq() { + let cond_eq = Solver::ConditionEq; + let inputs = vec![1]; + let r = cond_eq + .execute(&inputs.iter().map(|&i| Bn128Field::from(i)).collect()) + .unwrap(); + let res: Vec = vec![1, 1].iter().map(|&i| Bn128Field::from(i)).collect(); + assert_eq!(r, &res[..]); + } + } + + #[test] + fn bits_of_one() { + let inputs = vec![Bn128Field::from(1)]; + let res = Solver::Bits(Bn128Field::get_required_bits()) + .execute(&inputs) + .unwrap(); + assert_eq!(res[253], Bn128Field::from(1)); + for i in 0..252 { + assert_eq!(res[i], Bn128Field::from(0)); + } + } + + #[test] + fn bits_of_42() { + let inputs = vec![Bn128Field::from(42)]; + let res = Solver::Bits(Bn128Field::get_required_bits()) + .execute(&inputs) + .unwrap(); + assert_eq!(res[253], Bn128Field::from(0)); + assert_eq!(res[252], Bn128Field::from(1)); + assert_eq!(res[251], Bn128Field::from(0)); + assert_eq!(res[250], Bn128Field::from(1)); + assert_eq!(res[249], Bn128Field::from(0)); + assert_eq!(res[248], Bn128Field::from(1)); + assert_eq!(res[247], Bn128Field::from(0)); + } +} diff --git a/zokrates_core/src/static_analysis/constrain_inputs.rs b/zokrates_core/src/static_analysis/constrain_inputs.rs index 3125ad65..a0729f09 100644 --- a/zokrates_core/src/static_analysis/constrain_inputs.rs +++ b/zokrates_core/src/static_analysis/constrain_inputs.rs @@ -83,14 +83,20 @@ impl<'ast, T: Field> InputConstrainer<'ast, T> { } } TypedExpression::Struct(s) => { - for (id, ty) in s.ty() { - let e = match ty { + for member in s.ty() { + let e = match *member.ty { Type::FieldElement => { - FieldElementExpression::member(s.clone(), id.clone()).into() + FieldElementExpression::member(s.clone(), member.id.clone()).into() + } + Type::Boolean => { + BooleanExpression::member(s.clone(), member.id.clone()).into() + } + Type::Array(..) => { + ArrayExpression::member(s.clone(), member.id.clone()).into() + } + Type::Struct(..) => { + StructExpression::member(s.clone(), member.id.clone()).into() } - Type::Boolean => BooleanExpression::member(s.clone(), id.clone()).into(), - Type::Array(..) => ArrayExpression::member(s.clone(), id.clone()).into(), - Type::Struct(..) => StructExpression::member(s.clone(), id.clone()).into(), }; self.constrain_expression(e); @@ -101,25 +107,6 @@ impl<'ast, T: Field> InputConstrainer<'ast, T> { } impl<'ast, T: Field> Folder<'ast, T> for InputConstrainer<'ast, T> { - fn fold_parameter(&mut self, p: Parameter<'ast>) -> Parameter<'ast> { - let v = p.id.clone(); - - let e = match v.get_type() { - Type::FieldElement => FieldElementExpression::Identifier(v.id).into(), - Type::Boolean => BooleanExpression::Identifier(v.id).into(), - Type::Struct(members) => StructExpressionInner::Identifier(v.id) - .annotate(members) - .into(), - Type::Array(box ty, size) => ArrayExpressionInner::Identifier(v.id) - .annotate(ty, size) - .into(), - }; - - self.constrain_expression(e); - - p - } - fn fold_function(&mut self, f: TypedFunction<'ast, T>) -> TypedFunction<'ast, T> { TypedFunction { arguments: f @@ -131,4 +118,23 @@ impl<'ast, T: Field> Folder<'ast, T> for InputConstrainer<'ast, T> { ..f } } + + fn fold_parameter(&mut self, p: Parameter<'ast>) -> Parameter<'ast> { + let v = p.id.clone(); + + let e = match v.get_type() { + Type::FieldElement => FieldElementExpression::Identifier(v.id).into(), + Type::Boolean => BooleanExpression::Identifier(v.id).into(), + Type::Struct(members) => StructExpressionInner::Identifier(v.id) + .annotate(members) + .into(), + Type::Array(array_type) => ArrayExpressionInner::Identifier(v.id) + .annotate((*array_type.ty).clone(), array_type.size) + .into(), + }; + + self.constrain_expression(e); + + p + } } diff --git a/zokrates_core/src/static_analysis/flat_propagation.rs b/zokrates_core/src/static_analysis/flat_propagation.rs index a8cd184c..095cca5e 100644 --- a/zokrates_core/src/static_analysis/flat_propagation.rs +++ b/zokrates_core/src/static_analysis/flat_propagation.rs @@ -5,7 +5,6 @@ //! @date 2018 use crate::flat_absy::*; -use crate::helpers::DirectiveStatement; use std::collections::HashMap; use zokrates_field::Field; @@ -74,7 +73,7 @@ impl FlatStatement { e1.propagate(constants), e2.propagate(constants), )), - FlatStatement::Directive(d) => Some(FlatStatement::Directive(DirectiveStatement { + FlatStatement::Directive(d) => Some(FlatStatement::Directive(FlatDirective { inputs: d .inputs .into_iter() diff --git a/zokrates_core/src/static_analysis/inline.rs b/zokrates_core/src/static_analysis/inline.rs index 7b4dee6d..a85e8105 100644 --- a/zokrates_core/src/static_analysis/inline.rs +++ b/zokrates_core/src/static_analysis/inline.rs @@ -5,7 +5,7 @@ //! @date 2019 //! Start from the `main` function in the `main` module and inline all calls except those to flat embeds -//! The resulting program has a single module, where we define a function for each flat embed, and replace function calls to the embeds found +//! The resulting program has a single module, where we define a function for each flat embed and replace the function calls with the embeds found //! during inlining by calls to these functions, to be resolved during flattening. //! The resulting program has a single module of the form @@ -17,31 +17,63 @@ //! where any call in `main` must be to `_SHA_256_ROUND` or `_UNPACK` use std::collections::HashMap; -use typed_absy::types::{FunctionKey, MemberId, Type}; +use typed_absy::types::{FunctionKey, StructMember, Type}; use typed_absy::{folder::*, *}; use zokrates_field::Field; +#[derive(Debug, PartialEq, Eq, Hash, Clone)] +struct Location<'ast> { + module: TypedModuleId, + key: FunctionKey<'ast>, +} + +impl<'ast> Location<'ast> { + fn module(&self) -> &TypedModuleId { + &self.module + } +} + +type CallCache<'ast, T> = HashMap< + Location<'ast>, + HashMap< + FunctionKey<'ast>, + HashMap>, Vec>>, + >, +>; + /// An inliner #[derive(Debug)] pub struct Inliner<'ast, T: Field> { - modules: TypedModules<'ast, T>, // the modules to look for functions in when inlining - module_id: TypedModuleId, // the current module we're visiting - statement_buffer: Vec>, // a buffer of statements to be added to the inlined statements - stack: Vec<(String, FunctionKey<'ast>, usize)>, // the current call stack - call_count: HashMap<(String, FunctionKey<'ast>), usize>, // the call count for each function + /// the modules in which to look for functions when inlining + modules: TypedModules<'ast, T>, + /// the current module we're visiting + location: Location<'ast>, + /// a buffer of statements to be added to the inlined statements + statement_buffer: Vec>, + /// the current call stack + stack: Vec<(TypedModuleId, FunctionKey<'ast>, usize)>, + /// the call count for each function + call_count: HashMap<(TypedModuleId, FunctionKey<'ast>), usize>, + /// the cache for memoization: for each function body, tracks function calls + call_cache: CallCache<'ast, T>, } impl<'ast, T: Field> Inliner<'ast, T> { - fn with_modules_and_module_id>( + fn with_modules_and_module_id_and_key>( modules: TypedModules<'ast, T>, module_id: S, + key: FunctionKey<'ast>, ) -> Self { Inliner { modules, - module_id: module_id.into(), + location: Location { + module: module_id.into(), + key, + }, statement_buffer: vec![], stack: vec![], call_count: HashMap::new(), + call_cache: HashMap::new(), } } @@ -59,7 +91,11 @@ impl<'ast, T: Field> Inliner<'ast, T> { .unwrap(); // initialize an inliner over all modules, starting from the main module - let mut inliner = Inliner::with_modules_and_module_id(p.modules, main_module_id); + let mut inliner = Inliner::with_modules_and_module_id_and_key( + p.modules, + main_module_id, + main_key.clone(), + ); // inline all calls in the main function, recursively let main = inliner.fold_function_symbol(main); @@ -74,9 +110,9 @@ impl<'ast, T: Field> Inliner<'ast, T> { // return a program with a single module containing `main`, `_UNPACK`, and `_SHA256_ROUND TypedProgram { - main: String::from("main"), + main: "main".into(), modules: vec![( - String::from("main"), + "main".into(), TypedModule { functions: vec![ (unpack_key, TypedFunctionSymbol::Flat(unpack)), @@ -101,24 +137,33 @@ impl<'ast, T: Field> Inliner<'ast, T> { expressions: Vec>, ) -> Result>, (FunctionKey<'ast>, Vec>)> { + match self.call_cache().get(key).map(|m| m.get(&expressions)) { + Some(Some(exprs)) => return Ok(exprs.clone()), + _ => {} + }; + // here we clone a function symbol, which is cheap except when it contains the function body, in which case we'd clone anyways - match self.module().functions.get(&key).unwrap().clone() { + let res = match self.module().functions.get(&key).unwrap().clone() { // if the function called is in the same module, we can go ahead and inline in this module TypedFunctionSymbol::Here(function) => { + let (current_module, current_key) = + self.change_context(self.module_id().clone(), key.clone()); + + let module_id = self.module_id().clone(); + // increase the number of calls for this function by one let count = self .call_count - .entry((self.module_id.clone(), key.clone())) + .entry((self.module_id().clone(), key.clone())) .and_modify(|i| *i += 1) .or_insert(1); // push this call to the stack - self.stack - .push((self.module_id.clone(), key.clone(), *count)); + self.stack.push((module_id, key.clone(), *count)); // add definitions for the inputs let inputs_bindings: Vec<_> = function .arguments .iter() - .zip(expressions) + .zip(expressions.clone()) .map(|(a, e)| { TypedStatement::Definition( self.fold_assignee(TypedAssignee::Identifier(a.id.clone())), @@ -145,6 +190,8 @@ impl<'ast, T: Field> Inliner<'ast, T> { // pop this call from the stack self.stack.pop(); + self.change_context(current_module, current_key); + match ret.pop().unwrap() { TypedStatement::Return(exprs) => Ok(exprs), _ => unreachable!(""), @@ -153,25 +200,64 @@ impl<'ast, T: Field> Inliner<'ast, T> { // if the function called is in some other module, we switch focus to that module and call the function locally there TypedFunctionSymbol::There(function_key, module_id) => { // switch focus to `module_id` - let current_module = self.change_module(module_id); + let (current_module, current_key) = + self.change_context(module_id, function_key.clone()); // inline the call there - let res = self.try_inline_call(&function_key, expressions)?; + let res = self.try_inline_call(&function_key, expressions.clone())?; // switch back focus - self.change_module(current_module); + self.change_context(current_module, current_key); Ok(res) } // if the function is a flat symbol, replace the call with a call to the local function we provide so it can be inlined in flattening - TypedFunctionSymbol::Flat(embed) => Err((embed.key::(), expressions)), - } + TypedFunctionSymbol::Flat(embed) => Err((embed.key::(), expressions.clone())), + }; + + res.map(|exprs| { + self.call_cache_mut() + .entry(key.clone()) + .or_insert_with(|| HashMap::new()) + .insert(expressions, exprs.clone()); + exprs + }) } - // Focus the Inliner on another module with id `module_id` and return the current `module_id` - fn change_module(&mut self, module_id: TypedModuleId) -> TypedModuleId { - std::mem::replace(&mut self.module_id, module_id) + // Focus the inliner on another module with id `module_id` and return the current `module_id` + fn change_context( + &mut self, + module_id: TypedModuleId, + function_key: FunctionKey<'ast>, + ) -> (TypedModuleId, FunctionKey<'ast>) { + let current_module = std::mem::replace(&mut self.location.module, module_id); + let current_key = std::mem::replace(&mut self.location.key, function_key); + (current_module, current_key) } fn module(&self) -> &TypedModule<'ast, T> { - self.modules.get(&self.module_id).unwrap() + self.modules.get(self.module_id()).unwrap() + } + + fn call_cache( + &mut self, + ) -> &HashMap< + FunctionKey<'ast>, + HashMap>, Vec>>, + > { + self.call_cache + .entry(self.location.clone()) + .or_insert_with(|| HashMap::new()) + } + + fn call_cache_mut( + &mut self, + ) -> &mut HashMap< + FunctionKey<'ast>, + HashMap>, Vec>>, + > { + self.call_cache.get_mut(&self.location).unwrap() + } + + fn module_id(&self) -> &TypedModuleId { + self.location.module() } } @@ -238,6 +324,28 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { } } + // inline calls which return a boolean element + fn fold_boolean_expression( + &mut self, + e: BooleanExpression<'ast, T>, + ) -> BooleanExpression<'ast, T> { + match e { + BooleanExpression::FunctionCall(key, exps) => { + let exps: Vec<_> = exps.into_iter().map(|e| self.fold_expression(e)).collect(); + + match self.try_inline_call(&key, exps) { + Ok(mut ret) => match ret.pop().unwrap() { + TypedExpression::Boolean(e) => e, + _ => unreachable!(), + }, + Err((key, expressions)) => BooleanExpression::FunctionCall(key, expressions), + } + } + e => fold_boolean_expression(self, e), + } + } + + // inline calls which return an array fn fold_array_expression_inner( &mut self, ty: &Type, @@ -263,7 +371,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { fn fold_struct_expression_inner( &mut self, - ty: &Vec<(MemberId, Type)>, + ty: &Vec, e: StructExpressionInner<'ast, T>, ) -> StructExpressionInner<'ast, T> { match e { @@ -289,6 +397,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { #[cfg(test)] mod tests { use super::*; + use std::path::PathBuf; use typed_absy::types::{FunctionKey, Signature, Type}; use zokrates_field::Bn128Field; @@ -332,7 +441,7 @@ mod tests { TypedFunctionSymbol::There( FunctionKey::with_id("foo") .signature(Signature::new().outputs(vec![Type::FieldElement])), - String::from("foo"), + "foo".into(), ), ), ] @@ -356,12 +465,12 @@ mod tests { .collect(), }; - let modules: HashMap<_, _> = vec![(String::from("main"), main), (String::from("foo"), foo)] + let modules: HashMap<_, _> = vec![("main".into(), main), ("foo".into(), foo)] .into_iter() .collect(); let program = TypedProgram { - main: String::from("main"), + main: "main".into(), modules, }; @@ -371,7 +480,7 @@ mod tests { assert_eq!( program .modules - .get(&String::from("main")) + .get(&PathBuf::from("main")) .unwrap() .functions .get( @@ -447,7 +556,7 @@ mod tests { .inputs(vec![Type::FieldElement]) .outputs(vec![Type::FieldElement]), ), - String::from("foo"), + "foo".into(), ), ), ] @@ -478,12 +587,12 @@ mod tests { .collect(), }; - let modules: HashMap<_, _> = vec![(String::from("main"), main), (String::from("foo"), foo)] + let modules: HashMap<_, _> = vec![("main".into(), main), ("foo".into(), foo)] .into_iter() .collect(); let program: TypedProgram = TypedProgram { - main: String::from("main"), + main: "main".into(), modules, }; @@ -492,7 +601,7 @@ mod tests { assert_eq!(program.modules.len(), 1); let stack = vec![( - String::from("foo"), + "foo".into(), FunctionKey::with_id("foo").signature( Signature::new() .inputs(vec![Type::FieldElement]) @@ -504,7 +613,7 @@ mod tests { assert_eq!( program .modules - .get(&String::from("main")) + .get(&PathBuf::from("main")) .unwrap() .functions .get( @@ -544,6 +653,363 @@ mod tests { ); } + #[test] + fn memoize_local_call() { + // // foo + // def foo(field a) -> (field): + // return a + + // // main + // def main(field a) -> (field): + // field b = foo(a) + foo(a) + // return b + + // inlined + // def main(field a) -> (field) + // field _0 = a + a + // return _0 + + let signature = Signature::new() + .outputs(vec![Type::FieldElement]) + .inputs(vec![Type::FieldElement]); + + let main: TypedModule = TypedModule { + functions: vec![ + ( + FunctionKey::with_id("main").signature(signature.clone()), + TypedFunctionSymbol::Here(TypedFunction { + arguments: vec![Parameter { + id: Variable::field_element("a".into()), + private: true, + }], + statements: vec![ + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element("b".into())), + FieldElementExpression::Add( + box FieldElementExpression::FunctionCall( + FunctionKey::with_id("foo").signature(signature.clone()), + vec![FieldElementExpression::Identifier("a".into()).into()], + ), + box FieldElementExpression::FunctionCall( + FunctionKey::with_id("foo").signature(signature.clone()), + vec![FieldElementExpression::Identifier("a".into()).into()], + ), + ) + .into(), + ), + TypedStatement::Return(vec![FieldElementExpression::Identifier( + "b".into(), + ) + .into()]), + ], + signature: signature.clone(), + }), + ), + ( + FunctionKey::with_id("foo").signature(signature.clone()), + TypedFunctionSymbol::There( + FunctionKey::with_id("foo").signature(signature.clone()), + "foo".into(), + ), + ), + ] + .into_iter() + .collect(), + }; + + let foo: TypedModule = TypedModule { + functions: vec![( + FunctionKey::with_id("foo").signature(signature.clone()), + TypedFunctionSymbol::Here(TypedFunction { + arguments: vec![Parameter { + id: Variable::field_element("a".into()), + private: true, + }], + statements: vec![TypedStatement::Return(vec![ + FieldElementExpression::Identifier("a".into()).into(), + ])], + signature: signature.clone(), + }), + )] + .into_iter() + .collect(), + }; + + let modules: HashMap<_, _> = vec![("main".into(), main), ("foo".into(), foo)] + .into_iter() + .collect(); + + let program = TypedProgram { + main: "main".into(), + modules, + }; + + let program = Inliner::inline(program); + + assert_eq!(program.modules.len(), 1); + assert_eq!( + program + .modules + .get(&PathBuf::from("main")) + .unwrap() + .functions + .get(&FunctionKey::with_id("main").signature(signature.clone())) + .unwrap(), + &TypedFunctionSymbol::Here(TypedFunction { + arguments: vec![Parameter { + id: Variable::field_element("a".into()), + private: true, + }], + statements: vec![ + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element( + Identifier::from("a").stack(vec![( + "foo".into(), + FunctionKey::with_id("foo").signature(signature.clone()), + 1 + )]) + )), + FieldElementExpression::Identifier("a".into()).into() + ), + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element("b".into())), + FieldElementExpression::Add( + box FieldElementExpression::Identifier(Identifier::from("a").stack( + vec![( + "foo".into(), + FunctionKey::with_id("foo").signature(signature.clone()), + 1 + )] + )), + box FieldElementExpression::Identifier(Identifier::from("a").stack( + vec![( + "foo".into(), + FunctionKey::with_id("foo").signature(signature.clone()), + 1 + )] + )) + ) + .into() + ), + TypedStatement::Return(vec![ + FieldElementExpression::Identifier("b".into()).into(), + ]) + ], + signature: signature.clone(), + }) + ); + } + + #[test] + fn only_memoize_in_same_function() { + // // foo + // def foo(field a) -> (field): + // return a + + // // main + // def main(field a) -> (field): + // field b = foo(a) + bar(a) + // return b + // + // def bar(field a) -> (field): + // return foo(a) + + // inlined + // def main(field a) -> (field) + // field _0 = a + a + // return _0 + + let signature = Signature::new() + .outputs(vec![Type::FieldElement]) + .inputs(vec![Type::FieldElement]); + + let main: TypedModule = TypedModule { + functions: vec![ + ( + FunctionKey::with_id("main").signature( + Signature::new() + .outputs(vec![Type::FieldElement]) + .inputs(vec![Type::FieldElement]), + ), + TypedFunctionSymbol::Here(TypedFunction { + arguments: vec![Parameter { + id: Variable::field_element("a".into()), + private: true, + }], + statements: vec![ + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element("b".into())), + FieldElementExpression::Add( + box FieldElementExpression::FunctionCall( + FunctionKey::with_id("foo").signature(signature.clone()), + vec![FieldElementExpression::Identifier("a".into()).into()], + ), + box FieldElementExpression::FunctionCall( + FunctionKey::with_id("bar").signature(signature.clone()), + vec![FieldElementExpression::Identifier("a".into()).into()], + ), + ) + .into(), + ), + TypedStatement::Return(vec![FieldElementExpression::Identifier( + "b".into(), + ) + .into()]), + ], + signature: signature.clone(), + }), + ), + ( + FunctionKey::with_id("bar").signature(signature.clone()), + TypedFunctionSymbol::Here(TypedFunction { + arguments: vec![Parameter { + id: Variable::field_element("a".into()), + private: true, + }], + statements: vec![TypedStatement::Return(vec![ + FieldElementExpression::FunctionCall( + FunctionKey::with_id("foo").signature(signature.clone()), + vec![FieldElementExpression::Identifier("a".into()).into()], + ) + .into(), + ])], + signature: signature.clone(), + }), + ), + ( + FunctionKey::with_id("foo").signature(signature.clone()), + TypedFunctionSymbol::There( + FunctionKey::with_id("foo").signature(signature.clone()), + "foo".into(), + ), + ), + ] + .into_iter() + .collect(), + }; + + let foo: TypedModule = TypedModule { + functions: vec![( + FunctionKey::with_id("foo").signature(signature.clone()), + TypedFunctionSymbol::Here(TypedFunction { + arguments: vec![Parameter { + id: Variable::field_element("a".into()), + private: true, + }], + statements: vec![TypedStatement::Return(vec![ + FieldElementExpression::Identifier("a".into()).into(), + ])], + signature: signature.clone(), + }), + )] + .into_iter() + .collect(), + }; + + let modules: HashMap<_, _> = vec![("main".into(), main), ("foo".into(), foo)] + .into_iter() + .collect(); + + let program = TypedProgram { + main: "main".into(), + modules, + }; + + let program = Inliner::inline(program); + + assert_eq!(program.modules.len(), 1); + assert_eq!( + program + .modules + .get(&PathBuf::from("main")) + .unwrap() + .functions + .get(&FunctionKey::with_id("main").signature(signature.clone())) + .unwrap(), + &TypedFunctionSymbol::Here(TypedFunction { + arguments: vec![Parameter { + id: Variable::field_element("a".into()), + private: true, + }], + statements: vec![ + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element( + Identifier::from("a").stack(vec![( + "foo".into(), + FunctionKey::with_id("foo").signature(signature.clone()), + 1 + )]) + )), + FieldElementExpression::Identifier("a".into()).into() + ), + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element( + Identifier::from("a").stack(vec![( + "main".into(), + FunctionKey::with_id("bar").signature(signature.clone()), + 1 + )]) + )), + FieldElementExpression::Identifier("a".into()).into() + ), + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element( + Identifier::from("a").stack(vec![ + ( + "main".into(), + FunctionKey::with_id("bar").signature(signature.clone()), + 1 + ), + ( + "foo".into(), + FunctionKey::with_id("foo").signature(signature.clone()), + 2 + ) + ]) + )), + FieldElementExpression::Identifier(Identifier::from("a").stack(vec![( + "main".into(), + FunctionKey::with_id("bar").signature(signature.clone()), + 1 + )])) + .into() + ), + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element("b".into())), + FieldElementExpression::Add( + box FieldElementExpression::Identifier(Identifier::from("a").stack( + vec![( + "foo".into(), + FunctionKey::with_id("foo").signature(signature.clone()), + 1 + )] + )), + box FieldElementExpression::Identifier(Identifier::from("a").stack( + vec![ + ( + "main".into(), + FunctionKey::with_id("bar").signature(signature.clone()), + 1 + ), + ( + "foo".into(), + FunctionKey::with_id("foo").signature(signature.clone()), + 2 + ) + ] + )) + ) + .into() + ), + TypedStatement::Return(vec![ + FieldElementExpression::Identifier("b".into()).into(), + ]) + ], + signature: signature.clone(), + }) + ); + } + #[test] fn multi_def_from_other_module() { // // foo @@ -592,7 +1058,7 @@ mod tests { TypedFunctionSymbol::There( FunctionKey::with_id("foo") .signature(Signature::new().outputs(vec![Type::FieldElement])), - String::from("foo"), + "foo".into(), ), ), ] @@ -616,12 +1082,12 @@ mod tests { .collect(), }; - let modules: HashMap<_, _> = vec![(String::from("main"), main), (String::from("foo"), foo)] + let modules: HashMap<_, _> = vec![("main".into(), main), ("foo".into(), foo)] .into_iter() .collect(); let program = TypedProgram { - main: String::from("main"), + main: "main".into(), modules, }; @@ -631,7 +1097,7 @@ mod tests { assert_eq!( program .modules - .get(&String::from("main")) + .get(&PathBuf::from("main")) .unwrap() .functions .get( @@ -711,10 +1177,10 @@ mod tests { .collect(), }; - let modules: HashMap<_, _> = vec![(String::from("main"), main)].into_iter().collect(); + let modules: HashMap<_, _> = vec![("main".into(), main)].into_iter().collect(); let program = TypedProgram { - main: String::from("main"), + main: "main".into(), modules, }; @@ -724,7 +1190,7 @@ mod tests { assert_eq!( program .modules - .get(&String::from("main")) + .get(&PathBuf::from("main")) .unwrap() .functions .get( @@ -810,7 +1276,7 @@ mod tests { .inputs(vec![Type::FieldElement]) .outputs(vec![Type::FieldElement]), ), - String::from("id"), + "id".into(), ), ), ] @@ -839,19 +1305,19 @@ mod tests { .collect(), }; - let modules = vec![(String::from("main"), main), (String::from("id"), id)] + let modules = vec![("main".into(), main), ("id".into(), id)] .into_iter() .collect(); let program: TypedProgram = TypedProgram { - main: String::from("main"), + main: "main".into(), modules, }; let program = Inliner::inline(program); let stack0 = vec![( - String::from("id"), + "id".into(), FunctionKey::with_id("main").signature( Signature::new() .inputs(vec![Type::FieldElement]) @@ -860,7 +1326,7 @@ mod tests { 1, )]; let stack1 = vec![( - String::from("id"), + "id".into(), FunctionKey::with_id("main").signature( Signature::new() .inputs(vec![Type::FieldElement]) @@ -873,7 +1339,7 @@ mod tests { assert_eq!( program .modules - .get(&String::from("main")) + .get(&PathBuf::from("main")) .unwrap() .functions .get( diff --git a/zokrates_core/src/static_analysis/mod.rs b/zokrates_core/src/static_analysis/mod.rs index 726f641e..903ea18c 100644 --- a/zokrates_core/src/static_analysis/mod.rs +++ b/zokrates_core/src/static_analysis/mod.rs @@ -7,15 +7,21 @@ mod constrain_inputs; mod flat_propagation; mod inline; +mod propagate_unroll; mod propagation; +mod return_binder; +mod unconstrained_vars; mod unroll; use self::constrain_inputs::InputConstrainer; use self::inline::Inliner; +use self::propagate_unroll::PropagatedUnroller; use self::propagation::Propagator; -use self::unroll::Unroller; +use self::return_binder::ReturnBinder; +use self::unconstrained_vars::UnconstrainedVariableDetector; use crate::flat_absy::FlatProg; use crate::typed_absy::TypedProgram; +use ir::Prog; use zokrates_field::Field; pub trait Analyse { @@ -24,14 +30,17 @@ pub trait Analyse { impl<'ast, T: Field> Analyse for TypedProgram<'ast, T> { fn analyse(self) -> Self { - // unroll - let r = Unroller::unroll(self); + // propagated unrolling + let r = PropagatedUnroller::unroll(self).unwrap_or_else(|e| panic!(e)); + // return binding + let r = ReturnBinder::bind(r); // inline let r = Inliner::inline(r); // propagate let r = Propagator::propagate(r); // constrain inputs let r = InputConstrainer::constrain(r); + r } } @@ -41,3 +50,10 @@ impl Analyse for FlatProg { self.propagate() } } + +impl Analyse for Prog { + fn analyse(self) -> Self { + let r = UnconstrainedVariableDetector::detect(self); + r + } +} diff --git a/zokrates_core/src/static_analysis/propagate_unroll.rs b/zokrates_core/src/static_analysis/propagate_unroll.rs new file mode 100644 index 00000000..dcd99e26 --- /dev/null +++ b/zokrates_core/src/static_analysis/propagate_unroll.rs @@ -0,0 +1,236 @@ +//! Module containing iterative unrolling in order to unroll nested loops with variable bounds +//! +//! For example: +//! ```zokrates +//! for field i in 0..5 do +//! for field j in i..5 do +//! // +//! endfor +//! endfor +//! ``` +//! +//! We can unroll the outer loop, but to unroll the inner one we need to propagate the value of `i` to the lower bound of the loop +//! +//! This module does exactly that: +//! - unroll the outter loop, detecting that it cannot unroll the inner one as the lower `i` bound isn't constant +//! - apply constant propagation to the program, *not visiting statements of loops whose bounds are not constant yet* +//! - unroll again, this time the 5 inner loops all have constant bounds +//! +//! In the case that a loop bound cannot be reduced to a constant, we detect it by noticing that the unroll does +//! not make progress anymore. + +use static_analysis::propagation::Propagator; +use static_analysis::unroll::{Output, Unroller}; +use typed_absy::TypedProgram; +use zokrates_field::Field; + +pub struct PropagatedUnroller; + +impl PropagatedUnroller { + pub fn unroll<'ast, T: Field>( + p: TypedProgram<'ast, T>, + ) -> Result, &'static str> { + let mut blocked_at = None; + + // unroll a first time, retrieving whether the unroll is complete + let mut unrolled = Unroller::unroll(p); + + loop { + // conditions to exit the loop + unrolled = match unrolled { + Output::Complete(p) => return Ok(p), + Output::Incomplete(next, index) => { + if Some(index) == blocked_at { + return Err("Loop unrolling failed. This happened because a loop bound is not constant"); + } else { + // update the index where we blocked + blocked_at = Some(index); + + // propagate + let propagated = Propagator::propagate_verbose(next); + + // unroll + Unroller::unroll(propagated) + } + } + }; + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use typed_absy::types::{FunctionKey, Signature}; + use typed_absy::*; + use zokrates_field::Bn128Field; + + #[test] + fn detect_non_constant_bound() { + let loops = vec![TypedStatement::For( + Variable::field_element("i".into()), + FieldElementExpression::Identifier("i".into()), + FieldElementExpression::Number(Bn128Field::from(2)), + vec![], + )]; + + let statements = loops; + + let p = TypedProgram { + modules: vec![( + "main".into(), + TypedModule { + functions: vec![( + FunctionKey::with_id("main"), + TypedFunctionSymbol::Here(TypedFunction { + arguments: vec![], + signature: Signature::new(), + statements, + }), + )] + .into_iter() + .collect(), + }, + )] + .into_iter() + .collect(), + main: "main".into(), + }; + + assert!(PropagatedUnroller::unroll(p).is_err()); + } + + #[test] + fn for_loop() { + // for field i in 0..2 + // for field j in i..2 + // field foo = i + j + + // should be unrolled to + // i_0 = 0 + // j_0 = 0 + // foo_0 = i_0 + j_0 + // j_1 = 1 + // foo_1 = i_0 + j_1 + // i_1 = 1 + // j_2 = 1 + // foo_2 = i_1 + j_1 + + let s = TypedStatement::For( + Variable::field_element("i".into()), + FieldElementExpression::Number(Bn128Field::from(0)), + FieldElementExpression::Number(Bn128Field::from(2)), + vec![TypedStatement::For( + Variable::field_element("j".into()), + FieldElementExpression::Identifier("i".into()), + FieldElementExpression::Number(Bn128Field::from(2)), + vec![ + TypedStatement::Declaration(Variable::field_element("foo".into())), + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element("foo".into())), + FieldElementExpression::Add( + box FieldElementExpression::Identifier("i".into()), + box FieldElementExpression::Identifier("j".into()), + ) + .into(), + ), + ], + )], + ); + + let expected_statements = vec![ + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element( + Identifier::from("i").version(0), + )), + FieldElementExpression::Number(Bn128Field::from(0)).into(), + ), + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element( + Identifier::from("j").version(0), + )), + FieldElementExpression::Number(Bn128Field::from(0)).into(), + ), + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element( + Identifier::from("foo").version(0), + )), + FieldElementExpression::Add( + box FieldElementExpression::Identifier(Identifier::from("i").version(0)), + box FieldElementExpression::Identifier(Identifier::from("j").version(0)), + ) + .into(), + ), + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element( + Identifier::from("j").version(1), + )), + FieldElementExpression::Number(Bn128Field::from(1)).into(), + ), + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element( + Identifier::from("foo").version(1), + )), + FieldElementExpression::Add( + box FieldElementExpression::Identifier(Identifier::from("i").version(0)), + box FieldElementExpression::Identifier(Identifier::from("j").version(1)), + ) + .into(), + ), + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element( + Identifier::from("i").version(1), + )), + FieldElementExpression::Number(Bn128Field::from(1)).into(), + ), + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element( + Identifier::from("j").version(2), + )), + FieldElementExpression::Number(Bn128Field::from(1)).into(), + ), + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element( + Identifier::from("foo").version(2), + )), + FieldElementExpression::Add( + box FieldElementExpression::Identifier(Identifier::from("i").version(1)), + box FieldElementExpression::Identifier(Identifier::from("j").version(2)), + ) + .into(), + ), + ]; + + let p = TypedProgram { + modules: vec![( + "main".into(), + TypedModule { + functions: vec![( + FunctionKey::with_id("main"), + TypedFunctionSymbol::Here(TypedFunction { + arguments: vec![], + signature: Signature::new(), + statements: vec![s], + }), + )] + .into_iter() + .collect(), + }, + )] + .into_iter() + .collect(), + main: "main".into(), + }; + + let statements = match PropagatedUnroller::unroll(p).unwrap().modules + [std::path::Path::new("main")] + .functions[&FunctionKey::with_id("main")] + .clone() + { + TypedFunctionSymbol::Here(f) => f.statements, + _ => unreachable!(), + }; + + assert_eq!(statements, expected_statements); + } +} diff --git a/zokrates_core/src/static_analysis/propagation.rs b/zokrates_core/src/static_analysis/propagation.rs index a6dc48e6..0d87a654 100644 --- a/zokrates_core/src/static_analysis/propagation.rs +++ b/zokrates_core/src/static_analysis/propagation.rs @@ -1,5 +1,11 @@ //! Module containing constant propagation for the typed AST //! +//! On top of the usual behavior of removing statements which assign a constant to a variable (as the variable can simply be +//! substituted for the constant whenever used), we provide a `verbose` mode which does not remove such statements. This is done +//! as for partial passes which do not visit the whole program, the variables being defined may be be used in parts of the program +//! that are not visited. Keeping the statements is semantically equivalent and enables rebuilding the set of constants at the +//! next pass. +//! //! @file propagation.rs //! @author Thibaut Schaeffer //! @date 2018 @@ -8,23 +14,40 @@ use crate::typed_absy::folder::*; use crate::typed_absy::*; use std::collections::HashMap; use std::convert::TryFrom; -use typed_absy::types::{MemberId, Type}; +use typed_absy::types::{StructMember, Type}; use zokrates_field::Field; pub struct Propagator<'ast, T: Field> { + // constants keeps track of constant expressions + // we currently do not support partially constant expressions: `field [x, 1][1]` is not considered constant, `field [0, 1][1]` is constants: HashMap, TypedExpression<'ast, T>>, + // the verbose mode doesn't remove statements which assign constants to variables + // it's required when using propagation in combination with unrolling + verbose: bool, } impl<'ast, T: Field> Propagator<'ast, T> { + fn verbose() -> Self { + Propagator { + constants: HashMap::new(), + verbose: true, + } + } + fn new() -> Self { Propagator { constants: HashMap::new(), + verbose: false, } } pub fn propagate(p: TypedProgram<'ast, T>) -> TypedProgram<'ast, T> { Propagator::new().fold_program(p) } + + pub fn propagate_verbose(p: TypedProgram<'ast, T>) -> TypedProgram<'ast, T> { + Propagator::verbose().fold_program(p) + } } fn is_constant<'ast, T: Field>(e: &TypedExpression<'ast, T>) -> bool { @@ -63,8 +86,15 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { let expr = self.fold_expression(expr); if is_constant(&expr) { - self.constants.insert(TypedAssignee::Identifier(var), expr); - None + self.constants + .insert(TypedAssignee::Identifier(var.clone()), expr.clone()); + match self.verbose { + true => Some(TypedStatement::Definition( + TypedAssignee::Identifier(var), + expr, + )), + false => None, + } } else { Some(TypedStatement::Definition( TypedAssignee::Identifier(var), @@ -86,9 +116,17 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { self.fold_expression(e2), )) } - // we unrolled for loops in the previous step - TypedStatement::For(..) => { - unreachable!("for loop is unexpected, it should have been unrolled") + // only loops with variable bounds are expected here + // we stop propagation here as constants maybe be modified inside the loop body + // which we do not visit + TypedStatement::For(v, from, to, statements) => { + let from = self.fold_field_expression(from); + let to = self.fold_field_expression(to); + + // invalidate the constants map as any constant could be modified inside the loop body, which we don't visit + self.constants.clear(); + + Some(TypedStatement::For(v, from, to, statements)) } TypedStatement::MultipleDefinition(variables, expression_list) => { let expression_list = self.fold_expression_list(expression_list); @@ -98,6 +136,10 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { )) } }; + + // In verbose mode, we always return a statement + assert!(res.is_some() || !self.verbose); + match res { Some(v) => vec![v], None => vec![], @@ -241,7 +283,13 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { match s.into_inner() { StructExpressionInner::Value(v) => { - match members.iter().zip(v).find(|(id, _)| id.0 == m).unwrap().1 { + match members + .iter() + .zip(v) + .find(|(member, _)| member.id == m) + .unwrap() + .1 + { TypedExpression::FieldElement(s) => s, _ => unreachable!(), } @@ -337,7 +385,13 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { match s.into_inner() { StructExpressionInner::Value(v) => { - match members.iter().zip(v).find(|(id, _)| id.0 == m).unwrap().1 { + match members + .iter() + .zip(v) + .find(|(member, _)| member.id == m) + .unwrap() + .1 + { TypedExpression::Array(a) => a.into_inner(), _ => unreachable!(), } @@ -351,7 +405,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { fn fold_struct_expression_inner( &mut self, - ty: &Vec<(MemberId, Type)>, + ty: &Vec, e: StructExpressionInner<'ast, T>, ) -> StructExpressionInner<'ast, T> { match e { @@ -433,7 +487,13 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { match s.into_inner() { StructExpressionInner::Value(v) => { - match members.iter().zip(v).find(|(id, _)| id.0 == m).unwrap().1 { + match members + .iter() + .zip(v) + .find(|(member, _)| member.id == m) + .unwrap() + .1 + { TypedExpression::Struct(s) => s.into_inner(), _ => unreachable!(), } @@ -590,7 +650,13 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { match s.into_inner() { StructExpressionInner::Value(v) => { - match members.iter().zip(v).find(|(id, _)| id.0 == m).unwrap().1 { + match members + .iter() + .zip(v) + .find(|(member, _)| member.id == m) + .unwrap() + .1 + { TypedExpression::Boolean(s) => s, _ => unreachable!(), } diff --git a/zokrates_core/src/static_analysis/return_binder.rs b/zokrates_core/src/static_analysis/return_binder.rs new file mode 100644 index 00000000..fd2aefee --- /dev/null +++ b/zokrates_core/src/static_analysis/return_binder.rs @@ -0,0 +1,55 @@ +use typed_absy::folder::fold_statement; +use typed_absy::identifier::CoreIdentifier; +use typed_absy::*; +use zokrates_field::Field; + +pub struct ReturnBinder; + +impl ReturnBinder { + pub fn bind<'ast, T: Field>(p: TypedProgram<'ast, T>) -> TypedProgram<'ast, T> { + ReturnBinder {}.fold_program(p) + } +} + +impl<'ast, T: Field> Folder<'ast, T> for ReturnBinder { + fn fold_statement(&mut self, s: TypedStatement<'ast, T>) -> Vec> { + match s { + TypedStatement::Return(exprs) => { + let ret_identifiers: Vec> = (0..exprs.len()) + .map(|i| CoreIdentifier::Internal("RETURN", i).into()) + .collect(); + + let ret_expressions: Vec> = exprs + .iter() + .zip(ret_identifiers.iter()) + .map(|(e, i)| match e.get_type() { + Type::FieldElement => FieldElementExpression::Identifier(i.clone()).into(), + Type::Boolean => BooleanExpression::Identifier(i.clone()).into(), + Type::Array(array_type) => ArrayExpressionInner::Identifier(i.clone()) + .annotate(*array_type.ty, array_type.size) + .into(), + Type::Struct(struct_type) => StructExpressionInner::Identifier(i.clone()) + .annotate(struct_type) + .into(), + }) + .collect(); + + exprs + .into_iter() + .zip(ret_identifiers.iter()) + .map(|(e, i)| { + TypedStatement::Definition( + TypedAssignee::Identifier(Variable::with_id_and_type( + i.clone(), + e.get_type(), + )), + e, + ) + }) + .chain(std::iter::once(TypedStatement::Return(ret_expressions))) + .collect() + } + s => fold_statement(self, s), + } + } +} diff --git a/zokrates_core/src/static_analysis/unconstrained_vars.rs b/zokrates_core/src/static_analysis/unconstrained_vars.rs new file mode 100644 index 00000000..d566889d --- /dev/null +++ b/zokrates_core/src/static_analysis/unconstrained_vars.rs @@ -0,0 +1,176 @@ +use crate::ir::Prog; +use flat_absy::FlatVariable; +use ir::folder::Folder; +use ir::Directive; +use std::collections::HashSet; +use zokrates_field::Field; + +#[derive(Debug)] +pub struct UnconstrainedVariableDetector { + pub(self) variables: HashSet, +} + +impl UnconstrainedVariableDetector { + fn new(p: &Prog) -> Self { + UnconstrainedVariableDetector { + variables: p + .parameters() + .iter() + .filter(|p| p.private) + .map(|p| p.id) + .collect(), + } + } + pub fn detect(p: Prog) -> Prog { + let mut instance = Self::new(&p); + let p = instance.fold_module(p); + + // we should probably handle this case instead of asserting at some point + assert!( + instance.variables.is_empty(), + format!( + "Unconstrained variables are not allowed (found {} occasions)", + instance.variables.len() + ) + ); + p + } +} + +impl Folder for UnconstrainedVariableDetector { + fn fold_argument(&mut self, p: FlatVariable) -> FlatVariable { + p + } + fn fold_variable(&mut self, v: FlatVariable) -> FlatVariable { + self.variables.remove(&v); + v + } + fn fold_directive(&mut self, d: Directive) -> Directive { + self.variables.extend(d.outputs.iter()); + d + } +} + +#[cfg(test)] +mod tests { + use super::*; + use flat_absy::FlatVariable; + use ir::{Function, LinComb, Prog, QuadComb, Statement}; + use solvers::Solver; + use zokrates_field::Bn128Field; + + #[test] + #[should_panic] + fn should_detect_unconstrained_private_input() { + // def main(_0) -> (1): + // (1 * ~one) * (42 * ~one) == 1 * ~out_0 + // return ~out_0 + + let _0 = FlatVariable::new(0); // unused var + + let one = FlatVariable::one(); + let out_0 = FlatVariable::public(0); + + let main: Function = Function { + id: "main".to_string(), + arguments: vec![_0], + statements: vec![Statement::constraint( + QuadComb::from_linear_combinations( + LinComb::summand(1, one), + LinComb::summand(42, one), + ), + LinComb::summand(1, out_0), + )], + returns: vec![out_0], + }; + + let p: Prog = Prog { + private: vec![true], + main, + }; + + UnconstrainedVariableDetector::detect(p); + } + + #[test] + fn should_pass_with_constrained_private_input() { + // def main(_0) -> (1): + // (1 * ~one) * (1 * _0) == 1 * ~out_0 + // return ~out_0 + + let _0 = FlatVariable::new(0); + let out_0 = FlatVariable::public(0); + + let main: Function = Function { + id: "main".to_string(), + arguments: vec![_0], + statements: vec![Statement::definition(out_0, LinComb::from(_0))], + returns: vec![out_0], + }; + + let p: Prog = Prog { + private: vec![true], + main, + }; + + UnconstrainedVariableDetector::detect(p); + } + + #[test] + fn should_pass_with_directive() { + // def main(_0) -> (1): + // # _1, _2 = ConditionEq((-42) * ~one + 1 * _0) + // ((-42) * ~one + 1 * _0) * (1 * _2) == 1 * _1 + // (1 * ~one + (-1) * _1) * ((-42) * ~one + 1 * _0) == 0 + // (1 * ~one) * (1 * ~one + (-1) * _1) == 1 * ~out_0 + // return ~out_0 + + let _0 = FlatVariable::new(0); + let _1 = FlatVariable::new(1); + let _2 = FlatVariable::new(2); + + let out_0 = FlatVariable::public(0); + let one = FlatVariable::one(); + + let main: Function = Function { + id: "main".to_string(), + arguments: vec![_0], + statements: vec![ + Statement::Directive(Directive { + inputs: vec![LinComb::summand(-42, one) + LinComb::summand(1, _0)], + outputs: vec![_1, _2], + solver: Solver::ConditionEq, + }), + Statement::constraint( + QuadComb::from_linear_combinations( + LinComb::summand(-42, one) + LinComb::summand(1, _0), + LinComb::summand(1, _2), + ), + LinComb::summand(1, _1), + ), + Statement::constraint( + QuadComb::from_linear_combinations( + LinComb::summand(1, one) + LinComb::summand(-1, _1), + LinComb::summand(-42, one) + LinComb::summand(1, _0), + ), + LinComb::zero(), + ), + Statement::constraint( + QuadComb::from_linear_combinations( + LinComb::summand(1, one), + LinComb::summand(1, one) + LinComb::summand(-1, _1), + ), + LinComb::summand(1, out_0), + ), + ], + returns: vec![out_0], + }; + + let p: Prog = Prog { + private: vec![true], + main, + }; + + UnconstrainedVariableDetector::detect(p); + } +} diff --git a/zokrates_core/src/static_analysis/unroll.rs b/zokrates_core/src/static_analysis/unroll.rs index bc3e5910..e7df95c7 100644 --- a/zokrates_core/src/static_analysis/unroll.rs +++ b/zokrates_core/src/static_analysis/unroll.rs @@ -9,24 +9,36 @@ use crate::typed_absy::types::{MemberId, Type}; use crate::typed_absy::*; use std::collections::HashMap; use std::collections::HashSet; +use typed_absy::identifier::CoreIdentifier; use zokrates_field::Field; +pub enum Output<'ast, T: Field> { + Complete(TypedProgram<'ast, T>), + Incomplete(TypedProgram<'ast, T>, usize), +} + pub struct Unroller<'ast> { - substitution: HashMap, usize>, + // version index for any variable name + substitution: HashMap, usize>, + // whether all statements could be unrolled so far. Loops with variable bounds cannot. + complete: bool, + statement_count: usize, } impl<'ast> Unroller<'ast> { fn new() -> Self { Unroller { substitution: HashMap::new(), + complete: true, + statement_count: 0, } } fn issue_next_ssa_variable(&mut self, v: Variable<'ast>) -> Variable<'ast> { - let res = match self.substitution.get(&v.id) { + let res = match self.substitution.get(&v.id.id) { Some(i) => Variable { id: Identifier { - id: v.id.id, + id: v.id.id.clone(), version: i + 1, stack: vec![], }, @@ -34,15 +46,22 @@ impl<'ast> Unroller<'ast> { }, None => Variable { ..v.clone() }, }; + self.substitution - .entry(v.id) + .entry(v.id.id) .and_modify(|e| *e += 1) .or_insert(0); res } - pub fn unroll(p: TypedProgram) -> TypedProgram { - Unroller::new().fold_program(p) + pub fn unroll(p: TypedProgram) -> Output { + let mut unroller = Unroller::new(); + let p = unroller.fold_program(p); + + match unroller.complete { + true => Output::Complete(p), + false => Output::Incomplete(p, unroller.statement_count), + } } fn choose_many( @@ -208,9 +227,9 @@ impl<'ast> Unroller<'ast> { members .clone() .into_iter() - .map(|(id, t)| match t { + .map(|member| match *member.ty { Type::FieldElement => { - if id == head { + if member.id == head { Self::choose_many( FieldElementExpression::member( base.clone(), @@ -222,12 +241,15 @@ impl<'ast> Unroller<'ast> { statements, ) } else { - FieldElementExpression::member(base.clone(), id.clone()) - .into() + FieldElementExpression::member( + base.clone(), + member.id.clone(), + ) + .into() } } Type::Boolean => { - if id == head { + if member.id == head { Self::choose_many( BooleanExpression::member( base.clone(), @@ -239,12 +261,15 @@ impl<'ast> Unroller<'ast> { statements, ) } else { - BooleanExpression::member(base.clone(), id.clone()) - .into() + BooleanExpression::member( + base.clone(), + member.id.clone(), + ) + .into() } } Type::Array(..) => { - if id == head { + if member.id == head { Self::choose_many( ArrayExpression::member(base.clone(), head.clone()) .into(), @@ -253,11 +278,12 @@ impl<'ast> Unroller<'ast> { statements, ) } else { - ArrayExpression::member(base.clone(), id.clone()).into() + ArrayExpression::member(base.clone(), member.id.clone()) + .into() } } Type::Struct(..) => { - if id == head { + if member.id == head { Self::choose_many( StructExpression::member( base.clone(), @@ -269,8 +295,11 @@ impl<'ast> Unroller<'ast> { statements, ) } else { - StructExpression::member(base.clone(), id.clone()) - .into() + StructExpression::member( + base.clone(), + member.id.clone(), + ) + .into() } } }) @@ -312,6 +341,7 @@ fn linear<'ast, T: Field>(a: TypedAssignee<'ast, T>) -> (Variable, Vec Folder<'ast, T> for Unroller<'ast> { fn fold_statement(&mut self, s: TypedStatement<'ast, T>) -> Vec> { + self.statement_count += 1; match s { TypedStatement::Declaration(_) => vec![], TypedStatement::Definition(assignee, expr) => { @@ -326,9 +356,9 @@ impl<'ast, T: Field> Folder<'ast, T> for Unroller<'ast> { Type::Boolean => { BooleanExpression::Identifier(variable.id.clone().into()).into() } - Type::Array(box ty, size) => { + Type::Array(array_type) => { ArrayExpressionInner::Identifier(variable.id.clone().into()) - .annotate(ty, size) + .annotate(*array_type.ty, array_type.size) .into() } Type::Struct(members) => { @@ -339,6 +369,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Unroller<'ast> { }; let base = self.fold_expression(base); + let indices = indices .into_iter() .map(|a| match a { @@ -368,34 +399,45 @@ impl<'ast, T: Field> Folder<'ast, T> for Unroller<'ast> { vec![TypedStatement::MultipleDefinition(variables, exprs)] } TypedStatement::For(v, from, to, stats) => { - let mut values: Vec = vec![]; - let mut current = from; - while current < to { - values.push(current.clone()); - current = T::one() + ¤t; + let from = self.fold_field_expression(from); + let to = self.fold_field_expression(to); + + match (from, to) { + (FieldElementExpression::Number(from), FieldElementExpression::Number(to)) => { + let mut values: Vec = vec![]; + let mut current = from; + while current < to { + values.push(current.clone()); + current = T::one() + ¤t; + } + + let res = values + .into_iter() + .map(|index| { + vec![ + vec![ + TypedStatement::Declaration(v.clone()), + TypedStatement::Definition( + TypedAssignee::Identifier(v.clone()), + FieldElementExpression::Number(index).into(), + ), + ], + stats.clone(), + ] + .into_iter() + .flat_map(|x| x) + }) + .flat_map(|x| x) + .flat_map(|x| self.fold_statement(x)) + .collect(); + + res + } + (from, to) => { + self.complete = false; + vec![TypedStatement::For(v, from, to, stats)] + } } - - let res = values - .into_iter() - .map(|index| { - vec![ - vec![ - TypedStatement::Declaration(v.clone()), - TypedStatement::Definition( - TypedAssignee::Identifier(v.clone()), - FieldElementExpression::Number(index).into(), - ), - ], - stats.clone(), - ] - .into_iter() - .flat_map(|x| x) - }) - .flat_map(|x| x) - .flat_map(|x| self.fold_statement(x)) - .collect(); - - res } s => fold_statement(self, s), } @@ -404,7 +446,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Unroller<'ast> { fn fold_function(&mut self, f: TypedFunction<'ast, T>) -> TypedFunction<'ast, T> { self.substitution = HashMap::new(); for arg in &f.arguments { - self.substitution.insert(arg.id.id.clone(), 0); + self.substitution.insert(arg.id.id.id.clone(), 0); } fold_function(self, f) @@ -412,7 +454,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Unroller<'ast> { fn fold_name(&mut self, n: Identifier<'ast>) -> Identifier<'ast> { Identifier { - version: self.substitution.get(&n).unwrap_or(&0).clone(), + version: self.substitution.get(&n.id).unwrap_or(&0).clone(), ..n } } @@ -683,8 +725,8 @@ mod tests { let s = TypedStatement::For( Variable::field_element("i".into()), - Bn128Field::from(2), - Bn128Field::from(5), + FieldElementExpression::Number(Bn128Field::from(2)), + FieldElementExpression::Number(Bn128Field::from(5)), vec![ TypedStatement::Declaration(Variable::field_element("foo".into())), TypedStatement::Definition( @@ -738,6 +780,46 @@ mod tests { assert_eq!(u.fold_statement(s), expected); } + #[test] + fn idempotence() { + // an already unrolled program should not be modified by unrolling again + + // a = 5 + // a_1 = 6 + // a_2 = 7 + + // should be turned into + // a = 5 + // a_1 = 6 + // a_2 = 7 + + let mut u = Unroller::new(); + + let s = TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element( + Identifier::from("a").version(0), + )), + FieldElementExpression::Number(Bn128Field::from(5)).into(), + ); + assert_eq!(u.fold_statement(s.clone()), vec![s]); + + let s = TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element( + Identifier::from("a").version(1), + )), + FieldElementExpression::Number(Bn128Field::from(6)).into(), + ); + assert_eq!(u.fold_statement(s.clone()), vec![s]); + + let s = TypedStatement::Definition( + TypedAssignee::Identifier(Variable::field_element( + Identifier::from("a").version(2), + )), + FieldElementExpression::Number(Bn128Field::from(7)).into(), + ); + assert_eq!(u.fold_statement(s.clone()), vec![s]); + } + #[test] fn definition() { // field a diff --git a/zokrates_core/src/typed_absy/abi.rs b/zokrates_core/src/typed_absy/abi.rs new file mode 100644 index 00000000..f80f0f01 --- /dev/null +++ b/zokrates_core/src/typed_absy/abi.rs @@ -0,0 +1,342 @@ +use typed_absy::types::Signature; +use typed_absy::Type; + +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +pub struct AbiInput { + pub name: String, + pub public: bool, + #[serde(flatten)] + pub ty: Type, +} + +pub type AbiOutput = Type; + +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +pub struct Abi { + pub inputs: Vec, + pub outputs: Vec, +} + +impl Abi { + pub fn signature(&self) -> Signature { + Signature { + inputs: self.inputs.iter().map(|i| i.ty.clone()).collect(), + outputs: self.outputs.clone(), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::HashMap; + use typed_absy::types::{ArrayType, FunctionKey, StructMember}; + use typed_absy::{ + Parameter, Type, TypedFunction, TypedFunctionSymbol, TypedModule, TypedProgram, Variable, + }; + use zokrates_field::Bn128Field; + + #[test] + fn generate_abi_from_typed_ast() { + let mut functions = HashMap::new(); + functions.insert( + FunctionKey::with_id("main"), + TypedFunctionSymbol::Here(TypedFunction { + arguments: vec![ + Parameter { + id: Variable::field_element("a".into()), + private: true, + }, + Parameter { + id: Variable::boolean("b".into()), + private: false, + }, + ], + statements: vec![], + signature: Signature::new() + .inputs(vec![Type::FieldElement, Type::Boolean]) + .outputs(vec![Type::FieldElement]), + }), + ); + + let mut modules = HashMap::new(); + modules.insert("main".into(), TypedModule { functions }); + + let typed_ast: TypedProgram = TypedProgram { + main: "main".into(), + modules, + }; + + let abi: Abi = typed_ast.abi(); + let expected_abi = Abi { + inputs: vec![ + AbiInput { + name: String::from("a"), + public: false, + ty: Type::FieldElement, + }, + AbiInput { + name: String::from("b"), + public: true, + ty: Type::Boolean, + }, + ], + outputs: vec![Type::FieldElement], + }; + + assert_eq!(expected_abi, abi); + } + + #[test] + fn serialize_empty() { + let abi: Abi = Abi { + inputs: vec![], + outputs: vec![], + }; + + let json = serde_json::to_string(&abi).unwrap(); + assert_eq!(&json, r#"{"inputs":[],"outputs":[]}"#) + } + + #[test] + fn serialize_field() { + let abi: Abi = Abi { + inputs: vec![ + AbiInput { + name: String::from("a"), + public: true, + ty: Type::FieldElement, + }, + AbiInput { + name: String::from("b"), + public: true, + ty: Type::FieldElement, + }, + ], + outputs: vec![Type::FieldElement], + }; + + let json = serde_json::to_string_pretty(&abi).unwrap(); + assert_eq!( + &json, + r#"{ + "inputs": [ + { + "name": "a", + "public": true, + "type": "field" + }, + { + "name": "b", + "public": true, + "type": "field" + } + ], + "outputs": [ + { + "type": "field" + } + ] +}"# + ) + } + + #[test] + fn serialize_struct() { + let abi: Abi = Abi { + inputs: vec![AbiInput { + name: String::from("foo"), + public: true, + ty: Type::Struct(vec![ + StructMember::new(String::from("a"), Type::FieldElement), + StructMember::new(String::from("b"), Type::Boolean), + ]), + }], + outputs: vec![Type::Struct(vec![ + StructMember::new(String::from("a"), Type::FieldElement), + StructMember::new(String::from("b"), Type::Boolean), + ])], + }; + + let json = serde_json::to_string_pretty(&abi).unwrap(); + assert_eq!( + &json, + r#"{ + "inputs": [ + { + "name": "foo", + "public": true, + "type": "struct", + "components": [ + { + "name": "a", + "type": "field" + }, + { + "name": "b", + "type": "bool" + } + ] + } + ], + "outputs": [ + { + "type": "struct", + "components": [ + { + "name": "a", + "type": "field" + }, + { + "name": "b", + "type": "bool" + } + ] + } + ] +}"# + ) + } + + #[test] + fn serialize_nested_struct() { + let abi: Abi = Abi { + inputs: vec![AbiInput { + name: String::from("foo"), + public: true, + ty: Type::Struct(vec![StructMember::new( + String::from("bar"), + Type::Struct(vec![ + StructMember::new(String::from("a"), Type::FieldElement), + StructMember::new(String::from("b"), Type::FieldElement), + ]), + )]), + }], + outputs: vec![], + }; + + let json = serde_json::to_string_pretty(&abi).unwrap(); + assert_eq!( + &json, + r#"{ + "inputs": [ + { + "name": "foo", + "public": true, + "type": "struct", + "components": [ + { + "name": "bar", + "type": "struct", + "components": [ + { + "name": "a", + "type": "field" + }, + { + "name": "b", + "type": "field" + } + ] + } + ] + } + ], + "outputs": [] +}"# + ) + } + + #[test] + fn serialize_struct_array() { + let abi: Abi = Abi { + inputs: vec![AbiInput { + name: String::from("a"), + public: false, + ty: Type::Array(ArrayType::new( + Type::Struct(vec![ + StructMember::new(String::from("b"), Type::FieldElement), + StructMember::new(String::from("c"), Type::Boolean), + ]), + 2, + )), + }], + outputs: vec![Type::Boolean], + }; + + let json = serde_json::to_string_pretty(&abi).unwrap(); + assert_eq!( + &json, + r#"{ + "inputs": [ + { + "name": "a", + "public": false, + "type": "array", + "components": { + "size": 2, + "type": "struct", + "components": [ + { + "name": "b", + "type": "field" + }, + { + "name": "c", + "type": "bool" + } + ] + } + } + ], + "outputs": [ + { + "type": "bool" + } + ] +}"# + ) + } + + #[test] + fn serialize_multi_dimensional_array() { + let abi: Abi = Abi { + inputs: vec![AbiInput { + name: String::from("a"), + public: false, + ty: Type::Array(ArrayType::new( + Type::Array(ArrayType::new(Type::FieldElement, 2)), + 2, + )), + }], + outputs: vec![Type::FieldElement], + }; + + let json = serde_json::to_string_pretty(&abi).unwrap(); + assert_eq!( + &json, + r#"{ + "inputs": [ + { + "name": "a", + "public": false, + "type": "array", + "components": { + "size": 2, + "type": "array", + "components": { + "size": 2, + "type": "field" + } + } + } + ], + "outputs": [ + { + "type": "field" + } + ] +}"# + ) + } +} diff --git a/zokrates_core/src/typed_absy/folder.rs b/zokrates_core/src/typed_absy/folder.rs index 54d47998..edcad635 100644 --- a/zokrates_core/src/typed_absy/folder.rs +++ b/zokrates_core/src/typed_absy/folder.rs @@ -1,6 +1,7 @@ // Generic walk through a typed AST. Not mutating in place use crate::typed_absy::*; +use typed_absy::types::StructMember; use zokrates_field::Field; pub trait Folder<'ast, T: Field>: Sized { @@ -116,7 +117,7 @@ pub trait Folder<'ast, T: Field>: Sized { } fn fold_struct_expression_inner( &mut self, - ty: &Vec<(MemberId, Type)>, + ty: &Vec, e: StructExpressionInner<'ast, T>, ) -> StructExpressionInner<'ast, T> { fold_struct_expression_inner(self, ty, e) @@ -208,7 +209,7 @@ pub fn fold_array_expression_inner<'ast, T: Field, F: Folder<'ast, T>>( pub fn fold_struct_expression_inner<'ast, T: Field, F: Folder<'ast, T>>( f: &mut F, - _: &Vec<(MemberId, Type)>, + _: &Vec, e: StructExpressionInner<'ast, T>, ) -> StructExpressionInner<'ast, T> { match e { @@ -346,6 +347,10 @@ pub fn fold_boolean_expression<'ast, T: Field, F: Folder<'ast, T>>( let e = f.fold_boolean_expression(e); BooleanExpression::Not(box e) } + BooleanExpression::FunctionCall(key, exps) => { + let exps = exps.into_iter().map(|e| f.fold_expression(e)).collect(); + BooleanExpression::FunctionCall(key, exps) + } BooleanExpression::IfElse(box cond, box cons, box alt) => { let cond = f.fold_boolean_expression(cond); let cons = f.fold_boolean_expression(cons); diff --git a/zokrates_core/src/typed_absy/identifier.rs b/zokrates_core/src/typed_absy/identifier.rs new file mode 100644 index 00000000..b289e021 --- /dev/null +++ b/zokrates_core/src/typed_absy/identifier.rs @@ -0,0 +1,83 @@ +use std::fmt; +use typed_absy::types::FunctionKey; +use typed_absy::TypedModuleId; + +#[derive(Debug, PartialEq, Clone, Hash, Eq)] +pub enum CoreIdentifier<'ast> { + Source(&'ast str), + Internal(&'static str, usize), +} + +impl<'ast> fmt::Display for CoreIdentifier<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + CoreIdentifier::Source(s) => write!(f, "{}", s), + CoreIdentifier::Internal(s, i) => write!(f, "#INTERNAL#_{}_{}", s, i), + } + } +} + +/// A identifier for a variable +#[derive(Debug, PartialEq, Clone, Hash, Eq)] +pub struct Identifier<'ast> { + /// the id of the variable + pub id: CoreIdentifier<'ast>, + /// the version of the variable, used after SSA transformation + pub version: usize, + /// the call stack of the variable, used when inlining + pub stack: Vec<(TypedModuleId, FunctionKey<'ast>, usize)>, +} + +impl<'ast> fmt::Display for Identifier<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.stack.len() == 0 && self.version == 0 { + write!(f, "{}", self.id) + } else { + write!( + f, + "{}_{}_{}", + self.stack + .iter() + .map(|(name, sig, count)| format!( + "{}_{}_{}", + name.display(), + sig.to_slug(), + count + )) + .collect::>() + .join("_"), + self.id, + self.version + ) + } + } +} + +impl<'ast> From<&'ast str> for Identifier<'ast> { + fn from(id: &'ast str) -> Identifier<'ast> { + Identifier::from(CoreIdentifier::Source(id)) + } +} + +impl<'ast> From> for Identifier<'ast> { + fn from(id: CoreIdentifier<'ast>) -> Identifier<'ast> { + Identifier { + id, + version: 0, + stack: vec![], + } + } +} + +#[cfg(test)] +impl<'ast> Identifier<'ast> { + pub fn version(mut self, version: usize) -> Self { + self.version = version; + self + } + + pub fn stack(mut self, stack: Vec<(TypedModuleId, FunctionKey<'ast>, usize)>) -> Self { + self.stack = stack; + self + } +} diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index b4682b67..aa1c8c46 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -5,16 +5,19 @@ //! @author Jacob Eberhardt //! @date 2017 +pub mod abi; pub mod folder; +pub mod identifier; mod parameter; pub mod types; mod variable; pub use crate::typed_absy::parameter::Parameter; -pub use crate::typed_absy::types::Type; +pub use crate::typed_absy::types::{Signature, Type}; pub use crate::typed_absy::variable::Variable; +use std::path::PathBuf; -use crate::typed_absy::types::{FunctionKey, MemberId, Signature}; +use crate::typed_absy::types::{FunctionKey, MemberId}; use embed::FlatEmbed; use std::collections::HashMap; use std::convert::TryFrom; @@ -22,20 +25,12 @@ use std::fmt; use zokrates_field::Field; pub use self::folder::Folder; - -/// A identifier for a variable -#[derive(Debug, PartialEq, Clone, Hash, Eq)] -pub struct Identifier<'ast> { - /// the id of the variable - pub id: &'ast str, - /// the version of the variable, used after SSA transformation - pub version: usize, - /// the call stack of the variable, used when inlining - pub stack: Vec<(TypedModuleId, FunctionKey<'ast>, usize)>, -} +use typed_absy::abi::{Abi, AbiInput}; +pub use typed_absy::identifier::Identifier; +use typed_absy::types::StructMember; /// An identifier for a `TypedModule`. Typically a path or uri. -pub type TypedModuleId = String; +pub type TypedModuleId = PathBuf; /// A collection of `TypedModule`s pub type TypedModules<'ast, T> = HashMap>; @@ -53,13 +48,41 @@ pub struct TypedProgram<'ast, T> { pub main: TypedModuleId, } +impl<'ast, T: Field> TypedProgram<'ast, T> { + pub fn abi(&self) -> Abi { + let main = self.modules[&self.main] + .functions + .iter() + .find(|(id, _)| id.id == "main") + .unwrap() + .1; + let main = match main { + TypedFunctionSymbol::Here(main) => main, + _ => unreachable!(), + }; + + Abi { + inputs: main + .arguments + .iter() + .map(|p| AbiInput { + public: !p.private, + name: p.id.id.to_string(), + ty: p.id._type.clone(), + }) + .collect(), + outputs: main.signature.outputs.clone(), + } + } +} + impl<'ast, T: Field> fmt::Display for TypedProgram<'ast, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for (module_id, module) in &self.modules { writeln!( f, "| {}: |{}", - module_id, + module_id.display(), if *module_id == self.main { "<---- main" } else { @@ -82,49 +105,6 @@ pub struct TypedModule<'ast, T> { pub functions: TypedFunctionSymbols<'ast, T>, } -impl<'ast> fmt::Display for Identifier<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.stack.len() == 0 && self.version == 0 { - write!(f, "{}", self.id) - } else { - write!( - f, - "{}_{}_{}", - self.stack - .iter() - .map(|(name, sig, count)| format!("{}_{}_{}", name, sig.to_slug(), count)) - .collect::>() - .join("_"), - self.id, - self.version - ) - } - } -} - -impl<'ast> From<&'ast str> for Identifier<'ast> { - fn from(id: &'ast str) -> Identifier<'ast> { - Identifier { - id, - version: 0, - stack: vec![], - } - } -} - -#[cfg(test)] -impl<'ast> Identifier<'ast> { - pub fn version(mut self, version: usize) -> Self { - self.version = version; - self - } - - pub fn stack(mut self, stack: Vec<(TypedModuleId, FunctionKey<'ast>, usize)>) -> Self { - self.stack = stack; - self - } -} - #[derive(Clone, PartialEq)] pub enum TypedFunctionSymbol<'ast, T> { Here(TypedFunction<'ast, T>), @@ -169,7 +149,10 @@ impl<'ast, T: Field> fmt::Display for TypedModule<'ast, T> { TypedFunctionSymbol::Here(ref function) => format!("def {}{}", key.id, function), TypedFunctionSymbol::There(ref fun_key, ref module_id) => format!( "import {} from \"{}\" as {} // with signature {}", - fun_key.id, module_id, key.id, key.signature + fun_key.id, + module_id.display(), + key.id, + key.signature ), TypedFunctionSymbol::Flat(ref flat_fun) => { format!("def {}{}:\n\t// hidden", key.id, flat_fun.signature::()) @@ -209,7 +192,7 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedFunction<'ast, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, - "({}) -> ({}):\n{}", + "({}) -> ({}):", self.arguments .iter() .map(|x| format!("{}", x)) @@ -221,12 +204,16 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedFunction<'ast, T> { .map(|x| format!("{}", x)) .collect::>() .join(", "), - self.statements - .iter() - .map(|x| format!("\t{}", x)) - .collect::>() - .join("\n") - ) + )?; + + writeln!(f, "")?; + + for s in &self.statements { + s.fmt_indented(f, 1)?; + writeln!(f, "")?; + } + + Ok(()) } } @@ -263,16 +250,19 @@ impl<'ast, T> Typed for TypedAssignee<'ast, T> { TypedAssignee::Select(ref a, _) => { let a_type = a.get_type(); match a_type { - Type::Array(box t, _) => t, + Type::Array(t) => *t.ty, _ => unreachable!("an array element should only be defined over arrays"), } } TypedAssignee::Member(ref s, ref m) => { let s_type = s.get_type(); match s_type { - Type::Struct(members) => { - members.iter().find(|(id, _)| id == m).unwrap().1.clone() - } + Type::Struct(members) => *members + .iter() + .find(|member| member.id == *m) + .unwrap() + .ty + .clone(), _ => unreachable!("a struct access should only be defined over structs"), } } @@ -307,7 +297,12 @@ pub enum TypedStatement<'ast, T> { Definition(TypedAssignee<'ast, T>, TypedExpression<'ast, T>), Declaration(Variable<'ast>), Condition(TypedExpression<'ast, T>, TypedExpression<'ast, T>), - For(Variable<'ast>, T, T, Vec>), + For( + Variable<'ast>, + FieldElementExpression<'ast, T>, + FieldElementExpression<'ast, T>, + Vec>, + ), MultipleDefinition(Vec>, TypedExpressionList<'ast, T>), } @@ -345,6 +340,23 @@ impl<'ast, T: fmt::Debug> fmt::Debug for TypedStatement<'ast, T> { } } +impl<'ast, T: fmt::Display> TypedStatement<'ast, T> { + fn fmt_indented(&self, f: &mut fmt::Formatter, depth: usize) -> fmt::Result { + match self { + TypedStatement::For(variable, from, to, statements) => { + write!(f, "{}", "\t".repeat(depth))?; + writeln!(f, "for {} in {}..{} do", variable, from, to)?; + for s in statements { + s.fmt_indented(f, depth + 1)?; + writeln!(f, "")?; + } + writeln!(f, "{}endfor", "\t".repeat(depth)) + } + s => write!(f, "{}{}", "\t".repeat(depth), s), + } + } +} + impl<'ast, T: fmt::Display> fmt::Display for TypedStatement<'ast, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -461,7 +473,7 @@ impl<'ast, T: fmt::Display> fmt::Display for StructExpression<'ast, T> { "{{{}}}", self.ty .iter() - .map(|(id, _)| id) + .map(|member| member.id.clone()) .zip(values.iter()) .map(|(id, o)| format!("{}: {}", id, o)) .collect::>() @@ -630,6 +642,7 @@ pub enum BooleanExpression<'ast, T> { Box>, ), Member(Box>, MemberId), + FunctionCall(FunctionKey<'ast>, Vec>), Select( Box>, Box>, @@ -638,7 +651,7 @@ pub enum BooleanExpression<'ast, T> { /// An expression of type `array` /// # Remarks -/// * Contrary to basic types which represented as enums, we wrap an enum `ArrayExpressionInner` in a struct in order to keep track of the type (content and size) +/// * Contrary to basic types which are represented as enums, we wrap an enum `ArrayExpressionInner` in a struct in order to keep track of the type (content and size) /// of the array. Only using an enum would require generics, which would propagate up to TypedExpression which we want to keep simple, hence this "runtime" /// type checking #[derive(Clone, PartialEq, Hash, Eq)] @@ -695,12 +708,12 @@ impl<'ast, T> ArrayExpression<'ast, T> { #[derive(Clone, PartialEq, Hash, Eq)] pub struct StructExpression<'ast, T> { - ty: Vec<(MemberId, Type)>, + ty: Vec, inner: StructExpressionInner<'ast, T>, } impl<'ast, T> StructExpression<'ast, T> { - pub fn ty(&self) -> &Vec<(MemberId, Type)> { + pub fn ty(&self) -> &Vec { &self.ty } @@ -731,7 +744,7 @@ pub enum StructExpressionInner<'ast, T> { } impl<'ast, T> StructExpressionInner<'ast, T> { - pub fn annotate(self, ty: Vec<(MemberId, Type)>) -> StructExpression<'ast, T> { + pub fn annotate(self, ty: Vec) -> StructExpression<'ast, T> { StructExpression { ty, inner: self } } } @@ -833,6 +846,16 @@ impl<'ast, T: fmt::Display> fmt::Display for BooleanExpression<'ast, T> { 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 k, ref p) => { + write!(f, "{}(", k.id,)?; + for (i, param) in p.iter().enumerate() { + write!(f, "{}", param)?; + if i < p.len() - 1 { + write!(f, ", ")?; + } + } + write!(f, ")") + } BooleanExpression::IfElse(ref condition, ref consequent, ref alternative) => write!( f, "if {} then {} else {} fi", @@ -900,6 +923,11 @@ impl<'ast, T: fmt::Debug> fmt::Debug for BooleanExpression<'ast, T> { BooleanExpression::Gt(ref lhs, ref rhs) => write!(f, "Gt({:?}, {:?})", lhs, rhs), BooleanExpression::And(ref lhs, ref rhs) => write!(f, "And({:?}, {:?})", lhs, rhs), BooleanExpression::Not(ref exp) => write!(f, "Not({:?})", exp), + BooleanExpression::FunctionCall(ref i, ref p) => { + write!(f, "FunctionCall({:?}, (", i)?; + f.debug_list().entries(p.iter()).finish()?; + write!(f, ")") + } BooleanExpression::Select(ref array, ref index) => { write!(f, "Select({:?}, {:?})", array, index) } @@ -1026,7 +1054,7 @@ impl<'ast, T: fmt::Debug> fmt::Debug for TypedExpressionList<'ast, T> { } } -// Common behaviour accross expressions +// Common behaviour across expressions pub trait IfElse<'ast, T> { fn if_else(condition: BooleanExpression<'ast, T>, consequence: Self, alternative: Self) @@ -1096,7 +1124,7 @@ impl<'ast, T> Select<'ast, T> for BooleanExpression<'ast, T> { impl<'ast, T> Select<'ast, T> for ArrayExpression<'ast, T> { fn select(array: ArrayExpression<'ast, T>, index: FieldElementExpression<'ast, T>) -> Self { let (ty, size) = match array.inner_type() { - Type::Array(inner, size) => (inner.clone(), size.clone()), + Type::Array(array_type) => (array_type.ty.clone(), array_type.size.clone()), _ => unreachable!(), }; @@ -1137,16 +1165,16 @@ impl<'ast, T> Member<'ast, T> for ArrayExpression<'ast, T> { let ty = members .into_iter() - .find(|(id, _)| *id == member_id) + .find(|member| *member.id == member_id) .unwrap() - .1; + .ty; - let (ty, size) = match ty { - Type::Array(box ty, size) => (ty, size), + let (ty, size) = match *ty { + Type::Array(array_type) => (array_type.ty, array_type.size), _ => unreachable!(), }; - ArrayExpressionInner::Member(box s, member_id).annotate(ty, size) + ArrayExpressionInner::Member(box s, member_id).annotate(*ty, size) } } @@ -1156,11 +1184,11 @@ impl<'ast, T> Member<'ast, T> for StructExpression<'ast, T> { let ty = members .into_iter() - .find(|(id, _)| *id == member_id) + .find(|member| *member.id == member_id) .unwrap() - .1; + .ty; - let members = match ty { + let members = match *ty { Type::Struct(members) => members, _ => unreachable!(), }; diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_core/src/typed_absy/types.rs index 7cd73f80..9dc1583e 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_core/src/typed_absy/types.rs @@ -5,11 +5,49 @@ pub type Identifier<'ast> = &'ast str; pub type MemberId = String; #[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)] +pub struct StructMember { + #[serde(rename = "name")] + pub id: MemberId, + #[serde(flatten)] + pub ty: Box, +} + +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)] +pub struct ArrayType { + pub size: usize, + #[serde(flatten)] + pub ty: Box, +} + +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)] +#[serde(tag = "type", content = "components")] pub enum Type { + #[serde(rename = "field")] FieldElement, + #[serde(rename = "bool")] Boolean, - Array(Box, usize), - Struct(Vec<(MemberId, Type)>), + #[serde(rename = "array")] + Array(ArrayType), + #[serde(rename = "struct")] + Struct(Vec), +} + +impl ArrayType { + pub fn new(ty: Type, size: usize) -> Self { + ArrayType { + ty: Box::new(ty), + size, + } + } +} + +impl StructMember { + pub fn new(id: String, ty: Type) -> Self { + StructMember { + id, + ty: Box::new(ty), + } + } } impl fmt::Display for Type { @@ -17,13 +55,13 @@ impl fmt::Display for Type { match self { Type::FieldElement => write!(f, "field"), Type::Boolean => write!(f, "bool"), - Type::Array(ref ty, ref size) => write!(f, "{}[{}]", ty, size), + Type::Array(ref array_type) => write!(f, "{}[{}]", array_type.ty, array_type.size), Type::Struct(ref members) => write!( f, "{{{}}}", members .iter() - .map(|(id, t)| format!("{}: {}", id, t)) + .map(|member| format!("{}: {}", member.id, member.ty)) .collect::>() .join(", ") ), @@ -36,13 +74,13 @@ impl fmt::Debug for Type { match self { Type::FieldElement => write!(f, "field"), Type::Boolean => write!(f, "bool"), - Type::Array(ref ty, ref size) => write!(f, "{:?}[{:?}]", ty, size), + Type::Array(ref array_type) => write!(f, "{}[{}]", array_type.ty, array_type.size), Type::Struct(ref members) => write!( f, "{{{}}}", members .iter() - .map(|(id, t)| format!("{:?}: {:?}", id, t)) + .map(|member| format!("{}: {}", member.id, member.ty)) .collect::>() .join(", ") ), @@ -52,19 +90,19 @@ impl fmt::Debug for Type { impl Type { pub fn array(ty: Type, size: usize) -> Self { - Type::Array(box ty, size) + Type::Array(ArrayType::new(ty, size)) } fn to_slug(&self) -> String { match self { Type::FieldElement => String::from("f"), Type::Boolean => String::from("b"), - Type::Array(box ty, size) => format!("{}[{}]", ty.to_slug(), size), + Type::Array(array_type) => format!("{}[{}]", array_type.ty.to_slug(), array_type.size), Type::Struct(members) => format!( "{{{}}}", members .iter() - .map(|(id, ty)| format!("{}:{}", id, ty)) + .map(|member| format!("{}:{}", member.id, member.ty)) .collect::>() .join(",") ), @@ -76,8 +114,11 @@ impl Type { match self { Type::FieldElement => 1, Type::Boolean => 1, - Type::Array(ty, size) => size * ty.get_primitive_count(), - Type::Struct(members) => members.iter().map(|(_, t)| t.get_primitive_count()).sum(), + Type::Array(array_type) => array_type.size * array_type.ty.get_primitive_count(), + Type::Struct(members) => members + .iter() + .map(|member| member.ty.get_primitive_count()) + .sum(), } } } @@ -284,7 +325,7 @@ mod tests { #[test] fn array() { - let t = Type::Array(box Type::FieldElement, 42); + let t = Type::Array(ArrayType::new(Type::FieldElement, 42)); assert_eq!(t.get_primitive_count(), 42); } } diff --git a/zokrates_core/src/typed_absy/variable.rs b/zokrates_core/src/typed_absy/variable.rs index 52814062..eb11caf6 100644 --- a/zokrates_core/src/typed_absy/variable.rs +++ b/zokrates_core/src/typed_absy/variable.rs @@ -1,6 +1,7 @@ -use crate::typed_absy::types::{MemberId, Type}; +use crate::typed_absy::types::Type; use crate::typed_absy::Identifier; use std::fmt; +use typed_absy::types::StructMember; #[derive(Clone, PartialEq, Hash, Eq)] pub struct Variable<'ast> { @@ -26,7 +27,7 @@ impl<'ast> Variable<'ast> { Self::with_id_and_type(id, Type::array(ty, size)) } - pub fn struc(id: Identifier<'ast>, ty: Vec<(MemberId, Type)>) -> Variable<'ast> { + pub fn struc(id: Identifier<'ast>, ty: Vec) -> Variable<'ast> { Self::with_id_and_type(id, Type::Struct(ty)) } diff --git a/zokrates_core/tests/wasm.rs b/zokrates_core/tests/wasm.rs new file mode 100644 index 00000000..b5e9a692 --- /dev/null +++ b/zokrates_core/tests/wasm.rs @@ -0,0 +1,36 @@ +wasm_bindgen_test_configure!(run_in_browser); + +extern crate wasm_bindgen_test; +extern crate zokrates_core; +extern crate zokrates_field; +use wasm_bindgen_test::*; +use zokrates_core::flat_absy::FlatVariable; +use zokrates_core::ir::{Function, Prog, Statement}; +use zokrates_core::proof_system::ProofSystem; +use zokrates_field::Bn128Field; + +use zokrates_core::proof_system::G16; + +#[wasm_bindgen_test] +fn generate_proof() { + let program: Prog = Prog { + main: Function { + id: String::from("main"), + arguments: vec![FlatVariable::new(0)], + returns: vec![FlatVariable::new(0)], + statements: vec![Statement::Constraint( + FlatVariable::new(0).into(), + FlatVariable::new(0).into(), + )], + }, + private: vec![false], + }; + + let witness = program + .clone() + .execute(&vec![Bn128Field::from(42)]) + .unwrap(); + + let keys = G16::setup(program.clone()); + let _proof = G16::generate_proof(program, witness, keys.pk); +} diff --git a/zokrates_core_test/Cargo.toml b/zokrates_core_test/Cargo.toml index f6908f14..13e73f13 100644 --- a/zokrates_core_test/Cargo.toml +++ b/zokrates_core_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_core_test" -version = "0.1.0" +version = "0.1.1" authors = ["schaeff "] edition = "2018" diff --git a/zokrates_core_test/tests/tests/arrays/fun_spread.json b/zokrates_core_test/tests/tests/arrays/fun_spread.json new file mode 100644 index 00000000..5583d306 --- /dev/null +++ b/zokrates_core_test/tests/tests/arrays/fun_spread.json @@ -0,0 +1,6 @@ +{ + "entry_point": "./tests/tests/arrays/fun_spread.zok", + "max_constraint_count": 1050, + "tests": [ + ] +} \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/arrays/fun_spread.zok b/zokrates_core_test/tests/tests/arrays/fun_spread.zok new file mode 100644 index 00000000..a62a95e0 --- /dev/null +++ b/zokrates_core_test/tests/tests/arrays/fun_spread.zok @@ -0,0 +1,7 @@ +import "utils/pack/nonStrictUnpack256.zok" as unpack256 + +def main(field[2] inputs) -> (field[512]): + + field[512] preimage512 = [...unpack256(inputs[0]), ...unpack256(inputs[1])] + + return preimage512 \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/complex_call.json b/zokrates_core_test/tests/tests/complex_call.json new file mode 100644 index 00000000..5b300357 --- /dev/null +++ b/zokrates_core_test/tests/tests/complex_call.json @@ -0,0 +1,15 @@ +{ + "entry_point": "./tests/tests/complex_call.zok", + "tests": [ + { + "input": { + "values": ["1", "2", "0", "1", "2", "3", "4"] + }, + "output": { + "Ok": { + "values": ["1", "1", "3", "4"] + } + } + } + ] +} \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/complex_call.zok b/zokrates_core_test/tests/tests/complex_call.zok new file mode 100644 index 00000000..7f1780c3 --- /dev/null +++ b/zokrates_core_test/tests/tests/complex_call.zok @@ -0,0 +1,11 @@ +struct Foo { + bool[2] a + field b +} + +def f(bool a, field b, Foo c, field[2] d) -> (Foo, field): + return Foo { a: [a, a], b: d[0] }, if c.a[0] then b + c.b else d[1] fi + +def main(bool a, field b, Foo c, field[2] d) -> (Foo, field): + Foo e, field f = f(a, b, c, d) + return e, f \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/import/dep/dep/foo.zok b/zokrates_core_test/tests/tests/import/dep/dep/foo.zok new file mode 100644 index 00000000..4498c0fd --- /dev/null +++ b/zokrates_core_test/tests/tests/import/dep/dep/foo.zok @@ -0,0 +1,2 @@ +def foo() -> (field): + return 1 \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/import/dep/foo.zok b/zokrates_core_test/tests/tests/import/dep/foo.zok new file mode 100644 index 00000000..93e89cff --- /dev/null +++ b/zokrates_core_test/tests/tests/import/dep/foo.zok @@ -0,0 +1,4 @@ +from "./dep/foo" import foo as bar + +def foo() -> (field): + return 2 + bar() \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/import/import.json b/zokrates_core_test/tests/tests/import/import.json new file mode 100644 index 00000000..5a27ad8c --- /dev/null +++ b/zokrates_core_test/tests/tests/import/import.json @@ -0,0 +1,15 @@ +{ + "entry_point": "./tests/tests/import/import.zok", + "tests": [ + { + "input": { + "values": [] + }, + "output": { + "Ok": { + "values": ["3"] + } + } + } + ] +} \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/import/import.zok b/zokrates_core_test/tests/tests/import/import.zok new file mode 100644 index 00000000..cfe5e851 --- /dev/null +++ b/zokrates_core_test/tests/tests/import/import.zok @@ -0,0 +1,4 @@ +from "./dep/foo" import foo + +def main() -> (field): + return foo() \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/memoize/dep.zok b/zokrates_core_test/tests/tests/memoize/dep.zok new file mode 100644 index 00000000..df49dc48 --- /dev/null +++ b/zokrates_core_test/tests/tests/memoize/dep.zok @@ -0,0 +1,3 @@ +def dep(field a) -> (field): // this costs 2 constraits per call + field res = a ** 4 + return res \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/memoize/memoize.json b/zokrates_core_test/tests/tests/memoize/memoize.json new file mode 100644 index 00000000..03ad5490 --- /dev/null +++ b/zokrates_core_test/tests/tests/memoize/memoize.json @@ -0,0 +1,16 @@ +{ + "entry_point": "./tests/tests/memoize/memoize.zok", + "max_constraint_count": 14, + "tests": [ + { + "input": { + "values": ["3"] + }, + "output": { + "Ok": { + "values": [] + } + } + } + ] +} \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/memoize/memoize.zok b/zokrates_core_test/tests/tests/memoize/memoize.zok new file mode 100644 index 00000000..e092c80b --- /dev/null +++ b/zokrates_core_test/tests/tests/memoize/memoize.zok @@ -0,0 +1,14 @@ +from "./dep.zok" import dep as dep + +def local(field a) -> (field): // this costs 3 constraints per call + field res = a ** 8 + return res // currently expressions in the return statement don't get memoized + +def main(field a) -> (): + // calling a local function many times with the same arg should cost only once + local(a) + local(a) + local(a) + local(a) + local(a) == 5 * (a ** 8) + + // calling an imported function many times with the same arg should cost only once + dep(a) + dep(a) + dep(a) + dep(a) + dep(a) == 5 * (a ** 4) + + return diff --git a/zokrates_core_test/tests/tests/nested_loop.json b/zokrates_core_test/tests/tests/nested_loop.json new file mode 100644 index 00000000..c71202c9 --- /dev/null +++ b/zokrates_core_test/tests/tests/nested_loop.json @@ -0,0 +1,25 @@ +{ + "entry_point": "./tests/tests/nested_loop.zok", + "tests": [ + { + "input": { + "values": ["1", "2", "3", "4"] + }, + "output": { + "Ok": { + "values": ["4838400", "10", "25"] + } + } + }, + { + "input": { + "values": ["0", "1", "2", "3"] + }, + "output": { + "Ok": { + "values": ["0", "10", "25"] + } + } + } + ] +} \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/nested_loop.zok b/zokrates_core_test/tests/tests/nested_loop.zok new file mode 100644 index 00000000..2d00f1a0 --- /dev/null +++ b/zokrates_core_test/tests/tests/nested_loop.zok @@ -0,0 +1,27 @@ +def main(field[4] values) -> (field, field, field): + field res0 = 1 + field res1 = 0 + + field counter = 0 + + for field i in 0..4 do + for field j in i..4 do + counter = counter + 1 + res0 = res0 * (values[i] + values[j]) + endfor + endfor + + for field i in 0..counter do + res1 = res1 + 1 + endfor + + field res2 = 0 + field i = 0 + for field i in i..5 do + i = 5 + for field i in 0..i do + res2 = res2 + 1 + endfor + endfor + + return res0, res1, res2 \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/precedence.zok b/zokrates_core_test/tests/tests/precedence.zok index 48356e0d..86404b44 100644 --- a/zokrates_core_test/tests/tests/precedence.zok +++ b/zokrates_core_test/tests/tests/precedence.zok @@ -1,5 +1,5 @@ def main(field g) -> (field): - 9 == 1 + 2 * 2 ** 2 // Checks precedence of arithmetic operators (expecting transitiv behaviour) + 9 == 1 + 2 * 2 ** 2 // Checks precedence of arithmetic operators (expecting transitive behaviour) 9 == 2 ** 2 * 2 + 1 7 == 2 ** 2 * 2 - 1 3 == 2 ** 2 / 2 + 1 diff --git a/zokrates_core_test/tests/tests/split_bn.json b/zokrates_core_test/tests/tests/split_bn.json index d5781e31..0fd9a5bc 100644 --- a/zokrates_core_test/tests/tests/split_bn.json +++ b/zokrates_core_test/tests/tests/split_bn.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": ["0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "1", "1", "0", "1", "0", "0", "1", "1", "0", "0", "0", "1", "0", "0", "0", "0", "1", "0", "1", "1", "0", "0", "0", "0", "0", "0", "1", "0", "1", "0", "0", "0", "0", "0", "1", "0", "1", "1", "1", "0", "1", "1", "0", "0", "0", "0", "1", "1", "1", "1", "0", "0", "0", "0", "0", "1", "1", "0", "1", "0", "0", "0", "1", "1", "0", "1", "1", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "1", "1", "0", "1", "1", "0", "1", "0", "1", "1", "0", "1", "0", "0", "1", "1", "0", "1", "1", "0", "1", "0", "1", "1", "1", "1", "0", "1", "0", "1", "0", "0", "1", "1", "1", "1", "0", "1", "0", "0", "1", "0", "1", "1", "0", "1", "1", "0", "0", "0"] + "values": ["0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "1", "1", "0", "1", "0", "0", "1", "1", "0", "0", "0", "1", "0", "0", "0", "0", "1", "0", "1", "1", "0", "0", "0", "0", "0", "0", "1", "0", "1", "0", "0", "0", "0", "0", "1", "0", "1", "1", "1", "0", "1", "1", "0", "0", "0", "0", "1", "1", "1", "1", "0", "0", "0", "0", "0", "1", "1", "0", "1", "0", "0", "0", "1", "1", "0", "1", "1", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "1", "1", "0", "1", "1", "0", "1", "0", "1", "1", "0", "1", "0", "0", "1", "1", "0", "1", "1", "0", "1", "0", "1", "1", "1", "1", "0", "1", "0", "1", "0", "0", "1", "1", "1", "1", "0", "1", "0", "0", "1", "0", "1", "1", "0", "1", "1", "0", "0", "0"] } } }, @@ -28,7 +28,7 @@ }, "output": { "Ok": { - "values": ["0", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1"] + "values": ["0", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1"] } } }, diff --git a/zokrates_core_test/tests/tests/spread_slice.json b/zokrates_core_test/tests/tests/spread_slice.json index 47630aa7..d55bd61a 100644 --- a/zokrates_core_test/tests/tests/spread_slice.json +++ b/zokrates_core_test/tests/tests/spread_slice.json @@ -1,6 +1,10 @@ { "entry_point": "./tests/tests/spread_slice.zok", +<<<<<<< HEAD "curves": ["Bn128", "Bls12"], +======= + "max_constraint_count": 9, +>>>>>>> develop "tests": [ { "input": { diff --git a/zokrates_embed/Cargo.toml b/zokrates_embed/Cargo.toml index 6694f6e9..d7d92ac0 100644 --- a/zokrates_embed/Cargo.toml +++ b/zokrates_embed/Cargo.toml @@ -1,9 +1,14 @@ [package] name = "zokrates_embed" -version = "0.1.0" +version = "0.1.1" authors = ["schaeff "] edition = "2018" +[features] +default = [] +wasm = ["bellman_ce/wasm", "sapling-crypto_ce/wasm"] +multicore = ["bellman_ce/multicore", "sapling-crypto_ce/multicore"] + [dependencies] -sapling-crypto_ce = "0.1" -bellman_ce = "0.3" +bellman_ce = { version = "0.3.3", default-features = false} +sapling-crypto_ce = { version = "0.1.1", default-features = false } \ No newline at end of file diff --git a/zokrates_embed/src/lib.rs b/zokrates_embed/src/lib.rs index f7c8e885..8d689055 100644 --- a/zokrates_embed/src/lib.rs +++ b/zokrates_embed/src/lib.rs @@ -1,5 +1,5 @@ -extern crate bellman_ce as bellman; extern crate sapling_crypto_ce as sapling_crypto; +use sapling_crypto::bellman; use bellman::{ pairing::{ff::Field, Engine}, diff --git a/zokrates_field/Cargo.toml b/zokrates_field/Cargo.toml index 239d86ee..5e801d8e 100644 --- a/zokrates_field/Cargo.toml +++ b/zokrates_field/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_field" -version = "0.3.4" +version = "0.3.5" authors = ["Thibaut Schaeffer ", "Guillaume Ballet "] edition = "2018" @@ -10,14 +10,16 @@ serde_derive = "1.0" lazy_static = "1.4" bincode = "0.8.0" serde_json = "1.0" -num-traits = "0.2" -num-integer = "0.1" -bellman_ce = "0.3" +bellman_ce = { version = "0.3.3", default-features = false} sha2 = "0.8.0" +num-traits = { version = "0.2", default-features = false } +num-integer = { version = "0.1", default-features = false } +pairing_ce = "0.20" +ff_ce = { features = ["derive"], version = "0.9" } + +[dev-dependencies] +rand = "0.4" [dependencies.num-bigint] version = "0.2" features = ["serde"] - -[dev-dependencies] -rand = "0.4" diff --git a/zokrates_fs_resolver/Cargo.toml b/zokrates_fs_resolver/Cargo.toml index c58c456a..05239253 100644 --- a/zokrates_fs_resolver/Cargo.toml +++ b/zokrates_fs_resolver/Cargo.toml @@ -1,15 +1,12 @@ [package] name = "zokrates_fs_resolver" -version = "0.4.2" +version = "0.5.0" authors = ["Thibaut Schaeffer "] repository = "https://github.com/JacobEberhardt/ZoKrates.git" - -[features] -default = [] +edition = "2018" [dependencies] +zokrates_common = { path = "../zokrates_common" } [dev-dependencies] -tempfile = "3" - -[lib] \ No newline at end of file +tempfile = "3" \ No newline at end of file diff --git a/zokrates_fs_resolver/src/lib.rs b/zokrates_fs_resolver/src/lib.rs index 0d136b88..f0a86789 100644 --- a/zokrates_fs_resolver/src/lib.rs +++ b/zokrates_fs_resolver/src/lib.rs @@ -1,111 +1,126 @@ -use std::fs::File; +use std::fs::read_to_string; use std::io; -use std::io::BufReader; + use std::path::Path; use std::path::{Component, PathBuf}; +use zokrates_common::Resolver; const ZOKRATES_HOME: &str = &"ZOKRATES_HOME"; -pub fn resolve<'a>( - location: Option, - source: &'a str, -) -> Result<(BufReader, String, &'a str), io::Error> { - // the fs resolver has to be provided a location, as it supports relative paths - match location { - Some(location) => resolve_with_location(location, source), - None => Err(io::Error::new(io::ErrorKind::Other, "No location provided")), +pub struct FileSystemResolver; + +impl FileSystemResolver { + pub fn new() -> Self { + FileSystemResolver {} } } -fn resolve_with_location<'a>( - location: String, - source: &'a str, -) -> Result<(BufReader, String, &'a str), io::Error> { - let source = Path::new(source); +impl Resolver for FileSystemResolver { + fn resolve( + &self, + current_location: PathBuf, + import_location: PathBuf, + ) -> Result<(String, PathBuf), io::Error> { + let source = Path::new(&import_location); - // paths starting with `./` or `../` are interpreted relative to the current file - // other paths `abc/def` are interpreted relative to $ZOKRATES_HOME - let base = match source.components().next() { - Some(Component::CurDir) | Some(Component::ParentDir) => PathBuf::from(location), - _ => PathBuf::from( - std::env::var(ZOKRATES_HOME).expect("$ZOKRATES_HOME is not set, please set it"), - ), - }; + if !current_location.is_file() { + return Err(io::Error::new( + io::ErrorKind::Other, + format!("{} was expected to be a file", current_location.display()), + )); + } - let path_owned = base.join(PathBuf::from(source)).with_extension("zok"); + // paths starting with `./` or `../` are interpreted relative to the current file + // other paths `abc/def` are interpreted relative to $ZOKRATES_HOME + let base = match source.components().next() { + Some(Component::CurDir) | Some(Component::ParentDir) => { + Ok(PathBuf::from(current_location).parent().unwrap().into()) + } + _ => std::env::var(ZOKRATES_HOME) + .map_err(|_| { + io::Error::new( + io::ErrorKind::Other, + "$ZOKRATES_HOME is not set, please set it", + ) + }) + .map(PathBuf::from), + }?; - if path_owned.is_dir() { - return Err(io::Error::new(io::ErrorKind::Other, "Not a file")); + let path_owned = base + .join(PathBuf::from(import_location.clone())) + .with_extension("zok"); + + if !path_owned.is_file() { + return Err(io::Error::new( + io::ErrorKind::Other, + format!("No file found at {}", import_location.display()), + )); + } + + let source = read_to_string(&path_owned)?; + Ok((source, path_owned)) } - - let alias = generate_alias(source); - let next_location = generate_next_location(&path_owned)?; - - File::open(path_owned).and_then(|f| Ok((BufReader::new(f), next_location, alias))) -} - -fn generate_next_location<'a>(path: &'a PathBuf) -> Result { - path.parent() - .ok_or(io::Error::new(io::ErrorKind::Other, "Invalid path")) - .map(|v| v.to_path_buf().into_os_string().into_string().unwrap()) -} - -fn generate_alias<'a>(path: &'a Path) -> &'a str { - path.file_stem().unwrap().to_str().unwrap() } #[cfg(test)] mod tests { use super::*; + use std::fs::File; #[test] - fn valid_path_with_location() { - use std::io::Write; - + fn valid_path() { // create a source folder with a zok file let folder = tempfile::tempdir().unwrap(); let file_path = folder.path().join("bar.zok"); - let mut file = File::create(file_path).unwrap(); - writeln!(file, "some code").unwrap(); - let (_, next_location, alias) = - resolve(Some(folder.path().to_str().unwrap().to_string()), &"./bar").unwrap(); - assert_eq!(next_location, folder.path().to_str().unwrap().to_string()); - assert_eq!(alias, String::from("bar")); - } + File::create(file_path.clone()).unwrap(); - #[test] - fn valid_path_without_location() { - let res = resolve(None, &"./src/lib.rs"); - assert!(res.is_err()); + let fs_resolver = FileSystemResolver::new(); + let (_, next_location) = fs_resolver + .resolve(file_path.clone(), "./bar.zok".into()) + .unwrap(); + assert_eq!(next_location, file_path); } #[test] fn non_existing_file() { - let res = resolve(Some(String::from("./src")), &"./rubbish"); + let fs_resolver = FileSystemResolver::new(); + let res = fs_resolver.resolve("./source.zok".into(), "./rubbish".into()); assert!(res.is_err()); } #[test] fn invalid_location() { - let res = resolve(Some(String::from(",8!-$2abc")), &"./foo.zok"); + let fs_resolver = FileSystemResolver::new(); + let res = fs_resolver.resolve(",8!-$2abc".into(), "./foo".into()); assert!(res.is_err()); } #[test] fn not_a_file() { - let res = resolve(Some(String::from(".")), &"./src/"); + // create a source folder with a zok file + let folder = tempfile::tempdir().unwrap(); + let dir_path = folder.path().join("dir"); + std::fs::create_dir(dir_path.clone()).unwrap(); + + let fs_resolver = FileSystemResolver::new(); + let res = fs_resolver.resolve(".".into(), "./dir/".into()); assert!(res.is_err()); } #[test] fn no_parent() { - let res = resolve(Some(String::from(".")), &"."); + // create a source folder with a zok file + let folder = tempfile::tempdir().unwrap(); + let file_path = folder.path().join("foo.zok"); + File::create(file_path.clone()).unwrap(); + + let fs_resolver = FileSystemResolver::new(); + let res = fs_resolver.resolve(file_path, ".".into()); assert!(res.is_err()); } #[test] fn treat_relative_as_local() { - use std::io::BufRead; use std::io::Write; // create a HOME folder with a code file @@ -117,32 +132,21 @@ mod tests { // create a user folder with a code file let source_folder = tempfile::tempdir().unwrap(); let file_path = source_folder.path().join("bar.zok"); - let mut file = File::create(file_path).unwrap(); + let mut file = File::create(file_path.clone()).unwrap(); writeln!(file, "").unwrap(); // assign HOME folder to ZOKRATES_HOME std::env::set_var(ZOKRATES_HOME, zokrates_home_folder.path()); - let result = resolve( - Some( - source_folder - .path() - .to_path_buf() - .to_string_lossy() - .to_string(), - ), - &"./bar.zok", - ); + let fs_resolver = FileSystemResolver::new(); + let result = fs_resolver.resolve(file_path, "./bar.zok".into()); assert!(result.is_ok()); - let mut code = String::new(); - result.unwrap().0.read_line(&mut code).unwrap(); // the imported file should be the user's - assert_eq!(code, "\n".to_string()); + assert_eq!(result.unwrap().0, String::from("\n")); } #[test] fn treat_absolute_as_std() { - use std::io::BufRead; use std::io::Write; // create a HOME folder with a code file @@ -154,32 +158,21 @@ mod tests { // create a user folder with a code file let source_folder = tempfile::tempdir().unwrap(); let file_path = source_folder.path().join("bar.zok"); - let mut file = File::create(file_path).unwrap(); + let mut file = File::create(file_path.clone()).unwrap(); writeln!(file, "").unwrap(); // assign HOME folder to ZOKRATES_HOME std::env::set_var(ZOKRATES_HOME, zokrates_home_folder.path()); - let result = resolve( - Some( - source_folder - .path() - .to_path_buf() - .to_string_lossy() - .to_string(), - ), - &"bar.zok", - ); + let fs_resolver = FileSystemResolver::new(); + let result = fs_resolver.resolve(file_path.clone(), "bar.zok".into()); assert!(result.is_ok()); - let mut code = String::new(); - result.unwrap().0.read_line(&mut code).unwrap(); // the imported file should be the user's - assert_eq!(code, "\n".to_string()); + assert_eq!(result.unwrap().0, String::from("\n")); } #[test] fn navigate_up() { - use std::io::BufRead; use std::io::Write; // create a user folder with a code file @@ -188,22 +181,17 @@ mod tests { let file_path = source_folder.path().join("bar.zok"); let mut file = File::create(file_path).unwrap(); writeln!(file, "").unwrap(); + let origin_path = source_subfolder.path().join("foo.zok"); + File::create(origin_path).unwrap(); - let result = resolve( - Some( - source_subfolder - .path() - .to_path_buf() - .to_string_lossy() - .to_string(), - ), - &"../bar.zok", + let fs_resolver = FileSystemResolver::new(); + let result = fs_resolver.resolve( + source_subfolder.path().to_path_buf().join("foo.zok"), + "../bar.zok".into(), ); assert!(result.is_ok()); - let mut code = String::new(); - result.unwrap().0.read_line(&mut code).unwrap(); // the imported file should be the user's - assert_eq!(code, "\n".to_string()); + assert_eq!(result.unwrap().0, String::from("\n")); } #[test] @@ -219,21 +207,24 @@ mod tests { // assign HOME folder to ZOKRATES_HOME std::env::set_var(ZOKRATES_HOME, zokrates_home_folder.path()); - let result = resolve(Some("/path/to/user/folder".to_string()), &"./bar.zok"); + let fs_resolver = FileSystemResolver::new(); + let result = fs_resolver.resolve("/path/to/source.zok".into(), "./bar.zok".into()); assert!(result.is_err()); } #[test] fn fail_if_not_found_in_std() { std::env::set_var(ZOKRATES_HOME, ""); - let result = resolve(Some("/path/to/source".to_string()), &"bar.zok"); + let fs_resolver = FileSystemResolver::new(); + let result = fs_resolver.resolve("/path/to/source.zok".into(), "bar.zok".into()); assert!(result.is_err()); } #[test] - #[should_panic] fn panic_if_home_not_set() { std::env::remove_var(ZOKRATES_HOME); - let _ = resolve(Some("/path/to/source".to_string()), &"bar.zok"); + let fs_resolver = FileSystemResolver::new(); + let result = fs_resolver.resolve("/path/to/source.zok".into(), "bar.zok".into()); + assert!(result.is_err()); } } diff --git a/zokrates_js/.dockerignore b/zokrates_js/.dockerignore new file mode 100644 index 00000000..44f5edd1 --- /dev/null +++ b/zokrates_js/.dockerignore @@ -0,0 +1,8 @@ +pkg/ +node_modules/ +target/ +npm-debug.log +.git +.gitignore +.vscode +.idea \ No newline at end of file diff --git a/zokrates_js/.gitignore b/zokrates_js/.gitignore new file mode 100644 index 00000000..079a78d9 --- /dev/null +++ b/zokrates_js/.gitignore @@ -0,0 +1,7 @@ +node_modules +/dist +/target +/pkg +/wasm-pack.log +/stdlib +stdlib.json \ No newline at end of file diff --git a/zokrates_js/Cargo.lock b/zokrates_js/Cargo.lock new file mode 100644 index 00000000..bc603962 --- /dev/null +++ b/zokrates_js/Cargo.lock @@ -0,0 +1,1141 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "anyhow" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "backtrace" +version = "0.3.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bellman_ce" +version = "0.3.1" +source = "git+https://github.com/matter-labs/bellman?rev=9e35737#9e35737209d4afc2e69af1e0d7cbe6d02e32aecf" +dependencies = [ + "bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pairing_ce 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bellman_ce" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "pairing_ce 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bincode" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bincode" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bit-vec" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "blake2-rfc_bellman_edition" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bstr" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bumpalo" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cc" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "csv" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bstr 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "csv-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "either" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "failure" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ff_ce" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ff_derive_ce 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ff_derive_ce" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "from-pest" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hermit-abi" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "itertools" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "js-sys" +version = "0.3.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.66" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "nom" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-bigint" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-bigint" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-integer" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-iter" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num_cpus" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hermit-abi 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pairing_ce" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ff_ce 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pest" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pest-ast" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "single 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pest_derive" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pest_generator" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pest_meta" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "reduce" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "regex" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-automata" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ryu" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sapling-crypto_ce" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bellman_ce 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2-rfc_bellman_edition 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_bytes" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha-1" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha2" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "single" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sourcefile" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "typed-arena" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "typenum" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ucd-trie" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ucd-util" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-segmentation" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "utf8-ranges" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasm-bindgen" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bumpalo 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro-support 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasm-bindgen-webidl" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "web-sys" +version = "0.3.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-webidl 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "weedle" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "zokrates_abi" +version = "0.1.1" +dependencies = [ + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "zokrates_core 0.4.2", + "zokrates_field 0.3.5", +] + +[[package]] +name = "zokrates_common" +version = "0.1.0" + +[[package]] +name = "zokrates_core" +version = "0.4.2" +dependencies = [ + "bellman_ce 0.3.1 (git+https://github.com/matter-labs/bellman?rev=9e35737)", + "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ff_ce 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", + "pairing_ce 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "reduce 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "typed-arena 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zokrates_common 0.1.0", + "zokrates_embed 0.1.1", + "zokrates_field 0.3.5", + "zokrates_pest_ast 0.1.3", +] + +[[package]] +name = "zokrates_embed" +version = "0.1.1" +dependencies = [ + "bellman_ce 0.3.1 (git+https://github.com/matter-labs/bellman?rev=9e35737)", + "sapling-crypto_ce 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zokrates_field" +version = "0.3.5" +dependencies = [ + "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ff_ce 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "pairing_ce 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zokrates_js" +version = "1.0.21" +dependencies = [ + "bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "console_error_panic_hook 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "zokrates_abi 0.1.1", + "zokrates_common 0.1.0", + "zokrates_core 0.4.2", + "zokrates_field 0.3.5", +] + +[[package]] +name = "zokrates_parser" +version = "0.1.4" +dependencies = [ + "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zokrates_pest_ast" +version = "0.1.3" +dependencies = [ + "from-pest 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pest-ast 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "zokrates_field 0.3.5", + "zokrates_parser 0.1.4", +] + +[metadata] +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" +"checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" +"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +"checksum backtrace 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e4036b9bf40f3cf16aba72a3d65e8a520fc4bafcdc7079aea8f848c58c5b5536" +"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" +"checksum bellman_ce 0.3.1 (git+https://github.com/matter-labs/bellman?rev=9e35737)" = "" +"checksum bellman_ce 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "938ec0feff00f9dfda0e7cbfe8db8b717966a84f6a12e63ed0943c4a90d6a5de" +"checksum bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e103c8b299b28a9c6990458b7013dc4a8356a9b854c51b9883241f5866fac36e" +"checksum bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" +"checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" +"checksum blake2-rfc_bellman_edition 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fdc60350286c7c3db13b98e91dbe5c8b6830a6821bc20af5b0c310ce94d74915" +"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +"checksum bstr 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "502ae1441a0a5adb8fbd38a5955a6416b9493e92b465de5e4a9bde6a539c2c48" +"checksum bumpalo 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum console_error_panic_hook 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211" +"checksum constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +"checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +"checksum csv 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279" +"checksum csv-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" +"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +"checksum ff_ce 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "18af1ea1b80a4b474fae13af4c58cf0a5a2bc33832d5fa70f68a4b286178fdb5" +"checksum ff_derive_ce 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d245b4e76c5b36bb7721ea15b7fbc61bebf0c5d2890eaf49fe1e2a3eed36db9" +"checksum from-pest 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aba9389cedcba1fb3a2aa2ed00f584f2606bce8e0106614a17327a24513bc60f" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" +"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum hermit-abi 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e2c55f143919fbc0bc77e427fe2d74cf23786d7c1875666f2fde3ac3c659bb67" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" +"checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" +"checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" +"checksum js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "7889c7c36282151f6bf465be4700359318aef36baa951462382eae49e9577cf9" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" +"checksum memchr 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53445de381a1f436797497c61d851644d0e8e88e6140f22872ad33a704933978" +"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" +"checksum num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" +"checksum num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +"checksum num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00" +"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" +"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +"checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" +"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +"checksum pairing_ce 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f075a9c570e2026111cb6dddf6a320e5163c42aa32500b315ec34acbcf7c9b36" +"checksum pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e4fb201c5c22a55d8b24fef95f78be52738e5e1361129be1b5e862ecdb6894a" +"checksum pest-ast 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3fbf404899169771dd6a32c84248b83cd67a26cc7cc957aac87661490e1227e4" +"checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +"checksum pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9fcf299b5712d06ee128a556c94709aaa04512c4dffb8ead07c5c998447fc0" +"checksum pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df43fd99896fd72c485fe47542c7b500e4ac1e8700bf995544d1317a60ded547" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548" +"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum reduce 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "75b1fa5668b02f2a69746bba558f8f98cc087b123a587fd959122872ad9a3f3c" +"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" +"checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" +"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" +"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" +"checksum sapling-crypto_ce 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ec318b68765114e578fe42446b6861565b302bc93089aa01669d19417a6de993" +"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" +"checksum serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "defbb8a83d7f34cc8380751eeb892b825944222888aff18996ea7901f24aec88" +"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" +"checksum serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" +"checksum sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +"checksum sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" +"checksum single 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5add732a1ab689845591a1b50339cf5310b563e08dc5813c65991f30369ea2" +"checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" +"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" +"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +"checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5" +"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum tiny-keccak 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2953ca5148619bc99695c1274cb54c5275bbb913c6adad87e72eaf8db9787f69" +"checksum typed-arena 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d" +"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +"checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" +"checksum ucd-util 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5ccdc2daea7cf8bc50cd8710d170a9d816678e54943829c5082bb1594312cf8e" +"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c" +"checksum wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "11cdb95816290b525b32587d76419facd99662a07e59d3cdb560488a819d9a45" +"checksum wasm-bindgen-macro 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "574094772ce6921576fb6f2e3f7497b8a76273b6db092be18fc48a082de09dc3" +"checksum wasm-bindgen-macro-support 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "e85031354f25eaebe78bb7db1c3d86140312a911a106b2e29f9cc440ce3e7668" +"checksum wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e7e61fc929f4c0dddb748b102ebf9f632e2b8d739f2016542b4de2965a9601" +"checksum wasm-bindgen-webidl 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ef012a0d93fc0432df126a8eaf547b2dce25a8ce9212e1d3cbeef5c11157975d" +"checksum web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "aaf97caf6aa8c2b1dac90faf0db529d9d63c93846cca4911856f78a83cebf53b" +"checksum weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/zokrates_js/Cargo.toml b/zokrates_js/Cargo.toml new file mode 100644 index 00000000..6e2823e7 --- /dev/null +++ b/zokrates_js/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "zokrates_js" +version = "1.0.21" +authors = ["Darko Macesic"] +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +bincode = "1.1.4" +js-sys = "0.3.33" +serde = { version = "^1.0.59", features = ["derive"] } +serde_json = "1.0" +wasm-bindgen = { version = "0.2.46", features = ["serde-serialize"] } +zokrates_core = { path = "../zokrates_core", features = ["wasm"] } +zokrates_common = { path = "../zokrates_common" } +zokrates_field = { path = "../zokrates_field" } +zokrates_abi = { path = "../zokrates_abi" } +console_error_panic_hook = "0.1.5" \ No newline at end of file diff --git a/zokrates_js/Dockerfile b/zokrates_js/Dockerfile new file mode 100644 index 00000000..85a82439 --- /dev/null +++ b/zokrates_js/Dockerfile @@ -0,0 +1,8 @@ +FROM dark64/rust-wasm-env:latest + +COPY . src +RUN cd src/zokrates_js && npm run build && rm -rf target/ + +RUN cd / && mkdir build \ + && mv src/zokrates_js/* /build \ + && rm -rf src \ No newline at end of file diff --git a/zokrates_js/Dockerfile.env b/zokrates_js/Dockerfile.env new file mode 100644 index 00000000..bbf62823 --- /dev/null +++ b/zokrates_js/Dockerfile.env @@ -0,0 +1,25 @@ +FROM node:10 +SHELL ["/bin/bash", "-c"] + +ARG RUST_VERSION=nightly +ARG WASM_PACK_VERSION=0.8.1 + +ENV RUSTUP_HOME=/usr/local/rustup \ + CARGO_HOME=/usr/local/cargo \ + PATH=/usr/local/cargo/bin:$PATH + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ + libc6-dev \ + ; \ + \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path --default-toolchain $RUST_VERSION; \ + chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \ + rustup --version; \ + cargo --version; \ + rustc --version; + +RUN cargo install wasm-pack --version $WASM_PACK_VERSION \ No newline at end of file diff --git a/zokrates_js/README.md b/zokrates_js/README.md new file mode 100644 index 00000000..f681cef3 --- /dev/null +++ b/zokrates_js/README.md @@ -0,0 +1,37 @@ +# zokrates.js + +JavaScript bindings for [ZoKrates](https://github.com/Zokrates/ZoKrates) project. + +```bash +npm install zokrates-js +``` + +## API + +| Function | Description | +| ------ | ------ | +| initialize | Loads binding wasm module and returns a promise with ZoKrates provider | +| compile | Compiles source code into ZoKrates internal representation of arithmetic circuits | +| computeWitness | Computes a valid assignment of the variables, which include the results of the computation | +| setup | Generates a trusted setup for the compiled program | +| exportSolidityVerifier | Generates a Solidity contract which contains the generated verification key and a public function to verify a solution to the compiled program | +| generateProof | Generates a proof for a computation of the compiled program | + +## Usage + +```js +import { initialize } from 'zokrates-js'; + +function importResolver(location, path) { + // implement your resolving logic here + return { + source: "def main() -> (): return", + location: path + }; +} + +initialize().then((zokratesProvider) => { + // we have to initialize the wasm module before calling api functions + zokratesProvider.compile("def main(private field a) -> (field): return a", "main", importResolver) +}); +``` diff --git a/zokrates_js/build.sh b/zokrates_js/build.sh new file mode 100755 index 00000000..6e09d4b9 --- /dev/null +++ b/zokrates_js/build.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -e + +docker build -t zokrates_js -f zokrates_js/Dockerfile . \ No newline at end of file diff --git a/zokrates_js/gulpfile.js b/zokrates_js/gulpfile.js new file mode 100644 index 00000000..21275747 --- /dev/null +++ b/zokrates_js/gulpfile.js @@ -0,0 +1,27 @@ +/** general */ +const gulp = require('gulp'); +const dree = require('dree'); +const fs = require('fs'); +const path = require('path'); + +/** stdlib constants */ +const stdlibRoot = '../zokrates_stdlib/stdlib'; +const output = 'stdlib.json'; + +const options = { + extensions: ['zok'] +}; + +/** + * Serializes standard library directory tree to a json file. + */ +gulp.task('stdlib', function (done) { + var stdlib = {}; + dree.scan(stdlibRoot, options, function (file) { + const content = fs.readFileSync(file.path).toString(); + stdlib[file.relativePath] = content; + }); + + fs.writeFileSync(path.resolve(__dirname, output), JSON.stringify(stdlib)); + done(); +}); \ No newline at end of file diff --git a/zokrates_js/index.d.ts b/zokrates_js/index.d.ts new file mode 100644 index 00000000..4661cbce --- /dev/null +++ b/zokrates_js/index.d.ts @@ -0,0 +1,34 @@ +declare module 'zokrates-js' { + + export interface ResolverResult { + source: string, + location: string + } + + export interface ComputationResult { + witness: string, + output: string + } + + export interface CompilationArtifacts { + program: Uint8Array, + abi: string, + } + + export interface SetupKeypair { + vk: string, + pk: Uint8Array, + } + + export type ResolveCallback = (location: string, path: string) => ResolverResult; + + export interface ZoKratesProvider { + compile(source: string, location: string, callback: ResolveCallback): CompilationArtifacts; + setup(program: Uint8Array): SetupKeypair; + computeWitness(artifacts: CompilationArtifacts, args: any[]): ComputationResult; + exportSolidityVerifier(verifyingKey: string, isAbiv2: boolean): string + generateProof(program: Uint8Array, witness: string, provingKey: Uint8Array): string; + } + + export function initialize(): Promise; +} diff --git a/zokrates_js/index.js b/zokrates_js/index.js new file mode 100644 index 00000000..e86bb7b9 --- /dev/null +++ b/zokrates_js/index.js @@ -0,0 +1,61 @@ +import { appendExtension, getAbsolutePath } from './utils'; +import stdlib from './stdlib.json'; + +const initialize = async () => { + + const EXTENSION_ZOK = '.zok'; + const RESERVED_PATHS = [ + 'ecc/', + 'signature/', + 'hashes/', + 'utils/' + ]; + + // load web assembly module + const zokrates = await import('./pkg/index.js'); + + const resolveModule = (currentLocation, importLocation, callback) => { + if (isReserved(currentLocation) || isReserved(importLocation)) { + return resolveFromStandardLibrary(currentLocation, importLocation); + } + return callback(currentLocation, importLocation); + } + + const isReserved = (path) => RESERVED_PATHS.some(p => path.startsWith(p)); + + const resolveFromStandardLibrary = (currentLocation, importLocation) => { + let key = appendExtension(getAbsolutePath(currentLocation, importLocation), EXTENSION_ZOK); + let source = stdlib[key]; + return source ? { source, location: key } : null; + } + + return { + compile: (source, location, callback) => { + let result = zokrates.compile(source, location, (currentLocation, importLocation) => + resolveModule(currentLocation, importLocation, callback) + ); + return { + program: Array.from(result.program), + abi: result.abi + } + }, + setup: (program) => { + let result = zokrates.setup(program); + return { + vk: result.vk, + pk: Array.from(result.pk) + }; + }, + computeWitness: (artifacts, args) => { + return zokrates.compute_witness(artifacts, JSON.stringify(Array.from(args))); + }, + exportSolidityVerifier: (verifyingKey, isAbiv2) => { + return zokrates.export_solidity_verifier(verifyingKey, isAbiv2); + }, + generateProof: (program, witness, provingKey) => { + return zokrates.generate_proof(program, witness, provingKey); + } + } +} + +export { initialize }; \ No newline at end of file diff --git a/zokrates_js/package-lock.json b/zokrates_js/package-lock.json new file mode 100644 index 00000000..62f02b97 --- /dev/null +++ b/zokrates_js/package-lock.json @@ -0,0 +1,5129 @@ +{ + "name": "zokrates-js", + "version": "1.0.21", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@zeit/schemas": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.6.0.tgz", + "integrity": "sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg==", + "dev": true + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "ajv": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", + "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "dev": true, + "requires": { + "string-width": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + } + }, + "arch": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.1.1.tgz", + "integrity": "sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg==", + "dev": true + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "arg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arg/-/arg-2.0.0.tgz", + "integrity": "sha512-XxNTUzKnz1ctK3ZIcI2XUPlD96wbHP2nGqkPKpvk/HNRlPveYrXIVSTk9m3LcqOgDPg3B1nMvdV/K8wZd7PG4w==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "dev": true, + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "dev": true, + "requires": { + "async-done": "^1.2.2" + } + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "dev": true, + "requires": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "dev": true, + "requires": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + } + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true + }, + "clipboardy": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-1.2.3.tgz", + "integrity": "sha512-2WNImOvCRe6r63Gk9pShfkwXsVtKCroMAevIbiae021mS850UkWPbevxsBz3tnvjZIEGvlwaqCPsw+4ulzNgJA==", + "dev": true, + "requires": { + "arch": "^2.1.0", + "execa": "^0.8.0" + }, + "dependencies": { + "execa": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", + "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + } + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "dev": true, + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz", + "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.14", + "debug": "2.6.9", + "on-headers": "~1.0.1", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "copy-props": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", + "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "dev": true, + "requires": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "requires": { + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "dree": { + "version": "2.4.14", + "resolved": "https://registry.npmjs.org/dree/-/dree-2.4.14.tgz", + "integrity": "sha512-Vdh9iaGOIz/CLQobP+aC4CnmN0bkKlljjtLCTQJm25xgjEscrTP/yK9+JxdqnM0/d5zjRa245Sr5xoewoS5Icw==", + "dev": true, + "requires": { + "yargs": "^15.3.1" + } + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", + "dev": true, + "requires": { + "punycode": "^1.3.2" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true + }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", + "dev": true + } + } + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.12.tgz", + "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1", + "node-pre-gyp": "*" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "3.2.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.9.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.14.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "nopt": { + "version": "4.0.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.7.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.1", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.13", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.1.1", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + } + }, + "glob-watcher": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", + "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "object.defaults": "^1.1.0" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "requires": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + } + }, + "gulp-cli": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.2.0.tgz", + "integrity": "sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.1.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.0.1", + "yargs": "^7.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "dev": true, + "requires": { + "camelcase": "^3.0.0" + } + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "interpret": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "just-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", + "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "dev": true, + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "requires": { + "flush-write-stream": "^1.0.2" + } + }, + "liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "dev": true, + "requires": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, + "dependencies": { + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "dev": true, + "requires": { + "mime-db": "1.43.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", + "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "mocha": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.1.1.tgz", + "integrity": "sha512-3qQsu3ijNS3GkWcccT5Zw0hf/rWvu1fTN9sPvEd81hlwsr30GX2GcDSSoBxo24IR8FelmrAydGC6/1J5QQP4WA==", + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "chokidar": "3.3.0", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "3.0.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.3", + "ms": "2.1.1", + "node-environment-flags": "1.0.6", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.0" + }, + "dependencies": { + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "dev": true, + "optional": true + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "readdirp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "dev": true, + "requires": { + "picomatch": "^2.0.4" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "node-environment-flags": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", + "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "requires": { + "once": "^1.3.2" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dev": true, + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "requires": { + "rc": "^1.0.1" + } + }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "requires": { + "value-or-function": "^3.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "dev": true, + "requires": { + "sver-compat": "^1.5.0" + } + }, + "serve": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/serve/-/serve-11.3.0.tgz", + "integrity": "sha512-AU0g50Q1y5EVFX56bl0YX5OtVjUX1N737/Htj93dQGKuHiuLvVB45PD8Muar70W6Kpdlz8aNJfoUqTyAq9EE/A==", + "dev": true, + "requires": { + "@zeit/schemas": "2.6.0", + "ajv": "6.5.3", + "arg": "2.0.0", + "boxen": "1.3.0", + "chalk": "2.4.1", + "clipboardy": "1.2.3", + "compression": "1.7.3", + "serve-handler": "6.1.2", + "update-check": "1.5.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "serve-handler": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.2.tgz", + "integrity": "sha512-RFh49wX7zJmmOVDcIjiDSJnMH+ItQEvyuYLYuDBVoA/xmQSCuj+uRmk1cmBB5QQlI3qOiWKp6p4DUGY+Z5AB2A==", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.0.4", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "~1.33.0" + } + } + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "requires": { + "execa": "^0.7.0" + } + }, + "text-encoding": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.7.0.tgz", + "integrity": "sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA==", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "requires": { + "through2": "^2.0.3" + } + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "undertaker": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", + "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + } + }, + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "update-check": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.2.tgz", + "integrity": "sha512-1TrmYLuLj/5ZovwUS7fFd1jMH3NnFDN1y1A8dboedIDt7zs/zJMo6TwwlhYKkSeEwzleeiSBV5/3c9ufAQWDaQ==", + "dev": true, + "requires": { + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0" + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "v8flags": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", + "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + }, + "vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "dev": true, + "requires": { + "string-width": "^2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", + "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.1" + } + }, + "yargs-parser": { + "version": "18.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.1.tgz", + "integrity": "sha512-KRHEsOM16IX7XuLnMOqImcPNbLVXMNHYAoFc3BKR8Ortl5gzDbtXvvEoGx9imk5E+X1VeNKNlcHr8B8vi+7ipA==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + } + } +} diff --git a/zokrates_js/package.json b/zokrates_js/package.json new file mode 100644 index 00000000..26422ccb --- /dev/null +++ b/zokrates_js/package.json @@ -0,0 +1,41 @@ +{ + "name": "zokrates-js", + "main": "index.js", + "author": "Darko Macesic ", + "version": "1.0.21", + "keywords": [ + "zokrates", + "wasm-bindgen", + "zksnarks" + ], + "license": "GPLv3", + "files": [ + "pkg", + "index.js", + "index.d.ts", + "utils.js", + "stdlib.json", + "README.md" + ], + "types": "index.d.ts", + "scripts": { + "cargo:build": "cargo build --target=wasm32-unknown-unknown", + "wasm-pack:build": "wasm-pack build --out-name index --release --target bundler", + "setup": "npm install && gulp stdlib", + "prebuild": "npm run setup", + "build": "rimraf pkg && npm run wasm-pack:build", + "pretest": "npm run setup", + "test": "mocha --require esm --recursive tests" + }, + "devDependencies": { + "dree": "^2.4.14", + "esm": "^3.2.25", + "gulp": "^4.0.2", + "gulp-cli": "^2.2.0", + "mocha": "^7.1.1", + "rimraf": "^3.0.2", + "serve": "^11.3.0", + "text-encoding": "^0.7.0" + }, + "dependencies": {} +} diff --git a/zokrates_js/publish.sh b/zokrates_js/publish.sh new file mode 100755 index 00000000..681dcd1a --- /dev/null +++ b/zokrates_js/publish.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +PACKAGE_VERSION=$(cat package.json \ + | grep version \ + | head -1 \ + | awk -F: '{ print $2 }' \ + | sed 's/[",]//g' \ + | tr -d '[[:space:]]') + +CARGO_VERSION=$(cat Cargo.toml \ + | grep '^version' \ + | awk '{print $3}' \ + | sed -e 's/"//g') + +if [ $PACKAGE_VERSION != $CARGO_VERSION ]; then + echo "Cargo crate version must be equal to npm package version ($CARGO_VERSION -> $PACKAGE_VERSION)" + exit 0 +fi + +NPM_VERSION=$(npm view zokrates-js dist-tags.latest) + +if [ $NPM_VERSION = $PACKAGE_VERSION ]; then + echo "Latest npm version is equal to current package version. Up the version to publish to npm." + exit 0 +fi + +# publish +npm set //registry.npmjs.org/:_authToken=${NPM_TOKEN} +npm publish \ No newline at end of file diff --git a/zokrates_js/src/lib.rs b/zokrates_js/src/lib.rs new file mode 100644 index 00000000..9c1183d7 --- /dev/null +++ b/zokrates_js/src/lib.rs @@ -0,0 +1,192 @@ +use bincode::{deserialize, serialize}; +use serde::{Deserialize, Serialize}; +use serde_json::to_string_pretty; +use std::path::PathBuf; +use wasm_bindgen::prelude::*; +use zokrates_abi::{parse_strict, Decode, Encode, Inputs}; +use zokrates_common::Resolver; +use zokrates_core::compile::{compile as core_compile, CompilationArtifacts, CompileError}; +use zokrates_core::imports::Error; +use zokrates_core::ir; +use zokrates_core::proof_system::{self, ProofSystem}; +use zokrates_core::typed_absy::abi::Abi; +use zokrates_core::typed_absy::types::Signature; +use zokrates_field::field::FieldPrime; + +#[derive(Serialize, Deserialize)] +pub struct ResolverResult { + source: String, + location: String, +} + +#[derive(Serialize, Deserialize)] +pub struct CompilationResult { + program: Vec, + abi: String, +} + +#[derive(Serialize, Deserialize)] +pub struct ComputationResult { + witness: String, + output: String, +} + +impl ResolverResult { + fn into_tuple(self) -> (String, PathBuf) { + (self.source, PathBuf::from(self.location)) + } +} + +#[inline] +fn deserialize_program(value: &Vec) -> Result, JsValue> { + deserialize(&value) + .map_err(|err| JsValue::from_str(&format!("Could not deserialize program: {}", err))) +} + +#[inline] +fn serialize_program(program: &ir::Prog) -> Result, JsValue> { + serialize(program) + .map_err(|err| JsValue::from_str(&format!("Could not serialize program: {}", err))) +} + +pub struct JsResolver<'a> { + callback: &'a js_sys::Function, +} + +impl<'a> JsResolver<'a> { + pub fn new(callback: &'a js_sys::Function) -> Self { + JsResolver { callback } + } +} + +impl<'a> Resolver for JsResolver<'a> { + fn resolve( + &self, + current_location: PathBuf, + import_location: PathBuf, + ) -> Result<(String, PathBuf), Error> { + let value = self + .callback + .call2( + &JsValue::UNDEFINED, + ¤t_location.to_str().unwrap().into(), + &import_location.to_str().unwrap().into(), + ) + .map_err(|_| { + Error::new(format!( + "Error thrown in callback: could not resolve {}", + import_location.display() + )) + })?; + + if value.is_null() || value.is_undefined() { + Err(Error::new(format!( + "Could not resolve {}", + import_location.display() + ))) + } else { + let result: ResolverResult = value.into_serde().unwrap(); + Ok(result.into_tuple()) + } + } +} + +#[wasm_bindgen] +pub fn compile( + source: JsValue, + location: JsValue, + resolve: &js_sys::Function, +) -> Result { + let fmt_error = |e: &CompileError| format!("{}:{}", e.file().display(), e.value()); + let resolver = JsResolver::new(resolve); + + let artifacts: CompilationArtifacts = core_compile( + source.as_string().unwrap(), + PathBuf::from(location.as_string().unwrap()), + Some(&resolver), + ) + .map_err(|ce| { + JsValue::from_str(&format!( + "{}", + ce.0.iter() + .map(|e| fmt_error(e)) + .collect::>() + .join("\n") + )) + })?; + + let result = CompilationResult { + program: serialize_program(artifacts.prog())?, + abi: to_string_pretty(artifacts.abi()).unwrap(), + }; + + Ok(JsValue::from_serde(&result).unwrap()) +} + +#[wasm_bindgen] +pub fn compute_witness(artifacts: JsValue, args: JsValue) -> Result { + let result: CompilationResult = artifacts.into_serde().unwrap(); + let program_flattened = deserialize_program(&result.program)?; + + let abi: Abi = serde_json::from_str(result.abi.as_str()) + .map_err(|err| JsValue::from_str(&format!("Could not deserialize abi: {}", err)))?; + + let signature: Signature = abi.signature(); + let input = args.as_string().unwrap(); + + let inputs = parse_strict(&input, signature.inputs) + .map(|parsed| Inputs::Abi(parsed)) + .map_err(|why| JsValue::from_str(&format!("{}", why.to_string())))?; + + let witness = program_flattened + .execute(&inputs.encode()) + .map_err(|err| JsValue::from_str(&format!("Execution failed: {}", err)))?; + + let return_values: serde_json::Value = + zokrates_abi::CheckedValues::decode(witness.return_values(), signature.outputs).into(); + + let result = ComputationResult { + witness: format!("{}", witness), + output: to_string_pretty(&return_values).unwrap(), + }; + + Ok(JsValue::from_serde(&result).unwrap()) +} + +#[wasm_bindgen] +pub fn setup(program: JsValue) -> Result { + let input: Vec = program.into_serde().unwrap(); + let program_flattened = deserialize_program(&input)?; + let keypair = proof_system::G16 {}.setup(program_flattened); + Ok(JsValue::from_serde(&keypair).unwrap()) +} + +#[wasm_bindgen] +pub fn export_solidity_verifier(vk: JsValue, is_abiv2: JsValue) -> JsValue { + let verifier = proof_system::G16 {} + .export_solidity_verifier(vk.as_string().unwrap(), is_abiv2.as_bool().unwrap()); + JsValue::from_str(verifier.as_str()) +} + +#[wasm_bindgen] +pub fn generate_proof(program: JsValue, witness: JsValue, pk: JsValue) -> Result { + let input: Vec = program.into_serde().unwrap(); + let program_flattened = deserialize_program(&input)?; + + let str_witness = witness.as_string().unwrap(); + let ir_witness: ir::Witness = ir::Witness::read(str_witness.as_bytes()) + .map_err(|err| JsValue::from_str(&format!("Could not read witness: {}", err)))?; + + let proving_key: Vec = pk.into_serde().unwrap(); + let proof = proof_system::G16 {}.generate_proof(program_flattened, ir_witness, proving_key); + + Ok(JsValue::from_str(proof.as_str())) +} + +#[wasm_bindgen(start)] +pub fn main_js() -> Result<(), JsValue> { + #[cfg(debug_assertions)] + console_error_panic_hook::set_once(); + + Ok(()) +} diff --git a/zokrates_js/tests/stdlib.test.js b/zokrates_js/tests/stdlib.test.js new file mode 100644 index 00000000..f90ba414 --- /dev/null +++ b/zokrates_js/tests/stdlib.test.js @@ -0,0 +1,30 @@ +const assert = require('assert'); +const utils = require('../utils'); +const stdlib = require('../stdlib.json'); + +describe('stdlib', function() { + + it('should resolve module from stdlib (1)', function() { + let basePath = 'hashes/sha256/512bitPacked.zok'; + let relativePath = '../../utils/pack/pack128'; + + let absolutePath = utils.appendExtension(utils.getAbsolutePath(basePath, relativePath), '.zok'); + assert.notEqual(stdlib[absolutePath], undefined); + }); + + it('should resolve module from stdlib (2)', function() { + let basePath = 'hashes/sha256/256bitPadded.zok'; + let relativePath = './512bit'; + + let absolutePath = utils.appendExtension(utils.getAbsolutePath(basePath, relativePath), '.zok'); + assert.notEqual(stdlib[absolutePath], undefined); + }); + + it('should resolve module from stdlib (3)', function() { + let basePath = 'hashes/pedersen/6bit.zok'; + let relativePath = 'ecc/babyjubjubParams'; + + let absolutePath = utils.appendExtension(utils.getAbsolutePath(basePath, relativePath), '.zok'); + assert.notEqual(stdlib[absolutePath], undefined); + }); +}); \ No newline at end of file diff --git a/zokrates_js/tests/utils.test.js b/zokrates_js/tests/utils.test.js new file mode 100644 index 00000000..1ac375f8 --- /dev/null +++ b/zokrates_js/tests/utils.test.js @@ -0,0 +1,29 @@ +const assert = require('assert') +const utils = require('../utils'); + +describe('absolute path resolving', function() { + + it('should resolve valid absolute path (root)', function() { + let basePath = 'hashes/pedersen/6bit'; + let relativePath = 'ecc/babyjubjubParams'; + + let absolutePath = utils.getAbsolutePath(basePath, relativePath); + assert.equal(absolutePath, 'ecc/babyjubjubParams'); + }); + + it('should resolve valid absolute path (../)', function() { + let basePath = 'hashes/sha256/512bitPacked'; + let relativePath = '../../utils/pack/pack128'; + + let absolutePath = utils.getAbsolutePath(basePath, relativePath); + assert.equal(absolutePath, 'utils/pack/pack128'); + }); + + it('should resolve valid absolute path (./)', function() { + let basePath = 'hashes/sha256/256bitPadded'; + let relativePath = './512bit'; + + let absolutePath = utils.getAbsolutePath(basePath, relativePath); + assert.equal(absolutePath, 'hashes/sha256/512bit'); + }); +}); \ No newline at end of file diff --git a/zokrates_js/utils.js b/zokrates_js/utils.js new file mode 100644 index 00000000..270d3bfc --- /dev/null +++ b/zokrates_js/utils.js @@ -0,0 +1,26 @@ +export function getAbsolutePath(basePath, relativePath) { + if (relativePath[0] !== '.') { + return relativePath; + } + var stack = basePath.split('/'); + var chunks = relativePath.split('/'); + stack.pop(); + + for(var i = 0; i < chunks.length; i++) { + if (chunks[i] == '.') { + continue; + } else if (chunks[i] == '..') { + stack.pop(); + } else { + stack.push(chunks[i]); + } + } + return stack.join('/'); +} + +export function appendExtension(path, extension) { + if (path.endsWith(extension)) { + return path; + } + return path.concat(extension); +} \ No newline at end of file diff --git a/zokrates_parser/Cargo.toml b/zokrates_parser/Cargo.toml index c27f01bb..1df8a775 100644 --- a/zokrates_parser/Cargo.toml +++ b/zokrates_parser/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_parser" -version = "0.1.3" +version = "0.1.4" authors = ["JacobEberhardt "] edition = "2018" diff --git a/zokrates_parser/src/ace_mode/README.md b/zokrates_parser/src/ace_mode/README.md new file mode 100644 index 00000000..0a44ba3f --- /dev/null +++ b/zokrates_parser/src/ace_mode/README.md @@ -0,0 +1,3 @@ +### ZoKrates Ace Mode (Syntax Highlighting) + +[Ace](https://ace.c9.io/) Edit Mode for [ZoKrates DSL](https://github.com/Zokrates/ZoKrates). diff --git a/zokrates_parser/src/ace_mode/index.js b/zokrates_parser/src/ace_mode/index.js new file mode 100644 index 00000000..b4753e6c --- /dev/null +++ b/zokrates_parser/src/ace_mode/index.js @@ -0,0 +1,120 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2019, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +ace.define("ace/mode/zokrates_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../lib/oop"); + var TextHighlightRules = acequire("./text_highlight_rules").TextHighlightRules; + + var ZoKratesHighlightRules = function () { + + var keywords = ( + "endfor|as|return|byte|field|bool|if|then|fi|do|else|export|false|def|for|import|from|uint|in|public|private|struct|true" + ); + + var keywordMapper = this.createKeywordMapper({ + "keyword": keywords + }, "identifier"); + + var decimalInteger = "(?:(?:[1-9]\\d*)|(?:0))"; + var hexInteger = "(?:0[xX][\\dA-Fa-f]+)"; + var integer = "(?:" + decimalInteger + "|" + hexInteger + ")\\b"; + + this.$rules = { + "start": [ + { + token: "comment", // single line comment + regex: "\\/\\/.*$" + }, { + token: "comment", // multi line comment + regex: "\\/\\*", + next: "comment" + }, { + token: "string", // single line + regex: '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' + }, { + token: "constant.numeric", // integer + regex: integer + }, { + token: keywordMapper, + regex: "[a-zA-Z_$][a-zA-Z0-9_$]*\\b" + }, { + token: "keyword.operator", + regex: "\\+|\\-|\\*|\\*\\*|\\/|\\|\\||&&|\\^|!|<|>|<=|=>|==|!=|=" + }, { + token: "punctuation", + regex: ",|:|;" + }, { + token: "lparen", + regex: "[[({]" + }, { + token: "rparen", + regex: "[\\])}]" + }, { + token: "text", + regex: "\\s+" + } + ], + "comment": [ + { + token: "comment", // closing comment + regex: "\\*\\/", + next: "start" + }, { + defaultToken: "comment" + } + ] + }; + }; + + oop.inherits(ZoKratesHighlightRules, TextHighlightRules); + + exports.ZoKratesHighlightRules = ZoKratesHighlightRules; +}); + +ace.define("ace/mode/zokrates",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/zokrates_highlight_rules"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../lib/oop"); + var TextMode = acequire("./text").Mode; + var ZoKratesHighlightRules = acequire("./zokrates_highlight_rules").ZoKratesHighlightRules; + + var Mode = function () { + this.HighlightRules = ZoKratesHighlightRules; + }; + oop.inherits(Mode, TextMode); + + (function () { + this.$id = "ace/mode/zokrates"; + }).call(Mode.prototype); + + exports.Mode = Mode; +}); \ No newline at end of file diff --git a/zokrates_parser/src/ace_mode/package.json b/zokrates_parser/src/ace_mode/package.json new file mode 100644 index 00000000..77232c53 --- /dev/null +++ b/zokrates_parser/src/ace_mode/package.json @@ -0,0 +1,17 @@ +{ + "name": "ace-mode-zokrates", + "version": "1.0.1", + "description": "Ace Mode for ZoKrates DSL", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "zokrates", + "ace", + "mode", + "brace" + ], + "author": "Darko Macesic", + "license": "LGPL" +} diff --git a/zokrates_parser/src/lib.rs b/zokrates_parser/src/lib.rs index a135024e..12684ec8 100644 --- a/zokrates_parser/src/lib.rs +++ b/zokrates_parser/src/lib.rs @@ -122,11 +122,22 @@ mod tests { rule: Rule::statement, tokens: [ statement(0, 22, [ - multi_assignment_statement(0, 9, [ - optionally_typed_identifier(0, 1, [ - identifier(0, 1) + definition_statement(0, 9, [ + optionally_typed_assignee(0, 2, [ + assignee(0, 2, [ + identifier(0, 1) + ]) + ]), + expression(4, 9, [ + term(4, 9, [ + postfix_expression(4, 9, [ + identifier(4, 7), + access(7, 9, [ + call_access(7, 9) + ]) + ]) + ]) ]), - identifier(4, 7), ]) ]) ] diff --git a/zokrates_parser/src/zokrates.pest b/zokrates_parser/src/zokrates.pest index 7b62f2e6..b4b41034 100644 --- a/zokrates_parser/src/zokrates.pest +++ b/zokrates_parser/src/zokrates.pest @@ -1,4 +1,4 @@ -/** +/** * ZoKrates Grammar * Author: Jacob Eberhardt, Thibaut Schaeffer */ @@ -33,25 +33,21 @@ vis_private = {"private"} vis_public = {"public"} vis = { vis_private | vis_public } -// Statements +// Statements statement = { (return_statement // does not require subsequent newline | (iteration_statement - | multi_assignment_statement // try this first as we want all assignments based on return of function calls match here and not later | definition_statement - | assignment_statement - | expression_statement - ) ~ NEWLINE + | expression_statement + ) ~ NEWLINE ) ~ NEWLINE* } iteration_statement = { "for" ~ ty ~ identifier ~ "in" ~ expression ~ ".." ~ expression ~ "do" ~ NEWLINE* ~ statement* ~ "endfor"} return_statement = { "return" ~ expression_list} -multi_assignment_statement = { optionally_typed_identifier_list ~ "=" ~ identifier ~ "(" ~ expression_list ~ ")"} // This is very specific with regards to parsing. However, I think more generality is not needed here. -definition_statement = {ty ~ identifier ~ "=" ~ expression} // declare and assign, so only identifiers are allowed, unlike `assignment_statement` -assignment_statement = {assignee ~ "=" ~ expression } // TODO: Is this optimal? Can the left side be written more elegantly? +definition_statement = { optionally_typed_assignee_list ~ "=" ~ expression } // declare and assign, so only identifiers are allowed, unlike `assignment_statement` expression_statement = {expression} -optionally_typed_identifier_list = _{ optionally_typed_identifier ~ ("," ~ optionally_typed_identifier)* } -optionally_typed_identifier = { (identifier) | (ty ~ identifier) } // we don't use { ty? ~ identifier } as with a single token, it gets parsed as `ty` but we want `identifier` +optionally_typed_assignee_list = _{ optionally_typed_assignee ~ ("," ~ optionally_typed_assignee)* } +optionally_typed_assignee = { (ty ~ assignee) | (assignee) } // we don't use { ty? ~ identifier } as with a single token, it gets parsed as `ty` but we want `identifier` // Expressions expression_list = _{(expression ~ ("," ~ expression)*)?} @@ -118,9 +114,6 @@ op_unary = { op_not } WHITESPACE = _{ " " | "\t" | "\\" ~ NEWLINE} COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!NEWLINE ~ ANY)*) } -// TODO: Order by alphabet -keyword = @{"for" | "endfor" | "as" | "in" | "return" | "byte" | "field" | "bool" | "if" | "do" | "else" | "export" | "false" | - "def" | "for" | "import" | "uint" | - "in" | "public" | "private" | "return" | - "struct" | "true" - } \ No newline at end of file +keyword = @{"as"|"bool"|"byte"|"def"|"do"|"else"|"endfor"|"export"|"false"|"field"|"for"|"if"|"then"|"fi"|"import"|"from"| + "in"|"private"|"public"|"return"|"struct"|"true"|"uint" + } diff --git a/zokrates_pest_ast/src/lib.rs b/zokrates_pest_ast/src/lib.rs index 78c4f17b..b98da1db 100644 --- a/zokrates_pest_ast/src/lib.rs +++ b/zokrates_pest_ast/src/lib.rs @@ -9,11 +9,11 @@ extern crate lazy_static; pub use ast::{ Access, ArrayAccess, ArrayInitializerExpression, ArrayType, AssertionStatement, Assignee, - AssigneeAccess, AssignmentStatement, BasicOrStructType, BasicType, BinaryExpression, - BinaryOperator, CallAccess, ConstantExpression, DefinitionStatement, Expression, File, + AssigneeAccess, BasicOrStructType, BasicType, BinaryExpression, BinaryOperator, CallAccess, + ConstantExpression, DecimalNumberExpression, DefinitionStatement, Expression, FieldType, File, FromExpression, Function, IdentifierExpression, ImportDirective, ImportSource, InlineArrayExpression, InlineStructExpression, InlineStructMember, IterationStatement, - MultiAssignmentStatement, Parameter, PostfixExpression, Range, RangeOrExpression, + OptionallyTypedAssignee, Parameter, PostfixExpression, Range, RangeOrExpression, ReturnStatement, Span, Spread, SpreadOrExpression, Statement, StructDefinition, StructField, TernaryExpression, ToExpression, Type, UnaryExpression, UnaryOperator, Visibility, }; @@ -315,24 +315,12 @@ mod ast { Definition(DefinitionStatement<'ast>), Assertion(AssertionStatement<'ast>), Iteration(IterationStatement<'ast>), - Assignment(AssignmentStatement<'ast>), - MultiAssignment(MultiAssignmentStatement<'ast>), } #[derive(Debug, FromPest, PartialEq, Clone)] #[pest_ast(rule(Rule::definition_statement))] pub struct DefinitionStatement<'ast> { - pub ty: Type<'ast>, - pub id: IdentifierExpression<'ast>, - pub expression: Expression<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, - } - - #[derive(Debug, FromPest, PartialEq, Clone)] - #[pest_ast(rule(Rule::assignment_statement))] - pub struct AssignmentStatement<'ast> { - pub assignee: Assignee<'ast>, + pub lhs: Vec>, pub expression: Expression<'ast>, #[pest_ast(outer())] pub span: Span<'ast>, @@ -358,16 +346,6 @@ mod ast { pub span: Span<'ast>, } - #[derive(Debug, FromPest, PartialEq, Clone)] - #[pest_ast(rule(Rule::multi_assignment_statement))] - pub struct MultiAssignmentStatement<'ast> { - pub lhs: Vec>, - pub function_id: IdentifierExpression<'ast>, - pub arguments: Vec>, - #[pest_ast(outer())] - pub span: Span<'ast>, - } - #[derive(Debug, FromPest, PartialEq, Clone)] #[pest_ast(rule(Rule::return_statement))] pub struct ReturnStatement<'ast> { @@ -513,10 +491,10 @@ mod ast { } #[derive(Debug, FromPest, PartialEq, Clone)] - #[pest_ast(rule(Rule::optionally_typed_identifier))] - pub struct OptionallyTypedIdentifier<'ast> { + #[pest_ast(rule(Rule::optionally_typed_assignee))] + pub struct OptionallyTypedAssignee<'ast> { pub ty: Option>, - pub id: IdentifierExpression<'ast>, + pub a: Assignee<'ast>, #[pest_ast(outer())] pub span: Span<'ast>, } @@ -1018,54 +996,68 @@ mod tests { returns: vec![Type::Basic(BasicType::Field(FieldType { span: Span::new(&source, 15, 20).unwrap() }))], - statements: vec![Statement::MultiAssignment(MultiAssignmentStatement { - function_id: IdentifierExpression { - value: String::from("foo"), - span: Span::new(&source, 36, 39).unwrap() - }, + statements: vec![Statement::Definition(DefinitionStatement { lhs: vec![ - OptionallyTypedIdentifier { + OptionallyTypedAssignee { ty: Some(Type::Basic(BasicType::Field(FieldType { span: Span::new(&source, 23, 28).unwrap() }))), - id: IdentifierExpression { - value: String::from("a"), - span: Span::new(&source, 29, 30).unwrap(), + a: Assignee { + id: IdentifierExpression { + value: String::from("a"), + span: Span::new(&source, 29, 30).unwrap(), + }, + accesses: vec![], + span: Span::new(&source, 29, 30).unwrap() }, span: Span::new(&source, 23, 30).unwrap() }, - OptionallyTypedIdentifier { + OptionallyTypedAssignee { ty: None, - id: IdentifierExpression { - value: String::from("b"), - span: Span::new(&source, 32, 33).unwrap(), + a: Assignee { + id: IdentifierExpression { + value: String::from("b"), + span: Span::new(&source, 32, 33).unwrap(), + }, + accesses: vec![], + span: Span::new(&source, 32, 34).unwrap() }, - span: Span::new(&source, 32, 33).unwrap() + span: Span::new(&source, 32, 34).unwrap() }, ], - arguments: vec![ - Expression::Constant(ConstantExpression::DecimalNumber( - DecimalNumberExpression { - value: String::from("1"), - span: Span::new(&source, 40, 41).unwrap() - } - )), - Expression::add( - Expression::Constant(ConstantExpression::DecimalNumber( - DecimalNumberExpression { - value: String::from("2"), - span: Span::new(&source, 43, 44).unwrap() - } - )), - Expression::Constant(ConstantExpression::DecimalNumber( - DecimalNumberExpression { - value: String::from("3"), - span: Span::new(&source, 47, 48).unwrap() - } - )), - Span::new(&source, 43, 48).unwrap() - ), - ], + expression: Expression::Postfix(PostfixExpression { + id: IdentifierExpression { + value: String::from("foo"), + span: Span::new(&source, 36, 39).unwrap() + }, + accesses: vec![Access::Call(CallAccess { + expressions: vec![ + Expression::Constant(ConstantExpression::DecimalNumber( + DecimalNumberExpression { + value: String::from("1"), + span: Span::new(&source, 40, 41).unwrap() + } + )), + Expression::add( + Expression::Constant(ConstantExpression::DecimalNumber( + DecimalNumberExpression { + value: String::from("2"), + span: Span::new(&source, 43, 44).unwrap() + } + )), + Expression::Constant(ConstantExpression::DecimalNumber( + DecimalNumberExpression { + value: String::from("3"), + span: Span::new(&source, 47, 48).unwrap() + } + )), + Span::new(&source, 43, 48).unwrap() + ), + ], + span: Span::new(&source, 39, 49).unwrap() + })], + span: Span::new(&source, 36, 49).unwrap(), + }), span: Span::new(&source, 23, 49).unwrap() })], span: Span::new(&source, 0, 50).unwrap(), @@ -1090,7 +1082,7 @@ mod tests { field a = 1 a[32 + x][55] = y for field i in 0..3 do - a == 1 + 2 + 3+ 4+ 5+ 6+ 6+ 7+ 8 + 4+ 5+ 3+ 4+ 2+ 3 + a == 1 + 2 + 3+ 4+ 5+ 6+ 6+ 7+ 8 + 4+ 5+ 3+ 4+ 2+ 3 endfor a.member == 1 return a diff --git a/zokrates_stdlib/Cargo.toml b/zokrates_stdlib/Cargo.toml index cb48d3bb..83bafe83 100644 --- a/zokrates_stdlib/Cargo.toml +++ b/zokrates_stdlib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_stdlib" -version = "0.1.4" +version = "0.1.5" authors = ["Stefan Deml ", "schaeff "] edition = "2018" diff --git a/zokrates_stdlib/stdlib/ecc/babyjubjubParams.zok b/zokrates_stdlib/stdlib/ecc/babyjubjubParams.zok index cd9386f4..a1bae4bf 100644 --- a/zokrates_stdlib/stdlib/ecc/babyjubjubParams.zok +++ b/zokrates_stdlib/stdlib/ecc/babyjubjubParams.zok @@ -1,17 +1,30 @@ -// Parameters are based on: https://github.com/HarryR/ethsnarks/tree/9cdf0117c2e42c691e75b98979cb29b099eca998/src/jubjub +// Parameters are based on: https://github.com/HarryR/ethsnarks/tree/9cdf0117c2e42c691e75b98979cb29b099eca998/src/jubjub // Note: parameters will be updated soon to be more compatible with zCash's implementation -def main() -> (field[10]): + +struct BabyJubJubParams { + field JUBJUBE + field JUBJUBC + field JUBJUBA + field JUBJUBD + field MONTA + field MONTB + field[2] INFINITY + field Gu + field Gv +} + +def main() -> (BabyJubJubParams): // Order of the curve E - field JUBJUBE = 21888242871839275222246405745257275088614511777268538073601725287587578984328 + field JUBJUBE = 21888242871839275222246405745257275088614511777268538073601725287587578984328 field JUBJUBC = 8 // Cofactor field JUBJUBA = 168700 // Coefficient A field JUBJUBD = 168696 // Coefficient D field MONTA = 168698 // int(2*(JUBJUB_A+JUBJUB_D)/(JUBJUB_A-JUBJUB_D)) field MONTB = 1 // int(4/(JUBJUB_A-JUBJUB_D)) - + // Point at infinity - field[2] infinity = [0, 1] + field[2] INFINITY = [0, 1] // Generator field Gu = 16540640123574156134436876038791482806971768689494387082833631921987005038935 @@ -19,4 +32,14 @@ def main() -> (field[10]): // Index // 0 1 2 3 4 5 6 7 8 10 -return [JUBJUBA, JUBJUBD, infinity[0], infinity[1], Gu, Gv, JUBJUBE, JUBJUBC, MONTA, MONTB] +return BabyJubJubParams { + JUBJUBA: JUBJUBA, + JUBJUBD: JUBJUBD, + INFINITY: INFINITY, + Gu: Gu, + Gv: Gv, + JUBJUBE: JUBJUBE, + JUBJUBC: JUBJUBC, + MONTA: MONTA, + MONTB: MONTB +} diff --git a/zokrates_stdlib/stdlib/ecc/edwardsAdd.zok b/zokrates_stdlib/stdlib/ecc/edwardsAdd.zok index 99de1522..29874296 100644 --- a/zokrates_stdlib/stdlib/ecc/edwardsAdd.zok +++ b/zokrates_stdlib/stdlib/ecc/edwardsAdd.zok @@ -1,11 +1,13 @@ -import "ecc/babyjubjubParams" as context +from "ecc/babyjubjubParams" import main as context +from "ecc/babyjubjubParams" import BabyJubJubParams + // Add two points on a twisted Edwards curve // Curve parameters are defined with the last argument // https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Addition_on_twisted_Edwards_curves -def main(field[2] pt1, field[2] pt2, field[10] context) -> (field[2]): +def main(field[2] pt1, field[2] pt2, BabyJubJubParams context) -> (field[2]): - field a = context[0] - field d = context[1] + field a = context.JUBJUBA + field d = context.JUBJUBD field u1 = pt1[0] field v1 = pt1[1] diff --git a/zokrates_stdlib/stdlib/ecc/edwardsCompress.zok b/zokrates_stdlib/stdlib/ecc/edwardsCompress.zok index 7b874e7b..15109f03 100644 --- a/zokrates_stdlib/stdlib/ecc/edwardsCompress.zok +++ b/zokrates_stdlib/stdlib/ecc/edwardsCompress.zok @@ -1,4 +1,5 @@ import "utils/pack/nonStrictUnpack256" as unpack256 + // Compress JubJub Curve Point to 256bit array using big endianness bit order // Python reference code from pycrypto: // def compress(self): @@ -6,7 +7,7 @@ import "utils/pack/nonStrictUnpack256" as unpack256 // y = self.y.n // return int.to_bytes(y | ((x & 1) << 255), 32, "big") -def main(field[2] pt, field[10] context) -> (field[256]): +def main(field[2] pt) -> (field[256]): field x = pt[0] field y = pt[1] diff --git a/zokrates_stdlib/stdlib/ecc/edwardsNegate.zok b/zokrates_stdlib/stdlib/ecc/edwardsNegate.zok index af6d8156..43ac5cbf 100644 --- a/zokrates_stdlib/stdlib/ecc/edwardsNegate.zok +++ b/zokrates_stdlib/stdlib/ecc/edwardsNegate.zok @@ -1,8 +1,7 @@ -import "ecc/babyjubjubParams" as context // Negate a point on an Edwards curve // Curve parameters are defined with the last argument // Twisted Edwards Curves, BBJLP-2008, section 2 pg 2 -def main(field[2] pt, field[10] context) -> (field[2]): +def main(field[2] pt) -> (field[2]): field u = pt[0] field v = pt[1] diff --git a/zokrates_stdlib/stdlib/ecc/edwardsOnCurve.zok b/zokrates_stdlib/stdlib/ecc/edwardsOnCurve.zok index 67f1ded3..fa42e1a4 100644 --- a/zokrates_stdlib/stdlib/ecc/edwardsOnCurve.zok +++ b/zokrates_stdlib/stdlib/ecc/edwardsOnCurve.zok @@ -1,16 +1,18 @@ +from "ecc/babyjubjubParams" import BabyJubJubParams + // Check if a point is on a twisted Edwards curve // Curve parameters are defined with the last argument // See appendix 3.3.1 of Zcash protocol specification: // https://github.com/zcash/zips/blob/master/protocol/protocol.pdf -def main(field[2] pt, field[10] context) -> (field): +def main(field[2] pt, BabyJubJubParams context) -> (field): - field a = context[0] - field d = context[1] + field a = context.JUBJUBA + field d = context.JUBJUBD field uu = pt[0] * pt[0] field vv = pt[1] * pt[1] field uuvv = uu * vv - + a * uu + vv == 1 + d * uuvv return 1 diff --git a/zokrates_stdlib/stdlib/ecc/edwardsOrderCheck.zok b/zokrates_stdlib/stdlib/ecc/edwardsOrderCheck.zok index ca0c5daf..fc1d342c 100644 --- a/zokrates_stdlib/stdlib/ecc/edwardsOrderCheck.zok +++ b/zokrates_stdlib/stdlib/ecc/edwardsOrderCheck.zok @@ -1,25 +1,29 @@ import "ecc/edwardsAdd" as add import "ecc/edwardsScalarMult" as multiply import "utils/pack/nonStrictUnpack256" as unpack256 +from "ecc/babyjubjubParams" import BabyJubJubParams + // Verifies that the point is not one of the low-order points. // If any of the points is multiplied by the cofactor, the resulting point -// will be infinity. +// will be infinity. // Returns 1 if the point is not one of the low-order points, 0 otherwise. // Curve parameters are defined with the last argument // https://github.com/zcash-hackworks/sapling-crypto/blob/master/src/jubjub/edwards.rs#L166 -def main(field[2] pt, field[10] context) -> (field): +def main(field[2] pt, BabyJubJubParams context) -> (field): - field cofactor = context[7] + field cofactor = context.JUBJUBC + + cofactor == 8 // Co-factor currently hard-coded to 8 for efficiency reasons // See discussion here: https://github.com/Zokrates/ZoKrates/pull/301#discussion_r267203391 // Generic code: - // field[256] cofactorExponent = unpack256(cofactor) + // field[256] cofactorExponent = unpack256(cofactor) // field[2] ptExp = multiply(cofactorExponent, pt, context) field[2] ptExp = add(pt, pt, context) // 2*pt ptExp = add(ptExp, ptExp, context) // 4*pt ptExp = add(ptExp, ptExp, context) // 8*pt - + field out = if ptExp[0] == 0 && ptExp[1] == 1 then 0 else 1 fi return out diff --git a/zokrates_stdlib/stdlib/ecc/edwardsScalarMult.zok b/zokrates_stdlib/stdlib/ecc/edwardsScalarMult.zok index ccd32539..1f47d8b8 100644 --- a/zokrates_stdlib/stdlib/ecc/edwardsScalarMult.zok +++ b/zokrates_stdlib/stdlib/ecc/edwardsScalarMult.zok @@ -1,21 +1,23 @@ import "ecc/edwardsAdd" as add import "ecc/edwardsOnCurve" as assertOnCurve +from "ecc/babyjubjubParams" import BabyJubJubParams + // Function that implements scalar multiplication for a fixed base point // Curve parameters are defined with the last argument // The exponent is hard-coded to a 256bit scalar, hence we allow wrapping around the group for certain -// curve parameters. +// curve parameters. // Note that the exponent array is not check to be boolean in this gadget // Reference: https://github.com/zcash-hackworks/sapling-crypto/blob/master/src/jubjub/fs.rs#L555 -def main(field[256] exponent, field[2] pt, field[10] context) -> (field[2]): +def main(field[256] exponent, field[2] pt, BabyJubJubParams context) -> (field[2]): - field[2] infinity = [context[2], context[3]] + field[2] infinity = context.INFINITY field[2] doubledP = pt field[2] accumulatedP = infinity - + for field i in 0..256 do field j = 255 - i - candidateP = add(accumulatedP, doubledP, context) + field[2] candidateP = add(accumulatedP, doubledP, context) accumulatedP = if exponent[j] == 1 then candidateP else accumulatedP fi doubledP = add(doubledP, doubledP, context) endfor diff --git a/zokrates_stdlib/stdlib/ecc/proofOfOwnership.zok b/zokrates_stdlib/stdlib/ecc/proofOfOwnership.zok index f6b0c1fd..a959ad55 100644 --- a/zokrates_stdlib/stdlib/ecc/proofOfOwnership.zok +++ b/zokrates_stdlib/stdlib/ecc/proofOfOwnership.zok @@ -1,6 +1,7 @@ import "ecc/edwardsAdd" as add import "ecc/edwardsScalarMult" as multiply import "utils/pack/nonStrictUnpack256" as unpack256 +from "ecc/babyjubjubParams" import BabyJubJubParams /// Verifies match of a given public/private keypair. /// @@ -16,9 +17,9 @@ import "utils/pack/nonStrictUnpack256" as unpack256 /// /// Returns: /// Return 1 for pk/sk being a valid keypair, 0 otherwise. -def main(field[2] pk, field sk, field[10] context) -> (field): +def main(field[2] pk, field sk, BabyJubJubParams context) -> (field): - field[2] G = [context[4], context[5]] + field[2] G = [context.Gu, context.Gv] field[256] skBits = unpack256(sk) field[2] ptExp = multiply(skBits, G, context) diff --git a/zokrates_stdlib/stdlib/hashes/pedersen/512bit.zok b/zokrates_stdlib/stdlib/hashes/pedersen/512bit.zok index ea704854..a1d18a85 100644 --- a/zokrates_stdlib/stdlib/hashes/pedersen/512bit.zok +++ b/zokrates_stdlib/stdlib/hashes/pedersen/512bit.zok @@ -3,6 +3,7 @@ import "utils/multiplexer/lookup2bit" as sel2 import "ecc/babyjubjubParams" as context import "ecc/edwardsAdd" as add import "ecc/edwardsCompress" as edwardsCompress +from "ecc/babyjubjubParams" import BabyJubJubParams // Code to export generators used in this example: // import bitstring @@ -12,15 +13,15 @@ import "ecc/edwardsCompress" as edwardsCompress // #%% // entropy = np.random.bytes(64) // hasher = PedersenHasher("test") -// print(hasher.dsl_code) +// print(hasher.dsl_code) // 512bit to 256bit Pedersen hash using compression of the field elements def main(field[512] e) -> (field[256]): - context = context() - field[2] a = [context[2], context[3]] //Infinity + BabyJubJubParams context = context() + field[2] a = context.INFINITY //Infinity //Round 0 - cx = sel3s([e[0], e[1], e[2]], [13418723823902222986275588345615650707197303761863176429873001977640541977977 , 8366451672790208592553809639953117385619257483837439526516290319251622927412, 1785026334726838136757054176272745265857971873904476677125553010508875025629, 15763987975760561753692294837740043971877392788040801334205375164715487005236]) - cy = sel2([e[0], e[1]], [15255921313433251341520743036334816584226787412845488772781699434149539664639 , 10916775373885716961512013142444429405184550001421868906213743991404593770484, 18533662942827602783563125901366807026309605479742251601915445402562880550265, 12754584346112149619040942896930712185968371085994381911052593922432846916845]) + field cx = sel3s([e[0], e[1], e[2]], [13418723823902222986275588345615650707197303761863176429873001977640541977977 , 8366451672790208592553809639953117385619257483837439526516290319251622927412, 1785026334726838136757054176272745265857971873904476677125553010508875025629, 15763987975760561753692294837740043971877392788040801334205375164715487005236]) + field cy = sel2([e[0], e[1]], [15255921313433251341520743036334816584226787412845488772781699434149539664639 , 10916775373885716961512013142444429405184550001421868906213743991404593770484, 18533662942827602783563125901366807026309605479742251601915445402562880550265, 12754584346112149619040942896930712185968371085994381911052593922432846916845]) a = add(a, [cx, cy], context) //Round 1 cx = sel3s([e[3], e[4], e[5]], [10096735692467598736728394557736034054031417419721869067082824451240861468728 , 6979151010236415881632946866847657030447196774231162748523315765559549846746, 12137947022495312670974525048647679757468392619153927921382150023166867027471, 10624360821702266736197468438435445939719745367234393212061381062942588576905]) @@ -703,5 +704,5 @@ def main(field[512] e) -> (field[256]): cy = sel2([e[510], e[511]], [2329094643034533408459502544740928833981119919633412709248656884170940780093 , 3216329736050668550647765981020076413548845117352735257893224753954595290363, 18710403072495673647060422294369054840513840567808020912157404388689648711093, 9785201456176703812798077455183487364035650707229293534561747881523562553649]) a = add(a, [cx, cy], context) - field[256] aC = edwardsCompress(a, context) + field[256] aC = edwardsCompress(a) return aC diff --git a/zokrates_stdlib/stdlib/hashes/pedersen/6bit.zok b/zokrates_stdlib/stdlib/hashes/pedersen/6bit.zok index ca535350..491b34c8 100644 --- a/zokrates_stdlib/stdlib/hashes/pedersen/6bit.zok +++ b/zokrates_stdlib/stdlib/hashes/pedersen/6bit.zok @@ -1,16 +1,17 @@ -import "utils/multiplexer/lookup3bitSigned" as sel3s -import "utils/multiplexer/lookup2bit" as sel2 +import "utils/multiplexer/lookup3bitSigned" as sel3s +import "utils/multiplexer/lookup2bit" as sel2 import "ecc/babyjubjubParams" as context +from "ecc/babyjubjubParams" import BabyJubJubParams import "ecc/edwardsAdd" as add def main(field[6] e) -> (field[2]): - context = context() + BabyJubJubParams context = context() - field[2] a = [context[2], context[3]] //Infinity + field[2] a = context.INFINITY //Infinity //Round 0 - cx = sel3s([e[0], e[1], e[2]], [13418723823902222986275588345615650707197303761863176429873001977640541977977 , 8366451672790208592553809639953117385619257483837439526516290319251622927412, 1785026334726838136757054176272745265857971873904476677125553010508875025629, 15763987975760561753692294837740043971877392788040801334205375164715487005236]) - cy = sel2([e[0], e[1]], [15255921313433251341520743036334816584226787412845488772781699434149539664639 , 10916775373885716961512013142444429405184550001421868906213743991404593770484, 18533662942827602783563125901366807026309605479742251601915445402562880550265, 12754584346112149619040942896930712185968371085994381911052593922432846916845]) + field cx = sel3s([e[0], e[1], e[2]], [13418723823902222986275588345615650707197303761863176429873001977640541977977 , 8366451672790208592553809639953117385619257483837439526516290319251622927412, 1785026334726838136757054176272745265857971873904476677125553010508875025629, 15763987975760561753692294837740043971877392788040801334205375164715487005236]) + field cy = sel2([e[0], e[1]], [15255921313433251341520743036334816584226787412845488772781699434149539664639 , 10916775373885716961512013142444429405184550001421868906213743991404593770484, 18533662942827602783563125901366807026309605479742251601915445402562880550265, 12754584346112149619040942896930712185968371085994381911052593922432846916845]) a = add(a, [cx, cy], context) //Round 1 cx = sel3s([e[3], e[4], e[5]], [10096735692467598736728394557736034054031417419721869067082824451240861468728 , 6979151010236415881632946866847657030447196774231162748523315765559549846746, 12137947022495312670974525048647679757468392619153927921382150023166867027471, 10624360821702266736197468438435445939719745367234393212061381062942588576905]) diff --git a/zokrates_stdlib/stdlib/hashes/sha256/1024bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/1024bit.zok index 7ac2ab77..949dba4c 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/1024bit.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/1024bit.zok @@ -1,13 +1,13 @@ -import "./IVconstants" as IVconstants -import "./shaRoundNoBoolCheck" as sha256 +import "./IVconstants" as IVconstants +import "./shaRoundNoBoolCheck" as sha256 -// A function that takes 4 field[256] arrays as inputs +// A function that takes 4 field[256] arrays as inputs // and applies 2 rounds of sha256 compression. // It returns an array of 256 field elements. def main(field[256] a, field[256] b, field[256] c, field[256] d) -> (field[256]): - IV = IVconstants() - digest1 = sha256(a, b, IV) - digest2 = sha256(c, d, digest1) + field[256] IV = IVconstants() + field[256] digest1 = sha256(a, b, IV) + field[256] digest2 = sha256(c, d, digest1) return digest2 \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/1024bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/1024bitPadded.zok index 9d73110b..bc7e8192 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/1024bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/1024bitPadded.zok @@ -1,15 +1,15 @@ import "./1536bit" as sha256 -// Take two field[256] arrays as input +// Take two field[256] arrays as input // and returns their sha256 full round output as an array of 256 field elements. def main(field[256] a, field[256] b, field[256] c, field[256] d) -> (field[256]): - // Hash is computed on the full 512bit block size - // padding does not fit in the primary block + // Hash is computed on the full 1024bit block size + // padding does not fit in the first two blocks // add dummy block (single "1" followed by "0" + total length) field[256] dummyblock1 = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - // total length of message is 512 bits: 0b1000000000 + // total length of message is 1024 bits: 0b10000000000 field[256] dummyblock2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - digest = sha256(a, b, c, d, dummyblock1, dummyblock2) + field[256] digest = sha256(a, b, c, d, dummyblock1, dummyblock2) return digest diff --git a/zokrates_stdlib/stdlib/hashes/sha256/1536bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/1536bit.zok index bcb3c008..ce679f33 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/1536bit.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/1536bit.zok @@ -1,14 +1,14 @@ -import "./IVconstants" as IVconstants -import "./shaRoundNoBoolCheck" as sha256 +import "./IVconstants" as IVconstants +import "./shaRoundNoBoolCheck" as sha256 -// A function that takes 6 field[256] arrays as inputs +// A function that takes 6 field[256] arrays as inputs // and applies 3 rounds of sha256 compression. // It returns an array of 256 field elements. def main(field[256] a, field[256] b, field[256] c, field[256] d, field[256] e, field[256] f) -> (field[256]): - IV = IVconstants() - digest1 = sha256(a, b, IV) - digest2 = sha256(c, d, digest1) - digest3 = sha256(e, f, digest2) + field[256] IV = IVconstants() + field[256] digest1 = sha256(a, b, IV) + field[256] digest2 = sha256(c, d, digest1) + field[256] digest3 = sha256(e, f, digest2) return digest3 \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/256bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/256bitPadded.zok index 8c572edb..7a143dd7 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/256bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/256bitPadded.zok @@ -1,12 +1,12 @@ -import "./512bit" as sha256 +import "./512bit" as sha256 -// A function that takes 1 field[256] array as input +// A function that takes 1 field[256] array as input // and returns the sha256 full round output as an array of 256 field elements. def main(field[256] a) -> (field[256]): // Hash is computed on 256 bits of input // padding fits in the remaining 256 bits of the first block - // add dummy block (single "1" followed by "0" + total length) + // add dummy block (single "1" followed by "0" + total length) field[256] dummyblock1 = [ \ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ diff --git a/zokrates_stdlib/stdlib/hashes/sha256/512bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/512bit.zok index 1379ff79..a353f43b 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/512bit.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/512bit.zok @@ -1,15 +1,15 @@ -import "./IVconstants" as IVconstants -import "./shaRoundNoBoolCheck" as sha256 +import "./IVconstants" as IVconstants +import "./shaRoundNoBoolCheck" as sha256 -// A function that takes 2 field[256] arrays as inputs +// A function that takes 2 field[256] arrays as inputs // and returns their sha256 compression function as an array of 256 field elements. -// In contrast to full_round.zok no padding is being applied +// In contrast to full_round.zok no padding is being applied def main(field[256] a, field[256] b) -> (field[256]): // a and b is NOT checked to be of type bool - IV = IVconstants() - digest = sha256(a, b, IV) - //digest is constraint to be of type bool + field[256] IV = IVconstants() + field[256] digest = sha256(a, b, IV) + //digest is constraint to be of type bool - return digest + return digest diff --git a/zokrates_stdlib/stdlib/hashes/sha256/512bitPacked.zok b/zokrates_stdlib/stdlib/hashes/sha256/512bitPacked.zok index 37b3305b..00bc9894 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/512bitPacked.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/512bitPacked.zok @@ -3,20 +3,20 @@ import "../../utils/pack/unpack128" as unpack128 import "./512bitPadded" as sha256 // A function that takes an array of 4 field elements as inputs, unpacks each of them to 128 // bits (big endian), concatenates them and applies sha256. -// It then returns an array of two field elements, each representing 128 bits of the result. +// It then returns an array of two field elements, each representing 128 bits of the result. def main(field[4] preimage) -> (field[2]): - a = unpack128(preimage[0]) - b = unpack128(preimage[1]) - c = unpack128(preimage[2]) - d = unpack128(preimage[3]) - + field[128] a = unpack128(preimage[0]) + field[128] b = unpack128(preimage[1]) + field[128] c = unpack128(preimage[2]) + field[128] d = unpack128(preimage[3]) + field[256] lhs = [...a, ...b] field[256] rhs = [...c, ...d] - - field[256] r = sha256(lhs, rhs) - - res0 = pack128(r[..128]) - res1 = pack128(r[128..]) - return [res0, res1] \ No newline at end of file + field[256] r = sha256(lhs, rhs) + + field res0 = pack128(r[..128]) + field res1 = pack128(r[128..]) + + return [res0, res1] \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/512bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/512bitPadded.zok index 5ea988e2..17a7353a 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/512bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/512bitPadded.zok @@ -1,16 +1,16 @@ -import "./1024bit" as sha256 +import "./1024bit" as sha256 -// A function that takes 2 field[256] arrays as inputs +// A function that takes 2 field[256] arrays as inputs // and returns their sha256 full round output as an array of 256 field elements. def main(field[256] a, field[256] b) -> (field[256]): - // Hash is computed on the full 512bit block size + // Hash is computed on the full 512bit block size // padding does not fit in the primary block - // add dummy block (single "1" followed by "0" + total length) + // add dummy block (single "1" followed by "0" + total length) field[256] dummyblock1 = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] // total length of message is 512 bits: 0b1000000000 field[256] dummyblock2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - digest = sha256(a, b, dummyblock1, dummyblock2) + field[256] digest = sha256(a, b, dummyblock1, dummyblock2) - return digest \ No newline at end of file + return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/signatures/verifyEddsa.zok b/zokrates_stdlib/stdlib/signatures/verifyEddsa.zok index 2d88b4e1..6c553ad4 100644 --- a/zokrates_stdlib/stdlib/signatures/verifyEddsa.zok +++ b/zokrates_stdlib/stdlib/signatures/verifyEddsa.zok @@ -1,9 +1,10 @@ import "hashes/sha256/1024bitPadded" as sha256 -import "ecc/edwardsScalarMult" as scalarMult +import "ecc/edwardsScalarMult" as scalarMult import "ecc/edwardsAdd" as add import "utils/pack/nonStrictUnpack256" as unpack256 import "ecc/edwardsOnCurve" as onCurve import "ecc/edwardsOrderCheck" as orderCheck +from "ecc/babyjubjubParams" import BabyJubJubParams /// Verifies an EdDSA Signature. /// @@ -26,17 +27,17 @@ import "ecc/edwardsOrderCheck" as orderCheck /// /// Returns: /// Return 1 for S being a valid EdDSA Signature, 0 otherwise. -def main(private field[2] R, private field S, field[2] A, field[256] M0, field[256] M1, field[10] context) -> (field): +def main(private field[2] R, private field S, field[2] A, field[256] M0, field[256] M1, BabyJubJubParams context) -> (field): - field[2] G = [context[4], context[5]] + field[2] G = [context.Gu, context.Gv] - // Check if R is on curve and if it is not in a small subgroup. A is public input and can be checked offline + // Check if R is on curve and if it is not in a small subgroup. A is public input and can be checked offline field isOnCurve = onCurve(R, context) // throws if R is not on curve field isPrimeOrder = orderCheck(R, context) 1 == isPrimeOrder field[256] Rx = unpack256(R[0]) - field[256] Ax = unpack256(A[0]) + field[256] Ax = unpack256(A[0]) field[256] hRAM = sha256(Rx, Ax, M0, M1) field[256] sBits = unpack256(S) @@ -47,4 +48,4 @@ def main(private field[2] R, private field S, field[2] A, field[256] M0, field[2 field out = if rhs[0] == lhs[0] && rhs[1] == lhs[1] then 1 else 0 fi - return out + return out diff --git a/zokrates_stdlib/stdlib/utils/casts/1024to256array.zok b/zokrates_stdlib/stdlib/utils/casts/1024to256array.zok index 09a5a910..8663a5ed 100644 --- a/zokrates_stdlib/stdlib/utils/casts/1024to256array.zok +++ b/zokrates_stdlib/stdlib/utils/casts/1024to256array.zok @@ -1,3 +1,3 @@ def main(field[1024] input) -> (field[256], field[256], field[256], field[256]): - return input[0..256], input[256..512], input[512..768], input[768..1024] \ No newline at end of file + return input[0..256], input[256..512], input[512..768], input[768..1024] \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/utils/multiplexer/lookup3bitSigned.zok b/zokrates_stdlib/stdlib/utils/multiplexer/lookup3bitSigned.zok index b4b79f1f..355e70a9 100644 --- a/zokrates_stdlib/stdlib/utils/multiplexer/lookup3bitSigned.zok +++ b/zokrates_stdlib/stdlib/utils/multiplexer/lookup3bitSigned.zok @@ -5,7 +5,7 @@ import "./lookup2bit" as lookup // */ def main(field[3] b, field[4] c) -> (field): - field alpha = lookup([b[0], b[1]], c) + field alpha = lookup([b[0], b[1]], c) field out = alpha - 2*b[2]*alpha return out \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/utils/pack/pack128.zok b/zokrates_stdlib/stdlib/utils/pack/pack128.zok index 77966fe5..d17066be 100644 --- a/zokrates_stdlib/stdlib/utils/pack/pack128.zok +++ b/zokrates_stdlib/stdlib/utils/pack/pack128.zok @@ -7,4 +7,4 @@ def main(field[128] bits) -> (field): out = out + bits[i] * (2 ** j) endfor - return out \ No newline at end of file + return out \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/utils/pack/pack256.zok b/zokrates_stdlib/stdlib/utils/pack/pack256.zok index ce8d9029..bb0aee52 100644 --- a/zokrates_stdlib/stdlib/utils/pack/pack256.zok +++ b/zokrates_stdlib/stdlib/utils/pack/pack256.zok @@ -7,4 +7,4 @@ def main(field[256] bits) -> (field): out = out + bits[i] * (2 ** j) endfor - return out \ No newline at end of file + return out \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/ecc/edwardsAdd.zok b/zokrates_stdlib/tests/tests/ecc/edwardsAdd.zok index 6c5ac9fe..48866390 100644 --- a/zokrates_stdlib/tests/tests/ecc/edwardsAdd.zok +++ b/zokrates_stdlib/tests/tests/ecc/edwardsAdd.zok @@ -1,13 +1,14 @@ import "ecc/edwardsAdd" as add -import "ecc/edwardsNegate" as neg +import "ecc/edwardsNegate" as neg import "ecc/babyjubjubParams" as context +from "ecc/babyjubjubParams" import BabyJubJubParams // Code to create test cases: -// https://github.com/Zokrates/pycrypto +// https://github.com/Zokrates/pycrypto def testDoubleViaAdd() -> (field): - context = context() - field[2] G = [context[4], context[5]] - + BabyJubJubParams context = context() + field[2] G = [context.Gu, context.Gv] + field[2] out = add(G, G, context) out[0] == 17324563846726889236817837922625232543153115346355010501047597319863650987830 @@ -16,13 +17,13 @@ def testDoubleViaAdd() -> (field): return 1 def testIdentities() -> (field): - context = context() - field[2] G = [context[4], context[5]] - field[2] inf = [context[2], context[3]] + BabyJubJubParams context = context() + field[2] G = [context.Gu, context.Gv] + field[2] inf = context.INFINITY G == add(G, inf, context) - field[2] nG = neg(G, context) + field[2] nG = neg(G) field[2] nGaddG = add(G, nG, context) inf == nGaddG diff --git a/zokrates_stdlib/tests/tests/ecc/edwardsCompress.zok b/zokrates_stdlib/tests/tests/ecc/edwardsCompress.zok index 6a18be1b..b5161097 100644 --- a/zokrates_stdlib/tests/tests/ecc/edwardsCompress.zok +++ b/zokrates_stdlib/tests/tests/ecc/edwardsCompress.zok @@ -1,17 +1,18 @@ -import "ecc/edwardsCompress" as edwardsCompress +import "ecc/edwardsCompress" as edwardsCompress import "ecc/babyjubjubParams" as context +from "ecc/babyjubjubParams" import BabyJubJubParams // Code to create test cases: -// https://github.com/Zokrates/pycrypto +// https://github.com/Zokrates/pycrypto def testCompress() -> (field): - context = context() + BabyJubJubParams context = context() - field Gu = context[4] - field Gv = context[5] + field Gu = context.Gu + field Gv = context.Gv - Gcompressed = edwardsCompress([Gu, Gv], context) + field[256] Gcompressed = edwardsCompress([Gu, Gv]) - Gcompressed = [1,0,1,0,1,1,1,0,0,0,0,0,0,1,1,1,0,0,1,0,1,0,0,1,0,1,1,1,1,1,1,1,1,0,0,0,1,1,0,1,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,1,0,1,1,1,1,0,0,0,0,0,0,1,1,0,0,0,1,1,0,1,1,0,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,0,0,1,1,0,1,0,1,0,1,0,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,1,1,0,1,0,1,0,0,1,1,1,0,1,0,1,0,0,1,1,1,0,1,1,0,1,0,0,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,0,0,0,1,1,1,0,1,0,0,0,1,0,0,1,1,0,1,0,0,1,0,0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,0,0,1,1,0,0,1,0,0,0,1,0,1,0,1,0,0,1,0,1,1,0,1,0,1,1,1] + Gcompressed == [1,0,1,0,1,1,1,0,0,0,0,0,0,1,1,1,0,0,1,0,1,0,0,1,0,1,1,1,1,1,1,1,1,0,0,0,1,1,0,1,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,1,0,1,1,1,1,0,0,0,0,0,0,1,1,0,0,0,1,1,0,1,1,0,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,0,0,1,1,0,1,0,1,0,1,0,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,1,1,0,1,0,1,0,0,1,1,1,0,1,0,1,0,0,1,1,1,0,1,1,0,1,0,0,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,0,0,0,1,1,1,0,1,0,0,0,1,0,0,1,1,0,1,0,0,1,0,0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,0,0,1,1,0,0,1,0,0,0,1,0,1,0,1,0,0,1,0,1,1,0,1,0,1,1,1] return 1 diff --git a/zokrates_stdlib/tests/tests/ecc/edwardsOnCurve.zok b/zokrates_stdlib/tests/tests/ecc/edwardsOnCurve.zok index 7f92a8bc..8ac5b6ba 100644 --- a/zokrates_stdlib/tests/tests/ecc/edwardsOnCurve.zok +++ b/zokrates_stdlib/tests/tests/ecc/edwardsOnCurve.zok @@ -1,10 +1,11 @@ import "ecc/babyjubjubParams" as context +from "ecc/babyjubjubParams" import BabyJubJubParams import "ecc/edwardsOnCurve" as onCurve // Code to create test cases: -// https://github.com/Zokrates/pycrypto +// https://github.com/Zokrates/pycrypto def testOnCurveTrue() -> (field): - context = context() + BabyJubJubParams context = context() field testU = 17324563846726889236817837922625232543153115346355010501047597319863650987830 field testV = 20022170825455209233733649024450576091402881793145646502279487074566492066831 diff --git a/zokrates_stdlib/tests/tests/ecc/edwardsOrderCheck.zok b/zokrates_stdlib/tests/tests/ecc/edwardsOrderCheck.zok index 641f557c..eb0ca612 100644 --- a/zokrates_stdlib/tests/tests/ecc/edwardsOrderCheck.zok +++ b/zokrates_stdlib/tests/tests/ecc/edwardsOrderCheck.zok @@ -1,10 +1,11 @@ import "ecc/edwardsOrderCheck" as orderCheck import "ecc/babyjubjubParams" as context +from "ecc/babyjubjubParams" import BabyJubJubParams // Code to create test cases: -// https://github.com/Zokrates/pycrypto +// https://github.com/Zokrates/pycrypto def testOrderCheckTrue() -> (field): - context = context() + BabyJubJubParams context = context() field testU = 17324563846726889236817837922625232543153115346355010501047597319863650987830 field testV = 20022170825455209233733649024450576091402881793145646502279487074566492066831 @@ -15,7 +16,7 @@ def testOrderCheckTrue() -> (field): return 1 def testOrderCheckFalse() -> (field): - context = context() + BabyJubJubParams context = context() field testU = 4342719913949491028786768530115087822524712248835451589697801404893164183326 field testV = 4826523245007015323400664741523384119579596407052839571721035538011798951543 diff --git a/zokrates_stdlib/tests/tests/ecc/edwardsScalarMult.zok b/zokrates_stdlib/tests/tests/ecc/edwardsScalarMult.zok index 00f08260..12598615 100644 --- a/zokrates_stdlib/tests/tests/ecc/edwardsScalarMult.zok +++ b/zokrates_stdlib/tests/tests/ecc/edwardsScalarMult.zok @@ -1,11 +1,12 @@ import "ecc/babyjubjubParams" as context +from "ecc/babyjubjubParams" import BabyJubJubParams import "ecc/edwardsScalarMult" as mul // Code to create test cases: -// https://github.com/Zokrates/pycrypto +// https://github.com/Zokrates/pycrypto def testCyclic() -> (field): - context = context() - field[2] G = [context[4], context[5]] + BabyJubJubParams context = context() + field[2] G = [context.Gu, context.Gv] // exp = JUBJUB_E + 1 field[256] exp = [0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1] @@ -16,10 +17,10 @@ def testCyclic() -> (field): return 1 def testMul2() -> (field): - context = context() - field[2] G = [context[4], context[5]] + BabyJubJubParams context = context() + field[2] G = [context.Gu, context.Gv] - // exp == 2 + // exp == 2 field[256] exp = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0] field[2] out = mul(exp, G, context) @@ -29,13 +30,13 @@ def testMul2() -> (field): return 1 def testAssociativity() -> (field): - context = context() - field[2] G = [context[4], context[5]] + BabyJubJubParams context = context() + field[2] G = [context.Gu, context.Gv] // a = 1234 - field[256] a = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0] + field[256] a = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0] // b = 5678 - field[256] b = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0] + field[256] b = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0] // c = 7890 field[256] c = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0] @@ -58,11 +59,11 @@ def testAssociativity() -> (field): return 1 def testMultiplicative() -> (field): - context = context() - field[2] G = [context[4], context[5]] + BabyJubJubParams context = context() + field[2] G = [context.Gu, context.Gv] // a = 1234 - field[256] a = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0] + field[256] a = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0] // b = 5678 field[256] b = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0] // ab = a*b = 7006652 @@ -80,7 +81,7 @@ def testMultiplicative() -> (field): Gba == Gmab Gab == Gmab - return 1 + return 1 def main() -> (field): 1 == testMul2() diff --git a/zokrates_stdlib/tests/tests/ecc/proofOfOwnership.zok b/zokrates_stdlib/tests/tests/ecc/proofOfOwnership.zok index 9e8a2f95..9c0e7654 100644 --- a/zokrates_stdlib/tests/tests/ecc/proofOfOwnership.zok +++ b/zokrates_stdlib/tests/tests/ecc/proofOfOwnership.zok @@ -1,35 +1,36 @@ import "ecc/babyjubjubParams" as context +from "ecc/babyjubjubParams" import BabyJubJubParams import "ecc/proofOfOwnership" as proofOfOwnership import "ecc/edwardsScalarMult" as multiply import "utils/pack/nonStrictUnpack256" as unpack256 // Code to create test cases: -// https://github.com/Zokrates/pycrypto +// https://github.com/Zokrates/pycrypto def testOwnershipTrue() -> (field): - context = context() - field[2] G = [context[4], context[5]] + BabyJubJubParams context = context() + field[2] G = [context.Gu, context.Gv] field[2] Pk = [14897476871502190904409029696666322856887678969656209656241038339251270171395, 16668832459046858928951622951481252834155254151733002984053501254009901876174] field sk = 1997011358982923168928344992199991480689546837621580239342656433234255379025 - field out = proofOfOwnership(Pk, sk, context) + field out = proofOfOwnership(Pk, sk, context) out == 1 - return 1 + return 1 def testtOwnershipFalse() -> (field): - context = context() + BabyJubJubParams context = context() - field[2] Pk = [16328093915569409528980874702678312730273137210288183490878184636452430630129, 9377227749598842756429258362864743065769435972445705966557343775367597326529] + field[2] Pk = [16328093915569409528980874702678312730273137210288183490878184636452430630129, 9377227749598842756429258362864743065769435972445705966557343775367597326529] field sk = 1997011358982923168928344992199991480689546837621580239342656433234255379025 - field out = proofOfOwnership(Pk, sk, context) + field out = proofOfOwnership(Pk, sk, context) out == 0 return 1 def main() -> (field): - 1 == testOwnershipTrue() - 1 == testtOwnershipFalse() + 1 == testOwnershipTrue() + 1 == testtOwnershipFalse() return 1 \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/pedersen/512bit.zok b/zokrates_stdlib/tests/tests/hashes/pedersen/512bit.zok index 3cdd32d8..f79800b5 100644 --- a/zokrates_stdlib/tests/tests/hashes/pedersen/512bit.zok +++ b/zokrates_stdlib/tests/tests/hashes/pedersen/512bit.zok @@ -16,7 +16,7 @@ import "hashes/pedersen/512bit" as pedersen def main() -> (field): - field[512] e = [0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1] + field[512] e = [0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1] field[256] d = pedersen(e) d == [0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1] diff --git a/zokrates_stdlib/tests/tests/hashes/pedersen/6bit.zok b/zokrates_stdlib/tests/tests/hashes/pedersen/6bit.zok index 832c9d2b..0a12a61e 100644 --- a/zokrates_stdlib/tests/tests/hashes/pedersen/6bit.zok +++ b/zokrates_stdlib/tests/tests/hashes/pedersen/6bit.zok @@ -2,7 +2,7 @@ // // from zokrates.gadgets.pedersenHasher import PedersenHasher // import bitstring -// hasher = PedersenHasher("test", 2) +// hasher = PedersenHasher("test", 2) // bs = bitstring.BitArray('0b110000') // hasher.hash_bits(bs) diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/1024bitPadded.json b/zokrates_stdlib/tests/tests/hashes/sha256/1024bitPadded.json new file mode 100644 index 00000000..2798cee6 --- /dev/null +++ b/zokrates_stdlib/tests/tests/hashes/sha256/1024bitPadded.json @@ -0,0 +1,15 @@ +{ + "entry_point": "./tests/tests/hashes/sha256/1024bitPadded.zok", + "tests": [ + { + "input": { + "values": [] + }, + "output": { + "Ok": { + "values": ["1"] + } + } + } + ] +} \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/1024bitPadded.zok b/zokrates_stdlib/tests/tests/hashes/sha256/1024bitPadded.zok new file mode 100644 index 00000000..a4748e75 --- /dev/null +++ b/zokrates_stdlib/tests/tests/hashes/sha256/1024bitPadded.zok @@ -0,0 +1,29 @@ +// Python code used to create test vector: +// import hashlib + +// preimage = bytes.fromhex('00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\ +// 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\ +// 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\ +// 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05') + +// bin(int(preimage.hex(), 16)) +// # '0b101' + +// digest = hashlib.sha256(preimage).hexdigest() +// # digest = 'efa41ca4a5c76b495d55dfdbf9175320404b3c8048b38eb1873aa6633a363883' + +// bin(int(digest, 16)) +// # '0b1110111110100100000111001010010010100101110001110110101101001001010111010101010111011111110110111111100100010111010100110010000001000000010010110011110010000000010010001011001110001110101100011000011100111010101001100110001100111010001101100011100010000011' +import "hashes/sha256/1024bitPadded" as sha256 +def main() -> (field): + + field[256] a = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + field[256] b = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + field[256] c = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + field[256] d = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1] + + field[256] digest = sha256(a, b, c, d) + + digest == [1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1] + + return 1 \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/512bitPacked.zok b/zokrates_stdlib/tests/tests/hashes/sha256/512bitPacked.zok index 471a0376..7387fe09 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha256/512bitPacked.zok +++ b/zokrates_stdlib/tests/tests/hashes/sha256/512bitPacked.zok @@ -1,13 +1,13 @@ // Python code used to create test vector: -// import hashlib +// import hashlib // preimage = bytes.fromhex('00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\ // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05') -// bin(int(preimage.hex(), 16)) +// bin(int(preimage.hex(), 16)) // # '0b101' -// digest = hashlib.sha256(preimage).hexdigest() +// digest = hashlib.sha256(preimage).hexdigest() // # digest = 'c6481e22c5ff4164af680b8cfaa5e8ed3120eeff89c4f307c4a6faaae059ce10' // int(digest[:32], 16) @@ -23,7 +23,7 @@ def main() -> (field): field c = 0 field d = 5 - h = sha256packed([a, b, c, d]) + field[2] h = sha256packed([a, b, c, d]) h[0] == 263561599766550617289250058199814760685 h[1] == 65303172752238645975888084098459749904 diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/512bitPadded.zok b/zokrates_stdlib/tests/tests/hashes/sha256/512bitPadded.zok index 483c7b61..483325f4 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha256/512bitPadded.zok +++ b/zokrates_stdlib/tests/tests/hashes/sha256/512bitPadded.zok @@ -1,13 +1,13 @@ // Python code used to create test vector: -// import hashlib +// import hashlib // preimage = bytes.fromhex('00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\ // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05') -// bin(int(preimage.hex(), 16)) +// bin(int(preimage.hex(), 16)) // # '0b101' -// digest = hashlib.sha256(preimage).hexdigest() +// digest = hashlib.sha256(preimage).hexdigest() // # digest = 'c6481e22c5ff4164af680b8cfaa5e8ed3120eeff89c4f307c4a6faaae059ce10' // bin(int(digest, 16)) diff --git a/zokrates_stdlib/tests/tests/hashes/utils/256bitsDirectionHelper.zok b/zokrates_stdlib/tests/tests/hashes/utils/256bitsDirectionHelper.zok index e3ae4a34..2f21d468 100644 --- a/zokrates_stdlib/tests/tests/hashes/utils/256bitsDirectionHelper.zok +++ b/zokrates_stdlib/tests/tests/hashes/utils/256bitsDirectionHelper.zok @@ -18,7 +18,7 @@ def left() -> (field): field[256] a = [0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0] field[256] b = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1] - out = direction(0, a, b) + field[512] out = direction(0, a, b) out == [0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1] return 1 @@ -26,7 +26,7 @@ def right() -> (field): field[256] a = [0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0] field[256] b = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1] - out = direction(1, a, b) + field[512] out = direction(1, a, b) out == [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0] return 1 diff --git a/zokrates_stdlib/tests/tests/signatures/verifyEddsa.zok b/zokrates_stdlib/tests/tests/signatures/verifyEddsa.zok index 382090db..a863548d 100644 --- a/zokrates_stdlib/tests/tests/signatures/verifyEddsa.zok +++ b/zokrates_stdlib/tests/tests/signatures/verifyEddsa.zok @@ -1,19 +1,20 @@ import "signatures/verifyEddsa" as verifyEddsa import "ecc/babyjubjubParams" as context +from "ecc/babyjubjubParams" import BabyJubJubParams // Code to create test case: -// https://github.com/Zokrates/pycrypto +// https://github.com/Zokrates/pycrypto def main() -> (field): -context = context() + BabyJubJubParams context = context() - field[2] R = [20197911405516193152560090893341588680064377398162745404177962124159545390767, 9171190326927340493105240100684097896571028312802691203521747450053192554927] + field[2] R = [20197911405516193152560090893341588680064377398162745404177962124159545390767, 9171190326927340493105240100684097896571028312802691203521747450053192554927] field S = 6050429445242986634735172402304257690628456074852538287769363221635064371045 // Private Key - field[2] A = [14897476871502190904409029696666322856887678969656209656241038339251270171395, 16668832459046858928951622951481252834155254151733002984053501254009901876174] + field[2] A = [14897476871502190904409029696666322856887678969656209656241038339251270171395, 16668832459046858928951622951481252834155254151733002984053501254009901876174] - field[256] M0 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + field[256] M0 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] field[256] M1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1] field isVerified = verifyEddsa(R, S, A, M0, M1, context) diff --git a/zokrates_stdlib/tests/tests/utils/multiplexer/256bit.zok b/zokrates_stdlib/tests/tests/utils/multiplexer/256bit.zok index ef907555..9e184580 100644 --- a/zokrates_stdlib/tests/tests/utils/multiplexer/256bit.zok +++ b/zokrates_stdlib/tests/tests/utils/multiplexer/256bit.zok @@ -5,10 +5,10 @@ def left() -> (field): field[256] a = [0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0] field[256] b = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1] - field[256] output = [0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0] + field[256] output = [0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0] output == multiplex(bit, a, b) - return 1 + return 1 def right() -> (field): field bit = 1 //right @@ -19,7 +19,7 @@ def right() -> (field): field[256] output = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1] output == multiplex(bit, a, b) - return 1 + return 1 def main() -> (field): diff --git a/zokrates_stdlib/tests/tests/utils/multiplexer/2bit.zok b/zokrates_stdlib/tests/tests/utils/multiplexer/2bit.zok index 30d0e6c2..dc5bea9e 100644 --- a/zokrates_stdlib/tests/tests/utils/multiplexer/2bit.zok +++ b/zokrates_stdlib/tests/tests/utils/multiplexer/2bit.zok @@ -8,7 +8,7 @@ def left() -> (field): field[2] output = [0, 1] output == multiplex(bit, a, b) - return 1 + return 1 def right() -> (field): field bit = 1 //right @@ -18,7 +18,7 @@ def right() -> (field): field[2] output = [1, 0] output == multiplex(bit, a, b) - return 1 + return 1 def main() -> (field): diff --git a/zokrates_stdlib/tests/tests/utils/multiplexer/lookup1bit.zok b/zokrates_stdlib/tests/tests/utils/multiplexer/lookup1bit.zok index b602ea77..022d07d3 100644 --- a/zokrates_stdlib/tests/tests/utils/multiplexer/lookup1bit.zok +++ b/zokrates_stdlib/tests/tests/utils/multiplexer/lookup1bit.zok @@ -1,4 +1,4 @@ -import "utils/multiplexer/lookup1bit" as lookup +import "utils/multiplexer/lookup1bit" as lookup def left() -> (field): field sel = 0 //left @@ -6,7 +6,7 @@ def left() -> (field): 0 == lookup(sel, t) - return 1 + return 1 def right() -> (field): field sel = 1 //right @@ -14,7 +14,7 @@ def right() -> (field): 1 == lookup(sel, t) - return 1 + return 1 def main() -> (field): diff --git a/zokrates_stdlib/tests/tests/utils/multiplexer/lookup2bit.zok b/zokrates_stdlib/tests/tests/utils/multiplexer/lookup2bit.zok index 7b3dae52..052c477a 100644 --- a/zokrates_stdlib/tests/tests/utils/multiplexer/lookup2bit.zok +++ b/zokrates_stdlib/tests/tests/utils/multiplexer/lookup2bit.zok @@ -1,36 +1,36 @@ -import "utils/multiplexer/lookup2bit" as lookup +import "utils/multiplexer/lookup2bit" as lookup def first() -> (field): - field[2] sel = [0,0] + field[2] sel = [0,0] field[4] t = [0, 1, 2 , 3] 0 == lookup(sel, t) - return 1 + return 1 def second() -> (field): - field[2] sel = [1,0] + field[2] sel = [1,0] field[4] t = [0, 1, 2 , 3] 1 == lookup(sel, t) - return 1 + return 1 def thrid() -> (field): - field[2] sel = [0,1] + field[2] sel = [0,1] field[4] t = [0, 1, 2 , 3] 2 == lookup(sel, t) - return 1 + return 1 def fourth() -> (field): - field[2] sel = [1,1] + field[2] sel = [1,1] field[4] t = [0, 1, 2 , 3] 3 == lookup(sel, t) - return 1 + return 1 def main() -> (field): diff --git a/zokrates_stdlib/tests/tests/utils/multiplexer/lookup3bitSigned.zok b/zokrates_stdlib/tests/tests/utils/multiplexer/lookup3bitSigned.zok index c3af4b44..c85ba2eb 100644 --- a/zokrates_stdlib/tests/tests/utils/multiplexer/lookup3bitSigned.zok +++ b/zokrates_stdlib/tests/tests/utils/multiplexer/lookup3bitSigned.zok @@ -1,15 +1,15 @@ -import "utils/multiplexer/lookup3bitSigned" as lookup +import "utils/multiplexer/lookup3bitSigned" as lookup def first() -> (field): - field[3] sel = [0,0,0] + field[3] sel = [0,0,0] field[4] t = [0, 1, 2 , 3] 0 == lookup(sel, t) - return 1 + return 1 def firstNeg() -> (field): - field[3] sel = [0,0,1] + field[3] sel = [0,0,1] field[4] t = [0, 1, 2 , 3] 0 == lookup(sel, t) @@ -17,32 +17,32 @@ def firstNeg() -> (field): return 1 def second() -> (field): - field[3] sel = [1,0,0] + field[3] sel = [1,0,0] field[4] t = [0, 1, 2 , 3] 1 == lookup(sel, t) - return 1 + return 1 def secondNeg() -> (field): - field[3] sel = [1,0,1] + field[3] sel = [1,0,1] field[4] t = [0, 1, 2 , 3] field out = 0 - 1 out == lookup(sel, t) - return 1 + return 1 def thrid() -> (field): - field[3] sel = [0,1,0] + field[3] sel = [0,1,0] field[4] t = [0, 1, 2 , 3] 2 == lookup(sel, t) - return 1 + return 1 def thridNeg() -> (field): - field[3] sel = [0,1,1] + field[3] sel = [0,1,1] field[4] t = [0, 1, 2 , 3] field out = 0 - 2 @@ -51,7 +51,7 @@ def thridNeg() -> (field): return 1 def fourth() -> (field): - field[3] sel = [1,1,0] + field[3] sel = [1,1,0] field[4] t = [0, 1, 2 , 3] 3 == lookup(sel, t) @@ -59,13 +59,13 @@ def fourth() -> (field): return 1 def fourthNeg() -> (field): - field[3] sel = [1,1,1] + field[3] sel = [1,1,1] field[4] t = [0, 1, 2 , 3] field out = 0 - 3 out == lookup(sel, t) - return 1 + return 1 def main() -> (field): diff --git a/zokrates_stdlib/tests/tests/utils/pack/pack128.zok b/zokrates_stdlib/tests/tests/utils/pack/pack128.zok index 604de3cf..7a5ed594 100644 --- a/zokrates_stdlib/tests/tests/utils/pack/pack128.zok +++ b/zokrates_stdlib/tests/tests/utils/pack/pack128.zok @@ -20,7 +20,7 @@ def testZero() -> (field): def testMax() -> (field): - field[128] b = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] + field[128] b = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] field n = pack128(b) 340282366920938463463374607431768211455 == n diff --git a/zokrates_stdlib/tests/tests/utils/pack/unpack128.zok b/zokrates_stdlib/tests/tests/utils/pack/unpack128.zok index e4e66d31..6d86709e 100644 --- a/zokrates_stdlib/tests/tests/utils/pack/unpack128.zok +++ b/zokrates_stdlib/tests/tests/utils/pack/unpack128.zok @@ -20,7 +20,7 @@ def testMax() -> (field): field[128] b = unpack128(340282366920938463463374607431768211455) - b == [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] + b == [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] return 1 diff --git a/zokrates_test/Cargo.toml b/zokrates_test/Cargo.toml index 7204bf41..5c4ea6ca 100644 --- a/zokrates_test/Cargo.toml +++ b/zokrates_test/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "zokrates_test" -version = "0.1.0" +version = "0.1.1" authors = ["schaeff "] edition = "2018" [dependencies] zokrates_field = { version = "0.3", path = "../zokrates_field" } zokrates_core = { version = "0.4", path = "../zokrates_core" } -zokrates_fs_resolver = { version = "0.4", path = "../zokrates_fs_resolver" } +zokrates_fs_resolver = { version = "0.5", path = "../zokrates_fs_resolver" } serde = "1.0" serde_derive = "1.0" serde_json = "1.0" diff --git a/zokrates_test/src/lib.rs b/zokrates_test/src/lib.rs index ecb2934c..ab731210 100644 --- a/zokrates_test/src/lib.rs +++ b/zokrates_test/src/lib.rs @@ -15,6 +15,7 @@ enum Curve { struct Tests { pub entry_point: PathBuf, pub curves: Vec, + pub max_constraint_count: Option, pub tests: Vec, } @@ -41,6 +42,10 @@ struct Output { type Val = String; +fn parse_val(s: String) -> T { + T::try_from_dec_str(&s).unwrap() +} + impl From> for ComparableResult { fn from(r: ir::ExecutionResult) -> ComparableResult { ComparableResult(r.map(|v| v.return_values())) @@ -49,12 +54,7 @@ impl From> for ComparableResult { impl From for ComparableResult { fn from(r: TestResult) -> ComparableResult { - ComparableResult(r.map(|v| { - v.values - .iter() - .map(|v| T::try_from_dec_str(v).unwrap()) - .collect() - })) + ComparableResult(r.map(|v| v.values.into_iter().map(parse_val).collect())) } } @@ -76,7 +76,7 @@ fn compare(result: ir::ExecutionResult, expected: TestResult) -> Re use std::io::{BufReader, Read}; use zokrates_core::compile::compile; -use zokrates_fs_resolver::resolve; +use zokrates_fs_resolver::FileSystemResolver; pub fn test_inner(test_path: &str) { let t: Tests = @@ -91,30 +91,28 @@ pub fn test_inner(test_path: &str) { } fn compile_and_run(t: Tests) { - let mut code_reader = BufReader::new(File::open(&t.entry_point).unwrap()); + let code = std::fs::read_to_string(&t.entry_point).unwrap(); - let bin = compile::( - &mut code_reader, - Some( - t.entry_point - .parent() - .unwrap() - .to_str() - .unwrap() - .to_string(), + let resolver = FileSystemResolver::new(); + let artifacts = compile::(code, t.entry_point.clone(), Some(&resolver)).unwrap(); + + let bin = artifacts.prog(); + + match t.max_constraint_count { + Some(count) => assert!( + bin.constraint_count() <= count, + "Expected at the most {} constraints, found {}:\n{}", + count, + bin.constraint_count(), + bin ), - Some(resolve), - ) - .unwrap(); + _ => {} + }; for test in t.tests.into_iter() { let input = &test.input.values; - let output = bin.execute( - &input - .iter() - .map(|v| T::try_from_dec_str(&v.clone()).unwrap()) - .collect(), - ); + + let output = bin.execute(&(input.iter().cloned().map(parse_val).collect())); match compare(output, test.output) { Err(e) => {