From b1dbf16b35105538dd4daab6a8b6417543952bd2 Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Sun, 25 Sep 2022 11:40:49 -0400 Subject: [PATCH] feat: message encoder --- package-lock.json | 184 +++++++++++++++++++++++++++++++++++++++++++- package.json | 1 + src/encoder.spec.ts | 7 ++ src/encoder.ts | 52 +++++++++++++ 4 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 src/encoder.spec.ts create mode 100644 src/encoder.ts diff --git a/package-lock.json b/package-lock.json index 7300546..f8a69fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@waku/rln", - "version": "0.0.6", + "version": "0.0.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@waku/rln", - "version": "0.0.6", + "version": "0.0.7", "license": "MIT OR Apache-2.0", "dependencies": { "@waku/zerokit-rln-wasm": "^0.0.2" @@ -41,6 +41,7 @@ "husky": "^7.0.4", "ignore-loader": "^0.1.2", "isomorphic-fetch": "^3.0.0", + "js-waku": "file:../js-waku/", "jsdom": "^19.0.0", "jsdom-global": "^3.0.2", "karma": "^6.3.12", @@ -68,6 +69,97 @@ "node": ">=16" } }, + "../js-waku": { + "version": "0.29.0", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "@chainsafe/libp2p-gossipsub": "^4.1.1", + "@chainsafe/libp2p-noise": "^8.0.1", + "@ethersproject/rlp": "^5.5.0", + "@libp2p/crypto": "^1.0.4", + "@libp2p/interface-connection": "3.0.1", + "@libp2p/interface-peer-discovery": "^1.0.0", + "@libp2p/interface-peer-id": "^1.0.2", + "@libp2p/interface-peer-info": "^1.0.1", + "@libp2p/interface-peer-store": "^1.0.0", + "@libp2p/interface-pubsub": "^2.0.1", + "@libp2p/interfaces": "^3.0.2", + "@libp2p/mplex": "^5.1.1", + "@libp2p/peer-id": "^1.1.10", + "@libp2p/websockets": "^3.0.3", + "@multiformats/multiaddr": "^10.4.0", + "@noble/secp256k1": "^1.3.4", + "debug": "^4.3.4", + "dns-query": "^0.11.2", + "hi-base32": "^0.5.1", + "it-all": "^1.0.6", + "it-length-prefixed": "^8.0.2", + "it-pipe": "^2.0.4", + "js-sha3": "^0.8.0", + "libp2p": "0.38.0", + "p-event": "^5.0.1", + "protons-runtime": "^3.1.0", + "uint8arraylist": "^2.3.2", + "uint8arrays": "^3.0.0", + "uuid": "^8.3.2" + }, + "devDependencies": { + "@libp2p/peer-id-factory": "^1.0.15", + "@rollup/plugin-commonjs": "^22.0.0", + "@rollup/plugin-json": "^4.1.0", + "@rollup/plugin-node-resolve": "^13.3.0", + "@size-limit/preset-big-lib": "^8.0.0", + "@types/app-root-path": "^1.2.4", + "@types/chai": "^4.2.15", + "@types/debug": "^4.1.7", + "@types/mocha": "^9.1.0", + "@types/node": "^17.0.6", + "@types/tail": "^2.0.0", + "@types/uuid": "^8.3.0", + "@typescript-eslint/eslint-plugin": "^5.8.1", + "@typescript-eslint/parser": "^5.8.1", + "app-root-path": "^3.0.0", + "chai": "^4.3.4", + "cspell": "^5.14.0", + "eslint": "^8.6.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-functional": "^4.0.2", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-prettier": "^4.0.0", + "fast-check": "^2.14.0", + "gh-pages": "^3.2.3", + "husky": "^7.0.4", + "ignore-loader": "^0.1.2", + "isomorphic-fetch": "^3.0.0", + "jsdom": "^19.0.0", + "jsdom-global": "^3.0.2", + "karma": "^6.3.12", + "karma-chrome-launcher": "^3.1.0", + "karma-mocha": "^2.0.1", + "karma-webpack": "^5.0.0", + "lint-staged": "^13.0.3", + "mocha": "^9.1.3", + "npm-run-all": "^4.1.5", + "p-timeout": "^4.1.0", + "portfinder": "^1.0.28", + "prettier": "^2.1.1", + "process": "^0.11.10", + "protons": "^5.1.0", + "puppeteer": "^13.0.1", + "rollup": "^2.75.0", + "size-limit": "^8.0.0", + "tail": "^2.2.0", + "ts-loader": "^9.3.1", + "ts-node": "^10.9.1", + "typedoc": "^0.23.10", + "typescript": "^4.6.3" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@babel/code-frame": { "version": "7.18.6", "dev": true, @@ -4614,6 +4706,10 @@ "dev": true, "license": "MIT" }, + "node_modules/js-waku": { + "resolved": "../js-waku", + "link": true + }, "node_modules/js-yaml": { "version": "4.1.0", "dev": true, @@ -11295,6 +11391,90 @@ "version": "4.0.0", "dev": true }, + "js-waku": { + "version": "file:../js-waku", + "requires": { + "@chainsafe/libp2p-gossipsub": "^4.1.1", + "@chainsafe/libp2p-noise": "^8.0.1", + "@ethersproject/rlp": "^5.5.0", + "@libp2p/crypto": "^1.0.4", + "@libp2p/interface-connection": "3.0.1", + "@libp2p/interface-peer-discovery": "^1.0.0", + "@libp2p/interface-peer-id": "^1.0.2", + "@libp2p/interface-peer-info": "^1.0.1", + "@libp2p/interface-peer-store": "^1.0.0", + "@libp2p/interface-pubsub": "^2.0.1", + "@libp2p/interfaces": "^3.0.2", + "@libp2p/mplex": "^5.1.1", + "@libp2p/peer-id": "^1.1.10", + "@libp2p/peer-id-factory": "^1.0.15", + "@libp2p/websockets": "^3.0.3", + "@multiformats/multiaddr": "^10.4.0", + "@noble/secp256k1": "^1.3.4", + "@rollup/plugin-commonjs": "^22.0.0", + "@rollup/plugin-json": "^4.1.0", + "@rollup/plugin-node-resolve": "^13.3.0", + "@size-limit/preset-big-lib": "^8.0.0", + "@types/app-root-path": "^1.2.4", + "@types/chai": "^4.2.15", + "@types/debug": "^4.1.7", + "@types/mocha": "^9.1.0", + "@types/node": "^17.0.6", + "@types/tail": "^2.0.0", + "@types/uuid": "^8.3.0", + "@typescript-eslint/eslint-plugin": "^5.8.1", + "@typescript-eslint/parser": "^5.8.1", + "app-root-path": "^3.0.0", + "chai": "^4.3.4", + "cspell": "^5.14.0", + "debug": "^4.3.4", + "dns-query": "^0.11.2", + "eslint": "^8.6.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-functional": "^4.0.2", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-prettier": "^4.0.0", + "fast-check": "^2.14.0", + "gh-pages": "^3.2.3", + "hi-base32": "^0.5.1", + "husky": "^7.0.4", + "ignore-loader": "^0.1.2", + "isomorphic-fetch": "^3.0.0", + "it-all": "^1.0.6", + "it-length-prefixed": "^8.0.2", + "it-pipe": "^2.0.4", + "js-sha3": "^0.8.0", + "jsdom": "^19.0.0", + "jsdom-global": "^3.0.2", + "karma": "^6.3.12", + "karma-chrome-launcher": "^3.1.0", + "karma-mocha": "^2.0.1", + "karma-webpack": "^5.0.0", + "libp2p": "0.38.0", + "lint-staged": "^13.0.3", + "mocha": "^9.1.3", + "npm-run-all": "^4.1.5", + "p-event": "^5.0.1", + "p-timeout": "^4.1.0", + "portfinder": "^1.0.28", + "prettier": "^2.1.1", + "process": "^0.11.10", + "protons": "^5.1.0", + "protons-runtime": "^3.1.0", + "puppeteer": "^13.0.1", + "rollup": "^2.75.0", + "size-limit": "^8.0.0", + "tail": "^2.2.0", + "ts-loader": "^9.3.1", + "ts-node": "^10.9.1", + "typedoc": "^0.23.10", + "typescript": "^4.6.3", + "uint8arraylist": "^2.3.2", + "uint8arrays": "^3.0.0", + "uuid": "^8.3.2" + } + }, "js-yaml": { "version": "4.1.0", "dev": true, diff --git a/package.json b/package.json index f265be1..f5418a8 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "husky": "^7.0.4", "ignore-loader": "^0.1.2", "isomorphic-fetch": "^3.0.0", + "js-waku": "file:../js-waku/", "jsdom": "^19.0.0", "jsdom-global": "^3.0.2", "karma": "^6.3.12", diff --git a/src/encoder.spec.ts b/src/encoder.spec.ts new file mode 100644 index 0000000..f05f596 --- /dev/null +++ b/src/encoder.spec.ts @@ -0,0 +1,7 @@ +import { RLNEncoder } from "./encoder.js"; + +describe("js-rln: encoder", () => { + it("should attach a proof to a waku message", async function () { + console.log(RLNEncoder); + }); +}); diff --git a/src/encoder.ts b/src/encoder.ts new file mode 100644 index 0000000..b74de39 --- /dev/null +++ b/src/encoder.ts @@ -0,0 +1,52 @@ +import { Encoder, Message, ProtoMessage } from "js-waku/lib/interfaces"; +import * as proto from "js-waku/src/proto/message"; + +import { RLNInstance } from "./rln.js"; + +export class RLNEncoder implements Encoder { + constructor( + public contentTopic: string, + private encoder: Encoder, + private rlnInstance: RLNInstance, + private index: number, + private idKey: Uint8Array + ) { + if (idKey.length != 32) throw "invalid id key"; // TODO: use proper err message + if (index < 0) throw "invalid membership index"; + } + + async encode(message: Message): Promise { + const protoMessage = await this.encodeProto(message); + if (!protoMessage) return; + + return proto.WakuMessage.encode(protoMessage); + } + + toRLNSignal(msg: Message): Uint8Array { + const contentTopic = msg.contentTopic ?? ""; + const contentTopicBytes = Uint8Array.from( + contentTopic.split("").map((x: string) => x.charCodeAt(0)) + ); + return new Uint8Array([...(msg.payload ?? []), ...contentTopicBytes]); + } + + async encodeProto(message: Message): Promise { + const protoMessage = await this.encoder.encodeProto(message); + if (!protoMessage) return; + + const signal = this.toRLNSignal(message); + + console.time("proof_gen_timer"); + const proof = await this.rlnInstance.generateProof( + signal, + this.index, + message.timestamp, + this.idKey + ); + console.timeEnd("proof_gen_timer"); + + protoMessage.rateLimitProof = proof; + + return protoMessage; + } +}