@semaphore-protocol/group 2.6.1 → 3.0.0-beta.5
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 +6 -6
- package/dist/index.mjs +38 -25
- package/dist/index.node.js +42 -25
- package/dist/types/group.d.ts +11 -11
- package/dist/types/hash.d.ts +7 -0
- package/dist/types/types/index.d.ts +1 -1
- package/package.json +5 -2
- package/src/group.test.ts +16 -15
- package/src/group.ts +24 -23
- package/src/hash.ts +15 -0
- package/src/types/index.ts +1 -1
package/README.md
CHANGED
|
@@ -67,19 +67,19 @@ yarn add @semaphore-protocol/group
|
|
|
67
67
|
|
|
68
68
|
## 📜 Usage
|
|
69
69
|
|
|
70
|
-
\# **new Group**(
|
|
70
|
+
\# **new Group**(groupId: _Member_, treeDepth = 20): _Group_
|
|
71
71
|
|
|
72
72
|
```typescript
|
|
73
73
|
import { Group } from "@semaphore-protocol/group"
|
|
74
74
|
|
|
75
75
|
// Group with max 1048576 members (20^²).
|
|
76
|
-
const group1 = new Group()
|
|
76
|
+
const group1 = new Group(1)
|
|
77
77
|
|
|
78
78
|
// Group with max 65536 members (16^²).
|
|
79
|
-
const group2 = new Group(16)
|
|
79
|
+
const group2 = new Group(1, 16)
|
|
80
80
|
|
|
81
81
|
// Group with max 16777216 members (24^²).
|
|
82
|
-
const group3 = new Group(24)
|
|
82
|
+
const group3 = new Group(1, 24)
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
\# **addMember**(identityCommitment: _Member_)
|
|
@@ -120,8 +120,8 @@ group.removeMember(0)
|
|
|
120
120
|
group.indexOf(commitment) // 0
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
-
\# **
|
|
123
|
+
\# **generateMerkleProof**(index: _number_): _MerkleProof_
|
|
124
124
|
|
|
125
125
|
```typescript
|
|
126
|
-
const proof = group.
|
|
126
|
+
const proof = group.generateMerkleProof(0)
|
|
127
127
|
```
|
package/dist/index.mjs
CHANGED
|
@@ -1,27 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module @semaphore-protocol/group
|
|
3
|
-
* @version
|
|
3
|
+
* @version 3.0.0-beta.5
|
|
4
4
|
* @file A library to create and manage Semaphore groups.
|
|
5
5
|
* @copyright Ethereum Foundation 2022
|
|
6
6
|
* @license MIT
|
|
7
7
|
* @see [Github]{@link https://github.com/semaphore-protocol/semaphore/tree/main/packages/group}
|
|
8
8
|
*/
|
|
9
9
|
import { IncrementalMerkleTree } from '@zk-kit/incremental-merkle-tree';
|
|
10
|
-
import
|
|
10
|
+
import poseidon from 'poseidon-lite';
|
|
11
|
+
import { BigNumber } from '@ethersproject/bignumber';
|
|
12
|
+
import { zeroPad } from '@ethersproject/bytes';
|
|
13
|
+
import { keccak256 } from '@ethersproject/keccak256';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates a keccak256 hash of a message compatible with the SNARK scalar modulus.
|
|
17
|
+
* @param message The message to be hashed.
|
|
18
|
+
* @returns The message digest.
|
|
19
|
+
*/
|
|
20
|
+
function hash(message) {
|
|
21
|
+
message = BigNumber.from(message).toTwos(256).toHexString();
|
|
22
|
+
message = zeroPad(message, 32);
|
|
23
|
+
return BigInt(keccak256(message)) >> BigInt(8);
|
|
24
|
+
}
|
|
11
25
|
|
|
12
26
|
var Group = /** @class */ (function () {
|
|
13
27
|
/**
|
|
14
28
|
* Initializes the group with the tree depth and the zero value.
|
|
29
|
+
* @param groupId Group identifier.
|
|
15
30
|
* @param treeDepth Tree depth.
|
|
16
|
-
* @param zeroValue Zero values for zeroes.
|
|
17
31
|
*/
|
|
18
|
-
function Group(
|
|
32
|
+
function Group(groupId, treeDepth) {
|
|
19
33
|
if (treeDepth === void 0) { treeDepth = 20; }
|
|
20
|
-
if (zeroValue === void 0) { zeroValue = BigInt(0); }
|
|
21
34
|
if (treeDepth < 16 || treeDepth > 32) {
|
|
22
35
|
throw new Error("The tree depth must be between 16 and 32");
|
|
23
36
|
}
|
|
24
|
-
this.
|
|
37
|
+
this.merkleTree = new IncrementalMerkleTree(poseidon, treeDepth, hash(groupId), 2);
|
|
25
38
|
}
|
|
26
39
|
Object.defineProperty(Group.prototype, "root", {
|
|
27
40
|
/**
|
|
@@ -29,7 +42,7 @@ var Group = /** @class */ (function () {
|
|
|
29
42
|
* @returns Root hash.
|
|
30
43
|
*/
|
|
31
44
|
get: function () {
|
|
32
|
-
return this.
|
|
45
|
+
return this.merkleTree.root;
|
|
33
46
|
},
|
|
34
47
|
enumerable: false,
|
|
35
48
|
configurable: true
|
|
@@ -40,7 +53,7 @@ var Group = /** @class */ (function () {
|
|
|
40
53
|
* @returns Tree depth.
|
|
41
54
|
*/
|
|
42
55
|
get: function () {
|
|
43
|
-
return this.
|
|
56
|
+
return this.merkleTree.depth;
|
|
44
57
|
},
|
|
45
58
|
enumerable: false,
|
|
46
59
|
configurable: true
|
|
@@ -51,7 +64,7 @@ var Group = /** @class */ (function () {
|
|
|
51
64
|
* @returns Tree zero value.
|
|
52
65
|
*/
|
|
53
66
|
get: function () {
|
|
54
|
-
return this.
|
|
67
|
+
return this.merkleTree.zeroes[0];
|
|
55
68
|
},
|
|
56
69
|
enumerable: false,
|
|
57
70
|
configurable: true
|
|
@@ -62,7 +75,7 @@ var Group = /** @class */ (function () {
|
|
|
62
75
|
* @returns List of members.
|
|
63
76
|
*/
|
|
64
77
|
get: function () {
|
|
65
|
-
return this.
|
|
78
|
+
return this.merkleTree.leaves;
|
|
66
79
|
},
|
|
67
80
|
enumerable: false,
|
|
68
81
|
configurable: true
|
|
@@ -73,47 +86,47 @@ var Group = /** @class */ (function () {
|
|
|
73
86
|
* @returns Index of the member.
|
|
74
87
|
*/
|
|
75
88
|
Group.prototype.indexOf = function (member) {
|
|
76
|
-
return this.
|
|
89
|
+
return this.merkleTree.indexOf(member);
|
|
77
90
|
};
|
|
78
91
|
/**
|
|
79
92
|
* Adds a new member to the group.
|
|
80
|
-
* @param
|
|
93
|
+
* @param member New member.
|
|
81
94
|
*/
|
|
82
|
-
Group.prototype.addMember = function (
|
|
83
|
-
this.
|
|
95
|
+
Group.prototype.addMember = function (member) {
|
|
96
|
+
this.merkleTree.insert(BigInt(member));
|
|
84
97
|
};
|
|
85
98
|
/**
|
|
86
99
|
* Adds new members to the group.
|
|
87
|
-
* @param
|
|
100
|
+
* @param members New members.
|
|
88
101
|
*/
|
|
89
|
-
Group.prototype.addMembers = function (
|
|
90
|
-
for (var _i = 0,
|
|
91
|
-
var
|
|
92
|
-
this.addMember(
|
|
102
|
+
Group.prototype.addMembers = function (members) {
|
|
103
|
+
for (var _i = 0, members_1 = members; _i < members_1.length; _i++) {
|
|
104
|
+
var member = members_1[_i];
|
|
105
|
+
this.addMember(member);
|
|
93
106
|
}
|
|
94
107
|
};
|
|
95
108
|
/**
|
|
96
109
|
* Updates a member in the group.
|
|
97
110
|
* @param index Index of the member to be updated.
|
|
98
|
-
* @param
|
|
111
|
+
* @param member New member value.
|
|
99
112
|
*/
|
|
100
|
-
Group.prototype.updateMember = function (index,
|
|
101
|
-
this.
|
|
113
|
+
Group.prototype.updateMember = function (index, member) {
|
|
114
|
+
this.merkleTree.update(index, member);
|
|
102
115
|
};
|
|
103
116
|
/**
|
|
104
117
|
* Removes a member from the group.
|
|
105
118
|
* @param index Index of the member to be removed.
|
|
106
119
|
*/
|
|
107
120
|
Group.prototype.removeMember = function (index) {
|
|
108
|
-
this.
|
|
121
|
+
this.merkleTree.delete(index);
|
|
109
122
|
};
|
|
110
123
|
/**
|
|
111
124
|
* Creates a proof of membership.
|
|
112
125
|
* @param index Index of the proof's member.
|
|
113
126
|
* @returns Proof object.
|
|
114
127
|
*/
|
|
115
|
-
Group.prototype.
|
|
116
|
-
var merkleProof = this.
|
|
128
|
+
Group.prototype.generateMerkleProof = function (index) {
|
|
129
|
+
var merkleProof = this.merkleTree.createProof(index);
|
|
117
130
|
merkleProof.siblings = merkleProof.siblings.map(function (s) { return s[0]; });
|
|
118
131
|
return merkleProof;
|
|
119
132
|
};
|
package/dist/index.node.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module @semaphore-protocol/group
|
|
3
|
-
* @version
|
|
3
|
+
* @version 3.0.0-beta.5
|
|
4
4
|
* @file A library to create and manage Semaphore groups.
|
|
5
5
|
* @copyright Ethereum Foundation 2022
|
|
6
6
|
* @license MIT
|
|
@@ -11,21 +11,38 @@
|
|
|
11
11
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
12
12
|
|
|
13
13
|
var incrementalMerkleTree = require('@zk-kit/incremental-merkle-tree');
|
|
14
|
-
var
|
|
14
|
+
var poseidon = require('poseidon-lite');
|
|
15
|
+
var bignumber = require('@ethersproject/bignumber');
|
|
16
|
+
var bytes = require('@ethersproject/bytes');
|
|
17
|
+
var keccak256 = require('@ethersproject/keccak256');
|
|
18
|
+
|
|
19
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
20
|
+
|
|
21
|
+
var poseidon__default = /*#__PURE__*/_interopDefaultLegacy(poseidon);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Creates a keccak256 hash of a message compatible with the SNARK scalar modulus.
|
|
25
|
+
* @param message The message to be hashed.
|
|
26
|
+
* @returns The message digest.
|
|
27
|
+
*/
|
|
28
|
+
function hash(message) {
|
|
29
|
+
message = bignumber.BigNumber.from(message).toTwos(256).toHexString();
|
|
30
|
+
message = bytes.zeroPad(message, 32);
|
|
31
|
+
return BigInt(keccak256.keccak256(message)) >> BigInt(8);
|
|
32
|
+
}
|
|
15
33
|
|
|
16
34
|
var Group = /** @class */ (function () {
|
|
17
35
|
/**
|
|
18
36
|
* Initializes the group with the tree depth and the zero value.
|
|
37
|
+
* @param groupId Group identifier.
|
|
19
38
|
* @param treeDepth Tree depth.
|
|
20
|
-
* @param zeroValue Zero values for zeroes.
|
|
21
39
|
*/
|
|
22
|
-
function Group(
|
|
40
|
+
function Group(groupId, treeDepth) {
|
|
23
41
|
if (treeDepth === void 0) { treeDepth = 20; }
|
|
24
|
-
if (zeroValue === void 0) { zeroValue = BigInt(0); }
|
|
25
42
|
if (treeDepth < 16 || treeDepth > 32) {
|
|
26
43
|
throw new Error("The tree depth must be between 16 and 32");
|
|
27
44
|
}
|
|
28
|
-
this.
|
|
45
|
+
this.merkleTree = new incrementalMerkleTree.IncrementalMerkleTree(poseidon__default["default"], treeDepth, hash(groupId), 2);
|
|
29
46
|
}
|
|
30
47
|
Object.defineProperty(Group.prototype, "root", {
|
|
31
48
|
/**
|
|
@@ -33,7 +50,7 @@ var Group = /** @class */ (function () {
|
|
|
33
50
|
* @returns Root hash.
|
|
34
51
|
*/
|
|
35
52
|
get: function () {
|
|
36
|
-
return this.
|
|
53
|
+
return this.merkleTree.root;
|
|
37
54
|
},
|
|
38
55
|
enumerable: false,
|
|
39
56
|
configurable: true
|
|
@@ -44,7 +61,7 @@ var Group = /** @class */ (function () {
|
|
|
44
61
|
* @returns Tree depth.
|
|
45
62
|
*/
|
|
46
63
|
get: function () {
|
|
47
|
-
return this.
|
|
64
|
+
return this.merkleTree.depth;
|
|
48
65
|
},
|
|
49
66
|
enumerable: false,
|
|
50
67
|
configurable: true
|
|
@@ -55,7 +72,7 @@ var Group = /** @class */ (function () {
|
|
|
55
72
|
* @returns Tree zero value.
|
|
56
73
|
*/
|
|
57
74
|
get: function () {
|
|
58
|
-
return this.
|
|
75
|
+
return this.merkleTree.zeroes[0];
|
|
59
76
|
},
|
|
60
77
|
enumerable: false,
|
|
61
78
|
configurable: true
|
|
@@ -66,7 +83,7 @@ var Group = /** @class */ (function () {
|
|
|
66
83
|
* @returns List of members.
|
|
67
84
|
*/
|
|
68
85
|
get: function () {
|
|
69
|
-
return this.
|
|
86
|
+
return this.merkleTree.leaves;
|
|
70
87
|
},
|
|
71
88
|
enumerable: false,
|
|
72
89
|
configurable: true
|
|
@@ -77,47 +94,47 @@ var Group = /** @class */ (function () {
|
|
|
77
94
|
* @returns Index of the member.
|
|
78
95
|
*/
|
|
79
96
|
Group.prototype.indexOf = function (member) {
|
|
80
|
-
return this.
|
|
97
|
+
return this.merkleTree.indexOf(member);
|
|
81
98
|
};
|
|
82
99
|
/**
|
|
83
100
|
* Adds a new member to the group.
|
|
84
|
-
* @param
|
|
101
|
+
* @param member New member.
|
|
85
102
|
*/
|
|
86
|
-
Group.prototype.addMember = function (
|
|
87
|
-
this.
|
|
103
|
+
Group.prototype.addMember = function (member) {
|
|
104
|
+
this.merkleTree.insert(BigInt(member));
|
|
88
105
|
};
|
|
89
106
|
/**
|
|
90
107
|
* Adds new members to the group.
|
|
91
|
-
* @param
|
|
108
|
+
* @param members New members.
|
|
92
109
|
*/
|
|
93
|
-
Group.prototype.addMembers = function (
|
|
94
|
-
for (var _i = 0,
|
|
95
|
-
var
|
|
96
|
-
this.addMember(
|
|
110
|
+
Group.prototype.addMembers = function (members) {
|
|
111
|
+
for (var _i = 0, members_1 = members; _i < members_1.length; _i++) {
|
|
112
|
+
var member = members_1[_i];
|
|
113
|
+
this.addMember(member);
|
|
97
114
|
}
|
|
98
115
|
};
|
|
99
116
|
/**
|
|
100
117
|
* Updates a member in the group.
|
|
101
118
|
* @param index Index of the member to be updated.
|
|
102
|
-
* @param
|
|
119
|
+
* @param member New member value.
|
|
103
120
|
*/
|
|
104
|
-
Group.prototype.updateMember = function (index,
|
|
105
|
-
this.
|
|
121
|
+
Group.prototype.updateMember = function (index, member) {
|
|
122
|
+
this.merkleTree.update(index, member);
|
|
106
123
|
};
|
|
107
124
|
/**
|
|
108
125
|
* Removes a member from the group.
|
|
109
126
|
* @param index Index of the member to be removed.
|
|
110
127
|
*/
|
|
111
128
|
Group.prototype.removeMember = function (index) {
|
|
112
|
-
this.
|
|
129
|
+
this.merkleTree.delete(index);
|
|
113
130
|
};
|
|
114
131
|
/**
|
|
115
132
|
* Creates a proof of membership.
|
|
116
133
|
* @param index Index of the proof's member.
|
|
117
134
|
* @returns Proof object.
|
|
118
135
|
*/
|
|
119
|
-
Group.prototype.
|
|
120
|
-
var merkleProof = this.
|
|
136
|
+
Group.prototype.generateMerkleProof = function (index) {
|
|
137
|
+
var merkleProof = this.merkleTree.createProof(index);
|
|
121
138
|
merkleProof.siblings = merkleProof.siblings.map(function (s) { return s[0]; });
|
|
122
139
|
return merkleProof;
|
|
123
140
|
};
|
package/dist/types/group.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { MerkleProof } from "@zk-kit/incremental-merkle-tree";
|
|
1
|
+
import { IncrementalMerkleTree, MerkleProof } from "@zk-kit/incremental-merkle-tree";
|
|
2
2
|
import { Member } from "./types";
|
|
3
3
|
export default class Group {
|
|
4
|
-
|
|
4
|
+
merkleTree: IncrementalMerkleTree;
|
|
5
5
|
/**
|
|
6
6
|
* Initializes the group with the tree depth and the zero value.
|
|
7
|
+
* @param groupId Group identifier.
|
|
7
8
|
* @param treeDepth Tree depth.
|
|
8
|
-
* @param zeroValue Zero values for zeroes.
|
|
9
9
|
*/
|
|
10
|
-
constructor(
|
|
10
|
+
constructor(groupId: Member, treeDepth?: number);
|
|
11
11
|
/**
|
|
12
12
|
* Returns the root hash of the tree.
|
|
13
13
|
* @returns Root hash.
|
|
@@ -36,20 +36,20 @@ export default class Group {
|
|
|
36
36
|
indexOf(member: Member): number;
|
|
37
37
|
/**
|
|
38
38
|
* Adds a new member to the group.
|
|
39
|
-
* @param
|
|
39
|
+
* @param member New member.
|
|
40
40
|
*/
|
|
41
|
-
addMember(
|
|
41
|
+
addMember(member: Member): void;
|
|
42
42
|
/**
|
|
43
43
|
* Adds new members to the group.
|
|
44
|
-
* @param
|
|
44
|
+
* @param members New members.
|
|
45
45
|
*/
|
|
46
|
-
addMembers(
|
|
46
|
+
addMembers(members: Member[]): void;
|
|
47
47
|
/**
|
|
48
48
|
* Updates a member in the group.
|
|
49
49
|
* @param index Index of the member to be updated.
|
|
50
|
-
* @param
|
|
50
|
+
* @param member New member value.
|
|
51
51
|
*/
|
|
52
|
-
updateMember(index: number,
|
|
52
|
+
updateMember(index: number, member: Member): void;
|
|
53
53
|
/**
|
|
54
54
|
* Removes a member from the group.
|
|
55
55
|
* @param index Index of the member to be removed.
|
|
@@ -60,5 +60,5 @@ export default class Group {
|
|
|
60
60
|
* @param index Index of the proof's member.
|
|
61
61
|
* @returns Proof object.
|
|
62
62
|
*/
|
|
63
|
-
|
|
63
|
+
generateMerkleProof(index: number): MerkleProof;
|
|
64
64
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { BytesLike, Hexable } from "@ethersproject/bytes";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a keccak256 hash of a message compatible with the SNARK scalar modulus.
|
|
4
|
+
* @param message The message to be hashed.
|
|
5
|
+
* @returns The message digest.
|
|
6
|
+
*/
|
|
7
|
+
export default function hash(message: BytesLike | Hexable | number | bigint): bigint;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type Member = string | number | bigint;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@semaphore-protocol/group",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-beta.5",
|
|
4
4
|
"description": "A library to create and manage Semaphore groups.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.node.js",
|
|
@@ -35,7 +35,10 @@
|
|
|
35
35
|
"typedoc": "^0.22.11"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
+
"@ethersproject/bignumber": "^5.7.0",
|
|
39
|
+
"@ethersproject/bytes": "^5.7.0",
|
|
40
|
+
"@ethersproject/keccak256": "^5.7.0",
|
|
38
41
|
"@zk-kit/incremental-merkle-tree": "1.0.0",
|
|
39
|
-
"
|
|
42
|
+
"poseidon-lite": "^0.0.2"
|
|
40
43
|
}
|
|
41
44
|
}
|
package/src/group.test.ts
CHANGED
|
@@ -1,35 +1,36 @@
|
|
|
1
1
|
import Group from "./group"
|
|
2
|
+
import hash from "./hash"
|
|
2
3
|
|
|
3
4
|
describe("Group", () => {
|
|
4
5
|
describe("# Group", () => {
|
|
5
6
|
it("Should create a group", () => {
|
|
6
|
-
const group = new Group()
|
|
7
|
+
const group = new Group(1)
|
|
7
8
|
|
|
8
|
-
expect(group.root.toString()).toContain("
|
|
9
|
+
expect(group.root.toString()).toContain("103543")
|
|
9
10
|
expect(group.depth).toBe(20)
|
|
10
|
-
expect(group.zeroValue).toBe(
|
|
11
|
+
expect(group.zeroValue).toBe(hash(1))
|
|
11
12
|
expect(group.members).toHaveLength(0)
|
|
12
13
|
})
|
|
13
14
|
|
|
14
15
|
it("Should not create a group with a wrong tree depth", () => {
|
|
15
|
-
const fun = () => new Group(33)
|
|
16
|
+
const fun = () => new Group(1, 33)
|
|
16
17
|
|
|
17
18
|
expect(fun).toThrow("The tree depth must be between 16 and 32")
|
|
18
19
|
})
|
|
19
20
|
|
|
20
21
|
it("Should create a group with different parameters", () => {
|
|
21
|
-
const group = new Group(
|
|
22
|
+
const group = new Group(1, 32)
|
|
22
23
|
|
|
23
|
-
expect(group.root.toString()).toContain("
|
|
24
|
+
expect(group.root.toString()).toContain("460373")
|
|
24
25
|
expect(group.depth).toBe(32)
|
|
25
|
-
expect(group.zeroValue).toBe(
|
|
26
|
+
expect(group.zeroValue).toBe(hash(1))
|
|
26
27
|
expect(group.members).toHaveLength(0)
|
|
27
28
|
})
|
|
28
29
|
})
|
|
29
30
|
|
|
30
31
|
describe("# addMember", () => {
|
|
31
32
|
it("Should add a member to a group", () => {
|
|
32
|
-
const group = new Group()
|
|
33
|
+
const group = new Group(1)
|
|
33
34
|
|
|
34
35
|
group.addMember(BigInt(3))
|
|
35
36
|
|
|
@@ -39,7 +40,7 @@ describe("Group", () => {
|
|
|
39
40
|
|
|
40
41
|
describe("# addMembers", () => {
|
|
41
42
|
it("Should add many members to a group", () => {
|
|
42
|
-
const group = new Group()
|
|
43
|
+
const group = new Group(1)
|
|
43
44
|
|
|
44
45
|
group.addMembers([BigInt(1), BigInt(3)])
|
|
45
46
|
|
|
@@ -49,7 +50,7 @@ describe("Group", () => {
|
|
|
49
50
|
|
|
50
51
|
describe("# indexOf", () => {
|
|
51
52
|
it("Should return the index of a member in a group", () => {
|
|
52
|
-
const group = new Group()
|
|
53
|
+
const group = new Group(1)
|
|
53
54
|
group.addMembers([BigInt(1), BigInt(3)])
|
|
54
55
|
|
|
55
56
|
const index = group.indexOf(BigInt(3))
|
|
@@ -60,7 +61,7 @@ describe("Group", () => {
|
|
|
60
61
|
|
|
61
62
|
describe("# updateMember", () => {
|
|
62
63
|
it("Should update a member in a group", () => {
|
|
63
|
-
const group = new Group()
|
|
64
|
+
const group = new Group(1)
|
|
64
65
|
group.addMembers([BigInt(1), BigInt(3)])
|
|
65
66
|
|
|
66
67
|
group.updateMember(0, BigInt(1))
|
|
@@ -72,7 +73,7 @@ describe("Group", () => {
|
|
|
72
73
|
|
|
73
74
|
describe("# removeMember", () => {
|
|
74
75
|
it("Should remove a member from a group", () => {
|
|
75
|
-
const group = new Group()
|
|
76
|
+
const group = new Group(1)
|
|
76
77
|
group.addMembers([BigInt(1), BigInt(3)])
|
|
77
78
|
|
|
78
79
|
group.removeMember(0)
|
|
@@ -82,12 +83,12 @@ describe("Group", () => {
|
|
|
82
83
|
})
|
|
83
84
|
})
|
|
84
85
|
|
|
85
|
-
describe("#
|
|
86
|
+
describe("# generateMerkleProof", () => {
|
|
86
87
|
it("Should generate a proof of membership", () => {
|
|
87
|
-
const group = new Group()
|
|
88
|
+
const group = new Group(1)
|
|
88
89
|
group.addMembers([BigInt(1), BigInt(3)])
|
|
89
90
|
|
|
90
|
-
const proof = group.
|
|
91
|
+
const proof = group.generateMerkleProof(0)
|
|
91
92
|
|
|
92
93
|
expect(proof.leaf).toBe(BigInt(1))
|
|
93
94
|
})
|
package/src/group.ts
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import { IncrementalMerkleTree, MerkleProof } from "@zk-kit/incremental-merkle-tree"
|
|
2
|
-
import
|
|
2
|
+
import poseidon from "poseidon-lite"
|
|
3
|
+
import hash from "./hash"
|
|
3
4
|
import { Member } from "./types"
|
|
4
5
|
|
|
5
6
|
export default class Group {
|
|
6
|
-
|
|
7
|
+
merkleTree: IncrementalMerkleTree
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Initializes the group with the tree depth and the zero value.
|
|
11
|
+
* @param groupId Group identifier.
|
|
10
12
|
* @param treeDepth Tree depth.
|
|
11
|
-
* @param zeroValue Zero values for zeroes.
|
|
12
13
|
*/
|
|
13
|
-
constructor(
|
|
14
|
+
constructor(groupId: Member, treeDepth = 20) {
|
|
14
15
|
if (treeDepth < 16 || treeDepth > 32) {
|
|
15
16
|
throw new Error("The tree depth must be between 16 and 32")
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
this.
|
|
19
|
+
this.merkleTree = new IncrementalMerkleTree(poseidon, treeDepth, hash(groupId), 2)
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
/**
|
|
@@ -23,7 +24,7 @@ export default class Group {
|
|
|
23
24
|
* @returns Root hash.
|
|
24
25
|
*/
|
|
25
26
|
get root(): Member {
|
|
26
|
-
return this.
|
|
27
|
+
return this.merkleTree.root
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
/**
|
|
@@ -31,7 +32,7 @@ export default class Group {
|
|
|
31
32
|
* @returns Tree depth.
|
|
32
33
|
*/
|
|
33
34
|
get depth(): number {
|
|
34
|
-
return this.
|
|
35
|
+
return this.merkleTree.depth
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
/**
|
|
@@ -39,7 +40,7 @@ export default class Group {
|
|
|
39
40
|
* @returns Tree zero value.
|
|
40
41
|
*/
|
|
41
42
|
get zeroValue(): Member {
|
|
42
|
-
return this.
|
|
43
|
+
return this.merkleTree.zeroes[0]
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
/**
|
|
@@ -47,7 +48,7 @@ export default class Group {
|
|
|
47
48
|
* @returns List of members.
|
|
48
49
|
*/
|
|
49
50
|
get members(): Member[] {
|
|
50
|
-
return this.
|
|
51
|
+
return this.merkleTree.leaves
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
/**
|
|
@@ -56,34 +57,34 @@ export default class Group {
|
|
|
56
57
|
* @returns Index of the member.
|
|
57
58
|
*/
|
|
58
59
|
indexOf(member: Member): number {
|
|
59
|
-
return this.
|
|
60
|
+
return this.merkleTree.indexOf(member)
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
/**
|
|
63
64
|
* Adds a new member to the group.
|
|
64
|
-
* @param
|
|
65
|
+
* @param member New member.
|
|
65
66
|
*/
|
|
66
|
-
addMember(
|
|
67
|
-
this.
|
|
67
|
+
addMember(member: Member) {
|
|
68
|
+
this.merkleTree.insert(BigInt(member))
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
/**
|
|
71
72
|
* Adds new members to the group.
|
|
72
|
-
* @param
|
|
73
|
+
* @param members New members.
|
|
73
74
|
*/
|
|
74
|
-
addMembers(
|
|
75
|
-
for (const
|
|
76
|
-
this.addMember(
|
|
75
|
+
addMembers(members: Member[]) {
|
|
76
|
+
for (const member of members) {
|
|
77
|
+
this.addMember(member)
|
|
77
78
|
}
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
/**
|
|
81
82
|
* Updates a member in the group.
|
|
82
83
|
* @param index Index of the member to be updated.
|
|
83
|
-
* @param
|
|
84
|
+
* @param member New member value.
|
|
84
85
|
*/
|
|
85
|
-
updateMember(index: number,
|
|
86
|
-
this.
|
|
86
|
+
updateMember(index: number, member: Member) {
|
|
87
|
+
this.merkleTree.update(index, member)
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
/**
|
|
@@ -91,7 +92,7 @@ export default class Group {
|
|
|
91
92
|
* @param index Index of the member to be removed.
|
|
92
93
|
*/
|
|
93
94
|
removeMember(index: number) {
|
|
94
|
-
this.
|
|
95
|
+
this.merkleTree.delete(index)
|
|
95
96
|
}
|
|
96
97
|
|
|
97
98
|
/**
|
|
@@ -99,8 +100,8 @@ export default class Group {
|
|
|
99
100
|
* @param index Index of the proof's member.
|
|
100
101
|
* @returns Proof object.
|
|
101
102
|
*/
|
|
102
|
-
|
|
103
|
-
const merkleProof = this.
|
|
103
|
+
generateMerkleProof(index: number): MerkleProof {
|
|
104
|
+
const merkleProof = this.merkleTree.createProof(index)
|
|
104
105
|
|
|
105
106
|
merkleProof.siblings = merkleProof.siblings.map((s) => s[0])
|
|
106
107
|
|
package/src/hash.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BigNumber } from "@ethersproject/bignumber"
|
|
2
|
+
import { BytesLike, Hexable, zeroPad } from "@ethersproject/bytes"
|
|
3
|
+
import { keccak256 } from "@ethersproject/keccak256"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates a keccak256 hash of a message compatible with the SNARK scalar modulus.
|
|
7
|
+
* @param message The message to be hashed.
|
|
8
|
+
* @returns The message digest.
|
|
9
|
+
*/
|
|
10
|
+
export default function hash(message: BytesLike | Hexable | number | bigint): bigint {
|
|
11
|
+
message = BigNumber.from(message).toTwos(256).toHexString()
|
|
12
|
+
message = zeroPad(message, 32)
|
|
13
|
+
|
|
14
|
+
return BigInt(keccak256(message)) >> BigInt(8)
|
|
15
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export type Member = string | bigint
|
|
1
|
+
export type Member = string | number | bigint
|