From 3e5cb1d13c62d19a6e4a66f3d1c5dae4664f7379 Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Sat, 1 Oct 2022 08:02:13 -0400 Subject: [PATCH] fix: proof generation and validation --- example/index.js | 4 +- example/package-lock.json | 32 +++++++--------- package-lock.json | 78 +++++++++++++++++++++++++++++++-------- package.json | 4 +- src/codec.ts | 12 ++---- src/index.spec.ts | 16 +++----- src/message.ts | 8 +++- src/rln.ts | 15 ++++++-- 8 files changed, 107 insertions(+), 62 deletions(-) diff --git a/example/index.js b/example/index.js index 7f18f0b..18b361d 100644 --- a/example/index.js +++ b/example/index.js @@ -27,13 +27,13 @@ rln.create().then(async rlnInstance => { console.log("Generating proof..."); console.time("proof_gen_timer"); - let proof = await rlnInstance.generateProof(uint8Msg, index, epoch, memKeys.IDKey) + let proof = await rlnInstance.generateRLNProof(uint8Msg, index, epoch, memKeys.IDKey) console.timeEnd("proof_gen_timer"); console.log("Proof", proof) try { // verify the proof - let verifResult = rlnInstance.verifyProof(proof); + let verifResult = rlnInstance.verifyRLNProof(proof, uint8Msg); console.log("Is proof verified?", verifResult ? "yes" : "no"); } catch (err) { console.log("Invalid proof") diff --git a/example/package-lock.json b/example/package-lock.json index bcf26ca..112b06d 100644 --- a/example/package-lock.json +++ b/example/package-lock.json @@ -19,10 +19,10 @@ }, "..": { "name": "@waku/rln", - "version": "0.0.8", + "version": "0.0.9", "license": "MIT OR Apache-2.0", "dependencies": { - "@waku/zerokit-rln-wasm": "^0.0.2" + "@waku/zerokit-rln-wasm": "^0.0.3" }, "devDependencies": { "@rollup/plugin-commonjs": "^22.0.2", @@ -49,12 +49,12 @@ "eslint-plugin-functional": "^4.0.2", "eslint-plugin-import": "^2.25.3", "eslint-plugin-prettier": "^4.0.0", - "fast-check": "^2.14.0", + "fast-check": "^2.25.0", "gh-pages": "^3.2.3", "husky": "^7.0.4", "ignore-loader": "^0.1.2", "isomorphic-fetch": "^3.0.0", - "js-waku": "^0.29.0-7714812", + "js-waku": "^0.29.0-29436ea", "jsdom": "^19.0.0", "jsdom-global": "^3.0.2", "karma": "^6.3.12", @@ -3956,7 +3956,7 @@ "@types/uuid": "^8.3.0", "@typescript-eslint/eslint-plugin": "^5.8.1", "@typescript-eslint/parser": "^5.8.1", - "@waku/zerokit-rln-wasm": "^0.0.2", + "@waku/zerokit-rln-wasm": "^0.0.3", "@web/rollup-plugin-import-meta-assets": "^1.0.7", "app-root-path": "^3.0.0", "chai": "^4.3.4", @@ -3967,12 +3967,12 @@ "eslint-plugin-functional": "^4.0.2", "eslint-plugin-import": "^2.25.3", "eslint-plugin-prettier": "^4.0.0", - "fast-check": "^2.14.0", + "fast-check": "^2.25.0", "gh-pages": "^3.2.3", "husky": "^7.0.4", "ignore-loader": "^0.1.2", "isomorphic-fetch": "^3.0.0", - "js-waku": "^0.29.0-7714812", + "js-waku": "^0.29.0-29436ea", "jsdom": "^19.0.0", "jsdom-global": "^3.0.2", "karma": "^6.3.12", @@ -4147,8 +4147,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", - "dev": true, - "requires": {} + "dev": true }, "@webpack-cli/info": { "version": "1.5.0", @@ -4163,8 +4162,7 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", - "dev": true, - "requires": {} + "dev": true }, "@xtuc/ieee754": { "version": "1.2.0", @@ -4198,8 +4196,7 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "requires": {} + "dev": true }, "ajv": { "version": "8.11.0", @@ -6108,8 +6105,7 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} + "dev": true }, "json-schema-traverse": { "version": "0.4.1", @@ -6277,8 +6273,7 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} + "dev": true }, "json-schema-traverse": { "version": "0.4.1", @@ -6443,8 +6438,7 @@ "version": "8.9.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", - "dev": true, - "requires": {} + "dev": true } } } diff --git a/package-lock.json b/package-lock.json index 4d50970..76407fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@waku/rln", - "version": "0.0.8", + "version": "0.0.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@waku/rln", - "version": "0.0.8", + "version": "0.0.10", "license": "MIT OR Apache-2.0", "dependencies": { - "@waku/zerokit-rln-wasm": "^0.0.2" + "@waku/zerokit-rln-wasm": "^0.0.3" }, "devDependencies": { "@rollup/plugin-commonjs": "^22.0.2", @@ -2549,9 +2549,9 @@ "dev": true }, "node_modules/@waku/zerokit-rln-wasm": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@waku/zerokit-rln-wasm/-/zerokit-rln-wasm-0.0.2.tgz", - "integrity": "sha512-WFJXVhh5mlp1ActepsyCQ8RLWIp/BE0VmXdI+7Og0ealEtoaUzpHF1oxKeJpGLgYJWLYQc6DWgRz5Zz8vf+uKw==" + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@waku/zerokit-rln-wasm/-/zerokit-rln-wasm-0.0.3.tgz", + "integrity": "sha512-vN2lfCbFChB1ZiyNpE34NBELJ7IabBgdWtzOnvOwuwmuQgAsWCdvt7UGtjRfogMxr2clSTrI1pVYSD9ayf/d4w==" }, "node_modules/@web/rollup-plugin-import-meta-assets": { "version": "1.0.7", @@ -3233,6 +3233,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, + "peer": true, + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/byte-access": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/byte-access/-/byte-access-1.0.1.tgz", @@ -9692,6 +9705,16 @@ "node": ">= 4.0.0" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "dev": true, @@ -10423,11 +10446,14 @@ } }, "node_modules/undici": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.10.0.tgz", - "integrity": "sha512-c8HsD3IbwmjjbLvoZuRI26TZic+TSEe8FPMLLOkN1AfYRhdjnKBU6yL+IwcSCbdZiX4e5t0lfMDLDCqj4Sq70g==", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.11.0.tgz", + "integrity": "sha512-oWjWJHzFet0Ow4YZBkyiJwiK5vWqEYoH7BINzJAJOLedZ++JpAlCbUktW2GQ2DS2FpKmxD/JMtWUUWl1BtghGw==", "dev": true, "peer": true, + "dependencies": { + "busboy": "^1.6.0" + }, "engines": { "node": ">=12.18" } @@ -12969,9 +12995,9 @@ "dev": true }, "@waku/zerokit-rln-wasm": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@waku/zerokit-rln-wasm/-/zerokit-rln-wasm-0.0.2.tgz", - "integrity": "sha512-WFJXVhh5mlp1ActepsyCQ8RLWIp/BE0VmXdI+7Og0ealEtoaUzpHF1oxKeJpGLgYJWLYQc6DWgRz5Zz8vf+uKw==" + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@waku/zerokit-rln-wasm/-/zerokit-rln-wasm-0.0.3.tgz", + "integrity": "sha512-vN2lfCbFChB1ZiyNpE34NBELJ7IabBgdWtzOnvOwuwmuQgAsWCdvt7UGtjRfogMxr2clSTrI1pVYSD9ayf/d4w==" }, "@web/rollup-plugin-import-meta-assets": { "version": "1.0.7", @@ -13445,6 +13471,16 @@ "version": "3.3.0", "dev": true }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, + "peer": true, + "requires": { + "streamsearch": "^1.1.0" + } + }, "byte-access": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/byte-access/-/byte-access-1.0.1.tgz", @@ -17805,6 +17841,13 @@ } } }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "dev": true, + "peer": true + }, "string_decoder": { "version": "1.3.0", "dev": true, @@ -18267,11 +18310,14 @@ } }, "undici": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.10.0.tgz", - "integrity": "sha512-c8HsD3IbwmjjbLvoZuRI26TZic+TSEe8FPMLLOkN1AfYRhdjnKBU6yL+IwcSCbdZiX4e5t0lfMDLDCqj4Sq70g==", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.11.0.tgz", + "integrity": "sha512-oWjWJHzFet0Ow4YZBkyiJwiK5vWqEYoH7BINzJAJOLedZ++JpAlCbUktW2GQ2DS2FpKmxD/JMtWUUWl1BtghGw==", "dev": true, - "peer": true + "peer": true, + "requires": { + "busboy": "^1.6.0" + } }, "unique-string": { "version": "2.0.0", diff --git a/package.json b/package.json index a51bfa5..a3e876c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@waku/rln", - "version": "0.0.8", + "version": "0.0.10", "description": "Rate Limit Nullifier for js-waku", "types": "./dist/index.d.ts", "module": "./dist/index.js", @@ -125,6 +125,6 @@ ] }, "dependencies": { - "@waku/zerokit-rln-wasm": "^0.0.2" + "@waku/zerokit-rln-wasm": "^0.0.3" } } diff --git a/src/codec.ts b/src/codec.ts index c4d789c..cd8483b 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -1,5 +1,4 @@ import debug from "debug"; -import { utils } from "js-waku"; import { Decoder, Encoder, @@ -8,7 +7,7 @@ import { RateLimitProof, } from "js-waku/lib/interfaces"; -import { RlnMessage } from "./message.js"; +import { RlnMessage, toRLNSignal } from "./message.js"; import { MembershipKey, RLNInstance } from "./rln.js"; const log = debug("waku:message:rln-encoder"); @@ -29,6 +28,7 @@ export class RLNEncoder implements Encoder { } async toWire(message: Partial): Promise { + message.contentTopic = this.contentTopic; message.rateLimitProof = await this.generateProof(message); return this.encoder.toWire(message); @@ -37,6 +37,7 @@ export class RLNEncoder implements Encoder { async toProtoObj( message: Partial ): Promise { + message.contentTopic = this.contentTopic; const protoMessage = await this.encoder.toProtoObj(message); if (!protoMessage) return; @@ -51,7 +52,7 @@ export class RLNEncoder implements Encoder { const signal = toRLNSignal(message); console.time("proof_gen_timer"); - const proof = await this.rlnInstance.generateProof( + const proof = await this.rlnInstance.generateRLNProof( signal, this.index, message.timestamp, @@ -81,8 +82,3 @@ export class RLNDecoder implements Decoder> { return new RlnMessage(this.rlnInstance, msg, proto.rateLimitProof); } } - -function toRLNSignal(msg: Partial): Uint8Array { - const contentTopicBytes = utils.utf8ToBytes(msg.contentTopic ?? ""); - return new Uint8Array([...(msg.payload ?? []), ...contentTopicBytes]); -} diff --git a/src/index.spec.ts b/src/index.spec.ts index 5cdb0df..4c843da 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -33,7 +33,7 @@ describe("js-rln", () => { const epoch = new Date(); // generating proof - const proof = await rlnInstance.generateProof( + const proof = await rlnInstance.generateRLNProof( uint8Msg, index, epoch, @@ -42,24 +42,20 @@ describe("js-rln", () => { try { // verify the proof - const verifResult = rlnInstance.verifyProof(proof); + const verifResult = rlnInstance.verifyRLNProof(proof, uint8Msg); expect(verifResult).to.be.true; } catch (err) { assert.fail(0, 1, "should not have failed proof verification"); } try { - // Modifying the proof so it's invalid - proof.proof[0] = 0; - proof.proof[1] = 1; - proof.proof[2] = 2; - proof.proof[3] = 3; - + // Modifying the signal so it's invalid + uint8Msg[4] = 4; // verify the proof - const verifResult = rlnInstance.verifyProof(proof); + const verifResult = rlnInstance.verifyRLNProof(proof, uint8Msg); expect(verifResult).to.be.false; } catch (err) { - // + console.log(err); } }); }); diff --git a/src/message.ts b/src/message.ts index a0df079..0d0e400 100644 --- a/src/message.ts +++ b/src/message.ts @@ -1,8 +1,14 @@ +import { utils } from "js-waku"; import { Message, RateLimitProof } from "js-waku/lib/interfaces"; import { epochBytesToInt } from "./epoch.js"; import { RLNInstance } from "./rln.js"; +export function toRLNSignal(msg: Partial): Uint8Array { + const contentTopicBytes = utils.utf8ToBytes(msg.contentTopic ?? ""); + return new Uint8Array([...(msg.payload ?? []), ...contentTopicBytes]); +} + export class RlnMessage implements Message { constructor( public rlnInstance: RLNInstance, @@ -12,7 +18,7 @@ export class RlnMessage implements Message { public verify(): boolean | undefined { return this.rateLimitProof - ? this.rlnInstance.verifyProof(this.rateLimitProof) + ? this.rlnInstance.verifyRLNProof(this.rateLimitProof, toRLNSignal(this)) : undefined; } diff --git a/src/rln.ts b/src/rln.ts index 62b04b5..22d1d27 100644 --- a/src/rln.ts +++ b/src/rln.ts @@ -102,7 +102,7 @@ export class Proof implements RateLimitProof { } } -function proofToBytes(p: RateLimitProof): Uint8Array { +export function proofToBytes(p: RateLimitProof): Uint8Array { return concatenate( p.proof, p.merkleRoot, @@ -145,7 +145,7 @@ export class RLNInstance { return concatenate(idKey, memIndexBytes, epoch, msgLen, uint8Msg); } - async generateProof( + async generateRLNProof( msg: Uint8Array, index: number, epoch: Uint8Array | Date | undefined, @@ -181,13 +181,20 @@ export class RLNInstance { return new Proof(proofBytes); } - verifyProof(proof: RateLimitProof | Uint8Array): boolean { + verifyRLNProof(proof: RateLimitProof | Uint8Array, msg: Uint8Array): boolean { let pBytes: Uint8Array; if (proof instanceof Uint8Array) { pBytes = proof; } else { pBytes = proofToBytes(proof); } - return zerokitRLN.verifyProof(this.zkRLN, pBytes); + + // calculate message length + const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8); + + return zerokitRLN.verifyRLNProof( + this.zkRLN, + concatenate(pBytes, msgLen, msg) + ); } }