@waku/rln 0.1.1-8928376 → 0.1.1-ac12f68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -2
- package/bundle/assets/rln_wasm_bg-a503e304.wasm +0 -0
- package/bundle/index.js +27575 -3922
- package/dist/.tsbuildinfo +1 -1
- package/dist/byte_utils.d.ts +7 -0
- package/dist/byte_utils.js +13 -0
- package/dist/byte_utils.js.map +1 -1
- package/dist/codec.d.ts +5 -3
- package/dist/codec.js +8 -4
- package/dist/codec.js.map +1 -1
- package/dist/constants.js +1 -1
- package/dist/create.d.ts +2 -0
- package/dist/create.js +8 -0
- package/dist/create.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -9
- package/dist/index.js.map +1 -1
- package/dist/keystore/index.d.ts +2 -0
- package/dist/keystore/index.js.map +1 -1
- package/dist/keystore/keystore.d.ts +12 -11
- package/dist/keystore/keystore.js +28 -8
- package/dist/keystore/keystore.js.map +1 -1
- package/dist/keystore/types.d.ts +25 -5
- package/dist/message.d.ts +1 -1
- package/dist/message.js +1 -1
- package/dist/metamask.d.ts +2 -0
- package/dist/metamask.js +11 -0
- package/dist/metamask.js.map +1 -0
- package/dist/rln.d.ts +51 -0
- package/dist/rln.js +132 -2
- package/dist/rln.js.map +1 -1
- package/dist/rln_contract.d.ts +18 -13
- package/dist/rln_contract.js +63 -37
- package/dist/rln_contract.js.map +1 -1
- package/package.json +6 -6
- package/src/byte_utils.ts +14 -0
- package/src/codec.ts +10 -5
- package/src/constants.ts +1 -1
- package/src/create.ts +9 -0
- package/src/index.ts +4 -9
- package/src/message.ts +1 -1
- package/src/metamask.ts +16 -0
- package/src/rln.ts +237 -2
- package/src/rln_contract.ts +98 -59
- package/bundle/assets/rln_wasm_bg-6f96f821.wasm +0 -0
package/src/rln_contract.ts
CHANGED
@@ -1,21 +1,30 @@
|
|
1
|
+
import { hexToBytes } from "@waku/utils/bytes";
|
1
2
|
import { ethers } from "ethers";
|
2
3
|
|
4
|
+
import { zeroPadLE } from "./byte_utils.js";
|
3
5
|
import { RLN_REGISTRY_ABI, RLN_STORAGE_ABI } from "./constants.js";
|
4
|
-
import {
|
6
|
+
import type { DecryptedCredentials } from "./keystore/index.js";
|
7
|
+
import { type IdentityCredential, RLNInstance } from "./rln.js";
|
5
8
|
import { MerkleRootTracker } from "./root_tracker.js";
|
6
9
|
|
7
10
|
type Member = {
|
8
|
-
|
9
|
-
index:
|
11
|
+
idCommitment: string;
|
12
|
+
index: ethers.BigNumber;
|
10
13
|
};
|
11
14
|
|
12
|
-
type
|
15
|
+
type Signer = ethers.Signer;
|
13
16
|
|
14
|
-
type
|
15
|
-
|
16
|
-
|
17
|
+
type RLNContractOptions = {
|
18
|
+
signer: Signer;
|
19
|
+
registryAddress: string;
|
17
20
|
};
|
18
21
|
|
22
|
+
type RLNStorageOptions = {
|
23
|
+
storageIndex?: number;
|
24
|
+
};
|
25
|
+
|
26
|
+
type RLNContractInitOptions = RLNContractOptions & RLNStorageOptions;
|
27
|
+
|
19
28
|
type FetchMembersOptions = {
|
20
29
|
fromBlock?: number;
|
21
30
|
fetchRange?: number;
|
@@ -31,15 +40,15 @@ export class RLNContract {
|
|
31
40
|
private storageContract: undefined | ethers.Contract;
|
32
41
|
private _membersFilter: undefined | ethers.EventFilter;
|
33
42
|
|
34
|
-
private _members: Member
|
43
|
+
private _members: Map<number, Member> = new Map();
|
35
44
|
|
36
45
|
public static async init(
|
37
46
|
rlnInstance: RLNInstance,
|
38
|
-
options:
|
47
|
+
options: RLNContractInitOptions
|
39
48
|
): Promise<RLNContract> {
|
40
49
|
const rlnContract = new RLNContract(rlnInstance, options);
|
41
50
|
|
42
|
-
await rlnContract.initStorageContract(options.
|
51
|
+
await rlnContract.initStorageContract(options.signer);
|
43
52
|
await rlnContract.fetchMembers(rlnInstance);
|
44
53
|
rlnContract.subscribeToMembers(rlnInstance);
|
45
54
|
|
@@ -48,42 +57,61 @@ export class RLNContract {
|
|
48
57
|
|
49
58
|
constructor(
|
50
59
|
rlnInstance: RLNInstance,
|
51
|
-
{
|
60
|
+
{ registryAddress, signer }: RLNContractOptions
|
52
61
|
) {
|
53
62
|
const initialRoot = rlnInstance.getMerkleRoot();
|
54
63
|
|
55
64
|
this.registryContract = new ethers.Contract(
|
56
|
-
|
65
|
+
registryAddress,
|
57
66
|
RLN_REGISTRY_ABI,
|
58
|
-
|
67
|
+
signer
|
59
68
|
);
|
60
69
|
this.merkleRootTracker = new MerkleRootTracker(5, initialRoot);
|
61
70
|
}
|
62
71
|
|
63
|
-
private async initStorageContract(
|
64
|
-
|
65
|
-
|
72
|
+
private async initStorageContract(
|
73
|
+
signer: Signer,
|
74
|
+
options: RLNStorageOptions = {}
|
75
|
+
): Promise<void> {
|
76
|
+
const storageIndex = options?.storageIndex
|
77
|
+
? options.storageIndex
|
78
|
+
: await this.registryContract.usingStorageIndex();
|
79
|
+
const storageAddress = await this.registryContract.storages(storageIndex);
|
80
|
+
|
81
|
+
if (!storageAddress || storageAddress === ethers.constants.AddressZero) {
|
82
|
+
throw Error("No RLN Storage initialized on registry contract.");
|
83
|
+
}
|
66
84
|
|
67
|
-
this.storageIndex =
|
85
|
+
this.storageIndex = storageIndex;
|
68
86
|
this.storageContract = new ethers.Contract(
|
69
|
-
|
87
|
+
storageAddress,
|
70
88
|
RLN_STORAGE_ABI,
|
71
|
-
|
89
|
+
signer
|
72
90
|
);
|
73
91
|
this._membersFilter = this.storageContract.filters.MemberRegistered();
|
74
92
|
|
75
93
|
this.deployBlock = await this.storageContract.deployedBlockNumber();
|
76
94
|
}
|
77
95
|
|
96
|
+
public get registry(): ethers.Contract {
|
97
|
+
if (!this.registryContract) {
|
98
|
+
throw Error("Registry contract was not initialized");
|
99
|
+
}
|
100
|
+
return this.registryContract as ethers.Contract;
|
101
|
+
}
|
102
|
+
|
78
103
|
public get contract(): ethers.Contract {
|
79
104
|
if (!this.storageContract) {
|
80
|
-
throw Error("Storage contract was not initialized
|
105
|
+
throw Error("Storage contract was not initialized");
|
81
106
|
}
|
82
107
|
return this.storageContract as ethers.Contract;
|
83
108
|
}
|
84
109
|
|
85
110
|
public get members(): Member[] {
|
86
|
-
|
111
|
+
const sortedMembers = Array.from(this._members.values()).sort(
|
112
|
+
(left, right) => left.index.toNumber() - right.index.toNumber()
|
113
|
+
);
|
114
|
+
return sortedMembers;
|
87
115
|
}
|
88
116
|
|
89
117
|
private get membersFilter(): ethers.EventFilter {
|
@@ -115,13 +143,13 @@ export class RLNContract {
|
|
115
143
|
}
|
116
144
|
|
117
145
|
if (evt.removed) {
|
118
|
-
const index:
|
146
|
+
const index: ethers.BigNumber = evt.args.index;
|
119
147
|
const toRemoveVal = toRemoveTable.get(evt.blockNumber);
|
120
148
|
if (toRemoveVal != undefined) {
|
121
|
-
toRemoveVal.push(index);
|
149
|
+
toRemoveVal.push(index.toNumber());
|
122
150
|
toRemoveTable.set(evt.blockNumber, toRemoveVal);
|
123
151
|
} else {
|
124
|
-
toRemoveTable.set(evt.blockNumber, [index]);
|
152
|
+
toRemoveTable.set(evt.blockNumber, [index.toNumber()]);
|
125
153
|
}
|
126
154
|
} else {
|
127
155
|
let eventsPerBlock = toInsertTable.get(evt.blockNumber);
|
@@ -132,10 +160,10 @@ export class RLNContract {
|
|
132
160
|
eventsPerBlock.push(evt);
|
133
161
|
toInsertTable.set(evt.blockNumber, eventsPerBlock);
|
134
162
|
}
|
135
|
-
|
136
|
-
this.removeMembers(rlnInstance, toRemoveTable);
|
137
|
-
this.insertMembers(rlnInstance, toInsertTable);
|
138
163
|
});
|
164
|
+
|
165
|
+
this.removeMembers(rlnInstance, toRemoveTable);
|
166
|
+
this.insertMembers(rlnInstance, toInsertTable);
|
139
167
|
}
|
140
168
|
|
141
169
|
private insertMembers(
|
@@ -144,18 +172,19 @@ export class RLNContract {
|
|
144
172
|
): void {
|
145
173
|
toInsert.forEach((events: ethers.Event[], blockNumber: number) => {
|
146
174
|
events.forEach((evt) => {
|
147
|
-
|
175
|
+
const _idCommitment = evt?.args?.idCommitment;
|
176
|
+
const index: ethers.BigNumber = evt?.args?.index;
|
177
|
+
|
178
|
+
if (!_idCommitment || !index) {
|
148
179
|
return;
|
149
180
|
}
|
150
181
|
|
151
|
-
const
|
152
|
-
const index = evt.args.index;
|
153
|
-
const idCommitment = ethers.utils.zeroPad(
|
154
|
-
ethers.utils.arrayify(pubkey),
|
155
|
-
32
|
156
|
-
);
|
182
|
+
const idCommitment = zeroPadLE(hexToBytes(_idCommitment?._hex), 32);
|
157
183
|
rlnInstance.insertMember(idCommitment);
|
158
|
-
this.
|
184
|
+
this._members.set(index.toNumber(), {
|
185
|
+
index,
|
186
|
+
idCommitment: _idCommitment?._hex,
|
187
|
+
});
|
159
188
|
});
|
160
189
|
|
161
190
|
const currentRoot = rlnInstance.getMerkleRoot();
|
@@ -170,9 +199,8 @@ export class RLNContract {
|
|
170
199
|
const removeDescending = new Map([...toRemove].sort().reverse());
|
171
200
|
removeDescending.forEach((indexes: number[], blockNumber: number) => {
|
172
201
|
indexes.forEach((index) => {
|
173
|
-
|
174
|
-
|
175
|
-
this.members.splice(idx, 1);
|
202
|
+
if (this._members.has(index)) {
|
203
|
+
this._members.delete(index);
|
176
204
|
}
|
177
205
|
rlnInstance.deleteMember(index);
|
178
206
|
});
|
@@ -183,39 +211,50 @@ export class RLNContract {
|
|
183
211
|
|
184
212
|
public subscribeToMembers(rlnInstance: RLNInstance): void {
|
185
213
|
this.contract.on(this.membersFilter, (_pubkey, _index, event) =>
|
186
|
-
this.processEvents(rlnInstance, event)
|
214
|
+
this.processEvents(rlnInstance, [event])
|
187
215
|
);
|
188
216
|
}
|
189
217
|
|
190
|
-
public async
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
const identityCredential =
|
195
|
-
await rlnInstance.generateSeededIdentityCredential(signature);
|
196
|
-
|
197
|
-
return this.registerWithKey(identityCredential);
|
198
|
-
}
|
199
|
-
|
200
|
-
public async registerWithKey(
|
201
|
-
credential: IdentityCredential
|
202
|
-
): Promise<ethers.Event | undefined> {
|
203
|
-
if (!this.storageIndex) {
|
218
|
+
public async registerWithIdentity(
|
219
|
+
identity: IdentityCredential
|
220
|
+
): Promise<DecryptedCredentials | undefined> {
|
221
|
+
if (this.storageIndex === undefined) {
|
204
222
|
throw Error(
|
205
223
|
"Cannot register credential, no storage contract index found."
|
206
224
|
);
|
207
225
|
}
|
208
226
|
const txRegisterResponse: ethers.ContractTransaction =
|
209
|
-
await this.registryContract
|
227
|
+
await this.registryContract["register(uint16,uint256)"](
|
210
228
|
this.storageIndex,
|
211
|
-
|
212
|
-
{
|
213
|
-
gasLimit: 100000,
|
214
|
-
}
|
229
|
+
identity.IDCommitmentBigInt,
|
230
|
+
{ gasLimit: 100000 }
|
215
231
|
);
|
216
232
|
const txRegisterReceipt = await txRegisterResponse.wait();
|
217
233
|
|
218
|
-
|
234
|
+
// assumption: register(uint16,uint256) emits one event
|
235
|
+
const memberRegistered = txRegisterReceipt?.events?.[0];
|
236
|
+
|
237
|
+
if (!memberRegistered) {
|
238
|
+
return undefined;
|
239
|
+
}
|
240
|
+
|
241
|
+
const decodedData = this.contract.interface.decodeEventLog(
|
242
|
+
"MemberRegistered",
|
243
|
+
memberRegistered.data
|
244
|
+
);
|
245
|
+
|
246
|
+
const network = await this.registryContract.provider.getNetwork();
|
247
|
+
const address = this.registryContract.address;
|
248
|
+
const membershipId = decodedData.index.toNumber();
|
249
|
+
|
250
|
+
return {
|
251
|
+
identity,
|
252
|
+
membership: {
|
253
|
+
address,
|
254
|
+
treeIndex: membershipId,
|
255
|
+
chainId: network.chainId,
|
256
|
+
},
|
257
|
+
};
|
219
258
|
}
|
220
259
|
|
221
260
|
public roots(): Uint8Array[] {
|
Binary file
|