UNPKG

@waku/rln

Version:

RLN (Rate Limiting Nullifier) implementation for Waku

90 lines 3.76 kB
import { createDecoder, createEncoder } from "@waku/core"; import { Logger } from "@waku/utils"; import init from "@waku/zerokit-rln-wasm"; import * as zerokitRLN from "@waku/zerokit-rln-wasm"; import { createRLNDecoder, createRLNEncoder } from "./codec.js"; import { DEFAULT_RATE_LIMIT } from "./contract/constants.js"; import { RLNCredentialsManager } from "./credentials_manager.js"; import verificationKey from "./resources/verification_key"; import * as wc from "./resources/witness_calculator"; import { Zerokit } from "./zerokit.js"; const log = new Logger("waku:rln"); export class RLNInstance extends RLNCredentialsManager { zerokit; /** * Create an instance of RLN * @returns RLNInstance */ static async create() { try { // eslint-disable-next-line @typescript-eslint/no-explicit-any await init?.(); zerokitRLN.init_panic_hook(); const witnessCalculator = await RLNInstance.loadWitnessCalculator(); const zkey = await RLNInstance.loadZkey(); const stringEncoder = new TextEncoder(); const vkey = stringEncoder.encode(JSON.stringify(verificationKey)); const DEPTH = 20; const zkRLN = zerokitRLN.newRLN(DEPTH, zkey, vkey); const zerokit = new Zerokit(zkRLN, witnessCalculator, DEFAULT_RATE_LIMIT); return new RLNInstance(zerokit); } catch (error) { log.error("Failed to initialize RLN:", error); throw error; } } constructor(zerokit) { super(zerokit); this.zerokit = zerokit; } async createEncoder(options) { const { credentials: decryptedCredentials } = await RLNInstance.decryptCredentialsIfNeeded(options.credentials); const credentials = decryptedCredentials || this.credentials; if (!credentials) { throw Error("Failed to create Encoder: missing RLN credentials. Use createRLNEncoder directly."); } await this.verifyCredentialsAgainstContract(credentials); return createRLNEncoder({ encoder: createEncoder(options), rlnInstance: this, index: credentials.membership.treeIndex, credential: credentials.identity }); } createDecoder(contentTopic) { return createRLNDecoder({ rlnInstance: this, decoder: createDecoder(contentTopic) }); } static async loadWitnessCalculator() { try { const url = new URL("./resources/rln.wasm", import.meta.url); const response = await fetch(url); if (!response.ok) { throw new Error(`Failed to fetch witness calculator: ${response.status} ${response.statusText}`); } return await wc.builder(new Uint8Array(await response.arrayBuffer()), false); } catch (error) { log.error("Error loading witness calculator:", error); throw new Error(`Failed to load witness calculator: ${error instanceof Error ? error.message : String(error)}`); } } static async loadZkey() { try { const url = new URL("./resources/rln_final.zkey", import.meta.url); const response = await fetch(url); if (!response.ok) { throw new Error(`Failed to fetch zkey: ${response.status} ${response.statusText}`); } return new Uint8Array(await response.arrayBuffer()); } catch (error) { log.error("Error loading zkey:", error); throw new Error(`Failed to load zkey: ${error instanceof Error ? error.message : String(error)}`); } } } //# sourceMappingURL=rln.js.map