js-rln/src/codec.ts

81 lines
2.3 KiB
TypeScript
Raw Normal View History

2022-09-26 12:08:28 -04:00
import debug from "debug";
2022-09-27 13:54:44 +10:00
import { proto_message, utils } from "js-waku";
2022-09-26 12:08:28 -04:00
import {
Decoder,
Encoder,
Message,
ProtoMessage,
} from "js-waku/lib/interfaces";
2022-09-25 11:40:49 -04:00
2022-09-28 14:23:10 +10:00
import { RlnMessage } from "./message.js";
2022-09-26 12:08:28 -04:00
import { MembershipKey, RLNInstance } from "./rln.js";
const log = debug("waku:message:rln-encoder");
2022-09-25 11:40:49 -04:00
export class RLNEncoder implements Encoder {
2022-09-26 12:08:28 -04:00
public contentTopic: string;
2022-09-27 13:45:14 +10:00
private readonly idKey: Uint8Array;
2022-09-26 12:08:28 -04:00
2022-09-25 11:40:49 -04:00
constructor(
private encoder: Encoder,
private rlnInstance: RLNInstance,
private index: number,
2022-09-26 12:08:28 -04:00
membershipKey: MembershipKey
2022-09-25 11:40:49 -04:00
) {
if (index < 0) throw "invalid membership index";
2022-09-26 12:08:28 -04:00
this.idKey = membershipKey.IDKey;
this.contentTopic = encoder.contentTopic;
2022-09-25 11:40:49 -04:00
}
async encode(message: Message): Promise<Uint8Array | undefined> {
const protoMessage = await this.encodeProto(message);
if (!protoMessage) return;
2022-09-26 10:09:39 +10:00
return proto_message.WakuMessage.encode(protoMessage);
2022-09-25 11:40:49 -04:00
}
async encodeProto(message: Message): Promise<ProtoMessage | undefined> {
const protoMessage = await this.encoder.encodeProto(message);
if (!protoMessage) return;
2022-09-27 13:45:14 +10:00
const signal = toRLNSignal(message);
2022-09-25 11:40:49 -04:00
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;
}
}
2022-09-26 12:08:28 -04:00
2022-09-28 14:23:10 +10:00
export class RLNDecoder<T extends Message> implements Decoder<RlnMessage<T>> {
constructor(private rlnInstance: RLNInstance, private decoder: Decoder<T>) {}
2022-09-26 12:08:28 -04:00
2022-09-28 14:23:10 +10:00
get contentTopic(): string {
return this.decoder.contentTopic;
2022-09-26 12:08:28 -04:00
}
decodeProto(bytes: Uint8Array): Promise<ProtoMessage | undefined> {
const protoMessage = proto_message.WakuMessage.decode(bytes);
log("Message decoded", protoMessage);
return Promise.resolve(protoMessage);
}
2022-09-28 14:23:10 +10:00
async decode(proto: ProtoMessage): Promise<RlnMessage<T> | undefined> {
const msg: T | undefined = await this.decoder.decode(proto);
if (!msg) return;
return new RlnMessage(this.rlnInstance, msg, proto.rateLimitProof);
2022-09-26 12:08:28 -04:00
}
}
2022-09-27 13:45:14 +10:00
function toRLNSignal(msg: Message): Uint8Array {
2022-09-27 13:54:44 +10:00
const contentTopicBytes = utils.utf8ToBytes(msg.contentTopic ?? "");
2022-09-27 13:45:14 +10:00
return new Uint8Array([...(msg.payload ?? []), ...contentTopicBytes]);
}