@waku/rln 0.1.1 → 0.1.2-e1679b6
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 +58446 -12248
- package/dist/.tsbuildinfo +1 -1
- package/dist/byte_utils.d.ts +13 -0
- package/dist/byte_utils.js +22 -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.d.ts +2 -2
- package/dist/constants.js +62 -9
- package/dist/constants.js.map +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 +5 -3
- package/dist/index.js +5 -10
- package/dist/index.js.map +1 -1
- package/dist/keystore/cipher.d.ts +4 -0
- package/dist/keystore/cipher.js +28 -0
- package/dist/keystore/cipher.js.map +1 -0
- package/dist/keystore/credential_validation_generated.d.ts +8 -0
- package/dist/keystore/credential_validation_generated.js +121 -0
- package/dist/keystore/credential_validation_generated.js.map +1 -0
- package/dist/keystore/index.d.ts +4 -0
- package/dist/keystore/index.js +3 -0
- package/dist/keystore/index.js.map +1 -0
- package/dist/keystore/keystore.d.ts +50 -0
- package/dist/keystore/keystore.js +202 -0
- package/dist/keystore/keystore.js.map +1 -0
- package/dist/keystore/keystore_validation_generated.d.ts +8 -0
- package/dist/keystore/keystore_validation_generated.js +75 -0
- package/dist/keystore/keystore_validation_generated.js.map +1 -0
- package/dist/keystore/schema_validator.d.ts +2 -0
- package/dist/keystore/schema_validator.js +18 -0
- package/dist/keystore/schema_validator.js.map +1 -0
- package/dist/keystore/types.d.ts +29 -0
- package/dist/keystore/types.js +2 -0
- package/dist/keystore/types.js.map +1 -0
- package/dist/message.d.ts +2 -1
- package/dist/message.js +4 -1
- package/dist/message.js.map +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 +134 -12
- package/dist/rln.js.map +1 -1
- package/dist/rln_contract.d.ts +25 -14
- package/dist/rln_contract.js +80 -34
- package/dist/rln_contract.js.map +1 -1
- package/package.json +23 -8
- package/src/byte_utils.ts +24 -0
- package/src/codec.ts +10 -5
- package/src/constants.ts +63 -9
- package/src/create.ts +9 -0
- package/src/index.ts +13 -11
- package/src/message.ts +5 -1
- package/src/metamask.ts +16 -0
- package/src/rln.ts +240 -14
- package/src/rln_contract.ts +135 -53
- package/bundle/assets/rln_wasm_bg-6f96f821.wasm +0 -0
package/src/rln_contract.ts
CHANGED
@@ -1,19 +1,30 @@
|
|
1
|
+
import { hexToBytes } from "@waku/utils/bytes";
|
1
2
|
import { ethers } from "ethers";
|
2
3
|
|
3
|
-
import {
|
4
|
-
import {
|
5
|
-
import {
|
4
|
+
import { zeroPadLE } from "./byte_utils.js";
|
5
|
+
import { RLN_REGISTRY_ABI, RLN_STORAGE_ABI } from "./constants.js";
|
6
|
+
import type { DecryptedCredentials } from "./keystore/index.js";
|
7
|
+
import { type IdentityCredential, RLNInstance } from "./rln.js";
|
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
|
13
|
-
|
14
|
-
|
15
|
+
type Signer = ethers.Signer;
|
16
|
+
|
17
|
+
type RLNContractOptions = {
|
18
|
+
signer: Signer;
|
19
|
+
registryAddress: string;
|
20
|
+
};
|
21
|
+
|
22
|
+
type RLNStorageOptions = {
|
23
|
+
storageIndex?: number;
|
15
24
|
};
|
16
25
|
|
26
|
+
type RLNContractInitOptions = RLNContractOptions & RLNStorageOptions;
|
27
|
+
|
17
28
|
type FetchMembersOptions = {
|
18
29
|
fromBlock?: number;
|
19
30
|
fetchRange?: number;
|
@@ -21,18 +32,23 @@ type FetchMembersOptions = {
|
|
21
32
|
};
|
22
33
|
|
23
34
|
export class RLNContract {
|
24
|
-
private
|
25
|
-
private membersFilter: ethers.EventFilter;
|
35
|
+
private registryContract: ethers.Contract;
|
26
36
|
private merkleRootTracker: MerkleRootTracker;
|
27
37
|
|
28
|
-
private
|
38
|
+
private deployBlock: undefined | number;
|
39
|
+
private storageIndex: undefined | number;
|
40
|
+
private storageContract: undefined | ethers.Contract;
|
41
|
+
private _membersFilter: undefined | ethers.EventFilter;
|
42
|
+
|
43
|
+
private _members: Map<number, Member> = new Map();
|
29
44
|
|
30
45
|
public static async init(
|
31
46
|
rlnInstance: RLNInstance,
|
32
|
-
options:
|
47
|
+
options: RLNContractInitOptions
|
33
48
|
): Promise<RLNContract> {
|
34
49
|
const rlnContract = new RLNContract(rlnInstance, options);
|
35
50
|
|
51
|
+
await rlnContract.initStorageContract(options.signer);
|
36
52
|
await rlnContract.fetchMembers(rlnInstance);
|
37
53
|
rlnContract.subscribeToMembers(rlnInstance);
|
38
54
|
|
@@ -41,21 +57,68 @@ export class RLNContract {
|
|
41
57
|
|
42
58
|
constructor(
|
43
59
|
rlnInstance: RLNInstance,
|
44
|
-
{
|
60
|
+
{ registryAddress, signer }: RLNContractOptions
|
45
61
|
) {
|
46
62
|
const initialRoot = rlnInstance.getMerkleRoot();
|
47
63
|
|
48
|
-
this.
|
64
|
+
this.registryContract = new ethers.Contract(
|
65
|
+
registryAddress,
|
66
|
+
RLN_REGISTRY_ABI,
|
67
|
+
signer
|
68
|
+
);
|
49
69
|
this.merkleRootTracker = new MerkleRootTracker(5, initialRoot);
|
50
|
-
|
70
|
+
}
|
71
|
+
|
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
|
+
}
|
84
|
+
|
85
|
+
this.storageIndex = storageIndex;
|
86
|
+
this.storageContract = new ethers.Contract(
|
87
|
+
storageAddress,
|
88
|
+
RLN_STORAGE_ABI,
|
89
|
+
signer
|
90
|
+
);
|
91
|
+
this._membersFilter = this.storageContract.filters.MemberRegistered();
|
92
|
+
|
93
|
+
this.deployBlock = await this.storageContract.deployedBlockNumber();
|
94
|
+
}
|
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;
|
51
101
|
}
|
52
102
|
|
53
103
|
public get contract(): ethers.Contract {
|
54
|
-
|
104
|
+
if (!this.storageContract) {
|
105
|
+
throw Error("Storage contract was not initialized");
|
106
|
+
}
|
107
|
+
return this.storageContract as ethers.Contract;
|
55
108
|
}
|
56
109
|
|
57
110
|
public get members(): Member[] {
|
58
|
-
|
111
|
+
const sortedMembers = Array.from(this._members.values()).sort(
|
112
|
+
(left, right) => left.index.toNumber() - right.index.toNumber()
|
113
|
+
);
|
114
|
+
return sortedMembers;
|
115
|
+
}
|
116
|
+
|
117
|
+
private get membersFilter(): ethers.EventFilter {
|
118
|
+
if (!this._membersFilter) {
|
119
|
+
throw Error("Members filter was not initialized.");
|
120
|
+
}
|
121
|
+
return this._membersFilter as ethers.EventFilter;
|
59
122
|
}
|
60
123
|
|
61
124
|
public async fetchMembers(
|
@@ -63,6 +126,7 @@ export class RLNContract {
|
|
63
126
|
options: FetchMembersOptions = {}
|
64
127
|
): Promise<void> {
|
65
128
|
const registeredMemberEvents = await queryFilter(this.contract, {
|
129
|
+
fromBlock: this.deployBlock,
|
66
130
|
...options,
|
67
131
|
membersFilter: this.membersFilter,
|
68
132
|
});
|
@@ -79,13 +143,13 @@ export class RLNContract {
|
|
79
143
|
}
|
80
144
|
|
81
145
|
if (evt.removed) {
|
82
|
-
const index:
|
146
|
+
const index: ethers.BigNumber = evt.args.index;
|
83
147
|
const toRemoveVal = toRemoveTable.get(evt.blockNumber);
|
84
148
|
if (toRemoveVal != undefined) {
|
85
|
-
toRemoveVal.push(index);
|
149
|
+
toRemoveVal.push(index.toNumber());
|
86
150
|
toRemoveTable.set(evt.blockNumber, toRemoveVal);
|
87
151
|
} else {
|
88
|
-
toRemoveTable.set(evt.blockNumber, [index]);
|
152
|
+
toRemoveTable.set(evt.blockNumber, [index.toNumber()]);
|
89
153
|
}
|
90
154
|
} else {
|
91
155
|
let eventsPerBlock = toInsertTable.get(evt.blockNumber);
|
@@ -96,10 +160,10 @@ export class RLNContract {
|
|
96
160
|
eventsPerBlock.push(evt);
|
97
161
|
toInsertTable.set(evt.blockNumber, eventsPerBlock);
|
98
162
|
}
|
99
|
-
|
100
|
-
this.removeMembers(rlnInstance, toRemoveTable);
|
101
|
-
this.insertMembers(rlnInstance, toInsertTable);
|
102
163
|
});
|
164
|
+
|
165
|
+
this.removeMembers(rlnInstance, toRemoveTable);
|
166
|
+
this.insertMembers(rlnInstance, toInsertTable);
|
103
167
|
}
|
104
168
|
|
105
169
|
private insertMembers(
|
@@ -108,18 +172,19 @@ export class RLNContract {
|
|
108
172
|
): void {
|
109
173
|
toInsert.forEach((events: ethers.Event[], blockNumber: number) => {
|
110
174
|
events.forEach((evt) => {
|
111
|
-
|
175
|
+
const _idCommitment = evt?.args?.idCommitment;
|
176
|
+
const index: ethers.BigNumber = evt?.args?.index;
|
177
|
+
|
178
|
+
if (!_idCommitment || !index) {
|
112
179
|
return;
|
113
180
|
}
|
114
181
|
|
115
|
-
const
|
116
|
-
const index = evt.args.index;
|
117
|
-
const idCommitment = ethers.utils.zeroPad(
|
118
|
-
ethers.utils.arrayify(pubkey),
|
119
|
-
32
|
120
|
-
);
|
182
|
+
const idCommitment = zeroPadLE(hexToBytes(_idCommitment?._hex), 32);
|
121
183
|
rlnInstance.insertMember(idCommitment);
|
122
|
-
this.
|
184
|
+
this._members.set(index.toNumber(), {
|
185
|
+
index,
|
186
|
+
idCommitment: _idCommitment?._hex,
|
187
|
+
});
|
123
188
|
});
|
124
189
|
|
125
190
|
const currentRoot = rlnInstance.getMerkleRoot();
|
@@ -134,9 +199,8 @@ export class RLNContract {
|
|
134
199
|
const removeDescending = new Map([...toRemove].sort().reverse());
|
135
200
|
removeDescending.forEach((indexes: number[], blockNumber: number) => {
|
136
201
|
indexes.forEach((index) => {
|
137
|
-
|
138
|
-
|
139
|
-
this.members.splice(idx, 1);
|
202
|
+
if (this._members.has(index)) {
|
203
|
+
this._members.delete(index);
|
140
204
|
}
|
141
205
|
rlnInstance.deleteMember(index);
|
142
206
|
});
|
@@ -147,32 +211,50 @@ export class RLNContract {
|
|
147
211
|
|
148
212
|
public subscribeToMembers(rlnInstance: RLNInstance): void {
|
149
213
|
this.contract.on(this.membersFilter, (_pubkey, _index, event) =>
|
150
|
-
this.processEvents(rlnInstance, event)
|
214
|
+
this.processEvents(rlnInstance, [event])
|
151
215
|
);
|
152
216
|
}
|
153
217
|
|
154
|
-
public async
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
218
|
+
public async registerWithIdentity(
|
219
|
+
identity: IdentityCredential
|
220
|
+
): Promise<DecryptedCredentials | undefined> {
|
221
|
+
if (this.storageIndex === undefined) {
|
222
|
+
throw Error(
|
223
|
+
"Cannot register credential, no storage contract index found."
|
224
|
+
);
|
225
|
+
}
|
226
|
+
const txRegisterResponse: ethers.ContractTransaction =
|
227
|
+
await this.registryContract["register(uint16,uint256)"](
|
228
|
+
this.storageIndex,
|
229
|
+
identity.IDCommitmentBigInt,
|
230
|
+
{ gasLimit: 100000 }
|
231
|
+
);
|
232
|
+
const txRegisterReceipt = await txRegisterResponse.wait();
|
160
233
|
|
161
|
-
|
162
|
-
|
234
|
+
// assumption: register(uint16,uint256) emits one event
|
235
|
+
const memberRegistered = txRegisterReceipt?.events?.[0];
|
163
236
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
const depositValue = await this.contract.MEMBERSHIP_DEPOSIT();
|
237
|
+
if (!memberRegistered) {
|
238
|
+
return undefined;
|
239
|
+
}
|
168
240
|
|
169
|
-
const
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
const txRegisterReceipt = await txRegisterResponse.wait();
|
241
|
+
const decodedData = this.contract.interface.decodeEventLog(
|
242
|
+
"MemberRegistered",
|
243
|
+
memberRegistered.data
|
244
|
+
);
|
174
245
|
|
175
|
-
|
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
|
+
};
|
176
258
|
}
|
177
259
|
|
178
260
|
public roots(): Uint8Array[] {
|
Binary file
|