/
utils.ts
172 lines (161 loc) · 4.75 KB
/
utils.ts
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import {
hash5,
hashLeftRight,
SparseMerkleTree,
SnarkBigInt,
stringifyBigInts,
unstringifyBigInts,
} from '@unirep/crypto'
import Reputation from './Reputation'
import {
EPOCH_KEY_NULLIFIER_DOMAIN,
REPUTATION_NULLIFIER_DOMAIN,
} from '../config/nullifierDomainSeparator'
import {
formatProofForSnarkjsVerification,
EPOCH_TREE_DEPTH,
} from '@unirep/circuits'
/**
* Encode a `BigInt` array to string
* @param arr The array of `BigInt` elements
* @returns A string of the array
*/
export const encodeBigIntArray = (arr: BigInt[]): string => {
return JSON.stringify(stringifyBigInts(arr))
}
/**
* Decode an encoded string to a `BigInt` array
* @param input The string of the encoded data
* @returns The `bigint` array
*/
export const decodeBigIntArray = (input: string): bigint[] => {
return unstringifyBigInts(JSON.parse(input))
}
/**
* Default user state tree leaf is defined by `hash(posRep=0, negRep=0, graffiti=0, signUp=0)`
*/
const defaultUserStateLeaf = hash5([
BigInt(0),
BigInt(0),
BigInt(0),
BigInt(0),
BigInt(0),
])
/**
* Definition of default epoch tree leaf
*/
const SMT_ONE_LEAF = hashLeftRight(BigInt(1), BigInt(0))
/**
* Compute the empty user state tree root where the default leaves are `defaultUserStateLeaf`
* @param treeDepth The depth of the user state tree
* @returns The root of the user state tree
*/
const computeEmptyUserStateRoot = (treeDepth: number): BigInt => {
const t = new SparseMerkleTree(treeDepth, defaultUserStateLeaf)
return t.root
}
/**
* Compute the user state tree root with given attester ID and airdrop positive reputation
* @param treeDepth The depth of the user state tree
* @param leafIdx The attester ID, which is the index of the user state tree.
* @param airdropPosRep The airdrop positive reputation that is set by the attester
* @returns The root of the user state tree
*/
const computeInitUserStateRoot = (
treeDepth: number,
leafIdx?: number,
airdropPosRep: number = 0
): BigInt => {
const t = new SparseMerkleTree(treeDepth, defaultUserStateLeaf)
if (typeof leafIdx === 'number' && leafIdx > 0) {
const airdropReputation = new Reputation(
BigInt(airdropPosRep),
BigInt(0),
BigInt(0),
BigInt(1)
)
const leafValue = airdropReputation.hash()
t.update(BigInt(leafIdx), leafValue)
}
return t.root
}
/**
* Compute the epoch key of given identity, epoch and nonce
* @param identityNullifier The identity nullifier of the semaphore identity
* @param epoch The epoch of the epoch key
* @param nonce The nonce of the epoch key
* @param epochTreeDepth The depth of the epoch tree
* @returns The moded epoch key
*/
const genEpochKey = (
identityNullifier: SnarkBigInt,
epoch: number,
nonce: number,
epochTreeDepth: number = EPOCH_TREE_DEPTH
): SnarkBigInt => {
const values: any[] = [
identityNullifier,
epoch,
nonce,
BigInt(0),
BigInt(0),
]
let epochKey = hash5(values).valueOf()
// Adjust epoch key size according to epoch tree depth
const epochKeyModed = epochKey % BigInt(2 ** epochTreeDepth)
return epochKeyModed
}
/**
* Compute the epoch key nullifier of given identity, epoch and nonce. The epoch key
* nullifiers are used to prevent double user state transition.
* @param identityNullifier The identity nullifier of the semaphore identity
* @param epoch The epoch of the epoch key
* @param nonce The nonce of the epoch key
* @returns The epoch key nullifier
*/
const genEpochKeyNullifier = (
identityNullifier: SnarkBigInt,
epoch: number,
nonce: number
): SnarkBigInt => {
return hash5([
EPOCH_KEY_NULLIFIER_DOMAIN,
identityNullifier,
BigInt(epoch),
BigInt(nonce),
BigInt(0),
])
}
/**
* Compute the reputation nullifier of given identity, epoch, nonce and attester ID.
* The reputation nullifiers are used to prevent double spending of reputation.
* @param identityNullifier The identity nullifier of the semaphore identity
* @param epoch The epoch of the epoch key
* @param nonce The nonce of the epoch key
* @param attesterId The attester ID of the reputation
* @returns The reputation nullifier
*/
const genReputationNullifier = (
identityNullifier: SnarkBigInt,
epoch: number,
nonce: number,
attesterId: BigInt
): SnarkBigInt => {
return hash5([
REPUTATION_NULLIFIER_DOMAIN,
identityNullifier,
BigInt(epoch),
BigInt(nonce),
attesterId,
])
}
export {
defaultUserStateLeaf,
SMT_ONE_LEAF,
computeEmptyUserStateRoot,
computeInitUserStateRoot,
formatProofForSnarkjsVerification,
genEpochKey,
genEpochKeyNullifier,
genReputationNullifier,
}