zkjson 0.7.1 → 0.8.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/cjs/circomlibjs/SMT.js +481 -0
- package/cjs/circomlibjs/SMTMemDb.js +173 -0
- package/cjs/circomlibjs/buildPoseidon.js +162 -0
- package/cjs/circomlibjs/buildPoseidonWasm.js +124 -0
- package/cjs/circomlibjs/getHashes.js +220 -0
- package/cjs/circomlibjs/poseidonConstants$1.js +1 -0
- package/cjs/circomlibjs.js +6 -6
- package/cjs/collection.js +2 -2
- package/cjs/collection_tree.js +148 -0
- package/cjs/db.js +2 -2
- package/cjs/db_tree.js +398 -0
- package/cjs/index.js +16 -0
- package/cjs/newMemEmptyTrie.js +42 -0
- package/esm/circomlibjs/SMT.js +349 -0
- package/esm/circomlibjs/SMTMemDb.js +69 -0
- package/esm/circomlibjs/buildPoseidon.js +113 -0
- package/esm/circomlibjs/buildPoseidonWasm.js +445 -0
- package/esm/circomlibjs/getHashes.js +515 -0
- package/esm/circomlibjs/poseidonConstants$1.js +24806 -0
- package/esm/circomlibjs.js +70 -25385
- package/esm/collection.js +1 -1
- package/esm/collection_tree.js +43 -0
- package/esm/db.js +1 -1
- package/esm/db_tree.js +122 -0
- package/esm/index.js +3 -1
- package/esm/newMemEmptyTrie.js +11 -0
- package/package.json +1 -1
@@ -0,0 +1,349 @@
|
|
1
|
+
import * as ffjavascript from "ffjavascript"
|
2
|
+
import buildPoseidon from "./buildPoseidon.js"
|
3
|
+
import { splitEvery } from "ramda"
|
4
|
+
export default class SMT {
|
5
|
+
constructor(db, root, hash0, hash1, F) {
|
6
|
+
this.db = db
|
7
|
+
this.root = root
|
8
|
+
this.hash0 = hash0
|
9
|
+
this.hash1 = hash1
|
10
|
+
this.F = F
|
11
|
+
}
|
12
|
+
|
13
|
+
_splitBits(_key) {
|
14
|
+
const F = this.F
|
15
|
+
const res = ffjavascript.Scalar.bits(F.toObject(_key))
|
16
|
+
|
17
|
+
while (res.length < 256) res.push(false)
|
18
|
+
|
19
|
+
return res
|
20
|
+
}
|
21
|
+
|
22
|
+
async update(_key, _newValue) {
|
23
|
+
this.poseidon ??= await buildPoseidon()
|
24
|
+
this.zero ??= this.poseidon([
|
25
|
+
"0",
|
26
|
+
"0",
|
27
|
+
"0",
|
28
|
+
"0",
|
29
|
+
"0",
|
30
|
+
"0",
|
31
|
+
"0",
|
32
|
+
"0",
|
33
|
+
"0",
|
34
|
+
"0",
|
35
|
+
"0",
|
36
|
+
"0",
|
37
|
+
"0",
|
38
|
+
"0",
|
39
|
+
"0",
|
40
|
+
"0",
|
41
|
+
])
|
42
|
+
let _hash_value = _newValue
|
43
|
+
if (_newValue.length === 256) {
|
44
|
+
_hash_value = []
|
45
|
+
for (let v of splitEvery(16, _newValue)) {
|
46
|
+
const value =
|
47
|
+
v.join("") === "0000000000000000" ? this.zero : this.poseidon(v)
|
48
|
+
_hash_value.push(value)
|
49
|
+
}
|
50
|
+
}
|
51
|
+
const newValue = this.poseidon(_hash_value)
|
52
|
+
const F = this.F
|
53
|
+
const key = F.e(_key)
|
54
|
+
const resFind = await this.find(key)
|
55
|
+
const res = {}
|
56
|
+
res.oldRoot = this.root
|
57
|
+
res.oldKey = key
|
58
|
+
res.oldValue = resFind.foundValue
|
59
|
+
res.newKey = key
|
60
|
+
res.newValue = newValue
|
61
|
+
res.siblings = resFind.siblings
|
62
|
+
|
63
|
+
const ins = []
|
64
|
+
const dels = []
|
65
|
+
|
66
|
+
let rtOld = this.hash1(key, resFind.foundValue)
|
67
|
+
let rtNew = this.hash1(key, newValue)
|
68
|
+
ins.push([rtNew, [1, key, newValue]])
|
69
|
+
dels.push(rtOld)
|
70
|
+
|
71
|
+
const keyBits = this._splitBits(key)
|
72
|
+
for (let level = resFind.siblings.length - 1; level >= 0; level--) {
|
73
|
+
let oldNode, newNode
|
74
|
+
const sibling = resFind.siblings[level]
|
75
|
+
if (keyBits[level]) {
|
76
|
+
oldNode = [sibling, rtOld]
|
77
|
+
newNode = [sibling, rtNew]
|
78
|
+
} else {
|
79
|
+
oldNode = [rtOld, sibling]
|
80
|
+
newNode = [rtNew, sibling]
|
81
|
+
}
|
82
|
+
rtOld = this.hash0(oldNode[0], oldNode[1])
|
83
|
+
rtNew = this.hash0(newNode[0], newNode[1])
|
84
|
+
dels.push(rtOld)
|
85
|
+
ins.push([rtNew, newNode])
|
86
|
+
}
|
87
|
+
|
88
|
+
res.newRoot = rtNew
|
89
|
+
|
90
|
+
await this.db.multiDel(dels)
|
91
|
+
await this.db.multiIns(ins)
|
92
|
+
await this.db.setRoot(rtNew)
|
93
|
+
this.root = rtNew
|
94
|
+
|
95
|
+
return res
|
96
|
+
}
|
97
|
+
|
98
|
+
async delete(_key) {
|
99
|
+
const F = this.F
|
100
|
+
const key = F.e(_key)
|
101
|
+
|
102
|
+
const resFind = await this.find(key)
|
103
|
+
if (!resFind.found) throw new Error("Key does not exists")
|
104
|
+
|
105
|
+
const res = {
|
106
|
+
siblings: [],
|
107
|
+
delKey: key,
|
108
|
+
delValue: resFind.foundValue,
|
109
|
+
}
|
110
|
+
|
111
|
+
const dels = []
|
112
|
+
const ins = []
|
113
|
+
let rtOld = this.hash1(key, resFind.foundValue)
|
114
|
+
let rtNew
|
115
|
+
dels.push(rtOld)
|
116
|
+
|
117
|
+
let mixed
|
118
|
+
if (resFind.siblings.length > 0) {
|
119
|
+
const record = await this.db.get(
|
120
|
+
resFind.siblings[resFind.siblings.length - 1],
|
121
|
+
)
|
122
|
+
if (record.length == 3 && F.eq(record[0], F.one)) {
|
123
|
+
mixed = false
|
124
|
+
res.oldKey = record[1]
|
125
|
+
res.oldValue = record[2]
|
126
|
+
res.isOld0 = false
|
127
|
+
rtNew = resFind.siblings[resFind.siblings.length - 1]
|
128
|
+
} else if (record.length == 2) {
|
129
|
+
mixed = true
|
130
|
+
res.oldKey = key
|
131
|
+
res.oldValue = F.zero
|
132
|
+
res.isOld0 = true
|
133
|
+
rtNew = F.zero
|
134
|
+
} else {
|
135
|
+
throw new Error("Invalid node. Database corrupted")
|
136
|
+
}
|
137
|
+
} else {
|
138
|
+
rtNew = F.zero
|
139
|
+
res.oldKey = key
|
140
|
+
res.oldValue = F.zero
|
141
|
+
res.isOld0 = true
|
142
|
+
}
|
143
|
+
|
144
|
+
const keyBits = this._splitBits(key)
|
145
|
+
|
146
|
+
for (let level = resFind.siblings.length - 1; level >= 0; level--) {
|
147
|
+
let newSibling = resFind.siblings[level]
|
148
|
+
if (level == resFind.siblings.length - 1 && !res.isOld0) {
|
149
|
+
newSibling = F.zero
|
150
|
+
}
|
151
|
+
const oldSibling = resFind.siblings[level]
|
152
|
+
if (keyBits[level]) {
|
153
|
+
rtOld = this.hash0(oldSibling, rtOld)
|
154
|
+
} else {
|
155
|
+
rtOld = this.hash0(rtOld, oldSibling)
|
156
|
+
}
|
157
|
+
dels.push(rtOld)
|
158
|
+
if (!F.isZero(newSibling)) {
|
159
|
+
mixed = true
|
160
|
+
}
|
161
|
+
|
162
|
+
if (mixed) {
|
163
|
+
res.siblings.unshift(resFind.siblings[level])
|
164
|
+
let newNode
|
165
|
+
if (keyBits[level]) {
|
166
|
+
newNode = [newSibling, rtNew]
|
167
|
+
} else {
|
168
|
+
newNode = [rtNew, newSibling]
|
169
|
+
}
|
170
|
+
rtNew = this.hash0(newNode[0], newNode[1])
|
171
|
+
ins.push([rtNew, newNode])
|
172
|
+
}
|
173
|
+
}
|
174
|
+
|
175
|
+
await this.db.multiIns(ins)
|
176
|
+
await this.db.setRoot(rtNew)
|
177
|
+
this.root = rtNew
|
178
|
+
await this.db.multiDel(dels)
|
179
|
+
|
180
|
+
res.newRoot = rtNew
|
181
|
+
res.oldRoot = rtOld
|
182
|
+
|
183
|
+
return res
|
184
|
+
}
|
185
|
+
|
186
|
+
async insert(_key, _value) {
|
187
|
+
this.poseidon ??= await buildPoseidon()
|
188
|
+
this.zero ??= this.poseidon([
|
189
|
+
"0",
|
190
|
+
"0",
|
191
|
+
"0",
|
192
|
+
"0",
|
193
|
+
"0",
|
194
|
+
"0",
|
195
|
+
"0",
|
196
|
+
"0",
|
197
|
+
"0",
|
198
|
+
"0",
|
199
|
+
"0",
|
200
|
+
"0",
|
201
|
+
"0",
|
202
|
+
"0",
|
203
|
+
"0",
|
204
|
+
"0",
|
205
|
+
])
|
206
|
+
let _hash_value = _value
|
207
|
+
if (_value.length === 256) {
|
208
|
+
_hash_value = []
|
209
|
+
for (let v of splitEvery(16, _value)) {
|
210
|
+
const value =
|
211
|
+
v.join("") === "0000000000000000" ? this.zero : this.poseidon(v)
|
212
|
+
_hash_value.push(value)
|
213
|
+
}
|
214
|
+
}
|
215
|
+
|
216
|
+
const value = this.poseidon(_hash_value)
|
217
|
+
const F = this.F
|
218
|
+
const key = F.e(_key)
|
219
|
+
let addedOne = false
|
220
|
+
const res = {}
|
221
|
+
res.oldRoot = this.root
|
222
|
+
const newKeyBits = this._splitBits(key)
|
223
|
+
|
224
|
+
let rtOld
|
225
|
+
|
226
|
+
const resFind = await this.find(key)
|
227
|
+
if (resFind.found) throw new Error("Key already exists")
|
228
|
+
|
229
|
+
res.siblings = resFind.siblings
|
230
|
+
let mixed
|
231
|
+
|
232
|
+
if (!resFind.isOld0) {
|
233
|
+
const oldKeyits = this._splitBits(resFind.notFoundKey)
|
234
|
+
for (let i = res.siblings.length; oldKeyits[i] == newKeyBits[i]; i++) {
|
235
|
+
res.siblings.push(F.zero)
|
236
|
+
}
|
237
|
+
rtOld = this.hash1(resFind.notFoundKey, resFind.notFoundValue)
|
238
|
+
res.siblings.push(rtOld)
|
239
|
+
addedOne = true
|
240
|
+
mixed = false
|
241
|
+
} else if (res.siblings.length > 0) {
|
242
|
+
mixed = true
|
243
|
+
rtOld = F.zero
|
244
|
+
}
|
245
|
+
|
246
|
+
const inserts = []
|
247
|
+
const dels = []
|
248
|
+
|
249
|
+
let rt = this.hash1(key, value)
|
250
|
+
inserts.push([rt, [1, key, value]])
|
251
|
+
|
252
|
+
for (let i = res.siblings.length - 1; i >= 0; i--) {
|
253
|
+
if (i < res.siblings.length - 1 && !F.isZero(res.siblings[i])) {
|
254
|
+
mixed = true
|
255
|
+
}
|
256
|
+
if (mixed) {
|
257
|
+
const oldSibling = resFind.siblings[i]
|
258
|
+
if (newKeyBits[i]) {
|
259
|
+
rtOld = this.hash0(oldSibling, rtOld)
|
260
|
+
} else {
|
261
|
+
rtOld = this.hash0(rtOld, oldSibling)
|
262
|
+
}
|
263
|
+
dels.push(rtOld)
|
264
|
+
}
|
265
|
+
|
266
|
+
let newRt
|
267
|
+
if (newKeyBits[i]) {
|
268
|
+
newRt = this.hash0(res.siblings[i], rt)
|
269
|
+
inserts.push([newRt, [res.siblings[i], rt]])
|
270
|
+
} else {
|
271
|
+
newRt = this.hash0(rt, res.siblings[i])
|
272
|
+
inserts.push([newRt, [rt, res.siblings[i]]])
|
273
|
+
}
|
274
|
+
rt = newRt
|
275
|
+
}
|
276
|
+
|
277
|
+
if (addedOne) res.siblings.pop()
|
278
|
+
while (
|
279
|
+
res.siblings.length > 0 &&
|
280
|
+
F.isZero(res.siblings[res.siblings.length - 1])
|
281
|
+
) {
|
282
|
+
res.siblings.pop()
|
283
|
+
}
|
284
|
+
res.oldKey = resFind.notFoundKey
|
285
|
+
res.oldValue = resFind.notFoundValue
|
286
|
+
res.newRoot = rt
|
287
|
+
res.isOld0 = resFind.isOld0
|
288
|
+
|
289
|
+
await this.db.multiIns(inserts)
|
290
|
+
await this.db.setRoot(rt)
|
291
|
+
this.root = rt
|
292
|
+
await this.db.multiDel(dels)
|
293
|
+
|
294
|
+
return res
|
295
|
+
}
|
296
|
+
|
297
|
+
async find(_key) {
|
298
|
+
const key = this.F.e(_key)
|
299
|
+
const keyBits = this._splitBits(key)
|
300
|
+
return await this._find(key, keyBits, this.root, 0)
|
301
|
+
}
|
302
|
+
|
303
|
+
async _find(key, keyBits, root, level) {
|
304
|
+
const F = this.F
|
305
|
+
if (typeof root === "undefined") root = this.root
|
306
|
+
|
307
|
+
let res
|
308
|
+
if (F.isZero(root)) {
|
309
|
+
res = {
|
310
|
+
found: false,
|
311
|
+
siblings: [],
|
312
|
+
notFoundKey: key,
|
313
|
+
notFoundValue: F.zero,
|
314
|
+
isOld0: true,
|
315
|
+
}
|
316
|
+
return res
|
317
|
+
}
|
318
|
+
|
319
|
+
const record = await this.db.get(root)
|
320
|
+
|
321
|
+
if (record.length == 3 && F.eq(record[0], F.one)) {
|
322
|
+
if (F.eq(record[1], key)) {
|
323
|
+
res = {
|
324
|
+
found: true,
|
325
|
+
siblings: [],
|
326
|
+
foundValue: record[2],
|
327
|
+
isOld0: false,
|
328
|
+
}
|
329
|
+
} else {
|
330
|
+
res = {
|
331
|
+
found: false,
|
332
|
+
siblings: [],
|
333
|
+
notFoundKey: record[1],
|
334
|
+
notFoundValue: record[2],
|
335
|
+
isOld0: false,
|
336
|
+
}
|
337
|
+
}
|
338
|
+
} else {
|
339
|
+
if (keyBits[level] == 0) {
|
340
|
+
res = await this._find(key, keyBits, record[0], level + 1)
|
341
|
+
res.siblings.unshift(record[1])
|
342
|
+
} else {
|
343
|
+
res = await this._find(key, keyBits, record[1], level + 1)
|
344
|
+
res.siblings.unshift(record[0])
|
345
|
+
}
|
346
|
+
}
|
347
|
+
return res
|
348
|
+
}
|
349
|
+
}
|
@@ -0,0 +1,69 @@
|
|
1
|
+
export default class SMTMemDb {
|
2
|
+
constructor(F, kv) {
|
3
|
+
this.kv = kv
|
4
|
+
this.nodes = {}
|
5
|
+
this.root = F.zero
|
6
|
+
if (this.kv) {
|
7
|
+
const root = this.kv.get("root")
|
8
|
+
if (root) this.root = root
|
9
|
+
else this.kv.put("root", this.root)
|
10
|
+
}
|
11
|
+
this.F = F
|
12
|
+
}
|
13
|
+
|
14
|
+
async getRoot() {
|
15
|
+
return this.root
|
16
|
+
}
|
17
|
+
|
18
|
+
_key2str(k) {
|
19
|
+
this.F
|
20
|
+
const keyS = this.F.toString(k)
|
21
|
+
return keyS
|
22
|
+
}
|
23
|
+
|
24
|
+
_normalize(n) {
|
25
|
+
this.F
|
26
|
+
for (let i = 0; i < n.length; i++) {
|
27
|
+
n[i] = this.F.e(n[i])
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
async get(key) {
|
32
|
+
const keyS = this._key2str(key)
|
33
|
+
if (!this.nodes[keyS]) {
|
34
|
+
let node = this.kv.get(`node_${keyS}`)
|
35
|
+
if (node) this.nodes[keyS] = node
|
36
|
+
}
|
37
|
+
return this.nodes[keyS]
|
38
|
+
}
|
39
|
+
|
40
|
+
async multiGet(keys) {
|
41
|
+
const promises = []
|
42
|
+
for (let i = 0; i < keys.length; i++) {
|
43
|
+
promises.push(this.get(keys[i]))
|
44
|
+
}
|
45
|
+
return await Promise.all(promises)
|
46
|
+
}
|
47
|
+
|
48
|
+
async setRoot(rt) {
|
49
|
+
this.root = rt
|
50
|
+
if (this.kv) this.kv.put("root", this.root)
|
51
|
+
}
|
52
|
+
|
53
|
+
async multiIns(inserts) {
|
54
|
+
for (let i = 0; i < inserts.length; i++) {
|
55
|
+
const keyS = this._key2str(inserts[i][0])
|
56
|
+
this._normalize(inserts[i][1])
|
57
|
+
this.nodes[keyS] = inserts[i][1]
|
58
|
+
if (this.kv) this.kv.put(`node_${keyS}`, this.nodes[keyS])
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
async multiDel(dels) {
|
63
|
+
for (let i = 0; i < dels.length; i++) {
|
64
|
+
const keyS = this._key2str(dels[i])
|
65
|
+
delete this.nodes[keyS]
|
66
|
+
if (this.kv) this.kv.del(`node_${keyS}`)
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
@@ -0,0 +1,113 @@
|
|
1
|
+
import * as ffjavascript from "ffjavascript"
|
2
|
+
import poseidonConstants$1 from "./poseidonConstants$1.js"
|
3
|
+
import * as assert from "assert"
|
4
|
+
const assert__default = assert
|
5
|
+
|
6
|
+
function unsringifyConstants(Fr, o) {
|
7
|
+
if (typeof o == "string" && /^[0-9]+$/.test(o)) {
|
8
|
+
return Fr.e(o)
|
9
|
+
} else if (typeof o == "string" && /^0x[0-9a-fA-F]+$/.test(o)) {
|
10
|
+
return Fr.e(o)
|
11
|
+
} else if (Array.isArray(o)) {
|
12
|
+
return o.map(unsringifyConstants.bind(null, Fr))
|
13
|
+
} else if (typeof o == "object") {
|
14
|
+
if (o === null) return null
|
15
|
+
const res = {}
|
16
|
+
const keys = Object.keys(o)
|
17
|
+
keys.forEach(k => {
|
18
|
+
res[k] = unsringifyConstants(Fr, o[k])
|
19
|
+
})
|
20
|
+
return res
|
21
|
+
} else {
|
22
|
+
return o
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
export default async function buildPoseidon() {
|
27
|
+
const bn128 = await ffjavascript.getCurveFromName("bn128", true)
|
28
|
+
|
29
|
+
const F = bn128.Fr
|
30
|
+
|
31
|
+
const opt = unsringifyConstants(F, poseidonConstants$1)
|
32
|
+
|
33
|
+
const N_ROUNDS_F = 8
|
34
|
+
const N_ROUNDS_P = [
|
35
|
+
56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65, 70, 60, 64, 68,
|
36
|
+
]
|
37
|
+
|
38
|
+
const pow5 = a => F.mul(a, F.square(F.square(a, a)))
|
39
|
+
|
40
|
+
function poseidon(inputs, initState, nOut) {
|
41
|
+
assert__default["default"](inputs.length > 0)
|
42
|
+
assert__default["default"](inputs.length <= N_ROUNDS_P.length)
|
43
|
+
|
44
|
+
if (initState) {
|
45
|
+
initState = F.e(initState)
|
46
|
+
} else {
|
47
|
+
initState = F.zero
|
48
|
+
}
|
49
|
+
nOut = nOut || 1
|
50
|
+
|
51
|
+
const t = inputs.length + 1
|
52
|
+
const nRoundsF = N_ROUNDS_F
|
53
|
+
const nRoundsP = N_ROUNDS_P[t - 2]
|
54
|
+
const C = opt.C[t - 2]
|
55
|
+
const S = opt.S[t - 2]
|
56
|
+
const M = opt.M[t - 2]
|
57
|
+
const P = opt.P[t - 2]
|
58
|
+
|
59
|
+
let state = [initState, ...inputs.map(a => F.e(a))]
|
60
|
+
|
61
|
+
state = state.map((a, i) => F.add(a, C[i]))
|
62
|
+
|
63
|
+
for (let r = 0; r < nRoundsF / 2 - 1; r++) {
|
64
|
+
state = state.map(a => pow5(a))
|
65
|
+
state = state.map((a, i) => F.add(a, C[(r + 1) * t + i]))
|
66
|
+
state = state.map((_, i) =>
|
67
|
+
state.reduce((acc, a, j) => F.add(acc, F.mul(M[j][i], a)), F.zero),
|
68
|
+
)
|
69
|
+
}
|
70
|
+
state = state.map(a => pow5(a))
|
71
|
+
state = state.map((a, i) => F.add(a, C[(nRoundsF / 2 - 1 + 1) * t + i]))
|
72
|
+
state = state.map((_, i) =>
|
73
|
+
state.reduce((acc, a, j) => F.add(acc, F.mul(P[j][i], a)), F.zero),
|
74
|
+
)
|
75
|
+
for (let r = 0; r < nRoundsP; r++) {
|
76
|
+
state[0] = pow5(state[0])
|
77
|
+
state[0] = F.add(state[0], C[(nRoundsF / 2 + 1) * t + r])
|
78
|
+
|
79
|
+
const s0 = state.reduce((acc, a, j) => {
|
80
|
+
return F.add(acc, F.mul(S[(t * 2 - 1) * r + j], a))
|
81
|
+
}, F.zero)
|
82
|
+
for (let k = 1; k < t; k++) {
|
83
|
+
state[k] = F.add(
|
84
|
+
state[k],
|
85
|
+
F.mul(state[0], S[(t * 2 - 1) * r + t + k - 1]),
|
86
|
+
)
|
87
|
+
}
|
88
|
+
state[0] = s0
|
89
|
+
}
|
90
|
+
for (let r = 0; r < nRoundsF / 2 - 1; r++) {
|
91
|
+
state = state.map(a => pow5(a))
|
92
|
+
state = state.map((a, i) =>
|
93
|
+
F.add(a, C[(nRoundsF / 2 + 1) * t + nRoundsP + r * t + i]),
|
94
|
+
)
|
95
|
+
state = state.map((_, i) =>
|
96
|
+
state.reduce((acc, a, j) => F.add(acc, F.mul(M[j][i], a)), F.zero),
|
97
|
+
)
|
98
|
+
}
|
99
|
+
state = state.map(a => pow5(a))
|
100
|
+
state = state.map((_, i) =>
|
101
|
+
state.reduce((acc, a, j) => F.add(acc, F.mul(M[j][i], a)), F.zero),
|
102
|
+
)
|
103
|
+
|
104
|
+
if (nOut == 1) {
|
105
|
+
return state[0]
|
106
|
+
} else {
|
107
|
+
return state.slice(0, nOut)
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
poseidon.F = F
|
112
|
+
return poseidon
|
113
|
+
}
|