This commit is contained in:
Andrija Novakovic
2021-10-23 01:11:23 +02:00
parent 640f2c5e8d
commit 9cc257fa21
5 changed files with 2833 additions and 634 deletions

View File

@@ -0,0 +1,81 @@
const { expect, before } = require("chai");
const {ethers } = require('hardhat');
const { poseidon_gencontract: poseidonGenContract } = require("circomlibjs");
const { Semaphore, generateMerkleProof, genExternalNullifier, genSignalHash } = require("@libsem/protocols");
const { ZkIdentity } = require("@libsem/identity");
const deployPoseidonTx = (x) => {
return ethers.getContractFactory(
poseidonGenContract.generateABI(x),
poseidonGenContract.createCode(x)
)
}
let semaphore;
let defaultExternalNullifier;
const identityCommitments = [];
const ZERO_VALUE = BigInt(ethers.utils.solidityKeccak256(['bytes'], [ethers.utils.toUtf8Bytes('Semaphore')]))
before("*", async () => {
defaultExternalNullifier = genExternalNullifier("voting_1");
newExternalNullifier = genExternalNullifier('voting-2');
const PoseidonT3 = await deployPoseidonTx(2);
const poseidonT3 = await PoseidonT3.deploy();
await poseidonT3.deployed();
const PoseidonT6 = await deployPoseidonTx(5);
const poseidonT6 = await PoseidonT6.deploy();
await poseidonT6.deployed();
const Semaphore = await ethers.getContractFactory("Semaphore", {
libraries: {
PoseidonT3: poseidonT3.address,
PoseidonT6: poseidonT6.address,
}
});
semaphore = await Semaphore.deploy(20, defaultExternalNullifier);
await semaphore.deployed();
const leafIndex = 3
for (let i = 0; i < leafIndex; i++) {
const tmpIdentity = new ZkIdentity();
const tmpCommitment = tmpIdentity.genIdentityCommitment();
identityCommitments.push(tmpCommitment)
}
})
describe("Semaphore contract", () => {
it("Should generate full semaphore proof", async () => {
const identity = new ZkIdentity();
const identityCommitment = identity.genIdentityCommitment();
await semaphore.insertIdentity(identityCommitment);
const signal = "0x111";
const nullifierHash = Semaphore.genNullifierHash(externalNullifier, identity.getNullifier(), 20)
const commitments = Object.assign([], identityCommitments)
commitments.push(identityCommitment)
const merkleProof = generateMerkleProof(20, ZERO_VALUE, 5, commitments, identityCommitment)
const witness = Semaphore.genWitness(identity.getIdentity(), merkleProof, externalNullifier, signal)
const publicSignals = [
merkleProof.root,
nullifierHash,
genSignalHash(signal),
externalNullifier
]
const vkeyPath = path.join("./zkeyFiles", "semaphore", "verification_key.json")
const vKey = JSON.parse(fs.readFileSync(vkeyPath, "utf-8"))
const wasmFilePath = path.join("./zkeyFiles", "semaphore", "semaphore.wasm")
const finalZkeyPath = path.join("./zkeyFiles", "semaphore", "semaphore_final.zkey")
const fullProof = await Semaphore.genProof(witness, wasmFilePath, finalZkeyPath)
const res = await Semaphore.verifyProof(vKey, { proof: fullProof.proof, publicSignals })
})
})

