fix: proof generation and validation

This commit is contained in:
Richard Ramos 2022-10-01 08:02:13 -04:00 committed by fryorcraken.eth
parent 378ad04c53
commit 3e5cb1d13c
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
8 changed files with 107 additions and 62 deletions

View File

@ -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")

View File

@ -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
}
}
}

78
package-lock.json generated
View File

@ -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",

View File

@ -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"
}
}

View File

@ -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<Message>): Promise<Uint8Array | undefined> {
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<Message>
): Promise<ProtoMessage | undefined> {
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<T extends Message> implements Decoder<RlnMessage<T>> {
return new RlnMessage(this.rlnInstance, msg, proto.rateLimitProof);
}
}
function toRLNSignal(msg: Partial<Message>): Uint8Array {
const contentTopicBytes = utils.utf8ToBytes(msg.contentTopic ?? "");
return new Uint8Array([...(msg.payload ?? []), ...contentTopicBytes]);
}

View File

@ -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);
}
});
});

View File

@ -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<Message>): Uint8Array {
const contentTopicBytes = utils.utf8ToBytes(msg.contentTopic ?? "");
return new Uint8Array([...(msg.payload ?? []), ...contentTopicBytes]);
}
export class RlnMessage<T extends Message> implements Message {
constructor(
public rlnInstance: RLNInstance,
@ -12,7 +18,7 @@ export class RlnMessage<T extends Message> implements Message {
public verify(): boolean | undefined {
return this.rateLimitProof
? this.rlnInstance.verifyProof(this.rateLimitProof)
? this.rlnInstance.verifyRLNProof(this.rateLimitProof, toRLNSignal(this))
: undefined;
}

View File

@ -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)
);
}
}