@waku/rln 0.1.6-b133417.0 → 0.1.6-b4748fd.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/packages/rln/dist/contract/rln_base_contract.js +32 -8
- package/bundle/packages/rln/dist/contract/rln_contract.js +2 -2
- package/bundle/packages/rln/dist/credentials_manager.js +11 -17
- package/bundle/packages/rln/dist/identity.js +0 -5
- package/bundle/packages/rln/dist/keystore/keystore.js +11 -18
- package/bundle/packages/rln/dist/proof.js +2 -2
- package/bundle/packages/rln/dist/utils/bytes.js +61 -108
- package/bundle/packages/rln/dist/utils/hash.js +3 -3
- package/bundle/packages/rln/dist/zerokit.js +17 -17
- package/dist/.tsbuildinfo +1 -1
- package/dist/contract/rln_base_contract.d.ts +6 -0
- package/dist/contract/rln_base_contract.js +32 -8
- package/dist/contract/rln_base_contract.js.map +1 -1
- package/dist/contract/rln_contract.js +2 -2
- package/dist/contract/rln_contract.js.map +1 -1
- package/dist/credentials_manager.d.ts +0 -4
- package/dist/credentials_manager.js +11 -18
- package/dist/credentials_manager.js.map +1 -1
- package/dist/identity.d.ts +0 -1
- package/dist/identity.js +0 -4
- package/dist/identity.js.map +1 -1
- package/dist/keystore/keystore.js +11 -18
- package/dist/keystore/keystore.js.map +1 -1
- package/dist/proof.js +2 -2
- package/dist/proof.js.map +1 -1
- package/dist/utils/bytes.d.ts +16 -42
- package/dist/utils/bytes.js +60 -107
- package/dist/utils/bytes.js.map +1 -1
- package/dist/utils/hash.js +5 -5
- package/dist/utils/hash.js.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/zerokit.js +17 -17
- package/dist/zerokit.js.map +1 -1
- package/package.json +1 -1
- package/src/contract/rln_base_contract.ts +55 -17
- package/src/contract/rln_contract.ts +2 -5
- package/src/credentials_manager.ts +15 -31
- package/src/identity.ts +1 -7
- package/src/keystore/keystore.ts +11 -25
- package/src/proof.ts +2 -2
- package/src/utils/bytes.ts +67 -117
- package/src/utils/hash.ts +5 -15
- package/src/utils/index.ts +6 -1
- package/src/zerokit.ts +22 -30
@@ -13,9 +13,9 @@ import '../../../../node_modules/multiformats/dist/src/bases/base8.js';
|
|
13
13
|
import '../../../../node_modules/multiformats/dist/src/bases/identity.js';
|
14
14
|
import '../../../../node_modules/multiformats/dist/src/codecs/json.js';
|
15
15
|
import { Logger } from '../../../utils/dist/logger/index.js';
|
16
|
-
import {
|
16
|
+
import { buildBigIntFromUint8ArrayBE } from '../utils/bytes.js';
|
17
17
|
import { RLN_ABI } from './abi.js';
|
18
|
-
import { DEFAULT_RATE_LIMIT, RATE_LIMIT_PARAMS } from './constants.js';
|
18
|
+
import { DEFAULT_Q, DEFAULT_RATE_LIMIT, RATE_LIMIT_PARAMS } from './constants.js';
|
19
19
|
import { MembershipState } from './types.js';
|
20
20
|
import { Contract } from '../../../../node_modules/@ethersproject/contracts/lib.esm/index.js';
|
21
21
|
import { BigNumber } from '../../../../node_modules/@ethersproject/bignumber/lib.esm/bignumber.js';
|
@@ -27,6 +27,11 @@ class RLNBaseContract {
|
|
27
27
|
rateLimit;
|
28
28
|
minRateLimit;
|
29
29
|
maxRateLimit;
|
30
|
+
/**
|
31
|
+
* Default Q value for the RLN contract.
|
32
|
+
* @see https://github.com/waku-org/waku-rlnv2-contract/blob/b7e9a9b1bc69256a2a3076c1f099b50ce84e7eff/src/WakuRlnV2.sol#L25
|
33
|
+
*/
|
34
|
+
idCommitmentBigIntLimit = DEFAULT_Q;
|
30
35
|
_members = new Map();
|
31
36
|
_membersFilter;
|
32
37
|
_membershipErasedFilter;
|
@@ -65,12 +70,14 @@ class RLNBaseContract {
|
|
65
70
|
*/
|
66
71
|
static async create(options) {
|
67
72
|
const instance = new RLNBaseContract(options);
|
68
|
-
const [min, max] = await Promise.all([
|
73
|
+
const [min, max, idCommitmentBigIntLimit] = await Promise.all([
|
69
74
|
instance.contract.minMembershipRateLimit(),
|
70
|
-
instance.contract.maxMembershipRateLimit()
|
75
|
+
instance.contract.maxMembershipRateLimit(),
|
76
|
+
instance.contract.Q()
|
71
77
|
]);
|
72
78
|
instance.minRateLimit = BigNumber.from(min).toNumber();
|
73
79
|
instance.maxRateLimit = BigNumber.from(max).toNumber();
|
80
|
+
instance.idCommitmentBigIntLimit = BigInt(idCommitmentBigIntLimit.toString());
|
74
81
|
instance.validateRateLimit(instance.rateLimit);
|
75
82
|
return instance;
|
76
83
|
}
|
@@ -338,11 +345,28 @@ class RLNBaseContract {
|
|
338
345
|
log.error(`Error in withdraw: ${error.message}`);
|
339
346
|
}
|
340
347
|
}
|
348
|
+
getIdCommitmentBigInt(bytes) {
|
349
|
+
let idCommitmentBigIntBE = buildBigIntFromUint8ArrayBE(bytes);
|
350
|
+
log.info("1");
|
351
|
+
if (!this.contract) {
|
352
|
+
throw Error("RLN contract is not initialized");
|
353
|
+
}
|
354
|
+
const idCommitmentBigIntLimit = this.contract.idCommitmentBigIntLimit;
|
355
|
+
log.info("idCommitmentBigIntBE: ", idCommitmentBigIntBE);
|
356
|
+
log.info("idCommitmentBigIntLimit: ", idCommitmentBigIntLimit);
|
357
|
+
log.info("idCommitmentBigIntBE >= idCommitmentBigIntLimit: ", idCommitmentBigIntBE >= idCommitmentBigIntLimit);
|
358
|
+
if (idCommitmentBigIntBE >= idCommitmentBigIntLimit) {
|
359
|
+
log.warn(`ID commitment is greater than Q, reducing it by Q(idCommitmentBigIntLimit): ${idCommitmentBigIntBE} % ${idCommitmentBigIntLimit}`);
|
360
|
+
idCommitmentBigIntBE = idCommitmentBigIntBE % idCommitmentBigIntLimit;
|
361
|
+
}
|
362
|
+
return idCommitmentBigIntBE;
|
363
|
+
}
|
341
364
|
async registerWithIdentity(identity) {
|
342
365
|
try {
|
343
366
|
log.info(`Registering identity with rate limit: ${this.rateLimit} messages/epoch`);
|
367
|
+
const idCommitmentBigInt = this.getIdCommitmentBigInt(identity.IDCommitment);
|
344
368
|
// Check if the ID commitment is already registered
|
345
|
-
const existingIndex = await this.getMemberIndex(
|
369
|
+
const existingIndex = await this.getMemberIndex(idCommitmentBigInt);
|
346
370
|
if (existingIndex) {
|
347
371
|
throw new Error(`ID commitment is already registered with index ${existingIndex}`);
|
348
372
|
}
|
@@ -351,9 +375,9 @@ class RLNBaseContract {
|
|
351
375
|
if (remainingRateLimit < this.rateLimit) {
|
352
376
|
throw new Error(`Not enough remaining rate limit. Requested: ${this.rateLimit}, Available: ${remainingRateLimit}`);
|
353
377
|
}
|
354
|
-
const estimatedGas = await this.contract.estimateGas.register(
|
378
|
+
const estimatedGas = await this.contract.estimateGas.register(idCommitmentBigInt, this.rateLimit, []);
|
355
379
|
const gasLimit = estimatedGas.add(10000);
|
356
|
-
const txRegisterResponse = await this.contract.register(
|
380
|
+
const txRegisterResponse = await this.contract.register(idCommitmentBigInt, this.rateLimit, [], {
|
357
381
|
gasLimit
|
358
382
|
});
|
359
383
|
const txRegisterReceipt = await txRegisterResponse.wait();
|
@@ -417,7 +441,7 @@ class RLNBaseContract {
|
|
417
441
|
async registerWithPermitAndErase(identity, permit, idCommitmentsToErase) {
|
418
442
|
try {
|
419
443
|
log.info(`Registering identity with permit and rate limit: ${this.rateLimit} messages/epoch`);
|
420
|
-
const txRegisterResponse = await this.contract.registerWithPermit(permit.owner, permit.deadline, permit.v, permit.r, permit.s,
|
444
|
+
const txRegisterResponse = await this.contract.registerWithPermit(permit.owner, permit.deadline, permit.v, permit.r, permit.s, this.getIdCommitmentBigInt(identity.IDCommitment), this.rateLimit, idCommitmentsToErase.map((id) => BigNumber.from(id)));
|
421
445
|
const txRegisterReceipt = await txRegisterResponse.wait();
|
422
446
|
const memberRegistered = txRegisterReceipt.events?.find((event) => event.event === "MembershipRegistered");
|
423
447
|
if (!memberRegistered || !memberRegistered.args) {
|
@@ -4,7 +4,7 @@ import '../../../interfaces/dist/health_indicator.js';
|
|
4
4
|
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
|
-
import {
|
7
|
+
import { zeroPadLE } from '../utils/bytes.js';
|
8
8
|
import { RLNBaseContract } from './rln_base_contract.js';
|
9
9
|
import { BigNumber } from '../../../../node_modules/@ethersproject/bignumber/lib.esm/bignumber.js';
|
10
10
|
|
@@ -83,7 +83,7 @@ class RLNContract extends RLNBaseContract {
|
|
83
83
|
if (typeof index === "number" || typeof index === "string") {
|
84
84
|
index = BigNumber.from(index);
|
85
85
|
}
|
86
|
-
const idCommitment =
|
86
|
+
const idCommitment = zeroPadLE(hexToBytes(_idCommitment), 32);
|
87
87
|
rlnInstance.zerokit.insertMember(idCommitment);
|
88
88
|
const numericIndex = index.toNumber();
|
89
89
|
this._members.set(numericIndex, {
|
@@ -15,12 +15,12 @@ import '../../../node_modules/multiformats/dist/src/bases/base8.js';
|
|
15
15
|
import '../../../node_modules/multiformats/dist/src/bases/identity.js';
|
16
16
|
import '../../../node_modules/multiformats/dist/src/codecs/json.js';
|
17
17
|
import { Logger } from '../../utils/dist/logger/index.js';
|
18
|
-
import { LINEA_CONTRACT
|
18
|
+
import { LINEA_CONTRACT } from './contract/constants.js';
|
19
19
|
import { RLNBaseContract } from './contract/rln_base_contract.js';
|
20
20
|
import { IdentityCredential } from './identity.js';
|
21
21
|
import { Keystore } from './keystore/keystore.js';
|
22
|
-
import { BytesUtils } from './utils/bytes.js';
|
23
22
|
import { extractMetaMaskSigner } from './utils/metamask.js';
|
23
|
+
import { switchEndianness } from './utils/bytes.js';
|
24
24
|
import './utils/epoch.js';
|
25
25
|
|
26
26
|
const log = new Logger("waku:credentials");
|
@@ -202,21 +202,15 @@ class RLNCredentialsManager {
|
|
202
202
|
const idNullifierBE = hmac(sha256, seedBytes, encoder.encode("IDNullifier"));
|
203
203
|
const combinedBytes = new Uint8Array([...idTrapdoorBE, ...idNullifierBE]);
|
204
204
|
const idSecretHashBE = sha256(combinedBytes);
|
205
|
-
const
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
const nBE = BytesUtils.buildBigIntFromUint8ArrayBE(bytesBE);
|
215
|
-
if (nBE >= limit) {
|
216
|
-
log.warn(`ID commitment is greater than Q, reducing it by Q: ${nBE} % ${limit}`);
|
217
|
-
return BytesUtils.bigIntToUint8Array32BE(nBE % limit);
|
218
|
-
}
|
219
|
-
return bytesBE;
|
205
|
+
const idCommitmentBE = sha256(idSecretHashBE);
|
206
|
+
// All hashing functions return big-endian bytes
|
207
|
+
// We need to switch to little-endian for the identity credential
|
208
|
+
const idTrapdoorLE = switchEndianness(idTrapdoorBE);
|
209
|
+
const idNullifierLE = switchEndianness(idNullifierBE);
|
210
|
+
const idSecretHashLE = switchEndianness(idSecretHashBE);
|
211
|
+
const idCommitmentLE = switchEndianness(idCommitmentBE);
|
212
|
+
log.info("Successfully generated identity credential");
|
213
|
+
return new IdentityCredential(idTrapdoorLE, idNullifierLE, idSecretHashLE, idCommitmentLE);
|
220
214
|
}
|
221
215
|
}
|
222
216
|
|
@@ -1,11 +1,8 @@
|
|
1
|
-
import { BytesUtils } from './utils/bytes.js';
|
2
|
-
|
3
1
|
class IdentityCredential {
|
4
2
|
IDTrapdoor;
|
5
3
|
IDNullifier;
|
6
4
|
IDSecretHash;
|
7
5
|
IDCommitment;
|
8
|
-
IDCommitmentBigInt;
|
9
6
|
/**
|
10
7
|
* All variables are in little-endian format
|
11
8
|
*/
|
@@ -14,8 +11,6 @@ class IdentityCredential {
|
|
14
11
|
this.IDNullifier = IDNullifier;
|
15
12
|
this.IDSecretHash = IDSecretHash;
|
16
13
|
this.IDCommitment = IDCommitment;
|
17
|
-
this.IDCommitmentBigInt =
|
18
|
-
BytesUtils.buildBigIntFromUint8ArrayBE(IDCommitment);
|
19
14
|
}
|
20
15
|
static fromBytes(memKeys) {
|
21
16
|
if (memKeys.length < 128) {
|
@@ -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 { BytesUtils } from '../utils/bytes.js';
|
21
20
|
import { keccak256Checksum, decryptEipKeystore } from './cipher.js';
|
22
21
|
import { isKeystoreValid, isCredentialValid } from './schema_validator.js';
|
23
22
|
import { __exports as lib } from '../../../../_virtual/index.js';
|
@@ -164,24 +163,16 @@ class Keystore {
|
|
164
163
|
try {
|
165
164
|
const str = bytesToUtf8(bytes);
|
166
165
|
const obj = JSON.parse(str);
|
167
|
-
// Little Endian
|
168
166
|
const idCommitmentLE = Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idCommitment", []));
|
169
167
|
const idTrapdoorLE = Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idTrapdoor", []));
|
170
168
|
const idNullifierLE = Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idNullifier", []));
|
171
169
|
const idSecretHashLE = Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idSecretHash", []));
|
172
|
-
// Big Endian
|
173
|
-
const idCommitmentBE = BytesUtils.switchEndianness(idCommitmentLE);
|
174
|
-
const idTrapdoorBE = BytesUtils.switchEndianness(idTrapdoorLE);
|
175
|
-
const idNullifierBE = BytesUtils.switchEndianness(idNullifierLE);
|
176
|
-
const idSecretHashBE = BytesUtils.switchEndianness(idSecretHashLE);
|
177
|
-
const idCommitmentBigInt = BytesUtils.buildBigIntFromUint8ArrayBE(idCommitmentBE);
|
178
170
|
return {
|
179
171
|
identity: {
|
180
|
-
IDCommitment:
|
181
|
-
IDTrapdoor:
|
182
|
-
IDNullifier:
|
183
|
-
IDSecretHash:
|
184
|
-
IDCommitmentBigInt: idCommitmentBigInt
|
172
|
+
IDCommitment: idCommitmentLE,
|
173
|
+
IDTrapdoor: idTrapdoorLE,
|
174
|
+
IDNullifier: idNullifierLE,
|
175
|
+
IDSecretHash: idSecretHashLE
|
185
176
|
},
|
186
177
|
membership: {
|
187
178
|
treeIndex: _.get(obj, "treeIndex"),
|
@@ -217,15 +208,17 @@ class Keystore {
|
|
217
208
|
}
|
218
209
|
// follows nwaku implementation
|
219
210
|
// https://github.com/waku-org/nwaku/blob/f05528d4be3d3c876a8b07f9bb7dfaae8aa8ec6e/waku/waku_keystore/protocol_types.nim#L98
|
220
|
-
// IdentityCredential is stored in Big Endian format => switch to Little Endian
|
221
211
|
static fromIdentityToBytes(options) {
|
212
|
+
function toLittleEndian(bytes) {
|
213
|
+
return new Uint8Array(bytes).reverse();
|
214
|
+
}
|
222
215
|
return utf8ToBytes(JSON.stringify({
|
223
216
|
treeIndex: options.membership.treeIndex,
|
224
217
|
identityCredential: {
|
225
|
-
idCommitment: Array.from(
|
226
|
-
idNullifier: Array.from(
|
227
|
-
idSecretHash: Array.from(
|
228
|
-
idTrapdoor: Array.from(
|
218
|
+
idCommitment: Array.from(toLittleEndian(options.identity.IDCommitment)),
|
219
|
+
idNullifier: Array.from(toLittleEndian(options.identity.IDNullifier)),
|
220
|
+
idSecretHash: Array.from(toLittleEndian(options.identity.IDSecretHash)),
|
221
|
+
idTrapdoor: Array.from(toLittleEndian(options.identity.IDTrapdoor))
|
229
222
|
},
|
230
223
|
membershipContract: {
|
231
224
|
chainId: options.membership.chainId,
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { concatenate } from './utils/bytes.js';
|
2
2
|
import { poseidonHash } from './utils/hash.js';
|
3
3
|
import './utils/epoch.js';
|
4
4
|
|
@@ -48,7 +48,7 @@ class Proof {
|
|
48
48
|
}
|
49
49
|
}
|
50
50
|
function proofToBytes(p) {
|
51
|
-
return
|
51
|
+
return concatenate(p.proof, p.merkleRoot, p.epoch, p.shareX, p.shareY, p.nullifier, p.rlnIdentifier);
|
52
52
|
}
|
53
53
|
|
54
54
|
export { Proof, proofToBytes };
|
@@ -1,110 +1,63 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
}
|
62
|
-
let mul = 1;
|
63
|
-
let i = 0;
|
64
|
-
buf[offset] = value & 0xff;
|
65
|
-
while (++i < byteLength && (mul *= 0x100)) {
|
66
|
-
buf[offset + i] = (value / mul) & 0xff;
|
67
|
-
}
|
68
|
-
return buf;
|
69
|
-
}
|
70
|
-
/**
|
71
|
-
* Fills with zeros to set length
|
72
|
-
* @param array little endian Uint8Array
|
73
|
-
* @param length amount to pad
|
74
|
-
* @returns little endian Uint8Array padded with zeros to set length
|
75
|
-
*/
|
76
|
-
static zeroPadLE(array, length) {
|
77
|
-
const result = new Uint8Array(length);
|
78
|
-
for (let i = 0; i < length; i++) {
|
79
|
-
result[i] = array[i] || 0;
|
80
|
-
}
|
81
|
-
return result;
|
82
|
-
}
|
83
|
-
// Adapted from https://github.com/feross/buffer
|
84
|
-
static checkInt(buf, value, offset, ext, max, min) {
|
85
|
-
if (value > max || value < min)
|
86
|
-
throw new RangeError('"value" argument is out of bounds');
|
87
|
-
if (offset + ext > buf.length)
|
88
|
-
throw new RangeError("Index out of range");
|
89
|
-
}
|
90
|
-
/**
|
91
|
-
* Concatenate Uint8Arrays
|
92
|
-
* @param input
|
93
|
-
* @returns concatenation of all Uint8Array received as input
|
94
|
-
*/
|
95
|
-
static concatenate(...input) {
|
96
|
-
let totalLength = 0;
|
97
|
-
for (const arr of input) {
|
98
|
-
totalLength += arr.length;
|
99
|
-
}
|
100
|
-
const result = new Uint8Array(totalLength);
|
101
|
-
let offset = 0;
|
102
|
-
for (const arr of input) {
|
103
|
-
result.set(arr, offset);
|
104
|
-
offset += arr.length;
|
105
|
-
}
|
106
|
-
return result;
|
107
|
-
}
|
1
|
+
/**
|
2
|
+
* Concatenate Uint8Arrays
|
3
|
+
* @param input
|
4
|
+
* @returns concatenation of all Uint8Array received as input
|
5
|
+
*/
|
6
|
+
function concatenate(...input) {
|
7
|
+
let totalLength = 0;
|
8
|
+
for (const arr of input) {
|
9
|
+
totalLength += arr.length;
|
10
|
+
}
|
11
|
+
const result = new Uint8Array(totalLength);
|
12
|
+
let offset = 0;
|
13
|
+
for (const arr of input) {
|
14
|
+
result.set(arr, offset);
|
15
|
+
offset += arr.length;
|
16
|
+
}
|
17
|
+
return result;
|
18
|
+
}
|
19
|
+
function switchEndianness(bytes) {
|
20
|
+
return new Uint8Array(bytes.reverse());
|
21
|
+
}
|
22
|
+
function buildBigIntFromUint8ArrayBE(bytes) {
|
23
|
+
// Interpret bytes as big-endian
|
24
|
+
return bytes.reduce((acc, byte) => (acc << 8n) + BigInt(byte), 0n);
|
25
|
+
}
|
26
|
+
function writeUIntLE(buf, value, offset, byteLength, noAssert) {
|
27
|
+
value = +value;
|
28
|
+
offset = offset >>> 0;
|
29
|
+
byteLength = byteLength >>> 0;
|
30
|
+
{
|
31
|
+
const maxBytes = Math.pow(2, 8 * byteLength) - 1;
|
32
|
+
checkInt(buf, value, offset, byteLength, maxBytes, 0);
|
33
|
+
}
|
34
|
+
let mul = 1;
|
35
|
+
let i = 0;
|
36
|
+
buf[offset] = value & 0xff;
|
37
|
+
while (++i < byteLength && (mul *= 0x100)) {
|
38
|
+
buf[offset + i] = (value / mul) & 0xff;
|
39
|
+
}
|
40
|
+
return buf;
|
41
|
+
}
|
42
|
+
/**
|
43
|
+
* Fills with zeros to set length
|
44
|
+
* @param array little endian Uint8Array
|
45
|
+
* @param length amount to pad
|
46
|
+
* @returns little endian Uint8Array padded with zeros to set length
|
47
|
+
*/
|
48
|
+
function zeroPadLE(array, length) {
|
49
|
+
const result = new Uint8Array(length);
|
50
|
+
for (let i = 0; i < length; i++) {
|
51
|
+
result[i] = array[i] || 0;
|
52
|
+
}
|
53
|
+
return result;
|
54
|
+
}
|
55
|
+
// Adapted from https://github.com/feross/buffer
|
56
|
+
function checkInt(buf, value, offset, ext, max, min) {
|
57
|
+
if (value > max || value < min)
|
58
|
+
throw new RangeError('"value" argument is out of bounds');
|
59
|
+
if (offset + ext > buf.length)
|
60
|
+
throw new RangeError("Index out of range");
|
108
61
|
}
|
109
62
|
|
110
|
-
export {
|
63
|
+
export { buildBigIntFromUint8ArrayBE, concatenate, switchEndianness, writeUIntLE, zeroPadLE };
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import { poseidonHash as poseidonHash$1 } from '../../../../node_modules/@waku/zerokit-rln-wasm/rln_wasm.js';
|
2
|
-
import {
|
2
|
+
import { writeUIntLE, concatenate } from './bytes.js';
|
3
3
|
|
4
4
|
function poseidonHash(...input) {
|
5
|
-
const inputLen =
|
6
|
-
const lenPrefixedData =
|
5
|
+
const inputLen = writeUIntLE(new Uint8Array(8), input.length, 0, 8);
|
6
|
+
const lenPrefixedData = concatenate(inputLen, ...input);
|
7
7
|
return poseidonHash$1(lenPrefixedData);
|
8
8
|
}
|
9
9
|
|
@@ -2,7 +2,7 @@ import { generateExtendedMembershipKey, generateSeededExtendedMembershipKey, ins
|
|
2
2
|
import { DEFAULT_RATE_LIMIT, RATE_LIMIT_PARAMS } from './contract/constants.js';
|
3
3
|
import { IdentityCredential } from './identity.js';
|
4
4
|
import { Proof, proofToBytes } from './proof.js';
|
5
|
-
import {
|
5
|
+
import { writeUIntLE, concatenate } from './utils/bytes.js';
|
6
6
|
import { epochIntToBytes, dateToEpoch } from './utils/epoch.js';
|
7
7
|
|
8
8
|
class Zerokit {
|
@@ -40,8 +40,8 @@ class Zerokit {
|
|
40
40
|
insertMembers(index, ...idCommitments) {
|
41
41
|
// serializes a seq of IDCommitments to a byte seq
|
42
42
|
// the order of serialization is |id_commitment_len<8>|id_commitment<var>|
|
43
|
-
const idCommitmentLen =
|
44
|
-
const idCommitmentBytes =
|
43
|
+
const idCommitmentLen = writeUIntLE(new Uint8Array(8), idCommitments.length, 0, 8);
|
44
|
+
const idCommitmentBytes = concatenate(idCommitmentLen, ...idCommitments);
|
45
45
|
setLeavesFrom(this.zkRLN, index, idCommitmentBytes);
|
46
46
|
}
|
47
47
|
deleteMember(index) {
|
@@ -52,11 +52,11 @@ class Zerokit {
|
|
52
52
|
}
|
53
53
|
serializeMessage(uint8Msg, memIndex, epoch, idKey, rateLimit) {
|
54
54
|
// calculate message length
|
55
|
-
const msgLen =
|
56
|
-
const memIndexBytes =
|
57
|
-
const rateLimitBytes =
|
55
|
+
const msgLen = writeUIntLE(new Uint8Array(8), uint8Msg.length, 0, 8);
|
56
|
+
const memIndexBytes = writeUIntLE(new Uint8Array(8), memIndex, 0, 8);
|
57
|
+
const rateLimitBytes = writeUIntLE(new Uint8Array(8), rateLimit ?? this.rateLimit, 0, 8);
|
58
58
|
// [ id_key<32> | id_index<8> | epoch<32> | signal_len<8> | signal<var> | rate_limit<8> ]
|
59
|
-
return
|
59
|
+
return concatenate(idKey, memIndexBytes, epoch, msgLen, uint8Msg, rateLimitBytes);
|
60
60
|
}
|
61
61
|
async generateRLNProof(msg, index, epoch, idSecretHash, rateLimit) {
|
62
62
|
if (epoch === undefined) {
|
@@ -92,9 +92,9 @@ class Zerokit {
|
|
92
92
|
pBytes = proofToBytes(proof);
|
93
93
|
}
|
94
94
|
// calculate message length
|
95
|
-
const msgLen =
|
96
|
-
const rateLimitBytes =
|
97
|
-
return verifyRLNProof(this.zkRLN,
|
95
|
+
const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
|
96
|
+
const rateLimitBytes = writeUIntLE(new Uint8Array(8), rateLimit ?? this.rateLimit, 0, 8);
|
97
|
+
return verifyRLNProof(this.zkRLN, concatenate(pBytes, msgLen, msg, rateLimitBytes));
|
98
98
|
}
|
99
99
|
verifyWithRoots(proof, msg, roots, rateLimit) {
|
100
100
|
let pBytes;
|
@@ -105,10 +105,10 @@ class Zerokit {
|
|
105
105
|
pBytes = proofToBytes(proof);
|
106
106
|
}
|
107
107
|
// calculate message length
|
108
|
-
const msgLen =
|
109
|
-
const rateLimitBytes =
|
110
|
-
const rootsBytes =
|
111
|
-
return verifyWithRoots(this.zkRLN,
|
108
|
+
const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
|
109
|
+
const rateLimitBytes = writeUIntLE(new Uint8Array(8), rateLimit ?? this.rateLimit, 0, 8);
|
110
|
+
const rootsBytes = concatenate(...roots);
|
111
|
+
return verifyWithRoots(this.zkRLN, concatenate(pBytes, msgLen, msg, rateLimitBytes), rootsBytes);
|
112
112
|
}
|
113
113
|
verifyWithNoRoot(proof, msg, rateLimit) {
|
114
114
|
let pBytes;
|
@@ -119,9 +119,9 @@ class Zerokit {
|
|
119
119
|
pBytes = proofToBytes(proof);
|
120
120
|
}
|
121
121
|
// calculate message length
|
122
|
-
const msgLen =
|
123
|
-
const rateLimitBytes =
|
124
|
-
return verifyWithRoots(this.zkRLN,
|
122
|
+
const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
|
123
|
+
const rateLimitBytes = writeUIntLE(new Uint8Array(8), rateLimit ?? this.rateLimit, 0, 8);
|
124
|
+
return verifyWithRoots(this.zkRLN, concatenate(pBytes, msgLen, msg, rateLimitBytes), new Uint8Array());
|
125
125
|
}
|
126
126
|
}
|
127
127
|
|