From 51388a7c9674657a634209a61375e69d222fdba5 Mon Sep 17 00:00:00 2001 From: bdim1 Date: Wed, 2 Feb 2022 22:27:58 +0100 Subject: [PATCH 1/2] fix: rln changes & nrln removal --- packages/identity/src/identity.ts | 67 +-------------- packages/identity/src/index.ts | 4 +- packages/identity/tests/index.test.ts | 33 +------ packages/protocols/src/index.ts | 2 - packages/protocols/src/nrln.ts | 114 ------------------------ packages/protocols/tests/nrln.test.ts | 119 -------------------------- packages/protocols/tests/rln.test.ts | 10 +-- types/zk-kit/index.d.ts | 1 - 8 files changed, 13 insertions(+), 337 deletions(-) delete mode 100644 packages/protocols/src/nrln.ts delete mode 100644 packages/protocols/tests/nrln.test.ts diff --git a/packages/identity/src/identity.ts b/packages/identity/src/identity.ts index dde00b7..78c8b53 100644 --- a/packages/identity/src/identity.ts +++ b/packages/identity/src/identity.ts @@ -10,12 +10,6 @@ export enum Strategy { SERIALIZED // Identity parameters are passed from outside. } -// The secret type is used for the identity commitment generation. -export enum SecretType { - GENERIC, // Generic secret, composed of identityNullifier and identityTrapdoor. - MULTIPART // Multipart secret, composed from multiple parts dependent on the spam threshold. -} - /** * ZkIdentity is a class which can be used by protocols supported by the * @zk-key/protocols package and it simplifies the management of @@ -26,8 +20,6 @@ export default class ZkIdentity { private _identityNullifier: bigint private _secret: bigint[] = [] - private _multipartSecret: bigint[] = [] - private _defaultMultipartSecret: bigint[] = [] /** * Initializes the class attributes based on the strategy passed as parameter. @@ -40,8 +32,6 @@ export default class ZkIdentity { this._identityTrapdoor = genRandomNumber() this._identityNullifier = genRandomNumber() this._secret = [this._identityNullifier, this._identityTrapdoor] - this._setMultipartSecret() - break } case Strategy.MESSAGE: { @@ -58,8 +48,6 @@ export default class ZkIdentity { this._identityTrapdoor = hexToBigint(sha256(`${messageHash}identity_trapdoor`)) this._identityNullifier = hexToBigint(sha256(`${messageHash}identity_nullifier`)) this._secret = [this._identityNullifier, this._identityTrapdoor] - this._setMultipartSecret() - break } case Strategy.SERIALIZED: { @@ -78,19 +66,16 @@ export default class ZkIdentity { if ( !("identityNullifier" in metadata) || !("identityTrapdoor" in metadata) || - !("secret" in metadata) || - !("multipartSecret" in metadata) + !("secret" in metadata) ) { throw new Error("The serialized identity does not contain the right parameter") } - const { identityNullifier, identityTrapdoor, secret, multipartSecret } = metadata + const { identityNullifier, identityTrapdoor, secret } = metadata this._identityNullifier = hexToBigint(identityNullifier) this._identityTrapdoor = hexToBigint(identityTrapdoor) this._secret = secret.map((item) => hexToBigint(item)) - this._multipartSecret = multipartSecret.map((item) => hexToBigint(item)) - this._defaultMultipartSecret = this._multipartSecret.slice(0, 2) break } @@ -99,21 +84,6 @@ export default class ZkIdentity { } } - /** - * Sets the multipart secret attribute. - */ - private _setMultipartSecret(): void { - const initialComponent = Fq.pow(this._identityTrapdoor, this._identityNullifier) - - this._multipartSecret = [initialComponent] - - for (let i = 1; i < 16; i += 1) { - this._multipartSecret.push(Fq.pow(initialComponent, BigInt(i + 1))) - } - - this._defaultMultipartSecret = this._multipartSecret.slice(0, 2) - } - /** * Returns the identity trapdoor. * @returns The identity trapdoor. @@ -138,15 +108,6 @@ export default class ZkIdentity { return this._secret } - /** - * Returns the default multipart secret or a portion of the multipart secret. - * @param secretParts The number of the secret parts. - * @returns The multipart secret. - */ - public getMultipartSecret(secretParts: number = 2): bigint[] { - return secretParts === 2 ? this._defaultMultipartSecret : this._multipartSecret.slice(0, secretParts) - } - /** * Returns the Poseidon hash of the secret. * @returns The hash of the secret. @@ -155,32 +116,13 @@ export default class ZkIdentity { return poseidon(this._secret) } - /** - * Returns the Poseidon hash of the multipart secret. - * @param secretParts The number of the secret parts. - * @returns The hash of the multipart secret. - */ - public getMultipartSecretHash(secretParts: number = 2): bigint { - const multipartSecret = this.getMultipartSecret(secretParts) - - return poseidon(multipartSecret) - } /** - * Generates the identity commitment from the secret or the multipart secret. - * @param secretType The secret type for which to generate identity commitment - * @param secretParts The number of the secret parts. + * Generates the identity commitment from the secret. * @returns identity commitment */ - public genIdentityCommitment(secretType: SecretType = SecretType.GENERIC, secretParts: number = 2): bigint { - switch (secretType) { - case SecretType.GENERIC: + public genIdentityCommitment(): bigint { return poseidon([this.getSecretHash()]) - case SecretType.MULTIPART: - return poseidon([this.getMultipartSecretHash(secretParts)]) - default: - throw new Error("The provided secret type is not supported") - } } /** @@ -192,7 +134,6 @@ export default class ZkIdentity { identityNullifier: this._identityNullifier.toString(16), identityTrapdoor: this._identityTrapdoor.toString(16), secret: this._secret.map((item) => item.toString(16)), - multipartSecret: this._multipartSecret.map((item) => item.toString(16)) } return JSON.stringify(data) diff --git a/packages/identity/src/index.ts b/packages/identity/src/index.ts index 7e66396..02d708a 100644 --- a/packages/identity/src/index.ts +++ b/packages/identity/src/index.ts @@ -1,3 +1,3 @@ -import ZkIdentity, { SecretType, Strategy } from "./identity" +import ZkIdentity, { Strategy } from "./identity" -export { ZkIdentity, Strategy, SecretType } +export { ZkIdentity, Strategy } diff --git a/packages/identity/tests/index.test.ts b/packages/identity/tests/index.test.ts index 3956f8b..9aa58ef 100644 --- a/packages/identity/tests/index.test.ts +++ b/packages/identity/tests/index.test.ts @@ -1,4 +1,4 @@ -import { SecretType, Strategy, ZkIdentity } from "../src" +import { Strategy, ZkIdentity } from "../src" describe("ZK identity", () => { describe("Create identity", () => { @@ -32,35 +32,15 @@ describe("ZK identity", () => { const trapdoor = identity.getTrapdoor() const nullifier = identity.getNullifier() const identitySecret = identity.getSecret() - const identityMultipartSecret = identity.getMultipartSecret(5) expect(typeof identity).toBe("object") expect(trapdoor).toBe(BigInt("58952291509798197436757858062402199043831251943841934828591473955215726495831")) expect(nullifier).toBe(BigInt("44673097405870585416457571638073245190425597599743560105244308998175651589997")) expect(identitySecret).toHaveLength(2) expect(typeof identitySecret).toBe("object") - expect(identityMultipartSecret).toHaveLength(5) - expect(typeof identityMultipartSecret).toBe("object") }) - it("Should get the multipart secret hash", () => { - const identity = new ZkIdentity(Strategy.MESSAGE, "message") - - const multipartSecretHash = identity.getMultipartSecretHash(2) - - expect(multipartSecretHash).toBe( - BigInt("6297169125057226632028063090073601040720936421655236852498563322517193066452") - ) - }) - - it("Should not generate identity commitment if the secret type is wrong", () => { - const identity = new ZkIdentity() - const fun = () => identity.genIdentityCommitment("wrong" as any) - - expect(fun).toThrow("secret type is not supported") - }) - - it("Should generate an identity commitment from a generic secret", () => { + it("Should generate an identity commitment secret", () => { const identity = new ZkIdentity(Strategy.MESSAGE, "message") const identityCommitment = identity.genIdentityCommitment() @@ -69,15 +49,6 @@ describe("ZK identity", () => { ) }) - it("Should generate an identity commitment from a multipart secret", () => { - const identity = new ZkIdentity(Strategy.MESSAGE, "message") - const identityCommitment = identity.genIdentityCommitment(SecretType.MULTIPART) - - expect(identityCommitment).toBe( - BigInt("2814782719841798642796697732526373861365963990553246162063123378852339665110") - ) - }) - it("Should serialize an identity", () => { const identity = new ZkIdentity() const serialized = identity.serializeIdentity() diff --git a/packages/protocols/src/index.ts b/packages/protocols/src/index.ts index 29f2fac..43796a5 100644 --- a/packages/protocols/src/index.ts +++ b/packages/protocols/src/index.ts @@ -1,13 +1,11 @@ import { FullProof, MerkleProof, SolidityProof } from "@zk-kit/types" import RLN from "./rln" -import NRLN from "./nrln" import Semaphore from "./semaphore" import { generateMerkleProof, genExternalNullifier, genSignalHash } from "./utils" export { Semaphore, RLN, - NRLN, generateMerkleProof, genExternalNullifier, genSignalHash, diff --git a/packages/protocols/src/nrln.ts b/packages/protocols/src/nrln.ts deleted file mode 100644 index dc6ff4d..0000000 --- a/packages/protocols/src/nrln.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { MerkleProof, StrBigInt } from "@zk-kit/types" -import { poseidon } from "circomlibjs" -import { Fq, genSignalHash } from "./utils" -import ZkProtocol from "./zk-protocol" - -export default class NRLN extends ZkProtocol { - /** - * Creates witness for RLN proof - * @param identitySecret identity secret - * @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 identifier used by each separate app, needed for more accurate spam filtering - * @param shouldHash should signal be hashed before broadcast - * @returns rln witness - */ - public static genWitness( - identitySecret: bigint[], - merkleProof: MerkleProof, - epoch: StrBigInt, - signal: string, - rlnIdentifier: bigint, - shouldHash = true - ): any { - return { - identity_secret: identitySecret, - path_elements: merkleProof.siblings, - identity_path_index: merkleProof.pathIndices, - 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 - */ - public static calculateOutput( - identitySecret: bigint[], - epoch: bigint, - x: bigint, - limit: number, - rlnIdentifier: bigint - ): bigint[] { - const a0 = poseidon(identitySecret) - const coeffs: bigint[] = [] - - let tmpX = x - - coeffs.push(poseidon([identitySecret[0], epoch])) - let y: bigint = Fq.add(Fq.mul(coeffs[0], tmpX), a0) - - for (let i = 1; i < limit; i += 1) { - tmpX = Fq.mul(x, tmpX) - - coeffs.push(poseidon([identitySecret[i], epoch])) - y = Fq.add(y, Fq.mul(coeffs[i], tmpX)) - } - - coeffs.push(poseidon([rlnIdentifier])) - const nullifier: bigint = NRLN.genNullifier(coeffs) - return [y, nullifier] - } - - /** - * Calculates slashing nullifier - * @param coeffs coeefitients from calculated polinomial - * @returns slashing nullifier - */ - public static genNullifier(coeffs: bigint[]): bigint { - return poseidon(coeffs) - } - - /** - * When spam occurs, identity secret can be retrieved - * @param xs - * @param ys - * @returns identity secret - */ - 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) { - 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 - */ - public static genIdentifier(): bigint { - return Fq.random() - } -} diff --git a/packages/protocols/tests/nrln.test.ts b/packages/protocols/tests/nrln.test.ts deleted file mode 100644 index e2cdf57..0000000 --- a/packages/protocols/tests/nrln.test.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { SecretType, ZkIdentity } from "@zk-kit/identity" -import { poseidon } from "circomlibjs" -import { getCurveFromName } from "ffjavascript" -import * as fs from "fs" -import * as path from "path" -import { NRLN } from "../src" -import { generateMerkleProof, genExternalNullifier, genSignalHash } from "../src/utils" - -describe("NRLN", () => { - const zkeyFiles = "./packages/protocols/zkeyFiles" - const identityCommitments: bigint[] = [] - const SPAM_TRESHOLD = 3 - - let curve: any - - beforeAll(async () => { - curve = await getCurveFromName("bn128") - - const numberOfLeaves = 3 - - for (let i = 0; i < numberOfLeaves; i += 1) { - const identity = new ZkIdentity() - const identityCommitment = identity.genIdentityCommitment(SecretType.MULTIPART) - - identityCommitments.push(identityCommitment) - } - }) - - afterAll(async () => { - await curve.terminate() - }) - - describe("NRLN features", () => { - it("Should generate NRLN witness", () => { - 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 epoch = genExternalNullifier("test-epoch") - const rlnIdentifier = NRLN.genIdentifier() - - const merkleProof = generateMerkleProof(15, BigInt(0), 2, leaves, identityCommitment) - const witness = NRLN.genWitness(identitySecret, merkleProof, epoch, signal, rlnIdentifier) - - expect(typeof witness).toBe("object") - }) - - 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 = genExternalNullifier("test-epoch") - const rlnIdentifier = NRLN.genIdentifier() - - const merkleProof = generateMerkleProof(15, BigInt(0), 2, leaves, identityCommitment) - const witness = NRLN.genWitness(identitySecret, merkleProof, epoch, signal, rlnIdentifier) - - const [y, nullifier] = NRLN.calculateOutput( - identitySecret, - BigInt(epoch), - signalHash, - SPAM_TRESHOLD, - rlnIdentifier - ) - const publicSignals = [y, merkleProof.root, nullifier, signalHash, epoch, rlnIdentifier] - - const vkeyPath = path.join(zkeyFiles, "nrln", "verification_key.json") - const vKey = JSON.parse(fs.readFileSync(vkeyPath, "utf-8")) - - const wasmFilePath = path.join(zkeyFiles, "nrln", "rln.wasm") - const finalZkeyPath = path.join(zkeyFiles, "nrln", "rln_final.zkey") - - const fullProof = await NRLN.genProof(witness, wasmFilePath, finalZkeyPath) - const response = await NRLN.verifyProof(vKey, { proof: fullProof.proof, publicSignals }) - - expect(response).toBe(true) - }, 30000) - - 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) - const signal2 = "hey 2" - const signalHash2 = genSignalHash(signal2) - const signal3 = "hey 3" - const signalHash3 = genSignalHash(signal3) - const signal4 = "hey 4" - const signalHash4 = genSignalHash(signal4) - - 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 = NRLN.retrieveSecret( - [signalHash1, signalHash2, signalHash3, signalHash4], - [y1, y2, y3, y4] - ) - - expect(retrievedSecret).toEqual(poseidon(identitySecret)) - }) - }) -}) diff --git a/packages/protocols/tests/rln.test.ts b/packages/protocols/tests/rln.test.ts index aeae4d9..a0f4ece 100644 --- a/packages/protocols/tests/rln.test.ts +++ b/packages/protocols/tests/rln.test.ts @@ -1,4 +1,4 @@ -import { SecretType, ZkIdentity } from "@zk-kit/identity" +import { ZkIdentity } from "@zk-kit/identity" import { getCurveFromName } from "ffjavascript" import * as fs from "fs" import * as path from "path" @@ -18,7 +18,7 @@ describe("RLN", () => { for (let i = 0; i < numberOfLeaves; i += 1) { const identity = new ZkIdentity() - const identityCommitment = identity.genIdentityCommitment(SecretType.MULTIPART) + const identityCommitment = identity.genIdentityCommitment() identityCommitments.push(identityCommitment) } @@ -32,7 +32,7 @@ describe("RLN", () => { it("Should generate rln witness", () => { const identity = new ZkIdentity() const identityCommitment = identity.genIdentityCommitment() - const secretHash = identity.getMultipartSecretHash() + const secretHash = identity.getSecretHash() const leaves = Object.assign([], identityCommitments) leaves.push(identityCommitment) @@ -49,8 +49,8 @@ describe("RLN", () => { it("Should generate rln proof and verify it", async () => { const identity = new ZkIdentity() - const secretHash = identity.getMultipartSecretHash() - const identityCommitment = identity.genIdentityCommitment(SecretType.MULTIPART) + const secretHash = identity.getSecretHash() + const identityCommitment = identity.genIdentityCommitment() const leaves = Object.assign([], identityCommitments) leaves.push(identityCommitment) diff --git a/types/zk-kit/index.d.ts b/types/zk-kit/index.d.ts index 7183898..7fed242 100644 --- a/types/zk-kit/index.d.ts +++ b/types/zk-kit/index.d.ts @@ -40,5 +40,4 @@ export declare type SerializedIdentity = { identityNullifier: string identityTrapdoor: string secret: string[] - multipartSecret: string[] } From 8b4a347233dab37383782446f702bc9dfda09ed1 Mon Sep 17 00:00:00 2001 From: bdim1 Date: Wed, 2 Feb 2022 22:31:24 +0100 Subject: [PATCH 2/2] fix: lint fix --- packages/identity/src/identity.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/identity/src/identity.ts b/packages/identity/src/identity.ts index 78c8b53..16938e0 100644 --- a/packages/identity/src/identity.ts +++ b/packages/identity/src/identity.ts @@ -1,7 +1,7 @@ import { SerializedIdentity } from "@zk-kit/types" import { hexToBigint } from "bigint-conversion" import { poseidon } from "circomlibjs" -import { Fq, genRandomNumber, sha256 } from "./utils" +import { genRandomNumber, sha256 } from "./utils" // The strategy used to generate the ZK identity. export enum Strategy {