From 8f5e4d9985f883ab152519406d31a7db786dcf62 Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 4 Jul 2022 19:50:12 +0200 Subject: [PATCH] fix conflicts --- .circleci/config.yml | 1 + .gitignore | 7 + CHANGELOG.md | 12 + Cargo.lock | 540 ++++++++++++------ Cargo.toml | 1 + Dockerfile.env | 2 +- changelogs/unreleased/1138-dark64 | 1 - changelogs/unreleased/1139-dark64 | 1 - changelogs/unreleased/1141-schaeff | 1 - changelogs/unreleased/1143-schaeff | 1 + changelogs/unreleased/1146-dark64 | 1 - changelogs/unreleased/1152-schaeff | 1 - changelogs/unreleased/1169-dark64 | 1 + scripts/install_solcjs_deb.sh | 2 +- zokrates_ark/src/lib.rs | 40 +- zokrates_ast/src/common/embed.rs | 52 +- zokrates_ast/src/common/variable.rs | 2 +- zokrates_ast/src/flat/mod.rs | 6 + zokrates_ast/src/flat/utils.rs | 53 ++ zokrates_ast/src/ir/mod.rs | 13 +- zokrates_ast/src/ir/smtlib2.rs | 6 +- zokrates_bellman/src/lib.rs | 2 +- zokrates_circom/Cargo.toml | 17 + zokrates_circom/src/lib.rs | 90 +++ zokrates_circom/src/r1cs.rs | 416 ++++++++++++++ zokrates_circom/src/witness.rs | 219 +++++++ zokrates_cli/Cargo.toml | 3 +- zokrates_cli/src/cli_constants.rs | 2 + zokrates_cli/src/ops/compile.rs | 24 +- zokrates_cli/src/ops/compute_witness.rs | 22 +- zokrates_common/Cargo.toml | 2 +- zokrates_core/Cargo.toml | 2 +- .../reducer/constants_reader.rs | 40 +- .../tests/tests/constants/tuple.json | 16 + .../tests/tests/constants/tuple.zok | 5 + zokrates_embed/src/ark.rs | 18 +- zokrates_embed/src/bellman.rs | 18 +- zokrates_embed/src/lib.rs | 6 +- zokrates_js/Cargo.toml | 3 +- zokrates_js/index.d.ts | 14 +- zokrates_js/package.json | 5 +- zokrates_js/src/lib.rs | 84 ++- zokrates_js/tests/powersOfTau5_0000.ptau | Bin 0 -> 36800 bytes zokrates_js/tests/tests.js | 343 ++++++----- zokrates_js/wrapper.js | 51 +- zokrates_solidity_test/src/evm.rs | 57 +- zokrates_stdlib/Cargo.toml | 2 +- 47 files changed, 1707 insertions(+), 498 deletions(-) delete mode 100644 changelogs/unreleased/1138-dark64 delete mode 100644 changelogs/unreleased/1139-dark64 delete mode 100644 changelogs/unreleased/1141-schaeff create mode 100644 changelogs/unreleased/1143-schaeff delete mode 100644 changelogs/unreleased/1146-dark64 delete mode 100644 changelogs/unreleased/1152-schaeff create mode 100644 changelogs/unreleased/1169-dark64 create mode 100644 zokrates_ast/src/flat/utils.rs create mode 100644 zokrates_circom/Cargo.toml create mode 100644 zokrates_circom/src/lib.rs create mode 100644 zokrates_circom/src/r1cs.rs create mode 100644 zokrates_circom/src/witness.rs create mode 100644 zokrates_core_test/tests/tests/constants/tuple.json create mode 100644 zokrates_core_test/tests/tests/constants/tuple.zok create mode 100644 zokrates_js/tests/powersOfTau5_0000.ptau diff --git a/.circleci/config.yml b/.circleci/config.yml index 4bc00ba7..605f9b42 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -84,6 +84,7 @@ jobs: deploy: docker: - image: cimg/python:3.8-node + resource_class: large steps: - checkout - setup_remote_docker: diff --git a/.gitignore b/.gitignore index 44bec624..a11fa303 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,13 @@ proof.json universal_setup.dat witness +# ZoKrates source files at the root of the repository +/*.zok + +# snarkjs artifacts +*.wtns +*.r1cs + # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock # Cargo.lock diff --git a/CHANGELOG.md b/CHANGELOG.md index 00adc613..900e3e9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file. ## [Unreleased] https://github.com/Zokrates/ZoKrates/compare/latest...develop +## [0.7.14] - 2022-05-31 + +### Release +- https://github.com/Zokrates/ZoKrates/releases/tag/0.7.14 + +### Changes +- Add curve and scheme to the verification key and proof, detect these parameters on `verify`, `print-proof`, and `export-verifier` (#1152, @schaeff) +- Fix `one_liner.sh` script not resolving latest github tag (#1146, @dark64) +- Fix instructions to build from source (#1141, @schaeff) +- Fix keccak padding issue, allow arbitrary input size (#1139, @dark64) +- Fix tuple assignment when rhs is a conditional (#1138, @dark64) + ## [0.7.13] - 2022-04-18 ### Release diff --git a/Cargo.lock b/Cargo.lock index 013b4efa..d670ce95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -168,8 +168,8 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" dependencies = [ - "quote 1.0.18", - "syn 1.0.92", + "quote 1.0.20", + "syn 1.0.98", ] [[package]] @@ -180,8 +180,8 @@ checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" dependencies = [ "num-bigint 0.4.3", "num-traits 0.2.15", - "quote 1.0.18", - "syn 1.0.92", + "quote 1.0.20", + "syn 1.0.98", ] [[package]] @@ -323,9 +323,9 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8dd4e5f0bf8285d5ed538d27fab7411f3e297908fd93c62195de8bee3f199e82" dependencies = [ - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", ] [[package]] @@ -397,14 +397,14 @@ dependencies = [ [[package]] name = "auto_impl" -version = "0.5.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7862e21c893d65a1650125d157eaeec691439379a1cee17ee49031b79236ada4" +checksum = "8a8c1df849285fbacd587de7818cc7d13be6cd2cbcd47a04fb1801b0e2706e33" dependencies = [ - "proc-macro-error", - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro-error 1.0.4", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", ] [[package]] @@ -584,9 +584,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.9.1" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" [[package]] name = "byte-slice-cast" @@ -602,9 +602,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytecount" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e" +checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" [[package]] name = "byteorder" @@ -620,9 +620,9 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] name = "camino" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f3132262930b0522068049f5870a856ab8affc80c70d08b6ecb785771a6fc23" +checksum = "869119e97797867fd90f5e22af7d0bd274bd4635ebb9eb68c04f3f513ae6c412" dependencies = [ "serde", ] @@ -644,7 +644,7 @@ checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ "camino", "cargo-platform", - "semver 1.0.9", + "semver 1.0.12", "serde", "serde_json", ] @@ -676,17 +676,48 @@ dependencies = [ "ansi_term 0.12.1", "atty", "bitflags", - "strsim", + "strsim 0.8.0", "textwrap", "unicode-width", "vec_map", ] [[package]] -name = "cmake" -version = "0.1.45" +name = "clap-v3" +version = "3.0.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb6210b637171dfba4cda12e579ac6dc73f5165ad56133e5d72ef3131f320855" +checksum = "bfac055d61c39ace5061621530f7f55651a261a4fba296ce1bad06d41a8de65e" +dependencies = [ + "ansi_term 0.12.1", + "atty", + "bitflags", + "clap_derive-v3", + "indexmap", + "lazy_static", + "strsim 0.9.3", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "clap_derive-v3" +version = "3.0.0-beta.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6dd675567eb3e35787bd2583d129e85fabc7503b0a093d08c51198a307e2091" +dependencies = [ + "heck", + "proc-macro-error 0.4.12", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", +] + +[[package]] +name = "cmake" +version = "0.1.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" dependencies = [ "cc", ] @@ -807,9 +838,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-common" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +checksum = "5999502d32b9c48d492abe66392408144895020ec4709e549e840799f3bb74c0" dependencies = [ "generic-array 0.14.5", "typenum", @@ -863,8 +894,8 @@ version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" dependencies = [ - "quote 1.0.18", - "syn 1.0.92", + "quote 1.0.20", + "syn 1.0.98", ] [[package]] @@ -873,11 +904,17 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "difference" version = "1.0.0" @@ -940,9 +977,9 @@ dependencies = [ [[package]] name = "either" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" [[package]] name = "env_logger" @@ -953,7 +990,7 @@ dependencies = [ "atty", "humantime", "log", - "regex 1.5.5", + "regex 1.5.6", "termcolor", ] @@ -983,14 +1020,14 @@ dependencies = [ [[package]] name = "ethabi" -version = "17.0.0" +version = "17.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b69517146dfab88e9238c00c724fd8e277951c3cc6f22b016d72f422a832213e" +checksum = "f186de076b3e77b8e6d73c99d1b52edc2a229e604f4b5eb6992c06c11d79d537" dependencies = [ "ethereum-types", "hex 0.4.3", "once_cell", - "regex 1.5.5", + "regex 1.5.6", "serde", "serde_json", "sha3 0.10.1", @@ -1025,6 +1062,12 @@ dependencies = [ "uint", ] +[[package]] +name = "exitcode" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193" + [[package]] name = "failure" version = "0.1.8" @@ -1041,9 +1084,9 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", "synstructure", ] @@ -1083,9 +1126,9 @@ dependencies = [ "num-bigint 0.2.6", "num-integer", "num-traits 0.2.15", - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", ] [[package]] @@ -1227,9 +1270,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -1286,6 +1329,15 @@ dependencies = [ "ahash", ] +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1307,6 +1359,25 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-literal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d70693199b3cf4552f3fa720b54163927a3ebed2aef240efaf556033ab336a11" +dependencies = [ + "hex-literal-impl", + "proc-macro-hack", +] + +[[package]] +name = "hex-literal-impl" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59448fc2f82a5fb6907f78c3d69d843e82ff5b051923313cc4438cb0c7b745a8" +dependencies = [ + "proc-macro-hack", +] + [[package]] name = "humantime" version = "2.1.0" @@ -1346,9 +1417,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", ] [[package]] @@ -1379,6 +1450,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.8" @@ -1387,24 +1467,24 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" [[package]] name = "js-sys" -version = "0.3.57" +version = "0.3.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" dependencies = [ "wasm-bindgen", ] [[package]] name = "keccak" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" [[package]] name = "lazy_static" @@ -1417,9 +1497,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.125" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" [[package]] name = "log" @@ -1459,9 +1539,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" +checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" dependencies = [ "adler", ] @@ -1522,9 +1602,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fbc387afefefd5e9e39493299f3069e14a140dd34dc19b4c1c1a8fddb6a790" +checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" dependencies = [ "num-traits 0.2.15", ] @@ -1552,9 +1632,9 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg", "num-bigint 0.4.3", @@ -1606,9 +1686,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", ] [[package]] @@ -1622,9 +1702,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.10.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" +checksum = "ac8b1a9b2518dc799a2271eff1688707eb315f0d4697aa6b0871369ca4c4da55" [[package]] name = "opaque-debug" @@ -1660,9 +1740,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.1.2" +version = "3.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8b44461635bbb1a0300f100a841e571e7d919c81c73075ef5d152ffdb521066" +checksum = "9182e4a71cae089267ab03e67c99368db7cd877baf50f931e5d6d4b71e195ac0" dependencies = [ "arrayvec 0.7.2", "bitvec", @@ -1674,14 +1754,14 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.1.2" +version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c45ed1f39709f5a89338fab50e59816b2e8815f5bb58276e7ddf9afd495f73f8" +checksum = "9299338969a3d2f491d65f140b00ddec470858402f888af98e8642fb5e8965cd" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", ] [[package]] @@ -1705,7 +1785,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fbf404899169771dd6a32c84248b83cd67a26cc7cc957aac87661490e1227e4" dependencies = [ - "itertools", + "itertools 0.7.11", "proc-macro2 0.4.30", "quote 0.6.13", "single", @@ -1730,9 +1810,9 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", ] [[package]] @@ -1792,6 +1872,18 @@ dependencies = [ "output_vt100", ] +[[package]] +name = "pretty_assertions" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89f989ac94207d048d92db058e4f6ec7342b0971fc58d1271ca148b799b3563" +dependencies = [ + "ansi_term 0.12.1", + "ctor", + "diff", + "output_vt100", +] + [[package]] name = "primitive-types" version = "0.11.1" @@ -1815,16 +1907,42 @@ dependencies = [ "toml", ] +[[package]] +name = "proc-macro-error" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" +dependencies = [ + "proc-macro-error-attr 0.4.12", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", + "version_check", +] + [[package]] name = "proc-macro-error" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ - "proc-macro-error-attr", - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro-error-attr 1.0.4", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" +dependencies = [ + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", + "syn-mid", "version_check", ] @@ -1834,11 +1952,17 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.38", - "quote 1.0.18", + "proc-macro2 1.0.40", + "quote 1.0.20", "version_check", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + [[package]] name = "proc-macro2" version = "0.4.30" @@ -1850,11 +1974,11 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" +checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" dependencies = [ - "unicode-xid 0.2.3", + "unicode-ident", ] [[package]] @@ -1879,11 +2003,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" dependencies = [ - "proc-macro2 1.0.38", + "proc-macro2 1.0.40", ] [[package]] @@ -2000,13 +2124,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.5" +version = "1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" dependencies = [ "aho-corasick 0.7.18", "memchr", - "regex-syntax 0.6.25", + "regex-syntax 0.6.26", ] [[package]] @@ -2026,9 +2150,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" [[package]] name = "remove_dir_all" @@ -2041,8 +2165,8 @@ dependencies = [ [[package]] name = "revm" -version = "1.3.1" -source = "git+https://github.com/bluealloy/revm#8c63ba6c7f3667064608c2489c3e4b3e54451110" +version = "1.6.0" +source = "git+https://github.com/bluealloy/revm#6c2a08bf75640cefad1b82b29e541b3c93cbebf1" dependencies = [ "arrayref", "auto_impl", @@ -2058,7 +2182,7 @@ dependencies = [ [[package]] name = "revm_precompiles" version = "1.0.0" -source = "git+https://github.com/bluealloy/revm#8c63ba6c7f3667064608c2489c3e4b3e54451110" +source = "git+https://github.com/bluealloy/revm#6c2a08bf75640cefad1b82b29e541b3c93cbebf1" dependencies = [ "bytes", "num 0.4.0", @@ -2112,9 +2236,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" [[package]] name = "same-file" @@ -2156,18 +2280,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "secp256k1" -version = "0.22.1" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26947345339603ae8395f68e2f3d85a6b0a8ddfe6315818e80b8504415099db0" +checksum = "77cb4e47e3ccff9a1e168471c11e026c067f50ea7c11bf5e877cae505fb743a0" dependencies = [ "secp256k1-sys", ] [[package]] name = "secp256k1-sys" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa6f71720acd498e888501dd485d54bb437735f02dd95eb717dac5aee6631894" +checksum = "7058dc8eaf3f2810d7828680320acda0b25a288f6d288e19278e249bbf74226b" dependencies = [ "cc", ] @@ -2183,9 +2307,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" +checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1" dependencies = [ "serde", ] @@ -2201,9 +2325,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.137" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +checksum = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47" dependencies = [ "serde_derive", ] @@ -2220,23 +2344,23 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c" dependencies = [ - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", ] [[package]] name = "serde_json" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" dependencies = [ "indexmap", - "itoa 1.0.1", + "itoa 1.0.2", "ryu", "serde", ] @@ -2355,6 +2479,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + [[package]] name = "substrate-bn" version = "0.6.0" @@ -2393,13 +2523,24 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.92" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" +checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" dependencies = [ - "proc-macro2 1.0.38", - "quote 1.0.18", - "unicode-xid 0.2.3", + "proc-macro2 1.0.40", + "quote 1.0.20", + "unicode-ident", +] + +[[package]] +name = "syn-mid" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baa8e7560a164edb1621a55d18a0c59abf49d360f47aa7b821061dd7eea7fac9" +dependencies = [ + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", ] [[package]] @@ -2408,9 +2549,9 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", "unicode-xid 0.2.3", ] @@ -2477,9 +2618,9 @@ version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", ] [[package]] @@ -2511,9 +2652,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" +checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", @@ -2523,20 +2664,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" +checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" dependencies = [ - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", ] [[package]] name = "tracing-core" -version = "0.1.26" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" +checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" [[package]] name = "typed-arena" @@ -2583,6 +2724,18 @@ dependencies = [ "version_check", ] +[[package]] +name = "unicode-ident" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" + +[[package]] +name = "unicode-segmentation" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" + [[package]] name = "unicode-width" version = "0.1.9" @@ -2638,15 +2791,15 @@ dependencies = [ [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" dependencies = [ "cfg-if 1.0.0", "serde", @@ -2656,24 +2809,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.30" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" +checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -2683,38 +2836,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" dependencies = [ - "quote 1.0.18", + "quote 1.0.20", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" dependencies = [ - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" +checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" [[package]] name = "wasm-bindgen-test" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4464b3f74729a25f42b1a0cd9e6a515d2f25001f3535a6cfaf35d34a4de3bab" +checksum = "68b30cf2cba841a812f035c40c50f53eb9c56181192a9dd2c71b65e6a87a05ba" dependencies = [ "console_error_panic_hook", "js-sys", @@ -2726,19 +2879,19 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77c5a6f82cc6093a321ca5fb3dc9327fe51675d477b3799b4a9375bac3b7b4c" +checksum = "88ad594bf33e73cafcac2ae9062fc119d4f75f9c77e25022f91c9a64bd5b6463" dependencies = [ - "proc-macro2 1.0.38", - "quote 1.0.18", + "proc-macro2 1.0.40", + "quote 1.0.20", ] [[package]] name = "web-sys" -version = "0.3.57" +version = "0.3.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" dependencies = [ "js-sys", "wasm-bindgen", @@ -2786,9 +2939,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.5.5" +version = "1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" +checksum = "20b578acffd8516a6c3f2a1bdefc1ec37e547bb4e0fb8b6b01a4cafc886b4442" dependencies = [ "zeroize_derive", ] @@ -2799,12 +2952,32 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ - "proc-macro2 1.0.38", - "quote 1.0.18", - "syn 1.0.92", + "proc-macro2 1.0.40", + "quote 1.0.20", + "syn 1.0.98", "synstructure", ] +[[package]] +name = "zkutil" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51266e3b8d99e954d29b93a28464ee6ca239302bf38b2308137ff23d9fcce50c" +dependencies = [ + "bellman_ce", + "byteorder", + "cfg-if 0.1.10", + "clap-v3", + "exitcode", + "hex-literal", + "itertools 0.8.2", + "num-bigint 0.2.6", + "num-traits 0.2.15", + "rand 0.4.6", + "serde", + "serde_json", +] + [[package]] name = "zokrates_abi" version = "0.1.7" @@ -2876,9 +3049,22 @@ dependencies = [ "zokrates_proof_systems", ] +[[package]] +name = "zokrates_circom" +version = "0.1.0" +dependencies = [ + "bellman_ce", + "byteorder", + "pretty_assertions 1.2.1", + "zkutil", + "zokrates_ast", + "zokrates_core", + "zokrates_field", +] + [[package]] name = "zokrates_cli" -version = "0.7.13" +version = "0.7.14" dependencies = [ "assert_cli", "blake2 0.8.1", @@ -2907,6 +3093,7 @@ dependencies = [ "zokrates_ark", "zokrates_ast", "zokrates_bellman", + "zokrates_circom", "zokrates_common", "zokrates_core", "zokrates_field", @@ -2918,11 +3105,11 @@ dependencies = [ [[package]] name = "zokrates_common" -version = "0.1.0" +version = "0.1.1" [[package]] name = "zokrates_core" -version = "0.6.12" +version = "0.6.13" dependencies = [ "cfg-if 0.1.10", "csv", @@ -2930,7 +3117,7 @@ dependencies = [ "log", "num 0.1.42", "num-bigint 0.2.6", - "pretty_assertions", + "pretty_assertions 0.6.1", "reduce", "serde", "serde_json", @@ -3018,7 +3205,7 @@ dependencies = [ [[package]] name = "zokrates_js" -version = "1.0.43" +version = "1.0.44" dependencies = [ "console_error_panic_hook", "indexmap", @@ -3030,6 +3217,7 @@ dependencies = [ "zokrates_abi", "zokrates_ark", "zokrates_ast", + "zokrates_circom", "zokrates_common", "zokrates_core", "zokrates_field", @@ -3090,7 +3278,7 @@ dependencies = [ [[package]] name = "zokrates_stdlib" -version = "0.2.8" +version = "0.2.9" dependencies = [ "fs_extra", "zokrates_test", diff --git a/Cargo.toml b/Cargo.toml index b09fa804..92c7358e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ members = [ "zokrates_bellman", "zokrates_proof_systems", "zokrates_js", + "zokrates_circom" ] exclude = [] \ No newline at end of file diff --git a/Dockerfile.env b/Dockerfile.env index 1be291a8..862bd3b6 100644 --- a/Dockerfile.env +++ b/Dockerfile.env @@ -26,7 +26,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain none -y \ && rustup toolchain install $RUST_VERSION --allow-downgrade --profile minimal --component rustfmt clippy \ - && curl -sL https://deb.nodesource.com/setup_14.x | bash - && apt-get install -y nodejs && npm i -g solc \ + && curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs && npm i -g solc \ && curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh \ && curl -sL https://raw.githubusercontent.com/Sarcasm/run-clang-format/master/run-clang-format.py > /opt/run-clang-format.py \ && chmod +x /opt/run-clang-format.py \ diff --git a/changelogs/unreleased/1138-dark64 b/changelogs/unreleased/1138-dark64 deleted file mode 100644 index 932e3ead..00000000 --- a/changelogs/unreleased/1138-dark64 +++ /dev/null @@ -1 +0,0 @@ -Fix tuple assignment when rhs is a conditional \ No newline at end of file diff --git a/changelogs/unreleased/1139-dark64 b/changelogs/unreleased/1139-dark64 deleted file mode 100644 index 1cee95fc..00000000 --- a/changelogs/unreleased/1139-dark64 +++ /dev/null @@ -1 +0,0 @@ -Fix keccak padding issue, allow arbitrary input size \ No newline at end of file diff --git a/changelogs/unreleased/1141-schaeff b/changelogs/unreleased/1141-schaeff deleted file mode 100644 index 12032d66..00000000 --- a/changelogs/unreleased/1141-schaeff +++ /dev/null @@ -1 +0,0 @@ -Fix instructions to build from source \ No newline at end of file diff --git a/changelogs/unreleased/1143-schaeff b/changelogs/unreleased/1143-schaeff new file mode 100644 index 00000000..fd323cc7 --- /dev/null +++ b/changelogs/unreleased/1143-schaeff @@ -0,0 +1 @@ +Optionally export snarkjs artifacts \ No newline at end of file diff --git a/changelogs/unreleased/1146-dark64 b/changelogs/unreleased/1146-dark64 deleted file mode 100644 index 366be7f0..00000000 --- a/changelogs/unreleased/1146-dark64 +++ /dev/null @@ -1 +0,0 @@ -Fix `one_liner.sh` script not resolving latest github tag \ No newline at end of file diff --git a/changelogs/unreleased/1152-schaeff b/changelogs/unreleased/1152-schaeff deleted file mode 100644 index c23d1fee..00000000 --- a/changelogs/unreleased/1152-schaeff +++ /dev/null @@ -1 +0,0 @@ -Add curve and scheme to the verification key and proof, detect these parameters on `verify`, `print-proof`, and `export-verifier` \ No newline at end of file diff --git a/changelogs/unreleased/1169-dark64 b/changelogs/unreleased/1169-dark64 new file mode 100644 index 00000000..07203fbe --- /dev/null +++ b/changelogs/unreleased/1169-dark64 @@ -0,0 +1 @@ +Fix constant inlining for tuples \ No newline at end of file diff --git a/scripts/install_solcjs_deb.sh b/scripts/install_solcjs_deb.sh index 41b0c8e0..edca332a 100755 --- a/scripts/install_solcjs_deb.sh +++ b/scripts/install_solcjs_deb.sh @@ -2,6 +2,6 @@ apt-get update -y apt-get install -y curl gnupg sudo build-essential git -curl -sL https://deb.nodesource.com/setup_12.x | bash - +curl -sL https://deb.nodesource.com/setup_16.x | bash - apt-get install -y nodejs npm i -g solc \ No newline at end of file diff --git a/zokrates_ark/src/lib.rs b/zokrates_ark/src/lib.rs index 6df8e5c6..42ba76f2 100644 --- a/zokrates_ark/src/lib.rs +++ b/zokrates_ark/src/lib.rs @@ -72,15 +72,15 @@ fn ark_combination( .fold(LinearCombination::zero(), |acc, e| acc + e) } -impl>> Computation { - pub fn public_inputs_values(&self) -> Vec<::Fr> { - self.program - .public_inputs(self.witness.as_ref().unwrap()) - .iter() - .map(|v| v.clone().into_ark()) - .collect() - } -} +// impl>> Computation { +// pub fn public_inputs_values(&self) -> Vec<::Fr> { +// self.program +// .public_inputs(self.witness.as_ref().unwrap()) +// .iter() +// .map(|v| v.clone().into_ark()) +// .collect() +// } +// } impl>> ConstraintSynthesizer<<::ArkEngine as PairingEngine>::Fr> @@ -153,6 +153,28 @@ impl>> } } +impl>> Computation { + pub fn public_inputs_values(&self) -> Vec<::Fr> { + self.program + .public_inputs_values(self.witness.as_ref().unwrap()) + .iter() + .map(|v| v.clone().into_ark()) + .collect() + } +} + +// impl>> +// ConstraintSynthesizer<<::ArkEngine as PairingEngine>::Fr> +// for Computation +// { +// fn generate_constraints( +// self, +// cs: ConstraintSystemRef<<::ArkEngine as PairingEngine>::Fr>, +// ) -> Result<(), SynthesisError> { +// self.program.generate_constraints(cs, self.witness) +// } +// } + mod parse { use super::*; use ark_ff::ToBytes; diff --git a/zokrates_ast/src/common/embed.rs b/zokrates_ast/src/common/embed.rs index 635e6092..4133c5c8 100644 --- a/zokrates_ast/src/common/embed.rs +++ b/zokrates_ast/src/common/embed.rs @@ -1,4 +1,5 @@ use crate::common::{Parameter, RuntimeError, Solver, Variable}; +use crate::flat::{flat_expression_from_bits, flat_expression_from_variable_summands}; use crate::flat::{FlatDirective, FlatExpression, FlatFunctionIterator, FlatStatement}; use crate::typed::types::{ ConcreteGenericsAssignment, DeclarationConstant, DeclarationSignature, DeclarationType, @@ -308,29 +309,6 @@ 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 -#[cfg(any(feature = "ark", feature = "bellman"))] -fn flat_expression_from_vec(v: &[(usize, T)]) -> FlatExpression { - match v.len() { - 0 => FlatExpression::Number(T::zero()), - 1 => { - let (key, val) = v[0].clone(); - FlatExpression::Mult( - box FlatExpression::Number(val), - box FlatExpression::Identifier(Variable::new(key)), - ) - } - n => { - let (u, v) = v.split_at(n / 2); - FlatExpression::Add( - box flat_expression_from_vec::(u), - box flat_expression_from_vec::(v), - ) - } - } -} - /// Returns a flat function which computes a sha256 round /// /// # Remarks @@ -400,9 +378,9 @@ pub fn sha256_round( // insert flattened statements to represent constraints let constraint_statements = r1cs.constraints.into_iter().map(|c| { let c = from_bellman::(c); - let rhs_a = flat_expression_from_vec::(c.a.as_slice()); - let rhs_b = flat_expression_from_vec::(c.b.as_slice()); - let lhs = flat_expression_from_vec::(c.c.as_slice()); + let rhs_a = flat_expression_from_variable_summands::(c.a.as_slice()); + let rhs_b = flat_expression_from_variable_summands::(c.b.as_slice()); + let lhs = flat_expression_from_variable_summands::(c.c.as_slice()); FlatStatement::Condition( lhs, @@ -508,9 +486,9 @@ pub fn snark_verify_bls12_377( .into_iter() .map(|c| { let c = from_ark::(c); - let rhs_a = flat_expression_from_vec::(c.a.as_slice()); - let rhs_b = flat_expression_from_vec::(c.b.as_slice()); - let lhs = flat_expression_from_vec::(c.c.as_slice()); + let rhs_a = flat_expression_from_variable_summands::(c.a.as_slice()); + let rhs_b = flat_expression_from_variable_summands::(c.b.as_slice()); + let lhs = flat_expression_from_variable_summands::(c.c.as_slice()); FlatStatement::Condition( lhs, @@ -614,17 +592,11 @@ pub fn unpack_to_bitwidth( .collect(); // 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..bit_width { - lhs_sum = FlatExpression::Add( - box lhs_sum, - box FlatExpression::Mult( - box FlatExpression::Identifier(Variable::new(bit_width - i)), - box FlatExpression::Number(T::from(2).pow(i)), - ), - ); - } + let lhs_sum = flat_expression_from_bits( + (0..bit_width) + .map(|i| FlatExpression::Identifier(Variable::new(i + 1))) + .collect(), + ); statements.push(FlatStatement::Condition( lhs_sum, diff --git a/zokrates_ast/src/common/variable.rs b/zokrates_ast/src/common/variable.rs index 7a6b9b01..983e9e17 100644 --- a/zokrates_ast/src/common/variable.rs +++ b/zokrates_ast/src/common/variable.rs @@ -8,7 +8,7 @@ use std::fmt; // id < 0 for public outputs #[derive(Serialize, Deserialize, Clone, PartialEq, Hash, Eq, Ord, PartialOrd, Copy)] pub struct Variable { - id: isize, + pub id: isize, } impl Variable { diff --git a/zokrates_ast/src/flat/mod.rs b/zokrates_ast/src/flat/mod.rs index 27ac6e7f..a3b7f84e 100644 --- a/zokrates_ast/src/flat/mod.rs +++ b/zokrates_ast/src/flat/mod.rs @@ -6,11 +6,17 @@ //! @date 2017 pub mod folder; +pub mod utils; pub use crate::common::Parameter; pub use crate::common::RuntimeError; pub use crate::common::Variable; +pub use utils::{ + flat_expression_from_bits, flat_expression_from_expression_summands, + flat_expression_from_variable_summands, +}; + use crate::common::Solver; use std::collections::HashMap; use std::fmt; diff --git a/zokrates_ast/src/flat/utils.rs b/zokrates_ast/src/flat/utils.rs new file mode 100644 index 00000000..03239687 --- /dev/null +++ b/zokrates_ast/src/flat/utils.rs @@ -0,0 +1,53 @@ +use crate::flat::{FlatExpression, Variable}; +use zokrates_field::Field; + +// util to convert a vector of `(coefficient, expression)` to a flat_expression +// we build a binary tree of additions by splitting the vector recursively +pub fn flat_expression_from_expression_summands>>( + v: &[(T, U)], +) -> FlatExpression { + match v.len() { + 0 => FlatExpression::Number(T::zero()), + 1 => { + let (val, var) = v[0].clone(); + FlatExpression::Mult(box FlatExpression::Number(val), box var.into()) + } + n => { + let (u, v) = v.split_at(n / 2); + FlatExpression::Add( + box flat_expression_from_expression_summands(u), + box flat_expression_from_expression_summands(v), + ) + } + } +} + +pub fn flat_expression_from_bits(v: Vec>) -> FlatExpression { + flat_expression_from_expression_summands( + &v.into_iter() + .rev() + .enumerate() + .map(|(index, var)| (T::from(2).pow(index), var)) + .collect::>(), + ) +} + +pub fn flat_expression_from_variable_summands(v: &[(T, usize)]) -> FlatExpression { + match v.len() { + 0 => FlatExpression::Number(T::zero()), + 1 => { + let (val, var) = v[0].clone(); + FlatExpression::Mult( + box FlatExpression::Number(val), + box FlatExpression::Identifier(Variable::new(var)), + ) + } + n => { + let (u, v) = v.split_at(n / 2); + FlatExpression::Add( + box flat_expression_from_variable_summands(u), + box flat_expression_from_variable_summands(v), + ) + } + } +} diff --git a/zokrates_ast/src/ir/mod.rs b/zokrates_ast/src/ir/mod.rs index 13811b11..0c8b74b3 100644 --- a/zokrates_ast/src/ir/mod.rs +++ b/zokrates_ast/src/ir/mod.rs @@ -1,5 +1,6 @@ //use crate::solvers::Solver; use serde::{Deserialize, Serialize}; +use std::collections::BTreeSet; use std::fmt; use std::hash::Hash; use zokrates_field::Field; @@ -29,6 +30,8 @@ pub enum Statement { Directive(Directive), } +pub type PublicInputs = BTreeSet; + impl Statement { pub fn definition>>(v: Variable, e: U) -> Self { Statement::Constraint(e.into(), v.into(), None) @@ -108,10 +111,18 @@ impl>> ProgIterator { pub fn public_count(&self) -> usize { self.arguments.iter().filter(|a| !a.private).count() + self.return_count } + + pub fn public_inputs(&self) -> PublicInputs { + self.arguments + .iter() + .filter(|a| !a.private) + .map(|a| a.id) + .collect() + } } impl>> ProgIterator { - pub fn public_inputs(&self, witness: &Witness) -> Vec { + pub fn public_inputs_values(&self, witness: &Witness) -> Vec { self.arguments .iter() .filter(|p| !p.private) diff --git a/zokrates_ast/src/ir/smtlib2.rs b/zokrates_ast/src/ir/smtlib2.rs index 66e78ccf..c93259a1 100644 --- a/zokrates_ast/src/ir/smtlib2.rs +++ b/zokrates_ast/src/ir/smtlib2.rs @@ -20,11 +20,11 @@ impl fmt::Display for SMTLib2Display<'_, T> { } } -struct FlatVariableCollector { +struct VariableCollector { variables: BTreeSet, } -impl Visitor for FlatVariableCollector { +impl Visitor for VariableCollector { fn visit_variable(&mut self, v: &Variable) { self.variables.insert(*v); } @@ -32,7 +32,7 @@ impl Visitor for FlatVariableCollector { impl SMTLib2 for Prog { fn to_smtlib2(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut collector = FlatVariableCollector { + let mut collector = VariableCollector { variables: BTreeSet::::new(), }; collector.visit_module(self); diff --git a/zokrates_bellman/src/lib.rs b/zokrates_bellman/src/lib.rs index f6413f18..4bf39624 100644 --- a/zokrates_bellman/src/lib.rs +++ b/zokrates_bellman/src/lib.rs @@ -180,7 +180,7 @@ impl>> Co pub fn public_inputs_values(&self) -> Vec<::Fr> { self.program - .public_inputs(self.witness.as_ref().unwrap()) + .public_inputs_values(self.witness.as_ref().unwrap()) .iter() .map(|v| v.clone().into_bellman()) .collect() diff --git a/zokrates_circom/Cargo.toml b/zokrates_circom/Cargo.toml new file mode 100644 index 00000000..6e1ea256 --- /dev/null +++ b/zokrates_circom/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "zokrates_circom" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +zokrates_core = { version = "0.6", path = "../zokrates_core", default-features = false } +zokrates_ast = { version = "0.1", path = "../zokrates_ast", default-features = false } +zokrates_field = { version = "0.5.0", path = "../zokrates_field", default-features = false } +byteorder = "1.4.3" + +[dev-dependencies] +pretty_assertions = "1.2.1" +zkutil = "0.5.0" +bellman_ce = { version = "^0.3" } \ No newline at end of file diff --git a/zokrates_circom/src/lib.rs b/zokrates_circom/src/lib.rs new file mode 100644 index 00000000..1fd513b8 --- /dev/null +++ b/zokrates_circom/src/lib.rs @@ -0,0 +1,90 @@ +mod r1cs; +mod witness; + +pub use r1cs::write_r1cs; +pub use witness::write_witness; + +#[cfg(test)] +mod tests { + use std::io::Cursor; + + use bellman_ce::pairing::bn256::Bn256; + use zkutil::circom_circuit::{ + create_rng, generate_random_parameters, prove, r1cs_from_bin, witness_from_bin, + CircomCircuit, + }; + use zokrates_ast::{ + flat::{Parameter, Variable}, + ir::{LinComb, Prog, PublicInputs, QuadComb, Statement, Witness}, + }; + use zokrates_field::Bn128Field; + + use super::*; + + #[test] + fn setup_and_prove() { + let prog: Prog = Prog { + arguments: vec![ + Parameter::private(Variable::new(0)), + Parameter::public(Variable::new(1)), + ], + return_count: 1, + statements: vec![ + Statement::Constraint( + QuadComb::from_linear_combinations( + LinComb::from(Variable::new(0)), + LinComb::from(Variable::new(0)), + ), + LinComb::from(Variable::new(0)), + None, + ), + Statement::Constraint( + (LinComb::from(Variable::new(0)) + LinComb::from(Variable::new(1))).into(), + Variable::public(0).into(), + None, + ), + ], + }; + + let mut r1cs = vec![]; + + write_r1cs(&mut r1cs, prog).unwrap(); + + let public_inputs: PublicInputs = vec![Variable::new(1)].into_iter().collect(); + + let witness: Witness = Witness( + vec![ + (Variable::new(0), Bn128Field::from(1u32)), + (Variable::new(1), Bn128Field::from(1u32)), + (Variable::one(), Bn128Field::from(1u32)), + (Variable::public(0), Bn128Field::from(2u32)), + ] + .into_iter() + .collect(), + ); + + let mut wtns = vec![]; + + write_witness(&mut wtns, witness, public_inputs).unwrap(); + + let (r1cs, mapping) = r1cs_from_bin(Cursor::new(r1cs)).unwrap(); + let wtns = witness_from_bin::(Cursor::new(wtns)).unwrap(); + + let rng = create_rng(); + let circuit = CircomCircuit { + r1cs: r1cs.clone(), + witness: None, + wire_mapping: None, + }; + + let params = generate_random_parameters(circuit, rng).unwrap(); + + let circuit = CircomCircuit { + r1cs, + witness: Some(wtns), + wire_mapping: Some(mapping), + }; + let rng = create_rng(); + assert!(prove(circuit.clone(), ¶ms, rng).is_ok()); + } +} diff --git a/zokrates_circom/src/r1cs.rs b/zokrates_circom/src/r1cs.rs new file mode 100644 index 00000000..fadcb05b --- /dev/null +++ b/zokrates_circom/src/r1cs.rs @@ -0,0 +1,416 @@ +use byteorder::{LittleEndian, WriteBytesExt}; +use std::collections::HashMap; +use std::io::Result; +use std::{io::Write, ops::Add}; +use zokrates_ast::flat::Variable; +use zokrates_ast::ir::{Prog, Statement}; +use zokrates_field::Field; +struct Header { + pub field_size: u32, + pub prime_size: Vec, + pub n_wires: u32, + pub n_pub_out: u32, + pub n_pub_in: u32, + pub n_prv_in: u32, + pub n_labels: u64, + pub n_constraints: u32, +} + +type LinComb = Vec<(usize, T)>; +type Constraint = (LinComb, LinComb, LinComb); + +fn write_header(writer: &mut W, header: Header) -> Result<()> { + writer.write_u32::(header.field_size)?; + writer.write_all(&header.prime_size)?; + writer.write_u32::(header.n_wires)?; + writer.write_u32::(header.n_pub_out)?; + writer.write_u32::(header.n_pub_in)?; + writer.write_u32::(header.n_prv_in)?; + writer.write_u64::(header.n_labels)?; + writer.write_u32::(header.n_constraints)?; + + Ok(()) +} + +/// Returns the index of `var` in `variables`, adding `var` with incremented index if it does not yet exists. +/// +/// # Arguments +/// +/// * `variables` - A mutual map that maps all existing variables to their index. +/// * `var` - Variable to be searched for. +pub fn provide_variable_idx(variables: &mut HashMap, var: &Variable) -> usize { + let index = variables.len(); + *variables.entry(*var).or_insert(index) +} + +/// Calculates one R1CS row representation of a program and returns (V, A, B, C) so that: +/// * `V` contains all used variables and the index in the vector represents the used number in `A`, `B`, `C` +/// * `* = ` for a witness `x` +/// +/// # Arguments +/// +/// * `prog` - The program the representation is calculated for. +pub fn r1cs_program(prog: Prog) -> (Vec, usize, Vec>) { + let mut variables: HashMap = HashMap::new(); + provide_variable_idx(&mut variables, &Variable::one()); + + for i in 0..prog.return_count { + provide_variable_idx(&mut variables, &Variable::public(i)); + } + + for x in prog.arguments.iter().filter(|p| !p.private) { + provide_variable_idx(&mut variables, &x.id); + } + + // position where private part of witness starts + let private_inputs_offset = variables.len(); + + // first pass through statements to populate `variables` + for (quad, lin) in prog.statements.iter().filter_map(|s| match s { + Statement::Constraint(quad, lin, _) => Some((quad, lin)), + Statement::Directive(..) => None, + }) { + for (k, _) in &quad.left.0 { + provide_variable_idx(&mut variables, k); + } + for (k, _) in &quad.right.0 { + provide_variable_idx(&mut variables, k); + } + for (k, _) in &lin.0 { + provide_variable_idx(&mut variables, k); + } + } + + let mut constraints = vec![]; + + // second pass to convert program to raw sparse vectors + for (quad, lin) in prog.statements.into_iter().filter_map(|s| match s { + Statement::Constraint(quad, lin, _) => Some((quad, lin)), + Statement::Directive(..) => None, + }) { + constraints.push(( + quad.left + .0 + .into_iter() + .map(|(k, v)| (*variables.get(&k).unwrap(), v)) + .collect(), + quad.right + .0 + .into_iter() + .map(|(k, v)| (*variables.get(&k).unwrap(), v)) + .collect(), + lin.0 + .into_iter() + .map(|(k, v)| (*variables.get(&k).unwrap(), v)) + .collect(), + )); + } + + // Convert map back into list ordered by index + let mut variables_list = vec![Variable::new(0); variables.len()]; + for (k, v) in variables.drain() { + assert_eq!(variables_list[v], Variable::new(0)); + variables_list[v] = k; + } + (variables_list, private_inputs_offset, constraints) +} + +pub fn write_r1cs(writer: &mut W, p: Prog) -> Result<()> { + let modulo_byte_count = T::max_value().to_biguint().add(1u32).to_bytes_le().len() as u32; + + let n_pub_out = p.return_count as u32; + let n_pub_in = p.arguments.iter().filter(|a| !a.private).count() as u32; + let n_prv_in = p.arguments.iter().filter(|a| a.private).count() as u32; + + let (vars, _, constraints) = r1cs_program(p); + + let n_wires = vars.len(); + + let header = Header { + field_size: modulo_byte_count, + prime_size: T::max_value().to_biguint().add(1u32).to_bytes_le(), + n_wires: n_wires as u32, + n_pub_out, + n_pub_in, + n_prv_in, + n_labels: n_wires as u64, + n_constraints: constraints.len() as u32, + }; + + // magic + writer.write_all(&[0x72, 0x31, 0x63, 0x73])?; + // version + writer.write_u32::(1)?; + // section count + writer.write_u32::(3)?; + + // section type: constraints + // type + writer.write_u32::(2)?; + // size: 4 per lc + (32 + 4) per summand + let size = constraints + .iter() + .map(|(a, b, c)| { + (3 * 4 // for each lc, 4 bytes for its size + + (a.len() + b.len() + c.len()) // for each summand + * (modulo_byte_count as usize + 4)) // 4 bytes for the signal, `modulo_byte_count` bytes for the coefficient + as u64 + }) + .sum(); + writer.write_u64::(size)?; + + write_constraints(writer, constraints)?; + + // section type: header + // type + writer.write_u32::(1)?; + // size + writer.write_u64::(32 + 32)?; + + // header + write_header(writer, header)?; + + // section type: wire2label + // type + writer.write_u32::(3)?; + // size + writer.write_u64::(n_wires as u64 * 8)?; + + write_table(writer, &vars)?; + + Ok(()) +} + +fn write_constraints( + writer: &mut W, + constraints: Vec>, +) -> Result<()> { + for c in constraints { + write_lincomb(writer, c.0)?; + write_lincomb(writer, c.1)?; + write_lincomb(writer, c.2)?; + } + Ok(()) +} + +fn write_lincomb(writer: &mut W, l: LinComb) -> Result<()> { + writer.write_u32::(l.len() as u32)?; + for (var, coeff) in l { + writer.write_u32::(var as u32)?; + let mut res = vec![0u8; 32]; + for (value, padded) in coeff.to_biguint().to_bytes_le().iter().zip(res.iter_mut()) { + *padded = *value; + } + writer.write_all(&res)?; + } + Ok(()) +} + +// for now we do not write any signal map +fn write_table(w: &mut W, variables: &[Variable]) -> Result<()> { + for (i, _) in variables.iter().enumerate() { + w.write_u64::(i as u64)?; + } + Ok(()) +} + +#[cfg(test)] +mod tests { + use std::io::Cursor; + + use super::*; + use pretty_assertions::assert_eq; + use zkutil::r1cs_reader; + use zokrates_ast::{ + flat::{Parameter, Variable}, + ir::{LinComb, QuadComb, Statement}, + }; + use zokrates_field::Bn128Field; + + #[test] + fn empty() { + let prog: Prog = Prog::default(); + let mut buf = Vec::new(); + + #[rustfmt::skip] + let expected: Vec = vec![ + // magic + 0x72, 0x31, 0x63, 0x73, + // version + 0x01, 0x00, 0x00, 0x00, + // section count + 0x03, 0x00, 0x00, 0x00, + // constraints section (empty) + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // header + 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // modulus size in bytes + 0x20, 0x00, 0x00, 0x00, + // modulus + 0x01, 0x00, 0x00, 0xf0, 0x93, 0xf5, 0xe1, 0x43, 0x91, 0x70, 0xb9, 0x79, 0x48, 0xe8, 0x33, 0x28, 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, + // n wires + 0x01, 0x00, 0x00, 0x00, + // n pub outputs + 0x00, 0x00, 0x00, 0x00, + // n pub inputs + 0x00, 0x00, 0x00, 0x00, + // n priv + 0x00, 0x00, 0x00, 0x00, + // n labels + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // n constraints + 0x00, 0x00, 0x00, 0x00, + // wire map (variable one?) + 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + + write_r1cs(&mut buf, prog).unwrap(); + + assert_eq!(buf, expected); + + let c = Cursor::new(buf); + + assert!(r1cs_reader::read(c).is_ok()); + } + + #[test] + fn return_one() { + let prog: Prog = Prog { + arguments: vec![], + return_count: 1, + statements: vec![Statement::Constraint( + LinComb::one().into(), + Variable::public(0).into(), + None, + )], + }; + + let mut buf = Vec::new(); + + #[rustfmt::skip] + let expected: Vec = vec![ + 0x72, 0x31, 0x63, 0x73, + 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // size = 1 constraint = sum(4 /* write term_count_i */ + term_count_i * (4 + 32)) = 120 + 0x01, 0x00, 0x00, 0x00, // 1 element in this lc + 0x00, 0x00, 0x00, 0x00, // variable 0 + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // coeff 1 + 0x01, 0x00, 0x00, 0x00, // 1 element in this lc + 0x00, 0x00, 0x00, 0x00, // variable 0 + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // coeff 1 + 0x01, 0x00, 0x00, 0x00, // 1 element in this lc + 0x01, 0x00, 0x00, 0x00, // variable 1 + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // coeff 1 + // header + 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // modulo size + 0x20, 0x00, 0x00, 0x00, + // modulo + 0x01, 0x00, 0x00, 0xf0, 0x93, 0xf5, 0xe1, 0x43, 0x91, 0x70, 0xb9, 0x79, 0x48, 0xe8, 0x33, 0x28, 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, + 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, + // wire map (one, pub0) + 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + + write_r1cs(&mut buf, prog).unwrap(); + + assert_eq!(buf, expected); + + let c = Cursor::new(buf); + + assert!(r1cs_reader::read(c).is_ok()); + } + + #[test] + fn with_inputs() { + let prog: Prog = Prog { + arguments: vec![ + Parameter::private(Variable::new(0)), + Parameter::public(Variable::new(1)), + ], + return_count: 1, + statements: vec![ + Statement::Constraint( + QuadComb::from_linear_combinations( + LinComb::from(Variable::new(0)), + LinComb::from(Variable::new(0)), + ), + LinComb::from(Variable::new(0)), + None, + ), + Statement::Constraint( + (LinComb::from(Variable::new(0)) + LinComb::from(Variable::new(1))).into(), + Variable::public(0).into(), + None, + ), + ], + }; + + let mut buf = Vec::new(); + + #[rustfmt::skip] + let expected: Vec = vec![ + 0x72, 0x31, 0x63, 0x73, + 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // first constraint + 0x01, 0x00, 0x00, 0x00, // 1 element in this lc + 0x03, 0x00, 0x00, 0x00, // variable 3 + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // coeff 1 + 0x01, 0x00, 0x00, 0x00, // 1 element in this lc + 0x03, 0x00, 0x00, 0x00, // variable 3 + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // coeff 1 + 0x01, 0x00, 0x00, 0x00, // 1 element in this lc + 0x03, 0x00, 0x00, 0x00, // variable 3 + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // coeff 1 + // second constraint + 0x01, 0x00, 0x00, 0x00, // 1 element in this lc + 0x00, 0x00, 0x00, 0x00, // variable 0 + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // coeff 1 + 0x02, 0x00, 0x00, 0x00, // 2 element in this lc + 0x03, 0x00, 0x00, 0x00, // variable 3 + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // coeff 1 + 0x02, 0x00, 0x00, 0x00, // variable 2 + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // coeff 1 + 0x01, 0x00, 0x00, 0x00, // 1 element in this lc + 0x01, 0x00, 0x00, 0x00, // variable 1 + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // coeff 1 + // header + 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // modulo size + 0x20, 0x00, 0x00, 0x00, + // modulo + 0x01, 0x00, 0x00, 0xf0, 0x93, 0xf5, 0xe1, 0x43, 0x91, 0x70, 0xb9, 0x79, 0x48, 0xe8, 0x33, 0x28, 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, + 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + // wire map (one, ~out_0, _1, _0) + 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + + write_r1cs(&mut buf, prog).unwrap(); + + assert_eq!(buf, expected); + + let c = Cursor::new(buf); + + assert!(r1cs_reader::read(c).is_ok()); + } +} diff --git a/zokrates_circom/src/witness.rs b/zokrates_circom/src/witness.rs new file mode 100644 index 00000000..ff8021aa --- /dev/null +++ b/zokrates_circom/src/witness.rs @@ -0,0 +1,219 @@ +use std::{ + io::{Result, Write}, + ops::Add, +}; + +use byteorder::{LittleEndian, WriteBytesExt}; +use zokrates_ast::{ + flat::Variable, + ir::{PublicInputs, Witness}, +}; +use zokrates_field::Field; + +pub struct Header { + pub field_size: u32, + pub prime_size: Vec, + pub witness_size: u32, +} + +fn write_header(writer: &mut W, header: Header) -> Result<()> { + writer.write_u32::(header.field_size)?; + writer.write_all(&header.prime_size)?; + writer.write_u32::(header.witness_size)?; + + Ok(()) +} + +pub fn write_witness( + writer: &mut W, + w: Witness, + public_inputs: PublicInputs, +) -> Result<()> { + let modulo_byte_count = T::max_value().to_biguint().add(1u32).to_bytes_le().len() as u32; + let witness_size = w.0.len() as u32; + + let header = Header { + field_size: modulo_byte_count, + prime_size: T::max_value().to_biguint().add(1u32).to_bytes_le(), + witness_size, + }; + + // magic "wtns" + writer.write_all(&[0x77, 0x74, 0x6e, 0x73])?; + // version + writer.write_u32::(2)?; + // section count + writer.write_u32::(2)?; + + // section type: header + // type + writer.write_u32::(1)?; + // size + writer.write_u64::(8 + modulo_byte_count as u64)?; + + // header + write_header(writer, header)?; + + // section type: witness + // type + writer.write_u32::(2)?; + // size: `modulo_byte_count` per witness value + let size = witness_size as u64 * modulo_byte_count as u64; + writer.write_u64::(size)?; + + write_witness_values(writer, w, public_inputs)?; + + Ok(()) +} + +fn write_val(writer: &mut W, v: &T, modulo_byte_count: usize) -> Result<()> { + let mut res = vec![0u8; modulo_byte_count]; + for (value, padded) in v.to_biguint().to_bytes_le().iter().zip(res.iter_mut()) { + *padded = *value; + } + writer.write_all(&res)?; + Ok(()) +} + +fn write_witness_values( + writer: &mut W, + mut w: Witness, + public_inputs: PublicInputs, +) -> Result<()> { + let modulo_byte_count = T::max_value().to_biguint().add(1u32).to_bytes_le().len(); + + if let Some(value) = w.0.remove(&Variable::one()) { + write_val(writer, &value, modulo_byte_count)?; + } + + let output_count = w.0.iter().filter(|(var, _)| var.is_output()).count(); + + for value in (0..output_count).map(|id| w.0.remove(&Variable::public(id)).unwrap()) { + write_val(writer, &value, modulo_byte_count)?; + } + + for value in public_inputs.iter().map(|var| w.0.remove(var).unwrap()) { + write_val(writer, &value, modulo_byte_count)?; + } + + for (_, val) in w.0.iter() { + write_val(writer, val, modulo_byte_count)?; + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use pretty_assertions::assert_eq; + use zokrates_ast::{flat::Variable, ir::PublicInputs}; + use zokrates_field::Bn128Field; + + #[test] + fn empty() { + let w: Witness = Witness::default(); + let public_inputs: PublicInputs = Default::default(); + let mut buf = Vec::new(); + + #[rustfmt::skip] + let expected: Vec = vec![ + // magic + 0x77, 0x74, 0x6e, 0x73, + // version + 0x02, 0x00, 0x00, 0x00, + // section count + 0x02, 0x00, 0x00, 0x00, + // header + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // modulus size in bytes + 0x20, 0x00, 0x00, 0x00, + // modulus + 0x01, 0x00, 0x00, 0xf0, 0x93, 0xf5, 0xe1, 0x43, 0x91, 0x70, 0xb9, 0x79, 0x48, 0xe8, 0x33, 0x28, 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, + // witness size + 0x00, 0x00, 0x00, 0x00, + // witness section (empty) + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + + write_witness(&mut buf, w, public_inputs).unwrap(); + + assert_eq!(buf, expected); + } + + #[test] + fn one_value() { + let mut w: Witness = Witness::default(); + let public_inputs: PublicInputs = Default::default(); + w.0.insert(Variable::public(0), 1.into()); + let mut buf = Vec::new(); + + #[rustfmt::skip] + let expected: Vec = vec![ + // magic + 0x77, 0x74, 0x6e, 0x73, + // version + 0x02, 0x00, 0x00, 0x00, + // section count + 0x02, 0x00, 0x00, 0x00, + // header + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // modulus size in bytes + 0x20, 0x00, 0x00, 0x00, + // modulus + 0x01, 0x00, 0x00, 0xf0, 0x93, 0xf5, 0xe1, 0x43, 0x91, 0x70, 0xb9, 0x79, 0x48, 0xe8, 0x33, 0x28, 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, + // witness size + 0x01, 0x00, 0x00, 0x00, + // witness section + 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // values + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + + write_witness(&mut buf, w, public_inputs).unwrap(); + + assert_eq!(buf, expected); + } + + #[test] + fn one_and_pub_and_priv() { + let mut w: Witness = Witness::default(); + let public_inputs: PublicInputs = vec![Variable::new(1)].into_iter().collect(); + w.0.extend(vec![ + (Variable::public(0), 42.into()), + (Variable::one(), 1.into()), + (Variable::new(0), 43.into()), + (Variable::new(1), 44.into()), + ]); + let mut buf = Vec::new(); + + #[rustfmt::skip] + let expected: Vec = vec![ + // magic + 0x77, 0x74, 0x6e, 0x73, + // version + 0x02, 0x00, 0x00, 0x00, + // section count + 0x02, 0x00, 0x00, 0x00, + // header + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // modulus size in bytes + 0x20, 0x00, 0x00, 0x00, + // modulus + 0x01, 0x00, 0x00, 0xf0, 0x93, 0xf5, 0xe1, 0x43, 0x91, 0x70, 0xb9, 0x79, 0x48, 0xe8, 0x33, 0x28, 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, + // witness size + 0x04, 0x00, 0x00, 0x00, + // witness section + 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // values: ordering should be [one, ~out_0, _1, _0] because _1 is public + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + + write_witness(&mut buf, w, public_inputs).unwrap(); + + assert_eq!(buf, expected); + } +} diff --git a/zokrates_cli/Cargo.toml b/zokrates_cli/Cargo.toml index dfbcc3b6..2f8c8ef5 100644 --- a/zokrates_cli/Cargo.toml +++ b/zokrates_cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_cli" -version = "0.7.13" +version = "0.7.14" authors = ["Jacob Eberhardt ", "Dennis Kuhnert ", "Thibaut Schaeffer "] repository = "https://github.com/Zokrates/ZoKrates.git" edition = "2018" @@ -22,6 +22,7 @@ zokrates_abi = { version = "0.1", path = "../zokrates_abi" } zokrates_core = { version = "0.6", path = "../zokrates_core", default-features = false } zokrates_ast = { version = "0.1", path = "../zokrates_ast", default-features = false } zokrates_interpreter = { version = "0.1", path = "../zokrates_interpreter", default-features = false } +zokrates_circom = { version = "0.1", path = "../zokrates_circom", default-features = false } typed-arena = "1.4.1" zokrates_fs_resolver = { version = "0.5", path = "../zokrates_fs_resolver"} zokrates_common = { version = "0.1", path = "../zokrates_common", default-features = false } diff --git a/zokrates_cli/src/cli_constants.rs b/zokrates_cli/src/cli_constants.rs index 31e5867f..2f002f8d 100644 --- a/zokrates_cli/src/cli_constants.rs +++ b/zokrates_cli/src/cli_constants.rs @@ -1,6 +1,8 @@ use zokrates_common::constants::*; pub const FLATTENED_CODE_DEFAULT_PATH: &str = "out"; +pub const CIRCOM_R1CS_DEFAULT_PATH: &str = "out.r1cs"; +pub const CIRCOM_WITNESS_DEFAULT_PATH: &str = "out.wtns"; pub const ABI_SPEC_DEFAULT_PATH: &str = "abi.json"; pub const VERIFICATION_KEY_DEFAULT_PATH: &str = "verification.key"; pub const PROVING_KEY_DEFAULT_PATH: &str = "proving.key"; diff --git a/zokrates_cli/src/ops/compile.rs b/zokrates_cli/src/ops/compile.rs index a6730aaf..7c92ddb0 100644 --- a/zokrates_cli/src/ops/compile.rs +++ b/zokrates_cli/src/ops/compile.rs @@ -6,6 +6,7 @@ use std::fs::File; use std::io::{BufReader, BufWriter, Read}; use std::path::{Path, PathBuf}; use typed_arena::Arena; +use zokrates_circom::write_r1cs; use zokrates_common::constants::BN128; use zokrates_common::helpers::CurveParameter; use zokrates_core::compile::{compile, CompileConfig, CompileError}; @@ -46,7 +47,15 @@ pub fn subcommand() -> App<'static, 'static> { .takes_value(true) .required(false) .default_value(cli_constants::FLATTENED_CODE_DEFAULT_PATH) - ).arg(Arg::with_name("curve") + ).arg(Arg::with_name("r1cs") + .short("r1cs") + .long("r1cs") + .help("Path of the output r1cs file") + .value_name("FILE") + .takes_value(true) + .required(false) + .default_value(cli_constants::CIRCOM_R1CS_DEFAULT_PATH) +).arg(Arg::with_name("curve") .short("c") .long("curve") .help("Curve to be used in the compilation") @@ -75,6 +84,7 @@ 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 bin_output_path = Path::new(sub_matches.value_of("output").unwrap()); + let r1cs_output_path = Path::new(sub_matches.value_of("r1cs").unwrap()); let abi_spec_path = Path::new(sub_matches.value_of("abi-spec").unwrap()); log::debug!("Load entry point file {}", path.display()); @@ -133,9 +143,17 @@ fn cli_compile(sub_matches: &ArgMatches) -> Result<(), String> { let bin_output_file = File::create(&bin_output_path) .map_err(|why| format!("Could not create {}: {}", bin_output_path.display(), why))?; - let mut writer = BufWriter::new(bin_output_file); + let r1cs_output_file = File::create(&r1cs_output_path) + .map_err(|why| format!("Could not create {}: {}", r1cs_output_path.display(), why))?; - match program_flattened.serialize(&mut writer) { + let mut bin_writer = BufWriter::new(bin_output_file); + let mut r1cs_writer = BufWriter::new(r1cs_output_file); + + let program_flattened = program_flattened.collect(); + + write_r1cs(&mut r1cs_writer, program_flattened.clone()).unwrap(); + + match program_flattened.serialize(&mut bin_writer) { Ok(constraint_count) => { // serialize ABI spec and write to JSON file log::debug!("Serialize ABI"); diff --git a/zokrates_cli/src/ops/compute_witness.rs b/zokrates_cli/src/ops/compute_witness.rs index 6a29a872..742f2e49 100644 --- a/zokrates_cli/src/ops/compute_witness.rs +++ b/zokrates_cli/src/ops/compute_witness.rs @@ -10,6 +10,7 @@ use zokrates_ast::typed::{ abi::Abi, types::{ConcreteSignature, ConcreteType, GTupleType}, }; +use zokrates_circom::write_witness; use zokrates_field::Field; pub fn subcommand() -> App<'static, 'static> { @@ -34,11 +35,18 @@ pub fn subcommand() -> App<'static, 'static> { ).arg(Arg::with_name("output") .short("o") .long("output") - .help("Path of the output file") + .help("Path of the output witness file") .value_name("FILE") .takes_value(true) .required(false) .default_value(cli_constants::WITNESS_DEFAULT_PATH) + ).arg(Arg::with_name("circom-witness") + .long("circom-witness") + .help("Path of the output circom witness file") + .value_name("FILE") + .takes_value(true) + .required(false) + .default_value(cli_constants::CIRCOM_WITNESS_DEFAULT_PATH) ).arg(Arg::with_name("arguments") .short("a") .long("arguments") @@ -161,6 +169,8 @@ fn cli_compute>>( let interpreter = zokrates_interpreter::Interpreter::default(); + let public_inputs = ir_prog.public_inputs(); + let witness = interpreter .execute(ir_prog, &arguments.encode()) .map_err(|e| format!("Execution failed: {}", e))?; @@ -185,6 +195,16 @@ fn cli_compute>>( .write(writer) .map_err(|why| format!("Could not save witness: {:?}", why))?; + // write circom witness to file + let wtns_path = Path::new(sub_matches.value_of("circom-witness").unwrap()); + let wtns_file = File::create(&wtns_path) + .map_err(|why| format!("Could not create {}: {}", output_path.display(), why))?; + + let mut writer = BufWriter::new(wtns_file); + + write_witness(&mut writer, witness, public_inputs) + .map_err(|why| format!("Could not save circom witness: {:?}", why))?; + println!("Witness file written to '{}'", output_path.display()); Ok(()) } diff --git a/zokrates_common/Cargo.toml b/zokrates_common/Cargo.toml index f9c688b0..ef70f90d 100644 --- a/zokrates_common/Cargo.toml +++ b/zokrates_common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_common" -version = "0.1.0" +version = "0.1.1" authors = ["dark64 "] edition = "2018" diff --git a/zokrates_core/Cargo.toml b/zokrates_core/Cargo.toml index 1f46cecf..8ffac522 100644 --- a/zokrates_core/Cargo.toml +++ b/zokrates_core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_core" -version = "0.6.12" +version = "0.6.13" edition = "2018" authors = ["Jacob Eberhardt ", "Dennis Kuhnert "] repository = "https://github.com/Zokrates/ZoKrates" diff --git a/zokrates_core/src/static_analysis/reducer/constants_reader.rs b/zokrates_core/src/static_analysis/reducer/constants_reader.rs index 310fabc0..1d6ff6b4 100644 --- a/zokrates_core/src/static_analysis/reducer/constants_reader.rs +++ b/zokrates_core/src/static_analysis/reducer/constants_reader.rs @@ -33,6 +33,26 @@ impl<'a, 'ast, T: Field> ConstantsReader<'a, 'ast, T> { } impl<'a, 'ast, T: Field> Folder<'ast, T> for ConstantsReader<'a, 'ast, T> { + fn fold_declaration_constant( + &mut self, + c: DeclarationConstant<'ast, T>, + ) -> DeclarationConstant<'ast, T> { + match c { + DeclarationConstant::Constant(c) => { + let c = self.fold_canonical_constant_identifier(c); + + match self.constants.get(&c).cloned() { + Some(e) => match UExpression::try_from(e).unwrap().into_inner() { + UExpressionInner::Value(v) => DeclarationConstant::Concrete(v as u32), + _ => unreachable!(), + }, + None => DeclarationConstant::Constant(c), + } + } + c => fold_declaration_constant(self, c), + } + } + fn fold_field_expression( &mut self, e: FieldElementExpression<'ast, T>, @@ -169,24 +189,4 @@ impl<'a, 'ast, T: Field> Folder<'ast, T> for ConstantsReader<'a, 'ast, T> { e => fold_struct_expression_inner(self, ty, e), } } - - fn fold_declaration_constant( - &mut self, - c: DeclarationConstant<'ast, T>, - ) -> DeclarationConstant<'ast, T> { - match c { - DeclarationConstant::Constant(c) => { - let c = self.fold_canonical_constant_identifier(c); - - match self.constants.get(&c).cloned() { - Some(e) => match UExpression::try_from(e).unwrap().into_inner() { - UExpressionInner::Value(v) => DeclarationConstant::Concrete(v as u32), - _ => unreachable!(), - }, - None => DeclarationConstant::Constant(c), - } - } - c => fold_declaration_constant(self, c), - } - } } diff --git a/zokrates_core_test/tests/tests/constants/tuple.json b/zokrates_core_test/tests/tests/constants/tuple.json new file mode 100644 index 00000000..4a099efb --- /dev/null +++ b/zokrates_core_test/tests/tests/constants/tuple.json @@ -0,0 +1,16 @@ +{ + "entry_point": "./tests/tests/constants/tuple.zok", + "max_constraint_count": 3, + "tests": [ + { + "input": { + "values": [] + }, + "output": { + "Ok": { + "values": [[["1", "1"], true]] + } + } + } + ] +} diff --git a/zokrates_core_test/tests/tests/constants/tuple.zok b/zokrates_core_test/tests/tests/constants/tuple.zok new file mode 100644 index 00000000..47159ec0 --- /dev/null +++ b/zokrates_core_test/tests/tests/constants/tuple.zok @@ -0,0 +1,5 @@ +const u32 N = 2 +const (field[N], bool) A = ([1; N], true) + +def main() -> ((field[N], bool)): + return A \ No newline at end of file diff --git a/zokrates_embed/src/ark.rs b/zokrates_embed/src/ark.rs index beb756e4..40ce41dd 100644 --- a/zokrates_embed/src/ark.rs +++ b/zokrates_embed/src/ark.rs @@ -165,11 +165,7 @@ pub fn generate_verify_constraints( .into_iter() .zip(matrices.b.into_iter()) .zip(matrices.c.into_iter()) - .map(|((a, b), c)| Constraint { - a: a.into_iter().map(|(f, index)| (index, f)).collect(), - b: b.into_iter().map(|(f, index)| (index, f)).collect(), - c: c.into_iter().map(|(f, index)| (index, f)).collect(), - }) + .map(|((a, b), c)| Constraint { a, b, c }) .collect(); ( @@ -309,26 +305,26 @@ pub fn from_ark(c: Constraint Constraint { a: c.a .into_iter() - .map(|(index, fq)| { + .map(|(fq, index)| { let mut res: Vec = vec![]; fq.into_repr().write_le(&mut res).unwrap(); - (index, T::from_byte_vector(res)) + (T::from_byte_vector(res), index) }) .collect(), b: c.b .into_iter() - .map(|(index, fq)| { + .map(|(fq, index)| { let mut res: Vec = vec![]; fq.into_repr().write_le(&mut res).unwrap(); - (index, T::from_byte_vector(res)) + (T::from_byte_vector(res), index) }) .collect(), c: c.c .into_iter() - .map(|(index, fq)| { + .map(|(fq, index)| { let mut res: Vec = vec![]; fq.into_repr().write_le(&mut res).unwrap(); - (index, T::from_byte_vector(res)) + (T::from_byte_vector(res), index) }) .collect(), } diff --git a/zokrates_embed/src/bellman.rs b/zokrates_embed/src/bellman.rs index b178f295..cf20413b 100644 --- a/zokrates_embed/src/bellman.rs +++ b/zokrates_embed/src/bellman.rs @@ -180,17 +180,17 @@ impl ConstraintSystem for R1CS { let a = a .as_ref() .iter() - .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient)) + .map(|(variable, coefficient)| (*coefficient, var_to_index(*variable))) .collect(); let b = b .as_ref() .iter() - .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient)) + .map(|(variable, coefficient)| (*coefficient, var_to_index(*variable))) .collect(); let c = c .as_ref() .iter() - .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient)) + .map(|(variable, coefficient)| (*coefficient, var_to_index(*variable))) .collect(); self.constraints.push(Constraint { a, b, c }); @@ -257,26 +257,26 @@ pub fn from_bellman(c: Constraint) - Constraint { a: c.a .into_iter() - .map(|(index, fq)| { + .map(|(fq, index)| { let mut res: Vec = vec![]; fq.into_repr().write_le(&mut res).unwrap(); - (index, T::from_byte_vector(res)) + (T::from_byte_vector(res), index) }) .collect(), b: c.b .into_iter() - .map(|(index, fq)| { + .map(|(fq, index)| { let mut res: Vec = vec![]; fq.into_repr().write_le(&mut res).unwrap(); - (index, T::from_byte_vector(res)) + (T::from_byte_vector(res), index) }) .collect(), c: c.c .into_iter() - .map(|(index, fq)| { + .map(|(fq, index)| { let mut res: Vec = vec![]; fq.into_repr().write_le(&mut res).unwrap(); - (index, T::from_byte_vector(res)) + (T::from_byte_vector(res), index) }) .collect(), } diff --git a/zokrates_embed/src/lib.rs b/zokrates_embed/src/lib.rs index 2c873e2d..356c6fcd 100644 --- a/zokrates_embed/src/lib.rs +++ b/zokrates_embed/src/lib.rs @@ -26,7 +26,7 @@ pub struct Witness { #[derive(Default, Debug, PartialEq, Clone)] pub struct Constraint { - pub a: Vec<(usize, T)>, - pub b: Vec<(usize, T)>, - pub c: Vec<(usize, T)>, + pub a: Vec<(T, usize)>, + pub b: Vec<(T, usize)>, + pub c: Vec<(T, usize)>, } diff --git a/zokrates_js/Cargo.toml b/zokrates_js/Cargo.toml index 0c64dcb2..d7a81fcc 100644 --- a/zokrates_js/Cargo.toml +++ b/zokrates_js/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_js" -version = "1.0.43" +version = "1.0.44" authors = ["Darko Macesic"] edition = "2018" @@ -21,5 +21,6 @@ zokrates_ast = { path = "../zokrates_ast", default-features = false, features = zokrates_interpreter = { path = "../zokrates_interpreter", default-features = false, features = ["ark"] } zokrates_field = { path = "../zokrates_field", default-features = false } zokrates_abi = { path = "../zokrates_abi", default-features = false, features = ["ark"] } +zokrates_circom = { path = "../zokrates_circom" } console_error_panic_hook = "0.1.6" indexmap = "~1.6.2" # see https://github.com/rustwasm/wasm-bindgen/issues/2770#issuecomment-1041102532 \ No newline at end of file diff --git a/zokrates_js/index.d.ts b/zokrates_js/index.d.ts index 0e843e4b..3669d3ac 100644 --- a/zokrates_js/index.d.ts +++ b/zokrates_js/index.d.ts @@ -19,6 +19,7 @@ declare module "zokrates-js" { location?: string; resolveCallback?: ResolveCallback; config?: CompileConfig; + snarkjs?: boolean; } export type Proof = { @@ -31,9 +32,16 @@ declare module "zokrates-js" { location: string; } + export interface ComputeOptions { + snarkjs?: boolean; + } + export interface ComputationResult { witness: string; output: string; + snarkjs?: { + witness: Uint8Array; + }; } export interface Abi { @@ -44,6 +52,9 @@ declare module "zokrates-js" { export interface CompilationArtifacts { program: Uint8Array; abi: Abi; + snarkjs?: { + program: Uint8Array; + }; } export interface SetupKeypair { @@ -64,7 +75,8 @@ declare module "zokrates-js" { ): CompilationArtifacts; computeWitness( input: CompilationArtifacts | Uint8Array, - args: any[] + args: any[], + options?: ComputeOptions ): ComputationResult; setup(program: Uint8Array): SetupKeypair; universalSetup(size: number): Uint8Array; diff --git a/zokrates_js/package.json b/zokrates_js/package.json index 82497bb1..160e1e69 100644 --- a/zokrates_js/package.json +++ b/zokrates_js/package.json @@ -1,6 +1,6 @@ { "name": "zokrates-js", - "version": "1.0.43", + "version": "1.0.44", "module": "index.js", "main": "node/index.js", "description": "JavaScript bindings for ZoKrates", @@ -43,7 +43,7 @@ "clean-node-pkg": "rimraf node/pkg/README.md node/pkg/.gitignore", "pretest": "npm run setup && npm run build:node:dev", "test": "npm run run-tests", - "run-tests": "mocha --timeout 30000 --require esm --recursive tests" + "run-tests": "mocha --timeout 100000 --require esm --recursive tests" }, "devDependencies": { "dree": "^2.6.1", @@ -53,6 +53,7 @@ "mocha": "^9.2.0", "rimraf": "^3.0.2", "serve": "^11.3.2", + "snarkjs": "^0.4.19", "text-encoding": "^0.7.0", "toml": "^3.0.0", "wasm-pack": "^0.10.2" diff --git a/zokrates_js/src/lib.rs b/zokrates_js/src/lib.rs index 0c7162d2..3d0192a1 100644 --- a/zokrates_js/src/lib.rs +++ b/zokrates_js/src/lib.rs @@ -11,6 +11,7 @@ use zokrates_ast::ir; use zokrates_ast::ir::ProgEnum; use zokrates_ast::typed::abi::Abi; use zokrates_ast::typed::types::{ConcreteSignature, ConcreteType, GTupleType}; +use zokrates_circom::{write_r1cs, write_witness}; use zokrates_common::helpers::{CurveParameter, SchemeParameter}; use zokrates_common::Resolver; use zokrates_core::compile::{ @@ -29,6 +30,7 @@ use zokrates_proof_systems::{ pub struct CompilationResult { program: Vec, abi: Abi, + snarkjs_program: Option>, } #[wasm_bindgen] @@ -41,6 +43,14 @@ impl CompilationResult { pub fn abi(&self) -> JsValue { JsValue::from_serde(&self.abi).unwrap() } + + pub fn snarkjs_program(&self) -> Option { + self.snarkjs_program.as_ref().map(|p| { + let arr = js_sys::Uint8Array::new_with_length(p.len() as u32); + arr.copy_from(p); + arr + }) + } } #[derive(Serialize, Deserialize)] @@ -49,10 +59,28 @@ pub struct ResolverResult { location: String, } -#[derive(Serialize, Deserialize)] +#[wasm_bindgen] pub struct ComputationResult { witness: String, output: String, + snarkjs_witness: Option>, +} + +#[wasm_bindgen] +impl ComputationResult { + pub fn witness(&self) -> JsValue { + JsValue::from_str(&self.witness) + } + pub fn output(&self) -> JsValue { + JsValue::from_str(&self.output) + } + pub fn snarkjs_witness(&self) -> Option { + self.snarkjs_witness.as_ref().map(|w| { + let arr = js_sys::Uint8Array::new_with_length(w.len() as u32); + arr.copy_from(w); + arr + }) + } } pub struct JsResolver<'a> { @@ -107,7 +135,12 @@ mod internal { config: JsValue, ) -> Result { let resolver = JsResolver::new(resolve_callback); - let config: CompileConfig = config.into_serde().unwrap_or_default(); + let config: serde_json::Value = config.into_serde().unwrap(); + let with_snarkjs_program = config + .get("snarkjs") + .map(|v| *v == serde_json::Value::Bool(true)) + .unwrap_or(false); + let config: CompileConfig = serde_json::from_value(config).unwrap_or_default(); let fmt_error = |e: &CompileError| format!("{}:{}", e.file().display(), e.value()); @@ -131,13 +164,19 @@ mod internal { let abi = artifacts.abi().clone(); - let program = artifacts.prog(); + let program = artifacts.prog().collect(); + let snarkjs_program = with_snarkjs_program.then(|| { + let mut buffer = Cursor::new(vec![]); + write_r1cs(&mut buffer, program.clone()).unwrap(); + buffer.into_inner() + }); let mut buffer = Cursor::new(vec![]); let _ = program.serialize(&mut buffer); Ok(CompilationResult { abi, program: buffer.into_inner(), + snarkjs_program, }) } @@ -145,9 +184,16 @@ mod internal { program: ir::Prog, abi: JsValue, args: JsValue, - ) -> Result { + config: JsValue, + ) -> Result { let input = args.as_string().unwrap(); + let config: serde_json::Value = config.into_serde().unwrap(); + let with_snarkjs_witness = config + .get("snarkjs") + .map(|v| *v == serde_json::Value::Bool(true)) + .unwrap_or(false); + let (inputs, signature) = if abi.is_object() { let abi: Abi = abi.into_serde().map_err(|err| { JsValue::from_str(&format!("Could not deserialize `abi`: {}", err)) @@ -175,6 +221,8 @@ mod internal { let interpreter = zokrates_interpreter::Interpreter::default(); + let public_inputs = program.public_inputs(); + let witness = interpreter .execute(program, &inputs.encode()) .map_err(|err| JsValue::from_str(&format!("Execution failed: {}", err)))?; @@ -183,12 +231,17 @@ mod internal { zokrates_abi::Value::decode(witness.return_values(), *signature.output) .into_serde_json(); - let result = ComputationResult { + let snarkjs_witness = with_snarkjs_witness.then(|| { + let mut buffer = Cursor::new(vec![]); + write_witness(&mut buffer, witness.clone(), public_inputs).unwrap(); + buffer.into_inner() + }); + + Ok(ComputationResult { witness: format!("{}", witness), output: to_string_pretty(&return_values).unwrap(), - }; - - Ok(JsValue::from_serde(&result).unwrap()) + snarkjs_witness, + }) } pub fn setup_non_universal< @@ -313,15 +366,20 @@ pub fn compile( } #[wasm_bindgen] -pub fn compute_witness(program: &[u8], abi: JsValue, args: JsValue) -> Result { +pub fn compute_witness( + program: &[u8], + abi: JsValue, + args: JsValue, + config: JsValue, +) -> Result { let prog = ir::ProgEnum::deserialize(program) .map_err(|err| JsValue::from_str(&err))? .collect(); match prog { - ProgEnum::Bn128Program(p) => internal::compute::<_>(p, abi, args), - ProgEnum::Bls12_381Program(p) => internal::compute::<_>(p, abi, args), - ProgEnum::Bls12_377Program(p) => internal::compute::<_>(p, abi, args), - ProgEnum::Bw6_761Program(p) => internal::compute::<_>(p, abi, args), + ProgEnum::Bn128Program(p) => internal::compute::<_>(p, abi, args, config), + ProgEnum::Bls12_381Program(p) => internal::compute::<_>(p, abi, args, config), + ProgEnum::Bls12_377Program(p) => internal::compute::<_>(p, abi, args, config), + ProgEnum::Bw6_761Program(p) => internal::compute::<_>(p, abi, args, config), } } diff --git a/zokrates_js/tests/powersOfTau5_0000.ptau b/zokrates_js/tests/powersOfTau5_0000.ptau new file mode 100644 index 0000000000000000000000000000000000000000..62abfceb639b8f1f2fd1b9f150ad0b629188b2c4 GIT binary patch literal 36800 zcmeI5XHXQ`7RQI2hA0k_Ge{T#0RvHjgdHSG7FL4fAUP*NKx9A!VL%X&C|QE!BuJDj zK{CjYl_1~>2oLs!5AVxV?bdtl7PqTz_e|Av-E)7Z@BN?CeP-sqtBD&H1Og#BX{Sg2 zlXkkXoHWHBzGJXR771jRlU0mOP=b+OP|%y3>Qy{xLUYcl=7M-9pE+&VC#{M6WOuTq zkVd~l${7twlC1h5I=+b0pw30fBfI)&p4+^ zJjLk_0^wq*!yc#zj&jEGQ5L0Lo1CEwN>JpgIuKWnFP6EcOMAmaCD+fTyts7?ThCxh z?rx|+n&zSU3X!ePs#x&m5%u1RZFtIliizj*7rP0A0Y^uE^z5c|FOKnLUlgtR|G4-? z=R&)VA(45lgx_Vh@4A!j6r#cnqTjV2nE!}fOv@w%{R95s`UCS1tUqA=1^NT@7sMYR z{sQqQh`&Mp0rD@9fBx_DZ`{+H0EDMI@LV6%C4jmFP?rGe5k)rV=R?*cm@f>GEn+W z+eazyUF=NB4Z=y(6VcZBM$MWEtNDHg0t2R0C{{8~-!=#jF2_=yXB)jHPVaW>knq&a zHu3lnW?Fx>Nj;G;1{WtD_x>LQD9VRJJ@G9FZoTyZ8#&Ac1@J>yK=BUpy zp5|>&$F_{L%G2H=lfL(~kWrhebo1q zyUBR5t6eh!8Ktkw?VG$B=;b#`l`VQSm8L&trg?kBpNXmS`QtUxgx8T-x7^_Z1G97i z?QZb`X!h#MM30R-oR+!fA6X`f>?%&`kgc?@4@os9IeFTaT5`#YkJ;VPZ_?qqRu;CB z5g5eW)-i%}NLBfYx4V0lT8NE6CPE2{i#!z%1-8?19!(;8h$GG*JG0;@vv!|jzOqfEyS^Y_J6bPMg{DcFpPP;ZQDZL)J& zi&=TgMbo!+umvyYEj}0~+*X_>E`PUbT%+IVXQ-t@Bb%pF--q^jEYTZp^~KS3D&+c8 zy}mcpCXlG3?1zNk;eMCN<^AsC7^L|RGZg9jenK2gJX2mO^d_0%3$de5YHLMSkkGpwLbN-Tu)LgNr2ST4nby9E_swlwF^ry$&oWp6&P&+R)y*D%FIw zUOPpNs)scOctBNH5Gr{A@(;DWw}pnmbR7Av*h6szh2kv5MlU~V#RbRGH{tEeR3wo-pg~=xsF7vW)eC*)37GU^?gSv2i_dTO92QT;!Y2^=7urAUW({9j5lKoASK$EG;2JG|v(fYzntNxC(Um z_M~fS=+e@&>cT&7J=RBANP2h%%ka+QD(d%`U7tN4`eyzv#Yf6KJoe#7AI|fCH>Zk6 zI+eVUsii{HDzcKmGv{WR@tLiJ2wI19sc3$2b@Zvw&%7A_gyUo4sOoQyCQSq1Y0Yxg z>6r1DmPPIQO;HgIA6)xhnVR7gz$JV8Ggm4;Qg^-9YcaMR=FMqg%F=<+NW9hOg6a|`y@eT>lt1pvPqN<0b z#yiSnwB-4Pt%N%LNmP4ThZRCTjvPYDUfnH?mbPS)zsKq^*+)uHQLJ(tO-rF`Ft3^^ z_toN(=1tFc`u@s-9l||VyEJkxnT*0Kdktb+XV9B2SLSq=XT`&w`qRS+OYXF$=Q(BK zbLA&fvmwYTskfC<4TahqdQf?8Z0U;oH`Qa_EB#_cG67FQX^`c2E~nXNube5`%X!DH)X_yw=g=hgS{_jM6LoSYQH5~l&^9?n=17ze z2aK2rgVEPbv?Bwd2ZG^y&hR@nD^#H0fj6F_ zZjFBeolbU5kANSyC`>9-SC(op8+EOCTBV|k={Gao+Z)k^FT$Y;^%-8w=CH5xsxO$s z#e-9dx*u2DL*=3vBU{;21f7af`{72?W7>W^O;WVxeSNzR){PsoHJ#&4R?Ztk(#6Uv zCX5z~9*HklttN4NuwMMJw9CE~81x8!SXOoZo~1B3vFV^^5ZkNbxpEwceCe_2%D4wb z4wTemAYyUqX3>vztZ-*HH50FEpEf6m^q+IN)R$gjf$@yH#aL!Z1F(Re1Pb^=}vr|8n86gMXQ zPkk#C-CLnd>$tgUj{N{~KQ{G1NRh?%PK?AVWy~g$9h3eyBHh$)T`%=MniSaN&-~J0 zyASUblo*r#i-Z@{7Cu{z($->$fdyWC zx0D_ucc4*;%rfm`2_JIg#-#tyt}Oa(9$Uu+rqBH&#sa1$ss0lPdC5wIswGP3xf3xa z{YOn`a?Gv5(Gf|~4S7rXQMMEr?%09%^c@wf%xDg1Xff%3SC@TUB0b~$IwBeIi2|>j z(jaTi&iJJyQ!}0szHm1#CjEa3U(8=pf7+HH+JbcFdva^B=VN7cV5ctwF(&ie{6P;ViBEaklfd*xiAjwziwYR>Ogxu29;FMs&r2p284eRK8+=}wb4sjWE zg)5ar7Tt}n_So;Jl&sxWcyRUhqtdnv3SE{``cN3SXhh?#%GYt>yvCurf z(PGm7&A#Zxh|A%_YFghH)NZ6cg&mhM`rQ+|>{8#~pD0noi%I{3c{tmSWeVO?p1;s) z^fTt~ zSTIl^y5`~Cn+4Nq58W6~L-m@BVqwyMC$BgvN3D<}s;snL&z9RQ{rBhen;!?{-l=JB zwHduYjYS0= z+-Re4E=>B5r_oPd8n?}8En^ThLpLLrN~h@Z$>R8+D{0P~&t{pG^yH31;J=>b|Li)0 zpWXle{pQPmb$Hgt|6e%H+*{!PGv{(JU_jtM1i<|N4+`)C5C8-K0YCr{I5Px*{+}6F zgMk79fB+x>2mk_r03ZMe00MvjAOHxQVFF|)WB;rC$KRiI!&(1c;aMO5pS^zm?&kyl z|J^+Z><0w?H~}#K|2R8vCLjO^00MvjAn { // initialize once before running tests - before((done) => { - initialize().then((defaultProvider) => { + before(() => { + return initialize().then((defaultProvider) => { zokratesProvider = defaultProvider; - done(); + return fs.promises.mkdtemp(path.join(os.tmpdir(), path.sep)).then((folder) => { + tmpFolder = folder; + }); }); }); - describe("compilation", () => { - it("should compile", () => { - assert.doesNotThrow(() => { - const artifacts = zokratesProvider.compile( - "def main() -> field { return 42; }" - ); - assert.ok(artifacts !== undefined); - }); - }); + after(() => { + if (globalThis.curve_bn128) globalThis.curve_bn128.terminate(); + }); - it("should throw on invalid code", () => { - assert.throws(() => zokratesProvider.compile(":-)")); - }); + describe("compilation", () => { + it("should compile", () => { + assert.doesNotThrow(() => { + const artifacts = zokratesProvider.compile( + "def main() -> field: return 42" + ); + assert.ok(artifacts !== undefined); + assert.ok(artifacts.snarkjs === undefined); + }); + }); - it("should resolve stdlib module", () => { - const stdlib = require("../stdlib.js"); - assert.doesNotThrow(() => { - const code = `import "${ - Object.keys(stdlib)[0] - }" as func; def main() { return; }`; - zokratesProvider.compile(code); - }); - }); + it("should compile with snarkjs output", () => { + assert.doesNotThrow(() => { + const artifacts = zokratesProvider.compile( + "def main() -> field: return 42", + { snarkjs: true } + ); + assert.ok(artifacts !== undefined); + assert.ok(artifacts.snarkjs.program !== undefined); + }); + }); - it("should resolve user module", () => { - assert.doesNotThrow(() => { - const code = - 'import "test" as test; def main() -> field { return test(); }'; - const options = { - resolveCallback: (_, path) => { - return { - source: "def main() -> field { return 1; }", - location: path, - }; - }, - }; - zokratesProvider.compile(code, options); - }); - }); + it("should throw on invalid code", () => { + assert.throws(() => zokratesProvider.compile(":-)")); + }); - it("should throw on unresolved module", () => { - assert.throws(() => { - const code = - 'import "test" as test; def main() -> field { return test(); }'; - zokratesProvider.compile(code); - }); - }); - }); + it("should resolve stdlib module", () => { + const stdlib = require("../stdlib.js"); + assert.doesNotThrow(() => { + const code = `import "${ + Object.keys(stdlib)[0] + }" as func\ndef main(): return`; + zokratesProvider.compile(code); + }); + }); - describe("computation", () => { - it("should compute with valid inputs", () => { - assert.doesNotThrow(() => { - const code = "def main(private field a) -> field { return a * a; }"; - const artifacts = zokratesProvider.compile(code); + it("should resolve user module", () => { + assert.doesNotThrow(() => { + const code = + 'import "test" as test\ndef main() -> field: return test()'; + const options = { + resolveCallback: (_, path) => { + return { + source: "def main() -> (field): return 1", + location: path, + }; + }, + }; + zokratesProvider.compile(code, options); + }); + }); - const result = zokratesProvider.computeWitness(artifacts, ["2"]); - const output = JSON.parse(result.output); - assert.deepEqual(output, "4"); - }); - }); + it("should throw on unresolved module", () => { + assert.throws(() => { + const code = + 'import "test" as test\ndef main() -> field: return test()'; + zokratesProvider.compile(code); + }); + }); + }); - it("should throw on invalid input count", () => { - assert.throws(() => { - const code = "def main(private field a) -> field { return a * a; }"; - const artifacts = zokratesProvider.compile(code); - zokratesProvider.computeWitness(artifacts, ["1", "2"]); - }); - }); + describe("computation", () => { + it("should compute with valid inputs", () => { + assert.doesNotThrow(() => { + const code = "def main(private field a) -> field: return a * a"; + const artifacts = zokratesProvider.compile(code); + const result = zokratesProvider.computeWitness(artifacts, ["2"]); + const output = JSON.parse(result.output); + assert.deepEqual(output, ["4"]); + assert.ok(result.snarkjs === undefined); + }); + }); - it("should throw on invalid input type", () => { - assert.throws(() => { - const code = "def main(private field a) -> field { return a * a; }"; - const artifacts = zokratesProvider.compile(code); - zokratesProvider.computeWitness(artifacts, [true]); - }); - }); - }); + it("should compute with valid inputs with snarkjs output", () => { + assert.doesNotThrow(() => { + const code = "def main(private field a) -> field: return a * a"; + const artifacts = zokratesProvider.compile(code); - const runWithOptions = (options) => { - let provider; - let artifacts; - let computationResult; - let keypair; - let proof; + const result = zokratesProvider.computeWitness(artifacts, ["2"], { + snarkjs: true, + }); - before((done) => { - provider = zokratesProvider.withOptions(options); - done(); - }); + const output = JSON.parse(result.output); + assert.deepEqual(output, ["4"]); + assert.ok(result.snarkjs.witness !== undefined); + }); + }); - it("compile", () => { - assert.doesNotThrow(() => { - const code = - "def main(private field a, field b) -> bool { return a * a == b; }"; - artifacts = provider.compile(code); - }); - }); + it("should throw on invalid input count", () => { + assert.throws(() => { + const code = "def main(private field a) -> field: return a * a"; + const artifacts = zokratesProvider.compile(code); + zokratesProvider.computeWitness(artifacts, ["1", "2"]); + }); + }); - it("compute witness", () => { - assert.doesNotThrow(() => { - computationResult = provider.computeWitness(artifacts, ["2", "4"]); - }); - }); + it("should throw on invalid input type", () => { + assert.throws(() => { + const code = "def main(private field a) -> field: return a * a"; + const artifacts = zokratesProvider.compile(code); + zokratesProvider.computeWitness(artifacts, [true]); + }); + }); + }); - it("setup", () => { - assert.doesNotThrow(() => { - if (options.scheme === "marlin") { - const srs = provider.universalSetup(4); - keypair = provider.setupWithSrs(srs, artifacts.program); - } else { - keypair = provider.setup(artifacts.program); - } - }); - }); + const runWithOptions = (options) => { + let provider; + let artifacts; + let computationResult; + let keypair; + let proof; - if (options.curve === "bn128" && ["g16", "gm17"].includes(options.scheme)) { - it("export verifier", () => { - assert.doesNotThrow(() => { - let verifier = provider.exportSolidityVerifier(keypair.vk); - assert.ok(verifier.includes("contract")); - }); - }); - } + before(() => { + provider = zokratesProvider.withOptions(options); + }); - it("generate proof", () => { - assert.doesNotThrow(() => { - proof = provider.generateProof( - artifacts.program, - computationResult.witness, - keypair.pk - ); - assert.ok(proof !== undefined); - assert.equal(proof.inputs.length, 2); - }); - }); + it("compile", () => { + assert.doesNotThrow(() => { + const code = + "def main(private field a, field b) -> bool: return a * a == b"; + artifacts = provider.compile(code, { snarkjs: true }); + }); + }); - it("verify", () => { - assert.doesNotThrow(() => { - assert(provider.verify(keypair.vk, proof) === true); - }); - }); - }; + it("compute witness", () => { + assert.doesNotThrow(() => { + computationResult = provider.computeWitness(artifacts, ["2", "4"], { + snarkjs: true, + }); + }); + }); - for (const scheme of ["g16", "gm17", "marlin"]) { - describe(scheme, () => { - for (const curve of ["bn128", "bls12_381", "bls12_377", "bw6_761"]) { - describe(curve, () => runWithOptions({ scheme, curve })); - } - }); - } + it("setup", () => { + assert.doesNotThrow(() => { + if (options.scheme === "marlin") { + const srs = provider.universalSetup(4); + keypair = provider.setupWithSrs(srs, artifacts.program); + } else { + keypair = provider.setup(artifacts.program); + } + }); + }); + + if (options.scheme === "g16" && options.curve == "bn128") { + it("snarkjs setup", () => { + // write program to fs + let r1csPath = tmpFolder + "/prog.r1cs"; + let zkeyPath = tmpFolder + "/key.zkey"; + return fs.promises + .writeFile(r1csPath, artifacts.snarkjs.program) + .then(() => { + return snarkjs.zKey + .newZKey(r1csPath, "./tests/powersOfTau5_0000.ptau", zkeyPath) + .then(() => {}); + }); + }); + } + + if (options.curve === "bn128" && ["g16", "gm17"].includes(options.scheme)) { + it("export verifier", () => { + assert.doesNotThrow(() => { + let verifier = provider.exportSolidityVerifier(keypair.vk); + assert.ok(verifier.includes("contract")); + }); + }); + } + + it("generate proof", () => { + assert.doesNotThrow(() => { + proof = provider.generateProof( + artifacts.program, + computationResult.witness, + keypair.pk + ); + assert.ok(proof !== undefined); + assert.equal(proof.inputs.length, 2); + }); + }); + + if (options.scheme === "g16" && options.curve == "bn128") { + it("generate snarkjs proof", () => { + // write witness to fs + let witnessPath = tmpFolder + "/witness.wtns"; + let zkeyPath = tmpFolder + "/key.zkey"; + return fs.promises + .writeFile(witnessPath, computationResult.snarkjs.witness) + .then(() => { + return snarkjs.groth16.prove(zkeyPath, witnessPath); + }); + }); + } + + it("verify", () => { + assert.doesNotThrow(() => { + assert(provider.verify(keypair.vk, proof) === true); + }); + }); + }; + + for (const scheme of ["g16", "gm17", "marlin"]) { + describe(scheme, () => { + for (const curve of ["bn128", "bls12_381", "bls12_377", "bw6_761"]) { + describe(curve, () => runWithOptions({ scheme, curve })); + } + }); + } const testRunner = (rootPath, testPath, test) => { let entryPoint; @@ -241,7 +306,7 @@ describe("tests", function () { const test = require(file.path); const testName = file.path.substring(testsPath.length + 1); - if (!ignoreList.some(v => testName.startsWith(v))) + if (!ignoreList.some((v) => testName.startsWith(v))) describe(testName, () => testRunner(rootPath, file.path, test)); }); }); diff --git a/zokrates_js/wrapper.js b/zokrates_js/wrapper.js index 93da979e..d09369fb 100644 --- a/zokrates_js/wrapper.js +++ b/zokrates_js/wrapper.js @@ -35,12 +35,16 @@ module.exports = (dep) => { const defaultProvider = { compile: (source, compileOptions = {}) => { - const { + var { curve = "bn128", location = "main.zok", resolveCallback = () => null, config = {}, + snarkjs = false, } = compileOptions; + + config = { snarkjs, ...config }; + const callback = (currentLocation, importLocation) => { return ( resolveFromStdlib(currentLocation, importLocation) || @@ -48,15 +52,36 @@ module.exports = (dep) => { ); }; const ptr = zokrates.compile(source, location, callback, config, curve); - return { - program: ptr.program(), - abi: ptr.abi(), - }; + return Object.assign( + { + program: ptr.program(), + abi: ptr.abi(), + }, + snarkjs ? { snarkjs: { program: ptr.snarkjs_program() } } : {} + ); }, - computeWitness: (input, args) => { + computeWitness: (input, args, computeOptions = {}) => { const { program, abi } = input instanceof Uint8Array ? { program: input, abi: null } : input; - return zokrates.compute_witness(program, abi, JSON.stringify(args)); + + const { snarkjs = false } = computeOptions; + const ptr = zokrates.compute_witness(program, abi, JSON.stringify(args), { + snarkjs: snarkjs, + }); + + return Object.assign( + { + witness: ptr.witness(), + output: ptr.output(), + }, + snarkjs + ? { + snarkjs: { + witness: ptr.snarkjs_witness(), + }, + } + : {} + ); }, setup: (program, options) => { return zokrates.setup(program, options); @@ -79,8 +104,8 @@ module.exports = (dep) => { utils: { formatProof: (proof) => { return zokrates.format_proof(proof); - } - } + }, + }, }; const withOptions = (options) => { @@ -91,8 +116,8 @@ module.exports = (dep) => { ...compileOptions, curve: options.curve, }), - computeWitness: (artifacts, args) => - defaultProvider.computeWitness(artifacts, args), + computeWitness: (artifacts, args, computeOptions = {}) => + defaultProvider.computeWitness(artifacts, args, computeOptions), setup: (program) => defaultProvider.setup(program, options), universalSetup: (size) => defaultProvider.universalSetup(options.curve, size), @@ -105,11 +130,11 @@ module.exports = (dep) => { defaultProvider.exportSolidityVerifier(vk), utils: { formatProof: (proof) => defaultProvider.utils.formatProof(proof), - } + }, }; }; return { ...withOptions({ scheme: "g16", curve: "bn128" }), }; -}; \ No newline at end of file +}; diff --git a/zokrates_solidity_test/src/evm.rs b/zokrates_solidity_test/src/evm.rs index 61f1bd29..0c793d2b 100644 --- a/zokrates_solidity_test/src/evm.rs +++ b/zokrates_solidity_test/src/evm.rs @@ -1,6 +1,6 @@ use primitive_types::U256; pub use revm::Return; -use revm::{AccountInfo, InMemoryDB, Log, TransactOut, TransactTo, EVM}; +use revm::{AccountInfo, Database, InMemoryDB, Log, TransactOut, TransactTo, EVM}; use crate::{address::Address, Error, EvmTestError}; @@ -60,31 +60,18 @@ impl Evm { contract: Vec, deployer: &Address, ) -> Result { - match self - .vm - .db() - .unwrap() - .cache() - .get_key_value(deployer.as_ref()) - { - Some(_) => { - self.vm.env.tx.caller = *deployer.as_ref(); - self.vm.env.tx.transact_to = TransactTo::create(); - self.vm.env.tx.data = contract.into(); - let (_, tx_out, gas, _) = self.vm.transact_commit(); - let contract_address = match tx_out { - TransactOut::Create(_, Some(addr)) => Ok(Address(addr)), - _ => Err(Box::new(EvmTestError("create contract failed".to_string()))), - }?; - Ok(CreateContractResult { - addr: contract_address, - gas, - }) - } - None => Err(Box::new(EvmTestError( - "deployer address not found".to_string(), - ))), - } + self.vm.env.tx.caller = *deployer.as_ref(); + self.vm.env.tx.transact_to = TransactTo::create(); + self.vm.env.tx.data = contract.into(); + let (_, tx_out, gas, _) = self.vm.transact_commit(); + let contract_address = match tx_out { + TransactOut::Create(_, Some(addr)) => Ok(Address(addr)), + _ => Err(Box::new(EvmTestError("create contract failed".to_string()))), + }?; + Ok(CreateContractResult { + addr: contract_address, + gas, + }) } pub fn create_account(&mut self, address: &Address, balance: impl Into) { @@ -97,27 +84,17 @@ impl Evm { address: &Address, balance: impl Into, ) -> Result<(), Error> { - let mut acc = self - .vm - .db() - .unwrap() - .cache() - .get(address.as_ref()) - .ok_or_else(|| Box::new(EvmTestError("account address not found".to_string())))? - .clone(); + let mut acc = self.vm.db().unwrap().basic(*address.as_ref()).clone(); acc.balance = balance.into(); self.vm.db().unwrap().insert_cache(*address.as_ref(), acc); Ok(()) } pub fn balance_of(&mut self, address: &Address) -> U256 { - match self.vm.db().unwrap().cache().get(address.as_ref()) { - Some(acc) => acc.balance, - None => 0.into(), - } + self.vm.db().unwrap().basic(*address.as_ref()).balance } - pub fn get_account(&mut self, address: &Address) -> Option { - self.vm.db().unwrap().cache().get(address.as_ref()).cloned() + pub fn get_account(&mut self, address: &Address) -> AccountInfo { + self.vm.db().unwrap().basic(*address.as_ref()) } } diff --git a/zokrates_stdlib/Cargo.toml b/zokrates_stdlib/Cargo.toml index 4b9a76e9..709c0ca3 100644 --- a/zokrates_stdlib/Cargo.toml +++ b/zokrates_stdlib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_stdlib" -version = "0.2.8" +version = "0.2.9" authors = ["Stefan Deml ", "schaeff "] edition = "2018"