From b61a381a1114aeccb507ad032c490744ccdf0634 Mon Sep 17 00:00:00 2001 From: bdim1 Date: Tue, 28 Dec 2021 16:28:26 +0100 Subject: [PATCH] fix: rln/nrln refactoring, identities and types update, zkeyFiles added Former-commit-id: 69221053bfd42ca787e405b90b7654a6320eb797 [formerly b32fc77aa40f6306e415d41807cd2582add75576] [formerly fa913c98a96f91c77d01df6725d77adb020b68aa [formerly 36fcf8482bd40e4a81be7920c6664f4f737becd6]] Former-commit-id: 38c46f3594790895f456019d533aa41b3d01ca31 [formerly a204a646b8d4194514d68dd922183bbecfefdffa] Former-commit-id: d980f64fdcb24cf04c129818c19d7895605f156e --- packages/identity/package.json | 2 +- packages/identity/src/identity.ts | 144 ++++++++++++++--------- packages/identity/src/index.ts | 4 +- packages/identity/tests/identity.test.ts | 5 +- packages/protocols/package.json | 2 +- packages/protocols/src/index.ts | 5 +- packages/protocols/src/nRln.ts | 104 ---------------- packages/protocols/src/rln.ts | 86 +++++++++----- packages/protocols/tests/nrln.test.ts | 66 +++++------ packages/protocols/tests/rln.test.ts | 77 ++++++------ packages/types/package.json | 2 +- packages/types/src/index.ts | 1 + zkeyFiles.zip.REMOVED.git-id | 1 + 13 files changed, 227 insertions(+), 272 deletions(-) delete mode 100644 packages/protocols/src/nRln.ts create mode 100644 zkeyFiles.zip.REMOVED.git-id diff --git a/packages/identity/package.json b/packages/identity/package.json index 78b80c6..577e1f3 100644 --- a/packages/identity/package.json +++ b/packages/identity/package.json @@ -18,7 +18,7 @@ }, "license": "MIT", "dependencies": { - "@libsem/types": "^1.0.7", + "@libsem/types": "^1.0.8", "bigint-conversion": "^2.1.12", "circomlibjs": "^0.0.8", "crypto": "^1.0.1", diff --git a/packages/identity/src/identity.ts b/packages/identity/src/identity.ts index 50069c3..aa35213 100644 --- a/packages/identity/src/identity.ts +++ b/packages/identity/src/identity.ts @@ -14,10 +14,16 @@ export enum Strategy { SERIALIZED } +export enum SecretType { + GENERIC, // generic secret, composed of identityNullifier and identityTrapdoor + MULTIPART_SECRET, // multipart secret, composed from multiple parts dependent on the spam threshold +} + class ZkIdentity { private identityTrapdoor: bigint; private identityNullifier: bigint; private secret: Array = []; + private multipartSecret: Array = []; /** * Generates new ZkIdentity * @param strategy strategy for identity generation @@ -30,86 +36,65 @@ class ZkIdentity { this.identityTrapdoor = identityTrapdoor this.identityNullifier = identityNullifier this.genSecret() + this.genMultipartSecret() } else if (strategy === Strategy.MESSAGE) { const { identityTrapdoor, identityNullifier } = genIdentityFromMessage(metadata as string) this.identityTrapdoor = identityTrapdoor this.identityNullifier = identityNullifier this.genSecret() + this.genMultipartSecret() } else if (strategy === Strategy.SERIALIZED) { - const { identityNullifier, identityTrapdoor, secret } = metadata as SerializedIdentity + const { identityNullifier, identityTrapdoor, secret, multipartSecret } = metadata as SerializedIdentity this.identityNullifier = bigintConversion.hexToBigint(identityNullifier) this.identityTrapdoor = bigintConversion.hexToBigint(identityTrapdoor) this.secret = secret.map(item => bigintConversion.hexToBigint(item)); + this.multipartSecret = multipartSecret.map(item => bigintConversion.hexToBigint(item)); } else throw new Error("provided strategy is not supported") } - - /** - * Unserialize serialized identity - * @param serialisedIdentity - * @returns - */ - static genFromSerialized(serialisedIdentity: string): ZkIdentity { - const data = JSON.parse(serialisedIdentity) - if(!('identityNullifier' in data) || !('identityTrapdoor' in data) || !('secret' in data)) throw new Error("Wrong input identity"); - return new ZkIdentity(Strategy.SERIALIZED, { - identityNullifier: data['identityNullifier'], - identityTrapdoor: data['identityTrapdoor'], - secret: data['secret'] - }) - } - /** - * - * @returns Identity - */ - getIdentity(): Identity { - return { - identityNullifier: this.identityNullifier, - identityTrapdoor: this.identityTrapdoor - } - } - - getNullifier(): bigint { - return this.identityNullifier - } - - getSecret(): Array { - return this.secret - } - - - getSecretHash(): bigint { - return poseidonHash(this.secret) - } + // Secret and identity generation /** - * Creates secret from ZkIdentity - * @returns + * Generate generic secret. To be used by Semaphore related apps. */ - genSecret(parts = 2): void { + genSecret(): void { + this.secret = [this.identityNullifier, this.identityTrapdoor] + } + + /** + * Generate multipart secret. To be used by RLN related apps. + * @param parts The number of parts that the secret should be composed of, + * corresponding to the spam threshold of the protocol + */ + genMultipartSecret(parts = 2): void { if(parts < 2) throw new Error("Invalid number of parts"); - if(parts === 2) { - this.secret = [this.identityNullifier, this.identityTrapdoor] - } else { - const initialComponent = Fq.pow(this.identityTrapdoor, this.identityNullifier); - this.secret = [initialComponent] - for(let i = 1; i < parts; i++) { - this.secret.push(Fq.pow(initialComponent, BigInt(i + 1))) - } + + const initialComponent = Fq.pow(this.identityTrapdoor, this.identityNullifier); + this.multipartSecret = [initialComponent] + for(let i = 1; i < parts; i++) { + this.multipartSecret.push(Fq.pow(initialComponent, BigInt(i + 1))) } + } /** - * Generate commitment from identity + * Generate commitment from secret + * @param secretType The secret type for which to generate identity commitment * @returns identity commitment */ - genIdentityCommitment(): bigint { - const secretHash = this.getSecretHash(); + genIdentityCommitment(secretType: SecretType = SecretType.GENERIC): bigint { + let secretHash = this.getSecretHash(); + if(secretType === SecretType.MULTIPART_SECRET) { + secretHash = this.getMultipartSecretHash(); + } return poseidonHash([secretHash]) } + // Serialization + + /** * Serializes the `identityNullifier`, `identityTrapdoor` and `secret` from the identity * @returns stringified serialized identity @@ -118,10 +103,61 @@ class ZkIdentity { const data: SerializedIdentity = { identityNullifier: this.identityNullifier.toString(16), identityTrapdoor: this.identityTrapdoor.toString(16), - secret: this.secret.map(item => item.toString(16)) + secret: this.secret.map(item => item.toString(16)), + multipartSecret: this.multipartSecret.map(item => item.toString(16)) } return JSON.stringify(data); } + + /** + * Unserialize serialized identity + * @param serialisedIdentity + * @returns + */ + static genFromSerialized(serialisedIdentity: string): ZkIdentity { + const data = JSON.parse(serialisedIdentity) + if(!('identityNullifier' in data) || !('identityTrapdoor' in data) || !('secret' in data) || !('multipartSecret' in data)) throw new Error("Wrong input identity"); + return new ZkIdentity(Strategy.SERIALIZED, { + identityNullifier: data['identityNullifier'], + identityTrapdoor: data['identityTrapdoor'], + secret: data['secret'], + multipartSecret: data['multipartSecret'] + }) + } + + // Getters + + /** + * Return the raw user identity, composed of identityNullifier and identityTrapdoor. + * @returns Identity + */ + getIdentity(): Identity { + return { + identityNullifier: this.identityNullifier, + identityTrapdoor: this.identityTrapdoor + } + } + + getNullifier(): bigint { + return this.identityNullifier + } + + getSecret(): Array { + return this.secret + } + + getMultipartSecret(): Array { + return this.multipartSecret + } + + getSecretHash(): bigint { + return poseidonHash(this.secret) + } + + getMultipartSecretHash(): bigint { + return poseidonHash(this.multipartSecret); + } + } export default ZkIdentity diff --git a/packages/identity/src/index.ts b/packages/identity/src/index.ts index 7da71c1..ddacda7 100644 --- a/packages/identity/src/index.ts +++ b/packages/identity/src/index.ts @@ -1,4 +1,4 @@ -import ZkIdentity, { Strategy } from "./identity" +import ZkIdentity, { Strategy, SecretType } from "./identity" import { Identity } from "@libsem/types" -export { ZkIdentity, Identity, Strategy } +export { ZkIdentity, Identity, Strategy, SecretType } diff --git a/packages/identity/tests/identity.test.ts b/packages/identity/tests/identity.test.ts index 484e55e..e027c29 100644 --- a/packages/identity/tests/identity.test.ts +++ b/packages/identity/tests/identity.test.ts @@ -26,8 +26,8 @@ describe("Semaphore identity", () => { it("Should generate multipart secret", async () => { const secretParts = 5 const identity: ZkIdentity = new ZkIdentity() - identity.genSecret(secretParts) - const identitySecret = identity.getSecret() + identity.genMultipartSecret(secretParts) + const identitySecret = identity.getMultipartSecret() expect(identitySecret.length).toEqual(5) expect(typeof identitySecret).toEqual("object") @@ -35,7 +35,6 @@ describe("Semaphore identity", () => { it("Should generate identity commitment from identity", async () => { const identity: ZkIdentity = new ZkIdentity() - identity.genSecret(); const identityCommitment: bigint = identity.genIdentityCommitment() expect(typeof identityCommitment).toEqual("bigint") diff --git a/packages/protocols/package.json b/packages/protocols/package.json index 9b6ff0f..40a349b 100644 --- a/packages/protocols/package.json +++ b/packages/protocols/package.json @@ -24,7 +24,7 @@ "access": "public" }, "dependencies": { - "@libsem/types": "^1.0.7", + "@libsem/types": "^1.0.8", "circomlibjs": "^0.0.8", "ethers": "^5.4.7", "incrementalquintree": "^1.0.7", diff --git a/packages/protocols/src/index.ts b/packages/protocols/src/index.ts index b15c78b..b004af4 100644 --- a/packages/protocols/src/index.ts +++ b/packages/protocols/src/index.ts @@ -1,7 +1,6 @@ import Semaphore from "./semaphore" -import Rln from "./rln" -import NRln from "./nRln" +import RLN from "./rln" import { generateMerkleProof, genExternalNullifier, genSignalHash, Fq } from "./utils" import { Identity, MerkleProof, FullProof } from "@libsem/types" -export { Semaphore, Rln, NRln, generateMerkleProof, genExternalNullifier, genSignalHash, Identity, MerkleProof, FullProof } +export { Semaphore, RLN, generateMerkleProof, genExternalNullifier, genSignalHash, Identity, MerkleProof, FullProof } diff --git a/packages/protocols/src/nRln.ts b/packages/protocols/src/nRln.ts deleted file mode 100644 index 3fd821e..0000000 --- a/packages/protocols/src/nRln.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { ZkProtocol } from "./zk-protocol" -import { genSignalHash, poseidonHash } from "./utils" -import { Fq } from "./utils" - -class NRln extends ZkProtocol { - /** - * Creates witness for nrln proof - * @param identitySecret identity secret - * @param merkleProof merkle proof that identity exists in nrln tree - * @param epoch epoch on which signal is broadcasted - * @param signal signal that is being broadcasted - * @param rlnIdentifier identifier used by each separate app, needed for more accurate spam filtering - * @param shouldHash should signal be hashed before broadcast - * @returns rln witness - */ - genWitness( - identitySecret: Array, - merkleProof: any, - epoch: string | bigint, - signal: string, - rlnIdentifier: bigint, - shouldHash = true - ): any { - return { - identity_secret: identitySecret, - path_elements: merkleProof.pathElements, - identity_path_index: merkleProof.indices, - x: shouldHash ? genSignalHash(signal) : signal, - epoch, - rln_identifier: rlnIdentifier - } - } - - /** - * - * @param identitySecret identity secret - * @param epoch epoch - * @param x singal hash - * @param limit number of messages per epoch allowed - * @param rlnIdentifier identifier used by each separate app, needed for more accurate spam filtering - * @returns - */ - calculateOutput(identitySecret: Array, epoch: bigint, x: bigint, limit: number, rlnIdentifier: bigint): Array { - const a0 = poseidonHash(identitySecret) - - const coeffs: Array = [] - let tmpX = x - - coeffs.push(poseidonHash([identitySecret[0], epoch])) - let y: bigint = Fq.add(Fq.mul(coeffs[0], tmpX), a0) - - for (let i = 1; i < limit; i++) { - tmpX = Fq.mul(x, tmpX) - - coeffs.push(poseidonHash([identitySecret[i], epoch])) - y = Fq.add(y, Fq.mul(coeffs[i], tmpX)) - } - - coeffs.push(poseidonHash([rlnIdentifier])); - const nullifier: bigint = this.genNullifier(coeffs) - return [y, nullifier] - } - - /** - * Calculates slashing nullifier - * @param coeffs coeefitients from calculated polinomial - * @returns slashing nullifier - */ - genNullifier(coeffs: Array): bigint { - return poseidonHash(coeffs) - } - - /** - * When spam occurs, identity secret can be retrieved - * @param xs - * @param ys - * @returns identity secret - */ - retrieveSecret(xs: Array, ys: Array): 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++) { - let p = BigInt(1) - for (let j = 0; j < numOfPoints; j++) { - if (j !== i) { - p = Fq.mul(p, Fq.div(xs[j], Fq.sub(xs[j], xs[i]))) - } - } - f0 = Fq.add(f0, Fq.mul(ys[i], p)) - } - return f0 - } - - /** - * - * @returns unique identifier of the rln dapp - */ - genIdentifier(): bigint { - return Fq.random() - } -} - -export default new NRln() diff --git a/packages/protocols/src/rln.ts b/packages/protocols/src/rln.ts index 6a8952d..48b54f6 100644 --- a/packages/protocols/src/rln.ts +++ b/packages/protocols/src/rln.ts @@ -2,19 +2,19 @@ import { ZkProtocol } from "./zk-protocol" import { genSignalHash, poseidonHash } from "./utils" import { Fq } from "./utils" -class Rln extends ZkProtocol { +class RLN extends ZkProtocol { /** - * Creates witness for rln proof + * Creates witness for RLN proof * @param identitySecret identity secret - * @param merkleProof merkle proof that identity exists in rln tree + * @param merkleProof merkle proof that identity exists in RLN tree * @param epoch epoch on which signal is broadcasted * @param signal signal that is being broadcasted - * @param rlnIdentifier unique identifier of rln dapp + * @param rlnIdentifier identifier used by each separate app, needed for more accurate spam filtering * @param shouldHash should signal be hashed before broadcast * @returns rln witness */ genWitness( - identitySecret: bigint, + identitySecret: Array, merkleProof: any, epoch: string | bigint, signal: string, @@ -32,51 +32,73 @@ class Rln extends ZkProtocol { } /** - * Calculates + * * @param identitySecret identity secret - * @param epoch epoch on which signal is broadcasted - * @param rlnIdentifier unique identifier of rln dapp - * @param x signal hash - * @returns y & slashing nullfier + * @param epoch epoch + * @param x singal hash + * @param limit number of messages per epoch allowed + * @param rlnIdentifier identifier used by each separate app, needed for more accurate spam filtering + * @returns */ - calculateOutput(identitySecret: bigint, epoch: bigint, rlnIdentifier: bigint, x: bigint): Array { - const a1: bigint = poseidonHash([identitySecret, epoch]) - const y: bigint = Fq.normalize(a1 * x + identitySecret) - const nullifier = this.genNullifier(a1, rlnIdentifier) + calculateOutput(identitySecret: Array, epoch: bigint, x: bigint, limit: number, rlnIdentifier: bigint): Array { + const a0 = poseidonHash(identitySecret) + + const coeffs: Array = [] + let tmpX = x + + coeffs.push(poseidonHash([identitySecret[0], epoch])) + let y: bigint = Fq.add(Fq.mul(coeffs[0], tmpX), a0) + + for (let i = 1; i < limit; i++) { + tmpX = Fq.mul(x, tmpX) + + coeffs.push(poseidonHash([identitySecret[i], epoch])) + y = Fq.add(y, Fq.mul(coeffs[i], tmpX)) + } + + coeffs.push(poseidonHash([rlnIdentifier])); + const nullifier: bigint = this.genNullifier(coeffs) return [y, nullifier] } /** - * - * @param a1 y = a1 * x + a0 (a1 = poseidonHash(identity secret, epoch, rlnIdentifier)) - * @param rlnIdentifier unique identifier of rln dapp - * @returns rln slashing nullifier + * Calculates slashing nullifier + * @param coeffs coeefitients from calculated polinomial + * @returns slashing nullifier */ - genNullifier(a1: bigint, rlnIdentifier: bigint): bigint { - return poseidonHash([a1, rlnIdentifier]) + genNullifier(coeffs: Array): bigint { + return poseidonHash(coeffs) } /** * When spam occurs, identity secret can be retrieved - * @param x1 x1 - * @param x2 x2 - * @param y1 y1 - * @param y2 y2 + * @param xs + * @param ys * @returns identity secret */ - retrieveSecret(x1: bigint, x2: bigint, y1: bigint, y2: bigint): bigint { - const slope = Fq.div(Fq.sub(y2, y1), Fq.sub(x2, x1)) - const privateKey = Fq.sub(y1, Fq.mul(slope, x1)) - return Fq.normalize(privateKey) + retrieveSecret(xs: Array, ys: Array): 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++) { + let p = BigInt(1) + for (let j = 0; j < numOfPoints; j++) { + if (j !== i) { + p = Fq.mul(p, Fq.div(xs[j], Fq.sub(xs[j], xs[i]))) + } + } + f0 = Fq.add(f0, Fq.mul(ys[i], p)) + } + return f0 } /** * * @returns unique identifier of the rln dapp */ - genIdentifier(): bigint { - return Fq.random() - } + genIdentifier(): bigint { + return Fq.random() + } } -export default new Rln() +export default new RLN() diff --git a/packages/protocols/tests/nrln.test.ts b/packages/protocols/tests/nrln.test.ts index 39d334b..a76f0cb 100644 --- a/packages/protocols/tests/nrln.test.ts +++ b/packages/protocols/tests/nrln.test.ts @@ -1,5 +1,5 @@ -import { NRln } from "../src" -import { ZkIdentity } from "../../identity/src" +import { RLN } from "../src" +import { ZkIdentity, SecretType } from "../../identity/src" import { MerkleProof, FullProof } from "../../types" import { genSignalHash, genExternalNullifier, generateMerkleProof, poseidonHash } from "../src/utils" import * as path from "path" @@ -13,42 +13,42 @@ beforeAll(() => { for (let i = 0; i < leafIndex; i++) { const tmpIdentity = new ZkIdentity(); - tmpIdentity.genSecret(SPAM_TRESHOLD); - const tmpCommitment: bigint = tmpIdentity.genIdentityCommitment(); + tmpIdentity.genMultipartSecret(SPAM_TRESHOLD); + const tmpCommitment: bigint = tmpIdentity.genIdentityCommitment(SecretType.MULTIPART_SECRET); identityCommitments.push(tmpCommitment) } }) -describe("NRln", () => { - describe("NRln functionalities", () => { - it("Generate nrln witness", () => { +describe("RLN with non default spam threshold", () => { + describe("RLN features", () => { + it("Generate RLN witness", () => { const identity: ZkIdentity = new ZkIdentity(); - identity.genSecret(SPAM_TRESHOLD); + identity.genMultipartSecret(SPAM_TRESHOLD); - const identityCommitment: bigint = identity.genIdentityCommitment(); - const identitySecret: bigint[] = identity.getSecret(); + const identityCommitment: bigint = identity.genIdentityCommitment(SecretType.MULTIPART_SECRET); + const identitySecret: bigint[] = identity.getMultipartSecret(); const commitments: Array = Object.assign([], identityCommitments) commitments.push(identityCommitment) const signal = "hey hey" const epoch: string = genExternalNullifier("test-epoch") - const rlnIdentifier: bigint = NRln.genIdentifier() + const rlnIdentifier: bigint = RLN.genIdentifier() const merkleProof: MerkleProof = generateMerkleProof(15, BigInt(0), 2, commitments, identityCommitment) - const witness: FullProof = NRln.genWitness(identitySecret, merkleProof, epoch, signal, rlnIdentifier) + const witness: FullProof = RLN.genWitness(identitySecret, merkleProof, epoch, signal, rlnIdentifier) expect(typeof witness).toBe("object") }) - it.skip("Generate nrln proof and verify it", async () => { + it.skip("Generate RLN proof and verify it", async () => { /** - * Compiled NRln circuits are needed to run this test so it's being skipped in hooks + * Compiled RLN circuits are needed to run this test so it's being skipped in hooks */ const identity: ZkIdentity = new ZkIdentity(); - identity.genSecret(SPAM_TRESHOLD); + identity.genMultipartSecret(SPAM_TRESHOLD); - const identityCommitment: bigint = identity.genIdentityCommitment(); - const identitySecret: bigint[] = identity.getSecret(); + const identityCommitment: bigint = identity.genIdentityCommitment(SecretType.MULTIPART_SECRET); + const identitySecret: bigint[] = identity.getMultipartSecret(); const commitments: Array = Object.assign([], identityCommitments) commitments.push(identityCommitment) @@ -56,30 +56,30 @@ describe("NRln", () => { const signal = "hey hey" const signalHash = genSignalHash(signal) const epoch: string = genExternalNullifier("test-epoch") - const rlnIdentifier: bigint = NRln.genIdentifier() + const rlnIdentifier: bigint = RLN.genIdentifier() const merkleProof: MerkleProof = generateMerkleProof(15, BigInt(0), 2, commitments, identityCommitment) - const witness: FullProof = NRln.genWitness(identitySecret, merkleProof, epoch, signal, rlnIdentifier) + const witness: FullProof = RLN.genWitness(identitySecret, merkleProof, epoch, signal, rlnIdentifier) - const [y, nullifier] = NRln.calculateOutput(identitySecret, BigInt(epoch), signalHash, SPAM_TRESHOLD, rlnIdentifier) + const [y, nullifier] = RLN.calculateOutput(identitySecret, BigInt(epoch), signalHash, SPAM_TRESHOLD, rlnIdentifier) const publicSignals = [y, merkleProof.root, nullifier, signalHash, epoch, rlnIdentifier] - const vkeyPath: string = path.join("./zkeyFiles", "nrln", "verification_key.json") + const vkeyPath: string = path.join("./zkeyFiles", "rln_3", "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: string = path.join("./zkeyFiles", "rln_3", "rln.wasm") + const finalZkeyPath: string = path.join("./zkeyFiles", "rln_3", "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: FullProof = await RLN.genProof(witness, wasmFilePath, finalZkeyPath) + const res: boolean = await RLN.verifyProof(vKey, { proof: fullProof.proof, publicSignals }) expect(res).toBe(true) }, 30000) it("Should retrieve user secret after spaming", () => { const identity: ZkIdentity = new ZkIdentity(); - identity.genSecret(SPAM_TRESHOLD); + identity.genMultipartSecret(SPAM_TRESHOLD); - const identitySecret: bigint[] = identity.getSecret(); + const identitySecret: bigint[] = identity.getMultipartSecret(); const signal1 = "hey 1" const signalHash1 = genSignalHash(signal1) @@ -91,14 +91,14 @@ describe("NRln", () => { const signalHash4 = genSignalHash(signal4) const epoch: string = genExternalNullifier("test-epoch") - const rlnIdentifier: bigint = NRln.genIdentifier() + const rlnIdentifier: bigint = RLN.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 [y1] = RLN.calculateOutput(identitySecret, BigInt(epoch), signalHash1, SPAM_TRESHOLD, rlnIdentifier) + const [y2] = RLN.calculateOutput(identitySecret, BigInt(epoch), signalHash2, SPAM_TRESHOLD, rlnIdentifier) + const [y3] = RLN.calculateOutput(identitySecret, BigInt(epoch), signalHash3, SPAM_TRESHOLD, rlnIdentifier) + const [y4] = RLN.calculateOutput(identitySecret, BigInt(epoch), signalHash4, SPAM_TRESHOLD, rlnIdentifier) - const retrievedSecret: bigint = NRln.retrieveSecret([signalHash1, signalHash2, signalHash3, signalHash4], [y1, y2, y3, y4]) + const retrievedSecret: bigint = RLN.retrieveSecret([signalHash1, signalHash2, signalHash3, signalHash4], [y1, y2, y3, y4]) expect(retrievedSecret).toEqual(poseidonHash(identitySecret)); }) diff --git a/packages/protocols/tests/rln.test.ts b/packages/protocols/tests/rln.test.ts index a855b86..a1551b9 100644 --- a/packages/protocols/tests/rln.test.ts +++ b/packages/protocols/tests/rln.test.ts @@ -1,7 +1,7 @@ -import { Rln } from "../src" -import { ZkIdentity } from "../../identity/src" +import { RLN } from "../src" +import { ZkIdentity, SecretType } from "../../identity/src" import { MerkleProof, FullProof } from "../../types" -import { genSignalHash, genExternalNullifier, generateMerkleProof, poseidonHash } from "../src/utils" +import { genSignalHash, genExternalNullifier, generateMerkleProof } from "../src/utils" import * as path from "path" import * as fs from "fs" @@ -12,38 +12,39 @@ beforeAll(() => { for (let i = 0; i < leafIndex; i++) { const tmpIdentity = new ZkIdentity(); - const tmpCommitment: bigint = tmpIdentity.genIdentityCommitment(); + const tmpCommitment: bigint = tmpIdentity.genIdentityCommitment(SecretType.MULTIPART_SECRET); identityCommitments.push(tmpCommitment) } }) -describe("Rln", () => { - describe("Rln functionalities", () => { - it("Generate rln witness", () => { +describe("RLN with default spam threshold", () => { + describe("RLN functionalities", () => { + it("Generate RLN witness", () => { const identity: ZkIdentity = new ZkIdentity(); - const identityCommitment: bigint = identity.genIdentityCommitment(); - const secretHash: bigint = poseidonHash(identity.getSecret()); + const identityCommitment: bigint = identity.genIdentityCommitment(SecretType.MULTIPART_SECRET); + const secret: bigint[] = identity.getMultipartSecret(); const commitments: Array = Object.assign([], identityCommitments) commitments.push(identityCommitment) const signal = "hey hey" const epoch: string = genExternalNullifier("test-epoch") - const rlnIdentifier: bigint = Rln.genIdentifier() + const rlnIdentifier: bigint = RLN.genIdentifier() - const merkleProof: MerkleProof = generateMerkleProof(15, BigInt(0), 5, commitments, identityCommitment) - const witness: FullProof = Rln.genWitness(secretHash, merkleProof, epoch, signal, rlnIdentifier) + const merkleProof: MerkleProof = generateMerkleProof(15, BigInt(0), 2, commitments, identityCommitment) + const witness: FullProof = RLN.genWitness(secret, merkleProof, epoch, signal, rlnIdentifier) expect(typeof witness).toBe("object") }) - it.skip("Generate rln proof and verify it", async () => { + 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 = poseidonHash(identity.getSecret()); - - const identityCommitment: bigint = identity.genIdentityCommitment(); + identity.genMultipartSecret(2); + const secret: bigint[] = identity.getMultipartSecret(); + console.log("multipart secret", secret); + const identityCommitment: bigint = identity.genIdentityCommitment(SecretType.MULTIPART_SECRET); const commitments: Array = Object.assign([], identityCommitments) commitments.push(identityCommitment) @@ -51,43 +52,43 @@ describe("Rln", () => { const signal = "hey hey" const signalHash = genSignalHash(signal) const epoch: string = genExternalNullifier("test-epoch") - const rlnIdentifier: bigint = Rln.genIdentifier() + const rlnIdentifier: bigint = RLN.genIdentifier() const merkleProof: MerkleProof = generateMerkleProof(15, BigInt(0), 2, commitments, identityCommitment) - const witness: FullProof = Rln.genWitness(secretHash, merkleProof, epoch, signal, rlnIdentifier) + const witness: FullProof = RLN.genWitness(secret, merkleProof, epoch, signal, rlnIdentifier) - const [y, nullifier] = Rln.calculateOutput(secretHash, BigInt(epoch), rlnIdentifier, signalHash) + const [y, nullifier] = RLN.calculateOutput(secret, BigInt(epoch), signalHash, 2, rlnIdentifier); const publicSignals = [y, merkleProof.root, nullifier, signalHash, epoch, rlnIdentifier] - const vkeyPath: string = path.join("./zkeyFiles", "rln", "verification_key.json") + const vkeyPath: string = path.join("./zkeyFiles", "rln_default", "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: string = path.join("./zkeyFiles", "rln_default", "rln.wasm") + const finalZkeyPath: string = path.join("./zkeyFiles", "rln_default", "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: FullProof = await RLN.genProof(witness, wasmFilePath, finalZkeyPath) + const res: boolean = await RLN.verifyProof(vKey, { proof: fullProof.proof, publicSignals }) expect(res).toBe(true) }, 30000) - it("Should retrieve user secret after spaming", () => { - const identity: ZkIdentity = new ZkIdentity(); - const secretHash: bigint = poseidonHash(identity.getSecret()); + // it("Should retrieve user secret after spaming", () => { + // const identity: ZkIdentity = new ZkIdentity(); + // const secret: bigint[] = identity.getMultipartSecret(); - const signal1 = "hey hey" - const signalHash1 = genSignalHash(signal1) - const signal2 = "hey hey again" - const signalHash2 = genSignalHash(signal2) + // 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: string = genExternalNullifier("test-epoch") + // const rlnIdentifier: bigint = RLN.genIdentifier() - const [y1] = Rln.calculateOutput(secretHash, BigInt(epoch), rlnIdentifier, signalHash1) - const [y2] = Rln.calculateOutput(secretHash, BigInt(epoch), rlnIdentifier, signalHash2) + // const [y1] = RLN.calculateOutput(secret, BigInt(epoch), signalHash1, 2, rlnIdentifier ) + // const [y2] = RLN.calculateOutput(secret, BigInt(epoch), signalHash2, 2, rlnIdentifier) - const retrievedSecret: bigint = Rln.retrieveSecret(signalHash1, signalHash2, y1, y2) + // const retrievedSecret: bigint = RLN.retrieveSecret([signalHash1, signalHash2], [y1, y2]) - expect(retrievedSecret).toEqual(secretHash) - }) + // expect(retrievedSecret).toEqual(secret) + // }) }) }) diff --git a/packages/types/package.json b/packages/types/package.json index 9bbf992..2a03d68 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@libsem/types", - "version": "1.0.7", + "version": "1.0.8", "description": "Common type definitions for Semaphore modules.", "main": "src/index.ts", "types": "dist/index.d.ts", diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 19e6569..f5bf382 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -26,4 +26,5 @@ export declare type SerializedIdentity = { identityNullifier: string; identityTrapdoor: string; secret: string[]; + multipartSecret: string[]; }; \ No newline at end of file diff --git a/zkeyFiles.zip.REMOVED.git-id b/zkeyFiles.zip.REMOVED.git-id new file mode 100644 index 0000000..eb7e3a1 --- /dev/null +++ b/zkeyFiles.zip.REMOVED.git-id @@ -0,0 +1 @@ +84e86da6e86f333fb01d6cd1576b7b3657dca3e6 \ No newline at end of file