deploy scripts with hardhat-deploy module

Former-commit-id: 16b46efcab
This commit is contained in:
Andrija Novakovic
2021-10-21 00:14:20 +02:00
parent 3824857b04
commit bc4b0acefd
12 changed files with 100 additions and 215 deletions

14
deploy/01_poseidon_t3.js Normal file
View File

@@ -0,0 +1,14 @@
const { poseidon_gencontract: poseidonGenContract } = require('circomlibjs');
module.exports = async ({ getNamedAccounts, deployments }) => {
const { deploy } = deployments;
const { deployer } = await getNamedAccounts();
await deploy("PoseidonT3", {
from: deployer,
log: true,
abi: poseidonGenContract.generateABI(2),
bytecode: poseidonGenContract.createCode(2)
});
};
module.exports.tags = ['poseidon-t3', 'poseidon'];

14
deploy/02_poseidon_t6.js Normal file
View File

@@ -0,0 +1,14 @@
const { poseidon_gencontract: poseidonGenContract } = require('circomlibjs');
module.exports = async ({ getNamedAccounts, deployments }) => {
const { deploy } = deployments;
const { deployer } = await getNamedAccounts();
await deploy("PoseidonT3", {
from: deployer,
log: true,
abi: poseidonGenContract.generateABI(5),
bytecode: poseidonGenContract.createCode(5)
});
};
module.exports.tags = ['poseidon-t6', 'poseidon'];

39
deploy/1_complete.js Normal file
View File

@@ -0,0 +1,39 @@
const { poseidon_gencontract: poseidonGenContract } = require('circomlibjs');
const { genExternalNullifier } = require('../utils');
module.exports = async ({ getNamedAccounts, deployments }) => {
const { deploy } = deployments;
const { deployer } = await getNamedAccounts();
const poseidonT3 = await deploy("PoseidonT3", {
from: deployer,
log: true,
abi: poseidonGenContract.generateABI(2),
bytecode: poseidonGenContract.createCode(2)
});
const poseidonT6 = await deploy("PoseidonT6", {
from: deployer,
log: true,
abi: poseidonGenContract.generateABI(5),
bytecode: poseidonGenContract.createCode(5)
});
const externalNullifier = genExternalNullifier('test-voting');
const semaphore = await deploy('Semaphore', {
from: deployer,
log: true,
args: [20, externalNullifier],
libraries: {
PoseidonT3: poseidonT3.address,
PoseidonT6: poseidonT6.address
}
});
await deploy('SemaphoreClient', {
from: deployer,
log: true,
args: [semaphore.address],
});
};
module.exports.tags = ['complete'];

View File

@@ -1,4 +1,5 @@
require("@nomiclabs/hardhat-waffle");
require('hardhat-deploy');
// This is a sample Hardhat task. To learn how to create your own go to
// https://hardhat.org/guides/create-task.html
@@ -24,4 +25,12 @@ module.exports = {
allowUnlimitedContractSize: true,
},
},
namedAccounts: {
deployer: 0,
tokenOwner: 1,
},
paths: {
deploy: 'deploy',
deployments: 'deployments',
},
};

View File

@@ -1 +1 @@
350d6b1fa2a2537ad0a0585a837479fa82459080
15bb0cac2b8d3091fe503a0783186b5051ebf07f

View File

