diff --git a/foundry.toml b/foundry.toml index 93c0ddf..27c3b27 100644 --- a/foundry.toml +++ b/foundry.toml @@ -9,6 +9,9 @@ allow_paths = ["*", "/"] gas_limit = "18446744073709551615" memory_limit = 2147483648 verbosity = 3 +# via_ir = true +# optimizer = true +# optimizer_runs = 200 [rpc_endpoints] mainnet = "${MAINNET_RPC_URL}" diff --git a/package.json b/package.json index 70d0314..90808a2 100644 --- a/package.json +++ b/package.json @@ -18,9 +18,9 @@ "devDependencies": { "@rhinestone/modulekit": "~0.5.4", "@semaphore-protocol/contracts": "github:jimmychu0807/semaphore#identity-cli&path:/packages/contracts/contracts", + "@semaphore-protocol/group": "github:jimmychu0807/semaphore#identity-cli&path:/packages/group", "@semaphore-protocol/identity": "github:jimmychu0807/semaphore#identity-cli&path:/packages/identity", "@semaphore-protocol/proof": "github:jimmychu0807/semaphore#identity-cli&path:/packages/proof", - "@semaphore-protocol/group": "github:jimmychu0807/semaphore#identity-cli&path:/packages/group", "poseidon-solidity": "github:chancehudson/poseidon-solidity#main", "rimraf": "^5.0.5", "solady": "^0.0.287" @@ -41,15 +41,13 @@ "gas:report": "forge test --gas-report --mp \"./test/integration/**/*.sol\" --nmt \"test(Fuzz)?_RevertWhen_\\w{1,}?\"", "gas:snapshot": "forge snapshot --mp \"./test/integration/**/*.sol\" --nmt \"test(Fuzz)?_RevertWhen_\\w{1,}?\"", "gas:snapshot:optimized": "pnpm run build:optimized && FOUNDRY_PROFILE=test-optimized forge snapshot --mp \"./test/integration/**/*.sol\" --nmt \"test(Fork)?(Fuzz)?_RevertWhen_\\w{1,}?\"", - "lint": "pnpm lint:sol && pnpm prettier:check", "lint:sol": "forge fmt --check && pnpm solhint \"{script,src,test}/**/*.sol\"", "lint:write": "forge fmt && pnpm run prettier:write", - "prepack": "pnpm install && bash ./shell/prepare-artifacts.sh", + "lint": "pnpm lint:sol && pnpm prettier:check", "prettier:check": "prettier --no-error-on-unmatched-pattern -c \"{src,test,script}/**/*.{json,md,svg,yml}\"", "prettier:write": "prettier --no-error-on-unmatched-pattern -w \"{src,test,script}/**/*.{json,md,svg,yml}\"", "test": "forge test --ffi", - "test:lite": "FOUNDRY_PROFILE=lite forge test", - "test:optimized": "pnpm run build:optimized && FOUNDRY_PROFILE=test-optimized forge test" + "test:coverage": "forge coverage --ffi" }, "keywords": [ "account abstraction", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6e00cf4..b77e817 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -454,8 +454,8 @@ packages: '@openzeppelin/contracts@5.0.1': resolution: {integrity: sha512-yQJaT5HDp9hYOOp4jTYxMsR02gdFZFXhewX5HW9Jo4fsqSVqqyIO/xTHdWDaKX5a3pv1txmf076Lziz+sO7L1w==} - '@openzeppelin/contracts@5.1.0': - resolution: {integrity: sha512-p1ULhl7BXzjjbha5aqst+QMLY+4/LCWADXOCsmLHRM77AqiPjnd9vvUN9sosUfhL9JGKpZ0TjEGxgvnizmWGSA==} + '@openzeppelin/contracts@5.2.0': + resolution: {integrity: sha512-bxjNie5z89W1Ea0NZLZluFh8PrFNn9DH8DQlujEok2yjsOlraUPKID5p1Wk3qdNbf6XkQ1Os2RvfiHrrXLHWKA==} '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} @@ -611,8 +611,8 @@ packages: '@types/node@20.17.12': resolution: {integrity: sha512-vo/wmBgMIiEA23A/knMfn/cf37VnuF52nZh5ZoW0GWt4e4sxNquibrMRJ7UQsA06+MBx9r/H1jsI9grYjQCQlw==} - '@types/node@22.10.5': - resolution: {integrity: sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==} + '@types/node@22.10.6': + resolution: {integrity: sha512-qNiuwC4ZDAUNcY47xgaSuS92cjf8JbSUoaKS77bmLG1rU7MlATVSiw/IlrjtIyyskXBZ8KkNfjK/P5na7rgXbQ==} '@types/node@22.7.5': resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} @@ -623,8 +623,8 @@ packages: '@types/prettier@2.7.3': resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} - '@types/qs@6.9.17': - resolution: {integrity: sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==} + '@types/qs@6.9.18': + resolution: {integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==} '@types/secp256k1@4.0.6': resolution: {integrity: sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==} @@ -1593,8 +1593,8 @@ packages: jsonpath@1.1.1: resolution: {integrity: sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==} - jsonschema@1.4.1: - resolution: {integrity: sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==} + jsonschema@1.5.0: + resolution: {integrity: sha512-K+A9hhqbn0f3pJX17Q/7H6yQfD/5OXgdrR5UE12gMXCiN9D5Xq2o5mddV2QEcX/bjla99ASsAAQUyMCCRWAEhw==} keccak@3.0.4: resolution: {integrity: sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==} @@ -1939,9 +1939,9 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} - readdirp@4.0.2: - resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} - engines: {node: '>= 14.16.0'} + readdirp@4.1.1: + resolution: {integrity: sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==} + engines: {node: '>= 14.18.0'} rechoir@0.6.2: resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} @@ -2101,8 +2101,8 @@ packages: solady@0.0.287: resolution: {integrity: sha512-Cti/U83eqIB0e3UNxZvmkwrFrQCT9YLY1vhVguaWnOVLKzv/OU5tQbKLGpamUzMtcLSxaBjBdhaTlmiciGfhHg==} - solady@https://codeload.github.com/vectorized/solady/tar.gz/908472a02139e04e4c25280daca82e6c754204e8: - resolution: {tarball: https://codeload.github.com/vectorized/solady/tar.gz/908472a02139e04e4c25280daca82e6c754204e8} + solady@https://codeload.github.com/vectorized/solady/tar.gz/a1e450fbd3a9db70ea63f14a53d2f320151b4265: + resolution: {tarball: https://codeload.github.com/vectorized/solady/tar.gz/a1e450fbd3a9db70ea63f14a53d2f320151b4265} version: 0.0.292 solarray@https://codeload.github.com/sablier-labs/solarray/tar.gz/6bf10cb34cdace52a3ba5fe437e78cc82df92684: @@ -2948,7 +2948,7 @@ snapshots: '@openzeppelin/contracts@5.0.1': {} - '@openzeppelin/contracts@5.1.0': {} + '@openzeppelin/contracts@5.2.0': {} '@pkgjs/parseargs@0.11.0': optional: true @@ -2975,7 +2975,7 @@ snapshots: ds-test: https://codeload.github.com/dapphub/ds-test/tar.gz/e282159d5170298eb2455a6c05280ab5a73a4ef0 forge-std: https://codeload.github.com/foundry-rs/forge-std/tar.gz/8a225d81aa8e2e013580564588c79abb65eacc9e prettier: 2.8.8 - solady: https://codeload.github.com/vectorized/solady/tar.gz/908472a02139e04e4c25280daca82e6c754204e8 + solady: https://codeload.github.com/vectorized/solady/tar.gz/a1e450fbd3a9db70ea63f14a53d2f320151b4265 transitivePeerDependencies: - bufferutil - encoding @@ -2996,7 +2996,7 @@ snapshots: ds-test: https://codeload.github.com/dapphub/ds-test/tar.gz/e282159d5170298eb2455a6c05280ab5a73a4ef0 excessively-safe-call: '@nomad-xyz/excessively-safe-call@https://codeload.github.com/nomad-xyz/ExcessivelySafeCall/tar.gz/81cd99ce3e69117d665d7601c330ea03b97acce0' forge-std: https://codeload.github.com/foundry-rs/forge-std/tar.gz/726a6ee5fc8427a0013d6f624e486c9130c0e336 - solady: https://codeload.github.com/vectorized/solady/tar.gz/908472a02139e04e4c25280daca82e6c754204e8 + solady: https://codeload.github.com/vectorized/solady/tar.gz/a1e450fbd3a9db70ea63f14a53d2f320151b4265 solarray: https://codeload.github.com/sablier-labs/solarray/tar.gz/6bf10cb34cdace52a3ba5fe437e78cc82df92684 solhint: 5.0.3(typescript@4.9.5) transitivePeerDependencies: @@ -3169,11 +3169,11 @@ snapshots: '@types/bn.js@4.11.6': dependencies: - '@types/node': 22.10.5 + '@types/node': 22.10.6 '@types/bn.js@5.1.6': dependencies: - '@types/node': 22.10.5 + '@types/node': 22.10.6 '@types/debug@4.1.12': dependencies: @@ -3182,7 +3182,7 @@ snapshots: '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 22.10.5 + '@types/node': 22.10.6 '@types/http-cache-semantics@4.0.4': {} @@ -3198,7 +3198,7 @@ snapshots: dependencies: undici-types: 6.19.8 - '@types/node@22.10.5': + '@types/node@22.10.6': dependencies: undici-types: 6.20.0 @@ -3208,15 +3208,15 @@ snapshots: '@types/pbkdf2@3.1.2': dependencies: - '@types/node': 22.10.5 + '@types/node': 22.10.6 '@types/prettier@2.7.3': {} - '@types/qs@6.9.17': {} + '@types/qs@6.9.18': {} '@types/secp256k1@4.0.6': dependencies: - '@types/node': 22.10.5 + '@types/node': 22.10.6 '@zk-kit/artifacts@1.8.0': {} @@ -3274,7 +3274,7 @@ snapshots: accountabstraction@https://codeload.github.com/kopy-kat/account-abstraction/tar.gz/c5887153fbfe3ed09b2637cac39873f96d676f38(ethers@5.7.2)(hardhat@2.22.17(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)): dependencies: '@nomiclabs/hardhat-etherscan': 2.1.8(hardhat@2.22.17(typescript@4.9.5)) - '@openzeppelin/contracts': 5.1.0 + '@openzeppelin/contracts': 5.2.0 '@thehubbleproject/bls': 0.5.1 '@typechain/hardhat': 2.3.1(hardhat@2.22.17(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)) '@types/debug': 4.1.12 @@ -3554,7 +3554,7 @@ snapshots: chokidar@4.0.3: dependencies: - readdirp: 4.0.2 + readdirp: 4.1.1 ci-info@2.0.0: {} @@ -4188,7 +4188,7 @@ snapshots: '@ethersproject/solidity': 5.7.0 '@ethersproject/transactions': 5.7.0 '@ethersproject/wallet': 5.7.0 - '@types/qs': 6.9.17 + '@types/qs': 6.9.18 axios: 0.21.4(debug@4.4.0) chalk: 4.1.2 chokidar: 3.6.0 @@ -4431,7 +4431,7 @@ snapshots: static-eval: 2.0.2 underscore: 1.12.1 - jsonschema@1.4.1: {} + jsonschema@1.5.0: {} keccak@3.0.4: dependencies: @@ -4749,7 +4749,7 @@ snapshots: dependencies: picomatch: 2.3.1 - readdirp@4.0.2: {} + readdirp@4.1.1: {} rechoir@0.6.2: dependencies: @@ -4925,7 +4925,7 @@ snapshots: solady@0.0.287: {} - solady@https://codeload.github.com/vectorized/solady/tar.gz/908472a02139e04e4c25280daca82e6c754204e8: {} + solady@https://codeload.github.com/vectorized/solady/tar.gz/a1e450fbd3a9db70ea63f14a53d2f320151b4265: {} solarray@https://codeload.github.com/sablier-labs/solarray/tar.gz/6bf10cb34cdace52a3ba5fe437e78cc82df92684: {} @@ -4978,7 +4978,7 @@ snapshots: global-modules: 2.0.0 globby: 10.0.2 hardhat: 2.22.17(typescript@4.9.5) - jsonschema: 1.4.1 + jsonschema: 1.5.0 lodash: 4.17.21 mocha: 10.8.2 node-emoji: 1.11.0 diff --git a/src/utils/CurveBabyJubJub.sol b/src/utils/CurveBabyJubJub.sol new file mode 100644 index 0000000..698aa95 --- /dev/null +++ b/src/utils/CurveBabyJubJub.sol @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <=0.8.29; + +// ref: https://github.com/yondonfu/sol-baby-jubjub +// with: https://github.com/yondonfu/sol-baby-jubjub/pull/1 + +library CurveBabyJubJub { + // Curve parameters + // E: 168700x^2 + y^2 = 1 + 168696x^2y^2 + // A = 168700 + uint256 public constant A = 0x292FC; + // D = 168696 + uint256 public constant D = 0x292F8; + // curve order + uint256 public constant Q = + 21_888_242_871_839_275_222_246_405_745_257_275_088_548_364_400_416_034_343_698_204_186_575_808_495_617; + // Base8 point + // ref: + // https://github.com/privacy-scaling-explorations/zk-kit/blob/31c83b644857ed30983120baeff912f69a11f2e9/packages/baby-jubjub/src/baby-jubjub.ts#L19-L22 + uint256 public constant Base8x = + 5_299_619_240_641_551_281_634_865_583_518_297_030_282_874_472_190_772_894_086_521_144_482_721_001_553; + uint256 public constant Base8y = + 16_950_150_798_460_657_717_958_625_567_821_834_550_301_663_161_624_707_787_222_815_936_182_638_968_203; + + /** + * @dev Add 2 points on baby jubjub curve + * Formulae for adding 2 points on a twisted Edwards curve: + * x3 = (x1y2 + y1x2) / (1 + dx1x2y1y2) + * y3 = (y1y2 - ax1x2) / (1 - dx1x2y1y2) + */ + function pointAdd( + uint256 _x1, + uint256 _y1, + uint256 _x2, + uint256 _y2 + ) + internal + view + returns (uint256 x3, uint256 y3) + { + if (_x1 == 0 && _y1 == 1) { + return (_x2, _y2); + } + + if (_x2 == 0 && _y2 == 1) { + return (_x1, _y1); + } + + uint256 x1x2 = mulmod(_x1, _x2, Q); + uint256 y1y2 = mulmod(_y1, _y2, Q); + uint256 dx1x2y1y2 = mulmod(D, mulmod(x1x2, y1y2, Q), Q); + uint256 x3Num = addmod(mulmod(_x1, _y2, Q), mulmod(_y1, _x2, Q), Q); + uint256 y3Num = submod(y1y2, mulmod(A, x1x2, Q), Q); + + x3 = mulmod(x3Num, inverse(addmod(1, dx1x2y1y2, Q)), Q); + y3 = mulmod(y3Num, inverse(submod(1, dx1x2y1y2, Q)), Q); + } + + /** + * @dev Double a point on baby jubjub curve + * Doubling can be performed with the same formula as addition + */ + function pointDouble(uint256 _x1, uint256 _y1) internal view returns (uint256 x2, uint256 y2) { + return pointAdd(_x1, _y1, _x1, _y1); + } + + /** + * @dev Multiply a point on baby jubjub curve by a scalar + * Use the double and add algorithm + */ + function pointMul( + uint256 _x1, + uint256 _y1, + uint256 _d + ) + internal + view + returns (uint256 x2, uint256 y2) + { + uint256 remaining = _d; + + uint256 px = _x1; + uint256 py = _y1; + // Initialize (ax,ay) to the identity element + // Reference: + // https://github.com/privacy-scaling-explorations/zk-kit/blob/689e6871344c19e7f78df064b62d2bf7697ae3b8/packages/baby-jubjub/src/baby-jubjub.ts#L73 + uint256 ax = 0; + uint256 ay = 1; + + while (remaining != 0) { + if ((remaining & 1) != 0) { + // Binary digit is 1 so add + (ax, ay) = pointAdd(ax, ay, px, py); + } + (px, py) = pointDouble(px, py); + remaining = remaining / 2; + } + + x2 = ax; + y2 = ay; + } + + /** + * @dev Check if a given point is on the curve + * (168700x^2 + y^2) - (1 + 168696x^2y^2) == 0 + */ + function isOnCurve(uint256 _x, uint256 _y) internal pure returns (bool) { + uint256 xSq = mulmod(_x, _x, Q); + uint256 ySq = mulmod(_y, _y, Q); + uint256 lhs = addmod(mulmod(A, xSq, Q), ySq, Q); + uint256 rhs = addmod(1, mulmod(mulmod(D, xSq, Q), ySq, Q), Q); + return submod(lhs, rhs, Q) == 0; + } + + /** + * @dev Perform modular subtraction + */ + function submod(uint256 _a, uint256 _b, uint256 _mod) internal pure returns (uint256) { + uint256 aNN = _a; + + if (_a <= _b) { + aNN += _mod; + } + + return addmod(aNN - _b, 0, _mod); + } + + /** + * @dev Compute modular inverse of a number + */ + function inverse(uint256 _a) internal view returns (uint256) { + // We can use Euler's theorem instead of the extended Euclidean algorithm + // Since m = Q and Q is prime we have: a^-1 = a^(m - 2) (mod m) + return expmod(_a, Q - 2, Q); + } + + /** + * @dev Helper function to call the bigModExp precompile + */ + function expmod(uint256 _b, uint256 _e, uint256 _m) internal view returns (uint256 o) { + assembly { + let memPtr := mload(0x40) + mstore(memPtr, 0x20) // Length of base _b + mstore(add(memPtr, 0x20), 0x20) // Length of exponent _e + mstore(add(memPtr, 0x40), 0x20) // Length of modulus _m + mstore(add(memPtr, 0x60), _b) // Base _b + mstore(add(memPtr, 0x80), _e) // Exponent _e + mstore(add(memPtr, 0xa0), _m) // Modulus _m + + // The bigModExp precompile is at 0x05 + let success := staticcall(gas(), 0x05, memPtr, 0xc0, memPtr, 0x20) + switch success + case 0 { revert(0x0, 0x0) } + default { o := mload(memPtr) } + } + } +} diff --git a/src/utils/Identity.sol b/src/utils/Identity.sol index 25de456..50ca296 100644 --- a/src/utils/Identity.sol +++ b/src/utils/Identity.sol @@ -2,36 +2,65 @@ pragma solidity >=0.8.23 <=0.8.29; import { PoseidonT3 } from "poseidon-solidity/PoseidonT3.sol"; -// import { console } from "forge-std/console.sol"; +import { PoseidonT6 } from "poseidon-solidity/PoseidonT6.sol"; import { Vm } from "forge-std/Vm.sol"; +// import { console } from "forge-std/console.sol"; import { LibString } from "solady/Milady.sol"; +import { CurveBabyJubJub } from "./CurveBabyJubJub.sol"; + +Vm constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); library Identity { - Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + uint256 internal constant base8x = CurveBabyJubJub.Base8x; + uint256 internal constant base8y = CurveBabyJubJub.Base8y; function getCommitment(bytes memory pubKey) public pure returns (uint256 cmt) { (uint256 pkX, uint256 pkY) = abi.decode(pubKey, (uint256, uint256)); cmt = PoseidonT3.hash([pkX, pkY]); } - function verifySignature(bytes32 userOpHash, bytes memory signature) public returns (bool) { + function verifySignatureFFI(bytes32 message, bytes memory signature) public returns (bool) { (uint256 pkX, uint256 pkY, uint256 s0, uint256 s1, uint256 s2) = abi.decode(signature, (uint256, uint256, uint256, uint256, uint256)); - // TODO: implement eddsa-poseidon verifySignature() method in solidity. This part: - // https://github.com/privacy-scaling-explorations/zk-kit/blob/main/packages/eddsa-poseidon/src/eddsa-poseidon-factory.ts#L127-L158 - // Check if there is existing src to build on: - // - circom/contracts: https://github.com/iden3/contracts string[] memory inputs = new string[](6); inputs[0] = "pnpm"; inputs[1] = "semaphore-identity"; inputs[2] = "verify"; inputs[3] = vm.toString(abi.encodePacked(pkX, pkY)); - inputs[4] = vm.toString(userOpHash); + inputs[4] = vm.toString(message); inputs[5] = vm.toString(abi.encodePacked(s0, s1, s2)); bytes memory res = vm.ffi(inputs); string memory resStr = string(res); return LibString.eq(resStr, "true"); } + + function verifySignature(bytes32 message, bytes memory signature) public returns (bool) { + // Implement eddsa-poseidon verifySignature() method in solidity. + // https://github.com/privacy-scaling-explorations/zk-kit/blob/388f72b7a029a14bf5c20861d5f54bdaa98b3ac7/packages/eddsa-poseidon/src/eddsa-poseidon-factory.ts#L127-L158 + (uint256 pkX, uint256 pkY, uint256 s0, uint256 s1, uint256 s2) = + abi.decode(signature, (uint256, uint256, uint256, uint256, uint256)); + + uint256 hm = PoseidonT6.hash([s0, s1, pkX, pkY, uint256(message)]); + + // TODO: remove this after you can increase gas limit in getExecOps() + vm.pauseGasMetering(); + + (uint256 pLeftx, uint256 pLefty) = CurveBabyJubJub.pointMul(base8x, base8y, s2); + + // This is suppose to be: CurveBabyJubJub.pointMul(pkX, pkY, mulmod(8, hm, FM)), + // but I'm not sure the field modulus to use. No, not `CurveBabyJubJub.Q`. + (uint256 pRightx, uint256 pRighty) = CurveBabyJubJub.pointMul(pkX, pkY, hm); + (pRightx, pRighty) = CurveBabyJubJub.pointAdd(pRightx, pRighty, pRightx, pRighty); + (pRightx, pRighty) = CurveBabyJubJub.pointAdd(pRightx, pRighty, pRightx, pRighty); + (pRightx, pRighty) = CurveBabyJubJub.pointAdd(pRightx, pRighty, pRightx, pRighty); + + (uint256 pSumx, uint256 pSumy) = CurveBabyJubJub.pointAdd(s0, s1, pRightx, pRighty); + + // TODO: remove this after you can increase gas limit in getExecOps() + vm.resumeGasMetering(); + + return (pLeftx == pSumx && pLefty == pSumy); + } } diff --git a/test/Identity.t.sol b/test/Identity.t.sol new file mode 100644 index 0000000..80103fc --- /dev/null +++ b/test/Identity.t.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +// forge +import { Test } from "forge-std/Test.sol"; + +import { Identity as IdentityT } from "../src/utils/Identity.sol"; +import { Identity, IdentityLib } from "./utils/TestUtils.sol"; + +contract IdentityTest is Test { + using IdentityLib for Identity; + + function test_verifySignatureAcceptCorrectSignature1() public { + uint256 seed = 13; + bytes32 hash = bytes32(keccak256("hello world")); + + Identity id = IdentityLib.genIdentity(seed); + bytes memory signature = id.signHash(hash); + + assertEq(true, IdentityT.verifySignature(hash, signature)); + } + + function test_verifySignatureAcceptCorrectSignature2() public { + bytes32 hash = hex"00b917632b69261f21d20e0cabdf9f3fa1255c6e500021997a16cf3a46d80297"; + bytes memory signature = + hex"26c3a847609100b3fd926d3c0a61324a32479d5989f01383aca537869cb23a851d67a417abb29f71e1f7c3d0bcd93cb68f89203b046174f03c3822a9139b512611b5289e52e9f70ff4a30cb9a19d66de49266887d3d17ed35f2dfc30f44573dc0c44756c4e4c5a5e5eeacc68f39b4e2238041e70ca926139ea039e260ea7ca5000b8d0dfc37fc5de7b0f80b722f8966a43caa10c8068cf863e5d06f82ae7c9d8"; + + assertEq(true, IdentityT.verifySignature(hash, signature)); + } + + function test_verifySignatureRejectIncorrectSignature() public { + uint256 seed = 13; + bytes32 hash = bytes32(keccak256("hello world")); + + Identity id = IdentityLib.genIdentity(seed); + bytes memory signature = id.signHash(hash); + signature[0] = hex"ff"; + signature[1] = hex"ff"; + + assertEq(false, IdentityT.verifySignature(hash, signature)); + } +} diff --git a/test/Semaphore.t.sol b/test/Semaphore.t.sol index 58d685d..3f53ba6 100644 --- a/test/Semaphore.t.sol +++ b/test/Semaphore.t.sol @@ -39,7 +39,7 @@ contract SemaphoreUnitTest is Test { $users.push(User({ sk: sk, addr: addr })); } - function test_SemaphoreDeployed() public { + function test_semaphoreDeployed() public { ISemaphoreGroups groups = ISemaphoreGroups(address(semaphore)); User storage admin = $users[0]; diff --git a/test/SemaphoreMSAValidator.t.sol b/test/SemaphoreMSAValidator.t.sol index 00809f7..e1e763a 100644 --- a/test/SemaphoreMSAValidator.t.sol +++ b/test/SemaphoreMSAValidator.t.sol @@ -303,6 +303,12 @@ contract SemaphoreValidatorUnitTest is RhinestoneModuleKit, Test { callData: callData, txValidator: address(semaphoreValidator) }); + + // TODO: We need to increase the accountGasLimits, default 2e6 is not enough to verify + // signature, for all those elliptic curve computation. + // userOpData.userOp.accountGasLimits = bytes32(uint256(2e7)); + // userOpData.userOpHash = smartAcct.aux.entrypoint.getUserOpHash(userOpData.userOp); + userOpData.userOp.signature = id.signHash(userOpData.userOpHash); } diff --git a/test/SemaphoreMSAValidator.tree b/test/SemaphoreMSAValidator.tree deleted file mode 100644 index e69de29..0000000