3279
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,11 +3,13 @@
"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": "npx hardhat test",
"compile": "npx hardhat compile",
"compile:circuits": "scripts/build-circuits.sh <<< $'random text'",
"compile:contracts": "npx hardhat compile",
"develop": "npx hardhat node",
"deploy": "npx hardhat deploy --tags complete",
"deployPoseidon": "npx hardhat deploy --tags Poseidon"
"deploy:poseidon": "npx hardhat deploy --tags Poseidon",
"test": "npx hardhat test",
"test:integration": "npm run compile:circuits && node integration-test semaphore-proof-test.js"
},
"repository": {
"type": "git",
@@ -21,21 +23,24 @@
},
"homepage": "https://github.com/appliedzkp/semaphore.git#readme",
"dependencies": {
"@libsem/identity": "^1.0.8",
"@libsem/protocols": "^1.0.9",
"circomlib": "^0.5.3",
"hardhat-deploy": "^0.9.4",
"hardhat-deploy-ethers": "^0.3.0-beta.11",
"web3": "^1.5.2"
},
"devDependencies": {
"@libsem/identity": "^1.0.14",
"@libsem/protocols": "^1.0.14",
"@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-waffle": "^2.0.1",
"chai": "^4.3.4",
"chai-ethers": "^0.0.1",
"circomlibjs": "^0.0.8",
"ethereum-waffle": "^3.4.0",
"ethers": "^5.4.6",
"hardhat": "^2.6.1",
"http-server": "^13.0.1",
"mocha": "^9.1.3",
"snarkjs": "^0.4.7",
"ts-node": "^10.2.1",
"typescript": "^4.4.2"

View File

@@ -1,11 +1,9 @@
cd "$(dirname "$0")"
mkdir -p ../build
cd ../build
cd "$(dirname "$0")"
mkdir -p ../build
mkdir -p ../zkeyFiles
npx circom ../circuits/semaphore.circom --r1cs --wasm --sym
cd ../build
if [ -f ./powersOfTau28_hez_final_16.ptau ]; then
echo "powersOfTau28_hez_final_16.ptau already exists. Skipping."
@@ -14,6 +12,8 @@ else
wget https://hermez.s3-eu-west-1.amazonaws.com/powersOfTau28_hez_final_16.ptau
fi
npx circom ../circuits/semaphore.circom --r1cs --wasm --sym
npx snarkjs zkey new semaphore.r1cs powersOfTau28_hez_final_16.ptau semaphore_0000.zkey
npx snarkjs zkey contribute semaphore_0000.zkey semaphore_final.zkey

View File

@@ -0,0 +1,84 @@
const { expect } = require("chai");
const { ethers } = require('hardhat');
const { poseidon_gencontract: poseidonGenContract } = require("circomlibjs");
const { genExternalNullifier } = require("@libsem/protocols");
const deployPoseidonTx = (x) => {
return ethers.getContractFactory(
poseidonGenContract.generateABI(x),
poseidonGenContract.createCode(x)
)
}
let semaphore;
let defaultExternalNullifier;
let newExternalNullifier;
before("*", async () => {
defaultExternalNullifier = genExternalNullifier("voting_1");
newExternalNullifier = genExternalNullifier('voting-2');
const PoseidonT3 = await deployPoseidonTx(2);
const poseidonT3 = await PoseidonT3.deploy();
await poseidonT3.deployed();
const PoseidonT6 = await deployPoseidonTx(5);
const poseidonT6 = await PoseidonT6.deploy();
await poseidonT6.deployed();
const Semaphore = await ethers.getContractFactory("Semaphore", {
libraries: {
PoseidonT3: poseidonT3.address,
PoseidonT6: poseidonT6.address,
}
});
semaphore = await Semaphore.deploy(20, defaultExternalNullifier);
await semaphore.deployed();
})
describe("Semaphore contract", () => {
it("Default nullifier should be active", async () => {
const isActive = await semaphore.isExternalNullifierActive(defaultExternalNullifier);
expect(isActive).to.be.true;
});
it("ExternalNullifier should be active after add", async () => {
await semaphore.addExternalNullifier(newExternalNullifier);
const isActive = await semaphore.isExternalNullifierActive(newExternalNullifier);
expect(isActive).to.be.true;
});
it("ExternalNullifier should not be active after deactivation", async () => {
await semaphore.deactivateExternalNullifier(newExternalNullifier);
const isActive = await semaphore.isExternalNullifierActive(newExternalNullifier);
expect(isActive).to.be.false;
});
it("ExternalNullifier should be active after reactivation", async () => {
await semaphore.reactivateExternalNullifier(newExternalNullifier);
const isActive = await semaphore.isExternalNullifierActive(newExternalNullifier);
expect(isActive).to.be.true;
});
it("Non owner should not be able to add nullifier", async () => {
const [_, addr1] = await ethers.getSigners();
const newNullifier = genExternalNullifier('voting-3');
await expect(semaphore.connect(addr1).addExternalNullifier(newNullifier))
.to.be.revertedWith('Ownable: caller is not the owner');
})
it("Non owner should be able to add nullifier after setPermissioning", async () => {
const [_, addr1] = await ethers.getSigners();
await semaphore.setPermissioning(true);
const newNullifier = genExternalNullifier('voting-3');
await semaphore.addExternalNullifier(newNullifier);
const isActive = await semaphore.isExternalNullifierActive(newNullifier);
expect(isActive).to.be.true;
})
it("Should fail to add already existing nullifier", async () => {
await expect(semaphore.addExternalNullifier(newExternalNullifier))
.to.be.revertedWith('Semaphore: external nullifier already set');
})
it("Should return newExternalNullifier as next nullifier", async () => {
const nextNullifier = await semaphore.getNextExternalNullifier(defaultExternalNullifier);
expect(nextNullifier).to.be.equal(newExternalNullifier);
});
});