From db8796b757e97b459fca6935d2ac9269d09a9a91 Mon Sep 17 00:00:00 2001 From: Kyryl R Date: Thu, 5 Dec 2024 14:00:26 +0200 Subject: [PATCH] Initial commit --- .editorconfig | 11 ++ .github/ISSUE_TEMPLATE/bug-report.yml | 30 ++++ .github/ISSUE_TEMPLATE/feature-request.yml | 13 ++ .github/ISSUE_TEMPLATE/other-issue.md | 4 + .github/actions/setup/action.yml | 13 ++ .github/workflows/checks.yml | 25 ++++ .gitignore | 21 +++ .husky/pre-commit | 1 + .mocharc.json | 5 + .prettierignore | 17 +++ .prettierrc.json | 21 +++ LICENSE | 21 +++ README.md | 7 + bun.lockb | Bin 0 -> 169214 bytes circuits/Math.circom | 6 + circuits/templates/Math.circom | 18 +++ contracts/verifiers/MathVerifier.sol | 158 +++++++++++++++++++++ hardhat.config.ts | 56 ++++++++ package.json | 52 +++++++ scripts/index.ts | 2 + scripts/poseidon-sign-helpers.ts | 81 +++++++++++ scripts/utils/constants.ts | 8 ++ scripts/utils/index.ts | 2 + scripts/utils/utils.ts | 13 ++ test/Math.circuit.ts | 58 ++++++++ test/setup.ts | 5 + tsconfig.json | 18 +++ 27 files changed, 666 insertions(+) create mode 100644 .editorconfig create mode 100644 .github/ISSUE_TEMPLATE/bug-report.yml create mode 100644 .github/ISSUE_TEMPLATE/feature-request.yml create mode 100644 .github/ISSUE_TEMPLATE/other-issue.md create mode 100644 .github/actions/setup/action.yml create mode 100644 .github/workflows/checks.yml create mode 100644 .gitignore create mode 100755 .husky/pre-commit create mode 100644 .mocharc.json create mode 100644 .prettierignore create mode 100644 .prettierrc.json create mode 100644 LICENSE create mode 100644 README.md create mode 100755 bun.lockb create mode 100644 circuits/Math.circom create mode 100644 circuits/templates/Math.circom create mode 100644 contracts/verifiers/MathVerifier.sol create mode 100644 hardhat.config.ts create mode 100644 package.json create mode 100644 scripts/index.ts create mode 100644 scripts/poseidon-sign-helpers.ts create mode 100644 scripts/utils/constants.ts create mode 100644 scripts/utils/index.ts create mode 100644 scripts/utils/utils.ts create mode 100644 test/Math.circuit.ts create mode 100644 test/setup.ts create mode 100644 tsconfig.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..629a586 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +insert_final_newline = true +[*.ts] +indent_size = 2 +max_line_length = 120 +[*.sol] +indent_size = 4 +max_line_length = 99 diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 0000000..df552f0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,30 @@ +name: Bug Report +description: File a bug report +labels: ['bug'] +assignees: + - +body: + - type: markdown + attributes: + value: Thanks for taking the time to fill out this bug report! + - type: input + id: version + attributes: + label: "Project version" + placeholder: "1.2.3" + validations: + required: true + - type: textarea + id: what-happened + attributes: + label: What happened? + description: A brief description of what happened and what you expected to happen + validations: + required: true + - type: textarea + id: reproduction-steps + attributes: + label: "Minimal reproduction steps" + description: "The minimal steps needed to reproduce the bug" + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml new file mode 100644 index 0000000..c635199 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -0,0 +1,13 @@ +name: Feature request +description: Suggest a new feature +labels: ['feature'] +assignees: + - +body: + - type: textarea + id: feature-description + attributes: + label: "Describe the feature" + description: "A description of what you would like to see in the project" + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/other-issue.md b/.github/ISSUE_TEMPLATE/other-issue.md new file mode 100644 index 0000000..7115534 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/other-issue.md @@ -0,0 +1,4 @@ +--- +name: Other issue +about: Other kind of issue +--- diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml new file mode 100644 index 0000000..d9a0717 --- /dev/null +++ b/.github/actions/setup/action.yml @@ -0,0 +1,13 @@ +name: setup + +description: setup + +runs: + using: composite + steps: + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + + - name: Install packages + run: bun install + shell: bash diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml new file mode 100644 index 0000000..260b587 --- /dev/null +++ b/.github/workflows/checks.yml @@ -0,0 +1,25 @@ +name: "checks" + +on: + push: + branches: + - main + pull_request: + branches: + - main + - dev + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + + - uses: oven-sh/setup-bun@v2 + + - name: Setup + uses: ./.github/actions/setup + + - name: Run tests + run: bun run test diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ae6365c --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +node_modules +.env +.DS_Store + +# Hardhat files +cache +artifacts +coverage.json +coverage +abi +zkit + +# Typechain generated files +generated-types + +# Hardhat migrate +.storage.json +circuits/test + +IdentityAuth.witness.json +IdentityAuth.wtns diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..2defab9 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npm run lint-fix && git add -u diff --git a/.mocharc.json b/.mocharc.json new file mode 100644 index 0000000..3df7ebe --- /dev/null +++ b/.mocharc.json @@ -0,0 +1,5 @@ +{ + "require": ["ts-node/register", "./test/setup.ts"], + "extension": ["ts"], + "spec": "test/**/*.spec.ts" +} diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..747c7c8 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,17 @@ +node_modules +.env +.DS_Store +package-lock.json + +# Hardhat files +cache +artifacts +coverage.json +coverage +zkit + +# Typechain generated files +generated-types + +# Hardhat migrate +.storage.json diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..51d6e3d --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,21 @@ +{ + "overrides": [ + { + "files": "*.sol", + "options": { + "printWidth": 99, + "tabWidth": 4, + "useTabs": false, + "singleQuote": false, + "bracketSpacing": false + } + }, + { + "files": "*.ts", + "options": { + "printWidth": 120, + "tabWidth": 2 + } + } + ] +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..44eebd5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 ZKDL Camp + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..9af7153 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Hardhat Zkit template + +## Usage + +This project is using [bun](https://bun.sh/) JS runtime. If you do not have it installed follow the instructions [here](https://bun.sh/docs/installation). + +Otherwise, you can delete the `bun.lockb` lock file and run `npm install` to install the dependencies. diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..02051884c6e80c26b1d8b0674ef5c91754914ffc GIT binary patch literal 169214 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 z r; +} diff --git a/contracts/verifiers/MathVerifier.sol b/contracts/verifiers/MathVerifier.sol new file mode 100644 index 0000000..b1dbeda --- /dev/null +++ b/contracts/verifiers/MathVerifier.sol @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: MIT + +/* AUTOGENERATED FILE BY HARDHAT-ZKIT. DO NOT EDIT. */ + +pragma solidity >=0.7.0 <0.9.0; + +contract MathVerifier { + /// @dev base field size + uint256 public constant BASE_FIELD_SIZE = + 21888242871839275222246405745257275088696311157297823662689037894645226208583; + + /// @dev verification key data + uint256 public constant ALPHA_X = + 20491192805390485299153009773594534940189261866228447918068658471970481763042; + uint256 public constant ALPHA_Y = + 9383485363053290200918347156157836566562967994039712273449902621266178545958; + uint256 public constant BETA_X1 = + 4252822878758300859123897981450591353533073413197771768651442665752259397132; + uint256 public constant BETA_X2 = + 6375614351688725206403948262868962793625744043794305715222011528459656738731; + uint256 public constant BETA_Y1 = + 21847035105528745403288232691147584728191162732299865338377159692350059136679; + uint256 public constant BETA_Y2 = + 10505242626370262277552901082094356697409835680220590971873171140371331206856; + uint256 public constant GAMMA_X1 = + 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 public constant GAMMA_X2 = + 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 public constant GAMMA_Y1 = + 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 public constant GAMMA_Y2 = + 8495653923123431417604973247489272438418190587263600148770280649306958101930; + uint256 public constant DELTA_X1 = + 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 public constant DELTA_X2 = + 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 public constant DELTA_Y1 = + 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 public constant DELTA_Y2 = + 8495653923123431417604973247489272438418190587263600148770280649306958101930; + + uint256 public constant IC0_X = + 7246450750923962100077445566644177421429507238279338753215624391282583293394; + uint256 public constant IC0_Y = + 19778601966845352785929137625645717352315842481501201420677797211475501180673; + uint256 public constant IC1_X = + 21489871966673422990912038207381382789455440732690519161907414590243298309365; + uint256 public constant IC1_Y = + 6950355566631655764010982136442430243610621295051493732978619100549291270591; + + /// @dev memory pointer sizes + uint16 public constant P_PUBLIC_SIGNALS_ACCUMULATOR_SIZE = 128; + uint16 public constant P_TOTAL_SIZE = 896; + + function verifyProof( + uint256[2] memory pointA_, + uint256[2][2] memory pointB_, + uint256[2] memory pointC_, + uint256[1] memory publicSignals_ + ) public view returns (bool verified_) { + assembly { + function checkField(signal_) -> res_ { + res_ := lt(signal_, BASE_FIELD_SIZE) + } + + function g1MulAdd(pR_, x_, y_, s_) -> res_ { + let pointer_ := mload(64) // free pointer + + mstore(pointer_, x_) + mstore(add(pointer_, 32), y_) + mstore(add(pointer_, 64), s_) + + res_ := staticcall(sub(gas(), 2000), 7, pointer_, 96, pointer_, 64) // ecMul + res_ := and(res_, gt(returndatasize(), 0)) // check that multiplication succeeded + + if iszero(res_) { + leave + } + + mstore(add(pointer_, 64), mload(pR_)) + mstore(add(pointer_, 96), mload(add(pR_, 32))) + + res_ := staticcall(sub(gas(), 2000), 6, pointer_, 128, pR_, 64) // ecAdd + res_ := and(res_, gt(returndatasize(), 0)) // check that addition succeeded + } + + function checkPairing(pA_, pB_, pC_, pubSignals_, pointer_) -> res_ { + let pPairing_ := add(pointer_, P_PUBLIC_SIGNALS_ACCUMULATOR_SIZE) + + mstore(pointer_, IC0_X) + mstore(add(pointer_, 32), IC0_Y) + + /// @dev compute the linear combination of public signals + if iszero(g1MulAdd(pointer_, IC1_X, IC1_Y, mload(add(pubSignals_, 0)))) { + leave + } + + /// @dev -A + mstore(pPairing_, mload(pA_)) + mstore( + add(pPairing_, 32), + mod(sub(BASE_FIELD_SIZE, mload(add(pA_, 32))), BASE_FIELD_SIZE) + ) + + /// @dev B + mstore(add(pPairing_, 64), mload(mload(pB_))) + mstore(add(pPairing_, 96), mload(add(mload(pB_), 32))) + mstore(add(pPairing_, 128), mload(mload(add(pB_, 32)))) + mstore(add(pPairing_, 160), mload(add(mload(add(pB_, 32)), 32))) + + /// @dev alpha1 + mstore(add(pPairing_, 192), ALPHA_X) + mstore(add(pPairing_, 224), ALPHA_Y) + + /// @dev beta2 + mstore(add(pPairing_, 256), BETA_X1) + mstore(add(pPairing_, 288), BETA_X2) + mstore(add(pPairing_, 320), BETA_Y1) + mstore(add(pPairing_, 352), BETA_Y2) + + /// @dev public signals + mstore(add(pPairing_, 384), mload(pointer_)) + mstore(add(pPairing_, 416), mload(add(pointer_, 32))) + + /// @dev gamma2 + mstore(add(pPairing_, 448), GAMMA_X1) + mstore(add(pPairing_, 480), GAMMA_X2) + mstore(add(pPairing_, 512), GAMMA_Y1) + mstore(add(pPairing_, 544), GAMMA_Y2) + + /// @dev C + mstore(add(pPairing_, 576), mload(pC_)) + mstore(add(pPairing_, 608), mload(add(pC_, 32))) + + /// @dev delta2 + mstore(add(pPairing_, 640), DELTA_X1) + mstore(add(pPairing_, 672), DELTA_X2) + mstore(add(pPairing_, 704), DELTA_Y1) + mstore(add(pPairing_, 736), DELTA_Y2) + + res_ := staticcall(sub(gas(), 2000), 8, pPairing_, 768, pPairing_, 32) // ecPairing + res_ := and(res_, mload(pPairing_)) // check that pairing succeeded + } + + let pointer_ := mload(64) // free pointer + mstore(64, add(pointer_, P_TOTAL_SIZE)) + + /// @dev check that all public signals are in F + verified_ := 1 + verified_ := and(verified_, checkField(mload(add(publicSignals_, 0)))) + + /// @dev check pairings + if not(iszero(verified_)) { + verified_ := checkPairing(pointA_, pointB_, pointC_, publicSignals_, pointer_) + } + } + } +} diff --git a/hardhat.config.ts b/hardhat.config.ts new file mode 100644 index 0000000..698488a --- /dev/null +++ b/hardhat.config.ts @@ -0,0 +1,56 @@ +import "@nomicfoundation/hardhat-ethers"; + +import "@solarity/chai-zkit"; +import "@solarity/hardhat-zkit"; + +import "@typechain/hardhat"; + +import "tsconfig-paths/register"; + +import { HardhatUserConfig } from "hardhat/config"; + +import * as dotenv from "dotenv"; +dotenv.config(); + +const config: HardhatUserConfig = { + networks: { + hardhat: { + initialDate: "1970-01-01T00:00:00Z", + }, + localhost: { + url: "http://127.0.0.1:8545", + gasMultiplier: 1.2, + }, + }, + zkit: { + compilationSettings: { + optimization: "O1", + }, + setupSettings: { + contributionSettings: { + contributions: 0, + }, + }, + }, + solidity: { + version: "0.8.20", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + evmVersion: "paris", + }, + }, + mocha: { + timeout: 1000000, + }, + typechain: { + outDir: "generated-types/ethers", + target: "ethers-v6", + alwaysGenerateOverloads: true, + discriminateTypes: true, + }, +}; + +export default config; diff --git a/package.json b/package.json new file mode 100644 index 0000000..9661179 --- /dev/null +++ b/package.json @@ -0,0 +1,52 @@ +{ + "name": "hardhat-zkit-template", + "version": "0.1.0", + "license": "MIT", + "author": "Distributed Lab", + "description": "", + "keywords": [ + "solidity", + "smart-contracts" + ], + "files": [ + "**/*.sol", + "!mock/**/*" + ], + "scripts": { + "prepare": "husky", + "compile": "npx hardhat compile", + "clean": "npx hardhat clean", + "test": "npx hardhat test", + "generate-types": "TYPECHAIN_FORCE=true npx hardhat typechain", + "lint-fix": "npm run lint-ts-fix && npm run lint-json-fix", + "lint-json-fix": "prettier --write \"./**/*.json\"", + "lint-ts-fix": "prettier --write \"./**/*.ts\"", + "publish-to-npm": "npm run lint-fix && bash ./scripts/publish.sh --public" + }, + "dependencies": {}, + "devDependencies": { + "@iden3/js-crypto": "^1.1.0", + "@nomicfoundation/hardhat-ethers": "^3.0.6", + "@solarity/chai-zkit": "^0.2.5", + "@solarity/hardhat-zkit": "^0.4.14", + "@typechain/ethers-v6": "^0.5.1", + "@typechain/hardhat": "^9.1.0", + "@types/chai": "^4.3.16", + "@types/chai-as-promised": "^8.0.1", + "@types/mocha": "^10.0.7", + "@types/node": "^18.16.0", + "chai": "^4.5.0", + "chai-as-promised": "^8.0.1", + "dotenv": "^16.4.5", + "ethers": "^6.13.2", + "ffjavascript": "^0.3.1", + "hardhat": "^2.22.10", + "husky": "^9.0.11", + "mocha": "^10.7.3", + "prettier": "^3.3.3", + "ts-node": "^10.9.2", + "tsconfig-paths": "^4.2.0", + "typechain": "^8.3.2", + "typescript": "^5.6.2" + } +} diff --git a/scripts/index.ts b/scripts/index.ts new file mode 100644 index 0000000..c7f3a41 --- /dev/null +++ b/scripts/index.ts @@ -0,0 +1,2 @@ +export * from "./utils"; +export * from "./poseidon-sign-helpers"; diff --git a/scripts/poseidon-sign-helpers.ts b/scripts/poseidon-sign-helpers.ts new file mode 100644 index 0000000..9f13969 --- /dev/null +++ b/scripts/poseidon-sign-helpers.ts @@ -0,0 +1,81 @@ +import { ethers, keccak256 } from "ethers"; + +// @ts-ignore +import { Scalar } from "ffjavascript"; + +import { babyJub, Poseidon } from "@iden3/js-crypto"; + +export function poseidonHash(data: string): string { + data = ethers.hexlify(data); + + const chunks = splitHexIntoChunks(data.replace("0x", ""), 64); + const inputs = chunks.map((v) => BigInt(v)); + + return ethers.toBeHex(Poseidon.hash(inputs), 32); +} + +function splitHexIntoChunks(hexString: string, chunkSize = 64) { + const regex = new RegExp(`.{1,${chunkSize}}`, "g"); + const chunks = hexString.match(regex); + + if (!chunks) { + throw new Error("Invalid hex string"); + } + + return chunks.map((chunk) => "0x" + chunk); +} + +export function buildNullifier(pk: bigint): string { + return Poseidon.hash([pk]).toString(); +} + +export function signRawPoseidon(privateKay: bigint, hash: string) { + const publicKey = babyJub.mulPointEscalar(babyJub.Base8, privateKay); + + let r = Scalar.mod(BigInt(hash), babyJub.subOrder); + const R8 = babyJub.mulPointEscalar(babyJub.Base8, r); + + const hashedMessage = Poseidon.hash([R8[0], R8[1], publicKey[0], publicKey[1], BigInt(hash)]); + const hashedMessageScalar = Scalar.e(babyJub.F.toObject(hashedMessage)); + + const S = Scalar.mod(Scalar.add(r, Scalar.mul(hashedMessageScalar, privateKay)), babyJub.subOrder); + + return { + R8: R8, + S: S, + }; +} + +export function getPublicFromPrivateKey(privateKay: string) { + let s = BigInt(privateKay); + + return babyJub.mulPointEscalar(babyJub.Base8, s); +} + +export function verifySignature( + messageHash: string, + publicKey: [bigint, bigint], + signature: { R8: [bigint, bigint]; S: bigint }, +) { + const hashedMessage = Poseidon.hash([ + signature.R8[0], + signature.R8[1], + publicKey[0], + publicKey[1], + BigInt(messageHash), + ]); + + const hashedMessageScalar = Scalar.e(babyJub.F.toObject(hashedMessage)); + + const mulR = babyJub.mulPointEscalar(publicKey, hashedMessageScalar); + const P2 = babyJub.addPoint(signature.R8, mulR); + + const P1 = babyJub.mulPointEscalar(babyJub.Base8, signature.S); + + return P1[0] === P2[0] && P1[1] === P2[1]; +} + +export const hashPersonalMessage = function (message: Uint8Array): string { + const prefix = Buffer.from(`\u0019Ethereum Signed Message:\n32`, "utf-8"); + return keccak256(Buffer.concat([prefix, message])); +}; diff --git a/scripts/utils/constants.ts b/scripts/utils/constants.ts new file mode 100644 index 0000000..ef8f907 --- /dev/null +++ b/scripts/utils/constants.ts @@ -0,0 +1,8 @@ +export const ETHER_ADDR = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; + +export const SECONDS_IN_DAY = 86400; +export const SECONDS_IN_MONTH = SECONDS_IN_DAY * 30; + +export const DECIMAL = 10n ** 18n; +export const PRECISION = 10n ** 25n; +export const PERCENTAGE_100 = PRECISION * 100n; diff --git a/scripts/utils/index.ts b/scripts/utils/index.ts new file mode 100644 index 0000000..e8a6cf9 --- /dev/null +++ b/scripts/utils/index.ts @@ -0,0 +1,2 @@ +export * from "./constants"; +export * from "./utils"; diff --git a/scripts/utils/utils.ts b/scripts/utils/utils.ts new file mode 100644 index 0000000..097bdc2 --- /dev/null +++ b/scripts/utils/utils.ts @@ -0,0 +1,13 @@ +import { ethers } from "hardhat"; + +export function wei(value: string | number | bigint, decimal: number = 18): bigint { + if (typeof value == "number" || typeof value == "bigint") { + value = value.toString(); + } + + return ethers.parseUnits(value as string, decimal); +} + +export function fromWei(value: string | number | bigint, decimal: number = 18): string { + return (BigInt(value) / 10n ** BigInt(decimal)).toString(); +} diff --git a/test/Math.circuit.ts b/test/Math.circuit.ts new file mode 100644 index 0000000..0ce85cb --- /dev/null +++ b/test/Math.circuit.ts @@ -0,0 +1,58 @@ +import { expect } from "chai"; +import { ethers, zkit } from "hardhat"; + +import { Math, PrivateMath } from "@zkit"; + +describe("Math Circuit", () => { + let math: Math; + + before(async () => { + math = await zkit.getCircuit("Math"); + }); + + it("should revert if trying to generate proof when a is not binary", async () => { + const inputs: PrivateMath = { + x1: 2n, + x2: 3n, + x3: 6n, + }; + + await expect(math.generateProof(inputs)).eventually.to.be.rejectedWith( + "Error: Assert Failed. Error in template Math_0 line: 12", + ); + }); + + it("should multiply two numbers if a = 1", async () => { + const inputs: PrivateMath = { + x1: 1n, + x2: 3n, + x3: 6n, + }; + + const proof = await math.generateProof(inputs); + expect(proof.publicSignals.r).to.equal("18"); + }); + + it("should add two numbers if a = 0", async () => { + const inputs: PrivateMath = { + x1: 0n, + x2: 3n, + x3: 6n, + }; + + const proof = await math.generateProof(inputs); + expect(proof.publicSignals.r).to.equal("9"); + }); + + it("should verify proof on-chain", async () => { + const verifier = await ethers.deployContract("MathVerifier"); + + const proof = await math.generateProof({ + x1: 1n, + x2: 3n, + x3: 6n, + }); + + expect(math).to.verifyProof(proof).useSolidityVerifier(verifier); + }); +}); diff --git a/test/setup.ts b/test/setup.ts new file mode 100644 index 0000000..bddddb1 --- /dev/null +++ b/test/setup.ts @@ -0,0 +1,5 @@ +(async () => { + const chai = await import("chai"); + const chaiAsPromised = await import("chai-as-promised"); + chai.default.use(chaiAsPromised.default); +})(); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..da992ff --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "es2022", + "module": "commonjs", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "paths": { + "@/*": ["./*"], + "@ethers-v6": ["./generated-types/ethers"], + "@zkit": ["./generated-types/zkit"], + "@test-helpers": ["./test/helpers"], + "@scripts": ["./scripts"] + } + } +}