import debug from "debug"; import { Decoder, Encoder, Message, ProtoMessage, RateLimitProof, } from "js-waku/lib/interfaces"; import { RlnMessage, toRLNSignal } from "./message.js"; import { MembershipKey, RLNInstance } from "./rln.js"; const log = debug("waku:message:rln-encoder"); export class RLNEncoder implements Encoder { public contentTopic: string; private readonly idKey: Uint8Array; constructor( private encoder: Encoder, private rlnInstance: RLNInstance, private index: number, membershipKey: MembershipKey ) { if (index < 0) throw "invalid membership index"; this.idKey = membershipKey.IDKey; this.contentTopic = encoder.contentTopic; } async toWire(message: Partial): Promise { message.contentTopic = this.contentTopic; message.rateLimitProof = await this.generateProof(message); return this.encoder.toWire(message); } async toProtoObj( message: Partial ): Promise { message.contentTopic = this.contentTopic; const protoMessage = await this.encoder.toProtoObj(message); if (!protoMessage) return; protoMessage.rateLimitProof = await this.generateProof(message); return protoMessage; } private async generateProof( message: Partial ): Promise { const signal = toRLNSignal(message); console.time("proof_gen_timer"); const proof = await this.rlnInstance.generateRLNProof( signal, this.index, message.timestamp, this.idKey ); console.timeEnd("proof_gen_timer"); return proof; } } export class RLNDecoder implements Decoder> { constructor(private rlnInstance: RLNInstance, private decoder: Decoder) {} get contentTopic(): string { return this.decoder.contentTopic; } fromWireToProtoObj(bytes: Uint8Array): Promise { const protoMessage = this.decoder.fromWireToProtoObj(bytes); log("Message decoded", protoMessage); return Promise.resolve(protoMessage); } async fromProtoObj(proto: ProtoMessage): Promise | undefined> { const msg: T | undefined = await this.decoder.fromProtoObj(proto); if (!msg) return; return new RlnMessage(this.rlnInstance, msg, proto.rateLimitProof); } }