@waku/rln 0.1.6-16328a3.0 → 0.1.6-2ce706d.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/index.js +1 -1
- package/bundle/packages/core/dist/lib/message/version_0.js +1 -4
- package/bundle/packages/rln/dist/contract/constants.js +7 -1
- package/bundle/packages/rln/dist/contract/rln_base_contract.js +10 -5
- package/bundle/packages/rln/dist/credentials_manager.js +16 -14
- package/bundle/packages/rln/dist/identity.js +37 -7
- package/bundle/packages/rln/dist/keystore/keystore.js +15 -11
- package/bundle/packages/rln/dist/message.js +11 -0
- package/bundle/packages/rln/dist/utils/bytes.js +14 -16
- package/dist/.tsbuildinfo +1 -1
- package/dist/contract/constants.d.ts +6 -0
- package/dist/contract/constants.js +6 -0
- package/dist/contract/constants.js.map +1 -1
- package/dist/contract/rln_base_contract.js +10 -5
- package/dist/contract/rln_base_contract.js.map +1 -1
- package/dist/credentials_manager.js +16 -14
- package/dist/credentials_manager.js.map +1 -1
- package/dist/identity.d.ts +11 -2
- package/dist/identity.js +23 -6
- package/dist/identity.js.map +1 -1
- package/dist/keystore/keystore.js +15 -11
- package/dist/keystore/keystore.js.map +1 -1
- package/dist/message.d.ts +5 -4
- package/dist/message.js +2 -0
- package/dist/message.js.map +1 -1
- package/dist/utils/bytes.d.ts +2 -6
- package/dist/utils/bytes.js +13 -15
- package/dist/utils/bytes.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/package.json +1 -1
- package/src/contract/constants.ts +9 -0
- package/src/contract/rln_base_contract.ts +12 -13
- package/src/credentials_manager.ts +27 -21
- package/src/identity.ts +32 -6
- package/src/keystore/keystore.ts +28 -24
- package/src/message.ts +7 -4
- package/src/utils/bytes.ts +21 -25
- package/src/utils/index.ts +1 -1
- package/dist/contract/test-utils.d.ts +0 -39
- package/dist/contract/test-utils.js +0 -118
- package/dist/contract/test-utils.js.map +0 -1
- package/src/contract/test-utils.ts +0 -179
@@ -79,7 +79,8 @@ export class RLNBaseContract {
|
|
79
79
|
const instance = new RLNBaseContract(options);
|
80
80
|
const [min, max] = await Promise.all([
|
81
81
|
instance.contract.minMembershipRateLimit(),
|
82
|
-
instance.contract.maxMembershipRateLimit()
|
82
|
+
instance.contract.maxMembershipRateLimit(),
|
83
|
+
instance.contract.Q()
|
83
84
|
]);
|
84
85
|
instance.minRateLimit = ethers.BigNumber.from(min).toNumber();
|
85
86
|
instance.maxRateLimit = ethers.BigNumber.from(max).toNumber();
|
@@ -490,7 +491,6 @@ export class RLNBaseContract {
|
|
490
491
|
log.error(`Error in withdraw: ${(error as Error).message}`);
|
491
492
|
}
|
492
493
|
}
|
493
|
-
|
494
494
|
public async registerWithIdentity(
|
495
495
|
identity: IdentityCredential
|
496
496
|
): Promise<DecryptedCredentials | undefined> {
|
@@ -499,10 +499,12 @@ export class RLNBaseContract {
|
|
499
499
|
`Registering identity with rate limit: ${this.rateLimit} messages/epoch`
|
500
500
|
);
|
501
501
|
|
502
|
-
|
503
|
-
|
504
|
-
identity.IDCommitmentBigInt
|
502
|
+
const idCommitmentBigInt = IdentityCredential.getIdCommitmentBigInt(
|
503
|
+
identity.IDCommitment
|
505
504
|
);
|
505
|
+
|
506
|
+
// Check if the ID commitment is already registered
|
507
|
+
const existingIndex = await this.getMemberIndex(idCommitmentBigInt);
|
506
508
|
if (existingIndex) {
|
507
509
|
throw new Error(
|
508
510
|
`ID commitment is already registered with index ${existingIndex}`
|
@@ -518,19 +520,16 @@ export class RLNBaseContract {
|
|
518
520
|
}
|
519
521
|
|
520
522
|
const estimatedGas = await this.contract.estimateGas.register(
|
521
|
-
|
523
|
+
idCommitmentBigInt,
|
522
524
|
this.rateLimit,
|
523
525
|
[]
|
524
526
|
);
|
525
527
|
const gasLimit = estimatedGas.add(10000);
|
526
528
|
|
527
529
|
const txRegisterResponse: ethers.ContractTransaction =
|
528
|
-
await this.contract.register(
|
529
|
-
|
530
|
-
|
531
|
-
[],
|
532
|
-
{ gasLimit }
|
533
|
-
);
|
530
|
+
await this.contract.register(idCommitmentBigInt, this.rateLimit, [], {
|
531
|
+
gasLimit
|
532
|
+
});
|
534
533
|
|
535
534
|
const txRegisterReceipt = await txRegisterResponse.wait();
|
536
535
|
|
@@ -626,7 +625,7 @@ export class RLNBaseContract {
|
|
626
625
|
permit.v,
|
627
626
|
permit.r,
|
628
627
|
permit.s,
|
629
|
-
identity.
|
628
|
+
IdentityCredential.getIdCommitmentBigInt(identity.IDCommitment),
|
630
629
|
this.rateLimit,
|
631
630
|
idCommitmentsToErase.map((id) => ethers.BigNumber.from(id))
|
632
631
|
);
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { hmac } from "@noble/hashes/hmac";
|
2
|
-
import { sha256 } from "@noble/hashes/
|
2
|
+
import { sha256 } from "@noble/hashes/sha2";
|
3
3
|
import { Logger } from "@waku/utils";
|
4
4
|
import { ethers } from "ethers";
|
5
5
|
|
@@ -13,10 +13,7 @@ import type {
|
|
13
13
|
} from "./keystore/index.js";
|
14
14
|
import { KeystoreEntity, Password } from "./keystore/types.js";
|
15
15
|
import { RegisterMembershipOptions, StartRLNOptions } from "./types.js";
|
16
|
-
import {
|
17
|
-
buildBigIntFromUint8Array,
|
18
|
-
extractMetaMaskSigner
|
19
|
-
} from "./utils/index.js";
|
16
|
+
import { extractMetaMaskSigner, switchEndianness } from "./utils/index.js";
|
20
17
|
import { Zerokit } from "./zerokit.js";
|
21
18
|
|
22
19
|
const log = new Logger("waku:credentials");
|
@@ -116,7 +113,9 @@ export class RLNCredentialsManager {
|
|
116
113
|
);
|
117
114
|
} else {
|
118
115
|
log.info("Using local implementation to generate identity");
|
119
|
-
identity = this.generateSeededIdentityCredential(
|
116
|
+
identity = await this.generateSeededIdentityCredential(
|
117
|
+
options.signature
|
118
|
+
);
|
120
119
|
}
|
121
120
|
}
|
122
121
|
|
@@ -249,7 +248,9 @@ export class RLNCredentialsManager {
|
|
249
248
|
* @param seed A string seed to generate the identity from
|
250
249
|
* @returns IdentityCredential
|
251
250
|
*/
|
252
|
-
private generateSeededIdentityCredential(
|
251
|
+
private async generateSeededIdentityCredential(
|
252
|
+
seed: string
|
253
|
+
): Promise<IdentityCredential> {
|
253
254
|
log.info("Generating seeded identity credential");
|
254
255
|
// Convert the seed to bytes
|
255
256
|
const encoder = new TextEncoder();
|
@@ -257,26 +258,31 @@ export class RLNCredentialsManager {
|
|
257
258
|
|
258
259
|
// Generate deterministic values using HMAC-SHA256
|
259
260
|
// We use different context strings for each component to ensure they're different
|
260
|
-
const
|
261
|
-
const
|
261
|
+
const idTrapdoorBE = hmac(sha256, seedBytes, encoder.encode("IDTrapdoor"));
|
262
|
+
const idNullifierBE = hmac(
|
263
|
+
sha256,
|
264
|
+
seedBytes,
|
265
|
+
encoder.encode("IDNullifier")
|
266
|
+
);
|
262
267
|
|
263
|
-
|
264
|
-
const
|
265
|
-
const idSecretHash = sha256(combinedBytes);
|
268
|
+
const combinedBytes = new Uint8Array([...idTrapdoorBE, ...idNullifierBE]);
|
269
|
+
const idSecretHashBE = sha256(combinedBytes);
|
266
270
|
|
267
|
-
|
268
|
-
const idCommitment = sha256(idSecretHash);
|
271
|
+
const idCommitmentBE = sha256(idSecretHashBE);
|
269
272
|
|
270
|
-
//
|
271
|
-
|
273
|
+
// All hashing functions return big-endian bytes
|
274
|
+
// We need to switch to little-endian for the identity credential
|
275
|
+
const idTrapdoorLE = switchEndianness(idTrapdoorBE);
|
276
|
+
const idNullifierLE = switchEndianness(idNullifierBE);
|
277
|
+
const idSecretHashLE = switchEndianness(idSecretHashBE);
|
278
|
+
const idCommitmentLE = switchEndianness(idCommitmentBE);
|
272
279
|
|
273
280
|
log.info("Successfully generated identity credential");
|
274
281
|
return new IdentityCredential(
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
idCommitmentBigInt
|
282
|
+
idTrapdoorLE,
|
283
|
+
idNullifierLE,
|
284
|
+
idSecretHashLE,
|
285
|
+
idCommitmentLE
|
280
286
|
);
|
281
287
|
}
|
282
288
|
}
|
package/src/identity.ts
CHANGED
@@ -1,12 +1,19 @@
|
|
1
|
-
import {
|
1
|
+
import { Logger } from "@waku/utils";
|
2
|
+
|
3
|
+
import { DEFAULT_Q } from "./contract/constants.js";
|
4
|
+
import { buildBigIntFromUint8ArrayBE } from "./utils/bytes.js";
|
5
|
+
|
6
|
+
const log = new Logger("waku:rln:identity");
|
2
7
|
|
3
8
|
export class IdentityCredential {
|
9
|
+
/**
|
10
|
+
* All variables are in little-endian format
|
11
|
+
*/
|
4
12
|
public constructor(
|
5
13
|
public readonly IDTrapdoor: Uint8Array,
|
6
14
|
public readonly IDNullifier: Uint8Array,
|
7
15
|
public readonly IDSecretHash: Uint8Array,
|
8
|
-
public readonly IDCommitment: Uint8Array
|
9
|
-
public readonly IDCommitmentBigInt: bigint
|
16
|
+
public readonly IDCommitment: Uint8Array
|
10
17
|
) {}
|
11
18
|
|
12
19
|
public static fromBytes(memKeys: Uint8Array): IdentityCredential {
|
@@ -18,14 +25,33 @@ export class IdentityCredential {
|
|
18
25
|
const idNullifier = memKeys.subarray(32, 64);
|
19
26
|
const idSecretHash = memKeys.subarray(64, 96);
|
20
27
|
const idCommitment = memKeys.subarray(96, 128);
|
21
|
-
const idCommitmentBigInt = buildBigIntFromUint8Array(idCommitment, 32);
|
22
28
|
|
23
29
|
return new IdentityCredential(
|
24
30
|
idTrapdoor,
|
25
31
|
idNullifier,
|
26
32
|
idSecretHash,
|
27
|
-
idCommitment
|
28
|
-
idCommitmentBigInt
|
33
|
+
idCommitment
|
29
34
|
);
|
30
35
|
}
|
36
|
+
|
37
|
+
/**
|
38
|
+
* Converts an ID commitment from bytes to a BigInt, normalizing it against a limit if needed
|
39
|
+
* @param bytes The ID commitment bytes to convert
|
40
|
+
* @param limit Optional limit to normalize against (Q value)
|
41
|
+
* @returns The ID commitment as a BigInt
|
42
|
+
*/
|
43
|
+
public static getIdCommitmentBigInt(
|
44
|
+
bytes: Uint8Array,
|
45
|
+
limit: bigint = DEFAULT_Q
|
46
|
+
): bigint {
|
47
|
+
let idCommitmentBigIntBE = buildBigIntFromUint8ArrayBE(bytes);
|
48
|
+
|
49
|
+
if (limit && idCommitmentBigIntBE >= limit) {
|
50
|
+
log.warn(
|
51
|
+
`ID commitment is greater than Q, reducing it by Q: ${idCommitmentBigIntBE} % ${limit}`
|
52
|
+
);
|
53
|
+
idCommitmentBigIntBE = idCommitmentBigIntBE % limit;
|
54
|
+
}
|
55
|
+
return idCommitmentBigIntBE;
|
56
|
+
}
|
31
57
|
}
|
package/src/keystore/keystore.ts
CHANGED
@@ -14,8 +14,6 @@ import {
|
|
14
14
|
import _ from "lodash";
|
15
15
|
import { v4 as uuidV4 } from "uuid";
|
16
16
|
|
17
|
-
import { buildBigIntFromUint8Array } from "../utils/bytes.js";
|
18
|
-
|
19
17
|
import { decryptEipKeystore, keccak256Checksum } from "./cipher.js";
|
20
18
|
import { isCredentialValid, isKeystoreValid } from "./schema_validator.js";
|
21
19
|
import type {
|
@@ -250,26 +248,25 @@ export class Keystore {
|
|
250
248
|
const str = bytesToUtf8(bytes);
|
251
249
|
const obj = JSON.parse(str);
|
252
250
|
|
253
|
-
|
251
|
+
const idCommitmentLE = Keystore.fromArraylikeToBytes(
|
252
|
+
_.get(obj, "identityCredential.idCommitment", [])
|
253
|
+
);
|
254
|
+
const idTrapdoorLE = Keystore.fromArraylikeToBytes(
|
255
|
+
_.get(obj, "identityCredential.idTrapdoor", [])
|
256
|
+
);
|
257
|
+
const idNullifierLE = Keystore.fromArraylikeToBytes(
|
258
|
+
_.get(obj, "identityCredential.idNullifier", [])
|
259
|
+
);
|
260
|
+
const idSecretHashLE = Keystore.fromArraylikeToBytes(
|
261
|
+
_.get(obj, "identityCredential.idSecretHash", [])
|
262
|
+
);
|
263
|
+
|
254
264
|
return {
|
255
265
|
identity: {
|
256
|
-
IDCommitment:
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
_.get(obj, "identityCredential.idTrapdoor", [])
|
261
|
-
),
|
262
|
-
IDNullifier: Keystore.fromArraylikeToBytes(
|
263
|
-
_.get(obj, "identityCredential.idNullifier", [])
|
264
|
-
),
|
265
|
-
IDCommitmentBigInt: buildBigIntFromUint8Array(
|
266
|
-
Keystore.fromArraylikeToBytes(
|
267
|
-
_.get(obj, "identityCredential.idCommitment", [])
|
268
|
-
)
|
269
|
-
),
|
270
|
-
IDSecretHash: Keystore.fromArraylikeToBytes(
|
271
|
-
_.get(obj, "identityCredential.idSecretHash", [])
|
272
|
-
)
|
266
|
+
IDCommitment: idCommitmentLE,
|
267
|
+
IDTrapdoor: idTrapdoorLE,
|
268
|
+
IDNullifier: idNullifierLE,
|
269
|
+
IDSecretHash: idSecretHashLE
|
273
270
|
},
|
274
271
|
membership: {
|
275
272
|
treeIndex: _.get(obj, "treeIndex"),
|
@@ -321,14 +318,21 @@ export class Keystore {
|
|
321
318
|
// follows nwaku implementation
|
322
319
|
// https://github.com/waku-org/nwaku/blob/f05528d4be3d3c876a8b07f9bb7dfaae8aa8ec6e/waku/waku_keystore/protocol_types.nim#L98
|
323
320
|
private static fromIdentityToBytes(options: KeystoreEntity): Uint8Array {
|
321
|
+
function toLittleEndian(bytes: Uint8Array): Uint8Array {
|
322
|
+
return new Uint8Array(bytes).reverse();
|
323
|
+
}
|
324
324
|
return utf8ToBytes(
|
325
325
|
JSON.stringify({
|
326
326
|
treeIndex: options.membership.treeIndex,
|
327
327
|
identityCredential: {
|
328
|
-
idCommitment: Array.from(
|
329
|
-
|
330
|
-
|
331
|
-
|
328
|
+
idCommitment: Array.from(
|
329
|
+
toLittleEndian(options.identity.IDCommitment)
|
330
|
+
),
|
331
|
+
idNullifier: Array.from(toLittleEndian(options.identity.IDNullifier)),
|
332
|
+
idSecretHash: Array.from(
|
333
|
+
toLittleEndian(options.identity.IDSecretHash)
|
334
|
+
),
|
335
|
+
idTrapdoor: Array.from(toLittleEndian(options.identity.IDTrapdoor))
|
332
336
|
},
|
333
337
|
membershipContract: {
|
334
338
|
chainId: options.membership.chainId,
|
package/src/message.ts
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
import { message } from "@waku/core";
|
1
2
|
import type {
|
2
3
|
IDecodedMessage,
|
3
4
|
IMessage,
|
4
|
-
IRateLimitProof
|
5
|
+
IRateLimitProof,
|
6
|
+
IRlnMessage
|
5
7
|
} from "@waku/interfaces";
|
6
8
|
import * as utils from "@waku/utils/bytes";
|
7
9
|
|
@@ -13,12 +15,13 @@ export function toRLNSignal(contentTopic: string, msg: IMessage): Uint8Array {
|
|
13
15
|
return new Uint8Array([...(msg.payload ?? []), ...contentTopicBytes]);
|
14
16
|
}
|
15
17
|
|
16
|
-
export class RlnMessage<T extends IDecodedMessage> implements
|
18
|
+
export class RlnMessage<T extends IDecodedMessage> implements IRlnMessage {
|
17
19
|
public pubsubTopic = "";
|
20
|
+
public version = message.version_0.Version;
|
18
21
|
|
19
22
|
public constructor(
|
20
|
-
|
21
|
-
|
23
|
+
private rlnInstance: RLNInstance,
|
24
|
+
private msg: T,
|
22
25
|
public rateLimitProof: IRateLimitProof | undefined
|
23
26
|
) {}
|
24
27
|
|
package/src/utils/bytes.ts
CHANGED
@@ -17,18 +17,13 @@ export function concatenate(...input: Uint8Array[]): Uint8Array {
|
|
17
17
|
return result;
|
18
18
|
}
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
min: number
|
28
|
-
): void {
|
29
|
-
if (value > max || value < min)
|
30
|
-
throw new RangeError('"value" argument is out of bounds');
|
31
|
-
if (offset + ext > buf.length) throw new RangeError("Index out of range");
|
20
|
+
export function switchEndianness(bytes: Uint8Array): Uint8Array {
|
21
|
+
return new Uint8Array(bytes.reverse());
|
22
|
+
}
|
23
|
+
|
24
|
+
export function buildBigIntFromUint8ArrayBE(bytes: Uint8Array): bigint {
|
25
|
+
// Interpret bytes as big-endian
|
26
|
+
return bytes.reduce((acc, byte) => (acc << 8n) + BigInt(byte), 0n);
|
32
27
|
}
|
33
28
|
|
34
29
|
export function writeUIntLE(
|
@@ -56,19 +51,6 @@ export function writeUIntLE(
|
|
56
51
|
return buf;
|
57
52
|
}
|
58
53
|
|
59
|
-
/**
|
60
|
-
* Transforms Uint8Array into BigInt
|
61
|
-
* @param array: Uint8Array
|
62
|
-
* @returns BigInt
|
63
|
-
*/
|
64
|
-
export function buildBigIntFromUint8Array(
|
65
|
-
array: Uint8Array,
|
66
|
-
byteOffset: number = 0
|
67
|
-
): bigint {
|
68
|
-
const dataView = new DataView(array.buffer);
|
69
|
-
return dataView.getBigUint64(byteOffset, true);
|
70
|
-
}
|
71
|
-
|
72
54
|
/**
|
73
55
|
* Fills with zeros to set length
|
74
56
|
* @param array little endian Uint8Array
|
@@ -82,3 +64,17 @@ export function zeroPadLE(array: Uint8Array, length: number): Uint8Array {
|
|
82
64
|
}
|
83
65
|
return result;
|
84
66
|
}
|
67
|
+
|
68
|
+
// Adapted from https://github.com/feross/buffer
|
69
|
+
function checkInt(
|
70
|
+
buf: Uint8Array,
|
71
|
+
value: number,
|
72
|
+
offset: number,
|
73
|
+
ext: number,
|
74
|
+
max: number,
|
75
|
+
min: number
|
76
|
+
): void {
|
77
|
+
if (value > max || value < min)
|
78
|
+
throw new RangeError('"value" argument is out of bounds');
|
79
|
+
if (offset + ext > buf.length) throw new RangeError("Index out of range");
|
80
|
+
}
|
package/src/utils/index.ts
CHANGED
@@ -1,39 +0,0 @@
|
|
1
|
-
import * as ethers from "ethers";
|
2
|
-
import sinon from "sinon";
|
3
|
-
import type { IdentityCredential } from "../identity.js";
|
4
|
-
export declare const mockRateLimits: {
|
5
|
-
minRate: number;
|
6
|
-
maxRate: number;
|
7
|
-
maxTotalRate: number;
|
8
|
-
currentTotalRate: number;
|
9
|
-
};
|
10
|
-
type MockProvider = {
|
11
|
-
getLogs: () => never[];
|
12
|
-
getBlockNumber: () => Promise<number>;
|
13
|
-
getNetwork: () => Promise<{
|
14
|
-
chainId: number;
|
15
|
-
}>;
|
16
|
-
};
|
17
|
-
type MockFilters = {
|
18
|
-
MembershipRegistered: () => {
|
19
|
-
address: string;
|
20
|
-
};
|
21
|
-
MembershipErased: () => {
|
22
|
-
address: string;
|
23
|
-
};
|
24
|
-
MembershipExpired: () => {
|
25
|
-
address: string;
|
26
|
-
};
|
27
|
-
};
|
28
|
-
export declare function createMockProvider(): MockProvider;
|
29
|
-
export declare function createMockFilters(): MockFilters;
|
30
|
-
type ContractOverrides = Partial<{
|
31
|
-
filters: Record<string, unknown>;
|
32
|
-
[key: string]: unknown;
|
33
|
-
}>;
|
34
|
-
export declare function createMockRegistryContract(overrides?: ContractOverrides): ethers.Contract;
|
35
|
-
export declare function mockRLNRegisteredEvent(idCommitment?: string): ethers.Event;
|
36
|
-
export declare function formatIdCommitment(idCommitmentBigInt: bigint): string;
|
37
|
-
export declare function createRegisterStub(identity: IdentityCredential): sinon.SinonStub;
|
38
|
-
export declare function verifyRegistration(decryptedCredentials: any, identity: IdentityCredential, registerStub: sinon.SinonStub, insertMemberSpy: sinon.SinonStub): void;
|
39
|
-
export {};
|
@@ -1,118 +0,0 @@
|
|
1
|
-
import { hexToBytes } from "@waku/utils/bytes";
|
2
|
-
import { expect } from "chai";
|
3
|
-
import * as ethers from "ethers";
|
4
|
-
import sinon from "sinon";
|
5
|
-
import { DEFAULT_RATE_LIMIT, LINEA_CONTRACT } from "./constants.js";
|
6
|
-
export const mockRateLimits = {
|
7
|
-
minRate: 20,
|
8
|
-
maxRate: 600,
|
9
|
-
maxTotalRate: 1200,
|
10
|
-
currentTotalRate: 500
|
11
|
-
};
|
12
|
-
export function createMockProvider() {
|
13
|
-
return {
|
14
|
-
getLogs: () => [],
|
15
|
-
getBlockNumber: () => Promise.resolve(1000),
|
16
|
-
getNetwork: () => Promise.resolve({ chainId: 11155111 })
|
17
|
-
};
|
18
|
-
}
|
19
|
-
export function createMockFilters() {
|
20
|
-
return {
|
21
|
-
MembershipRegistered: () => ({ address: LINEA_CONTRACT.address }),
|
22
|
-
MembershipErased: () => ({ address: LINEA_CONTRACT.address }),
|
23
|
-
MembershipExpired: () => ({ address: LINEA_CONTRACT.address })
|
24
|
-
};
|
25
|
-
}
|
26
|
-
export function createMockRegistryContract(overrides = {}) {
|
27
|
-
const filters = {
|
28
|
-
MembershipRegistered: () => ({ address: LINEA_CONTRACT.address }),
|
29
|
-
MembershipErased: () => ({ address: LINEA_CONTRACT.address }),
|
30
|
-
MembershipExpired: () => ({ address: LINEA_CONTRACT.address })
|
31
|
-
};
|
32
|
-
const baseContract = {
|
33
|
-
minMembershipRateLimit: () => Promise.resolve(ethers.BigNumber.from(mockRateLimits.minRate)),
|
34
|
-
maxMembershipRateLimit: () => Promise.resolve(ethers.BigNumber.from(mockRateLimits.maxRate)),
|
35
|
-
maxTotalRateLimit: () => Promise.resolve(ethers.BigNumber.from(mockRateLimits.maxTotalRate)),
|
36
|
-
currentTotalRateLimit: () => Promise.resolve(ethers.BigNumber.from(mockRateLimits.currentTotalRate)),
|
37
|
-
queryFilter: () => [],
|
38
|
-
provider: createMockProvider(),
|
39
|
-
filters,
|
40
|
-
on: () => ({}),
|
41
|
-
removeAllListeners: () => ({}),
|
42
|
-
register: () => ({
|
43
|
-
wait: () => Promise.resolve({
|
44
|
-
events: [mockRLNRegisteredEvent()]
|
45
|
-
})
|
46
|
-
}),
|
47
|
-
estimateGas: {
|
48
|
-
register: () => Promise.resolve(ethers.BigNumber.from(100000))
|
49
|
-
},
|
50
|
-
functions: {
|
51
|
-
register: () => Promise.resolve()
|
52
|
-
},
|
53
|
-
getMemberIndex: () => Promise.resolve(null),
|
54
|
-
interface: {
|
55
|
-
getEvent: (eventName) => ({
|
56
|
-
name: eventName,
|
57
|
-
format: () => { }
|
58
|
-
})
|
59
|
-
},
|
60
|
-
address: LINEA_CONTRACT.address
|
61
|
-
};
|
62
|
-
// Merge overrides while preserving filters
|
63
|
-
const merged = {
|
64
|
-
...baseContract,
|
65
|
-
...overrides,
|
66
|
-
filters: { ...filters, ...(overrides.filters || {}) }
|
67
|
-
};
|
68
|
-
return merged;
|
69
|
-
}
|
70
|
-
export function mockRLNRegisteredEvent(idCommitment) {
|
71
|
-
return {
|
72
|
-
args: {
|
73
|
-
idCommitment: idCommitment ||
|
74
|
-
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
|
75
|
-
membershipRateLimit: ethers.BigNumber.from(DEFAULT_RATE_LIMIT),
|
76
|
-
index: ethers.BigNumber.from(1)
|
77
|
-
},
|
78
|
-
event: "MembershipRegistered"
|
79
|
-
};
|
80
|
-
}
|
81
|
-
export function formatIdCommitment(idCommitmentBigInt) {
|
82
|
-
return "0x" + idCommitmentBigInt.toString(16).padStart(64, "0");
|
83
|
-
}
|
84
|
-
export function createRegisterStub(identity) {
|
85
|
-
return sinon.stub().callsFake(() => ({
|
86
|
-
wait: () => Promise.resolve({
|
87
|
-
events: [
|
88
|
-
{
|
89
|
-
event: "MembershipRegistered",
|
90
|
-
args: {
|
91
|
-
idCommitment: formatIdCommitment(identity.IDCommitmentBigInt),
|
92
|
-
membershipRateLimit: ethers.BigNumber.from(DEFAULT_RATE_LIMIT),
|
93
|
-
index: ethers.BigNumber.from(1)
|
94
|
-
}
|
95
|
-
}
|
96
|
-
]
|
97
|
-
})
|
98
|
-
}));
|
99
|
-
}
|
100
|
-
export function verifyRegistration(decryptedCredentials, identity, registerStub, insertMemberSpy) {
|
101
|
-
if (!decryptedCredentials) {
|
102
|
-
throw new Error("Decrypted credentials should not be undefined");
|
103
|
-
}
|
104
|
-
// Verify registration call
|
105
|
-
expect(registerStub.calledWith(sinon.match.same(identity.IDCommitmentBigInt), sinon.match.same(DEFAULT_RATE_LIMIT), sinon.match.array, sinon.match.object)).to.be.true;
|
106
|
-
// Verify credential properties
|
107
|
-
expect(decryptedCredentials).to.have.property("identity");
|
108
|
-
expect(decryptedCredentials).to.have.property("membership");
|
109
|
-
expect(decryptedCredentials.membership).to.include({
|
110
|
-
address: LINEA_CONTRACT.address,
|
111
|
-
treeIndex: 1
|
112
|
-
});
|
113
|
-
// Verify member insertion
|
114
|
-
const expectedIdCommitment = ethers.utils.zeroPad(hexToBytes(formatIdCommitment(identity.IDCommitmentBigInt)), 32);
|
115
|
-
expect(insertMemberSpy.callCount).to.equal(1);
|
116
|
-
expect(insertMemberSpy.getCall(0).args[0]).to.deep.equal(expectedIdCommitment);
|
117
|
-
}
|
118
|
-
//# sourceMappingURL=test-utils.js.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../../src/contract/test-utils.ts"],"names":[],"mappings":"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"}
|