test: add tests to create proofs and verify them

Former-commit-id: f45d926275bd734185edfd1fa323e399fbc505cc [formerly 6a412ac4324d0bc65fadd31ef4952beb6b41c552] [formerly 4f9ad62e0aca23775e65b8e8bb9c2eb615ec8aca [formerly c920365e83a601a73401609bedca3542779ce6c8]] [formerly e73de9b0c0a262c979c1d17882ea3c4dd31aa59e [formerly 2a175fb199795e94a2e14e7e6774d611d72cf9de] [formerly 84f49553d22b1c51f4bd15f0f5e92c6f5ff0438e [formerly 865c5bb174]]]
Former-commit-id: 46e1332a4a2fbbdcc34fd4dbf5b98d04da3d52df [formerly 83b1530c98aef832277c838cd7714cfbb84d83c1] [formerly 1541c9c435e024eb0012f19e655ecb01804e4a47 [formerly 55eb157e1bfa9916887fb3a331dabcc3268cf62b]]
Former-commit-id: d8385e49a2f06264e525e2ce83f75746fd1b57dd [formerly dd8f63c8d306064f9f5163e9f2a6f841634e8b96]
Former-commit-id: ab49c153a92a66dfee8741a94529b7dd91ac74d2
This commit is contained in:
cedoor
2022-01-24 15:39:23 +01:00
parent 3408c00bfe
commit c8a85df511
5 changed files with 124 additions and 127 deletions

View File

