From 2615ef2c43424d350788d8f2bac180dc0b1a1dbd Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Wed, 2 Oct 2024 12:43:42 +0300 Subject: [PATCH] added vyper plonk verifier template --- package-lock.json | 793 ------------------ src/core/templates/verifier_plonk.vy.ejs | 646 ++++++++++++++ test/CircuitZKit.test.ts | 38 +- .../MultiDimensionalArray.groth16.vkey.json | 1 + .../MultiDimensionalArray.groth16.zkey | Bin 0 -> 7874 bytes .../MultiDimensionalArray.plonk.vkey.json | 63 ++ .../MultiDimensionalArray.plonk.zkey | Bin 0 -> 95932 bytes .../MultiDimensionalArray.r1cs | Bin 0 -> 784 bytes .../MultiDimensionalArray.sym | 12 + .../MultiDimensionalArray_artifacts.json | 38 + .../MultiDimensionalArray.wasm | Bin 0 -> 34796 bytes 11 files changed, 797 insertions(+), 794 deletions(-) create mode 100644 src/core/templates/verifier_plonk.vy.ejs create mode 100644 test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray.groth16.vkey.json create mode 100644 test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray.groth16.zkey create mode 100644 test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray.plonk.vkey.json create mode 100644 test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray.plonk.zkey create mode 100644 test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray.r1cs create mode 100644 test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray.sym create mode 100644 test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray_artifacts.json create mode 100644 test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray_js/MultiDimensionalArray.wasm diff --git a/package-lock.json b/package-lock.json index d0de23d..8d4dae0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -359,16 +359,6 @@ "node": ">=6.9.0" } }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -760,27 +750,6 @@ "@ethersproject/signing-key": "^5.7.0" } }, - "node_modules/@ethersproject/units": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", - "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, "node_modules/@ethersproject/web": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", @@ -827,102 +796,6 @@ "ffjavascript": "^0.2.48" } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1472,16 +1345,6 @@ "hardhat": "^2.22.62.8.3" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@scure/base": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.7.tgz", @@ -1686,12 +1549,6 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, - "node_modules/@solidity-parser/parser": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.18.0.tgz", - "integrity": "sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==", - "dev": true - }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -1791,27 +1648,6 @@ "integrity": "sha512-x37Jsv1vx6I6RMJdfvYEmDUOLYgzYMecwlk13gniDOcN20xLVe9hy9DlQxWeCPirqpDY/jwugQSqCi2RxehU3g==", "dev": true }, - "node_modules/abitype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.0.tgz", - "integrity": "sha512-NMeMah//6bJ56H5XRj8QCV4AwuW6hB6zqz2LnhhLdcWVQOsXki6/Pn3APeqxCma62nXIcmZWdu1DlHWS74umVQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/wevm" - }, - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3 >=3.22.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", @@ -1987,23 +1823,6 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/b4a": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", @@ -2207,12 +2026,6 @@ "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", "dev": true }, - "node_modules/brotli-wasm": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brotli-wasm/-/brotli-wasm-2.0.1.tgz", - "integrity": "sha512-+3USgYsC7bzb5yU0/p2HnnynZl0ak0E6uoIm4UW4Aby/8s8HFCq6NCfrrf1E9c3O8OCSzq3oYO1tUVqIi61Nww==", - "dev": true - }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -2397,15 +2210,6 @@ "node": ">=4" } }, - "node_modules/charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/check-error": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", @@ -2505,21 +2309,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-table3": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -2546,18 +2335,6 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/command-exists": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", @@ -2646,15 +2423,6 @@ "node": ">= 8" } }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/debug": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", @@ -2713,15 +2481,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -2740,12 +2499,6 @@ "node": ">=0.3.1" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, "node_modules/ejs": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", @@ -3181,20 +2934,6 @@ "node": ">=8.0.0" } }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fp-ts": { "version": "1.19.3", "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", @@ -3405,237 +3144,6 @@ } } }, - "node_modules/hardhat-gas-reporter": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-2.2.1.tgz", - "integrity": "sha512-3AfPDGBn6VPmRKU65W28qVvG5x+qYL2gH9PAivd31oGj/ZHpZTutqXh6wq46993Vz35rnPDnrGo028U4/NP/Vw==", - "dev": true, - "dependencies": { - "@ethersproject/abi": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/units": "^5.7.0", - "@solidity-parser/parser": "^0.18.0", - "axios": "^1.6.7", - "brotli-wasm": "^2.0.1", - "chalk": "4.1.2", - "cli-table3": "^0.6.3", - "ethereum-cryptography": "^2.1.3", - "glob": "^10.3.10", - "jsonschema": "^1.4.1", - "lodash": "^4.17.21", - "markdown-table": "2.0.0", - "sha1": "^1.1.1", - "viem": "2.7.14" - }, - "peerDependencies": { - "hardhat": "^2.16.0" - } - }, - "node_modules/hardhat-gas-reporter/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", - "dev": true, - "dependencies": { - "@noble/hashes": "1.4.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/hardhat-gas-reporter/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "dev": true, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/hardhat-gas-reporter/node_modules/@scure/bip32": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", - "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", - "dev": true, - "dependencies": { - "@noble/curves": "~1.4.0", - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/hardhat-gas-reporter/node_modules/@scure/bip39": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", - "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", - "dev": true, - "dependencies": { - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/hardhat-gas-reporter/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/hardhat-gas-reporter/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/hardhat-gas-reporter/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/hardhat-gas-reporter/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/hardhat-gas-reporter/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/hardhat-gas-reporter/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", - "dev": true, - "dependencies": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" - } - }, - "node_modules/hardhat-gas-reporter/node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/hardhat-gas-reporter/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/hardhat-gas-reporter/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/hardhat-gas-reporter/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/hardhat-gas-reporter/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/hardhat-gas-reporter/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/hardhat/node_modules/ws": { "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", @@ -3990,21 +3498,6 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, - "node_modules/isows": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.3.tgz", - "integrity": "sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wagmi-dev" - } - ], - "peerDependencies": { - "ws": "*" - } - }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -4159,21 +3652,6 @@ "node": ">=8" } }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/jake": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.1.tgz", @@ -4321,15 +3799,6 @@ "underscore": "1.12.1" } }, - "node_modules/jsonschema": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", - "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/keccak": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", @@ -4494,12 +3963,6 @@ "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", "dev": true }, - "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true - }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -4521,19 +3984,6 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "node_modules/markdown-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", - "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", - "dev": true, - "dependencies": { - "repeat-string": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -4554,27 +4004,6 @@ "node": ">= 0.10.0" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -4598,15 +4027,6 @@ "node": "*" } }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/mnemonist": { "version": "0.38.5", "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", @@ -5193,12 +4613,6 @@ "node": ">=8" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true - }, "node_modules/path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -5232,22 +4646,6 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -5408,12 +4806,6 @@ "node": ">=8" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, "node_modules/r1csfile": { "version": "0.0.47", "resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.47.tgz", @@ -5497,15 +4889,6 @@ "node": ">=4" } }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -5662,19 +5045,6 @@ "sha.js": "bin.js" } }, - "node_modules/sha1": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", - "integrity": "sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA==", - "dev": true, - "dependencies": { - "charenc": ">= 0.0.1", - "crypt": ">= 0.0.1" - }, - "engines": { - "node": "*" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5875,21 +5245,6 @@ "node": ">=8" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -5902,19 +5257,6 @@ "node": ">=8" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -6244,90 +5586,6 @@ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, - "node_modules/viem": { - "version": "2.7.14", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.7.14.tgz", - "integrity": "sha512-5b1KB1gXli02GOQHZIUsRluNUwssl2t4hqdFAzyWPwJ744N83jAOBOjOkrGz7K3qMIv9b0GQt3DoZIErSQTPkQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "dependencies": { - "@adraffy/ens-normalize": "1.10.0", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.2", - "@scure/bip32": "1.3.2", - "@scure/bip39": "1.2.1", - "abitype": "1.0.0", - "isows": "1.0.3", - "ws": "8.13.0" - }, - "peerDependencies": { - "typescript": ">=5.0.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/viem/node_modules/@adraffy/ens-normalize": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", - "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==", - "dev": true - }, - "node_modules/viem/node_modules/@scure/bip32": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz", - "integrity": "sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==", - "dev": true, - "dependencies": { - "@noble/curves": "~1.2.0", - "@noble/hashes": "~1.3.2", - "@scure/base": "~1.1.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/viem/node_modules/@scure/bip39": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", - "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", - "dev": true, - "dependencies": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/viem/node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/wasmbuilder": { "version": "0.0.16", "resolved": "https://registry.npmjs.org/wasmbuilder/-/wasmbuilder-0.0.16.tgz", @@ -6410,57 +5668,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", diff --git a/src/core/templates/verifier_plonk.vy.ejs b/src/core/templates/verifier_plonk.vy.ejs new file mode 100644 index 0000000..14d6b07 --- /dev/null +++ b/src/core/templates/verifier_plonk.vy.ejs @@ -0,0 +1,646 @@ +# pragma version ~=0.4.0 + +# AUTOGENERATED FILE BY HARDHAT-ZKIT. DO NOT EDIT. + +# Omega +W1: constant(uint256) = <%=w%> +# Scalar field size +BASE_FIELD_SIZE: constant(uint256) = 21888242871839275222246405745257275088548364400416034343698204186575808495617 +# Base field size +QF: constant(uint256) = 21888242871839275222246405745257275088696311157297823662689037894645226208583 + +# [1]_1 +G1_X: constant(uint256) = 1 +G1_Y: constant(uint256) = 2 +# [1]_2 +G2_X1: constant(uint256) = 10857046999023057135944570762232829481370756359578518086990519993285655852781 +G2_X2: constant(uint256) = 11559732032986387107991004021392285783925812861821192530917403151452391805634 +G2_Y1: constant(uint256) = 8495653923123431417604973247489272438418190587263600148770280649306958101930 +G2_Y2: constant(uint256) = 4082367875863433681332203403145435568316851327593401208105741076214120093531 + +# Verification Key data +N: constant(uint256) = <%=2**power%> +N_PUBLIC: constant(uint16) = <%=nPublic%> +N_LAGRANGE: constant(uint16) = <%=nPublic%> + +QM_X: constant(uint256) = <%=Qm[0]%> +QM_Y: constant(uint256) = <%=Qm[0] == "0" ? "0" : Qm[1]%> +QL_X: constant(uint256) = <%=Ql[0]%> +QL_Y: constant(uint256) = <%=Ql[0] == "0" ? "0" : Ql[1]%> +QR_X: constant(uint256) = <%=Qr[0]%> +QR_Y: constant(uint256) = <%=Qr[0] == "0" ? "0" : Qr[1]%> +QO_X: constant(uint256) = <%=Qo[0]%> +QO_Y: constant(uint256) = <%=Qo[0] == "0" ? "0" : Qo[1]%> +QC_X: constant(uint256) = <%=Qc[0]%> +QC_Y: constant(uint256) = <%=Qc[0] == "0" ? "0" : Qc[1]%> +S1_X: constant(uint256) = <%=S1[0]%> +S1_Y: constant(uint256) = <%=S1[0] == "0" ? "0" : S1[1]%> +S2_X: constant(uint256) = <%=S2[0]%> +S2_Y: constant(uint256) = <%=S2[0] == "0" ? "0" : S2[1]%> +S3_X: constant(uint256) = <%=S3[0]%> +S3_Y: constant(uint256) = <%=S3[0] == "0" ? "0" : S3[1]%> +K1: constant(uint256) = <%=k1%> +K2: constant(uint256) = <%=k2%> +X2_X1: constant(uint256) = <%=X_2[0][0]%> +X2_X2: constant(uint256) = <%=X_2[0][1]%> +X2_Y1: constant(uint256) = <%=X_2[1][0]%> +X2_Y2: constant(uint256) = <%=X_2[1][1]%> + +# Proof values offsets +# Byte offset of every parameter of the proof array +# Polynomial commitments +P_A: constant(uint16) = 0 +P_B: constant(uint16) = 2 +P_C: constant(uint16) = 4 +P_Z: constant(uint16) = 6 +P_T1: constant(uint16) = 8 +P_T2: constant(uint16) = 10 +P_T3: constant(uint16) = 12 +P_WX_I: constant(uint16) = 14 +P_WX_IW: constant(uint16) = 16 + +# Opening evaluations +P_EVAL_A: constant(uint16) = 18 +P_EVAL_B: constant(uint16) = 19 +P_EVAL_C: constant(uint16) = 20 +P_EVAL_S1: constant(uint16) = 21 +P_EVAL_S2: constant(uint16) = 22 +P_EVAL_ZW: constant(uint16) = 23 + +# Memory data +# Challenges +P_ALPHA: constant(uint16) = 0 +P_BETA: constant(uint16) = 1 +P_GAMMA: constant(uint16) = 2 +P_XI: constant(uint16) = 3 +P_XIN: constant(uint16) = 4 +P_BETA_XI: constant(uint16) = 5 +P_V1: constant(uint16) = 6 +P_V2: constant(uint16) = 7 +P_V3: constant(uint16) = 8 +P_V4: constant(uint16) = 9 +P_V5: constant(uint16) = 10 +P_U: constant(uint16) = 11 + +P_PI: constant(uint16) = 12 +P_EVAL_R0: constant(uint16) = 13 +P_D: constant(uint16) = 14 +P_F: constant(uint16) = 16 +P_E: constant(uint16) = 18 +P_TMP: constant(uint16) = 20 +P_ALPHA2: constant(uint16) = 22 +P_ZH: constant(uint16) = 23 +P_ZH_INV: constant(uint16) = 24 + +P_EVAL_L1: constant(uint16) = 25 + +P_TOTAL_SIZE: constant(uint16) = <%=800+nPublic%> + +EC_ADD_PRECOMPILED_ADDRESS: constant(address) = 0x0000000000000000000000000000000000000006 +EC_MUL_PRECOMPILED_ADDRESS: constant(address) = 0x0000000000000000000000000000000000000007 +EC_PAIRING_PRECOMPILED_ADDRESS: constant(address) = 0x0000000000000000000000000000000000000008 + + +@pure +@external +def verifyProof(proofArr: uint256[24], publicSignals: uint256[<%=nPublic%>]) -> bool: + if not self._checkInput(proofArr): + return False + + p: uint256[P_TOTAL_SIZE] = self._calculateChallenges(proofArr, publicSignals) + + p = self._calculateLagrange(p) + + p[P_PI] = self._calculatePI(p, publicSignals) + p[P_EVAL_R0] = self._calculateR0(p, proofArr) + + success: bool = True + tmpPoint: uint256[2] = [0, 0] + + success, tmpPoint = self._calculateD(p, proofArr) + if not success: + return False + + p[P_D] = tmpPoint[0] + p[P_D + 1] = tmpPoint[1] + + success, tmpPoint = self._calculateF(p, proofArr) + if not success: + return False + + p[P_F] = tmpPoint[0] + p[P_F + 1] = tmpPoint[1] + + success, tmpPoint = self._calculateE(p, proofArr) + if not success: + return False + + p[P_E] = tmpPoint[0] + p[P_E + 1] = tmpPoint[1] + + return self._checkPairing(p, proofArr) + + +@pure +@internal +def _ecadd(a: uint256[2], b: uint256[2]) -> (bool, uint256[2]): + success: bool = True + response: Bytes[64] = b"" + success, response = raw_call( + EC_ADD_PRECOMPILED_ADDRESS, + abi_encode(a, b), + max_outsize=64, + is_static_call=True, + revert_on_failure=False + ) + + if not success: + return (False, [0, 0]) + + x: uint256 = convert(slice(response, 0, 32), uint256) + y: uint256 = convert(slice(response, 32, 32), uint256) + + return (True, [x, y]) + + +@pure +@internal +def _ecmul(p: uint256[2], s: uint256) -> (bool, uint256[2]): + success: bool = True + response: Bytes[64] = b"" + success, response = raw_call( + EC_MUL_PRECOMPILED_ADDRESS, + abi_encode(p, s), + max_outsize=64, + is_static_call=True, + revert_on_failure=False + ) + + if not success: + return (False, [0, 0]) + + x: uint256 = convert(slice(response, 0, 32), uint256) + y: uint256 = convert(slice(response, 32, 32), uint256) + + return (True, [x, y]) + + +@pure +@internal +def _inverse(a: uint256, q: uint256) -> uint256: + t: int256 = 0 + newt: int256 = 1 + r: uint256 = q + newr: uint256 = a + quotient: uint256 = 0 + aux: int256 = 0 + + for _: uint256 in range(256): + if newr == 0: + break + + quotient = r // newr + aux = t - convert(quotient, int256) * newt + t = newt + newt = aux + + aux = convert(r - quotient * newr, int256) + r = newr + newr = convert(aux, uint256) + + assert r <= 1, "Inverse does not exist." + + if t < 0: + t += convert(q, int256) + + return convert(t, uint256) + + +@pure +@internal +def _inverseArray(pVals: uint256[<%=nPublic+1%>]) -> uint256[<%=nPublic+1%>]: + acc: uint256 = pVals[0] + inverses: uint256[<%=nPublic+1%>] = empty(uint256[<%=nPublic+1%>]) + pAux: uint256[<%=nPublic+1%>] = empty(uint256[<%=nPublic+1%>]) + + for i: uint256 in range(1, <%=nPublic+1%>): + pAux[i] = acc + acc = uint256_mulmod(acc, pVals[i], BASE_FIELD_SIZE) + + inv_total: uint256 = self._inverse(acc, BASE_FIELD_SIZE) + + for i: uint256 in range(<%=nPublic%>): + inverses[<%=nPublic%> - i] = uint256_mulmod(inv_total, pAux[<%=nPublic%> - i], BASE_FIELD_SIZE) + inv_total = uint256_mulmod(inv_total, pVals[<%=nPublic%> - i], BASE_FIELD_SIZE) + + inverses[0] = inv_total + + return inverses + + +@pure +@internal +def _checkInput(proof: uint256[24]) -> bool: + if proof[P_EVAL_A] >= BASE_FIELD_SIZE: + return False + + if proof[P_EVAL_B] >= BASE_FIELD_SIZE: + return False + + if proof[P_EVAL_C] >= BASE_FIELD_SIZE: + return False + + if proof[P_EVAL_S1] >= BASE_FIELD_SIZE: + return False + + if proof[P_EVAL_S2] >= BASE_FIELD_SIZE: + return False + + if proof[P_EVAL_ZW] >= BASE_FIELD_SIZE: + return False + + return True + + +@pure +@internal +def _calculateChallenges(proof: uint256[24], pubSignals: uint256[<%=nPublic%>]) -> uint256[P_TOTAL_SIZE]: + mIn<%=22+nPublic%>: uint256[<%=22+nPublic%>] = [ + QM_X, QM_Y, QL_X, QL_Y, QR_X, QR_Y, QO_X, QO_Y, QC_X, QC_Y, S1_X, S1_Y, S2_X, S2_Y, S3_X, S3_Y, + <% for (let i = 0; i < nPublic; i++) { %>pubSignals[<%=i%>], <% } %> + proof[P_A], proof[P_A + 1], proof[P_B], proof[P_B + 1], proof[P_C], proof[P_C + 1], + ] + + beta: uint256 = convert(keccak256(abi_encode(mIn<%=22+nPublic%>)), uint256) % BASE_FIELD_SIZE + + p: uint256[P_TOTAL_SIZE] = empty(uint256[P_TOTAL_SIZE]) + p[P_BETA] = beta + + # challenges.gamma + p[P_GAMMA] = convert(keccak256(abi_encode(p[P_BETA])), uint256) % BASE_FIELD_SIZE + + # challenges.alpha + mIn4: uint256[4] = [beta, p[P_GAMMA], proof[P_Z], proof[P_Z + 1]] + aux: uint256 = convert(keccak256(abi_encode(mIn4)), uint256) % BASE_FIELD_SIZE + p[P_ALPHA] = aux + p[P_ALPHA2] = uint256_mulmod(aux, aux, BASE_FIELD_SIZE) + + # challenges.xi + mIn7: uint256[7] = [aux, proof[P_T1], proof[P_T1 + 1], proof[P_T2], proof[P_T2 + 1], proof[P_T3], proof[P_T3 + 1]] + aux = convert(keccak256(abi_encode(mIn7)), uint256) % BASE_FIELD_SIZE + p[P_XI] = aux + + # challenges.v + mIn7 = [ + aux, proof[P_EVAL_A], proof[P_EVAL_B], proof[P_EVAL_C], proof[P_EVAL_S1], proof[P_EVAL_S2], proof[P_EVAL_ZW] + ] + v1: uint256 = convert(keccak256(abi_encode(mIn7)), uint256) % BASE_FIELD_SIZE + p[P_V1] = v1 + + # challenges.v^2, challenges.v^3, challenges.v^4, challenges.v^5 + p[P_V2] = uint256_mulmod(v1, v1, BASE_FIELD_SIZE) + p[P_V3] = uint256_mulmod(p[P_V2], v1, BASE_FIELD_SIZE) + p[P_V4] = uint256_mulmod(p[P_V3], v1, BASE_FIELD_SIZE) + p[P_V5] = uint256_mulmod(p[P_V4], v1, BASE_FIELD_SIZE) + + # challenges.beta * challenges.xi + p[P_BETA_XI] = uint256_mulmod(beta, aux, BASE_FIELD_SIZE) + + # challenges.xi^n + <%for (let i=0; i + aux = uint256_mulmod(aux, aux, BASE_FIELD_SIZE)<% } %> + p[P_XIN] = aux + + # Zh + aux = (aux - 1 + BASE_FIELD_SIZE) % BASE_FIELD_SIZE + p[P_ZH] = aux + p[P_ZH_INV] = aux + + # challenges.u + mIn4 = [proof[P_WX_I], proof[P_WX_I + 1], proof[P_WX_IW], proof[P_WX_IW + 1]] + p[P_U] = convert(keccak256(abi_encode(mIn4)), uint256) % BASE_FIELD_SIZE + + return p + + +@pure +@internal +def _evaluateLagrange(w: uint256, xi: uint256) -> uint256: + return uint256_mulmod(N, (xi + BASE_FIELD_SIZE - w) % BASE_FIELD_SIZE, BASE_FIELD_SIZE) + + +@pure +@internal +def _calculateLagrange(p: uint256[P_TOTAL_SIZE]) -> uint256[P_TOTAL_SIZE]: + w: uint256 = 1 + + for i: uint16 in range(1, <%=nPublic+1%>): + p[P_EVAL_L1 + (i - 1)] = self._evaluateLagrange(w, p[P_XI]) + w = uint256_mulmod(w, W1, BASE_FIELD_SIZE) + + pointsToInverse: uint256[<%=nPublic+1%>] = empty(uint256[<%=nPublic+1%>]) + for i: uint16 in range(<%=nPublic+1%>): + pointsToInverse[i] = p[P_ZH_INV + i] + + inverses: uint256[<%=nPublic+1%>] = self._inverseArray(pointsToInverse) + + for i: uint16 in range(<%=nPublic+1%>): + p[P_ZH_INV + i] = inverses[i] + + zh: uint256 = p[P_ZH] + w = 1 + + for i: uint16 in range(1, <%=nPublic+1%>): + p[P_EVAL_L1 + (i - 1)] = uint256_mulmod( + uint256_mulmod(p[P_EVAL_L1 + (i - 1)], zh, BASE_FIELD_SIZE), + w, + BASE_FIELD_SIZE + ) + w = uint256_mulmod(w, W1, BASE_FIELD_SIZE) + + return p + + +@pure +@internal +def _calculatePI(p: uint256[P_TOTAL_SIZE], pPub: uint256[<%=nPublic%>]) -> uint256: + pl: uint256 = 0 + + for i: uint16 in range(<%=nPublic%>): + pl = (pl + BASE_FIELD_SIZE - uint256_mulmod(p[P_EVAL_L1 + i], pPub[i], BASE_FIELD_SIZE)) % BASE_FIELD_SIZE + + return pl + + +@pure +@internal +def _calculateR0(p: uint256[P_TOTAL_SIZE], proof: uint256[24]) -> uint256: + e1: uint256 = p[P_PI] + + e2: uint256 = uint256_mulmod(p[P_EVAL_L1], p[P_ALPHA2], BASE_FIELD_SIZE) + + e3a: uint256 = uint256_addmod( + proof[P_EVAL_A], + uint256_mulmod(p[P_BETA], proof[P_EVAL_S1], BASE_FIELD_SIZE), + BASE_FIELD_SIZE + ) + e3a = uint256_addmod(e3a, p[P_GAMMA], BASE_FIELD_SIZE) + + e3b: uint256 = uint256_addmod( + proof[P_EVAL_B], + uint256_mulmod(p[P_BETA], proof[P_EVAL_S2], BASE_FIELD_SIZE), + BASE_FIELD_SIZE + ) + e3b = uint256_addmod(e3b, p[P_GAMMA], BASE_FIELD_SIZE) + + e3c: uint256 = uint256_addmod(proof[P_EVAL_C], p[P_GAMMA], BASE_FIELD_SIZE) + + e3: uint256 = uint256_mulmod(uint256_mulmod(e3a, e3b, BASE_FIELD_SIZE), e3c, BASE_FIELD_SIZE) + e3 = uint256_mulmod(e3, proof[P_EVAL_ZW], BASE_FIELD_SIZE) + e3 = uint256_mulmod(e3, p[P_ALPHA], BASE_FIELD_SIZE) + + r0: uint256 = uint256_addmod(e1, BASE_FIELD_SIZE - e2, BASE_FIELD_SIZE) + return uint256_addmod(r0, BASE_FIELD_SIZE - e3, BASE_FIELD_SIZE) + + +@pure +@internal +def _g1_mulAccC(pR: uint256[2], point: uint256[2], s: uint256) -> (bool, uint256[2]): + success: bool = True + mP: uint256[2] = [0, 0] + + success, mP = self._ecmul(point, s) + + return self._ecadd(mP, pR) + + +@pure +@internal +def _calculateD(p: uint256[P_TOTAL_SIZE], proof: uint256[24]) -> (bool, uint256[2]): + success: bool = True + pd: uint256[2] = [QC_X, QC_Y] + + success, pd = self._g1_mulAccC(pd, [QM_X, QM_Y], uint256_mulmod(proof[P_EVAL_A], proof[P_EVAL_B], BASE_FIELD_SIZE)) + if not success: + return (False, [0, 0]) + + success, pd = self._g1_mulAccC(pd, [QL_X, QL_Y], proof[P_EVAL_A]) + if not success: + return (False, [0, 0]) + + success, pd = self._g1_mulAccC(pd, [QR_X, QR_Y], proof[P_EVAL_B]) + if not success: + return (False, [0, 0]) + + success, pd = self._g1_mulAccC(pd, [QO_X, QO_Y], proof[P_EVAL_C]) + if not success: + return (False, [0, 0]) + + val1: uint256 = uint256_addmod( + uint256_addmod(proof[P_EVAL_A], p[P_BETA_XI], BASE_FIELD_SIZE), + p[P_GAMMA], + BASE_FIELD_SIZE + ) + + val2: uint256 = uint256_addmod( + uint256_addmod(proof[P_EVAL_B], uint256_mulmod(p[P_BETA_XI], K1, BASE_FIELD_SIZE), BASE_FIELD_SIZE), + p[P_GAMMA], + BASE_FIELD_SIZE + ) + + val3: uint256 = uint256_addmod( + uint256_addmod(proof[P_EVAL_C], uint256_mulmod(p[P_BETA_XI], K2, BASE_FIELD_SIZE), BASE_FIELD_SIZE), + p[P_GAMMA], + BASE_FIELD_SIZE + ) + + d2a: uint256 = uint256_mulmod( + uint256_mulmod(uint256_mulmod(val1, val2, BASE_FIELD_SIZE), val3, BASE_FIELD_SIZE), + p[P_ALPHA], + BASE_FIELD_SIZE + ) + + d2b: uint256 = uint256_mulmod(p[P_EVAL_L1], p[P_ALPHA2], BASE_FIELD_SIZE) + + mP: uint256[2] = [0, 0] + + success, mP = self._ecmul( + [proof[P_Z], proof[P_Z + 1]], + uint256_addmod(uint256_addmod(d2a, d2b, BASE_FIELD_SIZE), p[P_U], BASE_FIELD_SIZE) + ) + if not success: + return (False, [0, 0]) + + val1 = uint256_addmod( + uint256_addmod(proof[P_EVAL_A], uint256_mulmod(p[P_BETA], proof[P_EVAL_S1], BASE_FIELD_SIZE), BASE_FIELD_SIZE), + p[P_GAMMA], + BASE_FIELD_SIZE + ) + + val2 = uint256_addmod( + uint256_addmod(proof[P_EVAL_B], uint256_mulmod(p[P_BETA], proof[P_EVAL_S2], BASE_FIELD_SIZE), BASE_FIELD_SIZE), + p[P_GAMMA], + BASE_FIELD_SIZE + ) + + val3 = uint256_mulmod( + uint256_mulmod(p[P_ALPHA], p[P_BETA], BASE_FIELD_SIZE), + proof[P_EVAL_ZW], + BASE_FIELD_SIZE + ) + + success, mP = self._ecmul( + [proof[P_Z], proof[P_Z + 1]], + uint256_addmod(uint256_addmod(d2a, d2b, BASE_FIELD_SIZE), p[P_U], BASE_FIELD_SIZE) + ) + if not success: + return (False, [0, 0]) + + success, pd = self._ecadd(pd, mP) + if not success: + return (False, [0, 0]) + + success, mP = self._ecmul( + [S3_X, S3_Y], + uint256_mulmod(uint256_mulmod(val1, val2, BASE_FIELD_SIZE), val3, BASE_FIELD_SIZE) + ) + mP[1] = (QF - mP[1]) % QF + + success, pd = self._ecadd(pd, mP) + if not success: + return (False, [0, 0]) + + pd2: uint256[2] = [proof[P_T1], proof[P_T1 + 1]] + success, pd2 = self._g1_mulAccC(pd2, [proof[P_T2], proof[P_T2 + 1]], p[P_XIN]) + if not success: + return (False, [0, 0]) + + xin2: uint256 = uint256_mulmod(p[P_XIN], p[P_XIN], BASE_FIELD_SIZE) + success, pd2 = self._g1_mulAccC(pd2, [proof[P_T3], proof[P_T3 + 1]], xin2) + if not success: + return (False, [0, 0]) + + success, mP = self._ecmul(pd2, p[P_ZH]) + mP[1] = (QF - mP[1]) % QF + + return self._ecadd(pd, mP) + + +@pure +@internal +def _calculateF(p: uint256[P_TOTAL_SIZE], proof: uint256[24]) -> (bool, uint256[2]): + success: bool = True + pf: uint256[2] = [p[P_D], p[P_D + 1]] + + success, pf = self._g1_mulAccC(pf, [proof[P_A], proof[P_A + 1]], p[P_V1]) + if not success: + return (False, [0, 0]) + + success, pf = self._g1_mulAccC(pf, [proof[P_B], proof[P_B + 1]], p[P_V2]) + if not success: + return (False, [0, 0]) + + success, pf = self._g1_mulAccC(pf, [proof[P_C], proof[P_C + 1]], p[P_V3]) + if not success: + return (False, [0, 0]) + + success, pf = self._g1_mulAccC(pf, [S1_X, S1_Y], p[P_V4]) + if not success: + return (False, [0, 0]) + + return self._g1_mulAccC(pf, [S2_X, S2_Y], p[P_V5]) + + +@pure +@internal +def _calculateE(p: uint256[P_TOTAL_SIZE], proof: uint256[24]) -> (bool, uint256[2]): + s: uint256 = (BASE_FIELD_SIZE - p[P_EVAL_R0]) % BASE_FIELD_SIZE + + s = uint256_addmod(s, uint256_mulmod(proof[P_EVAL_A], p[P_V1], BASE_FIELD_SIZE), BASE_FIELD_SIZE) + s = uint256_addmod(s, uint256_mulmod(proof[P_EVAL_B], p[P_V2], BASE_FIELD_SIZE), BASE_FIELD_SIZE) + s = uint256_addmod(s, uint256_mulmod(proof[P_EVAL_C], p[P_V3], BASE_FIELD_SIZE), BASE_FIELD_SIZE) + s = uint256_addmod(s, uint256_mulmod(proof[P_EVAL_S1], p[P_V4], BASE_FIELD_SIZE), BASE_FIELD_SIZE) + s = uint256_addmod(s, uint256_mulmod(proof[P_EVAL_S2], p[P_V5], BASE_FIELD_SIZE), BASE_FIELD_SIZE) + s = uint256_addmod(s, uint256_mulmod(proof[P_EVAL_ZW], p[P_U], BASE_FIELD_SIZE), BASE_FIELD_SIZE) + + return self._ecmul([G1_X, G1_Y], s) + + +@pure +@internal +def _checkPairing(p: uint256[P_TOTAL_SIZE], proof: uint256[24]) -> bool: + mIn: uint256[12] = empty(uint256[12]) + + success: bool = True + mP: uint256[2] = [0, 0] + + # A1 + success, mP = self._ecmul([proof[P_WX_IW], proof[P_WX_IW + 1]], p[P_U]) + if not success: + return False + + aP: uint256[2] = [0, 0] + success, aP = self._ecadd([proof[P_WX_I], proof[P_WX_I + 1]], mP) + if not success: + return False + + mIn[0] = aP[0] + mIn[1] = (QF - aP[1]) % QF + + # [X]_2 + mIn[2] = X2_X2 + mIn[3] = X2_X1 + mIn[4] = X2_Y2 + mIn[5] = X2_Y1 + + # B1 + success, mP = self._ecmul([proof[P_WX_I], proof[P_WX_I + 1]], p[P_XI]) + if not success: + return False + + mIn[6] = mP[0] + mIn[7] = mP[1] + + s: uint256 = uint256_mulmod(p[P_U], p[P_XI], BASE_FIELD_SIZE) + s = uint256_mulmod(s, W1, BASE_FIELD_SIZE) + + success, mP = self._ecmul([proof[P_WX_IW], proof[P_WX_IW + 1]], s) + if not success: + return False + + success, aP = self._ecadd([mIn[6], mIn[7]], mP) + if not success: + return False + + success, aP = self._ecadd(aP, [p[P_F], p[P_F + 1]]) + if not success: + return False + + p[P_E + 1] = (QF - p[P_E + 1]) % QF + + success, aP = self._ecadd(aP, [p[P_E], p[P_E + 1]]) + if not success: + return False + + mIn[6] = aP[0] + mIn[7] = aP[1] + + # [1]_2 + mIn[8] = G2_X2 + mIn[9] = G2_X1 + mIn[10] = G2_Y2 + mIn[11] = G2_Y1 + + response: Bytes[32] = b"" + success, response = raw_call( + EC_PAIRING_PRECOMPILED_ADDRESS, + abi_encode(mIn), + max_outsize=32, + is_static_call=True, + revert_on_failure=False + ) + + if not success: + return False + + return convert(response, bool) diff --git a/test/CircuitZKit.test.ts b/test/CircuitZKit.test.ts index 690e39b..69eaf69 100644 --- a/test/CircuitZKit.test.ts +++ b/test/CircuitZKit.test.ts @@ -223,7 +223,7 @@ describe("CircuitZKit", () => { expect(await verifier.verifyProof(...data)).to.be.true; }); - it("should correctly create verifier and verify 'plonk' proof", async function () { + it("should correctly create Solidity verifier and verify 'plonk' proof", async function () { const circuitName = "Multiplier"; const verifierDirPath = getVerifiersDirFullPath(); const artifactsDirFullPath = getArtifactsFullPath(`${circuitName}.circom`); @@ -257,6 +257,42 @@ describe("CircuitZKit", () => { expect(await verifier.verifyProof(...data)).to.be.true; }); + it("should correctly create Vyper verifier and verify 'plonk' proof", async function () { + const circuitName = "MultiDimensionalArray"; + const verifierDirPath = getVerifiersDirFullPath(); + const artifactsDirFullPath = getArtifactsFullPath(`${circuitName}.circom`); + + const mdArrayCircuit = getCircuitZKit<"plonk">(circuitName, "plonk", { + circuitName, + circuitArtifactsPath: artifactsDirFullPath, + verifierDirPath, + }); + + const expectedVerifierFilePath = path.join(verifierDirPath, `${mdArrayCircuit.getVerifierName()}.vy`); + + await mdArrayCircuit.createVerifier("vy"); + expect(fs.existsSync(expectedVerifierFilePath)).to.be.true; + + await this.hre.run("compile", { quiet: true }); + + const a = 2; + const b = [ + [3, 1], + [44, 2], + ]; + + const proof: any = await mdArrayCircuit.generateProof({ a, b }); + + expect(await mdArrayCircuit.verifyProof(proof)).to.be.true; + + let data = await mdArrayCircuit.generateCalldata(proof); + + const MdArrayVerifierFactory = await this.hre.ethers.getContractFactory("MultiDimensionalArrayPlonkVerifier"); + const verifier = await MdArrayVerifierFactory.deploy(); + + expect(await verifier.verifyProof(...data)).to.be.true; + }); + it("should correctly create verifier several times", async () => { const circuitName = "Multiplier"; const verifierDirPath = getVerifiersDirFullPath(); diff --git a/test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray.groth16.vkey.json b/test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray.groth16.vkey.json new file mode 100644 index 0000000..0b9e3e9 --- /dev/null +++ b/test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray.groth16.vkey.json @@ -0,0 +1 @@ +{"protocol":"groth16","curve":"bn128","nPublic":10,"vk_alpha_1":["20491192805390485299153009773594534940189261866228447918068658471970481763042","9383485363053290200918347156157836566562967994039712273449902621266178545958","1"],"vk_beta_2":[["6375614351688725206403948262868962793625744043794305715222011528459656738731","4252822878758300859123897981450591353533073413197771768651442665752259397132"],["10505242626370262277552901082094356697409835680220590971873171140371331206856","21847035105528745403288232691147584728191162732299865338377159692350059136679"],["1","0"]],"vk_gamma_2":[["10857046999023057135944570762232829481370756359578518086990519993285655852781","11559732032986387107991004021392285783925812861821192530917403151452391805634"],["8495653923123431417604973247489272438418190587263600148770280649306958101930","4082367875863433681332203403145435568316851327593401208105741076214120093531"],["1","0"]],"vk_delta_2":[["11121757548064786277347723654771777697589351852136688710265908558867619706034","9511594120864330497760845197961554462019421854459034930600159412099448314441"],["11128786009117993081930366203489510400564801483205509889654407453019543621040","11890586469707710102408840231956795235484070722927440244326941071149147642216"],["1","0"]],"vk_alphabeta_12":[[["2029413683389138792403550203267699914886160938906632433982220835551125967885","21072700047562757817161031222997517981543347628379360635925549008442030252106"],["5940354580057074848093997050200682056184807770593307860589430076672439820312","12156638873931618554171829126792193045421052652279363021382169897324752428276"],["7898200236362823042373859371574133993780991612861777490112507062703164551277","7074218545237549455313236346927434013100842096812539264420499035217050630853"]],[["7077479683546002997211712695946002074877511277312570035766170199895071832130","10093483419865920389913245021038182291233451549023025229112148274109565435465"],["4595479056700221319381530156280926371456704509942304414423590385166031118820","19831328484489333784475432780421641293929726139240675179672856274388269393268"],["11934129596455521040620786944827826205713621633706285934057045369193958244500","8037395052364110730298837004334506829870972346962140206007064471173334027475"]]],"IC":[["3495694661568299179878948819174043851099678885336797490532661625634509456620","16449691720535956946494884801163388207063380307723678096092208850886491784850","1"],["2054279236838943706274953313756236537292322036282609347844303283687859336981","9310409617016868204445399592192768984461464076263793259131162336791588460855","1"],["4549101963883882136918061717506048747536543905969847743955187512947029251427","286982476162680491638647191378244700891252328354935273227013602617490386723","1"],["11884708174745769330192779892650439092194966066571302312721385264001937381049","13268131990047414176823694405854210162868219587848624459696126135172990017117","1"],["9799474276727028348664964041671679914724919422982579865092122769382950313536","6713034376041512319939194002721319007645465116926144109484961044854657959476","1"],["14022296220194218890981220204229983993676986201618170329944669925145440704166","2519510297529842692804647714336136314718121866392421315400801702201549332604","1"],["11474327268813938951012760319915851216855228323616198999638918058098493270120","16500656588235391685173826059205066302968692203113601429633113299933455194629","1"],["20796238970784755517182802061293333668486710089460310703934446287285882219146","3213077213885759377398277506040700138865811142585808906555900192062143733907","1"],["4755241111656492396903273326956608795143382767922486875641623966708572717243","16619885589196258576144193149671578663463975844477089736502404890231654038593","1"],["14950193769065094782935245708676799536470457473265243091124885117312549616769","6465459252878178455071904296538722022857571708009548619696960085030101615929","1"],["385979438052586810495960114303961400723993708222649653587148950133873626122","13447321594156279890979317717555593354311661716332933890908752718991044747964","1"]]} \ No newline at end of file diff --git a/test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray.groth16.zkey b/test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray.groth16.zkey new file mode 100644 index 0000000000000000000000000000000000000000..f5656659342af3cecd562047009134f65eb939d1 GIT binary patch literal 7874 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 literal 0 HcmV?d00001 diff --git a/test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray.plonk.vkey.json b/test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray.plonk.vkey.json new file mode 100644 index 0000000..c9c77ed --- /dev/null +++ b/test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray.plonk.vkey.json @@ -0,0 +1,63 @@ +{ + "protocol": "plonk", + "curve": "bn128", + "nPublic": 10, + "power": 5, + "k1": "2", + "k2": "3", + "Qm": [ + "20725296897021676741273642056169240329285346916285158361938444652581257033543", + "19707517720670499485357295484830119779349041426479603650432203457136506504553", + "1" + ], + "Ql": [ + "17359212988294702391946214274081597524316206017774228682133243429316382466169", + "13186074013007479625987897051305103109875388027117735083702144928328328417354", + "1" + ], + "Qr": [ + "14758822207824189241801199980321211283852275118707770109155494450459528308433", + "3111427114158633020352054765874786995654636141967641700746131063752278357531", + "1" + ], + "Qo": [ + "6244574162614808265956747865576107056431639803026857745017764366785514855788", + "3702796362167115123753264446046062519683988921847065794467224235285920160499", + "1" + ], + "Qc": [ + "19044597030438802983566910140227291914987665533437629098515891922685580896837", + "4657908630292315873601421240069348459791191118362492110690688921349850751286", + "1" + ], + "S1": [ + "15429054937789019171757319325502284862527279286683877739760989574604467061479", + "7821930593052013494045041470471816095239727048579657070946420897376673917026", + "1" + ], + "S2": [ + "3173429328132607418336872096074210942038805266431548245139519027688183520874", + "15855441316377869984246871206599918935607091929588958108942938040758330929807", + "1" + ], + "S3": [ + "9040900506899513085679484076599580398059396139904684129570618813481205004777", + "16820393608784268482740650194967033277242455801099197806602971357487892770048", + "1" + ], + "X_2": [ + [ + "21831381940315734285607113342023901060522397560371972897001948545212302161822", + "17231025384763736816414546592865244497437017442647097510447326538965263639101" + ], + [ + "2388026358213174446665280700919698872609886601280537296205114254867301080648", + "11507326595632554467052522095592665270651932854513688777769618397986436103170" + ], + [ + "1", + "0" + ] + ], + "w": "4419234939496763621076330863786513495701855246241724391626358375488475697872" +} \ No newline at end of file diff --git a/test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray.plonk.zkey b/test/fixture-projects/simple-circuits/zkit/artifacts/MultiDimensionalArray.circom/MultiDimensionalArray.plonk.zkey new file mode 100644 index 0000000000000000000000000000000000000000..b437f046f2da7f5a89ac7c87e4eeeec3bf2f4724 GIT binary patch literal 95932 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 KPA$Y;;r|an<)G#O literal 0 HcmV?d00001