Skip to content

Feat/set up for build and contracts #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: feat/refactor
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
{
"name": "@zk-jwt/zk-jwt",
"version": "0.0.1",
"license": "MIT",
"engines": {
"node": "18"
},
"private": true,
"scripts": {
"test": "jest"
Expand All @@ -9,8 +13,30 @@
"packages/*",
"frontend"
],
"packageManager": "yarn@3.2.3",
"engines": {
"node": ">=14.0.0"
"devDependencies": {
"@babel/core": "^7.22.5",
"@babel/plugin-transform-modules-commonjs": "^7.22.15",
"@babel/preset-env": "^7.22.2",
"@babel/preset-react": "^7.22.0",
"@babel/preset-typescript": "^7.21.5",
"@types/jest": "^29.5.4",
"babel-jest": "^29.5.0",
"babel-preset-jest": "^29.5.0",
"jest": "^29.5.0",
"prettier": "^3.0.0",
"prettier-plugin-solidity": "^1.1.3",
"ts-jest": "^29.1.1",
"typescript": "^4.5.4"
},
"babel": {
"presets": [
[
"@babel/preset-env"
],
"@babel/preset-typescript",
[
"jest"
]
]
}
}
5 changes: 5 additions & 0 deletions packages/circuits/jwt-verifier-test.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pragma circom 2.1.6;

include "./jwt-verifier.circom";

component main = JWTVerifier(121, 17, 1024, 128, 896, 14, 605);
36 changes: 18 additions & 18 deletions packages/circuits/package.json
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
{
"name": "@zk-jwt/circuits",
"name": "@zk-jwt/zk-jwt-circuits",
"version": "0.0.1",
"license": "MIT",
"scripts": {
"build": "mkdir -p build && circom jwt-verifier-test.circom --r1cs --wasm --sym -l ../../node_modules -o ./build",
"publish": "yarn npm publish --access=public",
"test": "NODE_OPTIONS=--max_old_space_size=8192 jest --runInBand --detectOpenHandles --forceExit --verbose tests"
"test": "NODE_OPTIONS=--max_old_space_size=8192 jest --runInBand --detectOpenHandles --forceExit --verbose tests",
"dev-setup": "NODE_OPTIONS=--max_old_space_size=16384 npx ts-node scripts/dev-setup.ts --output ./build"
},
"dependencies": {
"@zk-email/circuits": "6.1.5-nightly.2024-09-16",
"@zk-email/ether-email-auth-circom": "^0.0.2-preview",
"@zk-email/zk-regex-circom": "^2.1.1",
"circomlib": "^2.0.5"
"circomlib": "^2.0.5",
"snarkjs": "^0.7.4"
},
"devDependencies": {
"@babel/core": "^7.22.5",
"@babel/preset-env": "^7.22.2",
"@babel/preset-typescript": "^7.21.5",
"@zk-email/relayer-utils": "=0.3.7",
"babel-jest": "^29.5.0",
"babel-preset-jest": "^29.5.0",
"circom_tester": "^0.0.20",
"circomlibjs": "^0.1.7",
"@babel/preset-env": "^7.22.20",
"@babel/preset-typescript": "^7.23.0",
"@types/jest": "^29.5.4",
"chai": "^4.3.7",
"circom_tester": "^0.0.19",
"circomlib": "^2.0.5",
"circomlibjs": "^0.1.2",
"ffjavascript": "^0.2.59",
"jest": "^29.5.0",
"typescript": "^5.2.2"
"mocha": "^10.2.0",
"ts-jest": "^29.1.1",
"typescript": "^4.8.3"
},
"files": [
"/helpers",
Expand All @@ -33,12 +38,7 @@
"babel": {
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
"@babel/preset-env"
],
"@babel/preset-typescript",
[
Expand Down
181 changes: 181 additions & 0 deletions packages/circuits/scripts/dev-setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/**
*
* This script is for generating zKey and Verification Key for the circuit.
* Running this will download the phase1 file (if not already present),
* generate the zKey, and also export solidity and json verification keys.
*
* Running this will overwrite any existing zKey and verification key files.
*
*/

// @ts-ignore
import { zKey } from "snarkjs";
import https from "https";
import fs from "fs";
import path from "path";
import { program } from "commander";

program
.requiredOption(
"--output <string>",
"Path to the directory storing output files"
)
.option("--silent", "No console logs")
.option("--body", "Enable body parsing");

program.parse();
const args = program.opts();

function log(...message: any) {
if (!args.silent) {
console.log(...message);
}
}


let { ZKEY_ENTROPY, ZKEY_BEACON } = process.env;
if (ZKEY_ENTROPY == null) {
ZKEY_ENTROPY = "dev";
}
if (ZKEY_BEACON == null) {
ZKEY_BEACON = "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
}

let phase1Url =
"https://hermez.s3-eu-west-1.amazonaws.com/powersOfTau28_hez_final_22.ptau";
if (args.body) {
phase1Url =
"https://hermez.s3-eu-west-1.amazonaws.com/powersOfTau28_hez_final_23.ptau";
}
// const buildDir = path.join(__dirname, "../build");
// const phase1Path = path.join(buildDir, "powersOfTau28_hez_final_21.ptau");
// const r1cPath = path.join(buildDir, "wallet.r1cs");
const solidityTemplate = path.join(
require.resolve("snarkjs"),
"../../templates/verifier_groth16.sol.ejs"
);

// Output paths
// const zKeyPath = path.join(buildDir, "wallet.zkey");
// const vKeyPath = path.join(buildDir, "vkey.json");
// const solidityVerifierPath = path.join(buildDir, "verifier.sol");


// async function askBeacon() {
// if (!ZKEY_BEACON) {
// ZKEY_BEACON = await new Promise((resolve) => {
// const readline = require("readline").createInterface({
// input: process.stdin,
// output: process.stdout,
// });
// readline.question(
// "Enter Beacon (hex string) to apply: ",
// (entropy: string) => {
// readline.close();
// resolve(entropy);
// }
// );
// });
// }
// }

async function downloadPhase1(phase1Path: string) {
if (!fs.existsSync(phase1Path)) {
log(`✘ Phase 1 not found at ${phase1Path}`);
log(`䷢ Downloading Phase 1`);

const phase1File = fs.createWriteStream(phase1Path);

return new Promise((resolve, reject) => {
https
.get(phase1Url, (response) => {
response.pipe(phase1File);
phase1File.on("finish", () => {
phase1File.close();
resolve(true);
});
})
.on("error", (err) => {
fs.unlink(phase1Path, () => { });
reject(err);
});
});
}
}

async function generateKeys(
phase1Path: string,
r1cPath: string,
zKeyPath: string,
vKeyPath: string,
solidityVerifierPath: string
) {
log(`✓ Generating ZKey for ${r1cPath}`);
await zKey.newZKey(r1cPath, phase1Path, zKeyPath + ".step1", console);
log("✓ Partial ZKey generated");

await zKey.contribute(zKeyPath + ".step1", zKeyPath + ".step2", "Contributer 1", ZKEY_ENTROPY, console);
log("✓ First contribution completed");

// await askBeacon();
await zKey.beacon(zKeyPath + ".step2", zKeyPath, "Final Beacon", ZKEY_BEACON, 10, console);
log("✓ Beacon applied");

await zKey.verifyFromR1cs(r1cPath, phase1Path, zKeyPath, console);
log(`✓ Final ZKey verified - ${zKeyPath}`);

const vKey = await zKey.exportVerificationKey(zKeyPath, console);
fs.writeFileSync(vKeyPath, JSON.stringify(vKey, null, 2));
log(`✓ Verification key exported - ${vKeyPath}`);

const templates = {
groth16: fs.readFileSync(solidityTemplate, "utf8"),
};
const code = await zKey.exportSolidityVerifier(zKeyPath, templates, console);
fs.writeFileSync(solidityVerifierPath, code);
log(`✓ Solidity verifier exported - ${solidityVerifierPath}`);
fs.rmSync(zKeyPath + ".step1");
fs.rmSync(zKeyPath + ".step2");
}

async function exec() {
const buildDir = args.output;


if (!args.body) {
const phase1Path = path.join(buildDir, "powersOfTau28_hez_final_22.ptau");

await downloadPhase1(phase1Path);
log("✓ Phase 1:", phase1Path);

const emailAuthR1csPath = path.join(buildDir, "jwt-verifier-test.r1cs");
if (!fs.existsSync(emailAuthR1csPath)) {
throw new Error(`${emailAuthR1csPath} does not exist.`);
}
await generateKeys(phase1Path, emailAuthR1csPath, path.join(buildDir, "jwt-verifier-test.zkey"), path.join(buildDir, "jwt-verifier-test.vkey"), path.join(buildDir, "Groth16Verifier.sol"));
log("✓ Keys for email auth circuit generated");
} else {
const phase1Path = path.join(buildDir, "powersOfTau28_hez_final_23.ptau");

await downloadPhase1(phase1Path);
log("✓ Phase 1:", phase1Path);

const emailAuthR1csPath = path.join(buildDir, "email_auth_with_body_parsing_with_qp_encoding.r1cs");
if (!fs.existsSync(emailAuthR1csPath)) {
throw new Error(`${emailAuthR1csPath} does not exist.`);
}
await generateKeys(phase1Path, emailAuthR1csPath, path.join(buildDir, "email_auth_with_body_parsing_with_qp_encoding.zkey"), path.join(buildDir, "email_auth_with_body_parsing_with_qp_encoding.vkey"), path.join(buildDir, "Groth16BodyParsingVerifier.sol"));
log("✓ Keys for email auth with body parsing circuit generated");
}

}


exec()
.then(() => {
process.exit(0);
})
.catch((err) => {
console.log("Error: ", err);
process.exit(1);
});
2 changes: 2 additions & 0 deletions packages/contracts/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DEPLOYER_PRIVATE_KEY=0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
DEPLOY_SALT=my_unique_salt_string
14 changes: 14 additions & 0 deletions packages/contracts/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[profile.default]
src = "src"
out = "artifacts"
libs = ["../../node_modules", "lib"]
optimizer = true
optimizer-runs = 20_000

solc = "0.8.26"

# See more config options https://github.com/foundry-rs/foundry/tree/master/config

# OpenZeppelin
build_info = true
extra_output = ["storageLayout"]
29 changes: 29 additions & 0 deletions packages/contracts/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "@zk-jwt/zk-jwt-contracts",
"version": "0.0.1",
"license": "MIT",
"scripts": {
"build": "forge build --skip '*ZKSync*'",
"test": "forge test",
"lint": "solhint 'src/**/*.sol'"
},
"dependencies": {
"@openzeppelin/contracts": "^5.0.0",
"@openzeppelin/contracts-upgradeable": "^5.0.0",
"@zk-email/contracts": "^6.1.5",
"solady": "^0.0.123",
"solidity-stringutils": "github:LayerZero-Labs/solidity-stringutils"
},
"devDependencies": {
"ds-test": "https://github.com/dapphub/ds-test",
"forge-std": "https://github.com/foundry-rs/forge-std",
"solhint": "^3.6.1"
},
"files": [
"/src",
"foundry.toml",
"package.json",
"README.md",
"remappings.txt"
]
}
6 changes: 6 additions & 0 deletions packages/contracts/remappings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@openzeppelin/=../../node_modules/@openzeppelin
@openzeppelin/contracts-upgradeable/=../../node_modules/@openzeppelin/contracts-upgradeable
@zk-email/=../../node_modules/@zk-email
forge-std/=../../node_modules/forge-std/src
ds-test/=../../node_modules/ds-test/src
solidity-stringutils/=../../node_modules/solidity-stringutils/
23 changes: 23 additions & 0 deletions packages/contracts/script/Deploy_jwtRegistry.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// script/Deploy.s.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

import "forge-std/Script.sol";
import "../src/utils/JwtRegistry.sol";

contract DeployScript is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY");
address deployer = vm.addr(deployerPrivateKey);
bytes32 salt = keccak256(abi.encodePacked(vm.envString("DEPLOY_SALT")));

vm.startBroadcast(deployer);

// Deploy the contract using CREATE2
JwtRegistry jwtRegistry = new JwtRegistry{salt: salt}(deployer);

console.log("Contract deployed to:", address(jwtRegistry));

vm.stopBroadcast();
}
}
11 changes: 11 additions & 0 deletions packages/contracts/src/interfaces/IJwtGroth16Verifier.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

interface IJwtGroth16Verifier {
function verifyProof(
uint[2] calldata _pA,
uint[2][2] calldata _pB,
uint[2] calldata _pC,
uint[29] calldata _pubSignals
) external view returns (bool);
}
Loading
Loading