@kohaku-eth/tornado-cash 0.0.2-alpha.11 → 0.0.2-alpha.13
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/dist/index.d.ts +161 -65
- package/dist/index.js +87 -116
- package/dist/merkle-tree-worker.browser.js +3570 -0
- package/dist/merkle-tree-worker.node.js +3595 -0
- package/dist/merkle-tree.browser.js +13 -0
- package/dist/merkle-tree.node.js +13 -0
- package/dist/msm-worker.browser.js +1 -1
- package/dist/msm-worker.js +1 -1
- package/dist/state-manager.worker.js +20889 -26307
- package/dist/{state-manager.worker.node.cjs → state-manager.worker.node.js} +19900 -23948
- package/dist/worker-loader.browser.d.ts +86 -26
- package/dist/worker-loader.node.d.ts +86 -26
- package/dist/worker-loader.node.js +1 -6
- package/package.json +10 -11
|
@@ -0,0 +1,3595 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __commonJS = (cb, mod2) => function __require() {
|
|
8
|
+
return mod2 || (0, cb[__getOwnPropNames(cb)[0]])((mod2 = { exports: {} }).exports, mod2), mod2.exports;
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__getProtoOf(mod2)) : {}, __copyProps(
|
|
19
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
20
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
21
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
22
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
23
|
+
isNodeMode || !mod2 || !mod2.__esModule ? __defProp(target, "default", { value: mod2, enumerable: true }) : target,
|
|
24
|
+
mod2
|
|
25
|
+
));
|
|
26
|
+
|
|
27
|
+
// ../../node_modules/.pnpm/fixed-merkle-tree@0.7.3/node_modules/fixed-merkle-tree/lib/simpleHash.js
|
|
28
|
+
var require_simpleHash = __commonJS({
|
|
29
|
+
"../../node_modules/.pnpm/fixed-merkle-tree@0.7.3/node_modules/fixed-merkle-tree/lib/simpleHash.js"(exports) {
|
|
30
|
+
"use strict";
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.simpleHash = void 0;
|
|
33
|
+
function simpleHash(data, seed, hashLength = 40) {
|
|
34
|
+
const str = data.join("");
|
|
35
|
+
let i, l, hval = seed !== null && seed !== void 0 ? seed : 34658180293;
|
|
36
|
+
for (i = 0, l = str.length; i < l; i++) {
|
|
37
|
+
hval ^= str.charCodeAt(i);
|
|
38
|
+
hval += (hval << 1) + (hval << 4) + (hval << 6) + (hval << 8) + (hval << 24);
|
|
39
|
+
}
|
|
40
|
+
const hash = (hval >>> 0).toString(16);
|
|
41
|
+
return BigInt("0x" + hash.padEnd(hashLength - (hash.length - 1), "0")).toString(10);
|
|
42
|
+
}
|
|
43
|
+
exports.simpleHash = simpleHash;
|
|
44
|
+
exports.default = (left, right) => simpleHash([left, right]);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// ../../node_modules/.pnpm/fixed-merkle-tree@0.7.3/node_modules/fixed-merkle-tree/lib/BaseTree.js
|
|
49
|
+
var require_BaseTree = __commonJS({
|
|
50
|
+
"../../node_modules/.pnpm/fixed-merkle-tree@0.7.3/node_modules/fixed-merkle-tree/lib/BaseTree.js"(exports) {
|
|
51
|
+
"use strict";
|
|
52
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
+
exports.BaseTree = void 0;
|
|
54
|
+
var BaseTree = class {
|
|
55
|
+
get capacity() {
|
|
56
|
+
return 2 ** this.levels;
|
|
57
|
+
}
|
|
58
|
+
get layers() {
|
|
59
|
+
return this._layers.slice();
|
|
60
|
+
}
|
|
61
|
+
get zeros() {
|
|
62
|
+
return this._zeros.slice();
|
|
63
|
+
}
|
|
64
|
+
get elements() {
|
|
65
|
+
return this._layers[0].slice();
|
|
66
|
+
}
|
|
67
|
+
get root() {
|
|
68
|
+
var _a;
|
|
69
|
+
return (_a = this._layers[this.levels][0]) !== null && _a !== void 0 ? _a : this._zeros[this.levels];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Find an element in the tree
|
|
73
|
+
* @param elements elements of tree
|
|
74
|
+
* @param element An element to find
|
|
75
|
+
* @param comparator A function that checks leaf value equality
|
|
76
|
+
* @param fromIndex The index to start the search at. If the index is greater than or equal to the array's length, -1 is returned
|
|
77
|
+
* @returns {number} Index if element is found, otherwise -1
|
|
78
|
+
*/
|
|
79
|
+
static indexOf(elements, element, fromIndex, comparator) {
|
|
80
|
+
if (comparator) {
|
|
81
|
+
return elements.findIndex((el) => comparator(element, el));
|
|
82
|
+
} else {
|
|
83
|
+
return elements.indexOf(element, fromIndex);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Insert new element into the tree
|
|
88
|
+
* @param element Element to insert
|
|
89
|
+
*/
|
|
90
|
+
insert(element) {
|
|
91
|
+
if (this._layers[0].length >= this.capacity) {
|
|
92
|
+
throw new Error("Tree is full");
|
|
93
|
+
}
|
|
94
|
+
this.update(this._layers[0].length, element);
|
|
95
|
+
}
|
|
96
|
+
/*
|
|
97
|
+
* Insert multiple elements into the tree.
|
|
98
|
+
* @param {Array} elements Elements to insert
|
|
99
|
+
*/
|
|
100
|
+
bulkInsert(elements) {
|
|
101
|
+
if (!elements.length) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (this._layers[0].length + elements.length > this.capacity) {
|
|
105
|
+
throw new Error("Tree is full");
|
|
106
|
+
}
|
|
107
|
+
for (let i = 0; i < elements.length - 1; i++) {
|
|
108
|
+
this._layers[0].push(elements[i]);
|
|
109
|
+
let level = 0;
|
|
110
|
+
let index = this._layers[0].length - 1;
|
|
111
|
+
while (index % 2 === 1) {
|
|
112
|
+
level++;
|
|
113
|
+
index >>= 1;
|
|
114
|
+
const left = this._layers[level - 1][index * 2];
|
|
115
|
+
const right = this._layers[level - 1][index * 2 + 1];
|
|
116
|
+
this._layers[level][index] = this._hashFn(left, right);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
this.insert(elements[elements.length - 1]);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Change an element in the tree
|
|
123
|
+
* @param {number} index Index of element to change
|
|
124
|
+
* @param element Updated element value
|
|
125
|
+
*/
|
|
126
|
+
update(index, element) {
|
|
127
|
+
if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) {
|
|
128
|
+
throw new Error("Insert index out of bounds: " + index);
|
|
129
|
+
}
|
|
130
|
+
this._layers[0][index] = element;
|
|
131
|
+
this._processUpdate(index);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Get merkle path to a leaf
|
|
135
|
+
* @param {number} index Leaf index to generate path for
|
|
136
|
+
* @returns {{pathElements: Object[], pathIndex: number[]}} An object containing adjacent elements and left-right index
|
|
137
|
+
*/
|
|
138
|
+
path(index) {
|
|
139
|
+
if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) {
|
|
140
|
+
throw new Error("Index out of bounds: " + index);
|
|
141
|
+
}
|
|
142
|
+
let elIndex = +index;
|
|
143
|
+
const pathElements = [];
|
|
144
|
+
const pathIndices = [];
|
|
145
|
+
const pathPositions = [];
|
|
146
|
+
for (let level = 0; level < this.levels; level++) {
|
|
147
|
+
pathIndices[level] = elIndex % 2;
|
|
148
|
+
const leafIndex = elIndex ^ 1;
|
|
149
|
+
if (leafIndex < this._layers[level].length) {
|
|
150
|
+
pathElements[level] = this._layers[level][leafIndex];
|
|
151
|
+
pathPositions[level] = leafIndex;
|
|
152
|
+
} else {
|
|
153
|
+
pathElements[level] = this._zeros[level];
|
|
154
|
+
pathPositions[level] = 0;
|
|
155
|
+
}
|
|
156
|
+
elIndex >>= 1;
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
pathElements,
|
|
160
|
+
pathIndices,
|
|
161
|
+
pathPositions,
|
|
162
|
+
pathRoot: this.root
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
_buildZeros() {
|
|
166
|
+
this._zeros = [this.zeroElement];
|
|
167
|
+
for (let i = 1; i <= this.levels; i++) {
|
|
168
|
+
this._zeros[i] = this._hashFn(this._zeros[i - 1], this._zeros[i - 1]);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
_processNodes(nodes, layerIndex) {
|
|
172
|
+
const length = nodes.length;
|
|
173
|
+
let currentLength = Math.ceil(length / 2);
|
|
174
|
+
const currentLayer = new Array(currentLength);
|
|
175
|
+
currentLength--;
|
|
176
|
+
const starFrom = length - (length % 2 ^ 1);
|
|
177
|
+
let j = 0;
|
|
178
|
+
for (let i = starFrom; i >= 0; i -= 2) {
|
|
179
|
+
if (nodes[i - 1] === void 0)
|
|
180
|
+
break;
|
|
181
|
+
const left = nodes[i - 1];
|
|
182
|
+
const right = i === starFrom && length % 2 === 1 ? this._zeros[layerIndex - 1] : nodes[i];
|
|
183
|
+
currentLayer[currentLength - j] = this._hashFn(left, right);
|
|
184
|
+
j++;
|
|
185
|
+
}
|
|
186
|
+
return currentLayer;
|
|
187
|
+
}
|
|
188
|
+
_processUpdate(index) {
|
|
189
|
+
for (let level = 1; level <= this.levels; level++) {
|
|
190
|
+
index >>= 1;
|
|
191
|
+
const left = this._layers[level - 1][index * 2];
|
|
192
|
+
const right = index * 2 + 1 < this._layers[level - 1].length ? this._layers[level - 1][index * 2 + 1] : this._zeros[level - 1];
|
|
193
|
+
this._layers[level][index] = this._hashFn(left, right);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
exports.BaseTree = BaseTree;
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// ../../node_modules/.pnpm/fixed-merkle-tree@0.7.3/node_modules/fixed-merkle-tree/lib/FixedMerkleTree.js
|
|
202
|
+
var require_FixedMerkleTree = __commonJS({
|
|
203
|
+
"../../node_modules/.pnpm/fixed-merkle-tree@0.7.3/node_modules/fixed-merkle-tree/lib/FixedMerkleTree.js"(exports) {
|
|
204
|
+
"use strict";
|
|
205
|
+
var __importDefault = exports && exports.__importDefault || function(mod2) {
|
|
206
|
+
return mod2 && mod2.__esModule ? mod2 : { "default": mod2 };
|
|
207
|
+
};
|
|
208
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
209
|
+
var simpleHash_1 = __importDefault(require_simpleHash());
|
|
210
|
+
var BaseTree_1 = require_BaseTree();
|
|
211
|
+
var MerkleTree2 = class extends BaseTree_1.BaseTree {
|
|
212
|
+
constructor(levels, elements = [], { hashFunction = simpleHash_1.default, zeroElement = 0 } = {}) {
|
|
213
|
+
super();
|
|
214
|
+
this.levels = levels;
|
|
215
|
+
if (elements.length > this.capacity) {
|
|
216
|
+
throw new Error("Tree is full");
|
|
217
|
+
}
|
|
218
|
+
this._hashFn = hashFunction;
|
|
219
|
+
this.zeroElement = zeroElement;
|
|
220
|
+
this._layers = [];
|
|
221
|
+
const leaves = elements.slice();
|
|
222
|
+
this._layers = [leaves];
|
|
223
|
+
this._buildZeros();
|
|
224
|
+
this._buildHashes();
|
|
225
|
+
}
|
|
226
|
+
_buildHashes() {
|
|
227
|
+
for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) {
|
|
228
|
+
const nodes = this._layers[layerIndex - 1];
|
|
229
|
+
this._layers[layerIndex] = this._processNodes(nodes, layerIndex);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Insert multiple elements into the tree.
|
|
234
|
+
* @param {Array} elements Elements to insert
|
|
235
|
+
*/
|
|
236
|
+
bulkInsert(elements) {
|
|
237
|
+
if (!elements.length) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (this._layers[0].length + elements.length > this.capacity) {
|
|
241
|
+
throw new Error("Tree is full");
|
|
242
|
+
}
|
|
243
|
+
for (let i = 0; i < elements.length - 1; i++) {
|
|
244
|
+
this._layers[0].push(elements[i]);
|
|
245
|
+
let level = 0;
|
|
246
|
+
let index = this._layers[0].length - 1;
|
|
247
|
+
while (index % 2 === 1) {
|
|
248
|
+
level++;
|
|
249
|
+
index >>= 1;
|
|
250
|
+
this._layers[level][index] = this._hashFn(this._layers[level - 1][index * 2], this._layers[level - 1][index * 2 + 1]);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
this.insert(elements[elements.length - 1]);
|
|
254
|
+
}
|
|
255
|
+
indexOf(element, comparator) {
|
|
256
|
+
return BaseTree_1.BaseTree.indexOf(this._layers[0], element, 0, comparator);
|
|
257
|
+
}
|
|
258
|
+
proof(element) {
|
|
259
|
+
const index = this.indexOf(element);
|
|
260
|
+
return this.path(index);
|
|
261
|
+
}
|
|
262
|
+
getTreeEdge(edgeIndex) {
|
|
263
|
+
const edgeElement = this._layers[0][edgeIndex];
|
|
264
|
+
if (edgeElement === void 0) {
|
|
265
|
+
throw new Error("Element not found");
|
|
266
|
+
}
|
|
267
|
+
const edgePath = this.path(edgeIndex);
|
|
268
|
+
return { edgePath, edgeElement, edgeIndex, edgeElementsCount: this._layers[0].length };
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* 🪓
|
|
272
|
+
* @param count
|
|
273
|
+
*/
|
|
274
|
+
getTreeSlices(count = 4) {
|
|
275
|
+
const length = this._layers[0].length;
|
|
276
|
+
let size = Math.ceil(length / count);
|
|
277
|
+
if (size % 2)
|
|
278
|
+
size++;
|
|
279
|
+
const slices = [];
|
|
280
|
+
for (let i = 0; i < length; i += size) {
|
|
281
|
+
const edgeLeft = i;
|
|
282
|
+
const edgeRight = i + size;
|
|
283
|
+
slices.push({ edge: this.getTreeEdge(edgeLeft), elements: this.elements.slice(edgeLeft, edgeRight) });
|
|
284
|
+
}
|
|
285
|
+
return slices;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Serialize entire tree state including intermediate layers into a plain object
|
|
289
|
+
* Deserializing it back will not require to recompute any hashes
|
|
290
|
+
* Elements are not converted to a plain type, this is responsibility of the caller
|
|
291
|
+
*/
|
|
292
|
+
serialize() {
|
|
293
|
+
return {
|
|
294
|
+
levels: this.levels,
|
|
295
|
+
_zeros: this._zeros,
|
|
296
|
+
_layers: this._layers
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Deserialize data into a MerkleTree instance
|
|
301
|
+
* Make sure to provide the same hashFunction as was used in the source tree,
|
|
302
|
+
* otherwise the tree state will be invalid
|
|
303
|
+
*/
|
|
304
|
+
static deserialize(data, hashFunction) {
|
|
305
|
+
const instance = Object.assign(Object.create(this.prototype), data);
|
|
306
|
+
instance._hashFn = hashFunction || simpleHash_1.default;
|
|
307
|
+
instance.zeroElement = instance._zeros[0];
|
|
308
|
+
return instance;
|
|
309
|
+
}
|
|
310
|
+
toString() {
|
|
311
|
+
return JSON.stringify(this.serialize());
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
exports.default = MerkleTree2;
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
// ../../node_modules/.pnpm/fixed-merkle-tree@0.7.3/node_modules/fixed-merkle-tree/lib/PartialMerkleTree.js
|
|
319
|
+
var require_PartialMerkleTree = __commonJS({
|
|
320
|
+
"../../node_modules/.pnpm/fixed-merkle-tree@0.7.3/node_modules/fixed-merkle-tree/lib/PartialMerkleTree.js"(exports) {
|
|
321
|
+
"use strict";
|
|
322
|
+
var __importDefault = exports && exports.__importDefault || function(mod2) {
|
|
323
|
+
return mod2 && mod2.__esModule ? mod2 : { "default": mod2 };
|
|
324
|
+
};
|
|
325
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
326
|
+
exports.PartialMerkleTree = void 0;
|
|
327
|
+
var simpleHash_1 = __importDefault(require_simpleHash());
|
|
328
|
+
var BaseTree_1 = require_BaseTree();
|
|
329
|
+
var PartialMerkleTree = class extends BaseTree_1.BaseTree {
|
|
330
|
+
constructor(levels, { edgePath, edgeElement, edgeIndex, edgeElementsCount }, leaves, { hashFunction, zeroElement } = {}) {
|
|
331
|
+
super();
|
|
332
|
+
if (edgeIndex + leaves.length !== edgeElementsCount)
|
|
333
|
+
throw new Error("Invalid number of elements");
|
|
334
|
+
this._edgeLeafProof = edgePath;
|
|
335
|
+
this._initialRoot = edgePath.pathRoot;
|
|
336
|
+
this.zeroElement = zeroElement !== null && zeroElement !== void 0 ? zeroElement : 0;
|
|
337
|
+
this._edgeLeaf = { data: edgeElement, index: edgeIndex };
|
|
338
|
+
this._leavesAfterEdge = leaves;
|
|
339
|
+
this.levels = levels;
|
|
340
|
+
this._hashFn = hashFunction || simpleHash_1.default;
|
|
341
|
+
this._createProofMap();
|
|
342
|
+
this._buildTree();
|
|
343
|
+
}
|
|
344
|
+
get edgeIndex() {
|
|
345
|
+
return this._edgeLeaf.index;
|
|
346
|
+
}
|
|
347
|
+
get edgeElement() {
|
|
348
|
+
return this._edgeLeaf.data;
|
|
349
|
+
}
|
|
350
|
+
get edgeLeafProof() {
|
|
351
|
+
return this._edgeLeafProof;
|
|
352
|
+
}
|
|
353
|
+
_createProofMap() {
|
|
354
|
+
this._proofMap = this.edgeLeafProof.pathPositions.reduce((p, c, i) => {
|
|
355
|
+
p.set(i, [c, this.edgeLeafProof.pathElements[i]]);
|
|
356
|
+
return p;
|
|
357
|
+
}, /* @__PURE__ */ new Map());
|
|
358
|
+
this._proofMap.set(this.levels, [0, this.edgeLeafProof.pathRoot]);
|
|
359
|
+
}
|
|
360
|
+
_buildTree() {
|
|
361
|
+
const edgeLeafIndex = this._edgeLeaf.index;
|
|
362
|
+
this._leaves = Array(edgeLeafIndex).concat(this._leavesAfterEdge);
|
|
363
|
+
if (this._proofMap.has(0)) {
|
|
364
|
+
const [proofPos, proofEl] = this._proofMap.get(0);
|
|
365
|
+
this._leaves[proofPos] = proofEl;
|
|
366
|
+
}
|
|
367
|
+
this._layers = [this._leaves];
|
|
368
|
+
this._buildZeros();
|
|
369
|
+
this._buildHashes();
|
|
370
|
+
}
|
|
371
|
+
_buildHashes() {
|
|
372
|
+
for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) {
|
|
373
|
+
const nodes = this._layers[layerIndex - 1];
|
|
374
|
+
const currentLayer = this._processNodes(nodes, layerIndex);
|
|
375
|
+
if (this._proofMap.has(layerIndex)) {
|
|
376
|
+
const [proofPos, proofEl] = this._proofMap.get(layerIndex);
|
|
377
|
+
if (!currentLayer[proofPos])
|
|
378
|
+
currentLayer[proofPos] = proofEl;
|
|
379
|
+
}
|
|
380
|
+
this._layers[layerIndex] = currentLayer;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Change an element in the tree
|
|
385
|
+
* @param {number} index Index of element to change
|
|
386
|
+
* @param element Updated element value
|
|
387
|
+
*/
|
|
388
|
+
update(index, element) {
|
|
389
|
+
if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) {
|
|
390
|
+
throw new Error("Insert index out of bounds: " + index);
|
|
391
|
+
}
|
|
392
|
+
if (index < this._edgeLeaf.index) {
|
|
393
|
+
throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`);
|
|
394
|
+
}
|
|
395
|
+
this._layers[0][index] = element;
|
|
396
|
+
this._processUpdate(index);
|
|
397
|
+
}
|
|
398
|
+
path(index) {
|
|
399
|
+
var _a;
|
|
400
|
+
if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) {
|
|
401
|
+
throw new Error("Index out of bounds: " + index);
|
|
402
|
+
}
|
|
403
|
+
if (index < this._edgeLeaf.index) {
|
|
404
|
+
throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`);
|
|
405
|
+
}
|
|
406
|
+
let elIndex = Number(index);
|
|
407
|
+
const pathElements = [];
|
|
408
|
+
const pathIndices = [];
|
|
409
|
+
const pathPositions = [];
|
|
410
|
+
for (let level = 0; level < this.levels; level++) {
|
|
411
|
+
pathIndices[level] = elIndex % 2;
|
|
412
|
+
const leafIndex = elIndex ^ 1;
|
|
413
|
+
if (leafIndex < this._layers[level].length) {
|
|
414
|
+
pathElements[level] = this._layers[level][leafIndex];
|
|
415
|
+
pathPositions[level] = leafIndex;
|
|
416
|
+
} else {
|
|
417
|
+
pathElements[level] = this._zeros[level];
|
|
418
|
+
pathPositions[level] = 0;
|
|
419
|
+
}
|
|
420
|
+
const [proofPos, proofEl] = this._proofMap.get(level);
|
|
421
|
+
pathElements[level] = (_a = pathElements[level]) !== null && _a !== void 0 ? _a : proofPos === leafIndex ? proofEl : this._zeros[level];
|
|
422
|
+
elIndex >>= 1;
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
425
|
+
pathElements,
|
|
426
|
+
pathIndices,
|
|
427
|
+
pathPositions,
|
|
428
|
+
pathRoot: this.root
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
indexOf(element, comparator) {
|
|
432
|
+
return BaseTree_1.BaseTree.indexOf(this._layers[0], element, this.edgeIndex, comparator);
|
|
433
|
+
}
|
|
434
|
+
proof(element) {
|
|
435
|
+
const index = this.indexOf(element);
|
|
436
|
+
return this.path(index);
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Shifts edge of tree to left
|
|
440
|
+
* @param edge new TreeEdge below current edge
|
|
441
|
+
* @param elements leaves between old and new edge
|
|
442
|
+
*/
|
|
443
|
+
shiftEdge(edge, elements) {
|
|
444
|
+
if (this._edgeLeaf.index <= edge.edgeIndex) {
|
|
445
|
+
throw new Error(`New edgeIndex should be smaller then ${this._edgeLeaf.index}`);
|
|
446
|
+
}
|
|
447
|
+
if (elements.length !== this._edgeLeaf.index - edge.edgeIndex) {
|
|
448
|
+
throw new Error(`Elements length should be ${this._edgeLeaf.index - edge.edgeIndex}`);
|
|
449
|
+
}
|
|
450
|
+
this._edgeLeafProof = edge.edgePath;
|
|
451
|
+
this._edgeLeaf = { index: edge.edgeIndex, data: edge.edgeElement };
|
|
452
|
+
this._leavesAfterEdge = [...elements, ...this._leavesAfterEdge];
|
|
453
|
+
this._createProofMap();
|
|
454
|
+
this._buildTree();
|
|
455
|
+
}
|
|
456
|
+
serialize() {
|
|
457
|
+
return {
|
|
458
|
+
_edgeLeafProof: this._edgeLeafProof,
|
|
459
|
+
_edgeLeaf: this._edgeLeaf,
|
|
460
|
+
_layers: this._layers,
|
|
461
|
+
_zeros: this._zeros,
|
|
462
|
+
levels: this.levels
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
static deserialize(data, hashFunction) {
|
|
466
|
+
const instance = Object.assign(Object.create(this.prototype), data);
|
|
467
|
+
instance._hashFn = hashFunction || simpleHash_1.default;
|
|
468
|
+
instance._initialRoot = data._edgeLeafProof.pathRoot;
|
|
469
|
+
instance.zeroElement = instance._zeros[0];
|
|
470
|
+
instance._leavesAfterEdge = instance._layers[0].slice(data._edgeLeaf.index);
|
|
471
|
+
instance._createProofMap();
|
|
472
|
+
return instance;
|
|
473
|
+
}
|
|
474
|
+
toString() {
|
|
475
|
+
return JSON.stringify(this.serialize());
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
exports.PartialMerkleTree = PartialMerkleTree;
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
// ../../node_modules/.pnpm/fixed-merkle-tree@0.7.3/node_modules/fixed-merkle-tree/lib/index.js
|
|
483
|
+
var require_lib = __commonJS({
|
|
484
|
+
"../../node_modules/.pnpm/fixed-merkle-tree@0.7.3/node_modules/fixed-merkle-tree/lib/index.js"(exports) {
|
|
485
|
+
"use strict";
|
|
486
|
+
var __importDefault = exports && exports.__importDefault || function(mod2) {
|
|
487
|
+
return mod2 && mod2.__esModule ? mod2 : { "default": mod2 };
|
|
488
|
+
};
|
|
489
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
490
|
+
exports.MerkleTree = exports.simpleHash = exports.PartialMerkleTree = void 0;
|
|
491
|
+
var FixedMerkleTree_1 = __importDefault(require_FixedMerkleTree());
|
|
492
|
+
Object.defineProperty(exports, "MerkleTree", { enumerable: true, get: function() {
|
|
493
|
+
return FixedMerkleTree_1.default;
|
|
494
|
+
} });
|
|
495
|
+
var PartialMerkleTree_1 = require_PartialMerkleTree();
|
|
496
|
+
Object.defineProperty(exports, "PartialMerkleTree", { enumerable: true, get: function() {
|
|
497
|
+
return PartialMerkleTree_1.PartialMerkleTree;
|
|
498
|
+
} });
|
|
499
|
+
var simpleHash_1 = require_simpleHash();
|
|
500
|
+
Object.defineProperty(exports, "simpleHash", { enumerable: true, get: function() {
|
|
501
|
+
return simpleHash_1.simpleHash;
|
|
502
|
+
} });
|
|
503
|
+
exports.default = FixedMerkleTree_1.default;
|
|
504
|
+
}
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
// ../mimc-tree/dist/MimcMerkleTreeWorker.js
|
|
508
|
+
import { parentPort } from "worker_threads";
|
|
509
|
+
|
|
510
|
+
// ../../node_modules/.pnpm/@noble+hashes@2.2.0/node_modules/@noble/hashes/utils.js
|
|
511
|
+
function isBytes(a) {
|
|
512
|
+
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1;
|
|
513
|
+
}
|
|
514
|
+
function anumber(n, title = "") {
|
|
515
|
+
if (typeof n !== "number") {
|
|
516
|
+
const prefix = title && `"${title}" `;
|
|
517
|
+
throw new TypeError(`${prefix}expected number, got ${typeof n}`);
|
|
518
|
+
}
|
|
519
|
+
if (!Number.isSafeInteger(n) || n < 0) {
|
|
520
|
+
const prefix = title && `"${title}" `;
|
|
521
|
+
throw new RangeError(`${prefix}expected integer >= 0, got ${n}`);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
function abytes(value, length, title = "") {
|
|
525
|
+
const bytes = isBytes(value);
|
|
526
|
+
const len = value?.length;
|
|
527
|
+
const needsLen = length !== void 0;
|
|
528
|
+
if (!bytes || needsLen && len !== length) {
|
|
529
|
+
const prefix = title && `"${title}" `;
|
|
530
|
+
const ofLen = needsLen ? ` of length ${length}` : "";
|
|
531
|
+
const got = bytes ? `length=${len}` : `type=${typeof value}`;
|
|
532
|
+
const message = prefix + "expected Uint8Array" + ofLen + ", got " + got;
|
|
533
|
+
if (!bytes)
|
|
534
|
+
throw new TypeError(message);
|
|
535
|
+
throw new RangeError(message);
|
|
536
|
+
}
|
|
537
|
+
return value;
|
|
538
|
+
}
|
|
539
|
+
function aexists(instance, checkFinished = true) {
|
|
540
|
+
if (instance.destroyed)
|
|
541
|
+
throw new Error("Hash instance has been destroyed");
|
|
542
|
+
if (checkFinished && instance.finished)
|
|
543
|
+
throw new Error("Hash#digest() has already been called");
|
|
544
|
+
}
|
|
545
|
+
function aoutput(out, instance) {
|
|
546
|
+
abytes(out, void 0, "digestInto() output");
|
|
547
|
+
const min = instance.outputLen;
|
|
548
|
+
if (out.length < min) {
|
|
549
|
+
throw new RangeError('"digestInto() output" expected to be of length >=' + min);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
function u32(arr) {
|
|
553
|
+
return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));
|
|
554
|
+
}
|
|
555
|
+
function clean(...arrays) {
|
|
556
|
+
for (let i = 0; i < arrays.length; i++) {
|
|
557
|
+
arrays[i].fill(0);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
var isLE = /* @__PURE__ */ (() => new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68)();
|
|
561
|
+
function byteSwap(word) {
|
|
562
|
+
return word << 24 & 4278190080 | word << 8 & 16711680 | word >>> 8 & 65280 | word >>> 24 & 255;
|
|
563
|
+
}
|
|
564
|
+
function byteSwap32(arr) {
|
|
565
|
+
for (let i = 0; i < arr.length; i++) {
|
|
566
|
+
arr[i] = byteSwap(arr[i]);
|
|
567
|
+
}
|
|
568
|
+
return arr;
|
|
569
|
+
}
|
|
570
|
+
var swap32IfBE = isLE ? (u) => u : byteSwap32;
|
|
571
|
+
var hasHexBuiltin = /* @__PURE__ */ (() => (
|
|
572
|
+
// @ts-ignore
|
|
573
|
+
typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function"
|
|
574
|
+
))();
|
|
575
|
+
var hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
|
|
576
|
+
function bytesToHex(bytes) {
|
|
577
|
+
abytes(bytes);
|
|
578
|
+
if (hasHexBuiltin)
|
|
579
|
+
return bytes.toHex();
|
|
580
|
+
let hex = "";
|
|
581
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
582
|
+
hex += hexes[bytes[i]];
|
|
583
|
+
}
|
|
584
|
+
return hex;
|
|
585
|
+
}
|
|
586
|
+
var asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
|
|
587
|
+
function asciiToBase16(ch) {
|
|
588
|
+
if (ch >= asciis._0 && ch <= asciis._9)
|
|
589
|
+
return ch - asciis._0;
|
|
590
|
+
if (ch >= asciis.A && ch <= asciis.F)
|
|
591
|
+
return ch - (asciis.A - 10);
|
|
592
|
+
if (ch >= asciis.a && ch <= asciis.f)
|
|
593
|
+
return ch - (asciis.a - 10);
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
function hexToBytes(hex) {
|
|
597
|
+
if (typeof hex !== "string")
|
|
598
|
+
throw new TypeError("hex string expected, got " + typeof hex);
|
|
599
|
+
if (hasHexBuiltin) {
|
|
600
|
+
try {
|
|
601
|
+
return Uint8Array.fromHex(hex);
|
|
602
|
+
} catch (error) {
|
|
603
|
+
if (error instanceof SyntaxError)
|
|
604
|
+
throw new RangeError(error.message);
|
|
605
|
+
throw error;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
const hl = hex.length;
|
|
609
|
+
const al = hl / 2;
|
|
610
|
+
if (hl % 2)
|
|
611
|
+
throw new RangeError("hex string expected, got unpadded hex of length " + hl);
|
|
612
|
+
const array = new Uint8Array(al);
|
|
613
|
+
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
|
|
614
|
+
const n1 = asciiToBase16(hex.charCodeAt(hi));
|
|
615
|
+
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
|
|
616
|
+
if (n1 === void 0 || n2 === void 0) {
|
|
617
|
+
const char = hex[hi] + hex[hi + 1];
|
|
618
|
+
throw new RangeError('hex string expected, got non-hex character "' + char + '" at index ' + hi);
|
|
619
|
+
}
|
|
620
|
+
array[ai] = n1 * 16 + n2;
|
|
621
|
+
}
|
|
622
|
+
return array;
|
|
623
|
+
}
|
|
624
|
+
function utf8ToBytes(str) {
|
|
625
|
+
if (typeof str !== "string")
|
|
626
|
+
throw new TypeError("string expected");
|
|
627
|
+
return new Uint8Array(new TextEncoder().encode(str));
|
|
628
|
+
}
|
|
629
|
+
function concatBytes(...arrays) {
|
|
630
|
+
let sum = 0;
|
|
631
|
+
for (let i = 0; i < arrays.length; i++) {
|
|
632
|
+
const a = arrays[i];
|
|
633
|
+
abytes(a);
|
|
634
|
+
sum += a.length;
|
|
635
|
+
}
|
|
636
|
+
const res = new Uint8Array(sum);
|
|
637
|
+
for (let i = 0, pad = 0; i < arrays.length; i++) {
|
|
638
|
+
const a = arrays[i];
|
|
639
|
+
res.set(a, pad);
|
|
640
|
+
pad += a.length;
|
|
641
|
+
}
|
|
642
|
+
return res;
|
|
643
|
+
}
|
|
644
|
+
function createHasher(hashCons, info = {}) {
|
|
645
|
+
const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
|
|
646
|
+
const tmp = hashCons(void 0);
|
|
647
|
+
hashC.outputLen = tmp.outputLen;
|
|
648
|
+
hashC.blockLen = tmp.blockLen;
|
|
649
|
+
hashC.canXOF = tmp.canXOF;
|
|
650
|
+
hashC.create = (opts) => hashCons(opts);
|
|
651
|
+
Object.assign(hashC, info);
|
|
652
|
+
return Object.freeze(hashC);
|
|
653
|
+
}
|
|
654
|
+
function randomBytes(bytesLength = 32) {
|
|
655
|
+
anumber(bytesLength, "bytesLength");
|
|
656
|
+
const cr = typeof globalThis === "object" ? globalThis.crypto : null;
|
|
657
|
+
if (typeof cr?.getRandomValues !== "function")
|
|
658
|
+
throw new Error("crypto.getRandomValues must be defined");
|
|
659
|
+
if (bytesLength > 65536)
|
|
660
|
+
throw new RangeError(`"bytesLength" expected <= 65536, got ${bytesLength}`);
|
|
661
|
+
return cr.getRandomValues(new Uint8Array(bytesLength));
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
// ../../node_modules/.pnpm/@noble+curves@2.2.0/node_modules/@noble/curves/utils.js
|
|
665
|
+
var abytes2 = (value, length, title) => abytes(value, length, title);
|
|
666
|
+
var anumber2 = anumber;
|
|
667
|
+
var bytesToHex2 = bytesToHex;
|
|
668
|
+
var concatBytes2 = (...arrays) => concatBytes(...arrays);
|
|
669
|
+
var hexToBytes2 = (hex) => hexToBytes(hex);
|
|
670
|
+
var randomBytes2 = (bytesLength) => randomBytes(bytesLength);
|
|
671
|
+
var _0n = /* @__PURE__ */ BigInt(0);
|
|
672
|
+
var _1n = /* @__PURE__ */ BigInt(1);
|
|
673
|
+
function abool(value, title = "") {
|
|
674
|
+
if (typeof value !== "boolean") {
|
|
675
|
+
const prefix = title && `"${title}" `;
|
|
676
|
+
throw new TypeError(prefix + "expected boolean, got type=" + typeof value);
|
|
677
|
+
}
|
|
678
|
+
return value;
|
|
679
|
+
}
|
|
680
|
+
function abignumber(n) {
|
|
681
|
+
if (typeof n === "bigint") {
|
|
682
|
+
if (!isPosBig(n))
|
|
683
|
+
throw new RangeError("positive bigint expected, got " + n);
|
|
684
|
+
} else
|
|
685
|
+
anumber2(n);
|
|
686
|
+
return n;
|
|
687
|
+
}
|
|
688
|
+
function asafenumber(value, title = "") {
|
|
689
|
+
if (typeof value !== "number") {
|
|
690
|
+
const prefix = title && `"${title}" `;
|
|
691
|
+
throw new TypeError(prefix + "expected number, got type=" + typeof value);
|
|
692
|
+
}
|
|
693
|
+
if (!Number.isSafeInteger(value)) {
|
|
694
|
+
const prefix = title && `"${title}" `;
|
|
695
|
+
throw new RangeError(prefix + "expected safe integer, got " + value);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
function numberToHexUnpadded(num) {
|
|
699
|
+
const hex = abignumber(num).toString(16);
|
|
700
|
+
return hex.length & 1 ? "0" + hex : hex;
|
|
701
|
+
}
|
|
702
|
+
function hexToNumber(hex) {
|
|
703
|
+
if (typeof hex !== "string")
|
|
704
|
+
throw new TypeError("hex string expected, got " + typeof hex);
|
|
705
|
+
return hex === "" ? _0n : BigInt("0x" + hex);
|
|
706
|
+
}
|
|
707
|
+
function bytesToNumberBE(bytes) {
|
|
708
|
+
return hexToNumber(bytesToHex(bytes));
|
|
709
|
+
}
|
|
710
|
+
function bytesToNumberLE(bytes) {
|
|
711
|
+
return hexToNumber(bytesToHex(copyBytes(abytes(bytes)).reverse()));
|
|
712
|
+
}
|
|
713
|
+
function numberToBytesBE(n, len) {
|
|
714
|
+
anumber(len);
|
|
715
|
+
if (len === 0)
|
|
716
|
+
throw new RangeError("zero length");
|
|
717
|
+
n = abignumber(n);
|
|
718
|
+
const hex = n.toString(16);
|
|
719
|
+
if (hex.length > len * 2)
|
|
720
|
+
throw new RangeError("number too large");
|
|
721
|
+
return hexToBytes(hex.padStart(len * 2, "0"));
|
|
722
|
+
}
|
|
723
|
+
function numberToBytesLE(n, len) {
|
|
724
|
+
return numberToBytesBE(n, len).reverse();
|
|
725
|
+
}
|
|
726
|
+
function copyBytes(bytes) {
|
|
727
|
+
return Uint8Array.from(abytes2(bytes));
|
|
728
|
+
}
|
|
729
|
+
var isPosBig = (n) => typeof n === "bigint" && _0n <= n;
|
|
730
|
+
function inRange(n, min, max) {
|
|
731
|
+
return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;
|
|
732
|
+
}
|
|
733
|
+
function aInRange(title, n, min, max) {
|
|
734
|
+
if (!inRange(n, min, max))
|
|
735
|
+
throw new RangeError("expected valid " + title + ": " + min + " <= n < " + max + ", got " + n);
|
|
736
|
+
}
|
|
737
|
+
function bitLen(n) {
|
|
738
|
+
if (n < _0n)
|
|
739
|
+
throw new Error("expected non-negative bigint, got " + n);
|
|
740
|
+
let len;
|
|
741
|
+
for (len = 0; n > _0n; n >>= _1n, len += 1)
|
|
742
|
+
;
|
|
743
|
+
return len;
|
|
744
|
+
}
|
|
745
|
+
function bitGet(n, pos) {
|
|
746
|
+
return n >> BigInt(pos) & _1n;
|
|
747
|
+
}
|
|
748
|
+
var bitMask = (n) => (_1n << BigInt(n)) - _1n;
|
|
749
|
+
function validateObject(object, fields2 = {}, optFields = {}) {
|
|
750
|
+
if (Object.prototype.toString.call(object) !== "[object Object]")
|
|
751
|
+
throw new TypeError("expected valid options object");
|
|
752
|
+
function checkField(fieldName, expectedType, isOpt) {
|
|
753
|
+
if (!isOpt && expectedType !== "function" && !Object.hasOwn(object, fieldName))
|
|
754
|
+
throw new TypeError(`param "${fieldName}" is invalid: expected own property`);
|
|
755
|
+
const val = object[fieldName];
|
|
756
|
+
if (isOpt && val === void 0)
|
|
757
|
+
return;
|
|
758
|
+
const current = typeof val;
|
|
759
|
+
if (current !== expectedType || val === null)
|
|
760
|
+
throw new TypeError(`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`);
|
|
761
|
+
}
|
|
762
|
+
const iter = (f, isOpt) => Object.entries(f).forEach(([k, v]) => checkField(k, v, isOpt));
|
|
763
|
+
iter(fields2, false);
|
|
764
|
+
iter(optFields, true);
|
|
765
|
+
}
|
|
766
|
+
var notImplemented = () => {
|
|
767
|
+
throw new Error("not implemented");
|
|
768
|
+
};
|
|
769
|
+
|
|
770
|
+
// ../../node_modules/.pnpm/@noble+curves@2.2.0/node_modules/@noble/curves/abstract/modular.js
|
|
771
|
+
var _0n2 = /* @__PURE__ */ BigInt(0);
|
|
772
|
+
var _1n2 = /* @__PURE__ */ BigInt(1);
|
|
773
|
+
var _2n = /* @__PURE__ */ BigInt(2);
|
|
774
|
+
var _3n = /* @__PURE__ */ BigInt(3);
|
|
775
|
+
var _4n = /* @__PURE__ */ BigInt(4);
|
|
776
|
+
var _5n = /* @__PURE__ */ BigInt(5);
|
|
777
|
+
var _7n = /* @__PURE__ */ BigInt(7);
|
|
778
|
+
var _8n = /* @__PURE__ */ BigInt(8);
|
|
779
|
+
var _9n = /* @__PURE__ */ BigInt(9);
|
|
780
|
+
var _16n = /* @__PURE__ */ BigInt(16);
|
|
781
|
+
function mod(a, b) {
|
|
782
|
+
if (b <= _0n2)
|
|
783
|
+
throw new Error("mod: expected positive modulus, got " + b);
|
|
784
|
+
const result = a % b;
|
|
785
|
+
return result >= _0n2 ? result : b + result;
|
|
786
|
+
}
|
|
787
|
+
function invert(number, modulo) {
|
|
788
|
+
if (number === _0n2)
|
|
789
|
+
throw new Error("invert: expected non-zero number");
|
|
790
|
+
if (modulo <= _0n2)
|
|
791
|
+
throw new Error("invert: expected positive modulus, got " + modulo);
|
|
792
|
+
let a = mod(number, modulo);
|
|
793
|
+
let b = modulo;
|
|
794
|
+
let x = _0n2, y = _1n2, u = _1n2, v = _0n2;
|
|
795
|
+
while (a !== _0n2) {
|
|
796
|
+
const q = b / a;
|
|
797
|
+
const r = b - a * q;
|
|
798
|
+
const m = x - u * q;
|
|
799
|
+
const n = y - v * q;
|
|
800
|
+
b = a, a = r, x = u, y = v, u = m, v = n;
|
|
801
|
+
}
|
|
802
|
+
const gcd = b;
|
|
803
|
+
if (gcd !== _1n2)
|
|
804
|
+
throw new Error("invert: does not exist");
|
|
805
|
+
return mod(x, modulo);
|
|
806
|
+
}
|
|
807
|
+
function assertIsSquare(Fp3, root, n) {
|
|
808
|
+
const F = Fp3;
|
|
809
|
+
if (!F.eql(F.sqr(root), n))
|
|
810
|
+
throw new Error("Cannot find square root");
|
|
811
|
+
}
|
|
812
|
+
function sqrt3mod4(Fp3, n) {
|
|
813
|
+
const F = Fp3;
|
|
814
|
+
const p1div4 = (F.ORDER + _1n2) / _4n;
|
|
815
|
+
const root = F.pow(n, p1div4);
|
|
816
|
+
assertIsSquare(F, root, n);
|
|
817
|
+
return root;
|
|
818
|
+
}
|
|
819
|
+
function sqrt5mod8(Fp3, n) {
|
|
820
|
+
const F = Fp3;
|
|
821
|
+
const p5div8 = (F.ORDER - _5n) / _8n;
|
|
822
|
+
const n2 = F.mul(n, _2n);
|
|
823
|
+
const v = F.pow(n2, p5div8);
|
|
824
|
+
const nv = F.mul(n, v);
|
|
825
|
+
const i = F.mul(F.mul(nv, _2n), v);
|
|
826
|
+
const root = F.mul(nv, F.sub(i, F.ONE));
|
|
827
|
+
assertIsSquare(F, root, n);
|
|
828
|
+
return root;
|
|
829
|
+
}
|
|
830
|
+
function sqrt9mod16(P) {
|
|
831
|
+
const Fp_ = Field(P);
|
|
832
|
+
const tn = tonelliShanks(P);
|
|
833
|
+
const c1 = tn(Fp_, Fp_.neg(Fp_.ONE));
|
|
834
|
+
const c2 = tn(Fp_, c1);
|
|
835
|
+
const c3 = tn(Fp_, Fp_.neg(c1));
|
|
836
|
+
const c4 = (P + _7n) / _16n;
|
|
837
|
+
return ((Fp3, n) => {
|
|
838
|
+
const F = Fp3;
|
|
839
|
+
let tv1 = F.pow(n, c4);
|
|
840
|
+
let tv2 = F.mul(tv1, c1);
|
|
841
|
+
const tv3 = F.mul(tv1, c2);
|
|
842
|
+
const tv4 = F.mul(tv1, c3);
|
|
843
|
+
const e1 = F.eql(F.sqr(tv2), n);
|
|
844
|
+
const e2 = F.eql(F.sqr(tv3), n);
|
|
845
|
+
tv1 = F.cmov(tv1, tv2, e1);
|
|
846
|
+
tv2 = F.cmov(tv4, tv3, e2);
|
|
847
|
+
const e3 = F.eql(F.sqr(tv2), n);
|
|
848
|
+
const root = F.cmov(tv1, tv2, e3);
|
|
849
|
+
assertIsSquare(F, root, n);
|
|
850
|
+
return root;
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
function tonelliShanks(P) {
|
|
854
|
+
if (P < _3n)
|
|
855
|
+
throw new Error("sqrt is not defined for small field");
|
|
856
|
+
let Q = P - _1n2;
|
|
857
|
+
let S = 0;
|
|
858
|
+
while (Q % _2n === _0n2) {
|
|
859
|
+
Q /= _2n;
|
|
860
|
+
S++;
|
|
861
|
+
}
|
|
862
|
+
let Z = _2n;
|
|
863
|
+
const _Fp = Field(P);
|
|
864
|
+
while (FpLegendre(_Fp, Z) === 1) {
|
|
865
|
+
if (Z++ > 1e3)
|
|
866
|
+
throw new Error("Cannot find square root: probably non-prime P");
|
|
867
|
+
}
|
|
868
|
+
if (S === 1)
|
|
869
|
+
return sqrt3mod4;
|
|
870
|
+
let cc = _Fp.pow(Z, Q);
|
|
871
|
+
const Q1div2 = (Q + _1n2) / _2n;
|
|
872
|
+
return function tonelliSlow(Fp3, n) {
|
|
873
|
+
const F = Fp3;
|
|
874
|
+
if (F.is0(n))
|
|
875
|
+
return n;
|
|
876
|
+
if (FpLegendre(F, n) !== 1)
|
|
877
|
+
throw new Error("Cannot find square root");
|
|
878
|
+
let M = S;
|
|
879
|
+
let c = F.mul(F.ONE, cc);
|
|
880
|
+
let t = F.pow(n, Q);
|
|
881
|
+
let R = F.pow(n, Q1div2);
|
|
882
|
+
while (!F.eql(t, F.ONE)) {
|
|
883
|
+
if (F.is0(t))
|
|
884
|
+
return F.ZERO;
|
|
885
|
+
let i = 1;
|
|
886
|
+
let t_tmp = F.sqr(t);
|
|
887
|
+
while (!F.eql(t_tmp, F.ONE)) {
|
|
888
|
+
i++;
|
|
889
|
+
t_tmp = F.sqr(t_tmp);
|
|
890
|
+
if (i === M)
|
|
891
|
+
throw new Error("Cannot find square root");
|
|
892
|
+
}
|
|
893
|
+
const exponent = _1n2 << BigInt(M - i - 1);
|
|
894
|
+
const b = F.pow(c, exponent);
|
|
895
|
+
M = i;
|
|
896
|
+
c = F.sqr(b);
|
|
897
|
+
t = F.mul(t, c);
|
|
898
|
+
R = F.mul(R, b);
|
|
899
|
+
}
|
|
900
|
+
return R;
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
function FpSqrt(P) {
|
|
904
|
+
if (P % _4n === _3n)
|
|
905
|
+
return sqrt3mod4;
|
|
906
|
+
if (P % _8n === _5n)
|
|
907
|
+
return sqrt5mod8;
|
|
908
|
+
if (P % _16n === _9n)
|
|
909
|
+
return sqrt9mod16(P);
|
|
910
|
+
return tonelliShanks(P);
|
|
911
|
+
}
|
|
912
|
+
var FIELD_FIELDS = [
|
|
913
|
+
"create",
|
|
914
|
+
"isValid",
|
|
915
|
+
"is0",
|
|
916
|
+
"neg",
|
|
917
|
+
"inv",
|
|
918
|
+
"sqrt",
|
|
919
|
+
"sqr",
|
|
920
|
+
"eql",
|
|
921
|
+
"add",
|
|
922
|
+
"sub",
|
|
923
|
+
"mul",
|
|
924
|
+
"pow",
|
|
925
|
+
"div",
|
|
926
|
+
"addN",
|
|
927
|
+
"subN",
|
|
928
|
+
"mulN",
|
|
929
|
+
"sqrN"
|
|
930
|
+
];
|
|
931
|
+
function validateField(field) {
|
|
932
|
+
const initial = {
|
|
933
|
+
ORDER: "bigint",
|
|
934
|
+
BYTES: "number",
|
|
935
|
+
BITS: "number"
|
|
936
|
+
};
|
|
937
|
+
const opts = FIELD_FIELDS.reduce((map, val) => {
|
|
938
|
+
map[val] = "function";
|
|
939
|
+
return map;
|
|
940
|
+
}, initial);
|
|
941
|
+
validateObject(field, opts);
|
|
942
|
+
asafenumber(field.BYTES, "BYTES");
|
|
943
|
+
asafenumber(field.BITS, "BITS");
|
|
944
|
+
if (field.BYTES < 1 || field.BITS < 1)
|
|
945
|
+
throw new Error("invalid field: expected BYTES/BITS > 0");
|
|
946
|
+
if (field.ORDER <= _1n2)
|
|
947
|
+
throw new Error("invalid field: expected ORDER > 1, got " + field.ORDER);
|
|
948
|
+
return field;
|
|
949
|
+
}
|
|
950
|
+
function FpPow(Fp3, num, power) {
|
|
951
|
+
const F = Fp3;
|
|
952
|
+
if (power < _0n2)
|
|
953
|
+
throw new Error("invalid exponent, negatives unsupported");
|
|
954
|
+
if (power === _0n2)
|
|
955
|
+
return F.ONE;
|
|
956
|
+
if (power === _1n2)
|
|
957
|
+
return num;
|
|
958
|
+
let p = F.ONE;
|
|
959
|
+
let d = num;
|
|
960
|
+
while (power > _0n2) {
|
|
961
|
+
if (power & _1n2)
|
|
962
|
+
p = F.mul(p, d);
|
|
963
|
+
d = F.sqr(d);
|
|
964
|
+
power >>= _1n2;
|
|
965
|
+
}
|
|
966
|
+
return p;
|
|
967
|
+
}
|
|
968
|
+
function FpInvertBatch(Fp3, nums, passZero = false) {
|
|
969
|
+
const F = Fp3;
|
|
970
|
+
const inverted = new Array(nums.length).fill(passZero ? F.ZERO : void 0);
|
|
971
|
+
const multipliedAcc = nums.reduce((acc, num, i) => {
|
|
972
|
+
if (F.is0(num))
|
|
973
|
+
return acc;
|
|
974
|
+
inverted[i] = acc;
|
|
975
|
+
return F.mul(acc, num);
|
|
976
|
+
}, F.ONE);
|
|
977
|
+
const invertedAcc = F.inv(multipliedAcc);
|
|
978
|
+
nums.reduceRight((acc, num, i) => {
|
|
979
|
+
if (F.is0(num))
|
|
980
|
+
return acc;
|
|
981
|
+
inverted[i] = F.mul(acc, inverted[i]);
|
|
982
|
+
return F.mul(acc, num);
|
|
983
|
+
}, invertedAcc);
|
|
984
|
+
return inverted;
|
|
985
|
+
}
|
|
986
|
+
function FpLegendre(Fp3, n) {
|
|
987
|
+
const F = Fp3;
|
|
988
|
+
const p1mod2 = (F.ORDER - _1n2) / _2n;
|
|
989
|
+
const powered = F.pow(n, p1mod2);
|
|
990
|
+
const yes = F.eql(powered, F.ONE);
|
|
991
|
+
const zero = F.eql(powered, F.ZERO);
|
|
992
|
+
const no = F.eql(powered, F.neg(F.ONE));
|
|
993
|
+
if (!yes && !zero && !no)
|
|
994
|
+
throw new Error("invalid Legendre symbol result");
|
|
995
|
+
return yes ? 1 : zero ? 0 : -1;
|
|
996
|
+
}
|
|
997
|
+
function nLength(n, nBitLength) {
|
|
998
|
+
if (nBitLength !== void 0)
|
|
999
|
+
anumber2(nBitLength);
|
|
1000
|
+
if (n <= _0n2)
|
|
1001
|
+
throw new Error("invalid n length: expected positive n, got " + n);
|
|
1002
|
+
if (nBitLength !== void 0 && nBitLength < 1)
|
|
1003
|
+
throw new Error("invalid n length: expected positive bit length, got " + nBitLength);
|
|
1004
|
+
const bits = bitLen(n);
|
|
1005
|
+
if (nBitLength !== void 0 && nBitLength < bits)
|
|
1006
|
+
throw new Error(`invalid n length: expected bit length (${bits}) >= n.length (${nBitLength})`);
|
|
1007
|
+
const _nBitLength = nBitLength !== void 0 ? nBitLength : bits;
|
|
1008
|
+
const nByteLength = Math.ceil(_nBitLength / 8);
|
|
1009
|
+
return { nBitLength: _nBitLength, nByteLength };
|
|
1010
|
+
}
|
|
1011
|
+
var FIELD_SQRT = /* @__PURE__ */ new WeakMap();
|
|
1012
|
+
var _Field = class {
|
|
1013
|
+
ORDER;
|
|
1014
|
+
BITS;
|
|
1015
|
+
BYTES;
|
|
1016
|
+
isLE;
|
|
1017
|
+
ZERO = _0n2;
|
|
1018
|
+
ONE = _1n2;
|
|
1019
|
+
_lengths;
|
|
1020
|
+
_mod;
|
|
1021
|
+
constructor(ORDER, opts = {}) {
|
|
1022
|
+
if (ORDER <= _1n2)
|
|
1023
|
+
throw new Error("invalid field: expected ORDER > 1, got " + ORDER);
|
|
1024
|
+
let _nbitLength = void 0;
|
|
1025
|
+
this.isLE = false;
|
|
1026
|
+
if (opts != null && typeof opts === "object") {
|
|
1027
|
+
if (typeof opts.BITS === "number")
|
|
1028
|
+
_nbitLength = opts.BITS;
|
|
1029
|
+
if (typeof opts.sqrt === "function")
|
|
1030
|
+
Object.defineProperty(this, "sqrt", { value: opts.sqrt, enumerable: true });
|
|
1031
|
+
if (typeof opts.isLE === "boolean")
|
|
1032
|
+
this.isLE = opts.isLE;
|
|
1033
|
+
if (opts.allowedLengths)
|
|
1034
|
+
this._lengths = Object.freeze(opts.allowedLengths.slice());
|
|
1035
|
+
if (typeof opts.modFromBytes === "boolean")
|
|
1036
|
+
this._mod = opts.modFromBytes;
|
|
1037
|
+
}
|
|
1038
|
+
const { nBitLength, nByteLength } = nLength(ORDER, _nbitLength);
|
|
1039
|
+
if (nByteLength > 2048)
|
|
1040
|
+
throw new Error("invalid field: expected ORDER of <= 2048 bytes");
|
|
1041
|
+
this.ORDER = ORDER;
|
|
1042
|
+
this.BITS = nBitLength;
|
|
1043
|
+
this.BYTES = nByteLength;
|
|
1044
|
+
Object.freeze(this);
|
|
1045
|
+
}
|
|
1046
|
+
create(num) {
|
|
1047
|
+
return mod(num, this.ORDER);
|
|
1048
|
+
}
|
|
1049
|
+
isValid(num) {
|
|
1050
|
+
if (typeof num !== "bigint")
|
|
1051
|
+
throw new TypeError("invalid field element: expected bigint, got " + typeof num);
|
|
1052
|
+
return _0n2 <= num && num < this.ORDER;
|
|
1053
|
+
}
|
|
1054
|
+
is0(num) {
|
|
1055
|
+
return num === _0n2;
|
|
1056
|
+
}
|
|
1057
|
+
// is valid and invertible
|
|
1058
|
+
isValidNot0(num) {
|
|
1059
|
+
return !this.is0(num) && this.isValid(num);
|
|
1060
|
+
}
|
|
1061
|
+
isOdd(num) {
|
|
1062
|
+
return (num & _1n2) === _1n2;
|
|
1063
|
+
}
|
|
1064
|
+
neg(num) {
|
|
1065
|
+
return mod(-num, this.ORDER);
|
|
1066
|
+
}
|
|
1067
|
+
eql(lhs, rhs) {
|
|
1068
|
+
return lhs === rhs;
|
|
1069
|
+
}
|
|
1070
|
+
sqr(num) {
|
|
1071
|
+
return mod(num * num, this.ORDER);
|
|
1072
|
+
}
|
|
1073
|
+
add(lhs, rhs) {
|
|
1074
|
+
return mod(lhs + rhs, this.ORDER);
|
|
1075
|
+
}
|
|
1076
|
+
sub(lhs, rhs) {
|
|
1077
|
+
return mod(lhs - rhs, this.ORDER);
|
|
1078
|
+
}
|
|
1079
|
+
mul(lhs, rhs) {
|
|
1080
|
+
return mod(lhs * rhs, this.ORDER);
|
|
1081
|
+
}
|
|
1082
|
+
pow(num, power) {
|
|
1083
|
+
return FpPow(this, num, power);
|
|
1084
|
+
}
|
|
1085
|
+
div(lhs, rhs) {
|
|
1086
|
+
return mod(lhs * invert(rhs, this.ORDER), this.ORDER);
|
|
1087
|
+
}
|
|
1088
|
+
// Same as above, but doesn't normalize
|
|
1089
|
+
sqrN(num) {
|
|
1090
|
+
return num * num;
|
|
1091
|
+
}
|
|
1092
|
+
addN(lhs, rhs) {
|
|
1093
|
+
return lhs + rhs;
|
|
1094
|
+
}
|
|
1095
|
+
subN(lhs, rhs) {
|
|
1096
|
+
return lhs - rhs;
|
|
1097
|
+
}
|
|
1098
|
+
mulN(lhs, rhs) {
|
|
1099
|
+
return lhs * rhs;
|
|
1100
|
+
}
|
|
1101
|
+
inv(num) {
|
|
1102
|
+
return invert(num, this.ORDER);
|
|
1103
|
+
}
|
|
1104
|
+
sqrt(num) {
|
|
1105
|
+
let sqrt = FIELD_SQRT.get(this);
|
|
1106
|
+
if (!sqrt)
|
|
1107
|
+
FIELD_SQRT.set(this, sqrt = FpSqrt(this.ORDER));
|
|
1108
|
+
return sqrt(this, num);
|
|
1109
|
+
}
|
|
1110
|
+
toBytes(num) {
|
|
1111
|
+
return this.isLE ? numberToBytesLE(num, this.BYTES) : numberToBytesBE(num, this.BYTES);
|
|
1112
|
+
}
|
|
1113
|
+
fromBytes(bytes, skipValidation = false) {
|
|
1114
|
+
abytes2(bytes);
|
|
1115
|
+
const { _lengths: allowedLengths, BYTES, isLE: isLE2, ORDER, _mod: modFromBytes } = this;
|
|
1116
|
+
if (allowedLengths) {
|
|
1117
|
+
if (bytes.length < 1 || !allowedLengths.includes(bytes.length) || bytes.length > BYTES) {
|
|
1118
|
+
throw new Error("Field.fromBytes: expected " + allowedLengths + " bytes, got " + bytes.length);
|
|
1119
|
+
}
|
|
1120
|
+
const padded = new Uint8Array(BYTES);
|
|
1121
|
+
padded.set(bytes, isLE2 ? 0 : padded.length - bytes.length);
|
|
1122
|
+
bytes = padded;
|
|
1123
|
+
}
|
|
1124
|
+
if (bytes.length !== BYTES)
|
|
1125
|
+
throw new Error("Field.fromBytes: expected " + BYTES + " bytes, got " + bytes.length);
|
|
1126
|
+
let scalar = isLE2 ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
|
|
1127
|
+
if (modFromBytes)
|
|
1128
|
+
scalar = mod(scalar, ORDER);
|
|
1129
|
+
if (!skipValidation) {
|
|
1130
|
+
if (!this.isValid(scalar))
|
|
1131
|
+
throw new Error("invalid field element: outside of range 0..ORDER");
|
|
1132
|
+
}
|
|
1133
|
+
return scalar;
|
|
1134
|
+
}
|
|
1135
|
+
// TODO: we don't need it here, move out to separate fn
|
|
1136
|
+
invertBatch(lst) {
|
|
1137
|
+
return FpInvertBatch(this, lst);
|
|
1138
|
+
}
|
|
1139
|
+
// We can't move this out because Fp6, Fp12 implement it
|
|
1140
|
+
// and it's unclear what to return in there.
|
|
1141
|
+
cmov(a, b, condition) {
|
|
1142
|
+
abool(condition, "condition");
|
|
1143
|
+
return condition ? b : a;
|
|
1144
|
+
}
|
|
1145
|
+
};
|
|
1146
|
+
Object.freeze(_Field.prototype);
|
|
1147
|
+
function Field(ORDER, opts = {}) {
|
|
1148
|
+
return new _Field(ORDER, opts);
|
|
1149
|
+
}
|
|
1150
|
+
function getFieldBytesLength(fieldOrder) {
|
|
1151
|
+
if (typeof fieldOrder !== "bigint")
|
|
1152
|
+
throw new Error("field order must be bigint");
|
|
1153
|
+
if (fieldOrder <= _1n2)
|
|
1154
|
+
throw new Error("field order must be greater than 1");
|
|
1155
|
+
const bitLength = bitLen(fieldOrder - _1n2);
|
|
1156
|
+
return Math.ceil(bitLength / 8);
|
|
1157
|
+
}
|
|
1158
|
+
function getMinHashLength(fieldOrder) {
|
|
1159
|
+
const length = getFieldBytesLength(fieldOrder);
|
|
1160
|
+
return length + Math.ceil(length / 2);
|
|
1161
|
+
}
|
|
1162
|
+
function mapHashToField(key, fieldOrder, isLE2 = false) {
|
|
1163
|
+
abytes2(key);
|
|
1164
|
+
const len = key.length;
|
|
1165
|
+
const fieldLen = getFieldBytesLength(fieldOrder);
|
|
1166
|
+
const minLen = Math.max(getMinHashLength(fieldOrder), 16);
|
|
1167
|
+
if (len < minLen || len > 1024)
|
|
1168
|
+
throw new Error("expected " + minLen + "-1024 bytes of input, got " + len);
|
|
1169
|
+
const num = isLE2 ? bytesToNumberLE(key) : bytesToNumberBE(key);
|
|
1170
|
+
const reduced = mod(num, fieldOrder - _1n2) + _1n2;
|
|
1171
|
+
return isLE2 ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
// ../../node_modules/.pnpm/@noble+curves@2.2.0/node_modules/@noble/curves/abstract/curve.js
|
|
1175
|
+
var _0n3 = /* @__PURE__ */ BigInt(0);
|
|
1176
|
+
var _1n3 = /* @__PURE__ */ BigInt(1);
|
|
1177
|
+
function negateCt(condition, item) {
|
|
1178
|
+
const neg = item.negate();
|
|
1179
|
+
return condition ? neg : item;
|
|
1180
|
+
}
|
|
1181
|
+
function normalizeZ(c, points) {
|
|
1182
|
+
const invertedZs = FpInvertBatch(c.Fp, points.map((p) => p.Z));
|
|
1183
|
+
return points.map((p, i) => c.fromAffine(p.toAffine(invertedZs[i])));
|
|
1184
|
+
}
|
|
1185
|
+
function validateW(W, bits) {
|
|
1186
|
+
if (!Number.isSafeInteger(W) || W <= 0 || W > bits)
|
|
1187
|
+
throw new Error("invalid window size, expected [1.." + bits + "], got W=" + W);
|
|
1188
|
+
}
|
|
1189
|
+
function calcWOpts(W, scalarBits) {
|
|
1190
|
+
validateW(W, scalarBits);
|
|
1191
|
+
const windows = Math.ceil(scalarBits / W) + 1;
|
|
1192
|
+
const windowSize = 2 ** (W - 1);
|
|
1193
|
+
const maxNumber = 2 ** W;
|
|
1194
|
+
const mask = bitMask(W);
|
|
1195
|
+
const shiftBy = BigInt(W);
|
|
1196
|
+
return { windows, windowSize, mask, maxNumber, shiftBy };
|
|
1197
|
+
}
|
|
1198
|
+
function calcOffsets(n, window, wOpts) {
|
|
1199
|
+
const { windowSize, mask, maxNumber, shiftBy } = wOpts;
|
|
1200
|
+
let wbits = Number(n & mask);
|
|
1201
|
+
let nextN = n >> shiftBy;
|
|
1202
|
+
if (wbits > windowSize) {
|
|
1203
|
+
wbits -= maxNumber;
|
|
1204
|
+
nextN += _1n3;
|
|
1205
|
+
}
|
|
1206
|
+
const offsetStart = window * windowSize;
|
|
1207
|
+
const offset = offsetStart + Math.abs(wbits) - 1;
|
|
1208
|
+
const isZero = wbits === 0;
|
|
1209
|
+
const isNeg = wbits < 0;
|
|
1210
|
+
const isNegF = window % 2 !== 0;
|
|
1211
|
+
const offsetF = offsetStart;
|
|
1212
|
+
return { nextN, offset, isZero, isNeg, isNegF, offsetF };
|
|
1213
|
+
}
|
|
1214
|
+
var pointPrecomputes = /* @__PURE__ */ new WeakMap();
|
|
1215
|
+
var pointWindowSizes = /* @__PURE__ */ new WeakMap();
|
|
1216
|
+
function getW(P) {
|
|
1217
|
+
return pointWindowSizes.get(P) || 1;
|
|
1218
|
+
}
|
|
1219
|
+
function assert0(n) {
|
|
1220
|
+
if (n !== _0n3)
|
|
1221
|
+
throw new Error("invalid wNAF");
|
|
1222
|
+
}
|
|
1223
|
+
var wNAF = class {
|
|
1224
|
+
BASE;
|
|
1225
|
+
ZERO;
|
|
1226
|
+
Fn;
|
|
1227
|
+
bits;
|
|
1228
|
+
// Parametrized with a given Point class (not individual point)
|
|
1229
|
+
constructor(Point, bits) {
|
|
1230
|
+
this.BASE = Point.BASE;
|
|
1231
|
+
this.ZERO = Point.ZERO;
|
|
1232
|
+
this.Fn = Point.Fn;
|
|
1233
|
+
this.bits = bits;
|
|
1234
|
+
}
|
|
1235
|
+
// non-const time multiplication ladder
|
|
1236
|
+
_unsafeLadder(elm, n, p = this.ZERO) {
|
|
1237
|
+
let d = elm;
|
|
1238
|
+
while (n > _0n3) {
|
|
1239
|
+
if (n & _1n3)
|
|
1240
|
+
p = p.add(d);
|
|
1241
|
+
d = d.double();
|
|
1242
|
+
n >>= _1n3;
|
|
1243
|
+
}
|
|
1244
|
+
return p;
|
|
1245
|
+
}
|
|
1246
|
+
/**
|
|
1247
|
+
* Creates a wNAF precomputation window. Used for caching.
|
|
1248
|
+
* Default window size is set by `utils.precompute()` and is equal to 8.
|
|
1249
|
+
* Number of precomputed points depends on the curve size:
|
|
1250
|
+
* 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
|
|
1251
|
+
* - 𝑊 is the window size
|
|
1252
|
+
* - 𝑛 is the bitlength of the curve order.
|
|
1253
|
+
* For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
|
|
1254
|
+
* @param point - Point instance
|
|
1255
|
+
* @param W - window size
|
|
1256
|
+
* @returns precomputed point tables flattened to a single array
|
|
1257
|
+
*/
|
|
1258
|
+
precomputeWindow(point, W) {
|
|
1259
|
+
const { windows, windowSize } = calcWOpts(W, this.bits);
|
|
1260
|
+
const points = [];
|
|
1261
|
+
let p = point;
|
|
1262
|
+
let base = p;
|
|
1263
|
+
for (let window = 0; window < windows; window++) {
|
|
1264
|
+
base = p;
|
|
1265
|
+
points.push(base);
|
|
1266
|
+
for (let i = 1; i < windowSize; i++) {
|
|
1267
|
+
base = base.add(p);
|
|
1268
|
+
points.push(base);
|
|
1269
|
+
}
|
|
1270
|
+
p = base.double();
|
|
1271
|
+
}
|
|
1272
|
+
return points;
|
|
1273
|
+
}
|
|
1274
|
+
/**
|
|
1275
|
+
* Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
|
|
1276
|
+
* More compact implementation:
|
|
1277
|
+
* https://github.com/paulmillr/noble-secp256k1/blob/47cb1669b6e506ad66b35fe7d76132ae97465da2/index.ts#L502-L541
|
|
1278
|
+
* @returns real and fake (for const-time) points
|
|
1279
|
+
*/
|
|
1280
|
+
wNAF(W, precomputes, n) {
|
|
1281
|
+
if (!this.Fn.isValid(n))
|
|
1282
|
+
throw new Error("invalid scalar");
|
|
1283
|
+
let p = this.ZERO;
|
|
1284
|
+
let f = this.BASE;
|
|
1285
|
+
const wo = calcWOpts(W, this.bits);
|
|
1286
|
+
for (let window = 0; window < wo.windows; window++) {
|
|
1287
|
+
const { nextN, offset, isZero, isNeg, isNegF, offsetF } = calcOffsets(n, window, wo);
|
|
1288
|
+
n = nextN;
|
|
1289
|
+
if (isZero) {
|
|
1290
|
+
f = f.add(negateCt(isNegF, precomputes[offsetF]));
|
|
1291
|
+
} else {
|
|
1292
|
+
p = p.add(negateCt(isNeg, precomputes[offset]));
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
assert0(n);
|
|
1296
|
+
return { p, f };
|
|
1297
|
+
}
|
|
1298
|
+
/**
|
|
1299
|
+
* Implements unsafe EC multiplication using precomputed tables
|
|
1300
|
+
* and w-ary non-adjacent form.
|
|
1301
|
+
* @param acc - accumulator point to add result of multiplication
|
|
1302
|
+
* @returns point
|
|
1303
|
+
*/
|
|
1304
|
+
wNAFUnsafe(W, precomputes, n, acc = this.ZERO) {
|
|
1305
|
+
const wo = calcWOpts(W, this.bits);
|
|
1306
|
+
for (let window = 0; window < wo.windows; window++) {
|
|
1307
|
+
if (n === _0n3)
|
|
1308
|
+
break;
|
|
1309
|
+
const { nextN, offset, isZero, isNeg } = calcOffsets(n, window, wo);
|
|
1310
|
+
n = nextN;
|
|
1311
|
+
if (isZero) {
|
|
1312
|
+
continue;
|
|
1313
|
+
} else {
|
|
1314
|
+
const item = precomputes[offset];
|
|
1315
|
+
acc = acc.add(isNeg ? item.negate() : item);
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
assert0(n);
|
|
1319
|
+
return acc;
|
|
1320
|
+
}
|
|
1321
|
+
getPrecomputes(W, point, transform) {
|
|
1322
|
+
let comp = pointPrecomputes.get(point);
|
|
1323
|
+
if (!comp) {
|
|
1324
|
+
comp = this.precomputeWindow(point, W);
|
|
1325
|
+
if (W !== 1) {
|
|
1326
|
+
if (typeof transform === "function")
|
|
1327
|
+
comp = transform(comp);
|
|
1328
|
+
pointPrecomputes.set(point, comp);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
return comp;
|
|
1332
|
+
}
|
|
1333
|
+
cached(point, scalar, transform) {
|
|
1334
|
+
const W = getW(point);
|
|
1335
|
+
return this.wNAF(W, this.getPrecomputes(W, point, transform), scalar);
|
|
1336
|
+
}
|
|
1337
|
+
unsafe(point, scalar, transform, prev) {
|
|
1338
|
+
const W = getW(point);
|
|
1339
|
+
if (W === 1)
|
|
1340
|
+
return this._unsafeLadder(point, scalar, prev);
|
|
1341
|
+
return this.wNAFUnsafe(W, this.getPrecomputes(W, point, transform), scalar, prev);
|
|
1342
|
+
}
|
|
1343
|
+
// We calculate precomputes for elliptic curve point multiplication
|
|
1344
|
+
// using windowed method. This specifies window size and
|
|
1345
|
+
// stores precomputed values. Usually only base point would be precomputed.
|
|
1346
|
+
createCache(P, W) {
|
|
1347
|
+
validateW(W, this.bits);
|
|
1348
|
+
pointWindowSizes.set(P, W);
|
|
1349
|
+
pointPrecomputes.delete(P);
|
|
1350
|
+
}
|
|
1351
|
+
hasCache(elm) {
|
|
1352
|
+
return getW(elm) !== 1;
|
|
1353
|
+
}
|
|
1354
|
+
};
|
|
1355
|
+
function mulEndoUnsafe(Point, point, k1, k2) {
|
|
1356
|
+
let acc = point;
|
|
1357
|
+
let p1 = Point.ZERO;
|
|
1358
|
+
let p2 = Point.ZERO;
|
|
1359
|
+
while (k1 > _0n3 || k2 > _0n3) {
|
|
1360
|
+
if (k1 & _1n3)
|
|
1361
|
+
p1 = p1.add(acc);
|
|
1362
|
+
if (k2 & _1n3)
|
|
1363
|
+
p2 = p2.add(acc);
|
|
1364
|
+
acc = acc.double();
|
|
1365
|
+
k1 >>= _1n3;
|
|
1366
|
+
k2 >>= _1n3;
|
|
1367
|
+
}
|
|
1368
|
+
return { p1, p2 };
|
|
1369
|
+
}
|
|
1370
|
+
function createField(order, field, isLE2) {
|
|
1371
|
+
if (field) {
|
|
1372
|
+
if (field.ORDER !== order)
|
|
1373
|
+
throw new Error("Field.ORDER must match order: Fp == p, Fn == n");
|
|
1374
|
+
validateField(field);
|
|
1375
|
+
return field;
|
|
1376
|
+
} else {
|
|
1377
|
+
return Field(order, { isLE: isLE2 });
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
function createCurveFields(type, CURVE, curveOpts = {}, FpFnLE) {
|
|
1381
|
+
if (FpFnLE === void 0)
|
|
1382
|
+
FpFnLE = type === "edwards";
|
|
1383
|
+
if (!CURVE || typeof CURVE !== "object")
|
|
1384
|
+
throw new Error(`expected valid ${type} CURVE object`);
|
|
1385
|
+
for (const p of ["p", "n", "h"]) {
|
|
1386
|
+
const val = CURVE[p];
|
|
1387
|
+
if (!(typeof val === "bigint" && val > _0n3))
|
|
1388
|
+
throw new Error(`CURVE.${p} must be positive bigint`);
|
|
1389
|
+
}
|
|
1390
|
+
const Fp3 = createField(CURVE.p, curveOpts.Fp, FpFnLE);
|
|
1391
|
+
const Fn = createField(CURVE.n, curveOpts.Fn, FpFnLE);
|
|
1392
|
+
const _b = type === "weierstrass" ? "b" : "d";
|
|
1393
|
+
const params = ["Gx", "Gy", "a", _b];
|
|
1394
|
+
for (const p of params) {
|
|
1395
|
+
if (!Fp3.isValid(CURVE[p]))
|
|
1396
|
+
throw new Error(`CURVE.${p} must be valid field element of CURVE.Fp`);
|
|
1397
|
+
}
|
|
1398
|
+
CURVE = Object.freeze(Object.assign({}, CURVE));
|
|
1399
|
+
return { CURVE, Fp: Fp3, Fn };
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
// ../../node_modules/.pnpm/@noble+curves@2.2.0/node_modules/@noble/curves/abstract/weierstrass.js
|
|
1403
|
+
var divNearest = (num, den) => (num + (num >= 0 ? den : -den) / _2n2) / den;
|
|
1404
|
+
function _splitEndoScalar(k, basis, n) {
|
|
1405
|
+
aInRange("scalar", k, _0n4, n);
|
|
1406
|
+
const [[a1, b1], [a2, b2]] = basis;
|
|
1407
|
+
const c1 = divNearest(b2 * k, n);
|
|
1408
|
+
const c2 = divNearest(-b1 * k, n);
|
|
1409
|
+
let k1 = k - c1 * a1 - c2 * a2;
|
|
1410
|
+
let k2 = -c1 * b1 - c2 * b2;
|
|
1411
|
+
const k1neg = k1 < _0n4;
|
|
1412
|
+
const k2neg = k2 < _0n4;
|
|
1413
|
+
if (k1neg)
|
|
1414
|
+
k1 = -k1;
|
|
1415
|
+
if (k2neg)
|
|
1416
|
+
k2 = -k2;
|
|
1417
|
+
const MAX_NUM = bitMask(Math.ceil(bitLen(n) / 2)) + _1n4;
|
|
1418
|
+
if (k1 < _0n4 || k1 >= MAX_NUM || k2 < _0n4 || k2 >= MAX_NUM) {
|
|
1419
|
+
throw new Error("splitScalar (endomorphism): failed for k");
|
|
1420
|
+
}
|
|
1421
|
+
return { k1neg, k1, k2neg, k2 };
|
|
1422
|
+
}
|
|
1423
|
+
var DERErr = class extends Error {
|
|
1424
|
+
constructor(m = "") {
|
|
1425
|
+
super(m);
|
|
1426
|
+
}
|
|
1427
|
+
};
|
|
1428
|
+
var DER = {
|
|
1429
|
+
// asn.1 DER encoding utils
|
|
1430
|
+
Err: DERErr,
|
|
1431
|
+
// Basic building block is TLV (Tag-Length-Value)
|
|
1432
|
+
_tlv: {
|
|
1433
|
+
encode: (tag, data) => {
|
|
1434
|
+
const { Err: E } = DER;
|
|
1435
|
+
asafenumber(tag, "tag");
|
|
1436
|
+
if (tag < 0 || tag > 255)
|
|
1437
|
+
throw new E("tlv.encode: wrong tag");
|
|
1438
|
+
if (typeof data !== "string")
|
|
1439
|
+
throw new TypeError('"data" expected string, got type=' + typeof data);
|
|
1440
|
+
if (data.length & 1)
|
|
1441
|
+
throw new E("tlv.encode: unpadded data");
|
|
1442
|
+
const dataLen = data.length / 2;
|
|
1443
|
+
const len = numberToHexUnpadded(dataLen);
|
|
1444
|
+
if (len.length / 2 & 128)
|
|
1445
|
+
throw new E("tlv.encode: long form length too big");
|
|
1446
|
+
const lenLen = dataLen > 127 ? numberToHexUnpadded(len.length / 2 | 128) : "";
|
|
1447
|
+
const t = numberToHexUnpadded(tag);
|
|
1448
|
+
return t + lenLen + len + data;
|
|
1449
|
+
},
|
|
1450
|
+
// v - value, l - left bytes (unparsed)
|
|
1451
|
+
decode(tag, data) {
|
|
1452
|
+
const { Err: E } = DER;
|
|
1453
|
+
data = abytes2(data, void 0, "DER data");
|
|
1454
|
+
let pos = 0;
|
|
1455
|
+
if (tag < 0 || tag > 255)
|
|
1456
|
+
throw new E("tlv.encode: wrong tag");
|
|
1457
|
+
if (data.length < 2 || data[pos++] !== tag)
|
|
1458
|
+
throw new E("tlv.decode: wrong tlv");
|
|
1459
|
+
const first = data[pos++];
|
|
1460
|
+
const isLong = !!(first & 128);
|
|
1461
|
+
let length = 0;
|
|
1462
|
+
if (!isLong)
|
|
1463
|
+
length = first;
|
|
1464
|
+
else {
|
|
1465
|
+
const lenLen = first & 127;
|
|
1466
|
+
if (!lenLen)
|
|
1467
|
+
throw new E("tlv.decode(long): indefinite length not supported");
|
|
1468
|
+
if (lenLen > 4)
|
|
1469
|
+
throw new E("tlv.decode(long): byte length is too big");
|
|
1470
|
+
const lengthBytes = data.subarray(pos, pos + lenLen);
|
|
1471
|
+
if (lengthBytes.length !== lenLen)
|
|
1472
|
+
throw new E("tlv.decode: length bytes not complete");
|
|
1473
|
+
if (lengthBytes[0] === 0)
|
|
1474
|
+
throw new E("tlv.decode(long): zero leftmost byte");
|
|
1475
|
+
for (const b of lengthBytes)
|
|
1476
|
+
length = length << 8 | b;
|
|
1477
|
+
pos += lenLen;
|
|
1478
|
+
if (length < 128)
|
|
1479
|
+
throw new E("tlv.decode(long): not minimal encoding");
|
|
1480
|
+
}
|
|
1481
|
+
const v = data.subarray(pos, pos + length);
|
|
1482
|
+
if (v.length !== length)
|
|
1483
|
+
throw new E("tlv.decode: wrong value length");
|
|
1484
|
+
return { v, l: data.subarray(pos + length) };
|
|
1485
|
+
}
|
|
1486
|
+
},
|
|
1487
|
+
// https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,
|
|
1488
|
+
// since we always use positive integers here. It must always be empty:
|
|
1489
|
+
// - add zero byte if exists
|
|
1490
|
+
// - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)
|
|
1491
|
+
_int: {
|
|
1492
|
+
encode(num) {
|
|
1493
|
+
const { Err: E } = DER;
|
|
1494
|
+
abignumber(num);
|
|
1495
|
+
if (num < _0n4)
|
|
1496
|
+
throw new E("integer: negative integers are not allowed");
|
|
1497
|
+
let hex = numberToHexUnpadded(num);
|
|
1498
|
+
if (Number.parseInt(hex[0], 16) & 8)
|
|
1499
|
+
hex = "00" + hex;
|
|
1500
|
+
if (hex.length & 1)
|
|
1501
|
+
throw new E("unexpected DER parsing assertion: unpadded hex");
|
|
1502
|
+
return hex;
|
|
1503
|
+
},
|
|
1504
|
+
decode(data) {
|
|
1505
|
+
const { Err: E } = DER;
|
|
1506
|
+
if (data.length < 1)
|
|
1507
|
+
throw new E("invalid signature integer: empty");
|
|
1508
|
+
if (data[0] & 128)
|
|
1509
|
+
throw new E("invalid signature integer: negative");
|
|
1510
|
+
if (data.length > 1 && data[0] === 0 && !(data[1] & 128))
|
|
1511
|
+
throw new E("invalid signature integer: unnecessary leading zero");
|
|
1512
|
+
return bytesToNumberBE(data);
|
|
1513
|
+
}
|
|
1514
|
+
},
|
|
1515
|
+
toSig(bytes) {
|
|
1516
|
+
const { Err: E, _int: int, _tlv: tlv } = DER;
|
|
1517
|
+
const data = abytes2(bytes, void 0, "signature");
|
|
1518
|
+
const { v: seqBytes, l: seqLeftBytes } = tlv.decode(48, data);
|
|
1519
|
+
if (seqLeftBytes.length)
|
|
1520
|
+
throw new E("invalid signature: left bytes after parsing");
|
|
1521
|
+
const { v: rBytes, l: rLeftBytes } = tlv.decode(2, seqBytes);
|
|
1522
|
+
const { v: sBytes, l: sLeftBytes } = tlv.decode(2, rLeftBytes);
|
|
1523
|
+
if (sLeftBytes.length)
|
|
1524
|
+
throw new E("invalid signature: left bytes after parsing");
|
|
1525
|
+
return { r: int.decode(rBytes), s: int.decode(sBytes) };
|
|
1526
|
+
},
|
|
1527
|
+
hexFromSig(sig) {
|
|
1528
|
+
const { _tlv: tlv, _int: int } = DER;
|
|
1529
|
+
const rs = tlv.encode(2, int.encode(sig.r));
|
|
1530
|
+
const ss = tlv.encode(2, int.encode(sig.s));
|
|
1531
|
+
const seq = rs + ss;
|
|
1532
|
+
return tlv.encode(48, seq);
|
|
1533
|
+
}
|
|
1534
|
+
};
|
|
1535
|
+
Object.freeze(DER._tlv);
|
|
1536
|
+
Object.freeze(DER._int);
|
|
1537
|
+
Object.freeze(DER);
|
|
1538
|
+
var _0n4 = /* @__PURE__ */ BigInt(0);
|
|
1539
|
+
var _1n4 = /* @__PURE__ */ BigInt(1);
|
|
1540
|
+
var _2n2 = /* @__PURE__ */ BigInt(2);
|
|
1541
|
+
var _3n2 = /* @__PURE__ */ BigInt(3);
|
|
1542
|
+
var _4n2 = /* @__PURE__ */ BigInt(4);
|
|
1543
|
+
function weierstrass(params, extraOpts = {}) {
|
|
1544
|
+
const validated = createCurveFields("weierstrass", params, extraOpts);
|
|
1545
|
+
const Fp3 = validated.Fp;
|
|
1546
|
+
const Fn = validated.Fn;
|
|
1547
|
+
let CURVE = validated.CURVE;
|
|
1548
|
+
const { h: cofactor, n: CURVE_ORDER } = CURVE;
|
|
1549
|
+
validateObject(extraOpts, {}, {
|
|
1550
|
+
allowInfinityPoint: "boolean",
|
|
1551
|
+
clearCofactor: "function",
|
|
1552
|
+
isTorsionFree: "function",
|
|
1553
|
+
fromBytes: "function",
|
|
1554
|
+
toBytes: "function",
|
|
1555
|
+
endo: "object"
|
|
1556
|
+
});
|
|
1557
|
+
const { endo, allowInfinityPoint } = extraOpts;
|
|
1558
|
+
if (endo) {
|
|
1559
|
+
if (!Fp3.is0(CURVE.a) || typeof endo.beta !== "bigint" || !Array.isArray(endo.basises)) {
|
|
1560
|
+
throw new Error('invalid endo: expected "beta": bigint and "basises": array');
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
const lengths = getWLengths(Fp3, Fn);
|
|
1564
|
+
function assertCompressionIsSupported() {
|
|
1565
|
+
if (!Fp3.isOdd)
|
|
1566
|
+
throw new Error("compression is not supported: Field does not have .isOdd()");
|
|
1567
|
+
}
|
|
1568
|
+
function pointToBytes(_c, point, isCompressed) {
|
|
1569
|
+
if (allowInfinityPoint && point.is0())
|
|
1570
|
+
return Uint8Array.of(0);
|
|
1571
|
+
const { x, y } = point.toAffine();
|
|
1572
|
+
const bx = Fp3.toBytes(x);
|
|
1573
|
+
abool(isCompressed, "isCompressed");
|
|
1574
|
+
if (isCompressed) {
|
|
1575
|
+
assertCompressionIsSupported();
|
|
1576
|
+
const hasEvenY = !Fp3.isOdd(y);
|
|
1577
|
+
return concatBytes2(pprefix(hasEvenY), bx);
|
|
1578
|
+
} else {
|
|
1579
|
+
return concatBytes2(Uint8Array.of(4), bx, Fp3.toBytes(y));
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
function pointFromBytes(bytes) {
|
|
1583
|
+
abytes2(bytes, void 0, "Point");
|
|
1584
|
+
const { publicKey: comp, publicKeyUncompressed: uncomp } = lengths;
|
|
1585
|
+
const length = bytes.length;
|
|
1586
|
+
const head = bytes[0];
|
|
1587
|
+
const tail = bytes.subarray(1);
|
|
1588
|
+
if (allowInfinityPoint && length === 1 && head === 0)
|
|
1589
|
+
return { x: Fp3.ZERO, y: Fp3.ZERO };
|
|
1590
|
+
if (length === comp && (head === 2 || head === 3)) {
|
|
1591
|
+
const x = Fp3.fromBytes(tail);
|
|
1592
|
+
if (!Fp3.isValid(x))
|
|
1593
|
+
throw new Error("bad point: is not on curve, wrong x");
|
|
1594
|
+
const y2 = weierstrassEquation(x);
|
|
1595
|
+
let y;
|
|
1596
|
+
try {
|
|
1597
|
+
y = Fp3.sqrt(y2);
|
|
1598
|
+
} catch (sqrtError) {
|
|
1599
|
+
const err = sqrtError instanceof Error ? ": " + sqrtError.message : "";
|
|
1600
|
+
throw new Error("bad point: is not on curve, sqrt error" + err);
|
|
1601
|
+
}
|
|
1602
|
+
assertCompressionIsSupported();
|
|
1603
|
+
const evenY = Fp3.isOdd(y);
|
|
1604
|
+
const evenH = (head & 1) === 1;
|
|
1605
|
+
if (evenH !== evenY)
|
|
1606
|
+
y = Fp3.neg(y);
|
|
1607
|
+
return { x, y };
|
|
1608
|
+
} else if (length === uncomp && head === 4) {
|
|
1609
|
+
const L = Fp3.BYTES;
|
|
1610
|
+
const x = Fp3.fromBytes(tail.subarray(0, L));
|
|
1611
|
+
const y = Fp3.fromBytes(tail.subarray(L, L * 2));
|
|
1612
|
+
if (!isValidXY(x, y))
|
|
1613
|
+
throw new Error("bad point: is not on curve");
|
|
1614
|
+
return { x, y };
|
|
1615
|
+
} else {
|
|
1616
|
+
throw new Error(`bad point: got length ${length}, expected compressed=${comp} or uncompressed=${uncomp}`);
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
const encodePoint = extraOpts.toBytes === void 0 ? pointToBytes : extraOpts.toBytes;
|
|
1620
|
+
const decodePoint = extraOpts.fromBytes === void 0 ? pointFromBytes : extraOpts.fromBytes;
|
|
1621
|
+
function weierstrassEquation(x) {
|
|
1622
|
+
const x2 = Fp3.sqr(x);
|
|
1623
|
+
const x3 = Fp3.mul(x2, x);
|
|
1624
|
+
return Fp3.add(Fp3.add(x3, Fp3.mul(x, CURVE.a)), CURVE.b);
|
|
1625
|
+
}
|
|
1626
|
+
function isValidXY(x, y) {
|
|
1627
|
+
const left = Fp3.sqr(y);
|
|
1628
|
+
const right = weierstrassEquation(x);
|
|
1629
|
+
return Fp3.eql(left, right);
|
|
1630
|
+
}
|
|
1631
|
+
if (!isValidXY(CURVE.Gx, CURVE.Gy))
|
|
1632
|
+
throw new Error("bad curve params: generator point");
|
|
1633
|
+
const _4a3 = Fp3.mul(Fp3.pow(CURVE.a, _3n2), _4n2);
|
|
1634
|
+
const _27b2 = Fp3.mul(Fp3.sqr(CURVE.b), BigInt(27));
|
|
1635
|
+
if (Fp3.is0(Fp3.add(_4a3, _27b2)))
|
|
1636
|
+
throw new Error("bad curve params: a or b");
|
|
1637
|
+
function acoord(title, n, banZero = false) {
|
|
1638
|
+
if (!Fp3.isValid(n) || banZero && Fp3.is0(n))
|
|
1639
|
+
throw new Error(`bad point coordinate ${title}`);
|
|
1640
|
+
return n;
|
|
1641
|
+
}
|
|
1642
|
+
function aprjpoint(other) {
|
|
1643
|
+
if (!(other instanceof Point))
|
|
1644
|
+
throw new Error("Weierstrass Point expected");
|
|
1645
|
+
}
|
|
1646
|
+
function splitEndoScalarN(k) {
|
|
1647
|
+
if (!endo || !endo.basises)
|
|
1648
|
+
throw new Error("no endo");
|
|
1649
|
+
return _splitEndoScalar(k, endo.basises, Fn.ORDER);
|
|
1650
|
+
}
|
|
1651
|
+
function finishEndo(endoBeta, k1p, k2p, k1neg, k2neg) {
|
|
1652
|
+
k2p = new Point(Fp3.mul(k2p.X, endoBeta), k2p.Y, k2p.Z);
|
|
1653
|
+
k1p = negateCt(k1neg, k1p);
|
|
1654
|
+
k2p = negateCt(k2neg, k2p);
|
|
1655
|
+
return k1p.add(k2p);
|
|
1656
|
+
}
|
|
1657
|
+
class Point {
|
|
1658
|
+
// base / generator point
|
|
1659
|
+
static BASE = new Point(CURVE.Gx, CURVE.Gy, Fp3.ONE);
|
|
1660
|
+
// zero / infinity / identity point
|
|
1661
|
+
static ZERO = new Point(Fp3.ZERO, Fp3.ONE, Fp3.ZERO);
|
|
1662
|
+
// 0, 1, 0
|
|
1663
|
+
// math field
|
|
1664
|
+
static Fp = Fp3;
|
|
1665
|
+
// scalar field
|
|
1666
|
+
static Fn = Fn;
|
|
1667
|
+
X;
|
|
1668
|
+
Y;
|
|
1669
|
+
Z;
|
|
1670
|
+
/** Does NOT validate if the point is valid. Use `.assertValidity()`. */
|
|
1671
|
+
constructor(X, Y, Z) {
|
|
1672
|
+
this.X = acoord("x", X);
|
|
1673
|
+
this.Y = acoord("y", Y, true);
|
|
1674
|
+
this.Z = acoord("z", Z);
|
|
1675
|
+
Object.freeze(this);
|
|
1676
|
+
}
|
|
1677
|
+
static CURVE() {
|
|
1678
|
+
return CURVE;
|
|
1679
|
+
}
|
|
1680
|
+
/** Does NOT validate if the point is valid. Use `.assertValidity()`. */
|
|
1681
|
+
static fromAffine(p) {
|
|
1682
|
+
const { x, y } = p || {};
|
|
1683
|
+
if (!p || !Fp3.isValid(x) || !Fp3.isValid(y))
|
|
1684
|
+
throw new Error("invalid affine point");
|
|
1685
|
+
if (p instanceof Point)
|
|
1686
|
+
throw new Error("projective point not allowed");
|
|
1687
|
+
if (Fp3.is0(x) && Fp3.is0(y))
|
|
1688
|
+
return Point.ZERO;
|
|
1689
|
+
return new Point(x, y, Fp3.ONE);
|
|
1690
|
+
}
|
|
1691
|
+
static fromBytes(bytes) {
|
|
1692
|
+
const P = Point.fromAffine(decodePoint(abytes2(bytes, void 0, "point")));
|
|
1693
|
+
P.assertValidity();
|
|
1694
|
+
return P;
|
|
1695
|
+
}
|
|
1696
|
+
static fromHex(hex) {
|
|
1697
|
+
return Point.fromBytes(hexToBytes2(hex));
|
|
1698
|
+
}
|
|
1699
|
+
get x() {
|
|
1700
|
+
return this.toAffine().x;
|
|
1701
|
+
}
|
|
1702
|
+
get y() {
|
|
1703
|
+
return this.toAffine().y;
|
|
1704
|
+
}
|
|
1705
|
+
/**
|
|
1706
|
+
*
|
|
1707
|
+
* @param windowSize
|
|
1708
|
+
* @param isLazy - true will defer table computation until the first multiplication
|
|
1709
|
+
* @returns
|
|
1710
|
+
*/
|
|
1711
|
+
precompute(windowSize = 8, isLazy = true) {
|
|
1712
|
+
wnaf.createCache(this, windowSize);
|
|
1713
|
+
if (!isLazy)
|
|
1714
|
+
this.multiply(_3n2);
|
|
1715
|
+
return this;
|
|
1716
|
+
}
|
|
1717
|
+
// TODO: return `this`
|
|
1718
|
+
/** A point on curve is valid if it conforms to equation. */
|
|
1719
|
+
assertValidity() {
|
|
1720
|
+
const p = this;
|
|
1721
|
+
if (p.is0()) {
|
|
1722
|
+
if (extraOpts.allowInfinityPoint && Fp3.is0(p.X) && Fp3.eql(p.Y, Fp3.ONE) && Fp3.is0(p.Z))
|
|
1723
|
+
return;
|
|
1724
|
+
throw new Error("bad point: ZERO");
|
|
1725
|
+
}
|
|
1726
|
+
const { x, y } = p.toAffine();
|
|
1727
|
+
if (!Fp3.isValid(x) || !Fp3.isValid(y))
|
|
1728
|
+
throw new Error("bad point: x or y not field elements");
|
|
1729
|
+
if (!isValidXY(x, y))
|
|
1730
|
+
throw new Error("bad point: equation left != right");
|
|
1731
|
+
if (!p.isTorsionFree())
|
|
1732
|
+
throw new Error("bad point: not in prime-order subgroup");
|
|
1733
|
+
}
|
|
1734
|
+
hasEvenY() {
|
|
1735
|
+
const { y } = this.toAffine();
|
|
1736
|
+
if (!Fp3.isOdd)
|
|
1737
|
+
throw new Error("Field doesn't support isOdd");
|
|
1738
|
+
return !Fp3.isOdd(y);
|
|
1739
|
+
}
|
|
1740
|
+
/** Compare one point to another. */
|
|
1741
|
+
equals(other) {
|
|
1742
|
+
aprjpoint(other);
|
|
1743
|
+
const { X: X1, Y: Y1, Z: Z1 } = this;
|
|
1744
|
+
const { X: X2, Y: Y2, Z: Z2 } = other;
|
|
1745
|
+
const U1 = Fp3.eql(Fp3.mul(X1, Z2), Fp3.mul(X2, Z1));
|
|
1746
|
+
const U2 = Fp3.eql(Fp3.mul(Y1, Z2), Fp3.mul(Y2, Z1));
|
|
1747
|
+
return U1 && U2;
|
|
1748
|
+
}
|
|
1749
|
+
/** Flips point to one corresponding to (x, -y) in Affine coordinates. */
|
|
1750
|
+
negate() {
|
|
1751
|
+
return new Point(this.X, Fp3.neg(this.Y), this.Z);
|
|
1752
|
+
}
|
|
1753
|
+
// Renes-Costello-Batina exception-free doubling formula.
|
|
1754
|
+
// There is 30% faster Jacobian formula, but it is not complete.
|
|
1755
|
+
// https://eprint.iacr.org/2015/1060, algorithm 3
|
|
1756
|
+
// Cost: 8M + 3S + 3*a + 2*b3 + 15add.
|
|
1757
|
+
double() {
|
|
1758
|
+
const { a, b } = CURVE;
|
|
1759
|
+
const b3 = Fp3.mul(b, _3n2);
|
|
1760
|
+
const { X: X1, Y: Y1, Z: Z1 } = this;
|
|
1761
|
+
let X3 = Fp3.ZERO, Y3 = Fp3.ZERO, Z3 = Fp3.ZERO;
|
|
1762
|
+
let t0 = Fp3.mul(X1, X1);
|
|
1763
|
+
let t1 = Fp3.mul(Y1, Y1);
|
|
1764
|
+
let t2 = Fp3.mul(Z1, Z1);
|
|
1765
|
+
let t3 = Fp3.mul(X1, Y1);
|
|
1766
|
+
t3 = Fp3.add(t3, t3);
|
|
1767
|
+
Z3 = Fp3.mul(X1, Z1);
|
|
1768
|
+
Z3 = Fp3.add(Z3, Z3);
|
|
1769
|
+
X3 = Fp3.mul(a, Z3);
|
|
1770
|
+
Y3 = Fp3.mul(b3, t2);
|
|
1771
|
+
Y3 = Fp3.add(X3, Y3);
|
|
1772
|
+
X3 = Fp3.sub(t1, Y3);
|
|
1773
|
+
Y3 = Fp3.add(t1, Y3);
|
|
1774
|
+
Y3 = Fp3.mul(X3, Y3);
|
|
1775
|
+
X3 = Fp3.mul(t3, X3);
|
|
1776
|
+
Z3 = Fp3.mul(b3, Z3);
|
|
1777
|
+
t2 = Fp3.mul(a, t2);
|
|
1778
|
+
t3 = Fp3.sub(t0, t2);
|
|
1779
|
+
t3 = Fp3.mul(a, t3);
|
|
1780
|
+
t3 = Fp3.add(t3, Z3);
|
|
1781
|
+
Z3 = Fp3.add(t0, t0);
|
|
1782
|
+
t0 = Fp3.add(Z3, t0);
|
|
1783
|
+
t0 = Fp3.add(t0, t2);
|
|
1784
|
+
t0 = Fp3.mul(t0, t3);
|
|
1785
|
+
Y3 = Fp3.add(Y3, t0);
|
|
1786
|
+
t2 = Fp3.mul(Y1, Z1);
|
|
1787
|
+
t2 = Fp3.add(t2, t2);
|
|
1788
|
+
t0 = Fp3.mul(t2, t3);
|
|
1789
|
+
X3 = Fp3.sub(X3, t0);
|
|
1790
|
+
Z3 = Fp3.mul(t2, t1);
|
|
1791
|
+
Z3 = Fp3.add(Z3, Z3);
|
|
1792
|
+
Z3 = Fp3.add(Z3, Z3);
|
|
1793
|
+
return new Point(X3, Y3, Z3);
|
|
1794
|
+
}
|
|
1795
|
+
// Renes-Costello-Batina exception-free addition formula.
|
|
1796
|
+
// There is 30% faster Jacobian formula, but it is not complete.
|
|
1797
|
+
// https://eprint.iacr.org/2015/1060, algorithm 1
|
|
1798
|
+
// Cost: 12M + 0S + 3*a + 3*b3 + 23add.
|
|
1799
|
+
add(other) {
|
|
1800
|
+
aprjpoint(other);
|
|
1801
|
+
const { X: X1, Y: Y1, Z: Z1 } = this;
|
|
1802
|
+
const { X: X2, Y: Y2, Z: Z2 } = other;
|
|
1803
|
+
let X3 = Fp3.ZERO, Y3 = Fp3.ZERO, Z3 = Fp3.ZERO;
|
|
1804
|
+
const a = CURVE.a;
|
|
1805
|
+
const b3 = Fp3.mul(CURVE.b, _3n2);
|
|
1806
|
+
let t0 = Fp3.mul(X1, X2);
|
|
1807
|
+
let t1 = Fp3.mul(Y1, Y2);
|
|
1808
|
+
let t2 = Fp3.mul(Z1, Z2);
|
|
1809
|
+
let t3 = Fp3.add(X1, Y1);
|
|
1810
|
+
let t4 = Fp3.add(X2, Y2);
|
|
1811
|
+
t3 = Fp3.mul(t3, t4);
|
|
1812
|
+
t4 = Fp3.add(t0, t1);
|
|
1813
|
+
t3 = Fp3.sub(t3, t4);
|
|
1814
|
+
t4 = Fp3.add(X1, Z1);
|
|
1815
|
+
let t5 = Fp3.add(X2, Z2);
|
|
1816
|
+
t4 = Fp3.mul(t4, t5);
|
|
1817
|
+
t5 = Fp3.add(t0, t2);
|
|
1818
|
+
t4 = Fp3.sub(t4, t5);
|
|
1819
|
+
t5 = Fp3.add(Y1, Z1);
|
|
1820
|
+
X3 = Fp3.add(Y2, Z2);
|
|
1821
|
+
t5 = Fp3.mul(t5, X3);
|
|
1822
|
+
X3 = Fp3.add(t1, t2);
|
|
1823
|
+
t5 = Fp3.sub(t5, X3);
|
|
1824
|
+
Z3 = Fp3.mul(a, t4);
|
|
1825
|
+
X3 = Fp3.mul(b3, t2);
|
|
1826
|
+
Z3 = Fp3.add(X3, Z3);
|
|
1827
|
+
X3 = Fp3.sub(t1, Z3);
|
|
1828
|
+
Z3 = Fp3.add(t1, Z3);
|
|
1829
|
+
Y3 = Fp3.mul(X3, Z3);
|
|
1830
|
+
t1 = Fp3.add(t0, t0);
|
|
1831
|
+
t1 = Fp3.add(t1, t0);
|
|
1832
|
+
t2 = Fp3.mul(a, t2);
|
|
1833
|
+
t4 = Fp3.mul(b3, t4);
|
|
1834
|
+
t1 = Fp3.add(t1, t2);
|
|
1835
|
+
t2 = Fp3.sub(t0, t2);
|
|
1836
|
+
t2 = Fp3.mul(a, t2);
|
|
1837
|
+
t4 = Fp3.add(t4, t2);
|
|
1838
|
+
t0 = Fp3.mul(t1, t4);
|
|
1839
|
+
Y3 = Fp3.add(Y3, t0);
|
|
1840
|
+
t0 = Fp3.mul(t5, t4);
|
|
1841
|
+
X3 = Fp3.mul(t3, X3);
|
|
1842
|
+
X3 = Fp3.sub(X3, t0);
|
|
1843
|
+
t0 = Fp3.mul(t3, t1);
|
|
1844
|
+
Z3 = Fp3.mul(t5, Z3);
|
|
1845
|
+
Z3 = Fp3.add(Z3, t0);
|
|
1846
|
+
return new Point(X3, Y3, Z3);
|
|
1847
|
+
}
|
|
1848
|
+
subtract(other) {
|
|
1849
|
+
aprjpoint(other);
|
|
1850
|
+
return this.add(other.negate());
|
|
1851
|
+
}
|
|
1852
|
+
is0() {
|
|
1853
|
+
return this.equals(Point.ZERO);
|
|
1854
|
+
}
|
|
1855
|
+
/**
|
|
1856
|
+
* Constant time multiplication.
|
|
1857
|
+
* Uses wNAF method. Windowed method may be 10% faster,
|
|
1858
|
+
* but takes 2x longer to generate and consumes 2x memory.
|
|
1859
|
+
* Uses precomputes when available.
|
|
1860
|
+
* Uses endomorphism for Koblitz curves.
|
|
1861
|
+
* @param scalar - by which the point would be multiplied
|
|
1862
|
+
* @returns New point
|
|
1863
|
+
*/
|
|
1864
|
+
multiply(scalar) {
|
|
1865
|
+
const { endo: endo2 } = extraOpts;
|
|
1866
|
+
if (!Fn.isValidNot0(scalar))
|
|
1867
|
+
throw new RangeError("invalid scalar: out of range");
|
|
1868
|
+
let point, fake;
|
|
1869
|
+
const mul = (n) => wnaf.cached(this, n, (p) => normalizeZ(Point, p));
|
|
1870
|
+
if (endo2) {
|
|
1871
|
+
const { k1neg, k1, k2neg, k2 } = splitEndoScalarN(scalar);
|
|
1872
|
+
const { p: k1p, f: k1f } = mul(k1);
|
|
1873
|
+
const { p: k2p, f: k2f } = mul(k2);
|
|
1874
|
+
fake = k1f.add(k2f);
|
|
1875
|
+
point = finishEndo(endo2.beta, k1p, k2p, k1neg, k2neg);
|
|
1876
|
+
} else {
|
|
1877
|
+
const { p, f } = mul(scalar);
|
|
1878
|
+
point = p;
|
|
1879
|
+
fake = f;
|
|
1880
|
+
}
|
|
1881
|
+
return normalizeZ(Point, [point, fake])[0];
|
|
1882
|
+
}
|
|
1883
|
+
/**
|
|
1884
|
+
* Non-constant-time multiplication. Uses double-and-add algorithm.
|
|
1885
|
+
* It's faster, but should only be used when you don't care about
|
|
1886
|
+
* an exposed secret key e.g. sig verification, which works over *public* keys.
|
|
1887
|
+
*/
|
|
1888
|
+
multiplyUnsafe(scalar) {
|
|
1889
|
+
const { endo: endo2 } = extraOpts;
|
|
1890
|
+
const p = this;
|
|
1891
|
+
const sc = scalar;
|
|
1892
|
+
if (!Fn.isValid(sc))
|
|
1893
|
+
throw new RangeError("invalid scalar: out of range");
|
|
1894
|
+
if (sc === _0n4 || p.is0())
|
|
1895
|
+
return Point.ZERO;
|
|
1896
|
+
if (sc === _1n4)
|
|
1897
|
+
return p;
|
|
1898
|
+
if (wnaf.hasCache(this))
|
|
1899
|
+
return this.multiply(sc);
|
|
1900
|
+
if (endo2) {
|
|
1901
|
+
const { k1neg, k1, k2neg, k2 } = splitEndoScalarN(sc);
|
|
1902
|
+
const { p1, p2 } = mulEndoUnsafe(Point, p, k1, k2);
|
|
1903
|
+
return finishEndo(endo2.beta, p1, p2, k1neg, k2neg);
|
|
1904
|
+
} else {
|
|
1905
|
+
return wnaf.unsafe(p, sc);
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
/**
|
|
1909
|
+
* Converts Projective point to affine (x, y) coordinates.
|
|
1910
|
+
* (X, Y, Z) ∋ (x=X/Z, y=Y/Z).
|
|
1911
|
+
* @param invertedZ - Z^-1 (inverted zero) - optional, precomputation is useful for invertBatch
|
|
1912
|
+
*/
|
|
1913
|
+
toAffine(invertedZ) {
|
|
1914
|
+
const p = this;
|
|
1915
|
+
let iz = invertedZ;
|
|
1916
|
+
const { X, Y, Z } = p;
|
|
1917
|
+
if (Fp3.eql(Z, Fp3.ONE))
|
|
1918
|
+
return { x: X, y: Y };
|
|
1919
|
+
const is0 = p.is0();
|
|
1920
|
+
if (iz == null)
|
|
1921
|
+
iz = is0 ? Fp3.ONE : Fp3.inv(Z);
|
|
1922
|
+
const x = Fp3.mul(X, iz);
|
|
1923
|
+
const y = Fp3.mul(Y, iz);
|
|
1924
|
+
const zz = Fp3.mul(Z, iz);
|
|
1925
|
+
if (is0)
|
|
1926
|
+
return { x: Fp3.ZERO, y: Fp3.ZERO };
|
|
1927
|
+
if (!Fp3.eql(zz, Fp3.ONE))
|
|
1928
|
+
throw new Error("invZ was invalid");
|
|
1929
|
+
return { x, y };
|
|
1930
|
+
}
|
|
1931
|
+
/**
|
|
1932
|
+
* Checks whether Point is free of torsion elements (is in prime subgroup).
|
|
1933
|
+
* Always torsion-free for cofactor=1 curves.
|
|
1934
|
+
*/
|
|
1935
|
+
isTorsionFree() {
|
|
1936
|
+
const { isTorsionFree } = extraOpts;
|
|
1937
|
+
if (cofactor === _1n4)
|
|
1938
|
+
return true;
|
|
1939
|
+
if (isTorsionFree)
|
|
1940
|
+
return isTorsionFree(Point, this);
|
|
1941
|
+
return wnaf.unsafe(this, CURVE_ORDER).is0();
|
|
1942
|
+
}
|
|
1943
|
+
clearCofactor() {
|
|
1944
|
+
const { clearCofactor } = extraOpts;
|
|
1945
|
+
if (cofactor === _1n4)
|
|
1946
|
+
return this;
|
|
1947
|
+
if (clearCofactor)
|
|
1948
|
+
return clearCofactor(Point, this);
|
|
1949
|
+
return this.multiplyUnsafe(cofactor);
|
|
1950
|
+
}
|
|
1951
|
+
isSmallOrder() {
|
|
1952
|
+
if (cofactor === _1n4)
|
|
1953
|
+
return this.is0();
|
|
1954
|
+
return this.clearCofactor().is0();
|
|
1955
|
+
}
|
|
1956
|
+
toBytes(isCompressed = true) {
|
|
1957
|
+
abool(isCompressed, "isCompressed");
|
|
1958
|
+
this.assertValidity();
|
|
1959
|
+
return encodePoint(Point, this, isCompressed);
|
|
1960
|
+
}
|
|
1961
|
+
toHex(isCompressed = true) {
|
|
1962
|
+
return bytesToHex2(this.toBytes(isCompressed));
|
|
1963
|
+
}
|
|
1964
|
+
toString() {
|
|
1965
|
+
return `<Point ${this.is0() ? "ZERO" : this.toHex()}>`;
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
const bits = Fn.BITS;
|
|
1969
|
+
const wnaf = new wNAF(Point, extraOpts.endo ? Math.ceil(bits / 2) : bits);
|
|
1970
|
+
if (bits >= 8)
|
|
1971
|
+
Point.BASE.precompute(8);
|
|
1972
|
+
Object.freeze(Point.prototype);
|
|
1973
|
+
Object.freeze(Point);
|
|
1974
|
+
return Point;
|
|
1975
|
+
}
|
|
1976
|
+
function pprefix(hasEvenY) {
|
|
1977
|
+
return Uint8Array.of(hasEvenY ? 2 : 3);
|
|
1978
|
+
}
|
|
1979
|
+
function getWLengths(Fp3, Fn) {
|
|
1980
|
+
return {
|
|
1981
|
+
secretKey: Fn.BYTES,
|
|
1982
|
+
publicKey: 1 + Fp3.BYTES,
|
|
1983
|
+
publicKeyUncompressed: 1 + 2 * Fp3.BYTES,
|
|
1984
|
+
publicKeyHasPrefix: true,
|
|
1985
|
+
// Raw compact `(r || s)` signature width; DER and recovered signatures use
|
|
1986
|
+
// different lengths outside this helper.
|
|
1987
|
+
signature: 2 * Fn.BYTES
|
|
1988
|
+
};
|
|
1989
|
+
}
|
|
1990
|
+
|
|
1991
|
+
// ../../node_modules/.pnpm/@noble+curves@2.2.0/node_modules/@noble/curves/abstract/bls.js
|
|
1992
|
+
var _0n5 = BigInt(0);
|
|
1993
|
+
var _1n5 = BigInt(1);
|
|
1994
|
+
var _2n3 = BigInt(2);
|
|
1995
|
+
var _3n3 = BigInt(3);
|
|
1996
|
+
function NAfDecomposition(a) {
|
|
1997
|
+
const res = [];
|
|
1998
|
+
for (; a > _1n5; a >>= _1n5) {
|
|
1999
|
+
if ((a & _1n5) === _0n5)
|
|
2000
|
+
res.unshift(0);
|
|
2001
|
+
else if ((a & _3n3) === _3n3) {
|
|
2002
|
+
res.unshift(-1);
|
|
2003
|
+
a += _1n5;
|
|
2004
|
+
} else
|
|
2005
|
+
res.unshift(1);
|
|
2006
|
+
}
|
|
2007
|
+
return res;
|
|
2008
|
+
}
|
|
2009
|
+
function createBlsPairing(fields2, G1, G2, params) {
|
|
2010
|
+
const { Fr: Fr2, Fp2: Fp22, Fp12: Fp122 } = fields2;
|
|
2011
|
+
const { twistType, ateLoopSize, xNegative, postPrecompute } = params;
|
|
2012
|
+
let lineFunction;
|
|
2013
|
+
if (twistType === "multiplicative") {
|
|
2014
|
+
lineFunction = (c0, c1, c2, f, Px, Py) => Fp122.mul014(f, c0, Fp22.mul(c1, Px), Fp22.mul(c2, Py));
|
|
2015
|
+
} else if (twistType === "divisive") {
|
|
2016
|
+
lineFunction = (c0, c1, c2, f, Px, Py) => Fp122.mul034(f, Fp22.mul(c2, Py), Fp22.mul(c1, Px), c0);
|
|
2017
|
+
} else
|
|
2018
|
+
throw new Error("bls: unknown twist type");
|
|
2019
|
+
const Fp2div2 = Fp22.div(Fp22.ONE, Fp22.mul(Fp22.ONE, _2n3));
|
|
2020
|
+
function pointDouble(ell, Rx, Ry, Rz) {
|
|
2021
|
+
const t0 = Fp22.sqr(Ry);
|
|
2022
|
+
const t1 = Fp22.sqr(Rz);
|
|
2023
|
+
const t2 = Fp22.mulByB(Fp22.mul(t1, _3n3));
|
|
2024
|
+
const t3 = Fp22.mul(t2, _3n3);
|
|
2025
|
+
const t4 = Fp22.sub(Fp22.sub(Fp22.sqr(Fp22.add(Ry, Rz)), t1), t0);
|
|
2026
|
+
const c0 = Fp22.sub(t2, t0);
|
|
2027
|
+
const c1 = Fp22.mul(Fp22.sqr(Rx), _3n3);
|
|
2028
|
+
const c2 = Fp22.neg(t4);
|
|
2029
|
+
ell.push([c0, c1, c2]);
|
|
2030
|
+
Rx = Fp22.mul(Fp22.mul(Fp22.mul(Fp22.sub(t0, t3), Rx), Ry), Fp2div2);
|
|
2031
|
+
Ry = Fp22.sub(Fp22.sqr(Fp22.mul(Fp22.add(t0, t3), Fp2div2)), Fp22.mul(Fp22.sqr(t2), _3n3));
|
|
2032
|
+
Rz = Fp22.mul(t0, t4);
|
|
2033
|
+
return { Rx, Ry, Rz };
|
|
2034
|
+
}
|
|
2035
|
+
function pointAdd(ell, Rx, Ry, Rz, Qx, Qy) {
|
|
2036
|
+
const t0 = Fp22.sub(Ry, Fp22.mul(Qy, Rz));
|
|
2037
|
+
const t1 = Fp22.sub(Rx, Fp22.mul(Qx, Rz));
|
|
2038
|
+
const c0 = Fp22.sub(Fp22.mul(t0, Qx), Fp22.mul(t1, Qy));
|
|
2039
|
+
const c1 = Fp22.neg(t0);
|
|
2040
|
+
const c2 = t1;
|
|
2041
|
+
ell.push([c0, c1, c2]);
|
|
2042
|
+
const t2 = Fp22.sqr(t1);
|
|
2043
|
+
const t3 = Fp22.mul(t2, t1);
|
|
2044
|
+
const t4 = Fp22.mul(t2, Rx);
|
|
2045
|
+
const t5 = Fp22.add(Fp22.sub(t3, Fp22.mul(t4, _2n3)), Fp22.mul(Fp22.sqr(t0), Rz));
|
|
2046
|
+
Rx = Fp22.mul(t1, t5);
|
|
2047
|
+
Ry = Fp22.sub(Fp22.mul(Fp22.sub(t4, t5), t0), Fp22.mul(t3, Ry));
|
|
2048
|
+
Rz = Fp22.mul(Rz, t3);
|
|
2049
|
+
return { Rx, Ry, Rz };
|
|
2050
|
+
}
|
|
2051
|
+
const ATE_NAF = NAfDecomposition(ateLoopSize);
|
|
2052
|
+
const calcPairingPrecomputes = (point) => {
|
|
2053
|
+
const p = point;
|
|
2054
|
+
const { x, y } = p.toAffine();
|
|
2055
|
+
const Qx = x, Qy = y, negQy = Fp22.neg(y);
|
|
2056
|
+
let Rx = Qx, Ry = Qy, Rz = Fp22.ONE;
|
|
2057
|
+
const ell = [];
|
|
2058
|
+
for (const bit of ATE_NAF) {
|
|
2059
|
+
const cur = [];
|
|
2060
|
+
({ Rx, Ry, Rz } = pointDouble(cur, Rx, Ry, Rz));
|
|
2061
|
+
if (bit)
|
|
2062
|
+
({ Rx, Ry, Rz } = pointAdd(cur, Rx, Ry, Rz, Qx, bit === -1 ? negQy : Qy));
|
|
2063
|
+
ell.push(cur);
|
|
2064
|
+
}
|
|
2065
|
+
if (postPrecompute) {
|
|
2066
|
+
const last = ell[ell.length - 1];
|
|
2067
|
+
postPrecompute(Rx, Ry, Rz, Qx, Qy, pointAdd.bind(null, last));
|
|
2068
|
+
}
|
|
2069
|
+
return ell;
|
|
2070
|
+
};
|
|
2071
|
+
function millerLoopBatch(pairs, withFinalExponent = false) {
|
|
2072
|
+
let f12 = Fp122.ONE;
|
|
2073
|
+
if (pairs.length) {
|
|
2074
|
+
const ellLen = pairs[0][0].length;
|
|
2075
|
+
for (let i = 0; i < ellLen; i++) {
|
|
2076
|
+
f12 = Fp122.sqr(f12);
|
|
2077
|
+
for (const [ell, Px, Py] of pairs) {
|
|
2078
|
+
for (const [c0, c1, c2] of ell[i])
|
|
2079
|
+
f12 = lineFunction(c0, c1, c2, f12, Px, Py);
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
if (xNegative)
|
|
2084
|
+
f12 = Fp122.conjugate(f12);
|
|
2085
|
+
return withFinalExponent ? Fp122.finalExponentiate(f12) : f12;
|
|
2086
|
+
}
|
|
2087
|
+
function pairingBatch(pairs, withFinalExponent = true) {
|
|
2088
|
+
const res = [];
|
|
2089
|
+
for (const { g1, g2 } of pairs) {
|
|
2090
|
+
if (g1.is0() || g2.is0())
|
|
2091
|
+
throw new Error("pairing is not available for ZERO point");
|
|
2092
|
+
g1.assertValidity();
|
|
2093
|
+
g2.assertValidity();
|
|
2094
|
+
const Qa = g1.toAffine();
|
|
2095
|
+
res.push([calcPairingPrecomputes(g2), Qa.x, Qa.y]);
|
|
2096
|
+
}
|
|
2097
|
+
return millerLoopBatch(res, withFinalExponent);
|
|
2098
|
+
}
|
|
2099
|
+
function pairing(Q, P, withFinalExponent = true) {
|
|
2100
|
+
return pairingBatch([{ g1: Q, g2: P }], withFinalExponent);
|
|
2101
|
+
}
|
|
2102
|
+
const lengths = {
|
|
2103
|
+
seed: getMinHashLength(Fr2.ORDER)
|
|
2104
|
+
};
|
|
2105
|
+
const rand = params.randomBytes === void 0 ? randomBytes2 : params.randomBytes;
|
|
2106
|
+
const randomSecretKey = (seed) => {
|
|
2107
|
+
seed = seed === void 0 ? rand(lengths.seed) : seed;
|
|
2108
|
+
abytes2(seed, lengths.seed, "seed");
|
|
2109
|
+
return mapHashToField(seed, Fr2.ORDER);
|
|
2110
|
+
};
|
|
2111
|
+
Object.freeze(lengths);
|
|
2112
|
+
return {
|
|
2113
|
+
lengths,
|
|
2114
|
+
Fr: Fr2,
|
|
2115
|
+
Fp12: Fp122,
|
|
2116
|
+
// NOTE: we re-export Fp12 here because pairing results are Fp12!
|
|
2117
|
+
millerLoopBatch,
|
|
2118
|
+
pairing,
|
|
2119
|
+
pairingBatch,
|
|
2120
|
+
calcPairingPrecomputes,
|
|
2121
|
+
randomSecretKey
|
|
2122
|
+
};
|
|
2123
|
+
}
|
|
2124
|
+
function blsBasic(fields2, G1_Point, G2_Point, params) {
|
|
2125
|
+
const { Fp: Fp3, Fr: Fr2, Fp2: Fp22, Fp6, Fp12: Fp122 } = fields2;
|
|
2126
|
+
const G1 = { Point: G1_Point };
|
|
2127
|
+
const G2 = { Point: G2_Point };
|
|
2128
|
+
const pairingRes = createBlsPairing(fields2, G1_Point, G2_Point, params);
|
|
2129
|
+
const { millerLoopBatch, pairing, pairingBatch, calcPairingPrecomputes, randomSecretKey, lengths } = pairingRes;
|
|
2130
|
+
G1.Point.BASE.precompute(4);
|
|
2131
|
+
Object.freeze(G1);
|
|
2132
|
+
Object.freeze(G2);
|
|
2133
|
+
return Object.freeze({
|
|
2134
|
+
lengths: Object.freeze(lengths),
|
|
2135
|
+
millerLoopBatch,
|
|
2136
|
+
pairing,
|
|
2137
|
+
pairingBatch,
|
|
2138
|
+
G1,
|
|
2139
|
+
G2,
|
|
2140
|
+
fields: Object.freeze({ Fr: Fr2, Fp: Fp3, Fp2: Fp22, Fp6, Fp12: Fp122 }),
|
|
2141
|
+
params: Object.freeze({
|
|
2142
|
+
ateLoopSize: params.ateLoopSize,
|
|
2143
|
+
twistType: params.twistType
|
|
2144
|
+
}),
|
|
2145
|
+
utils: Object.freeze({
|
|
2146
|
+
randomSecretKey,
|
|
2147
|
+
calcPairingPrecomputes
|
|
2148
|
+
})
|
|
2149
|
+
});
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
// ../../node_modules/.pnpm/@noble+curves@2.2.0/node_modules/@noble/curves/abstract/tower.js
|
|
2153
|
+
var _0n6 = /* @__PURE__ */ BigInt(0);
|
|
2154
|
+
var _1n6 = /* @__PURE__ */ BigInt(1);
|
|
2155
|
+
var _2n4 = /* @__PURE__ */ BigInt(2);
|
|
2156
|
+
var _3n4 = /* @__PURE__ */ BigInt(3);
|
|
2157
|
+
var _6n = /* @__PURE__ */ BigInt(6);
|
|
2158
|
+
var _12n = /* @__PURE__ */ BigInt(12);
|
|
2159
|
+
var isObj = (value) => !!value && typeof value === "object";
|
|
2160
|
+
function calcFrobeniusCoefficients(Fp3, nonResidue, modulus, degree, num = 1, divisor) {
|
|
2161
|
+
asafenumber(num, "num");
|
|
2162
|
+
const F = Fp3;
|
|
2163
|
+
if (num <= 0)
|
|
2164
|
+
throw new Error("calcFrobeniusCoefficients: expected positive row count, got " + num);
|
|
2165
|
+
const _divisor = BigInt(divisor === void 0 ? degree : divisor);
|
|
2166
|
+
const towerModulus = modulus ** BigInt(degree);
|
|
2167
|
+
const res = [];
|
|
2168
|
+
for (let i = 0; i < num; i++) {
|
|
2169
|
+
const a = BigInt(i + 1);
|
|
2170
|
+
const powers = [];
|
|
2171
|
+
for (let j = 0, qPower = _1n6; j < degree; j++) {
|
|
2172
|
+
const numer = a * qPower - a;
|
|
2173
|
+
if (numer % _divisor)
|
|
2174
|
+
throw new Error("calcFrobeniusCoefficients: inexact tower exponent");
|
|
2175
|
+
const power = numer / _divisor % towerModulus;
|
|
2176
|
+
powers.push(F.pow(nonResidue, power));
|
|
2177
|
+
qPower *= modulus;
|
|
2178
|
+
}
|
|
2179
|
+
res.push(powers);
|
|
2180
|
+
}
|
|
2181
|
+
return res;
|
|
2182
|
+
}
|
|
2183
|
+
function psiFrobenius(Fp3, Fp22, base) {
|
|
2184
|
+
const PSI_X = Fp22.pow(base, (Fp3.ORDER - _1n6) / _3n4);
|
|
2185
|
+
const PSI_Y = Fp22.pow(base, (Fp3.ORDER - _1n6) / _2n4);
|
|
2186
|
+
function psi2(x, y) {
|
|
2187
|
+
const x2 = Fp22.mul(Fp22.frobeniusMap(x, 1), PSI_X);
|
|
2188
|
+
const y2 = Fp22.mul(Fp22.frobeniusMap(y, 1), PSI_Y);
|
|
2189
|
+
return [x2, y2];
|
|
2190
|
+
}
|
|
2191
|
+
const PSI2_X = Fp22.pow(base, (Fp3.ORDER ** _2n4 - _1n6) / _3n4);
|
|
2192
|
+
const PSI2_Y = Fp22.pow(base, (Fp3.ORDER ** _2n4 - _1n6) / _2n4);
|
|
2193
|
+
if (!Fp22.eql(PSI2_Y, Fp22.neg(Fp22.ONE)))
|
|
2194
|
+
throw new Error("psiFrobenius: PSI2_Y!==-1");
|
|
2195
|
+
function psi22(x, y) {
|
|
2196
|
+
return [Fp22.mul(x, PSI2_X), Fp22.neg(y)];
|
|
2197
|
+
}
|
|
2198
|
+
const mapAffine = (fn) => (c, P) => {
|
|
2199
|
+
const affine = P.toAffine();
|
|
2200
|
+
const p = fn(affine.x, affine.y);
|
|
2201
|
+
return c.fromAffine({ x: p[0], y: p[1] });
|
|
2202
|
+
};
|
|
2203
|
+
const G2psi2 = mapAffine(psi2);
|
|
2204
|
+
const G2psi22 = mapAffine(psi22);
|
|
2205
|
+
return { psi: psi2, psi2: psi22, G2psi: G2psi2, G2psi2: G2psi22, PSI_X, PSI_Y, PSI2_X, PSI2_Y };
|
|
2206
|
+
}
|
|
2207
|
+
var _Field2 = class {
|
|
2208
|
+
ORDER;
|
|
2209
|
+
BITS;
|
|
2210
|
+
BYTES;
|
|
2211
|
+
isLE;
|
|
2212
|
+
ZERO;
|
|
2213
|
+
ONE;
|
|
2214
|
+
Fp;
|
|
2215
|
+
NONRESIDUE;
|
|
2216
|
+
mulByB;
|
|
2217
|
+
Fp_NONRESIDUE;
|
|
2218
|
+
Fp_div2;
|
|
2219
|
+
FROBENIUS_COEFFICIENTS;
|
|
2220
|
+
constructor(Fp3, opts = {}) {
|
|
2221
|
+
const { NONRESIDUE = BigInt(-1), FP2_NONRESIDUE, Fp2mulByB } = opts;
|
|
2222
|
+
const ORDER = Fp3.ORDER;
|
|
2223
|
+
const FP2_ORDER = ORDER * ORDER;
|
|
2224
|
+
this.Fp = Fp3;
|
|
2225
|
+
this.ORDER = FP2_ORDER;
|
|
2226
|
+
this.BITS = bitLen(FP2_ORDER);
|
|
2227
|
+
this.BYTES = Math.ceil(bitLen(FP2_ORDER) / 8);
|
|
2228
|
+
this.isLE = Fp3.isLE;
|
|
2229
|
+
this.ZERO = this.create({ c0: Fp3.ZERO, c1: Fp3.ZERO });
|
|
2230
|
+
this.ONE = this.create({ c0: Fp3.ONE, c1: Fp3.ZERO });
|
|
2231
|
+
this.Fp_NONRESIDUE = Fp3.create(NONRESIDUE);
|
|
2232
|
+
this.Fp_div2 = Fp3.div(Fp3.ONE, _2n4);
|
|
2233
|
+
this.NONRESIDUE = this.create({ c0: FP2_NONRESIDUE[0], c1: FP2_NONRESIDUE[1] });
|
|
2234
|
+
this.FROBENIUS_COEFFICIENTS = Object.freeze(calcFrobeniusCoefficients(Fp3, this.Fp_NONRESIDUE, Fp3.ORDER, 2)[0]);
|
|
2235
|
+
this.mulByB = (num) => {
|
|
2236
|
+
const { c0, c1 } = Fp2mulByB(num);
|
|
2237
|
+
return Object.freeze({ c0, c1 });
|
|
2238
|
+
};
|
|
2239
|
+
Object.freeze(this);
|
|
2240
|
+
}
|
|
2241
|
+
fromBigTuple(tuple) {
|
|
2242
|
+
if (!Array.isArray(tuple) || tuple.length !== 2)
|
|
2243
|
+
throw new Error("invalid Fp2.fromBigTuple");
|
|
2244
|
+
const [c0, c1] = tuple;
|
|
2245
|
+
if (typeof c0 !== "bigint" || typeof c1 !== "bigint")
|
|
2246
|
+
throw new Error("invalid Fp2.fromBigTuple");
|
|
2247
|
+
return this.create({ c0, c1 });
|
|
2248
|
+
}
|
|
2249
|
+
create(num) {
|
|
2250
|
+
const { Fp: Fp3 } = this;
|
|
2251
|
+
const c0 = Fp3.create(num.c0);
|
|
2252
|
+
const c1 = Fp3.create(num.c1);
|
|
2253
|
+
return Object.freeze({ c0, c1 });
|
|
2254
|
+
}
|
|
2255
|
+
isValid(num) {
|
|
2256
|
+
if (!isObj(num))
|
|
2257
|
+
throw new TypeError("invalid field element: expected object, got " + typeof num);
|
|
2258
|
+
const { c0, c1 } = num;
|
|
2259
|
+
const { Fp: Fp3 } = this;
|
|
2260
|
+
return Fp3.isValid(c0) && Fp3.isValid(c1);
|
|
2261
|
+
}
|
|
2262
|
+
is0(num) {
|
|
2263
|
+
if (!isObj(num))
|
|
2264
|
+
return false;
|
|
2265
|
+
const { c0, c1 } = num;
|
|
2266
|
+
const { Fp: Fp3 } = this;
|
|
2267
|
+
return Fp3.is0(c0) && Fp3.is0(c1);
|
|
2268
|
+
}
|
|
2269
|
+
isValidNot0(num) {
|
|
2270
|
+
return !this.is0(num) && this.isValid(num);
|
|
2271
|
+
}
|
|
2272
|
+
eql({ c0, c1 }, { c0: r0, c1: r1 }) {
|
|
2273
|
+
const { Fp: Fp3 } = this;
|
|
2274
|
+
return Fp3.eql(c0, r0) && Fp3.eql(c1, r1);
|
|
2275
|
+
}
|
|
2276
|
+
neg({ c0, c1 }) {
|
|
2277
|
+
const { Fp: Fp3 } = this;
|
|
2278
|
+
return Object.freeze({ c0: Fp3.neg(c0), c1: Fp3.neg(c1) });
|
|
2279
|
+
}
|
|
2280
|
+
pow(num, power) {
|
|
2281
|
+
return FpPow(this, num, power);
|
|
2282
|
+
}
|
|
2283
|
+
invertBatch(nums) {
|
|
2284
|
+
return FpInvertBatch(this, nums);
|
|
2285
|
+
}
|
|
2286
|
+
// Normalized
|
|
2287
|
+
add(f1, f2) {
|
|
2288
|
+
const { Fp: Fp3 } = this;
|
|
2289
|
+
const { c0, c1 } = f1;
|
|
2290
|
+
const { c0: r0, c1: r1 } = f2;
|
|
2291
|
+
return Object.freeze({
|
|
2292
|
+
c0: Fp3.add(c0, r0),
|
|
2293
|
+
c1: Fp3.add(c1, r1)
|
|
2294
|
+
});
|
|
2295
|
+
}
|
|
2296
|
+
sub({ c0, c1 }, { c0: r0, c1: r1 }) {
|
|
2297
|
+
const { Fp: Fp3 } = this;
|
|
2298
|
+
return Object.freeze({
|
|
2299
|
+
c0: Fp3.sub(c0, r0),
|
|
2300
|
+
c1: Fp3.sub(c1, r1)
|
|
2301
|
+
});
|
|
2302
|
+
}
|
|
2303
|
+
mul({ c0, c1 }, rhs) {
|
|
2304
|
+
const { Fp: Fp3 } = this;
|
|
2305
|
+
if (typeof rhs === "bigint")
|
|
2306
|
+
return Object.freeze({ c0: Fp3.mul(c0, rhs), c1: Fp3.mul(c1, rhs) });
|
|
2307
|
+
const { c0: r0, c1: r1 } = rhs;
|
|
2308
|
+
let t1 = Fp3.mul(c0, r0);
|
|
2309
|
+
let t2 = Fp3.mul(c1, r1);
|
|
2310
|
+
const o0 = Fp3.sub(t1, t2);
|
|
2311
|
+
const o1 = Fp3.sub(Fp3.mul(Fp3.add(c0, c1), Fp3.add(r0, r1)), Fp3.add(t1, t2));
|
|
2312
|
+
return Object.freeze({ c0: o0, c1: o1 });
|
|
2313
|
+
}
|
|
2314
|
+
sqr({ c0, c1 }) {
|
|
2315
|
+
const { Fp: Fp3 } = this;
|
|
2316
|
+
const a = Fp3.add(c0, c1);
|
|
2317
|
+
const b = Fp3.sub(c0, c1);
|
|
2318
|
+
const c = Fp3.add(c0, c0);
|
|
2319
|
+
return Object.freeze({ c0: Fp3.mul(a, b), c1: Fp3.mul(c, c1) });
|
|
2320
|
+
}
|
|
2321
|
+
// NonNormalized stuff
|
|
2322
|
+
addN(a, b) {
|
|
2323
|
+
return this.add(a, b);
|
|
2324
|
+
}
|
|
2325
|
+
subN(a, b) {
|
|
2326
|
+
return this.sub(a, b);
|
|
2327
|
+
}
|
|
2328
|
+
mulN(a, b) {
|
|
2329
|
+
return this.mul(a, b);
|
|
2330
|
+
}
|
|
2331
|
+
sqrN(a) {
|
|
2332
|
+
return this.sqr(a);
|
|
2333
|
+
}
|
|
2334
|
+
// Why inversion for bigint inside Fp instead of Fp2? it is even used in that context?
|
|
2335
|
+
div(lhs, rhs) {
|
|
2336
|
+
const { Fp: Fp3 } = this;
|
|
2337
|
+
return this.mul(lhs, typeof rhs === "bigint" ? Fp3.inv(Fp3.create(rhs)) : this.inv(rhs));
|
|
2338
|
+
}
|
|
2339
|
+
inv({ c0: a, c1: b }) {
|
|
2340
|
+
const { Fp: Fp3 } = this;
|
|
2341
|
+
const factor = Fp3.inv(Fp3.create(a * a + b * b));
|
|
2342
|
+
return Object.freeze({ c0: Fp3.mul(factor, Fp3.create(a)), c1: Fp3.mul(factor, Fp3.create(-b)) });
|
|
2343
|
+
}
|
|
2344
|
+
sqrt(num) {
|
|
2345
|
+
const { Fp: Fp3 } = this;
|
|
2346
|
+
const Fp22 = this;
|
|
2347
|
+
const { c0, c1 } = num;
|
|
2348
|
+
if (Fp3.is0(c1)) {
|
|
2349
|
+
if (FpLegendre(Fp3, c0) === 1)
|
|
2350
|
+
return Fp22.create({ c0: Fp3.sqrt(c0), c1: Fp3.ZERO });
|
|
2351
|
+
else
|
|
2352
|
+
return Fp22.create({ c0: Fp3.ZERO, c1: Fp3.sqrt(Fp3.div(c0, this.Fp_NONRESIDUE)) });
|
|
2353
|
+
}
|
|
2354
|
+
const a = Fp3.sqrt(Fp3.sub(Fp3.sqr(c0), Fp3.mul(Fp3.sqr(c1), this.Fp_NONRESIDUE)));
|
|
2355
|
+
let d = Fp3.mul(Fp3.add(a, c0), this.Fp_div2);
|
|
2356
|
+
const legendre = FpLegendre(Fp3, d);
|
|
2357
|
+
if (legendre === -1)
|
|
2358
|
+
d = Fp3.sub(d, a);
|
|
2359
|
+
const a0 = Fp3.sqrt(d);
|
|
2360
|
+
const candidateSqrt = Fp22.create({ c0: a0, c1: Fp3.div(Fp3.mul(c1, this.Fp_div2), a0) });
|
|
2361
|
+
if (!Fp22.eql(Fp22.sqr(candidateSqrt), num))
|
|
2362
|
+
throw new Error("Cannot find square root");
|
|
2363
|
+
const x1 = candidateSqrt;
|
|
2364
|
+
const x2 = Fp22.neg(x1);
|
|
2365
|
+
const { re: re1, im: im1 } = Fp22.reim(x1);
|
|
2366
|
+
const { re: re2, im: im2 } = Fp22.reim(x2);
|
|
2367
|
+
if (im1 > im2 || im1 === im2 && re1 > re2)
|
|
2368
|
+
return x1;
|
|
2369
|
+
return x2;
|
|
2370
|
+
}
|
|
2371
|
+
// Same as sgn0_m_eq_2 in RFC 9380
|
|
2372
|
+
isOdd(x) {
|
|
2373
|
+
const { re: x0, im: x1 } = this.reim(x);
|
|
2374
|
+
const sign_0 = x0 % _2n4;
|
|
2375
|
+
const zero_0 = x0 === _0n6;
|
|
2376
|
+
const sign_1 = x1 % _2n4;
|
|
2377
|
+
return BigInt(sign_0 || zero_0 && sign_1) == _1n6;
|
|
2378
|
+
}
|
|
2379
|
+
// Bytes util
|
|
2380
|
+
fromBytes(b) {
|
|
2381
|
+
const { Fp: Fp3 } = this;
|
|
2382
|
+
abytes2(b);
|
|
2383
|
+
if (b.length !== this.BYTES)
|
|
2384
|
+
throw new Error("fromBytes invalid length=" + b.length);
|
|
2385
|
+
return this.create({
|
|
2386
|
+
c0: Fp3.fromBytes(b.subarray(0, Fp3.BYTES)),
|
|
2387
|
+
c1: Fp3.fromBytes(b.subarray(Fp3.BYTES))
|
|
2388
|
+
});
|
|
2389
|
+
}
|
|
2390
|
+
toBytes({ c0, c1 }) {
|
|
2391
|
+
return concatBytes2(this.Fp.toBytes(c0), this.Fp.toBytes(c1));
|
|
2392
|
+
}
|
|
2393
|
+
cmov({ c0, c1 }, { c0: r0, c1: r1 }, c) {
|
|
2394
|
+
const { Fp: Fp3 } = this;
|
|
2395
|
+
return this.create({
|
|
2396
|
+
c0: Fp3.cmov(c0, r0, c),
|
|
2397
|
+
c1: Fp3.cmov(c1, r1, c)
|
|
2398
|
+
});
|
|
2399
|
+
}
|
|
2400
|
+
reim({ c0, c1 }) {
|
|
2401
|
+
return { re: c0, im: c1 };
|
|
2402
|
+
}
|
|
2403
|
+
Fp4Square(a, b) {
|
|
2404
|
+
const Fp22 = this;
|
|
2405
|
+
const a2 = Fp22.sqr(a);
|
|
2406
|
+
const b2 = Fp22.sqr(b);
|
|
2407
|
+
return {
|
|
2408
|
+
first: Fp22.add(Fp22.mulByNonresidue(b2), a2),
|
|
2409
|
+
// b² * Nonresidue + a²
|
|
2410
|
+
second: Fp22.sub(Fp22.sub(Fp22.sqr(Fp22.add(a, b)), a2), b2)
|
|
2411
|
+
// (a + b)² - a² - b²
|
|
2412
|
+
};
|
|
2413
|
+
}
|
|
2414
|
+
// multiply by u + 1
|
|
2415
|
+
mulByNonresidue({ c0, c1 }) {
|
|
2416
|
+
return this.mul({ c0, c1 }, this.NONRESIDUE);
|
|
2417
|
+
}
|
|
2418
|
+
frobeniusMap({ c0, c1 }, power) {
|
|
2419
|
+
return Object.freeze({
|
|
2420
|
+
c0,
|
|
2421
|
+
c1: this.Fp.mul(c1, this.FROBENIUS_COEFFICIENTS[power % 2])
|
|
2422
|
+
});
|
|
2423
|
+
}
|
|
2424
|
+
};
|
|
2425
|
+
var _Field6 = class {
|
|
2426
|
+
ORDER;
|
|
2427
|
+
BITS;
|
|
2428
|
+
BYTES;
|
|
2429
|
+
isLE;
|
|
2430
|
+
ZERO;
|
|
2431
|
+
ONE;
|
|
2432
|
+
Fp2;
|
|
2433
|
+
constructor(Fp22) {
|
|
2434
|
+
this.Fp2 = Fp22;
|
|
2435
|
+
this.ORDER = Fp22.Fp.ORDER ** _6n;
|
|
2436
|
+
this.BITS = 3 * Fp22.BITS;
|
|
2437
|
+
this.BYTES = 3 * Fp22.BYTES;
|
|
2438
|
+
this.isLE = Fp22.isLE;
|
|
2439
|
+
this.ZERO = this.create({ c0: Fp22.ZERO, c1: Fp22.ZERO, c2: Fp22.ZERO });
|
|
2440
|
+
this.ONE = this.create({ c0: Fp22.ONE, c1: Fp22.ZERO, c2: Fp22.ZERO });
|
|
2441
|
+
Object.freeze(this);
|
|
2442
|
+
}
|
|
2443
|
+
// Most callers never touch Frobenius maps, so keep the sextic tables lazy:
|
|
2444
|
+
// eagerly deriving them dominates `bls12-381.js` / `bn254.js` import time.
|
|
2445
|
+
get FROBENIUS_COEFFICIENTS_1() {
|
|
2446
|
+
const frob2 = _FROBENIUS_COEFFICIENTS_6.get(this);
|
|
2447
|
+
if (frob2)
|
|
2448
|
+
return frob2[0];
|
|
2449
|
+
const { Fp2: Fp22 } = this;
|
|
2450
|
+
const { Fp: Fp3 } = Fp22;
|
|
2451
|
+
const rows = calcFrobeniusCoefficients(Fp22, Fp22.NONRESIDUE, Fp3.ORDER, 6, 2, 3);
|
|
2452
|
+
const cache = [Object.freeze(rows[0]), Object.freeze(rows[1])];
|
|
2453
|
+
_FROBENIUS_COEFFICIENTS_6.set(this, cache);
|
|
2454
|
+
return cache[0];
|
|
2455
|
+
}
|
|
2456
|
+
get FROBENIUS_COEFFICIENTS_2() {
|
|
2457
|
+
const frob2 = _FROBENIUS_COEFFICIENTS_6.get(this);
|
|
2458
|
+
if (frob2)
|
|
2459
|
+
return frob2[1];
|
|
2460
|
+
void this.FROBENIUS_COEFFICIENTS_1;
|
|
2461
|
+
return _FROBENIUS_COEFFICIENTS_6.get(this)[1];
|
|
2462
|
+
}
|
|
2463
|
+
add({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) {
|
|
2464
|
+
const { Fp2: Fp22 } = this;
|
|
2465
|
+
return Object.freeze({
|
|
2466
|
+
c0: Fp22.add(c0, r0),
|
|
2467
|
+
c1: Fp22.add(c1, r1),
|
|
2468
|
+
c2: Fp22.add(c2, r2)
|
|
2469
|
+
});
|
|
2470
|
+
}
|
|
2471
|
+
sub({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) {
|
|
2472
|
+
const { Fp2: Fp22 } = this;
|
|
2473
|
+
return Object.freeze({
|
|
2474
|
+
c0: Fp22.sub(c0, r0),
|
|
2475
|
+
c1: Fp22.sub(c1, r1),
|
|
2476
|
+
c2: Fp22.sub(c2, r2)
|
|
2477
|
+
});
|
|
2478
|
+
}
|
|
2479
|
+
mul({ c0, c1, c2 }, rhs) {
|
|
2480
|
+
const { Fp2: Fp22 } = this;
|
|
2481
|
+
if (typeof rhs === "bigint") {
|
|
2482
|
+
return Object.freeze({
|
|
2483
|
+
c0: Fp22.mul(c0, rhs),
|
|
2484
|
+
c1: Fp22.mul(c1, rhs),
|
|
2485
|
+
c2: Fp22.mul(c2, rhs)
|
|
2486
|
+
});
|
|
2487
|
+
}
|
|
2488
|
+
const { c0: r0, c1: r1, c2: r2 } = rhs;
|
|
2489
|
+
const t0 = Fp22.mul(c0, r0);
|
|
2490
|
+
const t1 = Fp22.mul(c1, r1);
|
|
2491
|
+
const t2 = Fp22.mul(c2, r2);
|
|
2492
|
+
return Object.freeze({
|
|
2493
|
+
// t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1)
|
|
2494
|
+
c0: Fp22.add(t0, Fp22.mulByNonresidue(Fp22.sub(Fp22.mul(Fp22.add(c1, c2), Fp22.add(r1, r2)), Fp22.add(t1, t2)))),
|
|
2495
|
+
// (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1)
|
|
2496
|
+
c1: Fp22.add(Fp22.sub(Fp22.mul(Fp22.add(c0, c1), Fp22.add(r0, r1)), Fp22.add(t0, t1)), Fp22.mulByNonresidue(t2)),
|
|
2497
|
+
// T1 + (c0 + c2) * (r0 + r2) - T0 + T2
|
|
2498
|
+
c2: Fp22.sub(Fp22.add(t1, Fp22.mul(Fp22.add(c0, c2), Fp22.add(r0, r2))), Fp22.add(t0, t2))
|
|
2499
|
+
});
|
|
2500
|
+
}
|
|
2501
|
+
sqr({ c0, c1, c2 }) {
|
|
2502
|
+
const { Fp2: Fp22 } = this;
|
|
2503
|
+
let t0 = Fp22.sqr(c0);
|
|
2504
|
+
let t1 = Fp22.mul(Fp22.mul(c0, c1), _2n4);
|
|
2505
|
+
let t3 = Fp22.mul(Fp22.mul(c1, c2), _2n4);
|
|
2506
|
+
let t4 = Fp22.sqr(c2);
|
|
2507
|
+
return Object.freeze({
|
|
2508
|
+
c0: Fp22.add(Fp22.mulByNonresidue(t3), t0),
|
|
2509
|
+
// T3 * (u + 1) + T0
|
|
2510
|
+
c1: Fp22.add(Fp22.mulByNonresidue(t4), t1),
|
|
2511
|
+
// T4 * (u + 1) + T1
|
|
2512
|
+
// T1 + (c0 - c1 + c2)² + T3 - T0 - T4
|
|
2513
|
+
c2: Fp22.sub(Fp22.sub(Fp22.add(Fp22.add(t1, Fp22.sqr(Fp22.add(Fp22.sub(c0, c1), c2))), t3), t0), t4)
|
|
2514
|
+
});
|
|
2515
|
+
}
|
|
2516
|
+
addN(a, b) {
|
|
2517
|
+
return this.add(a, b);
|
|
2518
|
+
}
|
|
2519
|
+
subN(a, b) {
|
|
2520
|
+
return this.sub(a, b);
|
|
2521
|
+
}
|
|
2522
|
+
mulN(a, b) {
|
|
2523
|
+
return this.mul(a, b);
|
|
2524
|
+
}
|
|
2525
|
+
sqrN(a) {
|
|
2526
|
+
return this.sqr(a);
|
|
2527
|
+
}
|
|
2528
|
+
create(num) {
|
|
2529
|
+
const { Fp2: Fp22 } = this;
|
|
2530
|
+
const c0 = Fp22.create(num.c0);
|
|
2531
|
+
const c1 = Fp22.create(num.c1);
|
|
2532
|
+
const c2 = Fp22.create(num.c2);
|
|
2533
|
+
return Object.freeze({ c0, c1, c2 });
|
|
2534
|
+
}
|
|
2535
|
+
isValid(num) {
|
|
2536
|
+
if (!isObj(num))
|
|
2537
|
+
throw new TypeError("invalid field element: expected object, got " + typeof num);
|
|
2538
|
+
const { c0, c1, c2 } = num;
|
|
2539
|
+
const { Fp2: Fp22 } = this;
|
|
2540
|
+
return Fp22.isValid(c0) && Fp22.isValid(c1) && Fp22.isValid(c2);
|
|
2541
|
+
}
|
|
2542
|
+
is0(num) {
|
|
2543
|
+
if (!isObj(num))
|
|
2544
|
+
return false;
|
|
2545
|
+
const { c0, c1, c2 } = num;
|
|
2546
|
+
const { Fp2: Fp22 } = this;
|
|
2547
|
+
return Fp22.is0(c0) && Fp22.is0(c1) && Fp22.is0(c2);
|
|
2548
|
+
}
|
|
2549
|
+
isValidNot0(num) {
|
|
2550
|
+
return !this.is0(num) && this.isValid(num);
|
|
2551
|
+
}
|
|
2552
|
+
neg({ c0, c1, c2 }) {
|
|
2553
|
+
const { Fp2: Fp22 } = this;
|
|
2554
|
+
return Object.freeze({ c0: Fp22.neg(c0), c1: Fp22.neg(c1), c2: Fp22.neg(c2) });
|
|
2555
|
+
}
|
|
2556
|
+
eql({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) {
|
|
2557
|
+
const { Fp2: Fp22 } = this;
|
|
2558
|
+
return Fp22.eql(c0, r0) && Fp22.eql(c1, r1) && Fp22.eql(c2, r2);
|
|
2559
|
+
}
|
|
2560
|
+
sqrt(_) {
|
|
2561
|
+
return notImplemented();
|
|
2562
|
+
}
|
|
2563
|
+
// Do we need division by bigint at all? Should be done via order:
|
|
2564
|
+
div(lhs, rhs) {
|
|
2565
|
+
const { Fp2: Fp22 } = this;
|
|
2566
|
+
const { Fp: Fp3 } = Fp22;
|
|
2567
|
+
return this.mul(lhs, typeof rhs === "bigint" ? Fp3.inv(Fp3.create(rhs)) : this.inv(rhs));
|
|
2568
|
+
}
|
|
2569
|
+
pow(num, power) {
|
|
2570
|
+
return FpPow(this, num, power);
|
|
2571
|
+
}
|
|
2572
|
+
invertBatch(nums) {
|
|
2573
|
+
return FpInvertBatch(this, nums);
|
|
2574
|
+
}
|
|
2575
|
+
inv({ c0, c1, c2 }) {
|
|
2576
|
+
const { Fp2: Fp22 } = this;
|
|
2577
|
+
let t0 = Fp22.sub(Fp22.sqr(c0), Fp22.mulByNonresidue(Fp22.mul(c2, c1)));
|
|
2578
|
+
let t1 = Fp22.sub(Fp22.mulByNonresidue(Fp22.sqr(c2)), Fp22.mul(c0, c1));
|
|
2579
|
+
let t2 = Fp22.sub(Fp22.sqr(c1), Fp22.mul(c0, c2));
|
|
2580
|
+
let t4 = Fp22.inv(Fp22.add(Fp22.mulByNonresidue(Fp22.add(Fp22.mul(c2, t1), Fp22.mul(c1, t2))), Fp22.mul(c0, t0)));
|
|
2581
|
+
return Object.freeze({ c0: Fp22.mul(t4, t0), c1: Fp22.mul(t4, t1), c2: Fp22.mul(t4, t2) });
|
|
2582
|
+
}
|
|
2583
|
+
// Bytes utils
|
|
2584
|
+
fromBytes(b) {
|
|
2585
|
+
const { Fp2: Fp22 } = this;
|
|
2586
|
+
abytes2(b);
|
|
2587
|
+
if (b.length !== this.BYTES)
|
|
2588
|
+
throw new Error("fromBytes invalid length=" + b.length);
|
|
2589
|
+
const B2 = Fp22.BYTES;
|
|
2590
|
+
return this.create({
|
|
2591
|
+
c0: Fp22.fromBytes(b.subarray(0, B2)),
|
|
2592
|
+
c1: Fp22.fromBytes(b.subarray(B2, B2 * 2)),
|
|
2593
|
+
c2: Fp22.fromBytes(b.subarray(2 * B2))
|
|
2594
|
+
});
|
|
2595
|
+
}
|
|
2596
|
+
toBytes({ c0, c1, c2 }) {
|
|
2597
|
+
const { Fp2: Fp22 } = this;
|
|
2598
|
+
return concatBytes2(Fp22.toBytes(c0), Fp22.toBytes(c1), Fp22.toBytes(c2));
|
|
2599
|
+
}
|
|
2600
|
+
cmov({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }, c) {
|
|
2601
|
+
const { Fp2: Fp22 } = this;
|
|
2602
|
+
return this.create({
|
|
2603
|
+
c0: Fp22.cmov(c0, r0, c),
|
|
2604
|
+
c1: Fp22.cmov(c1, r1, c),
|
|
2605
|
+
c2: Fp22.cmov(c2, r2, c)
|
|
2606
|
+
});
|
|
2607
|
+
}
|
|
2608
|
+
fromBigSix(tuple) {
|
|
2609
|
+
const { Fp2: Fp22 } = this;
|
|
2610
|
+
if (!Array.isArray(tuple) || tuple.length !== 6)
|
|
2611
|
+
throw new Error("invalid Fp6.fromBigSix");
|
|
2612
|
+
for (let i = 0; i < 6; i++)
|
|
2613
|
+
if (typeof tuple[i] !== "bigint")
|
|
2614
|
+
throw new Error("invalid Fp6.fromBigSix");
|
|
2615
|
+
const t = tuple;
|
|
2616
|
+
return this.create({
|
|
2617
|
+
c0: Fp22.fromBigTuple(t.slice(0, 2)),
|
|
2618
|
+
c1: Fp22.fromBigTuple(t.slice(2, 4)),
|
|
2619
|
+
c2: Fp22.fromBigTuple(t.slice(4, 6))
|
|
2620
|
+
});
|
|
2621
|
+
}
|
|
2622
|
+
frobeniusMap({ c0, c1, c2 }, power) {
|
|
2623
|
+
const { Fp2: Fp22 } = this;
|
|
2624
|
+
return Object.freeze({
|
|
2625
|
+
c0: Fp22.frobeniusMap(c0, power),
|
|
2626
|
+
c1: Fp22.mul(Fp22.frobeniusMap(c1, power), this.FROBENIUS_COEFFICIENTS_1[power % 6]),
|
|
2627
|
+
c2: Fp22.mul(Fp22.frobeniusMap(c2, power), this.FROBENIUS_COEFFICIENTS_2[power % 6])
|
|
2628
|
+
});
|
|
2629
|
+
}
|
|
2630
|
+
mulByFp2({ c0, c1, c2 }, rhs) {
|
|
2631
|
+
const { Fp2: Fp22 } = this;
|
|
2632
|
+
return Object.freeze({
|
|
2633
|
+
c0: Fp22.mul(c0, rhs),
|
|
2634
|
+
c1: Fp22.mul(c1, rhs),
|
|
2635
|
+
c2: Fp22.mul(c2, rhs)
|
|
2636
|
+
});
|
|
2637
|
+
}
|
|
2638
|
+
mulByNonresidue({ c0, c1, c2 }) {
|
|
2639
|
+
const { Fp2: Fp22 } = this;
|
|
2640
|
+
return Object.freeze({ c0: Fp22.mulByNonresidue(c2), c1: c0, c2: c1 });
|
|
2641
|
+
}
|
|
2642
|
+
// Sparse multiplication
|
|
2643
|
+
mul1({ c0, c1, c2 }, b1) {
|
|
2644
|
+
const { Fp2: Fp22 } = this;
|
|
2645
|
+
return Object.freeze({
|
|
2646
|
+
c0: Fp22.mulByNonresidue(Fp22.mul(c2, b1)),
|
|
2647
|
+
c1: Fp22.mul(c0, b1),
|
|
2648
|
+
c2: Fp22.mul(c1, b1)
|
|
2649
|
+
});
|
|
2650
|
+
}
|
|
2651
|
+
// Sparse multiplication
|
|
2652
|
+
mul01({ c0, c1, c2 }, b0, b1) {
|
|
2653
|
+
const { Fp2: Fp22 } = this;
|
|
2654
|
+
let t0 = Fp22.mul(c0, b0);
|
|
2655
|
+
let t1 = Fp22.mul(c1, b1);
|
|
2656
|
+
return Object.freeze({
|
|
2657
|
+
// ((c1 + c2) * b1 - T1) * (u + 1) + T0
|
|
2658
|
+
c0: Fp22.add(Fp22.mulByNonresidue(Fp22.sub(Fp22.mul(Fp22.add(c1, c2), b1), t1)), t0),
|
|
2659
|
+
// (b0 + b1) * (c0 + c1) - T0 - T1
|
|
2660
|
+
c1: Fp22.sub(Fp22.sub(Fp22.mul(Fp22.add(b0, b1), Fp22.add(c0, c1)), t0), t1),
|
|
2661
|
+
// (c0 + c2) * b0 - T0 + T1
|
|
2662
|
+
c2: Fp22.add(Fp22.sub(Fp22.mul(Fp22.add(c0, c2), b0), t0), t1)
|
|
2663
|
+
});
|
|
2664
|
+
}
|
|
2665
|
+
};
|
|
2666
|
+
var _FROBENIUS_COEFFICIENTS_6 = /* @__PURE__ */ new WeakMap();
|
|
2667
|
+
var _Field12 = class {
|
|
2668
|
+
ORDER;
|
|
2669
|
+
BITS;
|
|
2670
|
+
BYTES;
|
|
2671
|
+
isLE;
|
|
2672
|
+
ZERO;
|
|
2673
|
+
ONE;
|
|
2674
|
+
Fp6;
|
|
2675
|
+
X_LEN;
|
|
2676
|
+
finalExponentiate;
|
|
2677
|
+
constructor(Fp6, opts) {
|
|
2678
|
+
const { X_LEN, Fp12finalExponentiate } = opts;
|
|
2679
|
+
const { Fp2: Fp22 } = Fp6;
|
|
2680
|
+
const { Fp: Fp3 } = Fp22;
|
|
2681
|
+
this.Fp6 = Fp6;
|
|
2682
|
+
this.ORDER = Fp3.ORDER ** _12n;
|
|
2683
|
+
this.BITS = 2 * Fp6.BITS;
|
|
2684
|
+
this.BYTES = 2 * Fp6.BYTES;
|
|
2685
|
+
this.isLE = Fp6.isLE;
|
|
2686
|
+
this.ZERO = this.create({ c0: Fp6.ZERO, c1: Fp6.ZERO });
|
|
2687
|
+
this.ONE = this.create({ c0: Fp6.ONE, c1: Fp6.ZERO });
|
|
2688
|
+
this.X_LEN = X_LEN;
|
|
2689
|
+
this.finalExponentiate = (num) => {
|
|
2690
|
+
const copy2 = ({ c0, c1 }) => Object.freeze({ c0, c1 });
|
|
2691
|
+
const copy6 = ({ c0, c1, c2 }) => Object.freeze({ c0: copy2(c0), c1: copy2(c1), c2: copy2(c2) });
|
|
2692
|
+
const res = Fp12finalExponentiate(num);
|
|
2693
|
+
return Object.freeze({ c0: copy6(res.c0), c1: copy6(res.c1) });
|
|
2694
|
+
};
|
|
2695
|
+
Object.freeze(this);
|
|
2696
|
+
}
|
|
2697
|
+
// Keep the degree-12 Frobenius row lazy too; after the first lookup the cached
|
|
2698
|
+
// array is reused exactly like the old eager table.
|
|
2699
|
+
get FROBENIUS_COEFFICIENTS() {
|
|
2700
|
+
const frob2 = _FROBENIUS_COEFFICIENTS_12.get(this);
|
|
2701
|
+
if (frob2)
|
|
2702
|
+
return frob2;
|
|
2703
|
+
const { Fp2: Fp22 } = this.Fp6;
|
|
2704
|
+
const { Fp: Fp3 } = Fp22;
|
|
2705
|
+
const cache = Object.freeze(calcFrobeniusCoefficients(Fp22, Fp22.NONRESIDUE, Fp3.ORDER, 12, 1, 6)[0]);
|
|
2706
|
+
_FROBENIUS_COEFFICIENTS_12.set(this, cache);
|
|
2707
|
+
return cache;
|
|
2708
|
+
}
|
|
2709
|
+
create(num) {
|
|
2710
|
+
const { Fp6 } = this;
|
|
2711
|
+
const c0 = Fp6.create(num.c0);
|
|
2712
|
+
const c1 = Fp6.create(num.c1);
|
|
2713
|
+
return Object.freeze({ c0, c1 });
|
|
2714
|
+
}
|
|
2715
|
+
isValid(num) {
|
|
2716
|
+
if (!isObj(num))
|
|
2717
|
+
throw new TypeError("invalid field element: expected object, got " + typeof num);
|
|
2718
|
+
const { c0, c1 } = num;
|
|
2719
|
+
const { Fp6 } = this;
|
|
2720
|
+
return Fp6.isValid(c0) && Fp6.isValid(c1);
|
|
2721
|
+
}
|
|
2722
|
+
is0(num) {
|
|
2723
|
+
if (!isObj(num))
|
|
2724
|
+
return false;
|
|
2725
|
+
const { c0, c1 } = num;
|
|
2726
|
+
const { Fp6 } = this;
|
|
2727
|
+
return Fp6.is0(c0) && Fp6.is0(c1);
|
|
2728
|
+
}
|
|
2729
|
+
isValidNot0(num) {
|
|
2730
|
+
return !this.is0(num) && this.isValid(num);
|
|
2731
|
+
}
|
|
2732
|
+
neg({ c0, c1 }) {
|
|
2733
|
+
const { Fp6 } = this;
|
|
2734
|
+
return Object.freeze({ c0: Fp6.neg(c0), c1: Fp6.neg(c1) });
|
|
2735
|
+
}
|
|
2736
|
+
eql({ c0, c1 }, { c0: r0, c1: r1 }) {
|
|
2737
|
+
const { Fp6 } = this;
|
|
2738
|
+
return Fp6.eql(c0, r0) && Fp6.eql(c1, r1);
|
|
2739
|
+
}
|
|
2740
|
+
sqrt(_) {
|
|
2741
|
+
return notImplemented();
|
|
2742
|
+
}
|
|
2743
|
+
inv({ c0, c1 }) {
|
|
2744
|
+
const { Fp6 } = this;
|
|
2745
|
+
let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1))));
|
|
2746
|
+
return Object.freeze({ c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) });
|
|
2747
|
+
}
|
|
2748
|
+
div(lhs, rhs) {
|
|
2749
|
+
const { Fp6 } = this;
|
|
2750
|
+
const { Fp2: Fp22 } = Fp6;
|
|
2751
|
+
const { Fp: Fp3 } = Fp22;
|
|
2752
|
+
return this.mul(lhs, typeof rhs === "bigint" ? Fp3.inv(Fp3.create(rhs)) : this.inv(rhs));
|
|
2753
|
+
}
|
|
2754
|
+
pow(num, power) {
|
|
2755
|
+
return FpPow(this, num, power);
|
|
2756
|
+
}
|
|
2757
|
+
invertBatch(nums) {
|
|
2758
|
+
return FpInvertBatch(this, nums);
|
|
2759
|
+
}
|
|
2760
|
+
// Normalized
|
|
2761
|
+
add({ c0, c1 }, { c0: r0, c1: r1 }) {
|
|
2762
|
+
const { Fp6 } = this;
|
|
2763
|
+
return Object.freeze({
|
|
2764
|
+
c0: Fp6.add(c0, r0),
|
|
2765
|
+
c1: Fp6.add(c1, r1)
|
|
2766
|
+
});
|
|
2767
|
+
}
|
|
2768
|
+
sub({ c0, c1 }, { c0: r0, c1: r1 }) {
|
|
2769
|
+
const { Fp6 } = this;
|
|
2770
|
+
return Object.freeze({
|
|
2771
|
+
c0: Fp6.sub(c0, r0),
|
|
2772
|
+
c1: Fp6.sub(c1, r1)
|
|
2773
|
+
});
|
|
2774
|
+
}
|
|
2775
|
+
mul({ c0, c1 }, rhs) {
|
|
2776
|
+
const { Fp6 } = this;
|
|
2777
|
+
if (typeof rhs === "bigint")
|
|
2778
|
+
return Object.freeze({ c0: Fp6.mul(c0, rhs), c1: Fp6.mul(c1, rhs) });
|
|
2779
|
+
let { c0: r0, c1: r1 } = rhs;
|
|
2780
|
+
let t1 = Fp6.mul(c0, r0);
|
|
2781
|
+
let t2 = Fp6.mul(c1, r1);
|
|
2782
|
+
return Object.freeze({
|
|
2783
|
+
c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)),
|
|
2784
|
+
// T1 + T2 * v
|
|
2785
|
+
// (c0 + c1) * (r0 + r1) - (T1 + T2)
|
|
2786
|
+
c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2))
|
|
2787
|
+
});
|
|
2788
|
+
}
|
|
2789
|
+
sqr({ c0, c1 }) {
|
|
2790
|
+
const { Fp6 } = this;
|
|
2791
|
+
let ab = Fp6.mul(c0, c1);
|
|
2792
|
+
return Object.freeze({
|
|
2793
|
+
// (c1 * v + c0) * (c0 + c1) - AB - AB * v
|
|
2794
|
+
c0: Fp6.sub(Fp6.sub(Fp6.mul(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab), Fp6.mulByNonresidue(ab)),
|
|
2795
|
+
c1: Fp6.add(ab, ab)
|
|
2796
|
+
});
|
|
2797
|
+
}
|
|
2798
|
+
// NonNormalized stuff
|
|
2799
|
+
addN(a, b) {
|
|
2800
|
+
return this.add(a, b);
|
|
2801
|
+
}
|
|
2802
|
+
subN(a, b) {
|
|
2803
|
+
return this.sub(a, b);
|
|
2804
|
+
}
|
|
2805
|
+
mulN(a, b) {
|
|
2806
|
+
return this.mul(a, b);
|
|
2807
|
+
}
|
|
2808
|
+
sqrN(a) {
|
|
2809
|
+
return this.sqr(a);
|
|
2810
|
+
}
|
|
2811
|
+
// Bytes utils
|
|
2812
|
+
fromBytes(b) {
|
|
2813
|
+
const { Fp6 } = this;
|
|
2814
|
+
abytes2(b);
|
|
2815
|
+
if (b.length !== this.BYTES)
|
|
2816
|
+
throw new Error("fromBytes invalid length=" + b.length);
|
|
2817
|
+
return this.create({
|
|
2818
|
+
c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)),
|
|
2819
|
+
c1: Fp6.fromBytes(b.subarray(Fp6.BYTES))
|
|
2820
|
+
});
|
|
2821
|
+
}
|
|
2822
|
+
toBytes({ c0, c1 }) {
|
|
2823
|
+
const { Fp6 } = this;
|
|
2824
|
+
return concatBytes2(Fp6.toBytes(c0), Fp6.toBytes(c1));
|
|
2825
|
+
}
|
|
2826
|
+
cmov({ c0, c1 }, { c0: r0, c1: r1 }, c) {
|
|
2827
|
+
const { Fp6 } = this;
|
|
2828
|
+
return this.create({
|
|
2829
|
+
c0: Fp6.cmov(c0, r0, c),
|
|
2830
|
+
c1: Fp6.cmov(c1, r1, c)
|
|
2831
|
+
});
|
|
2832
|
+
}
|
|
2833
|
+
// Utils
|
|
2834
|
+
// toString() {
|
|
2835
|
+
// return '' + 'Fp12(' + this.c0 + this.c1 + '* w');
|
|
2836
|
+
// },
|
|
2837
|
+
// fromTuple(c: [Fp6, Fp6]) {
|
|
2838
|
+
// return new Fp12(...c);
|
|
2839
|
+
// }
|
|
2840
|
+
fromBigTwelve(tuple) {
|
|
2841
|
+
const { Fp6 } = this;
|
|
2842
|
+
if (!Array.isArray(tuple) || tuple.length !== 12)
|
|
2843
|
+
throw new Error("invalid Fp12.fromBigTwelve");
|
|
2844
|
+
for (let i = 0; i < 12; i++)
|
|
2845
|
+
if (typeof tuple[i] !== "bigint")
|
|
2846
|
+
throw new Error("invalid Fp12.fromBigTwelve");
|
|
2847
|
+
const t = tuple;
|
|
2848
|
+
return this.create({
|
|
2849
|
+
c0: Fp6.fromBigSix(t.slice(0, 6)),
|
|
2850
|
+
c1: Fp6.fromBigSix(t.slice(6, 12))
|
|
2851
|
+
});
|
|
2852
|
+
}
|
|
2853
|
+
// Raises to q**i -th power
|
|
2854
|
+
frobeniusMap(lhs, power) {
|
|
2855
|
+
const { Fp6 } = this;
|
|
2856
|
+
const { Fp2: Fp22 } = Fp6;
|
|
2857
|
+
const { c0, c1, c2 } = Fp6.frobeniusMap(lhs.c1, power);
|
|
2858
|
+
const coeff = this.FROBENIUS_COEFFICIENTS[power % 12];
|
|
2859
|
+
return Object.freeze({
|
|
2860
|
+
c0: Fp6.frobeniusMap(lhs.c0, power),
|
|
2861
|
+
c1: Object.freeze({
|
|
2862
|
+
c0: Fp22.mul(c0, coeff),
|
|
2863
|
+
c1: Fp22.mul(c1, coeff),
|
|
2864
|
+
c2: Fp22.mul(c2, coeff)
|
|
2865
|
+
})
|
|
2866
|
+
});
|
|
2867
|
+
}
|
|
2868
|
+
mulByFp2({ c0, c1 }, rhs) {
|
|
2869
|
+
const { Fp6 } = this;
|
|
2870
|
+
return Object.freeze({
|
|
2871
|
+
c0: Fp6.mulByFp2(c0, rhs),
|
|
2872
|
+
c1: Fp6.mulByFp2(c1, rhs)
|
|
2873
|
+
});
|
|
2874
|
+
}
|
|
2875
|
+
conjugate({ c0, c1 }) {
|
|
2876
|
+
return Object.freeze({ c0, c1: this.Fp6.neg(c1) });
|
|
2877
|
+
}
|
|
2878
|
+
// Sparse multiplication
|
|
2879
|
+
mul014({ c0, c1 }, o0, o1, o4) {
|
|
2880
|
+
const { Fp6 } = this;
|
|
2881
|
+
const { Fp2: Fp22 } = Fp6;
|
|
2882
|
+
let t0 = Fp6.mul01(c0, o0, o1);
|
|
2883
|
+
let t1 = Fp6.mul1(c1, o4);
|
|
2884
|
+
return Object.freeze({
|
|
2885
|
+
c0: Fp6.add(Fp6.mulByNonresidue(t1), t0),
|
|
2886
|
+
// T1 * v + T0
|
|
2887
|
+
// (c1 + c0) * [o0, o1+o4] - T0 - T1
|
|
2888
|
+
c1: Fp6.sub(Fp6.sub(Fp6.mul01(Fp6.add(c1, c0), o0, Fp22.add(o1, o4)), t0), t1)
|
|
2889
|
+
});
|
|
2890
|
+
}
|
|
2891
|
+
mul034({ c0, c1 }, o0, o3, o4) {
|
|
2892
|
+
const { Fp6 } = this;
|
|
2893
|
+
const { Fp2: Fp22 } = Fp6;
|
|
2894
|
+
const a = Object.freeze({
|
|
2895
|
+
c0: Fp22.mul(c0.c0, o0),
|
|
2896
|
+
c1: Fp22.mul(c0.c1, o0),
|
|
2897
|
+
c2: Fp22.mul(c0.c2, o0)
|
|
2898
|
+
});
|
|
2899
|
+
const b = Fp6.mul01(c1, o3, o4);
|
|
2900
|
+
const e = Fp6.mul01(Fp6.add(c0, c1), Fp22.add(o0, o3), o4);
|
|
2901
|
+
return Object.freeze({
|
|
2902
|
+
c0: Fp6.add(Fp6.mulByNonresidue(b), a),
|
|
2903
|
+
c1: Fp6.sub(e, Fp6.add(a, b))
|
|
2904
|
+
});
|
|
2905
|
+
}
|
|
2906
|
+
// A cyclotomic group is a subgroup of Fp^n defined by
|
|
2907
|
+
// GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1}
|
|
2908
|
+
// The result of any pairing is in a cyclotomic subgroup
|
|
2909
|
+
// https://eprint.iacr.org/2009/565.pdf
|
|
2910
|
+
// https://eprint.iacr.org/2010/354.pdf
|
|
2911
|
+
_cyclotomicSquare({ c0, c1 }) {
|
|
2912
|
+
const { Fp6 } = this;
|
|
2913
|
+
const { Fp2: Fp22 } = Fp6;
|
|
2914
|
+
const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0;
|
|
2915
|
+
const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1;
|
|
2916
|
+
const { first: t3, second: t4 } = Fp22.Fp4Square(c0c0, c1c1);
|
|
2917
|
+
const { first: t5, second: t6 } = Fp22.Fp4Square(c1c0, c0c2);
|
|
2918
|
+
const { first: t7, second: t8 } = Fp22.Fp4Square(c0c1, c1c2);
|
|
2919
|
+
const t9 = Fp22.mulByNonresidue(t8);
|
|
2920
|
+
return Object.freeze({
|
|
2921
|
+
c0: Object.freeze({
|
|
2922
|
+
c0: Fp22.add(Fp22.mul(Fp22.sub(t3, c0c0), _2n4), t3),
|
|
2923
|
+
// 2 * (T3 - c0c0) + T3
|
|
2924
|
+
c1: Fp22.add(Fp22.mul(Fp22.sub(t5, c0c1), _2n4), t5),
|
|
2925
|
+
// 2 * (T5 - c0c1) + T5
|
|
2926
|
+
c2: Fp22.add(Fp22.mul(Fp22.sub(t7, c0c2), _2n4), t7)
|
|
2927
|
+
}),
|
|
2928
|
+
// 2 * (T7 - c0c2) + T7
|
|
2929
|
+
c1: Object.freeze({
|
|
2930
|
+
c0: Fp22.add(Fp22.mul(Fp22.add(t9, c1c0), _2n4), t9),
|
|
2931
|
+
// 2 * (T9 + c1c0) + T9
|
|
2932
|
+
c1: Fp22.add(Fp22.mul(Fp22.add(t4, c1c1), _2n4), t4),
|
|
2933
|
+
// 2 * (T4 + c1c1) + T4
|
|
2934
|
+
c2: Fp22.add(Fp22.mul(Fp22.add(t6, c1c2), _2n4), t6)
|
|
2935
|
+
})
|
|
2936
|
+
});
|
|
2937
|
+
}
|
|
2938
|
+
// https://eprint.iacr.org/2009/565.pdf
|
|
2939
|
+
_cyclotomicExp(num, n) {
|
|
2940
|
+
aInRange("cyclotomic exponent", n, _0n6, _1n6 << BigInt(this.X_LEN));
|
|
2941
|
+
let z = this.ONE;
|
|
2942
|
+
for (let i = this.X_LEN - 1; i >= 0; i--) {
|
|
2943
|
+
z = this._cyclotomicSquare(z);
|
|
2944
|
+
if (bitGet(n, i))
|
|
2945
|
+
z = this.mul(z, num);
|
|
2946
|
+
}
|
|
2947
|
+
return z;
|
|
2948
|
+
}
|
|
2949
|
+
};
|
|
2950
|
+
var _FROBENIUS_COEFFICIENTS_12 = /* @__PURE__ */ new WeakMap();
|
|
2951
|
+
function tower12(opts) {
|
|
2952
|
+
validateObject(opts, {
|
|
2953
|
+
ORDER: "bigint",
|
|
2954
|
+
X_LEN: "number",
|
|
2955
|
+
FP2_NONRESIDUE: "object",
|
|
2956
|
+
Fp2mulByB: "function",
|
|
2957
|
+
Fp12finalExponentiate: "function"
|
|
2958
|
+
}, { NONRESIDUE: "bigint" });
|
|
2959
|
+
asafenumber(opts.X_LEN, "X_LEN");
|
|
2960
|
+
if (opts.X_LEN < 1)
|
|
2961
|
+
throw new Error("invalid X_LEN");
|
|
2962
|
+
const nonresidue = opts.FP2_NONRESIDUE;
|
|
2963
|
+
if (!Array.isArray(nonresidue) || nonresidue.length !== 2)
|
|
2964
|
+
throw new Error("invalid FP2_NONRESIDUE");
|
|
2965
|
+
if (typeof nonresidue[0] !== "bigint" || typeof nonresidue[1] !== "bigint")
|
|
2966
|
+
throw new Error("invalid FP2_NONRESIDUE");
|
|
2967
|
+
const Fp3 = Field(opts.ORDER);
|
|
2968
|
+
const Fp22 = new _Field2(Fp3, opts);
|
|
2969
|
+
const Fp6 = new _Field6(Fp22);
|
|
2970
|
+
const Fp122 = new _Field12(Fp6, opts);
|
|
2971
|
+
return { Fp: Fp3, Fp2: Fp22, Fp6, Fp12: Fp122 };
|
|
2972
|
+
}
|
|
2973
|
+
|
|
2974
|
+
// ../../node_modules/.pnpm/@noble+curves@2.2.0/node_modules/@noble/curves/bn254.js
|
|
2975
|
+
var _0n7 = /* @__PURE__ */ BigInt(0);
|
|
2976
|
+
var _1n7 = /* @__PURE__ */ BigInt(1);
|
|
2977
|
+
var _2n5 = /* @__PURE__ */ BigInt(2);
|
|
2978
|
+
var _3n5 = /* @__PURE__ */ BigInt(3);
|
|
2979
|
+
var _6n2 = /* @__PURE__ */ BigInt(6);
|
|
2980
|
+
var BN_X = /* @__PURE__ */ BigInt("4965661367192848881");
|
|
2981
|
+
var BN_X_LEN = /* @__PURE__ */ (() => bitLen(BN_X))();
|
|
2982
|
+
var SIX_X_SQUARED = /* @__PURE__ */ (() => _6n2 * BN_X ** _2n5)();
|
|
2983
|
+
var bn254_G1_CURVE = {
|
|
2984
|
+
p: BigInt("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"),
|
|
2985
|
+
n: BigInt("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"),
|
|
2986
|
+
// The Ethereum specs define G1 as prime-order but do not spell out the
|
|
2987
|
+
// cofactor separately; `h = 1` is the implementation-derived value.
|
|
2988
|
+
h: _1n7,
|
|
2989
|
+
a: _0n7,
|
|
2990
|
+
b: _3n5,
|
|
2991
|
+
Gx: _1n7,
|
|
2992
|
+
Gy: BigInt(2)
|
|
2993
|
+
};
|
|
2994
|
+
var bn254_Fr = /* @__PURE__ */ (() => Field(bn254_G1_CURVE.n))();
|
|
2995
|
+
var Fp2B = /* @__PURE__ */ (() => ({
|
|
2996
|
+
c0: BigInt("19485874751759354771024239261021720505790618469301721065564631296452457478373"),
|
|
2997
|
+
c1: BigInt("266929791119991161246907387137283842545076965332900288569378510910307636690")
|
|
2998
|
+
}))();
|
|
2999
|
+
var Fp12;
|
|
3000
|
+
var tower = /* @__PURE__ */ (() => {
|
|
3001
|
+
const res = tower12({
|
|
3002
|
+
ORDER: bn254_G1_CURVE.p,
|
|
3003
|
+
X_LEN: BN_X_LEN,
|
|
3004
|
+
// Public `Fp2.NONRESIDUE` below is the sextic-tower seed `(9, 1)`, not the
|
|
3005
|
+
// quadratic relation `i^2 + 1 = 0` from the EIP text.
|
|
3006
|
+
FP2_NONRESIDUE: [BigInt(9), _1n7],
|
|
3007
|
+
Fp2mulByB: (num) => Fp2.mul(num, Fp2B),
|
|
3008
|
+
Fp12finalExponentiate: (num) => {
|
|
3009
|
+
const powMinusX = (num2) => Fp12.conjugate(Fp12._cyclotomicExp(num2, BN_X));
|
|
3010
|
+
const r0 = Fp12.mul(Fp12.conjugate(num), Fp12.inv(num));
|
|
3011
|
+
const r = Fp12.mul(Fp12.frobeniusMap(r0, 2), r0);
|
|
3012
|
+
const y1 = Fp12._cyclotomicSquare(powMinusX(r));
|
|
3013
|
+
const y2 = Fp12.mul(Fp12._cyclotomicSquare(y1), y1);
|
|
3014
|
+
const y4 = powMinusX(y2);
|
|
3015
|
+
const y6 = powMinusX(Fp12._cyclotomicSquare(y4));
|
|
3016
|
+
const y8 = Fp12.mul(Fp12.mul(Fp12.conjugate(y6), y4), Fp12.conjugate(y2));
|
|
3017
|
+
const y9 = Fp12.mul(y8, y1);
|
|
3018
|
+
return Fp12.mul(Fp12.frobeniusMap(Fp12.mul(Fp12.conjugate(r), y9), 3), Fp12.mul(Fp12.frobeniusMap(y8, 2), Fp12.mul(Fp12.frobeniusMap(y9, 1), Fp12.mul(Fp12.mul(y8, y4), r))));
|
|
3019
|
+
}
|
|
3020
|
+
});
|
|
3021
|
+
Fp12 = res.Fp12;
|
|
3022
|
+
return res;
|
|
3023
|
+
})();
|
|
3024
|
+
var Fp = /* @__PURE__ */ (() => tower.Fp)();
|
|
3025
|
+
var Fp2 = /* @__PURE__ */ (() => tower.Fp2)();
|
|
3026
|
+
var frob;
|
|
3027
|
+
var getFrob = () => frob || (frob = psiFrobenius(Fp, Fp2, Fp2.NONRESIDUE));
|
|
3028
|
+
var psi = (x, y) => {
|
|
3029
|
+
const fn = getFrob().psi;
|
|
3030
|
+
psi = fn;
|
|
3031
|
+
return fn(x, y);
|
|
3032
|
+
};
|
|
3033
|
+
var G2psi = (c, P) => {
|
|
3034
|
+
const fn = getFrob().G2psi;
|
|
3035
|
+
G2psi = fn;
|
|
3036
|
+
return fn(c, P);
|
|
3037
|
+
};
|
|
3038
|
+
var _postPrecompute = (Rx, Ry, Rz, Qx, Qy, pointAdd) => {
|
|
3039
|
+
const q = psi(Qx, Qy);
|
|
3040
|
+
({ Rx, Ry, Rz } = pointAdd(Rx, Ry, Rz, q[0], q[1]));
|
|
3041
|
+
const q2 = psi(q[0], q[1]);
|
|
3042
|
+
pointAdd(Rx, Ry, Rz, q2[0], Fp2.neg(q2[1]));
|
|
3043
|
+
};
|
|
3044
|
+
var bn254_G2_CURVE = /* @__PURE__ */ (() => ({
|
|
3045
|
+
p: Fp2.ORDER,
|
|
3046
|
+
n: bn254_G1_CURVE.n,
|
|
3047
|
+
// As with G1, the Ethereum specs do not spell out the G2 cofactor
|
|
3048
|
+
// separately; this literal is the implementation-derived value.
|
|
3049
|
+
h: BigInt("0x30644e72e131a029b85045b68181585e06ceecda572a2489345f2299c0f9fa8d"),
|
|
3050
|
+
a: Fp2.ZERO,
|
|
3051
|
+
b: Fp2B,
|
|
3052
|
+
Gx: Fp2.fromBigTuple([
|
|
3053
|
+
BigInt("10857046999023057135944570762232829481370756359578518086990519993285655852781"),
|
|
3054
|
+
BigInt("11559732032986387107991004021392285783925812861821192530917403151452391805634")
|
|
3055
|
+
]),
|
|
3056
|
+
Gy: Fp2.fromBigTuple([
|
|
3057
|
+
BigInt("8495653923123431417604973247489272438418190587263600148770280649306958101930"),
|
|
3058
|
+
BigInt("4082367875863433681332203403145435568316851327593401208105741076214120093531")
|
|
3059
|
+
])
|
|
3060
|
+
}))();
|
|
3061
|
+
var fields = /* @__PURE__ */ (() => ({ Fp, Fp2, Fp6: tower.Fp6, Fp12, Fr: bn254_Fr }))();
|
|
3062
|
+
var bn254_G1 = /* @__PURE__ */ weierstrass(bn254_G1_CURVE, {
|
|
3063
|
+
Fp,
|
|
3064
|
+
Fn: bn254_Fr,
|
|
3065
|
+
// Ethereum encodes infinity as `(0, 0)`, so the public point API accepts it
|
|
3066
|
+
// even though it is not an affine curve point, and `fromAffine()` stays lazy:
|
|
3067
|
+
// adversarial inputs still need `assertValidity()`.
|
|
3068
|
+
allowInfinityPoint: true
|
|
3069
|
+
});
|
|
3070
|
+
var bn254_G2 = /* @__PURE__ */ weierstrass(bn254_G2_CURVE, {
|
|
3071
|
+
Fp: Fp2,
|
|
3072
|
+
Fn: bn254_Fr,
|
|
3073
|
+
// Ethereum encodes infinity as `((0, 0), (0, 0))`, so the public point API
|
|
3074
|
+
// accepts it even though it is not an affine curve point.
|
|
3075
|
+
allowInfinityPoint: true,
|
|
3076
|
+
// Optimized BN254 G2 subgroup test used to satisfy the EIP-197 order check.
|
|
3077
|
+
isTorsionFree: (c, P) => P.multiplyUnsafe(SIX_X_SQUARED).equals(G2psi(c, P))
|
|
3078
|
+
// [p]P = [6X^2]P
|
|
3079
|
+
});
|
|
3080
|
+
var bn254_params = /* @__PURE__ */ (() => ({
|
|
3081
|
+
// Optimal-ate Miller loop parameter derived from the positive BN seed.
|
|
3082
|
+
ateLoopSize: BN_X * _6n2 + _2n5,
|
|
3083
|
+
r: bn254_Fr.ORDER,
|
|
3084
|
+
xNegative: false,
|
|
3085
|
+
// EIP-197 writes G2 as `y^2 = x^3 + 3 / (i + 9)`, so the pairing
|
|
3086
|
+
// configuration uses the divisive twist convention.
|
|
3087
|
+
twistType: "divisive",
|
|
3088
|
+
postPrecompute: _postPrecompute
|
|
3089
|
+
}))();
|
|
3090
|
+
var bn254 = /* @__PURE__ */ blsBasic(fields, bn254_G1, bn254_G2, bn254_params);
|
|
3091
|
+
|
|
3092
|
+
// ../../node_modules/.pnpm/@noble+hashes@2.2.0/node_modules/@noble/hashes/_u64.js
|
|
3093
|
+
var U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);
|
|
3094
|
+
var _32n = /* @__PURE__ */ BigInt(32);
|
|
3095
|
+
function fromBig(n, le = false) {
|
|
3096
|
+
if (le)
|
|
3097
|
+
return { h: Number(n & U32_MASK64), l: Number(n >> _32n & U32_MASK64) };
|
|
3098
|
+
return { h: Number(n >> _32n & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };
|
|
3099
|
+
}
|
|
3100
|
+
function split(lst, le = false) {
|
|
3101
|
+
const len = lst.length;
|
|
3102
|
+
let Ah = new Uint32Array(len);
|
|
3103
|
+
let Al = new Uint32Array(len);
|
|
3104
|
+
for (let i = 0; i < len; i++) {
|
|
3105
|
+
const { h, l } = fromBig(lst[i], le);
|
|
3106
|
+
[Ah[i], Al[i]] = [h, l];
|
|
3107
|
+
}
|
|
3108
|
+
return [Ah, Al];
|
|
3109
|
+
}
|
|
3110
|
+
var rotlSH = (h, l, s) => h << s | l >>> 32 - s;
|
|
3111
|
+
var rotlSL = (h, l, s) => l << s | h >>> 32 - s;
|
|
3112
|
+
var rotlBH = (h, l, s) => l << s - 32 | h >>> 64 - s;
|
|
3113
|
+
var rotlBL = (h, l, s) => h << s - 32 | l >>> 64 - s;
|
|
3114
|
+
|
|
3115
|
+
// ../../node_modules/.pnpm/@noble+hashes@2.2.0/node_modules/@noble/hashes/sha3.js
|
|
3116
|
+
var _0n8 = BigInt(0);
|
|
3117
|
+
var _1n8 = BigInt(1);
|
|
3118
|
+
var _2n6 = BigInt(2);
|
|
3119
|
+
var _7n2 = BigInt(7);
|
|
3120
|
+
var _256n = BigInt(256);
|
|
3121
|
+
var _0x71n = BigInt(113);
|
|
3122
|
+
var SHA3_PI = [];
|
|
3123
|
+
var SHA3_ROTL = [];
|
|
3124
|
+
var _SHA3_IOTA = [];
|
|
3125
|
+
for (let round = 0, R = _1n8, x = 1, y = 0; round < 24; round++) {
|
|
3126
|
+
[x, y] = [y, (2 * x + 3 * y) % 5];
|
|
3127
|
+
SHA3_PI.push(2 * (5 * y + x));
|
|
3128
|
+
SHA3_ROTL.push((round + 1) * (round + 2) / 2 % 64);
|
|
3129
|
+
let t = _0n8;
|
|
3130
|
+
for (let j = 0; j < 7; j++) {
|
|
3131
|
+
R = (R << _1n8 ^ (R >> _7n2) * _0x71n) % _256n;
|
|
3132
|
+
if (R & _2n6)
|
|
3133
|
+
t ^= _1n8 << (_1n8 << BigInt(j)) - _1n8;
|
|
3134
|
+
}
|
|
3135
|
+
_SHA3_IOTA.push(t);
|
|
3136
|
+
}
|
|
3137
|
+
var IOTAS = split(_SHA3_IOTA, true);
|
|
3138
|
+
var SHA3_IOTA_H = IOTAS[0];
|
|
3139
|
+
var SHA3_IOTA_L = IOTAS[1];
|
|
3140
|
+
var rotlH = (h, l, s) => s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s);
|
|
3141
|
+
var rotlL = (h, l, s) => s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s);
|
|
3142
|
+
function keccakP(s, rounds = 24) {
|
|
3143
|
+
anumber(rounds, "rounds");
|
|
3144
|
+
if (rounds < 1 || rounds > 24)
|
|
3145
|
+
throw new Error('"rounds" expected integer 1..24');
|
|
3146
|
+
const B = new Uint32Array(5 * 2);
|
|
3147
|
+
for (let round = 24 - rounds; round < 24; round++) {
|
|
3148
|
+
for (let x = 0; x < 10; x++)
|
|
3149
|
+
B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];
|
|
3150
|
+
for (let x = 0; x < 10; x += 2) {
|
|
3151
|
+
const idx1 = (x + 8) % 10;
|
|
3152
|
+
const idx0 = (x + 2) % 10;
|
|
3153
|
+
const B0 = B[idx0];
|
|
3154
|
+
const B1 = B[idx0 + 1];
|
|
3155
|
+
const Th = rotlH(B0, B1, 1) ^ B[idx1];
|
|
3156
|
+
const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1];
|
|
3157
|
+
for (let y = 0; y < 50; y += 10) {
|
|
3158
|
+
s[x + y] ^= Th;
|
|
3159
|
+
s[x + y + 1] ^= Tl;
|
|
3160
|
+
}
|
|
3161
|
+
}
|
|
3162
|
+
let curH = s[2];
|
|
3163
|
+
let curL = s[3];
|
|
3164
|
+
for (let t = 0; t < 24; t++) {
|
|
3165
|
+
const shift = SHA3_ROTL[t];
|
|
3166
|
+
const Th = rotlH(curH, curL, shift);
|
|
3167
|
+
const Tl = rotlL(curH, curL, shift);
|
|
3168
|
+
const PI = SHA3_PI[t];
|
|
3169
|
+
curH = s[PI];
|
|
3170
|
+
curL = s[PI + 1];
|
|
3171
|
+
s[PI] = Th;
|
|
3172
|
+
s[PI + 1] = Tl;
|
|
3173
|
+
}
|
|
3174
|
+
for (let y = 0; y < 50; y += 10) {
|
|
3175
|
+
const b0 = s[y], b1 = s[y + 1], b2 = s[y + 2], b3 = s[y + 3];
|
|
3176
|
+
s[y] ^= ~s[y + 2] & s[y + 4];
|
|
3177
|
+
s[y + 1] ^= ~s[y + 3] & s[y + 5];
|
|
3178
|
+
s[y + 2] ^= ~s[y + 4] & s[y + 6];
|
|
3179
|
+
s[y + 3] ^= ~s[y + 5] & s[y + 7];
|
|
3180
|
+
s[y + 4] ^= ~s[y + 6] & s[y + 8];
|
|
3181
|
+
s[y + 5] ^= ~s[y + 7] & s[y + 9];
|
|
3182
|
+
s[y + 6] ^= ~s[y + 8] & b0;
|
|
3183
|
+
s[y + 7] ^= ~s[y + 9] & b1;
|
|
3184
|
+
s[y + 8] ^= ~b0 & b2;
|
|
3185
|
+
s[y + 9] ^= ~b1 & b3;
|
|
3186
|
+
}
|
|
3187
|
+
s[0] ^= SHA3_IOTA_H[round];
|
|
3188
|
+
s[1] ^= SHA3_IOTA_L[round];
|
|
3189
|
+
}
|
|
3190
|
+
clean(B);
|
|
3191
|
+
}
|
|
3192
|
+
var Keccak = class _Keccak {
|
|
3193
|
+
state;
|
|
3194
|
+
pos = 0;
|
|
3195
|
+
posOut = 0;
|
|
3196
|
+
finished = false;
|
|
3197
|
+
state32;
|
|
3198
|
+
destroyed = false;
|
|
3199
|
+
blockLen;
|
|
3200
|
+
suffix;
|
|
3201
|
+
outputLen;
|
|
3202
|
+
canXOF;
|
|
3203
|
+
enableXOF = false;
|
|
3204
|
+
rounds;
|
|
3205
|
+
// NOTE: we accept arguments in bytes instead of bits here.
|
|
3206
|
+
constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) {
|
|
3207
|
+
this.blockLen = blockLen;
|
|
3208
|
+
this.suffix = suffix;
|
|
3209
|
+
this.outputLen = outputLen;
|
|
3210
|
+
this.enableXOF = enableXOF;
|
|
3211
|
+
this.canXOF = enableXOF;
|
|
3212
|
+
this.rounds = rounds;
|
|
3213
|
+
anumber(outputLen, "outputLen");
|
|
3214
|
+
if (!(0 < blockLen && blockLen < 200))
|
|
3215
|
+
throw new Error("only keccak-f1600 function is supported");
|
|
3216
|
+
this.state = new Uint8Array(200);
|
|
3217
|
+
this.state32 = u32(this.state);
|
|
3218
|
+
}
|
|
3219
|
+
clone() {
|
|
3220
|
+
return this._cloneInto();
|
|
3221
|
+
}
|
|
3222
|
+
keccak() {
|
|
3223
|
+
swap32IfBE(this.state32);
|
|
3224
|
+
keccakP(this.state32, this.rounds);
|
|
3225
|
+
swap32IfBE(this.state32);
|
|
3226
|
+
this.posOut = 0;
|
|
3227
|
+
this.pos = 0;
|
|
3228
|
+
}
|
|
3229
|
+
update(data) {
|
|
3230
|
+
aexists(this);
|
|
3231
|
+
abytes(data);
|
|
3232
|
+
const { blockLen, state } = this;
|
|
3233
|
+
const len = data.length;
|
|
3234
|
+
for (let pos = 0; pos < len; ) {
|
|
3235
|
+
const take = Math.min(blockLen - this.pos, len - pos);
|
|
3236
|
+
for (let i = 0; i < take; i++)
|
|
3237
|
+
state[this.pos++] ^= data[pos++];
|
|
3238
|
+
if (this.pos === blockLen)
|
|
3239
|
+
this.keccak();
|
|
3240
|
+
}
|
|
3241
|
+
return this;
|
|
3242
|
+
}
|
|
3243
|
+
finish() {
|
|
3244
|
+
if (this.finished)
|
|
3245
|
+
return;
|
|
3246
|
+
this.finished = true;
|
|
3247
|
+
const { state, suffix, pos, blockLen } = this;
|
|
3248
|
+
state[pos] ^= suffix;
|
|
3249
|
+
if ((suffix & 128) !== 0 && pos === blockLen - 1)
|
|
3250
|
+
this.keccak();
|
|
3251
|
+
state[blockLen - 1] ^= 128;
|
|
3252
|
+
this.keccak();
|
|
3253
|
+
}
|
|
3254
|
+
writeInto(out) {
|
|
3255
|
+
aexists(this, false);
|
|
3256
|
+
abytes(out);
|
|
3257
|
+
this.finish();
|
|
3258
|
+
const bufferOut = this.state;
|
|
3259
|
+
const { blockLen } = this;
|
|
3260
|
+
for (let pos = 0, len = out.length; pos < len; ) {
|
|
3261
|
+
if (this.posOut >= blockLen)
|
|
3262
|
+
this.keccak();
|
|
3263
|
+
const take = Math.min(blockLen - this.posOut, len - pos);
|
|
3264
|
+
out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);
|
|
3265
|
+
this.posOut += take;
|
|
3266
|
+
pos += take;
|
|
3267
|
+
}
|
|
3268
|
+
return out;
|
|
3269
|
+
}
|
|
3270
|
+
xofInto(out) {
|
|
3271
|
+
if (!this.enableXOF)
|
|
3272
|
+
throw new Error("XOF is not possible for this instance");
|
|
3273
|
+
return this.writeInto(out);
|
|
3274
|
+
}
|
|
3275
|
+
xof(bytes) {
|
|
3276
|
+
anumber(bytes);
|
|
3277
|
+
return this.xofInto(new Uint8Array(bytes));
|
|
3278
|
+
}
|
|
3279
|
+
digestInto(out) {
|
|
3280
|
+
aoutput(out, this);
|
|
3281
|
+
if (this.finished)
|
|
3282
|
+
throw new Error("digest() was already called");
|
|
3283
|
+
this.writeInto(out.subarray(0, this.outputLen));
|
|
3284
|
+
this.destroy();
|
|
3285
|
+
}
|
|
3286
|
+
digest() {
|
|
3287
|
+
const out = new Uint8Array(this.outputLen);
|
|
3288
|
+
this.digestInto(out);
|
|
3289
|
+
return out;
|
|
3290
|
+
}
|
|
3291
|
+
destroy() {
|
|
3292
|
+
this.destroyed = true;
|
|
3293
|
+
clean(this.state);
|
|
3294
|
+
}
|
|
3295
|
+
_cloneInto(to) {
|
|
3296
|
+
const { blockLen, suffix, outputLen, rounds, enableXOF } = this;
|
|
3297
|
+
to ||= new _Keccak(blockLen, suffix, outputLen, enableXOF, rounds);
|
|
3298
|
+
to.blockLen = blockLen;
|
|
3299
|
+
to.state32.set(this.state32);
|
|
3300
|
+
to.pos = this.pos;
|
|
3301
|
+
to.posOut = this.posOut;
|
|
3302
|
+
to.finished = this.finished;
|
|
3303
|
+
to.rounds = rounds;
|
|
3304
|
+
to.suffix = suffix;
|
|
3305
|
+
to.outputLen = outputLen;
|
|
3306
|
+
to.enableXOF = enableXOF;
|
|
3307
|
+
to.canXOF = this.canXOF;
|
|
3308
|
+
to.destroyed = this.destroyed;
|
|
3309
|
+
return to;
|
|
3310
|
+
}
|
|
3311
|
+
};
|
|
3312
|
+
var genKeccak = (suffix, blockLen, outputLen, info = {}) => createHasher(() => new Keccak(blockLen, suffix, outputLen), info);
|
|
3313
|
+
var keccak_256 = /* @__PURE__ */ genKeccak(1, 136, 32);
|
|
3314
|
+
|
|
3315
|
+
// ../../node_modules/.pnpm/micro-zk-proofs@0.3.1/node_modules/micro-zk-proofs/mimcsponge.js
|
|
3316
|
+
var Fr = bn254.fields.Fr;
|
|
3317
|
+
var SEED = "mimcsponge";
|
|
3318
|
+
var NROUNDS = 220;
|
|
3319
|
+
function getConstants(seed = SEED, nRounds = NROUNDS) {
|
|
3320
|
+
if (typeof seed !== "string")
|
|
3321
|
+
throw new TypeError('"seed" expected string, got type=' + typeof seed);
|
|
3322
|
+
anumber(nRounds, "nRounds");
|
|
3323
|
+
if (nRounds < 2)
|
|
3324
|
+
throw new RangeError(`expected nRounds >= 2, got ${nRounds}`);
|
|
3325
|
+
const cts = [BigInt(0)];
|
|
3326
|
+
let c = keccak_256(utf8ToBytes(seed));
|
|
3327
|
+
for (let i = 0; i < nRounds - 2; i++)
|
|
3328
|
+
cts.push(Fr.create(Fr.fromBytes(c = keccak_256(c), true)));
|
|
3329
|
+
cts.push(BigInt(0));
|
|
3330
|
+
return cts;
|
|
3331
|
+
}
|
|
3332
|
+
|
|
3333
|
+
// ../../node_modules/.pnpm/micro-wrkr@0.2.0/node_modules/micro-wrkr/utils.js
|
|
3334
|
+
var checkChunks = (numChunks, name = "numChunks") => {
|
|
3335
|
+
if (typeof numChunks !== "number")
|
|
3336
|
+
throw new TypeError(`expected ${name} number, got ${typeof numChunks}`);
|
|
3337
|
+
if (!Number.isSafeInteger(numChunks) || numChunks <= 0)
|
|
3338
|
+
throw new RangeError(`${name} must be > 0`);
|
|
3339
|
+
return numChunks;
|
|
3340
|
+
};
|
|
3341
|
+
function splitChunks(list, numChunks) {
|
|
3342
|
+
numChunks = checkChunks(numChunks);
|
|
3343
|
+
const chunkSize = Math.ceil(list.length / numChunks);
|
|
3344
|
+
const res = [];
|
|
3345
|
+
for (let i = 0; i < list.length; i += chunkSize)
|
|
3346
|
+
res.push(list.slice(i, i + chunkSize));
|
|
3347
|
+
return res;
|
|
3348
|
+
}
|
|
3349
|
+
var stringifyError = (e) => "" + (e instanceof Error ? e.message : e);
|
|
3350
|
+
var getConcurrencyFromPlatform = (platform) => {
|
|
3351
|
+
const cpus = platform.cpus();
|
|
3352
|
+
return cpus === void 0 ? 1 : cpus;
|
|
3353
|
+
};
|
|
3354
|
+
function initBatchGen(platform, getWorker, reducers, threads) {
|
|
3355
|
+
if (threads == null)
|
|
3356
|
+
threads = getConcurrencyFromPlatform(platform);
|
|
3357
|
+
let id = 0;
|
|
3358
|
+
const workers = [];
|
|
3359
|
+
const WAIT = {};
|
|
3360
|
+
const errHandler = (err) => {
|
|
3361
|
+
for (const i in WAIT)
|
|
3362
|
+
WAIT[i].reject(err);
|
|
3363
|
+
};
|
|
3364
|
+
const msgHandler = (msg) => {
|
|
3365
|
+
const { id: id2, res, err } = msg;
|
|
3366
|
+
const handler = WAIT[id2];
|
|
3367
|
+
delete WAIT[id2];
|
|
3368
|
+
if (!handler)
|
|
3369
|
+
throw new Error("unknown id");
|
|
3370
|
+
if (err !== void 0)
|
|
3371
|
+
handler.reject(new Error(err));
|
|
3372
|
+
else
|
|
3373
|
+
handler.resolve(res);
|
|
3374
|
+
};
|
|
3375
|
+
for (let i = 0; i < threads; i++) {
|
|
3376
|
+
workers.push(platform.createWorker(getWorker, msgHandler, errHandler));
|
|
3377
|
+
}
|
|
3378
|
+
const methods = {};
|
|
3379
|
+
for (const fn in reducers) {
|
|
3380
|
+
methods[fn] = async (input, _threads) => {
|
|
3381
|
+
const requested = checkChunks(_threads !== void 0 ? _threads : threads, "threads");
|
|
3382
|
+
const count = requested > workers.length ? workers.length : requested;
|
|
3383
|
+
const chunks = splitChunks(input, count);
|
|
3384
|
+
const promises = chunks.map((chunk, i) => {
|
|
3385
|
+
const currId = id++;
|
|
3386
|
+
const thread = workers[i];
|
|
3387
|
+
const p = new Promise((resolve, reject) => {
|
|
3388
|
+
if (WAIT[currId] !== void 0)
|
|
3389
|
+
reject(new Error("worker: id re-use"));
|
|
3390
|
+
WAIT[currId] = { resolve, reject };
|
|
3391
|
+
});
|
|
3392
|
+
thread.send({ id: currId, fn, payload: chunk });
|
|
3393
|
+
return p;
|
|
3394
|
+
});
|
|
3395
|
+
const results = await Promise.all(promises);
|
|
3396
|
+
const reducer = reducers[fn];
|
|
3397
|
+
return reducer ? reducer(results) : results.flat(1);
|
|
3398
|
+
};
|
|
3399
|
+
}
|
|
3400
|
+
const terminate = () => {
|
|
3401
|
+
errHandler(new Error("worker stopped"));
|
|
3402
|
+
for (const w of workers)
|
|
3403
|
+
w.terminate();
|
|
3404
|
+
};
|
|
3405
|
+
return { methods, terminate };
|
|
3406
|
+
}
|
|
3407
|
+
function initWrkr(platform) {
|
|
3408
|
+
return {
|
|
3409
|
+
getConcurrency: () => getConcurrencyFromPlatform(platform),
|
|
3410
|
+
// WorkerPlatform hooks are receiver-free function properties.
|
|
3411
|
+
// Custom platforms should close over state instead of using `this`.
|
|
3412
|
+
initWorker: platform.initWorker,
|
|
3413
|
+
initBatch: (getWorker, reducers, threads) => initBatchGen(platform, getWorker, reducers, threads)
|
|
3414
|
+
};
|
|
3415
|
+
}
|
|
3416
|
+
|
|
3417
|
+
// ../mimc-tree/dist/MimcMerkleTree.js
|
|
3418
|
+
var import_fixed_merkle_tree = __toESM(require_lib(), 1);
|
|
3419
|
+
var MIMC_MERKLE_TREE_ZERO_VALUE = "21663839004416932945382355908790599225266501822907911457504978515578255421292";
|
|
3420
|
+
var BN254_SCALAR_FIELD_SIZE = BigInt("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001");
|
|
3421
|
+
var MONTGOMERY_BITS = 256n;
|
|
3422
|
+
var MONTGOMERY_R = 1n << MONTGOMERY_BITS;
|
|
3423
|
+
var MONTGOMERY_MASK = MONTGOMERY_R - 1n;
|
|
3424
|
+
var MONTGOMERY_R2 = MONTGOMERY_R * MONTGOMERY_R % BN254_SCALAR_FIELD_SIZE;
|
|
3425
|
+
var MONTGOMERY_NEG_FIELD_INVERSE = getMontgomeryNegFieldInverse(BN254_SCALAR_FIELD_SIZE);
|
|
3426
|
+
var MIMC_SPONGE_ROUNDS = 220;
|
|
3427
|
+
var MIMC_SPONGE_CONSTANTS = getConstants("mimcsponge", MIMC_SPONGE_ROUNDS);
|
|
3428
|
+
var MIMC_SPONGE_CONSTANTS_MONTGOMERY = MIMC_SPONGE_CONSTANTS.map(mimcMontgomeryFromField);
|
|
3429
|
+
var MIMC_MERKLE_TREE_ZERO_VALUE_BIGINT = BigInt(MIMC_MERKLE_TREE_ZERO_VALUE);
|
|
3430
|
+
var MIMC_MERKLE_TREE_ZERO_VALUE_MONTGOMERY = mimcMontgomeryFromField(MIMC_MERKLE_TREE_ZERO_VALUE_BIGINT);
|
|
3431
|
+
var mimcBrowserWrkr = initWrkr({
|
|
3432
|
+
cpus: () => {
|
|
3433
|
+
const browserGlobal = globalThis;
|
|
3434
|
+
return browserGlobal.navigator?.hardwareConcurrency;
|
|
3435
|
+
},
|
|
3436
|
+
initWorker(handlers) {
|
|
3437
|
+
const workerScope = globalThis;
|
|
3438
|
+
if (!workerScope.postMessage || !workerScope.addEventListener) {
|
|
3439
|
+
throw new Error("MiMC browser worker must be started as a Web Worker.");
|
|
3440
|
+
}
|
|
3441
|
+
workerScope.addEventListener("message", (event) => {
|
|
3442
|
+
const { id, fn, payload } = event.data;
|
|
3443
|
+
try {
|
|
3444
|
+
workerScope.postMessage?.({
|
|
3445
|
+
id,
|
|
3446
|
+
res: handlers[fn](payload)
|
|
3447
|
+
});
|
|
3448
|
+
} catch (error) {
|
|
3449
|
+
workerScope.postMessage?.({
|
|
3450
|
+
id,
|
|
3451
|
+
err: stringifyError(error)
|
|
3452
|
+
});
|
|
3453
|
+
}
|
|
3454
|
+
});
|
|
3455
|
+
},
|
|
3456
|
+
createWorker(getWorker, onMessage, onError) {
|
|
3457
|
+
const worker = getWorker();
|
|
3458
|
+
worker.addEventListener("message", (event) => {
|
|
3459
|
+
onMessage(event.data);
|
|
3460
|
+
});
|
|
3461
|
+
worker.addEventListener("error", (event) => {
|
|
3462
|
+
onError(getBrowserWorkerErrorMessage(event));
|
|
3463
|
+
});
|
|
3464
|
+
worker.addEventListener("messageerror", (event) => {
|
|
3465
|
+
onError(getBrowserWorkerErrorMessage(event));
|
|
3466
|
+
});
|
|
3467
|
+
return {
|
|
3468
|
+
send: (message) => worker.postMessage(message),
|
|
3469
|
+
terminate: () => {
|
|
3470
|
+
worker.terminate();
|
|
3471
|
+
}
|
|
3472
|
+
};
|
|
3473
|
+
}
|
|
3474
|
+
});
|
|
3475
|
+
function getMontgomeryNegFieldInverse(modulus) {
|
|
3476
|
+
let inverse = 1n;
|
|
3477
|
+
for (let i = 0; i < 8; i++) {
|
|
3478
|
+
inverse = inverse * (2n - modulus * inverse) & MONTGOMERY_MASK;
|
|
3479
|
+
}
|
|
3480
|
+
return -inverse & MONTGOMERY_MASK;
|
|
3481
|
+
}
|
|
3482
|
+
function mimcFieldMod(value) {
|
|
3483
|
+
const result = value % BN254_SCALAR_FIELD_SIZE;
|
|
3484
|
+
return result >= 0n ? result : result + BN254_SCALAR_FIELD_SIZE;
|
|
3485
|
+
}
|
|
3486
|
+
function mimcMontgomeryReduce(value) {
|
|
3487
|
+
const quotient = (value & MONTGOMERY_MASK) * MONTGOMERY_NEG_FIELD_INVERSE & MONTGOMERY_MASK;
|
|
3488
|
+
let reduced = value + quotient * BN254_SCALAR_FIELD_SIZE >> MONTGOMERY_BITS;
|
|
3489
|
+
if (reduced >= BN254_SCALAR_FIELD_SIZE)
|
|
3490
|
+
reduced -= BN254_SCALAR_FIELD_SIZE;
|
|
3491
|
+
return reduced;
|
|
3492
|
+
}
|
|
3493
|
+
function mimcMontgomeryMultiply(left, right) {
|
|
3494
|
+
return mimcMontgomeryReduce(left * right);
|
|
3495
|
+
}
|
|
3496
|
+
function mimcMontgomeryFromField(value) {
|
|
3497
|
+
return mimcMontgomeryMultiply(mimcFieldMod(value), MONTGOMERY_R2);
|
|
3498
|
+
}
|
|
3499
|
+
function mimcSpongeUpdateMontgomery(input, spongeLeft, spongeRight) {
|
|
3500
|
+
const constants = MIMC_SPONGE_CONSTANTS_MONTGOMERY;
|
|
3501
|
+
const fieldSize = BN254_SCALAR_FIELD_SIZE;
|
|
3502
|
+
const inverse = MONTGOMERY_NEG_FIELD_INVERSE;
|
|
3503
|
+
const mask = MONTGOMERY_MASK;
|
|
3504
|
+
let left = spongeLeft + input;
|
|
3505
|
+
if (left >= fieldSize)
|
|
3506
|
+
left -= fieldSize;
|
|
3507
|
+
let right = spongeRight;
|
|
3508
|
+
for (let round = 0; round < MIMC_SPONGE_ROUNDS; round++) {
|
|
3509
|
+
let t = left + constants[round];
|
|
3510
|
+
if (t >= fieldSize)
|
|
3511
|
+
t -= fieldSize;
|
|
3512
|
+
let product = t * t;
|
|
3513
|
+
let quotient = (product & mask) * inverse & mask;
|
|
3514
|
+
let squared = product + quotient * fieldSize >> MONTGOMERY_BITS;
|
|
3515
|
+
if (squared >= fieldSize)
|
|
3516
|
+
squared -= fieldSize;
|
|
3517
|
+
product = squared * squared;
|
|
3518
|
+
quotient = (product & mask) * inverse & mask;
|
|
3519
|
+
let fourthPower = product + quotient * fieldSize >> MONTGOMERY_BITS;
|
|
3520
|
+
if (fourthPower >= fieldSize)
|
|
3521
|
+
fourthPower -= fieldSize;
|
|
3522
|
+
product = fourthPower * t;
|
|
3523
|
+
quotient = (product & mask) * inverse & mask;
|
|
3524
|
+
let fifthPower = product + quotient * fieldSize >> MONTGOMERY_BITS;
|
|
3525
|
+
if (fifthPower >= fieldSize)
|
|
3526
|
+
fifthPower -= fieldSize;
|
|
3527
|
+
let nextRight = right + fifthPower;
|
|
3528
|
+
if (nextRight >= fieldSize)
|
|
3529
|
+
nextRight -= fieldSize;
|
|
3530
|
+
if (round < MIMC_SPONGE_ROUNDS - 1) {
|
|
3531
|
+
right = left;
|
|
3532
|
+
left = nextRight;
|
|
3533
|
+
} else {
|
|
3534
|
+
right = nextRight;
|
|
3535
|
+
}
|
|
3536
|
+
}
|
|
3537
|
+
return [left, right];
|
|
3538
|
+
}
|
|
3539
|
+
function mimcMerkleTreeHashMontgomery(left, right) {
|
|
3540
|
+
const [firstLeft, firstRight] = mimcSpongeUpdateMontgomery(left, 0n, 0n);
|
|
3541
|
+
return mimcSpongeUpdateMontgomery(right, firstLeft, firstRight)[0];
|
|
3542
|
+
}
|
|
3543
|
+
function __mimcHashLayerMontgomery(nodes, zero, startNodeIndex = 0, previousLayerLength = nodes.length) {
|
|
3544
|
+
const currentLayerLength = Math.ceil(nodes.length / 2);
|
|
3545
|
+
const currentLayer = new Array(currentLayerLength);
|
|
3546
|
+
for (let nodeIndex = 0, parentIndex = 0; nodeIndex < nodes.length; nodeIndex += 2, parentIndex++) {
|
|
3547
|
+
const globalNodeIndex = startNodeIndex + nodeIndex;
|
|
3548
|
+
const left = nodes[nodeIndex];
|
|
3549
|
+
const right = globalNodeIndex + 1 < previousLayerLength ? nodes[nodeIndex + 1] : zero;
|
|
3550
|
+
currentLayer[parentIndex] = mimcMerkleTreeHashMontgomery(left, right);
|
|
3551
|
+
}
|
|
3552
|
+
return currentLayer;
|
|
3553
|
+
}
|
|
3554
|
+
function getBrowserWorkerErrorMessage(event) {
|
|
3555
|
+
if (event.error instanceof Error) {
|
|
3556
|
+
return event.error.message;
|
|
3557
|
+
}
|
|
3558
|
+
if (event.error !== void 0) {
|
|
3559
|
+
return String(event.error);
|
|
3560
|
+
}
|
|
3561
|
+
return event.message ?? "MiMC browser worker failed.";
|
|
3562
|
+
}
|
|
3563
|
+
|
|
3564
|
+
// ../mimc-tree/dist/MimcMerkleTreeWorker.js
|
|
3565
|
+
if (!parentPort) {
|
|
3566
|
+
throw new Error("MiMC worker must be started as a worker thread.");
|
|
3567
|
+
}
|
|
3568
|
+
parentPort.on("message", (value) => {
|
|
3569
|
+
const request = value;
|
|
3570
|
+
const signal = new Int32Array(request.signal);
|
|
3571
|
+
try {
|
|
3572
|
+
request.port.postMessage({
|
|
3573
|
+
nodes: __mimcHashLayerMontgomery(request.nodes, request.zero, request.startNodeIndex, request.previousLayerLength)
|
|
3574
|
+
});
|
|
3575
|
+
} catch (error) {
|
|
3576
|
+
request.port.postMessage({
|
|
3577
|
+
error: error instanceof Error ? error.message : String(error)
|
|
3578
|
+
});
|
|
3579
|
+
} finally {
|
|
3580
|
+
request.port.close();
|
|
3581
|
+
Atomics.store(signal, 0, 1);
|
|
3582
|
+
Atomics.notify(signal, 0);
|
|
3583
|
+
}
|
|
3584
|
+
});
|
|
3585
|
+
/*! Bundled license information:
|
|
3586
|
+
|
|
3587
|
+
@noble/curves/utils.js:
|
|
3588
|
+
@noble/curves/abstract/modular.js:
|
|
3589
|
+
@noble/curves/abstract/curve.js:
|
|
3590
|
+
@noble/curves/abstract/weierstrass.js:
|
|
3591
|
+
@noble/curves/abstract/bls.js:
|
|
3592
|
+
@noble/curves/abstract/tower.js:
|
|
3593
|
+
@noble/curves/bn254.js:
|
|
3594
|
+
(*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
3595
|
+
*/
|