mirror of
https://github.com/logos-messaging/js-rln.git
synced 2026-01-02 13:43:06 +00:00
decouple zerokit
This commit is contained in:
parent
d763a76515
commit
f27ec077dd
@ -25,11 +25,10 @@ import {
|
||||
RLNDecoder,
|
||||
RLNEncoder,
|
||||
} from "./codec.js";
|
||||
import { createRLN } from "./create.js";
|
||||
import { RlnMessage } from "./message.js";
|
||||
import { epochBytesToInt } from "./utils/index.js";
|
||||
|
||||
import * as rln from "./index.js";
|
||||
|
||||
const TestContentTopic = "/test/1/waku-message/utf8";
|
||||
const EMPTY_PUBSUB_TOPIC = "";
|
||||
|
||||
@ -44,12 +43,12 @@ const EMPTY_PROTO_MESSAGE = {
|
||||
|
||||
describe("RLN codec with version 0", () => {
|
||||
it("toWire", async function () {
|
||||
const rlnInstance = await rln.createRLN();
|
||||
const credential = rlnInstance.generateIdentityCredentials();
|
||||
const rlnInstance = await createRLN();
|
||||
const credential = rlnInstance.zerokit.generateIdentityCredentials();
|
||||
const index = 0;
|
||||
const payload = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
|
||||
rlnInstance.insertMember(credential.IDCommitment);
|
||||
rlnInstance.zerokit.insertMember(credential.IDCommitment);
|
||||
|
||||
const rlnEncoder = createRLNEncoder({
|
||||
encoder: createEncoder({ contentTopic: TestContentTopic }),
|
||||
@ -73,7 +72,7 @@ describe("RLN codec with version 0", () => {
|
||||
))!;
|
||||
|
||||
expect(msg.rateLimitProof).to.not.be.undefined;
|
||||
expect(msg.verify([rlnInstance.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verifyNoRoot()).to.be.true;
|
||||
expect(msg.epoch).to.not.be.undefined;
|
||||
expect(msg.epoch).to.be.gt(0);
|
||||
@ -85,12 +84,12 @@ describe("RLN codec with version 0", () => {
|
||||
});
|
||||
|
||||
it("toProtoObj", async function () {
|
||||
const rlnInstance = await rln.createRLN();
|
||||
const credential = rlnInstance.generateIdentityCredentials();
|
||||
const rlnInstance = await createRLN();
|
||||
const credential = rlnInstance.zerokit.generateIdentityCredentials();
|
||||
const index = 0;
|
||||
const payload = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
|
||||
rlnInstance.insertMember(credential.IDCommitment);
|
||||
rlnInstance.zerokit.insertMember(credential.IDCommitment);
|
||||
|
||||
const rlnEncoder = new RLNEncoder(
|
||||
createEncoder({ contentTopic: TestContentTopic }),
|
||||
@ -114,7 +113,7 @@ describe("RLN codec with version 0", () => {
|
||||
expect(msg).to.not.be.undefined;
|
||||
expect(msg.rateLimitProof).to.not.be.undefined;
|
||||
|
||||
expect(msg.verify([rlnInstance.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verifyNoRoot()).to.be.true;
|
||||
expect(msg.epoch).to.not.be.undefined;
|
||||
expect(msg.epoch).to.be.gt(0);
|
||||
@ -128,12 +127,12 @@ describe("RLN codec with version 0", () => {
|
||||
|
||||
describe("RLN codec with version 1", () => {
|
||||
it("Symmetric, toWire", async function () {
|
||||
const rlnInstance = await rln.createRLN();
|
||||
const credential = rlnInstance.generateIdentityCredentials();
|
||||
const rlnInstance = await createRLN();
|
||||
const credential = rlnInstance.zerokit.generateIdentityCredentials();
|
||||
const index = 0;
|
||||
const payload = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
|
||||
rlnInstance.insertMember(credential.IDCommitment);
|
||||
rlnInstance.zerokit.insertMember(credential.IDCommitment);
|
||||
|
||||
const symKey = generateSymmetricKey();
|
||||
|
||||
@ -163,7 +162,7 @@ describe("RLN codec with version 1", () => {
|
||||
))!;
|
||||
|
||||
expect(msg.rateLimitProof).to.not.be.undefined;
|
||||
expect(msg.verify([rlnInstance.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verifyNoRoot()).to.be.true;
|
||||
expect(msg.epoch).to.not.be.undefined;
|
||||
expect(msg.epoch).to.be.gt(0);
|
||||
@ -175,12 +174,12 @@ describe("RLN codec with version 1", () => {
|
||||
});
|
||||
|
||||
it("Symmetric, toProtoObj", async function () {
|
||||
const rlnInstance = await rln.createRLN();
|
||||
const credential = rlnInstance.generateIdentityCredentials();
|
||||
const rlnInstance = await createRLN();
|
||||
const credential = rlnInstance.zerokit.generateIdentityCredentials();
|
||||
const index = 0;
|
||||
const payload = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
|
||||
rlnInstance.insertMember(credential.IDCommitment);
|
||||
rlnInstance.zerokit.insertMember(credential.IDCommitment);
|
||||
|
||||
const symKey = generateSymmetricKey();
|
||||
|
||||
@ -209,7 +208,7 @@ describe("RLN codec with version 1", () => {
|
||||
expect(msg).to.not.be.undefined;
|
||||
expect(msg.rateLimitProof).to.not.be.undefined;
|
||||
|
||||
expect(msg.verify([rlnInstance.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verifyNoRoot()).to.be.true;
|
||||
expect(msg.epoch).to.not.be.undefined;
|
||||
expect(msg.epoch).to.be.gt(0);
|
||||
@ -221,12 +220,12 @@ describe("RLN codec with version 1", () => {
|
||||
});
|
||||
|
||||
it("Asymmetric, toWire", async function () {
|
||||
const rlnInstance = await rln.createRLN();
|
||||
const credential = rlnInstance.generateIdentityCredentials();
|
||||
const rlnInstance = await createRLN();
|
||||
const credential = rlnInstance.zerokit.generateIdentityCredentials();
|
||||
const index = 0;
|
||||
const payload = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
|
||||
rlnInstance.insertMember(credential.IDCommitment);
|
||||
rlnInstance.zerokit.insertMember(credential.IDCommitment);
|
||||
|
||||
const privateKey = generatePrivateKey();
|
||||
const publicKey = getPublicKey(privateKey);
|
||||
@ -257,7 +256,7 @@ describe("RLN codec with version 1", () => {
|
||||
))!;
|
||||
|
||||
expect(msg.rateLimitProof).to.not.be.undefined;
|
||||
expect(msg.verify([rlnInstance.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verifyNoRoot()).to.be.true;
|
||||
expect(msg.epoch).to.not.be.undefined;
|
||||
expect(msg.epoch).to.be.gt(0);
|
||||
@ -269,12 +268,12 @@ describe("RLN codec with version 1", () => {
|
||||
});
|
||||
|
||||
it("Asymmetric, toProtoObj", async function () {
|
||||
const rlnInstance = await rln.createRLN();
|
||||
const credential = rlnInstance.generateIdentityCredentials();
|
||||
const rlnInstance = await createRLN();
|
||||
const credential = rlnInstance.zerokit.generateIdentityCredentials();
|
||||
const index = 0;
|
||||
const payload = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
|
||||
rlnInstance.insertMember(credential.IDCommitment);
|
||||
rlnInstance.zerokit.insertMember(credential.IDCommitment);
|
||||
|
||||
const privateKey = generatePrivateKey();
|
||||
const publicKey = getPublicKey(privateKey);
|
||||
@ -304,7 +303,7 @@ describe("RLN codec with version 1", () => {
|
||||
expect(msg).to.not.be.undefined;
|
||||
expect(msg.rateLimitProof).to.not.be.undefined;
|
||||
|
||||
expect(msg.verify([rlnInstance.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verifyNoRoot()).to.be.true;
|
||||
expect(msg.epoch).to.not.be.undefined;
|
||||
expect(msg.epoch).to.be.gt(0);
|
||||
@ -318,12 +317,12 @@ describe("RLN codec with version 1", () => {
|
||||
|
||||
describe("RLN Codec - epoch", () => {
|
||||
it("toProtoObj", async function () {
|
||||
const rlnInstance = await rln.createRLN();
|
||||
const credential = rlnInstance.generateIdentityCredentials();
|
||||
const rlnInstance = await createRLN();
|
||||
const credential = rlnInstance.zerokit.generateIdentityCredentials();
|
||||
const index = 0;
|
||||
const payload = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
|
||||
rlnInstance.insertMember(credential.IDCommitment);
|
||||
rlnInstance.zerokit.insertMember(credential.IDCommitment);
|
||||
|
||||
const rlnEncoder = new RLNEncoder(
|
||||
createEncoder({ contentTopic: TestContentTopic }),
|
||||
@ -350,7 +349,7 @@ describe("RLN Codec - epoch", () => {
|
||||
expect(msg).to.not.be.undefined;
|
||||
expect(msg.rateLimitProof).to.not.be.undefined;
|
||||
|
||||
expect(msg.verify([rlnInstance.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verifyNoRoot()).to.be.true;
|
||||
expect(msg.epoch).to.not.be.undefined;
|
||||
expect(msg.epoch!.toString(10).length).to.eq(9);
|
||||
@ -374,12 +373,12 @@ describe("RLN codec with version 0 and meta setter", () => {
|
||||
};
|
||||
|
||||
it("toWire", async function () {
|
||||
const rlnInstance = await rln.createRLN();
|
||||
const credential = rlnInstance.generateIdentityCredentials();
|
||||
const rlnInstance = await createRLN();
|
||||
const credential = rlnInstance.zerokit.generateIdentityCredentials();
|
||||
const index = 0;
|
||||
const payload = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
|
||||
rlnInstance.insertMember(credential.IDCommitment);
|
||||
rlnInstance.zerokit.insertMember(credential.IDCommitment);
|
||||
|
||||
const rlnEncoder = createRLNEncoder({
|
||||
encoder: createEncoder({ contentTopic: TestContentTopic, metaSetter }),
|
||||
@ -410,7 +409,7 @@ describe("RLN codec with version 0 and meta setter", () => {
|
||||
expect(msg!.meta).to.deep.eq(expectedMeta);
|
||||
|
||||
expect(msg.rateLimitProof).to.not.be.undefined;
|
||||
expect(msg.verify([rlnInstance.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verifyNoRoot()).to.be.true;
|
||||
expect(msg.epoch).to.not.be.undefined;
|
||||
expect(msg.epoch).to.be.gt(0);
|
||||
@ -422,12 +421,12 @@ describe("RLN codec with version 0 and meta setter", () => {
|
||||
});
|
||||
|
||||
it("toProtoObj", async function () {
|
||||
const rlnInstance = await rln.createRLN();
|
||||
const credential = rlnInstance.generateIdentityCredentials();
|
||||
const rlnInstance = await createRLN();
|
||||
const credential = rlnInstance.zerokit.generateIdentityCredentials();
|
||||
const index = 0;
|
||||
const payload = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
|
||||
rlnInstance.insertMember(credential.IDCommitment);
|
||||
rlnInstance.zerokit.insertMember(credential.IDCommitment);
|
||||
|
||||
const rlnEncoder = new RLNEncoder(
|
||||
createEncoder({ contentTopic: TestContentTopic, metaSetter }),
|
||||
@ -458,7 +457,7 @@ describe("RLN codec with version 0 and meta setter", () => {
|
||||
expect(msg).to.not.be.undefined;
|
||||
expect(msg.rateLimitProof).to.not.be.undefined;
|
||||
|
||||
expect(msg.verify([rlnInstance.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true;
|
||||
expect(msg.verifyNoRoot()).to.be.true;
|
||||
expect(msg.epoch).to.not.be.undefined;
|
||||
expect(msg.epoch).to.be.gt(0);
|
||||
|
||||
@ -45,7 +45,7 @@ export class RLNEncoder implements IEncoder {
|
||||
|
||||
private async generateProof(message: IMessage): Promise<IRateLimitProof> {
|
||||
const signal = toRLNSignal(this.contentTopic, message);
|
||||
const proof = await this.rlnInstance.generateRLNProof(
|
||||
const proof = await this.rlnInstance.zerokit.generateRLNProof(
|
||||
signal,
|
||||
this.index,
|
||||
message.timestamp,
|
||||
|
||||
@ -2,20 +2,23 @@ import chai from "chai";
|
||||
import spies from "chai-spies";
|
||||
import * as ethers from "ethers";
|
||||
|
||||
import * as rln from "../index.js";
|
||||
import { createRLN } from "../create.js";
|
||||
|
||||
import { SEPOLIA_CONTRACT } from "./constants.js";
|
||||
import { RLNContract } from "./rln_contract.js";
|
||||
|
||||
chai.use(spies);
|
||||
|
||||
describe("RLN Contract abstraction", () => {
|
||||
it("should be able to fetch members from events and store to rln instance", async () => {
|
||||
const rlnInstance = await rln.createRLN();
|
||||
const rlnInstance = await createRLN();
|
||||
|
||||
rlnInstance.insertMember = () => undefined;
|
||||
rlnInstance.zerokit.insertMember = () => undefined;
|
||||
const insertMemberSpy = chai.spy.on(rlnInstance, "insertMember");
|
||||
|
||||
const voidSigner = new ethers.VoidSigner(rln.SEPOLIA_CONTRACT.address);
|
||||
const rlnContract = new rln.RLNContract(rlnInstance, {
|
||||
registryAddress: rln.SEPOLIA_CONTRACT.address,
|
||||
const voidSigner = new ethers.VoidSigner(SEPOLIA_CONTRACT.address);
|
||||
const rlnContract = new RLNContract(rlnInstance, {
|
||||
registryAddress: SEPOLIA_CONTRACT.address,
|
||||
signer: voidSigner,
|
||||
});
|
||||
|
||||
@ -36,10 +39,10 @@ describe("RLN Contract abstraction", () => {
|
||||
const mockSignature =
|
||||
"0xdeb8a6b00a8e404deb1f52d3aa72ed7f60a2ff4484c737eedaef18a0aacb2dfb4d5d74ac39bb71fa358cf2eb390565a35b026cc6272f2010d4351e17670311c21c";
|
||||
|
||||
const rlnInstance = await rln.createRLN();
|
||||
const voidSigner = new ethers.VoidSigner(rln.SEPOLIA_CONTRACT.address);
|
||||
const rlnContract = new rln.RLNContract(rlnInstance, {
|
||||
registryAddress: rln.SEPOLIA_CONTRACT.address,
|
||||
const rlnInstance = await createRLN();
|
||||
const voidSigner = new ethers.VoidSigner(SEPOLIA_CONTRACT.address);
|
||||
const rlnContract = new RLNContract(rlnInstance, {
|
||||
registryAddress: SEPOLIA_CONTRACT.address,
|
||||
signer: voidSigner,
|
||||
});
|
||||
|
||||
@ -58,7 +61,7 @@ describe("RLN Contract abstraction", () => {
|
||||
);
|
||||
|
||||
const identity =
|
||||
rlnInstance.generateSeededIdentityCredential(mockSignature);
|
||||
rlnInstance.zerokit.generateSeededIdentityCredential(mockSignature);
|
||||
await rlnContract.registerWithIdentity(identity);
|
||||
|
||||
chai.expect(contractSpy).to.have.been.called();
|
||||
|
||||
@ -61,7 +61,7 @@ export class RLNContract {
|
||||
rlnInstance: RLNInstance,
|
||||
{ registryAddress, signer }: RLNContractOptions
|
||||
) {
|
||||
const initialRoot = rlnInstance.getMerkleRoot();
|
||||
const initialRoot = rlnInstance.zerokit.getMerkleRoot();
|
||||
|
||||
this.registryContract = new ethers.Contract(
|
||||
registryAddress,
|
||||
@ -182,14 +182,14 @@ export class RLNContract {
|
||||
}
|
||||
|
||||
const idCommitment = zeroPadLE(hexToBytes(_idCommitment?._hex), 32);
|
||||
rlnInstance.insertMember(idCommitment);
|
||||
rlnInstance.zerokit.insertMember(idCommitment);
|
||||
this._members.set(index.toNumber(), {
|
||||
index,
|
||||
idCommitment: _idCommitment?._hex,
|
||||
});
|
||||
});
|
||||
|
||||
const currentRoot = rlnInstance.getMerkleRoot();
|
||||
const currentRoot = rlnInstance.zerokit.getMerkleRoot();
|
||||
this.merkleRootTracker.pushRoot(blockNumber, currentRoot);
|
||||
});
|
||||
}
|
||||
@ -204,7 +204,7 @@ export class RLNContract {
|
||||
if (this._members.has(index)) {
|
||||
this._members.delete(index);
|
||||
}
|
||||
rlnInstance.deleteMember(index);
|
||||
rlnInstance.zerokit.deleteMember(index);
|
||||
});
|
||||
|
||||
this.merkleRootTracker.backFill(blockNumber);
|
||||
|
||||
@ -6,7 +6,7 @@ describe("js-rln", () => {
|
||||
it("should verify a proof", async function () {
|
||||
const rlnInstance = await createRLN();
|
||||
|
||||
const credential = rlnInstance.generateIdentityCredentials();
|
||||
const credential = rlnInstance.zerokit.generateIdentityCredentials();
|
||||
|
||||
//peer's index in the Merkle Tree
|
||||
const index = 5;
|
||||
@ -15,11 +15,11 @@ describe("js-rln", () => {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
if (i == index) {
|
||||
// insert the current peer's pk
|
||||
rlnInstance.insertMember(credential.IDCommitment);
|
||||
rlnInstance.zerokit.insertMember(credential.IDCommitment);
|
||||
} else {
|
||||
// create a new key pair
|
||||
rlnInstance.insertMember(
|
||||
rlnInstance.generateIdentityCredentials().IDCommitment
|
||||
rlnInstance.zerokit.insertMember(
|
||||
rlnInstance.zerokit.generateIdentityCredentials().IDCommitment
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -33,7 +33,7 @@ describe("js-rln", () => {
|
||||
const epoch = new Date();
|
||||
|
||||
// generating proof
|
||||
const proof = await rlnInstance.generateRLNProof(
|
||||
const proof = await rlnInstance.zerokit.generateRLNProof(
|
||||
uint8Msg,
|
||||
index,
|
||||
epoch,
|
||||
@ -42,7 +42,7 @@ describe("js-rln", () => {
|
||||
|
||||
try {
|
||||
// verify the proof
|
||||
const verifResult = rlnInstance.verifyRLNProof(proof, uint8Msg);
|
||||
const verifResult = rlnInstance.zerokit.verifyRLNProof(proof, uint8Msg);
|
||||
expect(verifResult).to.be.true;
|
||||
} catch (err) {
|
||||
assert.fail(0, 1, "should not have failed proof verification");
|
||||
@ -52,7 +52,7 @@ describe("js-rln", () => {
|
||||
// Modifying the signal so it's invalid
|
||||
uint8Msg[4] = 4;
|
||||
// verify the proof
|
||||
const verifResult = rlnInstance.verifyRLNProof(proof, uint8Msg);
|
||||
const verifResult = rlnInstance.zerokit.verifyRLNProof(proof, uint8Msg);
|
||||
expect(verifResult).to.be.false;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
@ -61,7 +61,8 @@ describe("js-rln", () => {
|
||||
it("should verify a proof with a seeded membership key generation", async function () {
|
||||
const rlnInstance = await createRLN();
|
||||
const seed = "This is a test seed";
|
||||
const credential = rlnInstance.generateSeededIdentityCredential(seed);
|
||||
const credential =
|
||||
rlnInstance.zerokit.generateSeededIdentityCredential(seed);
|
||||
|
||||
//peer's index in the Merkle Tree
|
||||
const index = 5;
|
||||
@ -70,11 +71,11 @@ describe("js-rln", () => {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
if (i == index) {
|
||||
// insert the current peer's pk
|
||||
rlnInstance.insertMember(credential.IDCommitment);
|
||||
rlnInstance.zerokit.insertMember(credential.IDCommitment);
|
||||
} else {
|
||||
// create a new key pair
|
||||
rlnInstance.insertMember(
|
||||
rlnInstance.generateIdentityCredentials().IDCommitment
|
||||
rlnInstance.zerokit.insertMember(
|
||||
rlnInstance.zerokit.generateIdentityCredentials().IDCommitment
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -88,7 +89,7 @@ describe("js-rln", () => {
|
||||
const epoch = new Date();
|
||||
|
||||
// generating proof
|
||||
const proof = await rlnInstance.generateRLNProof(
|
||||
const proof = await rlnInstance.zerokit.generateRLNProof(
|
||||
uint8Msg,
|
||||
index,
|
||||
epoch,
|
||||
@ -97,7 +98,7 @@ describe("js-rln", () => {
|
||||
|
||||
try {
|
||||
// verify the proof
|
||||
const verifResult = rlnInstance.verifyRLNProof(proof, uint8Msg);
|
||||
const verifResult = rlnInstance.zerokit.verifyRLNProof(proof, uint8Msg);
|
||||
expect(verifResult).to.be.true;
|
||||
} catch (err) {
|
||||
assert.fail(0, 1, "should not have failed proof verification");
|
||||
@ -107,7 +108,7 @@ describe("js-rln", () => {
|
||||
// Modifying the signal so it's invalid
|
||||
uint8Msg[4] = 4;
|
||||
// verify the proof
|
||||
const verifResult = rlnInstance.verifyRLNProof(proof, uint8Msg);
|
||||
const verifResult = rlnInstance.zerokit.verifyRLNProof(proof, uint8Msg);
|
||||
expect(verifResult).to.be.false;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
@ -117,8 +118,8 @@ describe("js-rln", () => {
|
||||
it("should generate the same membership key if the same seed is provided", async function () {
|
||||
const rlnInstance = await createRLN();
|
||||
const seed = "This is a test seed";
|
||||
const memKeys1 = rlnInstance.generateSeededIdentityCredential(seed);
|
||||
const memKeys2 = rlnInstance.generateSeededIdentityCredential(seed);
|
||||
const memKeys1 = rlnInstance.zerokit.generateSeededIdentityCredential(seed);
|
||||
const memKeys2 = rlnInstance.zerokit.generateSeededIdentityCredential(seed);
|
||||
|
||||
memKeys1.IDCommitment.forEach((element, index) => {
|
||||
expect(element).to.equal(memKeys2.IDCommitment[index]);
|
||||
|
||||
@ -24,7 +24,7 @@ export class RlnMessage<T extends IDecodedMessage> implements IDecodedMessage {
|
||||
|
||||
public verify(roots: Uint8Array[]): boolean | undefined {
|
||||
return this.rateLimitProof
|
||||
? this.rlnInstance.verifyWithRoots(
|
||||
? this.rlnInstance.zerokit.verifyWithRoots(
|
||||
this.rateLimitProof,
|
||||
toRLNSignal(this.msg.contentTopic, this.msg),
|
||||
...roots
|
||||
@ -34,7 +34,7 @@ export class RlnMessage<T extends IDecodedMessage> implements IDecodedMessage {
|
||||
|
||||
public verifyNoRoot(): boolean | undefined {
|
||||
return this.rateLimitProof
|
||||
? this.rlnInstance.verifyWithNoRoot(
|
||||
? this.rlnInstance.zerokit.verifyWithNoRoot(
|
||||
this.rateLimitProof,
|
||||
toRLNSignal(this.msg.contentTopic, this.msg)
|
||||
) // this.rlnInstance.verifyRLNProof once issue status-im/nwaku#1248 is fixed
|
||||
|
||||
185
src/rln.ts
185
src/rln.ts
@ -2,7 +2,6 @@ import { createDecoder, createEncoder } from "@waku/core";
|
||||
import type {
|
||||
ContentTopic,
|
||||
IDecodedMessage,
|
||||
IRateLimitProof,
|
||||
EncoderOptions as WakuEncoderOptions,
|
||||
} from "@waku/interfaces";
|
||||
import init from "@waku/zerokit-rln-wasm";
|
||||
@ -23,17 +22,11 @@ import type {
|
||||
EncryptedCredentials,
|
||||
} from "./keystore/index.js";
|
||||
import { KeystoreEntity, Password } from "./keystore/types.js";
|
||||
import { Proof, proofToBytes } from "./proof.js";
|
||||
import verificationKey from "./resources/verification_key.js";
|
||||
import * as wc from "./resources/witness_calculator.js";
|
||||
import { WitnessCalculator } from "./resources/witness_calculator.js";
|
||||
import {
|
||||
concatenate,
|
||||
dateToEpoch,
|
||||
epochIntToBytes,
|
||||
extractMetaMaskSigner,
|
||||
writeUIntLE,
|
||||
} from "./utils/index.js";
|
||||
import { extractMetaMaskSigner } from "./utils/index.js";
|
||||
import { Zerokit } from "./zerokit.js";
|
||||
|
||||
async function loadWitnessCalculator(): Promise<WitnessCalculator> {
|
||||
const url = new URL("./resources/rln.wasm", import.meta.url);
|
||||
@ -63,8 +56,9 @@ export async function create(): Promise<RLNInstance> {
|
||||
|
||||
const DEPTH = 20;
|
||||
const zkRLN = zerokitRLN.newRLN(DEPTH, zkey, vkey);
|
||||
const zerokit = new Zerokit(zkRLN, witnessCalculator);
|
||||
|
||||
return new RLNInstance(zkRLN, witnessCalculator);
|
||||
return new RLNInstance(zerokit);
|
||||
}
|
||||
|
||||
type StartRLNOptions = {
|
||||
@ -101,10 +95,7 @@ export class RLNInstance {
|
||||
private keystore = Keystore.create();
|
||||
private _credentials: undefined | DecryptedCredentials;
|
||||
|
||||
constructor(
|
||||
private zkRLN: number,
|
||||
private witnessCalculator: WitnessCalculator
|
||||
) {}
|
||||
constructor(public zerokit: Zerokit) {}
|
||||
|
||||
public get contract(): undefined | RLNContract {
|
||||
return this._contract;
|
||||
@ -212,7 +203,9 @@ export class RLNInstance {
|
||||
let identity = "identity" in options && options.identity;
|
||||
|
||||
if ("signature" in options) {
|
||||
identity = await this.generateSeededIdentityCredential(options.signature);
|
||||
identity = await this.zerokit.generateSeededIdentityCredential(
|
||||
options.signature
|
||||
);
|
||||
}
|
||||
|
||||
if (!identity) {
|
||||
@ -289,166 +282,4 @@ export class RLNInstance {
|
||||
decoder: createDecoder(contentTopic),
|
||||
});
|
||||
}
|
||||
|
||||
generateIdentityCredentials(): IdentityCredential {
|
||||
const memKeys = zerokitRLN.generateExtendedMembershipKey(this.zkRLN); // TODO: rename this function in zerokit rln-wasm
|
||||
return IdentityCredential.fromBytes(memKeys);
|
||||
}
|
||||
|
||||
generateSeededIdentityCredential(seed: string): IdentityCredential {
|
||||
const stringEncoder = new TextEncoder();
|
||||
const seedBytes = stringEncoder.encode(seed);
|
||||
// TODO: rename this function in zerokit rln-wasm
|
||||
const memKeys = zerokitRLN.generateSeededExtendedMembershipKey(
|
||||
this.zkRLN,
|
||||
seedBytes
|
||||
);
|
||||
return IdentityCredential.fromBytes(memKeys);
|
||||
}
|
||||
|
||||
insertMember(idCommitment: Uint8Array): void {
|
||||
zerokitRLN.insertMember(this.zkRLN, idCommitment);
|
||||
}
|
||||
|
||||
insertMembers(index: number, ...idCommitments: Array<Uint8Array>): void {
|
||||
// serializes a seq of IDCommitments to a byte seq
|
||||
// the order of serialization is |id_commitment_len<8>|id_commitment<var>|
|
||||
const idCommitmentLen = writeUIntLE(
|
||||
new Uint8Array(8),
|
||||
idCommitments.length,
|
||||
0,
|
||||
8
|
||||
);
|
||||
const idCommitmentBytes = concatenate(idCommitmentLen, ...idCommitments);
|
||||
zerokitRLN.setLeavesFrom(this.zkRLN, index, idCommitmentBytes);
|
||||
}
|
||||
|
||||
deleteMember(index: number): void {
|
||||
zerokitRLN.deleteLeaf(this.zkRLN, index);
|
||||
}
|
||||
|
||||
getMerkleRoot(): Uint8Array {
|
||||
return zerokitRLN.getRoot(this.zkRLN);
|
||||
}
|
||||
|
||||
serializeMessage(
|
||||
uint8Msg: Uint8Array,
|
||||
memIndex: number,
|
||||
epoch: Uint8Array,
|
||||
idKey: Uint8Array
|
||||
): Uint8Array {
|
||||
// calculate message length
|
||||
const msgLen = writeUIntLE(new Uint8Array(8), uint8Msg.length, 0, 8);
|
||||
|
||||
// Converting index to LE bytes
|
||||
const memIndexBytes = writeUIntLE(new Uint8Array(8), memIndex, 0, 8);
|
||||
|
||||
// [ id_key<32> | id_index<8> | epoch<32> | signal_len<8> | signal<var> ]
|
||||
return concatenate(idKey, memIndexBytes, epoch, msgLen, uint8Msg);
|
||||
}
|
||||
|
||||
async generateRLNProof(
|
||||
msg: Uint8Array,
|
||||
index: number,
|
||||
epoch: Uint8Array | Date | undefined,
|
||||
idSecretHash: Uint8Array
|
||||
): Promise<IRateLimitProof> {
|
||||
if (epoch == undefined) {
|
||||
epoch = epochIntToBytes(dateToEpoch(new Date()));
|
||||
} else if (epoch instanceof Date) {
|
||||
epoch = epochIntToBytes(dateToEpoch(epoch));
|
||||
}
|
||||
|
||||
if (epoch.length != 32) throw "invalid epoch";
|
||||
if (idSecretHash.length != 32) throw "invalid id secret hash";
|
||||
if (index < 0) throw "index must be >= 0";
|
||||
|
||||
const serialized_msg = this.serializeMessage(
|
||||
msg,
|
||||
index,
|
||||
epoch,
|
||||
idSecretHash
|
||||
);
|
||||
const rlnWitness = zerokitRLN.getSerializedRLNWitness(
|
||||
this.zkRLN,
|
||||
serialized_msg
|
||||
);
|
||||
const inputs = zerokitRLN.RLNWitnessToJson(this.zkRLN, rlnWitness);
|
||||
const calculatedWitness = await this.witnessCalculator.calculateWitness(
|
||||
inputs,
|
||||
false
|
||||
); // no sanity check being used in zerokit
|
||||
|
||||
const proofBytes = zerokitRLN.generate_rln_proof_with_witness(
|
||||
this.zkRLN,
|
||||
calculatedWitness,
|
||||
rlnWitness
|
||||
);
|
||||
|
||||
return new Proof(proofBytes);
|
||||
}
|
||||
|
||||
verifyRLNProof(
|
||||
proof: IRateLimitProof | Uint8Array,
|
||||
msg: Uint8Array
|
||||
): boolean {
|
||||
let pBytes: Uint8Array;
|
||||
if (proof instanceof Uint8Array) {
|
||||
pBytes = proof;
|
||||
} else {
|
||||
pBytes = proofToBytes(proof);
|
||||
}
|
||||
|
||||
// calculate message length
|
||||
const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
|
||||
|
||||
return zerokitRLN.verifyRLNProof(
|
||||
this.zkRLN,
|
||||
concatenate(pBytes, msgLen, msg)
|
||||
);
|
||||
}
|
||||
|
||||
verifyWithRoots(
|
||||
proof: IRateLimitProof | Uint8Array,
|
||||
msg: Uint8Array,
|
||||
...roots: Array<Uint8Array>
|
||||
): boolean {
|
||||
let pBytes: Uint8Array;
|
||||
if (proof instanceof Uint8Array) {
|
||||
pBytes = proof;
|
||||
} else {
|
||||
pBytes = proofToBytes(proof);
|
||||
}
|
||||
// calculate message length
|
||||
const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
|
||||
|
||||
const rootsBytes = concatenate(...roots);
|
||||
|
||||
return zerokitRLN.verifyWithRoots(
|
||||
this.zkRLN,
|
||||
concatenate(pBytes, msgLen, msg),
|
||||
rootsBytes
|
||||
);
|
||||
}
|
||||
|
||||
verifyWithNoRoot(
|
||||
proof: IRateLimitProof | Uint8Array,
|
||||
msg: Uint8Array
|
||||
): boolean {
|
||||
let pBytes: Uint8Array;
|
||||
if (proof instanceof Uint8Array) {
|
||||
pBytes = proof;
|
||||
} else {
|
||||
pBytes = proofToBytes(proof);
|
||||
}
|
||||
|
||||
// calculate message length
|
||||
const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
|
||||
|
||||
return zerokitRLN.verifyWithRoots(
|
||||
this.zkRLN,
|
||||
concatenate(pBytes, msgLen, msg),
|
||||
new Uint8Array()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
181
src/zerokit.ts
Normal file
181
src/zerokit.ts
Normal file
@ -0,0 +1,181 @@
|
||||
import type { IRateLimitProof } from "@waku/interfaces";
|
||||
import * as zerokitRLN from "@waku/zerokit-rln-wasm";
|
||||
|
||||
import { IdentityCredential } from "./identity.js";
|
||||
import { Proof, proofToBytes } from "./proof.js";
|
||||
import { WitnessCalculator } from "./resources/witness_calculator.js";
|
||||
import {
|
||||
concatenate,
|
||||
dateToEpoch,
|
||||
epochIntToBytes,
|
||||
writeUIntLE,
|
||||
} from "./utils/index.js";
|
||||
|
||||
export class Zerokit {
|
||||
constructor(
|
||||
private zkRLN: number,
|
||||
private witnessCalculator: WitnessCalculator
|
||||
) {}
|
||||
|
||||
generateIdentityCredentials(): IdentityCredential {
|
||||
const memKeys = zerokitRLN.generateExtendedMembershipKey(this.zkRLN); // TODO: rename this function in zerokit rln-wasm
|
||||
return IdentityCredential.fromBytes(memKeys);
|
||||
}
|
||||
|
||||
generateSeededIdentityCredential(seed: string): IdentityCredential {
|
||||
const stringEncoder = new TextEncoder();
|
||||
const seedBytes = stringEncoder.encode(seed);
|
||||
// TODO: rename this function in zerokit rln-wasm
|
||||
const memKeys = zerokitRLN.generateSeededExtendedMembershipKey(
|
||||
this.zkRLN,
|
||||
seedBytes
|
||||
);
|
||||
return IdentityCredential.fromBytes(memKeys);
|
||||
}
|
||||
|
||||
insertMember(idCommitment: Uint8Array): void {
|
||||
zerokitRLN.insertMember(this.zkRLN, idCommitment);
|
||||
}
|
||||
|
||||
insertMembers(index: number, ...idCommitments: Array<Uint8Array>): void {
|
||||
// serializes a seq of IDCommitments to a byte seq
|
||||
// the order of serialization is |id_commitment_len<8>|id_commitment<var>|
|
||||
const idCommitmentLen = writeUIntLE(
|
||||
new Uint8Array(8),
|
||||
idCommitments.length,
|
||||
0,
|
||||
8
|
||||
);
|
||||
const idCommitmentBytes = concatenate(idCommitmentLen, ...idCommitments);
|
||||
zerokitRLN.setLeavesFrom(this.zkRLN, index, idCommitmentBytes);
|
||||
}
|
||||
|
||||
deleteMember(index: number): void {
|
||||
zerokitRLN.deleteLeaf(this.zkRLN, index);
|
||||
}
|
||||
|
||||
getMerkleRoot(): Uint8Array {
|
||||
return zerokitRLN.getRoot(this.zkRLN);
|
||||
}
|
||||
|
||||
serializeMessage(
|
||||
uint8Msg: Uint8Array,
|
||||
memIndex: number,
|
||||
epoch: Uint8Array,
|
||||
idKey: Uint8Array
|
||||
): Uint8Array {
|
||||
// calculate message length
|
||||
const msgLen = writeUIntLE(new Uint8Array(8), uint8Msg.length, 0, 8);
|
||||
|
||||
// Converting index to LE bytes
|
||||
const memIndexBytes = writeUIntLE(new Uint8Array(8), memIndex, 0, 8);
|
||||
|
||||
// [ id_key<32> | id_index<8> | epoch<32> | signal_len<8> | signal<var> ]
|
||||
return concatenate(idKey, memIndexBytes, epoch, msgLen, uint8Msg);
|
||||
}
|
||||
|
||||
async generateRLNProof(
|
||||
msg: Uint8Array,
|
||||
index: number,
|
||||
epoch: Uint8Array | Date | undefined,
|
||||
idSecretHash: Uint8Array
|
||||
): Promise<IRateLimitProof> {
|
||||
if (epoch == undefined) {
|
||||
epoch = epochIntToBytes(dateToEpoch(new Date()));
|
||||
} else if (epoch instanceof Date) {
|
||||
epoch = epochIntToBytes(dateToEpoch(epoch));
|
||||
}
|
||||
|
||||
if (epoch.length != 32) throw "invalid epoch";
|
||||
if (idSecretHash.length != 32) throw "invalid id secret hash";
|
||||
if (index < 0) throw "index must be >= 0";
|
||||
|
||||
const serialized_msg = this.serializeMessage(
|
||||
msg,
|
||||
index,
|
||||
epoch,
|
||||
idSecretHash
|
||||
);
|
||||
const rlnWitness = zerokitRLN.getSerializedRLNWitness(
|
||||
this.zkRLN,
|
||||
serialized_msg
|
||||
);
|
||||
const inputs = zerokitRLN.RLNWitnessToJson(this.zkRLN, rlnWitness);
|
||||
const calculatedWitness = await this.witnessCalculator.calculateWitness(
|
||||
inputs,
|
||||
false
|
||||
); // no sanity check being used in zerokit
|
||||
|
||||
const proofBytes = zerokitRLN.generate_rln_proof_with_witness(
|
||||
this.zkRLN,
|
||||
calculatedWitness,
|
||||
rlnWitness
|
||||
);
|
||||
|
||||
return new Proof(proofBytes);
|
||||
}
|
||||
|
||||
verifyRLNProof(
|
||||
proof: IRateLimitProof | Uint8Array,
|
||||
msg: Uint8Array
|
||||
): boolean {
|
||||
let pBytes: Uint8Array;
|
||||
if (proof instanceof Uint8Array) {
|
||||
pBytes = proof;
|
||||
} else {
|
||||
pBytes = proofToBytes(proof);
|
||||
}
|
||||
|
||||
// calculate message length
|
||||
const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
|
||||
|
||||
return zerokitRLN.verifyRLNProof(
|
||||
this.zkRLN,
|
||||
concatenate(pBytes, msgLen, msg)
|
||||
);
|
||||
}
|
||||
|
||||
verifyWithRoots(
|
||||
proof: IRateLimitProof | Uint8Array,
|
||||
msg: Uint8Array,
|
||||
...roots: Array<Uint8Array>
|
||||
): boolean {
|
||||
let pBytes: Uint8Array;
|
||||
if (proof instanceof Uint8Array) {
|
||||
pBytes = proof;
|
||||
} else {
|
||||
pBytes = proofToBytes(proof);
|
||||
}
|
||||
// calculate message length
|
||||
const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
|
||||
|
||||
const rootsBytes = concatenate(...roots);
|
||||
|
||||
return zerokitRLN.verifyWithRoots(
|
||||
this.zkRLN,
|
||||
concatenate(pBytes, msgLen, msg),
|
||||
rootsBytes
|
||||
);
|
||||
}
|
||||
|
||||
verifyWithNoRoot(
|
||||
proof: IRateLimitProof | Uint8Array,
|
||||
msg: Uint8Array
|
||||
): boolean {
|
||||
let pBytes: Uint8Array;
|
||||
if (proof instanceof Uint8Array) {
|
||||
pBytes = proof;
|
||||
} else {
|
||||
pBytes = proofToBytes(proof);
|
||||
}
|
||||
|
||||
// calculate message length
|
||||
const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
|
||||
|
||||
return zerokitRLN.verifyWithRoots(
|
||||
this.zkRLN,
|
||||
concatenate(pBytes, msgLen, msg),
|
||||
new Uint8Array()
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user