@@ -1,9 +1,13 @@
{
"name": "semaphore",
"version": "1.0.0",
"version": "2.0.0",
"description": "Solidity contracts, zk-SNARK circuits, and test scripts for the Semaphore zero-knowledge signalling gadget. This version uses the Poseidon hash and does not use EdDSA signatures.",
"scripts": {
"test": "ts-node test/verify.ts"
"test": "npx hardhat test",
"compile": "npx hardhat compile",
"develop": "npx hardhat node",
"deploy": "npx hardhat deploy --tags complete",
"deployPoseidon": "npx hardhat deploy --tags poseidon"
},
"repository": {
"type": "git",
@@ -20,6 +24,7 @@
"@libsem/identity": "^1.0.8",
"@libsem/protocols": "^1.0.9",
"circomlib": "^0.5.3",
"hardhat-deploy": "^0.9.4",
"web3": "^1.5.2"
},
"devDependencies": {

View File

@@ -20,7 +20,7 @@ npx snarkjs zkey contribute semaphore_0000.zkey semaphore_final.zkey
npx snarkjs zkey export verificationkey semaphore_final.zkey verification_key.json
snarkjs zkey export solidityverifier semaphore_final.zkey verifier.sol
npx snarkjs zkey export solidityverifier semaphore_final.zkey verifier.sol
mv verifier.sol ../contracts/Verifier.sol

View File

@@ -1,32 +0,0 @@
// We require the Hardhat Runtime Environment explicitly here. This is optional
// but useful for running the script in a standalone fashion through `node <script>`.
//
// When running the script with `npx hardhat run <script>` you'll find the Hardhat
// Runtime Environment's members available in the global scope.
const hre = require("hardhat");
async function main() {
// Hardhat always runs the compile task when running scripts with its command
// line interface.
//
// If this script is run directly using `node` you may want to call compile
// manually to make sure everything is compiled
// await hre.run('compile');
// We get the contract to deploy
const Greeter = await hre.ethers.getContractFactory("Greeter");
const greeter = await Greeter.deploy("Hello, Hardhat!");
await greeter.deployed();
console.log("Greeter deployed to:", greeter.address);
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -1,5 +0,0 @@
#!/usr/bin/env bash
cd "$(dirname "$0")"
cd ../zkeyFiles
http-server -p 8000 --cors

View File

@@ -1,122 +0,0 @@
const poseidonGenContract = require('circomlib/src/poseidon_gencontract.js');
const path = require('path');
const fs = require('fs');
const Web3 = require('web3');
const ZERO_VALUE = BigInt(ethers.utils.solidityKeccak256(['bytes'], [ethers.utils.toUtf8Bytes('Semaphore')]));
const SNARK_FIELD_SIZE = BigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
const { ZkIdentity } = require('@libsem/identity');
const { Semaphore, genExternalNullifier, genSignalHash, generateMerkleProof } = require('@libsem/protocols');
const { expect } = require('chai');
describe("Semaphore", function () {
it("Should broadcast signal", async function () {
const PoseidonT3 = await ethers.getContractFactory(
poseidonGenContract.generateABI(2),
poseidonGenContract.createCode(2)
)
const poseidonT3 = await PoseidonT3.deploy();
await poseidonT3.deployed();
const PoseidonT6 = await ethers.getContractFactory(
poseidonGenContract.generateABI(5),
poseidonGenContract.createCode(5)
);
const poseidonT6 = await PoseidonT6.deploy();
await poseidonT6.deployed();
const Hasher = await ethers.getContractFactory("Hasher", {
libraries: {
PoseidonT3: poseidonT3.address,
PoseidonT6: poseidonT6.address,
},
});
const hasher = await Hasher.deploy();
await hasher.deployed();
const externalNullifier = genExternalNullifier("voting-1");
const SemaphoreContract = await ethers.getContractFactory("Semaphore", {
libraries: {
PoseidonT3: poseidonT3.address,
PoseidonT6: poseidonT6.address,
}
});
const semaphore = await SemaphoreContract.deploy(20, externalNullifier);
await semaphore.deployed();
const leafIndex = 4;
const idCommitments = [];
for (let i=0; i<leafIndex;i++) {
const tmpIdentity = ZkIdentity.genIdentity();
const tmpCommitment = ZkIdentity.genIdentityCommitment(tmpIdentity);
idCommitments.push(tmpCommitment);
}
const promises = idCommitments.map(async (id) => {
const index = await semaphore.insertIdentity(id);
return index;
});
await Promise.all(promises);
const identity = ZkIdentity.genIdentity();
let signal = 'yes';
signal = Web3.utils.utf8ToHex(signal);
const signalHash = genSignalHash(signal);
const nullifiersHash = Semaphore.genNullifierHash(externalNullifier, identity.identityNullifier, 20);
const identityCommitment = ZkIdentity.genIdentityCommitment(identity);
await semaphore.insertIdentity(identityCommitment);
idCommitments.push(identityCommitment);
const merkleProof = generateMerkleProof(20, ZERO_VALUE, 5, idCommitments, identityCommitment);
const witness = Semaphore.genWitness(identity, merkleProof, externalNullifier, signal);
const wasmFilePath = path.join('./zkeyFiles', 'semaphore.wasm');
const finalZkeyPath = path.join('./zkeyFiles', 'semaphore_final.zkey');
const fullProof = await Semaphore.genProof(witness, wasmFilePath, finalZkeyPath);
const solidityProof = Semaphore.packToSolidityProof(fullProof);
const packedProof = await semaphore.packProof(
solidityProof.a,
solidityProof.b,
solidityProof.c,
);
const preBroadcastCheck = await semaphore.preBroadcastCheck(
ethers.utils.hexlify(ethers.utils.toUtf8Bytes(signal)),
packedProof,
merkleProof.root,
nullifiersHash,
signalHash,
externalNullifier
)
expect(preBroadcastCheck).to.be.true;
const res = await semaphore.broadcastSignal(
ethers.utils.hexlify(ethers.utils.toUtf8Bytes(signal)),
packedProof,
merkleProof.root,
nullifiersHash,
externalNullifier
)
expect(res.hash).to.be.an('string');
// const verificationRes = await semaphore.verifyProof(
// solidityProof.a,
// solidityProof.b,
// solidityProof.c,
// solidityProof.inputs
// );
});
});

View File

@@ -1,52 +0,0 @@
const snarkjs = require("snarkjs");
import * as fs from 'fs';
import * as path from 'path';
import { ZkIdentity, Identity } from '@libsem/identity';
import { Semaphore, MerkleProof, IProof, generateMerkleProof, genExternalNullifier, genSignalHash } from '@libsem/protocols';
import * as ethers from 'ethers';
const ZERO_VALUE = BigInt(ethers.utils.solidityKeccak256(['bytes'], [ethers.utils.toUtf8Bytes('Semaphore')]));
async function run() {
const identityCommitments: Array<bigint> = [];
const leafIndex = 3;
for (let i=0; i<leafIndex;i++) {
const tmpIdentity = ZkIdentity.genIdentity();
const tmpCommitment: bigint = ZkIdentity.genIdentityCommitment(tmpIdentity);
identityCommitments.push(tmpCommitment);
}
const identity: Identity = ZkIdentity.genIdentity();
const externalNullifier: string = genExternalNullifier("voting_1");
const signal = '0x111';
const identityCommitment: bigint = ZkIdentity.genIdentityCommitment(identity);
const nullifierHash: bigint = Semaphore.genNullifierHash(externalNullifier, identity.identityNullifier, 20);
const commitments: Array<bigint> = Object.assign([], identityCommitments);
commitments.push(identityCommitment);
const merkleProof: MerkleProof = generateMerkleProof(20, BigInt(0), 5, commitments, identityCommitment);
const witness: IProof = Semaphore.genWitness(identity, merkleProof, externalNullifier, signal);
const publicSignals: Array<bigint | string> = [merkleProof.root, nullifierHash, genSignalHash(signal), externalNullifier];
const vkeyPath: string = path.join('./zkeyFiles', 'verification_key.json');
const vKey = JSON.parse(fs.readFileSync(vkeyPath, 'utf-8'));
const wasmFilePath: string = path.join('./zkeyFiles', 'semaphore.wasm');
const finalZkeyPath: string = path.join('./zkeyFiles', 'semaphore_final.zkey');
const fullProof: IProof = await Semaphore.genProof(witness, wasmFilePath, finalZkeyPath);
const res: boolean = await Semaphore.verifyProof(vKey, { proof: fullProof.proof, publicSignals });
if(res) {
console.log('VERIFICATION OK');
} else {
console.log('VERIFICATION FAILED');
}
}
run().then(() => {
process.exit(0);
});

15
utils/index.js Normal file
View File

@@ -0,0 +1,15 @@
const { ethers } = require('ethers');
const genExternalNullifier = (plaintext) => {
const _cutOrExpandHexToBytes = (hexStr, bytes) => {
const len = bytes * 2;
const h = hexStr.slice(2, len + 2);
return "0x" + h.padStart(len, "0");
};
const hashed = ethers.utils.solidityKeccak256(["string"], [plaintext]);
return _cutOrExpandHexToBytes("0x" + hashed.slice(8), 32);
};
module.exports = { genExternalNullifier }