@waku/rln 0.1.5-053bb95.0 → 0.1.5-1d384f2.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 +244 -114
- package/bundle/packages/rln/dist/contract/rln_contract.js +74 -89
- package/bundle/packages/rln/dist/credentials_manager.js +1 -1
- package/bundle/packages/rln/dist/identity.js +0 -8
- package/bundle/packages/rln/dist/keystore/keystore.js +28 -15
- 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 +244 -114
- 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 +1 -1
- 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 -15
- package/dist/keystore/keystore.js.map +1 -1
- package/package.json +1 -1
- package/src/contract/constants.ts +1 -1
- package/src/contract/rln_base_contract.ts +390 -183
- package/src/contract/rln_contract.ts +95 -120
- package/src/credentials_manager.ts +1 -1
- package/src/identity.ts +0 -9
- package/src/keystore/keystore.ts +50 -27
- 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
|
|
@@ -126,7 +126,7 @@ class RLNCredentialsManager {
|
|
126
126
|
options.address ||
|
127
127
|
LINEA_CONTRACT.address;
|
128
128
|
if (address === LINEA_CONTRACT.address) {
|
129
|
-
chainId = LINEA_CONTRACT.chainId;
|
129
|
+
chainId = LINEA_CONTRACT.chainId.toString();
|
130
130
|
log.info(`Using Linea contract with chainId: ${chainId}`);
|
131
131
|
}
|
132
132
|
const signer = options.signer || (await extractMetaMaskSigner());
|
@@ -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,15 +164,15 @@ 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"),
|
@@ -187,6 +186,20 @@ class Keystore {
|
|
187
186
|
return;
|
188
187
|
}
|
189
188
|
}
|
189
|
+
static fromArraylikeToBytes(obj) {
|
190
|
+
if (Array.isArray(obj)) {
|
191
|
+
return new Uint8Array(obj);
|
192
|
+
}
|
193
|
+
const bytes = [];
|
194
|
+
let index = 0;
|
195
|
+
let lastElement = obj[index];
|
196
|
+
while (lastElement !== undefined) {
|
197
|
+
bytes.push(lastElement);
|
198
|
+
index += 1;
|
199
|
+
lastElement = obj[index];
|
200
|
+
}
|
201
|
+
return new Uint8Array(bytes);
|
202
|
+
}
|
190
203
|
// follows nwaku implementation
|
191
204
|
// https://github.com/waku-org/nwaku/blob/f05528d4be3d3c876a8b07f9bb7dfaae8aa8ec6e/waku/waku_keystore/protocol_types.nim#L111
|
192
205
|
static computeMembershipHash(info) {
|
@@ -196,16 +209,16 @@ class Keystore {
|
|
196
209
|
// https://github.com/waku-org/nwaku/blob/f05528d4be3d3c876a8b07f9bb7dfaae8aa8ec6e/waku/waku_keystore/protocol_types.nim#L98
|
197
210
|
static fromIdentityToBytes(options) {
|
198
211
|
return utf8ToBytes(JSON.stringify({
|
199
|
-
membershipContract: {
|
200
|
-
chainId: options.membership.chainId,
|
201
|
-
address: options.membership.address
|
202
|
-
},
|
203
212
|
treeIndex: options.membership.treeIndex,
|
204
213
|
identityCredential: {
|
205
|
-
|
214
|
+
idCommitment: Array.from(options.identity.IDCommitment),
|
206
215
|
idNullifier: Array.from(options.identity.IDNullifier),
|
207
216
|
idSecretHash: Array.from(options.identity.IDSecretHash),
|
208
|
-
|
217
|
+
idTrapdoor: Array.from(options.identity.IDTrapdoor)
|
218
|
+
},
|
219
|
+
membershipContract: {
|
220
|
+
chainId: options.membership.chainId,
|
221
|
+
address: options.membership.address
|
209
222
|
},
|
210
223
|
userMessageLimit: options.membership.rateLimit
|
211
224
|
}));
|
@@ -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;
|