@waku/rln 0.1.5-053bb95.0 → 0.1.5-4adf870.0
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/bundle/_virtual/utils.js +2 -2
- package/bundle/_virtual/utils2.js +2 -2
- package/bundle/packages/rln/dist/contract/constants.js +5 -2
- package/bundle/packages/rln/dist/contract/rln_base_contract.js +246 -116
- package/bundle/packages/rln/dist/contract/rln_contract.js +74 -89
- package/bundle/packages/rln/dist/credentials_manager.js +2 -2
- package/bundle/packages/rln/dist/identity.js +0 -8
- package/bundle/packages/rln/dist/keystore/keystore.js +28 -19
- package/bundle/packages/rln/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/random.js +1 -1
- package/bundle/packages/rln/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/utils.js +2 -2
- package/bundle/packages/rln/node_modules/@noble/hashes/_sha2.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/hmac.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/pbkdf2.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/scrypt.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/sha256.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/sha512.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/utils.js +1 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/contract/constants.d.ts +1 -1
- package/dist/contract/constants.js +1 -1
- package/dist/contract/constants.js.map +1 -1
- package/dist/contract/rln_base_contract.d.ts +30 -22
- package/dist/contract/rln_base_contract.js +246 -116
- package/dist/contract/rln_base_contract.js.map +1 -1
- package/dist/contract/rln_contract.d.ts +4 -24
- package/dist/contract/rln_contract.js +74 -89
- package/dist/contract/rln_contract.js.map +1 -1
- package/dist/credentials_manager.js +2 -2
- package/dist/credentials_manager.js.map +1 -1
- package/dist/identity.d.ts +0 -1
- package/dist/identity.js +0 -8
- package/dist/identity.js.map +1 -1
- package/dist/keystore/keystore.d.ts +1 -0
- package/dist/keystore/keystore.js +28 -19
- package/dist/keystore/keystore.js.map +1 -1
- package/dist/keystore/types.d.ts +1 -1
- package/package.json +1 -1
- package/src/contract/constants.ts +1 -1
- package/src/contract/rln_base_contract.ts +392 -185
- package/src/contract/rln_contract.ts +95 -120
- package/src/credentials_manager.ts +2 -2
- package/src/identity.ts +0 -9
- package/src/keystore/keystore.ts +46 -31
- package/src/keystore/types.ts +1 -1
- package/bundle/packages/rln/dist/contract/errors.js +0 -62
- package/dist/contract/errors.d.ts +0 -30
- package/dist/contract/errors.js +0 -61
- package/dist/contract/errors.js.map +0 -1
- package/src/contract/errors.ts +0 -75
@@ -5,122 +5,107 @@ import { hexToBytes } from '../../../utils/dist/bytes/index.js';
|
|
5
5
|
import { Logger } from '../../../utils/dist/logger/index.js';
|
6
6
|
import { MerkleRootTracker } from '../root_tracker.js';
|
7
7
|
import { zeroPadLE } from '../utils/bytes.js';
|
8
|
-
import { ContractStateError } from './errors.js';
|
9
8
|
import { RLNBaseContract } from './rln_base_contract.js';
|
9
|
+
import { BigNumber } from '../../../../node_modules/@ethersproject/bignumber/lib.esm/bignumber.js';
|
10
10
|
|
11
11
|
const log = new Logger("waku:rln:contract");
|
12
12
|
class RLNContract extends RLNBaseContract {
|
13
13
|
instance;
|
14
14
|
merkleRootTracker;
|
15
|
-
lastSyncedBlock = 0;
|
16
15
|
/**
|
17
16
|
* Asynchronous initializer for RLNContract.
|
18
17
|
* Allows injecting a mocked contract for testing purposes.
|
19
18
|
*/
|
20
19
|
static async init(rlnInstance, options) {
|
21
20
|
const rlnContract = new RLNContract(rlnInstance, options);
|
22
|
-
await rlnContract.syncState();
|
23
21
|
return rlnContract;
|
24
22
|
}
|
25
|
-
/**
|
26
|
-
* Override base contract method to keep Merkle tree in sync
|
27
|
-
* Registers a new membership with the given commitment and rate limit
|
28
|
-
*/
|
29
|
-
async registerMembership(idCommitment, rateLimit = this.getRateLimit()) {
|
30
|
-
await super.registerMembership(idCommitment, rateLimit);
|
31
|
-
await this.syncState();
|
32
|
-
}
|
33
|
-
/**
|
34
|
-
* Override base contract method to keep Merkle tree in sync
|
35
|
-
* Erases an existing membership from the contract
|
36
|
-
*/
|
37
|
-
async eraseMembership(idCommitment, eraseFromMembershipSet = true) {
|
38
|
-
await super.eraseMembership(idCommitment, eraseFromMembershipSet);
|
39
|
-
await this.syncState();
|
40
|
-
}
|
41
|
-
/**
|
42
|
-
* Gets the current Merkle root
|
43
|
-
* Returns the latest valid root or empty array if no roots exist
|
44
|
-
*/
|
45
|
-
async getMerkleRoot() {
|
46
|
-
await this.syncState();
|
47
|
-
const roots = this.merkleRootTracker.roots();
|
48
|
-
return roots.length > 0 ? roots[0] : new Uint8Array();
|
49
|
-
}
|
50
23
|
constructor(rlnInstance, options) {
|
51
24
|
super(options);
|
52
25
|
this.instance = rlnInstance;
|
53
26
|
const initialRoot = rlnInstance.zerokit.getMerkleRoot();
|
54
27
|
this.merkleRootTracker = new MerkleRootTracker(5, initialRoot);
|
55
28
|
}
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
const currentBlock = await this.provider.getBlockNumber();
|
62
|
-
// If we're already synced, just get new members
|
63
|
-
if (this.lastSyncedBlock > 0) {
|
64
|
-
await this.syncNewMembers(this.lastSyncedBlock, currentBlock);
|
65
|
-
this.lastSyncedBlock = currentBlock;
|
29
|
+
processEvents(events) {
|
30
|
+
const toRemoveTable = new Map();
|
31
|
+
const toInsertTable = new Map();
|
32
|
+
events.forEach((evt) => {
|
33
|
+
if (!evt.args) {
|
66
34
|
return;
|
67
35
|
}
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
for (let i = 0; i < nextIndex.toNumber(); i++) {
|
74
|
-
try {
|
75
|
-
this.instance.zerokit.deleteMember(i);
|
36
|
+
if (evt.event === "MembershipErased" ||
|
37
|
+
evt.event === "MembershipExpired") {
|
38
|
+
let index = evt.args.index;
|
39
|
+
if (!index) {
|
40
|
+
return;
|
76
41
|
}
|
77
|
-
|
78
|
-
|
79
|
-
|
42
|
+
if (typeof index === "number" || typeof index === "string") {
|
43
|
+
index = BigNumber.from(index);
|
44
|
+
}
|
45
|
+
else {
|
46
|
+
log.error("Index is not a number or string", {
|
47
|
+
index,
|
48
|
+
event: evt
|
49
|
+
});
|
50
|
+
return;
|
51
|
+
}
|
52
|
+
const toRemoveVal = toRemoveTable.get(evt.blockNumber);
|
53
|
+
if (toRemoveVal != undefined) {
|
54
|
+
toRemoveVal.push(index.toNumber());
|
55
|
+
toRemoveTable.set(evt.blockNumber, toRemoveVal);
|
56
|
+
}
|
57
|
+
else {
|
58
|
+
toRemoveTable.set(evt.blockNumber, [index.toNumber()]);
|
80
59
|
}
|
81
60
|
}
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
61
|
+
else if (evt.event === "MembershipRegistered") {
|
62
|
+
let eventsPerBlock = toInsertTable.get(evt.blockNumber);
|
63
|
+
if (eventsPerBlock == undefined) {
|
64
|
+
eventsPerBlock = [];
|
65
|
+
}
|
66
|
+
eventsPerBlock.push(evt);
|
67
|
+
toInsertTable.set(evt.blockNumber, eventsPerBlock);
|
86
68
|
}
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
this.lastSyncedBlock = currentBlock;
|
91
|
-
log.info(`Synced ${members.length} members to current block ${currentBlock}`);
|
92
|
-
}
|
93
|
-
catch (error) {
|
94
|
-
log.error("Failed to sync state", error);
|
95
|
-
throw new ContractStateError("Failed to sync contract state");
|
96
|
-
}
|
69
|
+
});
|
70
|
+
this.removeMembers(this.instance, toRemoveTable);
|
71
|
+
this.insertMembers(this.instance, toInsertTable);
|
97
72
|
}
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
73
|
+
insertMembers(rlnInstance, toInsert) {
|
74
|
+
toInsert.forEach((events, blockNumber) => {
|
75
|
+
events.forEach((evt) => {
|
76
|
+
if (!evt.args)
|
77
|
+
return;
|
78
|
+
const _idCommitment = evt.args.idCommitment;
|
79
|
+
let index = evt.args.index;
|
80
|
+
if (!_idCommitment || !index) {
|
81
|
+
return;
|
82
|
+
}
|
83
|
+
if (typeof index === "number" || typeof index === "string") {
|
84
|
+
index = BigNumber.from(index);
|
85
|
+
}
|
86
|
+
const idCommitment = zeroPadLE(hexToBytes(_idCommitment), 32);
|
87
|
+
rlnInstance.zerokit.insertMember(idCommitment);
|
88
|
+
const numericIndex = index.toNumber();
|
89
|
+
this._members.set(numericIndex, {
|
90
|
+
index,
|
91
|
+
idCommitment: _idCommitment
|
92
|
+
});
|
93
|
+
});
|
94
|
+
const currentRoot = rlnInstance.zerokit.getMerkleRoot();
|
95
|
+
this.merkleRootTracker.pushRoot(blockNumber, currentRoot);
|
96
|
+
});
|
97
|
+
}
|
98
|
+
removeMembers(rlnInstance, toRemove) {
|
99
|
+
const removeDescending = new Map([...toRemove].reverse());
|
100
|
+
removeDescending.forEach((indexes, blockNumber) => {
|
101
|
+
indexes.forEach((index) => {
|
102
|
+
if (this._members.has(index)) {
|
103
|
+
this._members.delete(index);
|
104
|
+
rlnInstance.zerokit.deleteMember(index);
|
105
|
+
}
|
106
|
+
});
|
107
|
+
this.merkleRootTracker.backFill(blockNumber);
|
108
|
+
});
|
124
109
|
}
|
125
110
|
}
|
126
111
|
|
@@ -132,7 +132,7 @@ class RLNCredentialsManager {
|
|
132
132
|
const signer = options.signer || (await extractMetaMaskSigner());
|
133
133
|
const currentChainId = await signer.getChainId();
|
134
134
|
log.info(`Current chain ID: ${currentChainId}`);
|
135
|
-
if (chainId && chainId !== currentChainId
|
135
|
+
if (chainId && chainId !== currentChainId) {
|
136
136
|
log.error(`Chain ID mismatch: contract=${chainId}, current=${currentChainId}`);
|
137
137
|
throw Error(`Failed to start RLN contract, chain ID of contract is different from current one: contract-${chainId}, current network-${currentChainId}`);
|
138
138
|
}
|
@@ -181,7 +181,7 @@ class RLNCredentialsManager {
|
|
181
181
|
const chainId = credentials.membership.chainId;
|
182
182
|
const network = await this.contract.provider.getNetwork();
|
183
183
|
const currentChainId = network.chainId;
|
184
|
-
if (chainId !== currentChainId
|
184
|
+
if (chainId !== currentChainId) {
|
185
185
|
throw Error(`Failed to verify chain coordinates: credentials chainID=${chainId} is not equal to registryContract chainID=${currentChainId}`);
|
186
186
|
}
|
187
187
|
}
|
@@ -25,14 +25,6 @@ class IdentityCredential {
|
|
25
25
|
const idCommitmentBigInt = buildBigIntFromUint8Array(idCommitment, 32);
|
26
26
|
return new IdentityCredential(idTrapdoor, idNullifier, idSecretHash, idCommitment, idCommitmentBigInt);
|
27
27
|
}
|
28
|
-
toJSON() {
|
29
|
-
return {
|
30
|
-
idTrapdoor: Array.from(this.IDTrapdoor),
|
31
|
-
idNullifier: Array.from(this.IDNullifier),
|
32
|
-
idSecretHash: Array.from(this.IDSecretHash),
|
33
|
-
idCommitment: Array.from(this.IDCommitment)
|
34
|
-
};
|
35
|
-
}
|
36
28
|
}
|
37
29
|
|
38
30
|
export { IdentityCredential };
|
@@ -17,7 +17,6 @@ import { Logger } from '../../../utils/dist/logger/index.js';
|
|
17
17
|
import { sha256 } from '../../../../node_modules/ethereum-cryptography/esm/sha256.js';
|
18
18
|
import { bytesToUtf8 } from '../../../../node_modules/ethereum-cryptography/esm/utils.js';
|
19
19
|
import _ from '../../../../node_modules/lodash/lodash.js';
|
20
|
-
import { IdentityCredential } from '../identity.js';
|
21
20
|
import { buildBigIntFromUint8Array } from '../utils/bytes.js';
|
22
21
|
import { keccak256Checksum, decryptEipKeystore } from './cipher.js';
|
23
22
|
import { isKeystoreValid, isCredentialValid } from './schema_validator.js';
|
@@ -165,20 +164,20 @@ class Keystore {
|
|
165
164
|
try {
|
166
165
|
const str = bytesToUtf8(bytes);
|
167
166
|
const obj = JSON.parse(str);
|
168
|
-
//
|
169
|
-
const { idTrapdoor, idNullifier, idSecretHash, idCommitment } = _.get(obj, "identityCredential", {});
|
170
|
-
const idTrapdoorArray = new Uint8Array(idTrapdoor || []);
|
171
|
-
const idNullifierArray = new Uint8Array(idNullifier || []);
|
172
|
-
const idSecretHashArray = new Uint8Array(idSecretHash || []);
|
173
|
-
const idCommitmentArray = new Uint8Array(idCommitment || []);
|
174
|
-
const idCommitmentBigInt = buildBigIntFromUint8Array(idCommitmentArray);
|
167
|
+
// TODO: add runtime validation of nwaku credentials
|
175
168
|
return {
|
176
|
-
identity:
|
169
|
+
identity: {
|
170
|
+
IDCommitment: Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idCommitment", [])),
|
171
|
+
IDTrapdoor: Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idTrapdoor", [])),
|
172
|
+
IDNullifier: Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idNullifier", [])),
|
173
|
+
IDCommitmentBigInt: buildBigIntFromUint8Array(Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idCommitment", []))),
|
174
|
+
IDSecretHash: Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idSecretHash", []))
|
175
|
+
},
|
177
176
|
membership: {
|
178
177
|
treeIndex: _.get(obj, "treeIndex"),
|
179
178
|
chainId: _.get(obj, "membershipContract.chainId"),
|
180
179
|
address: _.get(obj, "membershipContract.address"),
|
181
|
-
rateLimit: _.get(obj, "
|
180
|
+
rateLimit: _.get(obj, "membershipContract.rateLimit")
|
182
181
|
}
|
183
182
|
};
|
184
183
|
}
|
@@ -187,6 +186,17 @@ class Keystore {
|
|
187
186
|
return;
|
188
187
|
}
|
189
188
|
}
|
189
|
+
static fromArraylikeToBytes(obj) {
|
190
|
+
const bytes = [];
|
191
|
+
let index = 0;
|
192
|
+
let lastElement = obj[index];
|
193
|
+
while (lastElement !== undefined) {
|
194
|
+
bytes.push(lastElement);
|
195
|
+
index += 1;
|
196
|
+
lastElement = obj[index];
|
197
|
+
}
|
198
|
+
return new Uint8Array(bytes);
|
199
|
+
}
|
190
200
|
// follows nwaku implementation
|
191
201
|
// https://github.com/waku-org/nwaku/blob/f05528d4be3d3c876a8b07f9bb7dfaae8aa8ec6e/waku/waku_keystore/protocol_types.nim#L111
|
192
202
|
static computeMembershipHash(info) {
|
@@ -196,18 +206,17 @@ class Keystore {
|
|
196
206
|
// https://github.com/waku-org/nwaku/blob/f05528d4be3d3c876a8b07f9bb7dfaae8aa8ec6e/waku/waku_keystore/protocol_types.nim#L98
|
197
207
|
static fromIdentityToBytes(options) {
|
198
208
|
return utf8ToBytes(JSON.stringify({
|
199
|
-
membershipContract: {
|
200
|
-
chainId: options.membership.chainId,
|
201
|
-
address: options.membership.address
|
202
|
-
},
|
203
209
|
treeIndex: options.membership.treeIndex,
|
204
210
|
identityCredential: {
|
205
|
-
|
206
|
-
idNullifier:
|
207
|
-
idSecretHash:
|
208
|
-
|
211
|
+
idCommitment: options.identity.IDCommitment,
|
212
|
+
idNullifier: options.identity.IDNullifier,
|
213
|
+
idSecretHash: options.identity.IDSecretHash,
|
214
|
+
idTrapdoor: options.identity.IDTrapdoor
|
209
215
|
},
|
210
|
-
|
216
|
+
membershipContract: {
|
217
|
+
chainId: options.membership.chainId,
|
218
|
+
address: options.membership.address
|
219
|
+
}
|
211
220
|
}));
|
212
221
|
}
|
213
222
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { __exports as random } from '../../../../../../../_virtual/random.js';
|
2
2
|
import '../../../../@noble/hashes/utils.js';
|
3
|
-
import { __exports as utils } from '../../../../../../../_virtual/
|
3
|
+
import { __exports as utils } from '../../../../../../../_virtual/utils.js';
|
4
4
|
|
5
5
|
Object.defineProperty(random, "__esModule", { value: true });
|
6
6
|
random.getRandomBytes = random.getRandomBytesSync = void 0;
|
@@ -1,10 +1,10 @@
|
|
1
1
|
import { commonjsGlobal } from '../../../../../../../_virtual/_commonjsHelpers.js';
|
2
2
|
import { commonjsRequire } from '../../../../../../../_virtual/_commonjs-dynamic-modules.js';
|
3
|
-
import { __module as utils } from '../../../../../../../_virtual/
|
3
|
+
import { __module as utils } from '../../../../../../../_virtual/utils2.js';
|
4
4
|
import '../../../../@noble/hashes/_assert.js';
|
5
5
|
import '../../../../@noble/hashes/utils.js';
|
6
6
|
import { __exports as _assert } from '../../../../../../../_virtual/_assert.js';
|
7
|
-
import { __exports as utils$1 } from '../../../../../../../_virtual/
|
7
|
+
import { __exports as utils$1 } from '../../../../../../../_virtual/utils.js';
|
8
8
|
|
9
9
|
utils.exports;
|
10
10
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { __exports as _sha2 } from '../../../../../_virtual/_sha2.js';
|
2
2
|
import './_assert.js';
|
3
3
|
import './utils.js';
|
4
|
-
import { __exports as utils } from '../../../../../_virtual/
|
4
|
+
import { __exports as utils } from '../../../../../_virtual/utils.js';
|
5
5
|
import { __exports as _assert } from '../../../../../_virtual/_assert.js';
|
6
6
|
|
7
7
|
Object.defineProperty(_sha2, "__esModule", { value: true });
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { __exports as hmac } from '../../../../../_virtual/hmac.js';
|
2
2
|
import './_assert.js';
|
3
3
|
import './utils.js';
|
4
|
-
import { __exports as utils } from '../../../../../_virtual/
|
4
|
+
import { __exports as utils } from '../../../../../_virtual/utils.js';
|
5
5
|
import { __exports as _assert } from '../../../../../_virtual/_assert.js';
|
6
6
|
|
7
7
|
(function (exports) {
|
@@ -2,7 +2,7 @@ import { __exports as pbkdf2$1 } from '../../../../../_virtual/pbkdf22.js';
|
|
2
2
|
import './_assert.js';
|
3
3
|
import './hmac.js';
|
4
4
|
import './utils.js';
|
5
|
-
import { __exports as utils } from '../../../../../_virtual/
|
5
|
+
import { __exports as utils } from '../../../../../_virtual/utils.js';
|
6
6
|
import { __exports as _assert } from '../../../../../_virtual/_assert.js';
|
7
7
|
import { __exports as hmac } from '../../../../../_virtual/hmac.js';
|
8
8
|
|
@@ -3,7 +3,7 @@ import './_assert.js';
|
|
3
3
|
import './sha256.js';
|
4
4
|
import './pbkdf2.js';
|
5
5
|
import './utils.js';
|
6
|
-
import { __exports as utils } from '../../../../../_virtual/
|
6
|
+
import { __exports as utils } from '../../../../../_virtual/utils.js';
|
7
7
|
import { __exports as _assert } from '../../../../../_virtual/_assert.js';
|
8
8
|
import { __exports as pbkdf2 } from '../../../../../_virtual/pbkdf22.js';
|
9
9
|
import { __exports as sha256 } from '../../../../../_virtual/sha2562.js';
|
@@ -2,7 +2,7 @@ import { __exports as sha256 } from '../../../../../_virtual/sha2562.js';
|
|
2
2
|
import './_sha2.js';
|
3
3
|
import './utils.js';
|
4
4
|
import { __exports as _sha2 } from '../../../../../_virtual/_sha2.js';
|
5
|
-
import { __exports as utils } from '../../../../../_virtual/
|
5
|
+
import { __exports as utils } from '../../../../../_virtual/utils.js';
|
6
6
|
|
7
7
|
Object.defineProperty(sha256, "__esModule", { value: true });
|
8
8
|
sha256.sha224 = sha256.sha256 = void 0;
|
@@ -4,7 +4,7 @@ import './_u64.js';
|
|
4
4
|
import './utils.js';
|
5
5
|
import { __exports as _u64 } from '../../../../../_virtual/_u64.js';
|
6
6
|
import { __exports as _sha2 } from '../../../../../_virtual/_sha2.js';
|
7
|
-
import { __exports as utils } from '../../../../../_virtual/
|
7
|
+
import { __exports as utils } from '../../../../../_virtual/utils.js';
|
8
8
|
|
9
9
|
Object.defineProperty(sha512, "__esModule", { value: true });
|
10
10
|
sha512.sha384 = sha512.sha512_256 = sha512.sha512_224 = sha512.sha512 = sha512.SHA512 = void 0;
|