@@ -1,4 +1,4 @@
import { MerkleProof } from "@zk-kit/types"
import { MerkleProof, StrBigInt } from "@zk-kit/types"
import { poseidon } from "circomlibjs"
import { Fq, genSignalHash } from "./utils"
import ZkProtocol from "./zk-protocol"
@@ -15,9 +15,9 @@ export default class NRLN extends ZkProtocol {
* @returns rln witness
*/
public static genWitness(
identitySecret: Array<bigint>,
identitySecret: bigint[],
merkleProof: MerkleProof,
epoch: string | bigint,
epoch: StrBigInt,
signal: string,
rlnIdentifier: bigint,
shouldHash = true
@@ -42,15 +42,15 @@ export default class NRLN extends ZkProtocol {
* @returns
*/
public static calculateOutput(
identitySecret: Array<bigint>,
identitySecret: bigint[],
epoch: bigint,
x: bigint,
limit: number,
rlnIdentifier: bigint
): Array<bigint> {
): bigint[] {
const a0 = poseidon(identitySecret)
const coeffs: bigint[] = []
const coeffs: Array<bigint> = []
let tmpX = x
coeffs.push(poseidon([identitySecret[0], epoch]))
@@ -73,7 +73,7 @@ export default class NRLN extends ZkProtocol {
* @param coeffs coeefitients from calculated polinomial
* @returns slashing nullifier
*/
public static genNullifier(coeffs: Array<bigint>): bigint {
public static genNullifier(coeffs: bigint[]): bigint {
return poseidon(coeffs)
}
@@ -83,10 +83,14 @@ export default class NRLN extends ZkProtocol {
* @param ys
* @returns identity secret
*/
public static retrieveSecret(xs: Array<bigint>, ys: Array<bigint>): bigint {
if (xs.length !== ys.length) throw new Error("x and y arrays must be of same size")
public static retrieveSecret(xs: bigint[], ys: bigint[]): bigint {
if (xs.length !== ys.length) {
throw new Error("x and y arrays must be of same size")
}
const numOfPoints: number = xs.length
let f0 = BigInt(0)
for (let i = 0; i < numOfPoints; i += 1) {
let p = BigInt(1)
for (let j = 0; j < numOfPoints; j += 1) {
@@ -96,6 +100,7 @@ export default class NRLN extends ZkProtocol {
}
f0 = Fq.add(f0, Fq.mul(ys[i], p))
}
return f0
}

View File

@@ -1,4 +1,4 @@
import { MerkleProof } from "@zk-kit/types"
import { MerkleProof, StrBigInt } from "@zk-kit/types"
import { poseidon } from "circomlibjs"
import { Fq, genSignalHash } from "./utils"
import ZkProtocol from "./zk-protocol"
@@ -17,7 +17,7 @@ export default class RLN extends ZkProtocol {
public static genWitness(
identitySecret: bigint,
merkleProof: MerkleProof,
epoch: string | bigint,
epoch: StrBigInt,
signal: string,
rlnIdentifier: bigint,
shouldHash = true
@@ -40,15 +40,11 @@ export default class RLN extends ZkProtocol {
* @param x signal hash
* @returns y & slashing nullfier
*/
public static calculateOutput(
identitySecret: bigint,
epoch: bigint,
rlnIdentifier: bigint,
x: bigint
): Array<bigint> {
const a1: bigint = poseidon([identitySecret, epoch])
const y: bigint = Fq.normalize(a1 * x + identitySecret)
public static calculateOutput(identitySecret: bigint, epoch: bigint, rlnIdentifier: bigint, x: bigint): bigint[] {
const a1 = poseidon([identitySecret, epoch])
const y = Fq.normalize(a1 * x + identitySecret)
const nullifier = RLN.genNullifier(a1, rlnIdentifier)
return [y, nullifier]
}

View File

@@ -1,62 +1,60 @@
import { SecretType, ZkIdentity } from "@zk-kit/identity"
import { FullProof, MerkleProof } from "@zk-kit/types"
import { poseidon } from "circomlibjs"
import * as fs from "fs"
import * as path from "path"
import { NRLN } from "../src"
import { generateMerkleProof, genExternalNullifier, genSignalHash } from "../src/utils"
const identityCommitments: Array<bigint> = []
const SPAM_TRESHOLD = 3
beforeAll(() => {
const leafIndex = 3
for (let i = 0; i < leafIndex; i += 1) {
const tmpIdentity = new ZkIdentity()
const tmpCommitment: bigint = tmpIdentity.genIdentityCommitment(SecretType.MULTIPART, SPAM_TRESHOLD)
identityCommitments.push(tmpCommitment)
}
})
describe("NRLN", () => {
const zkeyFiles = "./packages/protocols/zkeyFiles"
const identityCommitments: bigint[] = []
const SPAM_TRESHOLD = 3
beforeAll(() => {
const numberOfLeaves = 3
for (let i = 0; i < numberOfLeaves; i += 1) {
const identity = new ZkIdentity()
const identityCommitment = identity.genIdentityCommitment(SecretType.MULTIPART, SPAM_TRESHOLD)
identityCommitments.push(identityCommitment)
}
})
describe("NRLN features", () => {
it("Generate NRLN witness", () => {
const identity: ZkIdentity = new ZkIdentity()
it("Should generate NRLN witness", () => {
const identity = new ZkIdentity()
const identityCommitment = identity.genIdentityCommitment(SecretType.MULTIPART, SPAM_TRESHOLD)
const identitySecret = identity.getMultipartSecret(SPAM_TRESHOLD)
const identityCommitment: bigint = identity.genIdentityCommitment(SecretType.MULTIPART, SPAM_TRESHOLD)
const identitySecret: bigint[] = identity.getMultipartSecret(SPAM_TRESHOLD)
const commitments: Array<bigint> = Object.assign([], identityCommitments)
commitments.push(identityCommitment)
const leaves = Object.assign([], identityCommitments)
leaves.push(identityCommitment)
const signal = "hey hey"
const epoch: string = genExternalNullifier("test-epoch")
const rlnIdentifier: bigint = NRLN.genIdentifier()
const epoch = genExternalNullifier("test-epoch")
const rlnIdentifier = NRLN.genIdentifier()
const merkleProof: MerkleProof = generateMerkleProof(15, BigInt(0), 2, commitments, identityCommitment)
const witness: FullProof = NRLN.genWitness(identitySecret, merkleProof, epoch, signal, rlnIdentifier)
const merkleProof = generateMerkleProof(15, BigInt(0), 2, leaves, identityCommitment)
const witness = NRLN.genWitness(identitySecret, merkleProof, epoch, signal, rlnIdentifier)
expect(typeof witness).toBe("object")
})
it.skip("Generate NRLN proof and verify it", async () => {
/**
* Compiled RLN circuits are needed to run this test so it's being skipped in hooks
*/
const identity: ZkIdentity = new ZkIdentity()
const identityCommitment: bigint = identity.genIdentityCommitment(SecretType.MULTIPART, SPAM_TRESHOLD)
const identitySecret: bigint[] = identity.getMultipartSecret(SPAM_TRESHOLD)
const commitments: Array<bigint> = Object.assign([], identityCommitments)
commitments.push(identityCommitment)
it("Should generate NRLN proof and verify it", async () => {
const identity = new ZkIdentity()
const identityCommitment = identity.genIdentityCommitment(SecretType.MULTIPART, SPAM_TRESHOLD)
const identitySecret = identity.getMultipartSecret(SPAM_TRESHOLD)
const leaves = Object.assign([], identityCommitments)
leaves.push(identityCommitment)
const signal = "hey hey"
const signalHash = genSignalHash(signal)
const epoch: string = genExternalNullifier("test-epoch")
const rlnIdentifier: bigint = NRLN.genIdentifier()
const epoch = genExternalNullifier("test-epoch")
const rlnIdentifier = NRLN.genIdentifier()
const merkleProof: MerkleProof = generateMerkleProof(15, BigInt(0), 2, commitments, identityCommitment)
const witness: FullProof = NRLN.genWitness(identitySecret, merkleProof, epoch, signal, rlnIdentifier)
const merkleProof = generateMerkleProof(15, BigInt(0), 2, leaves, identityCommitment)
const witness = NRLN.genWitness(identitySecret, merkleProof, epoch, signal, rlnIdentifier)
const [y, nullifier] = NRLN.calculateOutput(
identitySecret,
@@ -67,21 +65,22 @@ describe("NRLN", () => {
)
const publicSignals = [y, merkleProof.root, nullifier, signalHash, epoch, rlnIdentifier]
const vkeyPath: string = path.join("./zkeyFiles", "nrln", "verification_key.json")
const vkeyPath = path.join(zkeyFiles, "nrln", "verification_key.json")
const vKey = JSON.parse(fs.readFileSync(vkeyPath, "utf-8"))
const wasmFilePath: string = path.join("./zkeyFiles", "nrln", "rln.wasm")
const finalZkeyPath: string = path.join("./zkeyFiles", "nrln", "rln_final.zkey")
const wasmFilePath = path.join(zkeyFiles, "nrln", "rln.wasm")
const finalZkeyPath = path.join(zkeyFiles, "nrln", "rln_final.zkey")
const fullProof: FullProof = await NRLN.genProof(witness, wasmFilePath, finalZkeyPath)
const res: boolean = await NRLN.verifyProof(vKey, { proof: fullProof.proof, publicSignals })
const fullProof = await NRLN.genProof(witness, wasmFilePath, finalZkeyPath)
const response = await NRLN.verifyProof(vKey, { proof: fullProof.proof, publicSignals })
expect(res).toBe(true)
expect(response).toBe(true)
}, 30000)
it("Should retrieve user secret after spaming", () => {
const identity: ZkIdentity = new ZkIdentity()
const identitySecret: bigint[] = identity.getMultipartSecret(SPAM_TRESHOLD)
it("Should retrieve user secret after spaming", () => {
const identity = new ZkIdentity()
const identitySecret = identity.getMultipartSecret(SPAM_TRESHOLD)
const signal1 = "hey 1"
const signalHash1 = genSignalHash(signal1)
@@ -92,15 +91,15 @@ describe("NRLN", () => {
const signal4 = "hey 4"
const signalHash4 = genSignalHash(signal4)
const epoch: string = genExternalNullifier("test-epoch")
const rlnIdentifier: bigint = NRLN.genIdentifier()
const epoch = genExternalNullifier("test-epoch")
const rlnIdentifier = NRLN.genIdentifier()
const [y1] = NRLN.calculateOutput(identitySecret, BigInt(epoch), signalHash1, SPAM_TRESHOLD, rlnIdentifier)
const [y2] = NRLN.calculateOutput(identitySecret, BigInt(epoch), signalHash2, SPAM_TRESHOLD, rlnIdentifier)
const [y3] = NRLN.calculateOutput(identitySecret, BigInt(epoch), signalHash3, SPAM_TRESHOLD, rlnIdentifier)
const [y4] = NRLN.calculateOutput(identitySecret, BigInt(epoch), signalHash4, SPAM_TRESHOLD, rlnIdentifier)
const retrievedSecret: bigint = NRLN.retrieveSecret(
const retrievedSecret = NRLN.retrieveSecret(
[signalHash1, signalHash2, signalHash3, signalHash4],
[y1, y2, y3, y4]
)

View File

@@ -1,93 +1,90 @@
import { FullProof, MerkleProof } from "@zk-kit/types"
import { SecretType, ZkIdentity } from "@zk-kit/identity"
import * as fs from "fs"
import * as path from "path"
import { SecretType, ZkIdentity } from "@zk-kit/identity"
import { RLN } from "../src"
import { generateMerkleProof, genExternalNullifier, genSignalHash } from "../src/utils"
const identityCommitments: Array<bigint> = []
beforeAll(() => {
const leafIndex = 3
for (let i = 0; i < leafIndex; i += 1) {
const tmpIdentity = new ZkIdentity()
const tmpCommitment: bigint = tmpIdentity.genIdentityCommitment(SecretType.MULTIPART)
identityCommitments.push(tmpCommitment)
}
})
describe("RLN", () => {
describe("RLN functionalities", () => {
it("Generate rln witness", () => {
const identity: ZkIdentity = new ZkIdentity()
const identityCommitment: bigint = identity.genIdentityCommitment()
const secretHash: bigint = identity.getMultipartSecretHash()
const zkeyFiles = "./packages/protocols/zkeyFiles"
const identityCommitments: bigint[] = []
const commitments: Array<bigint> = Object.assign([], identityCommitments)
commitments.push(identityCommitment)
beforeAll(() => {
const numberOfLeaves = 3
for (let i = 0; i < numberOfLeaves; i += 1) {
const identity = new ZkIdentity()
const identityCommitment = identity.genIdentityCommitment(SecretType.MULTIPART)
identityCommitments.push(identityCommitment)
}
})
describe("RLN functionalities", () => {
it("Should generate rln witness", () => {
const identity = new ZkIdentity()
const identityCommitment = identity.genIdentityCommitment()
const secretHash = identity.getMultipartSecretHash()
const leaves = Object.assign([], identityCommitments)
leaves.push(identityCommitment)
const signal = "hey hey"
const epoch: string = genExternalNullifier("test-epoch")
const rlnIdentifier: bigint = RLN.genIdentifier()
const rlnIdentifier = RLN.genIdentifier()
const merkleProof: MerkleProof = generateMerkleProof(15, BigInt(0), 2, commitments, identityCommitment)
const witness: FullProof = RLN.genWitness(secretHash, merkleProof, epoch, signal, rlnIdentifier)
const merkleProof = generateMerkleProof(15, BigInt(0), 2, leaves, identityCommitment)
const witness = RLN.genWitness(secretHash, merkleProof, epoch, signal, rlnIdentifier)
expect(typeof witness).toBe("object")
})
it.skip("Generate rln proof and verify it", async () => {
/**
* Compiled RLN circuits are needed to run this test so it's being skipped in hooks
*/
const identity: ZkIdentity = new ZkIdentity()
const secretHash: bigint = identity.getMultipartSecretHash()
it("Should generate rln proof and verify it", async () => {
const identity = new ZkIdentity()
const secretHash = identity.getMultipartSecretHash()
const identityCommitment = identity.genIdentityCommitment(SecretType.MULTIPART)
const identityCommitment: bigint = identity.genIdentityCommitment(SecretType.MULTIPART)
const commitments: Array<bigint> = Object.assign([], identityCommitments)
commitments.push(identityCommitment)
const leaves = Object.assign([], identityCommitments)
leaves.push(identityCommitment)
const signal = "hey hey"
const signalHash = genSignalHash(signal)
const epoch: string = genExternalNullifier("test-epoch")
const rlnIdentifier: bigint = RLN.genIdentifier()
const epoch = genExternalNullifier("test-epoch")
const rlnIdentifier = RLN.genIdentifier()
const merkleProof: MerkleProof = generateMerkleProof(15, BigInt(0), 2, commitments, identityCommitment)
const witness: FullProof = RLN.genWitness(secretHash, merkleProof, epoch, signal, rlnIdentifier)
const merkleProof = generateMerkleProof(15, BigInt(0), 2, leaves, identityCommitment)
const witness = RLN.genWitness(secretHash, merkleProof, epoch, signal, rlnIdentifier)
const [y, nullifier] = RLN.calculateOutput(secretHash, BigInt(epoch), rlnIdentifier, signalHash)
const publicSignals = [y, merkleProof.root, nullifier, signalHash, epoch, rlnIdentifier]
const vkeyPath: string = path.join("./zkeyFiles", "rln", "verification_key.json")
const vkeyPath = path.join(zkeyFiles, "rln", "verification_key.json")
const vKey = JSON.parse(fs.readFileSync(vkeyPath, "utf-8"))
const wasmFilePath: string = path.join("./zkeyFiles", "rln", "rln.wasm")
const finalZkeyPath: string = path.join("./zkeyFiles", "rln", "rln_final.zkey")
const wasmFilePath = path.join(zkeyFiles, "rln", "rln.wasm")
const finalZkeyPath = path.join(zkeyFiles, "rln", "rln_final.zkey")
const fullProof: FullProof = await RLN.genProof(witness, wasmFilePath, finalZkeyPath)
const res: boolean = await RLN.verifyProof(vKey, { proof: fullProof.proof, publicSignals })
const fullProof = await RLN.genProof(witness, wasmFilePath, finalZkeyPath)
const response = await RLN.verifyProof(vKey, { proof: fullProof.proof, publicSignals })
expect(res).toBe(true)
expect(response).toBe(true)
}, 30000)
it("Should retrieve user secret after spaming", () => {
const identity: ZkIdentity = new ZkIdentity()
const secretHash: bigint = identity.getSecretHash()
const identity = new ZkIdentity()
const secretHash = identity.getSecretHash()
const signal1 = "hey hey"
const signalHash1 = genSignalHash(signal1)
const signal2 = "hey hey again"
const signalHash2 = genSignalHash(signal2)
const epoch: string = genExternalNullifier("test-epoch")
const rlnIdentifier: bigint = RLN.genIdentifier()
const epoch = genExternalNullifier("test-epoch")
const rlnIdentifier = RLN.genIdentifier()
const [y1] = RLN.calculateOutput(secretHash, BigInt(epoch), rlnIdentifier, signalHash1)
const [y2] = RLN.calculateOutput(secretHash, BigInt(epoch), rlnIdentifier, signalHash2)
const retrievedSecret: bigint = RLN.retrieveSecret(signalHash1, signalHash2, y1, y2)
const retrievedSecret = RLN.retrieveSecret(signalHash1, signalHash2, y1, y2)
expect(retrievedSecret).toEqual(secretHash)
})

View File

@@ -1,11 +1,12 @@
import { ZkIdentity } from "@zk-kit/identity"
import { FullProof } from "@zk-kit/types"
import fs from "fs"
import path from "path"
import { Semaphore } from "../src"
import { generateMerkleProof, genExternalNullifier, genSignalHash } from "../src/utils"
describe("Semaphore", () => {
const zkeyFiles = "./packages/protocols/zkeyFiles"
describe("Generate and verify proof", () => {
it("Should generate a Semaphore witness", async () => {
const identity = new ZkIdentity()
@@ -27,8 +28,7 @@ describe("Semaphore", () => {
expect(typeof witness).toBe("object")
})
// Compiled Semaphore circuits are needed to run this test, so it's being skipped in hooks.
it.skip("Should generate semaphore full proof", async () => {
it("Should generate Semaphore full proof", async () => {
const identity = new ZkIdentity()
const identityCommitment = identity.genIdentityCommitment()
const externalNullifier = genExternalNullifier("voting_1")
@@ -45,18 +45,18 @@ describe("Semaphore", () => {
signal
)
const wasmFilePath: string = path.join("./zkeyFiles", "semaphore", "semaphore.wasm")
const finalZkeyPath: string = path.join("./zkeyFiles", "semaphore", "semaphore_final.zkey")
const fullProof: FullProof = await Semaphore.genProof(witness, wasmFilePath, finalZkeyPath)
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 vkeyPath: string = path.join("./zkeyFiles", "semaphore", "verification_key.json")
const vkeyPath = path.join("./packages/protocols/zkeyFiles", "semaphore", "verification_key.json")
const vKey = JSON.parse(fs.readFileSync(vkeyPath, "utf-8"))
const nullifierHash = Semaphore.genNullifierHash(externalNullifier, identity.getNullifier())
const publicSignals = [merkleProof.root.toString(), nullifierHash, genSignalHash(signal), externalNullifier]
const res: boolean = await Semaphore.verifyProof(vKey, { proof: fullProof.proof, publicSignals })
const response = await Semaphore.verifyProof(vKey, { proof: fullProof.proof, publicSignals })
expect(res).toBe(true)
expect(response).toBe(true)
}, 30000)
})
})