mirror of
https://github.com/logos-messaging/js-rln.git
synced 2026-01-04 06:33:09 +00:00
feat: track roots in rln contract and use sepolia instead of goerli (#62)
This commit is contained in:
parent
b7cb3f9bbf
commit
7e93896538
@ -9,6 +9,7 @@
|
|||||||
"merkle",
|
"merkle",
|
||||||
"nwaku",
|
"nwaku",
|
||||||
"rlnjs",
|
"rlnjs",
|
||||||
|
"sepolia",
|
||||||
"vkey",
|
"vkey",
|
||||||
"Waku",
|
"Waku",
|
||||||
"zerokit",
|
"zerokit",
|
||||||
|
|||||||
@ -1,58 +1,64 @@
|
|||||||
import * as rln from "@waku/rln";
|
import * as rln from "@waku/rln";
|
||||||
|
|
||||||
rln.create().then(async rlnInstance => {
|
rln.create().then(async (rlnInstance) => {
|
||||||
const credentials = rlnInstance.generateIdentityCredentials();
|
const credentials = rlnInstance.generateIdentityCredentials();
|
||||||
|
|
||||||
//peer's index in the Merkle Tree
|
//peer's index in the Merkle Tree
|
||||||
const index = 5
|
const index = 5;
|
||||||
|
|
||||||
// Create a Merkle tree with random members
|
// Create a Merkle tree with random members
|
||||||
for (let i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
if (i == index) {
|
if (i == index) {
|
||||||
// insert the current peer's pk
|
// insert the current peer's pk
|
||||||
rlnInstance.insertMember(credentials.IDCommitment);
|
rlnInstance.insertMember(credentials.IDCommitment);
|
||||||
} else {
|
} else {
|
||||||
// create a new key pair
|
// create a new key pair
|
||||||
const credentials = rlnInstance.generateIdentityCredentials(); // TODO: handle error
|
const credentials = rlnInstance.generateIdentityCredentials(); // TODO: handle error
|
||||||
rlnInstance.insertMember(credentials.IDCommitment);
|
rlnInstance.insertMember(credentials.IDCommitment);
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// prepare the message
|
// prepare the message
|
||||||
const uint8Msg = Uint8Array.from("Hello World".split("").map(x => x.charCodeAt()));
|
const uint8Msg = Uint8Array.from(
|
||||||
|
"Hello World".split("").map((x) => x.charCodeAt())
|
||||||
|
);
|
||||||
|
|
||||||
// setting up the epoch
|
// setting up the epoch
|
||||||
const epoch = new Date();
|
const epoch = new Date();
|
||||||
|
|
||||||
console.log("Generating proof...");
|
console.log("Generating proof...");
|
||||||
console.time("proof_gen_timer");
|
console.time("proof_gen_timer");
|
||||||
let proof = await rlnInstance.generateRLNProof(uint8Msg, index, epoch, credentials.IDSecretHash)
|
let proof = await rlnInstance.generateRLNProof(
|
||||||
console.timeEnd("proof_gen_timer");
|
uint8Msg,
|
||||||
console.log("Proof", proof)
|
index,
|
||||||
|
epoch,
|
||||||
|
credentials.IDSecretHash
|
||||||
|
);
|
||||||
|
console.timeEnd("proof_gen_timer");
|
||||||
|
console.log("Proof", proof);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// verify the proof
|
// verify the proof
|
||||||
let verifResult = rlnInstance.verifyRLNProof(proof, uint8Msg);
|
let verifResult = rlnInstance.verifyRLNProof(proof, uint8Msg);
|
||||||
console.log("Is proof verified?", verifResult ? "yes" : "no");
|
console.log("Is proof verified?", verifResult ? "yes" : "no");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("Invalid proof")
|
console.log("Invalid proof");
|
||||||
}
|
}
|
||||||
|
|
||||||
const provider = new ethers.providers.Web3Provider(
|
const provider = new ethers.providers.Web3Provider(window.ethereum, "any");
|
||||||
window.ethereum,
|
|
||||||
"any"
|
|
||||||
);
|
|
||||||
|
|
||||||
const DEFAULT_SIGNATURE_MESSAGE =
|
const DEFAULT_SIGNATURE_MESSAGE =
|
||||||
"The signature of this message will be used to generate your RLN credentials. Anyone accessing it may send messages on your behalf, please only share with the RLN dApp";
|
"The signature of this message will be used to generate your RLN credentials. Anyone accessing it may send messages on your behalf, please only share with the RLN dApp";
|
||||||
|
|
||||||
const signer = provider.getSigner();
|
const signer = provider.getSigner();
|
||||||
const signature = await signer.signMessage(DEFAULT_SIGNATURE_MESSAGE);
|
const signature = await signer.signMessage(DEFAULT_SIGNATURE_MESSAGE);
|
||||||
console.log(`Got signature: ${signature}`);
|
console.log(`Got signature: ${signature}`);
|
||||||
|
|
||||||
const contract = await rln.RLNContract.init(rlnInstance, {address: rln.GOERLI_CONTRACT.address, provider: signer });
|
const contract = await rln.RLNContract.init(rlnInstance, {
|
||||||
|
address: rln.SEPOLIA_CONTRACT.address,
|
||||||
|
provider: signer,
|
||||||
|
});
|
||||||
|
|
||||||
const event = await contract.registerMember(rlnInstance, signature);
|
const event = await contract.registerMember(rlnInstance, signature);
|
||||||
console.log(`Registered as member with ${event}`);
|
console.log(`Registered as member with ${event}`);
|
||||||
});
|
});
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@waku/rln",
|
"name": "@waku/rln",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@waku/rln",
|
"name": "@waku/rln",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"license": "MIT OR Apache-2.0",
|
"license": "MIT OR Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@waku/utils": "^0.0.5",
|
"@waku/utils": "^0.0.5",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@waku/rln",
|
"name": "@waku/rln",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"description": "Rate Limit Nullifier for js-waku",
|
"description": "Rate Limit Nullifier for js-waku",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
"module": "./dist/index.js",
|
"module": "./dist/index.js",
|
||||||
|
|||||||
@ -63,7 +63,7 @@ describe("RLN codec with version 0", () => {
|
|||||||
))!;
|
))!;
|
||||||
|
|
||||||
expect(msg.rateLimitProof).to.not.be.undefined;
|
expect(msg.rateLimitProof).to.not.be.undefined;
|
||||||
expect(msg.verify()).to.be.true;
|
expect(msg.verify([rlnInstance.getMerkleRoot()])).to.be.true;
|
||||||
expect(msg.verifyNoRoot()).to.be.true;
|
expect(msg.verifyNoRoot()).to.be.true;
|
||||||
expect(msg.epoch).to.not.be.undefined;
|
expect(msg.epoch).to.not.be.undefined;
|
||||||
expect(msg.epoch).to.be.gt(0);
|
expect(msg.epoch).to.be.gt(0);
|
||||||
@ -104,7 +104,7 @@ describe("RLN codec with version 0", () => {
|
|||||||
expect(msg).to.not.be.undefined;
|
expect(msg).to.not.be.undefined;
|
||||||
expect(msg.rateLimitProof).to.not.be.undefined;
|
expect(msg.rateLimitProof).to.not.be.undefined;
|
||||||
|
|
||||||
expect(msg.verify()).to.be.true;
|
expect(msg.verify([rlnInstance.getMerkleRoot()])).to.be.true;
|
||||||
expect(msg.verifyNoRoot()).to.be.true;
|
expect(msg.verifyNoRoot()).to.be.true;
|
||||||
expect(msg.epoch).to.not.be.undefined;
|
expect(msg.epoch).to.not.be.undefined;
|
||||||
expect(msg.epoch).to.be.gt(0);
|
expect(msg.epoch).to.be.gt(0);
|
||||||
@ -153,7 +153,7 @@ describe("RLN codec with version 1", () => {
|
|||||||
))!;
|
))!;
|
||||||
|
|
||||||
expect(msg.rateLimitProof).to.not.be.undefined;
|
expect(msg.rateLimitProof).to.not.be.undefined;
|
||||||
expect(msg.verify()).to.be.true;
|
expect(msg.verify([rlnInstance.getMerkleRoot()])).to.be.true;
|
||||||
expect(msg.verifyNoRoot()).to.be.true;
|
expect(msg.verifyNoRoot()).to.be.true;
|
||||||
expect(msg.epoch).to.not.be.undefined;
|
expect(msg.epoch).to.not.be.undefined;
|
||||||
expect(msg.epoch).to.be.gt(0);
|
expect(msg.epoch).to.be.gt(0);
|
||||||
@ -199,7 +199,7 @@ describe("RLN codec with version 1", () => {
|
|||||||
expect(msg).to.not.be.undefined;
|
expect(msg).to.not.be.undefined;
|
||||||
expect(msg.rateLimitProof).to.not.be.undefined;
|
expect(msg.rateLimitProof).to.not.be.undefined;
|
||||||
|
|
||||||
expect(msg.verify()).to.be.true;
|
expect(msg.verify([rlnInstance.getMerkleRoot()])).to.be.true;
|
||||||
expect(msg.verifyNoRoot()).to.be.true;
|
expect(msg.verifyNoRoot()).to.be.true;
|
||||||
expect(msg.epoch).to.not.be.undefined;
|
expect(msg.epoch).to.not.be.undefined;
|
||||||
expect(msg.epoch).to.be.gt(0);
|
expect(msg.epoch).to.be.gt(0);
|
||||||
@ -247,7 +247,7 @@ describe("RLN codec with version 1", () => {
|
|||||||
))!;
|
))!;
|
||||||
|
|
||||||
expect(msg.rateLimitProof).to.not.be.undefined;
|
expect(msg.rateLimitProof).to.not.be.undefined;
|
||||||
expect(msg.verify()).to.be.true;
|
expect(msg.verify([rlnInstance.getMerkleRoot()])).to.be.true;
|
||||||
expect(msg.verifyNoRoot()).to.be.true;
|
expect(msg.verifyNoRoot()).to.be.true;
|
||||||
expect(msg.epoch).to.not.be.undefined;
|
expect(msg.epoch).to.not.be.undefined;
|
||||||
expect(msg.epoch).to.be.gt(0);
|
expect(msg.epoch).to.be.gt(0);
|
||||||
@ -294,7 +294,7 @@ describe("RLN codec with version 1", () => {
|
|||||||
expect(msg).to.not.be.undefined;
|
expect(msg).to.not.be.undefined;
|
||||||
expect(msg.rateLimitProof).to.not.be.undefined;
|
expect(msg.rateLimitProof).to.not.be.undefined;
|
||||||
|
|
||||||
expect(msg.verify()).to.be.true;
|
expect(msg.verify([rlnInstance.getMerkleRoot()])).to.be.true;
|
||||||
expect(msg.verifyNoRoot()).to.be.true;
|
expect(msg.verifyNoRoot()).to.be.true;
|
||||||
expect(msg.epoch).to.not.be.undefined;
|
expect(msg.epoch).to.not.be.undefined;
|
||||||
expect(msg.epoch).to.be.gt(0);
|
expect(msg.epoch).to.be.gt(0);
|
||||||
@ -340,7 +340,7 @@ describe("RLN Codec - epoch", () => {
|
|||||||
expect(msg).to.not.be.undefined;
|
expect(msg).to.not.be.undefined;
|
||||||
expect(msg.rateLimitProof).to.not.be.undefined;
|
expect(msg.rateLimitProof).to.not.be.undefined;
|
||||||
|
|
||||||
expect(msg.verify()).to.be.true;
|
expect(msg.verify([rlnInstance.getMerkleRoot()])).to.be.true;
|
||||||
expect(msg.verifyNoRoot()).to.be.true;
|
expect(msg.verifyNoRoot()).to.be.true;
|
||||||
expect(msg.epoch).to.not.be.undefined;
|
expect(msg.epoch).to.not.be.undefined;
|
||||||
expect(msg.epoch!.toString(10).length).to.eq(9);
|
expect(msg.epoch!.toString(10).length).to.eq(9);
|
||||||
|
|||||||
@ -6,9 +6,9 @@ export const RLN_ABI = [
|
|||||||
"event MemberWithdrawn(uint256 pubkey, uint256 index)",
|
"event MemberWithdrawn(uint256 pubkey, uint256 index)",
|
||||||
];
|
];
|
||||||
|
|
||||||
export const GOERLI_CONTRACT = {
|
export const SEPOLIA_CONTRACT = {
|
||||||
chainId: 5,
|
chainId: 11155111,
|
||||||
startBlock: 7109391,
|
startBlock: 3193048,
|
||||||
address: "0x4252105670fe33d2947e8ead304969849e64f2a6",
|
address: "0x9C09146844C1326c2dBC41c451766C7138F88155",
|
||||||
abi: RLN_ABI,
|
abi: RLN_ABI,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { RLNDecoder, RLNEncoder } from "./codec.js";
|
import { RLNDecoder, RLNEncoder } from "./codec.js";
|
||||||
import { GOERLI_CONTRACT, RLN_ABI } from "./constants.js";
|
import { RLN_ABI, SEPOLIA_CONTRACT } from "./constants.js";
|
||||||
import {
|
import {
|
||||||
IdentityCredential,
|
IdentityCredential,
|
||||||
Proof,
|
Proof,
|
||||||
@ -28,5 +28,5 @@ export {
|
|||||||
MerkleRootTracker,
|
MerkleRootTracker,
|
||||||
RLNContract,
|
RLNContract,
|
||||||
RLN_ABI,
|
RLN_ABI,
|
||||||
GOERLI_CONTRACT,
|
SEPOLIA_CONTRACT,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -22,11 +22,12 @@ export class RlnMessage<T extends IDecodedMessage> implements IDecodedMessage {
|
|||||||
public rateLimitProof: IRateLimitProof | undefined
|
public rateLimitProof: IRateLimitProof | undefined
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public verify(): boolean | undefined {
|
public verify(roots: Uint8Array[]): boolean | undefined {
|
||||||
return this.rateLimitProof
|
return this.rateLimitProof
|
||||||
? this.rlnInstance.verifyWithRoots(
|
? this.rlnInstance.verifyWithRoots(
|
||||||
this.rateLimitProof,
|
this.rateLimitProof,
|
||||||
toRLNSignal(this.msg.contentTopic, this.msg)
|
toRLNSignal(this.msg.contentTopic, this.msg),
|
||||||
|
...roots
|
||||||
) // this.rlnInstance.verifyRLNProof once issue status-im/nwaku#1248 is fixed
|
) // this.rlnInstance.verifyRLNProof once issue status-im/nwaku#1248 is fixed
|
||||||
: undefined;
|
: undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,9 +13,9 @@ describe("RLN Contract abstraction", () => {
|
|||||||
rlnInstance.insertMember = () => undefined;
|
rlnInstance.insertMember = () => undefined;
|
||||||
const insertMemberSpy = chai.spy.on(rlnInstance, "insertMember");
|
const insertMemberSpy = chai.spy.on(rlnInstance, "insertMember");
|
||||||
|
|
||||||
const voidSigner = new ethers.VoidSigner(rln.GOERLI_CONTRACT.address);
|
const voidSigner = new ethers.VoidSigner(rln.SEPOLIA_CONTRACT.address);
|
||||||
const rlnContract = new rln.RLNContract({
|
const rlnContract = new rln.RLNContract(rlnInstance, {
|
||||||
address: rln.GOERLI_CONTRACT.address,
|
address: rln.SEPOLIA_CONTRACT.address,
|
||||||
provider: voidSigner,
|
provider: voidSigner,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -33,9 +33,9 @@ describe("RLN Contract abstraction", () => {
|
|||||||
"0xdeb8a6b00a8e404deb1f52d3aa72ed7f60a2ff4484c737eedaef18a0aacb2dfb4d5d74ac39bb71fa358cf2eb390565a35b026cc6272f2010d4351e17670311c21c";
|
"0xdeb8a6b00a8e404deb1f52d3aa72ed7f60a2ff4484c737eedaef18a0aacb2dfb4d5d74ac39bb71fa358cf2eb390565a35b026cc6272f2010d4351e17670311c21c";
|
||||||
|
|
||||||
const rlnInstance = await rln.create();
|
const rlnInstance = await rln.create();
|
||||||
const voidSigner = new ethers.VoidSigner(rln.GOERLI_CONTRACT.address);
|
const voidSigner = new ethers.VoidSigner(rln.SEPOLIA_CONTRACT.address);
|
||||||
const rlnContract = new rln.RLNContract({
|
const rlnContract = new rln.RLNContract(rlnInstance, {
|
||||||
address: rln.GOERLI_CONTRACT.address,
|
address: rln.SEPOLIA_CONTRACT.address,
|
||||||
provider: voidSigner,
|
provider: voidSigner,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { ethers } from "ethers";
|
|||||||
|
|
||||||
import { RLN_ABI } from "./constants.js";
|
import { RLN_ABI } from "./constants.js";
|
||||||
import { IdentityCredential, RLNInstance } from "./rln.js";
|
import { IdentityCredential, RLNInstance } from "./rln.js";
|
||||||
|
import { MerkleRootTracker } from "./root_tracker";
|
||||||
|
|
||||||
type Member = {
|
type Member = {
|
||||||
pubkey: string;
|
pubkey: string;
|
||||||
@ -22,6 +23,7 @@ type FetchMembersOptions = {
|
|||||||
export class RLNContract {
|
export class RLNContract {
|
||||||
private _contract: ethers.Contract;
|
private _contract: ethers.Contract;
|
||||||
private membersFilter: ethers.EventFilter;
|
private membersFilter: ethers.EventFilter;
|
||||||
|
private merkleRootTracker: MerkleRootTracker;
|
||||||
|
|
||||||
private _members: Member[] = [];
|
private _members: Member[] = [];
|
||||||
|
|
||||||
@ -29,7 +31,7 @@ export class RLNContract {
|
|||||||
rlnInstance: RLNInstance,
|
rlnInstance: RLNInstance,
|
||||||
options: ContractOptions
|
options: ContractOptions
|
||||||
): Promise<RLNContract> {
|
): Promise<RLNContract> {
|
||||||
const rlnContract = new RLNContract(options);
|
const rlnContract = new RLNContract(rlnInstance, options);
|
||||||
|
|
||||||
await rlnContract.fetchMembers(rlnInstance);
|
await rlnContract.fetchMembers(rlnInstance);
|
||||||
rlnContract.subscribeToMembers(rlnInstance);
|
rlnContract.subscribeToMembers(rlnInstance);
|
||||||
@ -37,8 +39,14 @@ export class RLNContract {
|
|||||||
return rlnContract;
|
return rlnContract;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor({ address, provider }: ContractOptions) {
|
constructor(
|
||||||
|
rlnInstance: RLNInstance,
|
||||||
|
{ address, provider }: ContractOptions
|
||||||
|
) {
|
||||||
|
const initialRoot = rlnInstance.getMerkleRoot();
|
||||||
|
|
||||||
this._contract = new ethers.Contract(address, RLN_ABI, provider);
|
this._contract = new ethers.Contract(address, RLN_ABI, provider);
|
||||||
|
this.merkleRootTracker = new MerkleRootTracker(5, initialRoot);
|
||||||
this.membersFilter = this.contract.filters.MemberRegistered();
|
this.membersFilter = this.contract.filters.MemberRegistered();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,38 +66,91 @@ export class RLNContract {
|
|||||||
...options,
|
...options,
|
||||||
membersFilter: this.membersFilter,
|
membersFilter: this.membersFilter,
|
||||||
});
|
});
|
||||||
|
this.processEvents(rlnInstance, registeredMemberEvents);
|
||||||
|
}
|
||||||
|
|
||||||
for (const event of registeredMemberEvents) {
|
public processEvents(rlnInstance: RLNInstance, events: ethers.Event[]): void {
|
||||||
this.addMemberFromEvent(rlnInstance, event);
|
const toRemoveTable = new Map<number, number[]>();
|
||||||
}
|
const toInsertTable = new Map<number, ethers.Event[]>();
|
||||||
|
|
||||||
|
events.forEach((evt) => {
|
||||||
|
if (!evt.args) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evt.removed) {
|
||||||
|
const index: number = evt.args.index;
|
||||||
|
const toRemoveVal = toRemoveTable.get(evt.blockNumber);
|
||||||
|
if (toRemoveVal != undefined) {
|
||||||
|
toRemoveVal.push(index);
|
||||||
|
toRemoveTable.set(evt.blockNumber, toRemoveVal);
|
||||||
|
} else {
|
||||||
|
toRemoveTable.set(evt.blockNumber, [index]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let eventsPerBlock = toInsertTable.get(evt.blockNumber);
|
||||||
|
if (eventsPerBlock == undefined) {
|
||||||
|
eventsPerBlock = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
eventsPerBlock.push(evt);
|
||||||
|
toInsertTable.set(evt.blockNumber, eventsPerBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.removeMembers(rlnInstance, toRemoveTable);
|
||||||
|
this.insertMembers(rlnInstance, toInsertTable);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private insertMembers(
|
||||||
|
rlnInstance: RLNInstance,
|
||||||
|
toInsert: Map<number, ethers.Event[]>
|
||||||
|
): void {
|
||||||
|
toInsert.forEach((events: ethers.Event[], blockNumber: number) => {
|
||||||
|
events.forEach((evt) => {
|
||||||
|
if (!evt.args) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pubkey = evt.args.pubkey;
|
||||||
|
const index = evt.args.index;
|
||||||
|
const idCommitment = ethers.utils.zeroPad(
|
||||||
|
ethers.utils.arrayify(pubkey),
|
||||||
|
32
|
||||||
|
);
|
||||||
|
rlnInstance.insertMember(idCommitment);
|
||||||
|
this.members.push({ index, pubkey });
|
||||||
|
});
|
||||||
|
|
||||||
|
const currentRoot = rlnInstance.getMerkleRoot();
|
||||||
|
this.merkleRootTracker.pushRoot(blockNumber, currentRoot);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private removeMembers(
|
||||||
|
rlnInstance: RLNInstance,
|
||||||
|
toRemove: Map<number, number[]>
|
||||||
|
): void {
|
||||||
|
const removeDescending = new Map([...toRemove].sort().reverse());
|
||||||
|
removeDescending.forEach((indexes: number[], blockNumber: number) => {
|
||||||
|
indexes.forEach((index) => {
|
||||||
|
const idx = this.members.findIndex((m) => m.index === index);
|
||||||
|
if (idx > -1) {
|
||||||
|
this.members.splice(idx, 1);
|
||||||
|
}
|
||||||
|
rlnInstance.deleteMember(index);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.merkleRootTracker.backFill(blockNumber);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public subscribeToMembers(rlnInstance: RLNInstance): void {
|
public subscribeToMembers(rlnInstance: RLNInstance): void {
|
||||||
this.contract.on(this.membersFilter, (_pubkey, _index, event) =>
|
this.contract.on(this.membersFilter, (_pubkey, _index, event) =>
|
||||||
this.addMemberFromEvent(rlnInstance, event)
|
this.processEvents(rlnInstance, event)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private addMemberFromEvent(
|
|
||||||
rlnInstance: RLNInstance,
|
|
||||||
event: ethers.Event
|
|
||||||
): void {
|
|
||||||
if (!event.args) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pubkey: string = event.args.pubkey;
|
|
||||||
const index: number = event.args.index;
|
|
||||||
|
|
||||||
this.members.push({ index, pubkey });
|
|
||||||
|
|
||||||
const idCommitment = ethers.utils.zeroPad(
|
|
||||||
ethers.utils.arrayify(pubkey),
|
|
||||||
32
|
|
||||||
);
|
|
||||||
rlnInstance.insertMember(idCommitment);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async registerWithSignature(
|
public async registerWithSignature(
|
||||||
rlnInstance: RLNInstance,
|
rlnInstance: RLNInstance,
|
||||||
signature: string
|
signature: string
|
||||||
@ -113,6 +174,10 @@ export class RLNContract {
|
|||||||
|
|
||||||
return txRegisterReceipt?.events?.[0];
|
return txRegisterReceipt?.events?.[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public roots(): Uint8Array[] {
|
||||||
|
return this.merkleRootTracker.roots();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type CustomQueryOptions = FetchMembersOptions & {
|
type CustomQueryOptions = FetchMembersOptions & {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user