tornado-core 1.0.7

revert back to .ws
This commit is contained in:
Tornado Contrib 2024-09-21 17:25:44 +00:00
parent ef56beb29b
commit 700426acb7
Signed by: tornadocontrib
GPG Key ID: 60B4DF1A076C64B1
6 changed files with 1392 additions and 1387 deletions

1
.npmrc Normal file

@ -0,0 +1 @@
@tornado:registry=https://git.tornado.ws/api/packages/tornado-packages/npm/

922
dist/index.umd.js vendored

@ -9511,160 +9511,160 @@ exports.bytes = exports.stringToBytes;
/***/ ((__unused_webpack_module, exports) => { /***/ ((__unused_webpack_module, exports) => {
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.BaseTree = void 0; exports.BaseTree = void 0;
class BaseTree { class BaseTree {
get capacity() { get capacity() {
return 2 ** this.levels; return 2 ** this.levels;
} }
get layers() { get layers() {
return this._layers.slice(); return this._layers.slice();
} }
get zeros() { get zeros() {
return this._zeros.slice(); return this._zeros.slice();
} }
get elements() { get elements() {
return this._layers[0].slice(); return this._layers[0].slice();
} }
get root() { get root() {
var _a; var _a;
return (_a = this._layers[this.levels][0]) !== null && _a !== void 0 ? _a : this._zeros[this.levels]; return (_a = this._layers[this.levels][0]) !== null && _a !== void 0 ? _a : this._zeros[this.levels];
} }
/** /**
* Find an element in the tree * Find an element in the tree
* @param elements elements of tree * @param elements elements of tree
* @param element An element to find * @param element An element to find
* @param comparator A function that checks leaf value equality * @param comparator A function that checks leaf value equality
* @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 * @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
* @returns {number} Index if element is found, otherwise -1 * @returns {number} Index if element is found, otherwise -1
*/ */
static indexOf(elements, element, fromIndex, comparator) { static indexOf(elements, element, fromIndex, comparator) {
if (comparator) { if (comparator) {
return elements.findIndex((el) => comparator(element, el)); return elements.findIndex((el) => comparator(element, el));
} }
else { else {
return elements.indexOf(element, fromIndex); return elements.indexOf(element, fromIndex);
} }
} }
/** /**
* Insert new element into the tree * Insert new element into the tree
* @param element Element to insert * @param element Element to insert
*/ */
insert(element) { insert(element) {
if (this._layers[0].length >= this.capacity) { if (this._layers[0].length >= this.capacity) {
throw new Error('Tree is full'); throw new Error('Tree is full');
} }
this.update(this._layers[0].length, element); this.update(this._layers[0].length, element);
} }
/* /*
* Insert multiple elements into the tree. * Insert multiple elements into the tree.
* @param {Array} elements Elements to insert * @param {Array} elements Elements to insert
*/ */
bulkInsert(elements) { bulkInsert(elements) {
if (!elements.length) { if (!elements.length) {
return; return;
} }
if (this._layers[0].length + elements.length > this.capacity) { if (this._layers[0].length + elements.length > this.capacity) {
throw new Error('Tree is full'); throw new Error('Tree is full');
} }
// First we insert all elements except the last one // First we insert all elements except the last one
// updating only full subtree hashes (all layers where inserted element has odd index) // updating only full subtree hashes (all layers where inserted element has odd index)
// the last element will update the full path to the root making the tree consistent again // the last element will update the full path to the root making the tree consistent again
for (let i = 0; i < elements.length - 1; i++) { for (let i = 0; i < elements.length - 1; i++) {
this._layers[0].push(elements[i]); this._layers[0].push(elements[i]);
let level = 0; let level = 0;
let index = this._layers[0].length - 1; let index = this._layers[0].length - 1;
while (index % 2 === 1) { while (index % 2 === 1) {
level++; level++;
index >>= 1; index >>= 1;
const left = this._layers[level - 1][index * 2]; const left = this._layers[level - 1][index * 2];
const right = this._layers[level - 1][index * 2 + 1]; const right = this._layers[level - 1][index * 2 + 1];
this._layers[level][index] = this._hashFn(left, right); this._layers[level][index] = this._hashFn(left, right);
} }
} }
this.insert(elements[elements.length - 1]); this.insert(elements[elements.length - 1]);
} }
/** /**
* Change an element in the tree * Change an element in the tree
* @param {number} index Index of element to change * @param {number} index Index of element to change
* @param element Updated element value * @param element Updated element value
*/ */
update(index, element) { update(index, element) {
if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) { if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) {
throw new Error('Insert index out of bounds: ' + index); throw new Error('Insert index out of bounds: ' + index);
} }
this._layers[0][index] = element; this._layers[0][index] = element;
this._processUpdate(index); this._processUpdate(index);
} }
/** /**
* Get merkle path to a leaf * Get merkle path to a leaf
* @param {number} index Leaf index to generate path for * @param {number} index Leaf index to generate path for
* @returns {{pathElements: Object[], pathIndex: number[]}} An object containing adjacent elements and left-right index * @returns {{pathElements: Object[], pathIndex: number[]}} An object containing adjacent elements and left-right index
*/ */
path(index) { path(index) {
if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) { if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) {
throw new Error('Index out of bounds: ' + index); throw new Error('Index out of bounds: ' + index);
} }
let elIndex = +index; let elIndex = +index;
const pathElements = []; const pathElements = [];
const pathIndices = []; const pathIndices = [];
const pathPositions = []; const pathPositions = [];
for (let level = 0; level < this.levels; level++) { for (let level = 0; level < this.levels; level++) {
pathIndices[level] = elIndex % 2; pathIndices[level] = elIndex % 2;
const leafIndex = elIndex ^ 1; const leafIndex = elIndex ^ 1;
if (leafIndex < this._layers[level].length) { if (leafIndex < this._layers[level].length) {
pathElements[level] = this._layers[level][leafIndex]; pathElements[level] = this._layers[level][leafIndex];
pathPositions[level] = leafIndex; pathPositions[level] = leafIndex;
} }
else { else {
pathElements[level] = this._zeros[level]; pathElements[level] = this._zeros[level];
pathPositions[level] = 0; pathPositions[level] = 0;
} }
elIndex >>= 1; elIndex >>= 1;
} }
return { return {
pathElements, pathElements,
pathIndices, pathIndices,
pathPositions, pathPositions,
pathRoot: this.root, pathRoot: this.root,
}; };
} }
_buildZeros() { _buildZeros() {
this._zeros = [this.zeroElement]; this._zeros = [this.zeroElement];
for (let i = 1; i <= this.levels; i++) { for (let i = 1; i <= this.levels; i++) {
this._zeros[i] = this._hashFn(this._zeros[i - 1], this._zeros[i - 1]); this._zeros[i] = this._hashFn(this._zeros[i - 1], this._zeros[i - 1]);
} }
} }
_processNodes(nodes, layerIndex) { _processNodes(nodes, layerIndex) {
const length = nodes.length; const length = nodes.length;
let currentLength = Math.ceil(length / 2); let currentLength = Math.ceil(length / 2);
const currentLayer = new Array(currentLength); const currentLayer = new Array(currentLength);
currentLength--; currentLength--;
const starFrom = length - ((length % 2) ^ 1); const starFrom = length - ((length % 2) ^ 1);
let j = 0; let j = 0;
for (let i = starFrom; i >= 0; i -= 2) { for (let i = starFrom; i >= 0; i -= 2) {
if (nodes[i - 1] === undefined) if (nodes[i - 1] === undefined)
break; break;
const left = nodes[i - 1]; const left = nodes[i - 1];
const right = (i === starFrom && length % 2 === 1) ? this._zeros[layerIndex - 1] : nodes[i]; const right = (i === starFrom && length % 2 === 1) ? this._zeros[layerIndex - 1] : nodes[i];
currentLayer[currentLength - j] = this._hashFn(left, right); currentLayer[currentLength - j] = this._hashFn(left, right);
j++; j++;
} }
return currentLayer; return currentLayer;
} }
_processUpdate(index) { _processUpdate(index) {
for (let level = 1; level <= this.levels; level++) { for (let level = 1; level <= this.levels; level++) {
index >>= 1; index >>= 1;
const left = this._layers[level - 1][index * 2]; const left = this._layers[level - 1][index * 2];
const right = index * 2 + 1 < this._layers[level - 1].length const right = index * 2 + 1 < this._layers[level - 1].length
? this._layers[level - 1][index * 2 + 1] ? this._layers[level - 1][index * 2 + 1]
: this._zeros[level - 1]; : this._zeros[level - 1];
this._layers[level][index] = this._hashFn(left, right); this._layers[level][index] = this._hashFn(left, right);
} }
} }
} }
exports.BaseTree = BaseTree; exports.BaseTree = BaseTree;
/***/ }), /***/ }),
@ -9673,120 +9673,120 @@ exports.BaseTree = BaseTree;
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict"; "use strict";
var __importDefault = (this && this.__importDefault) || function (mod) { var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
const simpleHash_1 = __importDefault(__webpack_require__(5319)); const simpleHash_1 = __importDefault(__webpack_require__(5319));
const BaseTree_1 = __webpack_require__(7736); const BaseTree_1 = __webpack_require__(7736);
class MerkleTree extends BaseTree_1.BaseTree { class MerkleTree extends BaseTree_1.BaseTree {
constructor(levels, elements = [], { hashFunction = simpleHash_1.default, zeroElement = 0, } = {}) { constructor(levels, elements = [], { hashFunction = simpleHash_1.default, zeroElement = 0, } = {}) {
super(); super();
this.levels = levels; this.levels = levels;
if (elements.length > this.capacity) { if (elements.length > this.capacity) {
throw new Error('Tree is full'); throw new Error('Tree is full');
} }
this._hashFn = hashFunction; this._hashFn = hashFunction;
this.zeroElement = zeroElement; this.zeroElement = zeroElement;
this._layers = []; this._layers = [];
const leaves = elements.slice(); const leaves = elements.slice();
this._layers = [leaves]; this._layers = [leaves];
this._buildZeros(); this._buildZeros();
this._buildHashes(); this._buildHashes();
} }
_buildHashes() { _buildHashes() {
for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) { for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) {
const nodes = this._layers[layerIndex - 1]; const nodes = this._layers[layerIndex - 1];
this._layers[layerIndex] = this._processNodes(nodes, layerIndex); this._layers[layerIndex] = this._processNodes(nodes, layerIndex);
} }
} }
/** /**
* Insert multiple elements into the tree. * Insert multiple elements into the tree.
* @param {Array} elements Elements to insert * @param {Array} elements Elements to insert
*/ */
bulkInsert(elements) { bulkInsert(elements) {
if (!elements.length) { if (!elements.length) {
return; return;
} }
if (this._layers[0].length + elements.length > this.capacity) { if (this._layers[0].length + elements.length > this.capacity) {
throw new Error('Tree is full'); throw new Error('Tree is full');
} }
// First we insert all elements except the last one // First we insert all elements except the last one
// updating only full subtree hashes (all layers where inserted element has odd index) // updating only full subtree hashes (all layers where inserted element has odd index)
// the last element will update the full path to the root making the tree consistent again // the last element will update the full path to the root making the tree consistent again
for (let i = 0; i < elements.length - 1; i++) { for (let i = 0; i < elements.length - 1; i++) {
this._layers[0].push(elements[i]); this._layers[0].push(elements[i]);
let level = 0; let level = 0;
let index = this._layers[0].length - 1; let index = this._layers[0].length - 1;
while (index % 2 === 1) { while (index % 2 === 1) {
level++; level++;
index >>= 1; index >>= 1;
this._layers[level][index] = this._hashFn(this._layers[level - 1][index * 2], this._layers[level - 1][index * 2 + 1]); this._layers[level][index] = this._hashFn(this._layers[level - 1][index * 2], this._layers[level - 1][index * 2 + 1]);
} }
} }
this.insert(elements[elements.length - 1]); this.insert(elements[elements.length - 1]);
} }
indexOf(element, comparator) { indexOf(element, comparator) {
return BaseTree_1.BaseTree.indexOf(this._layers[0], element, 0, comparator); return BaseTree_1.BaseTree.indexOf(this._layers[0], element, 0, comparator);
} }
proof(element) { proof(element) {
const index = this.indexOf(element); const index = this.indexOf(element);
return this.path(index); return this.path(index);
} }
getTreeEdge(edgeIndex) { getTreeEdge(edgeIndex) {
const edgeElement = this._layers[0][edgeIndex]; const edgeElement = this._layers[0][edgeIndex];
if (edgeElement === undefined) { if (edgeElement === undefined) {
throw new Error('Element not found'); throw new Error('Element not found');
} }
const edgePath = this.path(edgeIndex); const edgePath = this.path(edgeIndex);
return { edgePath, edgeElement, edgeIndex, edgeElementsCount: this._layers[0].length }; return { edgePath, edgeElement, edgeIndex, edgeElementsCount: this._layers[0].length };
} }
/** /**
* 🪓 * 🪓
* @param count * @param count
*/ */
getTreeSlices(count = 4) { getTreeSlices(count = 4) {
const length = this._layers[0].length; const length = this._layers[0].length;
let size = Math.ceil(length / count); let size = Math.ceil(length / count);
if (size % 2) if (size % 2)
size++; size++;
const slices = []; const slices = [];
for (let i = 0; i < length; i += size) { for (let i = 0; i < length; i += size) {
const edgeLeft = i; const edgeLeft = i;
const edgeRight = i + size; const edgeRight = i + size;
slices.push({ edge: this.getTreeEdge(edgeLeft), elements: this.elements.slice(edgeLeft, edgeRight) }); slices.push({ edge: this.getTreeEdge(edgeLeft), elements: this.elements.slice(edgeLeft, edgeRight) });
} }
return slices; return slices;
} }
/** /**
* Serialize entire tree state including intermediate layers into a plain object * Serialize entire tree state including intermediate layers into a plain object
* Deserializing it back will not require to recompute any hashes * Deserializing it back will not require to recompute any hashes
* Elements are not converted to a plain type, this is responsibility of the caller * Elements are not converted to a plain type, this is responsibility of the caller
*/ */
serialize() { serialize() {
return { return {
levels: this.levels, levels: this.levels,
_zeros: this._zeros, _zeros: this._zeros,
_layers: this._layers, _layers: this._layers,
}; };
} }
/** /**
* Deserialize data into a MerkleTree instance * Deserialize data into a MerkleTree instance
* Make sure to provide the same hashFunction as was used in the source tree, * Make sure to provide the same hashFunction as was used in the source tree,
* otherwise the tree state will be invalid * otherwise the tree state will be invalid
*/ */
static deserialize(data, hashFunction) { static deserialize(data, hashFunction) {
const instance = Object.assign(Object.create(this.prototype), data); const instance = Object.assign(Object.create(this.prototype), data);
instance._hashFn = hashFunction || simpleHash_1.default; instance._hashFn = hashFunction || simpleHash_1.default;
instance.zeroElement = instance._zeros[0]; instance.zeroElement = instance._zeros[0];
return instance; return instance;
} }
toString() { toString() {
return JSON.stringify(this.serialize()); return JSON.stringify(this.serialize());
} }
} }
exports["default"] = MerkleTree; exports["default"] = MerkleTree;
/***/ }), /***/ }),
@ -9795,165 +9795,165 @@ exports["default"] = MerkleTree;
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict"; "use strict";
var __importDefault = (this && this.__importDefault) || function (mod) { var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.PartialMerkleTree = void 0; exports.PartialMerkleTree = void 0;
const simpleHash_1 = __importDefault(__webpack_require__(5319)); const simpleHash_1 = __importDefault(__webpack_require__(5319));
const BaseTree_1 = __webpack_require__(7736); const BaseTree_1 = __webpack_require__(7736);
class PartialMerkleTree extends BaseTree_1.BaseTree { class PartialMerkleTree extends BaseTree_1.BaseTree {
constructor(levels, { edgePath, edgeElement, edgeIndex, edgeElementsCount, }, leaves, { hashFunction, zeroElement } = {}) { constructor(levels, { edgePath, edgeElement, edgeIndex, edgeElementsCount, }, leaves, { hashFunction, zeroElement } = {}) {
super(); super();
if (edgeIndex + leaves.length !== edgeElementsCount) if (edgeIndex + leaves.length !== edgeElementsCount)
throw new Error('Invalid number of elements'); throw new Error('Invalid number of elements');
this._edgeLeafProof = edgePath; this._edgeLeafProof = edgePath;
this._initialRoot = edgePath.pathRoot; this._initialRoot = edgePath.pathRoot;
this.zeroElement = zeroElement !== null && zeroElement !== void 0 ? zeroElement : 0; this.zeroElement = zeroElement !== null && zeroElement !== void 0 ? zeroElement : 0;
this._edgeLeaf = { data: edgeElement, index: edgeIndex }; this._edgeLeaf = { data: edgeElement, index: edgeIndex };
this._leavesAfterEdge = leaves; this._leavesAfterEdge = leaves;
this.levels = levels; this.levels = levels;
this._hashFn = hashFunction || simpleHash_1.default; this._hashFn = hashFunction || simpleHash_1.default;
this._createProofMap(); this._createProofMap();
this._buildTree(); this._buildTree();
} }
get edgeIndex() { get edgeIndex() {
return this._edgeLeaf.index; return this._edgeLeaf.index;
} }
get edgeElement() { get edgeElement() {
return this._edgeLeaf.data; return this._edgeLeaf.data;
} }
get edgeLeafProof() { get edgeLeafProof() {
return this._edgeLeafProof; return this._edgeLeafProof;
} }
_createProofMap() { _createProofMap() {
this._proofMap = this.edgeLeafProof.pathPositions.reduce((p, c, i) => { this._proofMap = this.edgeLeafProof.pathPositions.reduce((p, c, i) => {
p.set(i, [c, this.edgeLeafProof.pathElements[i]]); p.set(i, [c, this.edgeLeafProof.pathElements[i]]);
return p; return p;
}, new Map()); }, new Map());
this._proofMap.set(this.levels, [0, this.edgeLeafProof.pathRoot]); this._proofMap.set(this.levels, [0, this.edgeLeafProof.pathRoot]);
} }
_buildTree() { _buildTree() {
const edgeLeafIndex = this._edgeLeaf.index; const edgeLeafIndex = this._edgeLeaf.index;
this._leaves = Array(edgeLeafIndex).concat(this._leavesAfterEdge); this._leaves = Array(edgeLeafIndex).concat(this._leavesAfterEdge);
if (this._proofMap.has(0)) { if (this._proofMap.has(0)) {
const [proofPos, proofEl] = this._proofMap.get(0); const [proofPos, proofEl] = this._proofMap.get(0);
this._leaves[proofPos] = proofEl; this._leaves[proofPos] = proofEl;
} }
this._layers = [this._leaves]; this._layers = [this._leaves];
this._buildZeros(); this._buildZeros();
this._buildHashes(); this._buildHashes();
} }
_buildHashes() { _buildHashes() {
for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) { for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) {
const nodes = this._layers[layerIndex - 1]; const nodes = this._layers[layerIndex - 1];
const currentLayer = this._processNodes(nodes, layerIndex); const currentLayer = this._processNodes(nodes, layerIndex);
if (this._proofMap.has(layerIndex)) { if (this._proofMap.has(layerIndex)) {
const [proofPos, proofEl] = this._proofMap.get(layerIndex); const [proofPos, proofEl] = this._proofMap.get(layerIndex);
if (!currentLayer[proofPos]) if (!currentLayer[proofPos])
currentLayer[proofPos] = proofEl; currentLayer[proofPos] = proofEl;
} }
this._layers[layerIndex] = currentLayer; this._layers[layerIndex] = currentLayer;
} }
} }
/** /**
* Change an element in the tree * Change an element in the tree
* @param {number} index Index of element to change * @param {number} index Index of element to change
* @param element Updated element value * @param element Updated element value
*/ */
update(index, element) { update(index, element) {
if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) { if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) {
throw new Error('Insert index out of bounds: ' + index); throw new Error('Insert index out of bounds: ' + index);
} }
if (index < this._edgeLeaf.index) { if (index < this._edgeLeaf.index) {
throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`); throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`);
} }
this._layers[0][index] = element; this._layers[0][index] = element;
this._processUpdate(index); this._processUpdate(index);
} }
path(index) { path(index) {
var _a; var _a;
if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) { if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) {
throw new Error('Index out of bounds: ' + index); throw new Error('Index out of bounds: ' + index);
} }
if (index < this._edgeLeaf.index) { if (index < this._edgeLeaf.index) {
throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`); throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`);
} }
let elIndex = Number(index); let elIndex = Number(index);
const pathElements = []; const pathElements = [];
const pathIndices = []; const pathIndices = [];
const pathPositions = []; const pathPositions = [];
for (let level = 0; level < this.levels; level++) { for (let level = 0; level < this.levels; level++) {
pathIndices[level] = elIndex % 2; pathIndices[level] = elIndex % 2;
const leafIndex = elIndex ^ 1; const leafIndex = elIndex ^ 1;
if (leafIndex < this._layers[level].length) { if (leafIndex < this._layers[level].length) {
pathElements[level] = this._layers[level][leafIndex]; pathElements[level] = this._layers[level][leafIndex];
pathPositions[level] = leafIndex; pathPositions[level] = leafIndex;
} }
else { else {
pathElements[level] = this._zeros[level]; pathElements[level] = this._zeros[level];
pathPositions[level] = 0; pathPositions[level] = 0;
} }
const [proofPos, proofEl] = this._proofMap.get(level); const [proofPos, proofEl] = this._proofMap.get(level);
pathElements[level] = (_a = pathElements[level]) !== null && _a !== void 0 ? _a : (proofPos === leafIndex ? proofEl : this._zeros[level]); pathElements[level] = (_a = pathElements[level]) !== null && _a !== void 0 ? _a : (proofPos === leafIndex ? proofEl : this._zeros[level]);
elIndex >>= 1; elIndex >>= 1;
} }
return { return {
pathElements, pathElements,
pathIndices, pathIndices,
pathPositions, pathPositions,
pathRoot: this.root, pathRoot: this.root,
}; };
} }
indexOf(element, comparator) { indexOf(element, comparator) {
return BaseTree_1.BaseTree.indexOf(this._layers[0], element, this.edgeIndex, comparator); return BaseTree_1.BaseTree.indexOf(this._layers[0], element, this.edgeIndex, comparator);
} }
proof(element) { proof(element) {
const index = this.indexOf(element); const index = this.indexOf(element);
return this.path(index); return this.path(index);
} }
/** /**
* Shifts edge of tree to left * Shifts edge of tree to left
* @param edge new TreeEdge below current edge * @param edge new TreeEdge below current edge
* @param elements leaves between old and new edge * @param elements leaves between old and new edge
*/ */
shiftEdge(edge, elements) { shiftEdge(edge, elements) {
if (this._edgeLeaf.index <= edge.edgeIndex) { if (this._edgeLeaf.index <= edge.edgeIndex) {
throw new Error(`New edgeIndex should be smaller then ${this._edgeLeaf.index}`); throw new Error(`New edgeIndex should be smaller then ${this._edgeLeaf.index}`);
} }
if (elements.length !== (this._edgeLeaf.index - edge.edgeIndex)) { if (elements.length !== (this._edgeLeaf.index - edge.edgeIndex)) {
throw new Error(`Elements length should be ${this._edgeLeaf.index - edge.edgeIndex}`); throw new Error(`Elements length should be ${this._edgeLeaf.index - edge.edgeIndex}`);
} }
this._edgeLeafProof = edge.edgePath; this._edgeLeafProof = edge.edgePath;
this._edgeLeaf = { index: edge.edgeIndex, data: edge.edgeElement }; this._edgeLeaf = { index: edge.edgeIndex, data: edge.edgeElement };
this._leavesAfterEdge = [...elements, ...this._leavesAfterEdge]; this._leavesAfterEdge = [...elements, ...this._leavesAfterEdge];
this._createProofMap(); this._createProofMap();
this._buildTree(); this._buildTree();
} }
serialize() { serialize() {
return { return {
_edgeLeafProof: this._edgeLeafProof, _edgeLeafProof: this._edgeLeafProof,
_edgeLeaf: this._edgeLeaf, _edgeLeaf: this._edgeLeaf,
_layers: this._layers, _layers: this._layers,
_zeros: this._zeros, _zeros: this._zeros,
levels: this.levels, levels: this.levels,
}; };
} }
static deserialize(data, hashFunction) { static deserialize(data, hashFunction) {
const instance = Object.assign(Object.create(this.prototype), data); const instance = Object.assign(Object.create(this.prototype), data);
instance._hashFn = hashFunction || simpleHash_1.default; instance._hashFn = hashFunction || simpleHash_1.default;
instance._initialRoot = data._edgeLeafProof.pathRoot; instance._initialRoot = data._edgeLeafProof.pathRoot;
instance.zeroElement = instance._zeros[0]; instance.zeroElement = instance._zeros[0];
instance._leavesAfterEdge = instance._layers[0].slice(data._edgeLeaf.index); instance._leavesAfterEdge = instance._layers[0].slice(data._edgeLeaf.index);
instance._createProofMap(); instance._createProofMap();
return instance; return instance;
} }
toString() { toString() {
return JSON.stringify(this.serialize()); return JSON.stringify(this.serialize());
} }
} }
exports.PartialMerkleTree = PartialMerkleTree; exports.PartialMerkleTree = PartialMerkleTree;
/***/ }), /***/ }),
@ -9962,19 +9962,19 @@ exports.PartialMerkleTree = PartialMerkleTree;
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict"; "use strict";
var __importDefault = (this && this.__importDefault) || function (mod) { var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.MerkleTree = exports.simpleHash = exports.PartialMerkleTree = void 0; exports.MerkleTree = exports.simpleHash = exports.PartialMerkleTree = void 0;
const FixedMerkleTree_1 = __importDefault(__webpack_require__(9093)); const FixedMerkleTree_1 = __importDefault(__webpack_require__(9093));
Object.defineProperty(exports, "MerkleTree", ({ enumerable: true, get: function () { return FixedMerkleTree_1.default; } })); Object.defineProperty(exports, "MerkleTree", ({ enumerable: true, get: function () { return FixedMerkleTree_1.default; } }));
var PartialMerkleTree_1 = __webpack_require__(91230); var PartialMerkleTree_1 = __webpack_require__(91230);
Object.defineProperty(exports, "PartialMerkleTree", ({ enumerable: true, get: function () { return PartialMerkleTree_1.PartialMerkleTree; } })); Object.defineProperty(exports, "PartialMerkleTree", ({ enumerable: true, get: function () { return PartialMerkleTree_1.PartialMerkleTree; } }));
var simpleHash_1 = __webpack_require__(5319); var simpleHash_1 = __webpack_require__(5319);
Object.defineProperty(exports, "simpleHash", ({ enumerable: true, get: function () { return simpleHash_1.simpleHash; } })); Object.defineProperty(exports, "simpleHash", ({ enumerable: true, get: function () { return simpleHash_1.simpleHash; } }));
exports["default"] = FixedMerkleTree_1.default; exports["default"] = FixedMerkleTree_1.default;
/***/ }), /***/ }),
@ -9983,27 +9983,27 @@ exports["default"] = FixedMerkleTree_1.default;
/***/ ((__unused_webpack_module, exports) => { /***/ ((__unused_webpack_module, exports) => {
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.simpleHash = void 0; exports.simpleHash = void 0;
/*** /***
* This is insecure hash function, just for example only * This is insecure hash function, just for example only
* @param data * @param data
* @param seed * @param seed
* @param hashLength * @param hashLength
*/ */
function simpleHash(data, seed, hashLength = 40) { function simpleHash(data, seed, hashLength = 40) {
const str = data.join(''); const str = data.join('');
let i, l, hval = seed !== null && seed !== void 0 ? seed : 0x811c9dcc5; let i, l, hval = seed !== null && seed !== void 0 ? seed : 0x811c9dcc5;
for (i = 0, l = str.length; i < l; i++) { for (i = 0, l = str.length; i < l; i++) {
hval ^= str.charCodeAt(i); hval ^= str.charCodeAt(i);
hval += (hval << 1) + (hval << 4) + (hval << 6) + (hval << 8) + (hval << 24); hval += (hval << 1) + (hval << 4) + (hval << 6) + (hval << 8) + (hval << 24);
} }
const hash = (hval >>> 0).toString(16); const hash = (hval >>> 0).toString(16);
return BigInt('0x' + hash.padEnd(hashLength - (hash.length - 1), '0')).toString(10); return BigInt('0x' + hash.padEnd(hashLength - (hash.length - 1), '0')).toString(10);
} }
exports.simpleHash = simpleHash; exports.simpleHash = simpleHash;
exports["default"] = (left, right) => simpleHash([left, right]); exports["default"] = (left, right) => simpleHash([left, right]);
/***/ }), /***/ }),

@ -15,470 +15,470 @@ var FixedMerkleTree = {};
var simpleHash$1 = {}; var simpleHash$1 = {};
Object.defineProperty(simpleHash$1, "__esModule", { value: true }); Object.defineProperty(simpleHash$1, "__esModule", { value: true });
simpleHash$1.simpleHash = void 0; simpleHash$1.simpleHash = void 0;
/*** /***
* This is insecure hash function, just for example only * This is insecure hash function, just for example only
* @param data * @param data
* @param seed * @param seed
* @param hashLength * @param hashLength
*/ */
function simpleHash(data, seed, hashLength = 40) { function simpleHash(data, seed, hashLength = 40) {
const str = data.join(''); const str = data.join('');
let i, l, hval = seed !== null && seed !== void 0 ? seed : 0x811c9dcc5; let i, l, hval = seed !== null && seed !== void 0 ? seed : 0x811c9dcc5;
for (i = 0, l = str.length; i < l; i++) { for (i = 0, l = str.length; i < l; i++) {
hval ^= str.charCodeAt(i); hval ^= str.charCodeAt(i);
hval += (hval << 1) + (hval << 4) + (hval << 6) + (hval << 8) + (hval << 24); hval += (hval << 1) + (hval << 4) + (hval << 6) + (hval << 8) + (hval << 24);
} }
const hash = (hval >>> 0).toString(16); const hash = (hval >>> 0).toString(16);
return BigInt('0x' + hash.padEnd(hashLength - (hash.length - 1), '0')).toString(10); return BigInt('0x' + hash.padEnd(hashLength - (hash.length - 1), '0')).toString(10);
} }
simpleHash$1.simpleHash = simpleHash; simpleHash$1.simpleHash = simpleHash;
simpleHash$1.default = (left, right) => simpleHash([left, right]); simpleHash$1.default = (left, right) => simpleHash([left, right]);
var BaseTree$1 = {}; var BaseTree$1 = {};
Object.defineProperty(BaseTree$1, "__esModule", { value: true }); Object.defineProperty(BaseTree$1, "__esModule", { value: true });
BaseTree$1.BaseTree = void 0; BaseTree$1.BaseTree = void 0;
class BaseTree { class BaseTree {
get capacity() { get capacity() {
return 2 ** this.levels; return 2 ** this.levels;
} }
get layers() { get layers() {
return this._layers.slice(); return this._layers.slice();
} }
get zeros() { get zeros() {
return this._zeros.slice(); return this._zeros.slice();
} }
get elements() { get elements() {
return this._layers[0].slice(); return this._layers[0].slice();
} }
get root() { get root() {
var _a; var _a;
return (_a = this._layers[this.levels][0]) !== null && _a !== void 0 ? _a : this._zeros[this.levels]; return (_a = this._layers[this.levels][0]) !== null && _a !== void 0 ? _a : this._zeros[this.levels];
} }
/** /**
* Find an element in the tree * Find an element in the tree
* @param elements elements of tree * @param elements elements of tree
* @param element An element to find * @param element An element to find
* @param comparator A function that checks leaf value equality * @param comparator A function that checks leaf value equality
* @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 * @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
* @returns {number} Index if element is found, otherwise -1 * @returns {number} Index if element is found, otherwise -1
*/ */
static indexOf(elements, element, fromIndex, comparator) { static indexOf(elements, element, fromIndex, comparator) {
if (comparator) { if (comparator) {
return elements.findIndex((el) => comparator(element, el)); return elements.findIndex((el) => comparator(element, el));
} }
else { else {
return elements.indexOf(element, fromIndex); return elements.indexOf(element, fromIndex);
} }
} }
/** /**
* Insert new element into the tree * Insert new element into the tree
* @param element Element to insert * @param element Element to insert
*/ */
insert(element) { insert(element) {
if (this._layers[0].length >= this.capacity) { if (this._layers[0].length >= this.capacity) {
throw new Error('Tree is full'); throw new Error('Tree is full');
} }
this.update(this._layers[0].length, element); this.update(this._layers[0].length, element);
} }
/* /*
* Insert multiple elements into the tree. * Insert multiple elements into the tree.
* @param {Array} elements Elements to insert * @param {Array} elements Elements to insert
*/ */
bulkInsert(elements) { bulkInsert(elements) {
if (!elements.length) { if (!elements.length) {
return; return;
} }
if (this._layers[0].length + elements.length > this.capacity) { if (this._layers[0].length + elements.length > this.capacity) {
throw new Error('Tree is full'); throw new Error('Tree is full');
} }
// First we insert all elements except the last one // First we insert all elements except the last one
// updating only full subtree hashes (all layers where inserted element has odd index) // updating only full subtree hashes (all layers where inserted element has odd index)
// the last element will update the full path to the root making the tree consistent again // the last element will update the full path to the root making the tree consistent again
for (let i = 0; i < elements.length - 1; i++) { for (let i = 0; i < elements.length - 1; i++) {
this._layers[0].push(elements[i]); this._layers[0].push(elements[i]);
let level = 0; let level = 0;
let index = this._layers[0].length - 1; let index = this._layers[0].length - 1;
while (index % 2 === 1) { while (index % 2 === 1) {
level++; level++;
index >>= 1; index >>= 1;
const left = this._layers[level - 1][index * 2]; const left = this._layers[level - 1][index * 2];
const right = this._layers[level - 1][index * 2 + 1]; const right = this._layers[level - 1][index * 2 + 1];
this._layers[level][index] = this._hashFn(left, right); this._layers[level][index] = this._hashFn(left, right);
} }
} }
this.insert(elements[elements.length - 1]); this.insert(elements[elements.length - 1]);
} }
/** /**
* Change an element in the tree * Change an element in the tree
* @param {number} index Index of element to change * @param {number} index Index of element to change
* @param element Updated element value * @param element Updated element value
*/ */
update(index, element) { update(index, element) {
if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) { if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) {
throw new Error('Insert index out of bounds: ' + index); throw new Error('Insert index out of bounds: ' + index);
} }
this._layers[0][index] = element; this._layers[0][index] = element;
this._processUpdate(index); this._processUpdate(index);
} }
/** /**
* Get merkle path to a leaf * Get merkle path to a leaf
* @param {number} index Leaf index to generate path for * @param {number} index Leaf index to generate path for
* @returns {{pathElements: Object[], pathIndex: number[]}} An object containing adjacent elements and left-right index * @returns {{pathElements: Object[], pathIndex: number[]}} An object containing adjacent elements and left-right index
*/ */
path(index) { path(index) {
if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) { if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) {
throw new Error('Index out of bounds: ' + index); throw new Error('Index out of bounds: ' + index);
} }
let elIndex = +index; let elIndex = +index;
const pathElements = []; const pathElements = [];
const pathIndices = []; const pathIndices = [];
const pathPositions = []; const pathPositions = [];
for (let level = 0; level < this.levels; level++) { for (let level = 0; level < this.levels; level++) {
pathIndices[level] = elIndex % 2; pathIndices[level] = elIndex % 2;
const leafIndex = elIndex ^ 1; const leafIndex = elIndex ^ 1;
if (leafIndex < this._layers[level].length) { if (leafIndex < this._layers[level].length) {
pathElements[level] = this._layers[level][leafIndex]; pathElements[level] = this._layers[level][leafIndex];
pathPositions[level] = leafIndex; pathPositions[level] = leafIndex;
} }
else { else {
pathElements[level] = this._zeros[level]; pathElements[level] = this._zeros[level];
pathPositions[level] = 0; pathPositions[level] = 0;
} }
elIndex >>= 1; elIndex >>= 1;
} }
return { return {
pathElements, pathElements,
pathIndices, pathIndices,
pathPositions, pathPositions,
pathRoot: this.root, pathRoot: this.root,
}; };
} }
_buildZeros() { _buildZeros() {
this._zeros = [this.zeroElement]; this._zeros = [this.zeroElement];
for (let i = 1; i <= this.levels; i++) { for (let i = 1; i <= this.levels; i++) {
this._zeros[i] = this._hashFn(this._zeros[i - 1], this._zeros[i - 1]); this._zeros[i] = this._hashFn(this._zeros[i - 1], this._zeros[i - 1]);
} }
} }
_processNodes(nodes, layerIndex) { _processNodes(nodes, layerIndex) {
const length = nodes.length; const length = nodes.length;
let currentLength = Math.ceil(length / 2); let currentLength = Math.ceil(length / 2);
const currentLayer = new Array(currentLength); const currentLayer = new Array(currentLength);
currentLength--; currentLength--;
const starFrom = length - ((length % 2) ^ 1); const starFrom = length - ((length % 2) ^ 1);
let j = 0; let j = 0;
for (let i = starFrom; i >= 0; i -= 2) { for (let i = starFrom; i >= 0; i -= 2) {
if (nodes[i - 1] === undefined) if (nodes[i - 1] === undefined)
break; break;
const left = nodes[i - 1]; const left = nodes[i - 1];
const right = (i === starFrom && length % 2 === 1) ? this._zeros[layerIndex - 1] : nodes[i]; const right = (i === starFrom && length % 2 === 1) ? this._zeros[layerIndex - 1] : nodes[i];
currentLayer[currentLength - j] = this._hashFn(left, right); currentLayer[currentLength - j] = this._hashFn(left, right);
j++; j++;
} }
return currentLayer; return currentLayer;
} }
_processUpdate(index) { _processUpdate(index) {
for (let level = 1; level <= this.levels; level++) { for (let level = 1; level <= this.levels; level++) {
index >>= 1; index >>= 1;
const left = this._layers[level - 1][index * 2]; const left = this._layers[level - 1][index * 2];
const right = index * 2 + 1 < this._layers[level - 1].length const right = index * 2 + 1 < this._layers[level - 1].length
? this._layers[level - 1][index * 2 + 1] ? this._layers[level - 1][index * 2 + 1]
: this._zeros[level - 1]; : this._zeros[level - 1];
this._layers[level][index] = this._hashFn(left, right); this._layers[level][index] = this._hashFn(left, right);
} }
} }
} }
BaseTree$1.BaseTree = BaseTree; BaseTree$1.BaseTree = BaseTree;
var __importDefault$1 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { var __importDefault$1 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(FixedMerkleTree, "__esModule", { value: true }); Object.defineProperty(FixedMerkleTree, "__esModule", { value: true });
const simpleHash_1$1 = __importDefault$1(simpleHash$1); const simpleHash_1$1 = __importDefault$1(simpleHash$1);
const BaseTree_1$1 = BaseTree$1; const BaseTree_1$1 = BaseTree$1;
class MerkleTree extends BaseTree_1$1.BaseTree { class MerkleTree extends BaseTree_1$1.BaseTree {
constructor(levels, elements = [], { hashFunction = simpleHash_1$1.default, zeroElement = 0, } = {}) { constructor(levels, elements = [], { hashFunction = simpleHash_1$1.default, zeroElement = 0, } = {}) {
super(); super();
this.levels = levels; this.levels = levels;
if (elements.length > this.capacity) { if (elements.length > this.capacity) {
throw new Error('Tree is full'); throw new Error('Tree is full');
} }
this._hashFn = hashFunction; this._hashFn = hashFunction;
this.zeroElement = zeroElement; this.zeroElement = zeroElement;
this._layers = []; this._layers = [];
const leaves = elements.slice(); const leaves = elements.slice();
this._layers = [leaves]; this._layers = [leaves];
this._buildZeros(); this._buildZeros();
this._buildHashes(); this._buildHashes();
} }
_buildHashes() { _buildHashes() {
for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) { for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) {
const nodes = this._layers[layerIndex - 1]; const nodes = this._layers[layerIndex - 1];
this._layers[layerIndex] = this._processNodes(nodes, layerIndex); this._layers[layerIndex] = this._processNodes(nodes, layerIndex);
} }
} }
/** /**
* Insert multiple elements into the tree. * Insert multiple elements into the tree.
* @param {Array} elements Elements to insert * @param {Array} elements Elements to insert
*/ */
bulkInsert(elements) { bulkInsert(elements) {
if (!elements.length) { if (!elements.length) {
return; return;
} }
if (this._layers[0].length + elements.length > this.capacity) { if (this._layers[0].length + elements.length > this.capacity) {
throw new Error('Tree is full'); throw new Error('Tree is full');
} }
// First we insert all elements except the last one // First we insert all elements except the last one
// updating only full subtree hashes (all layers where inserted element has odd index) // updating only full subtree hashes (all layers where inserted element has odd index)
// the last element will update the full path to the root making the tree consistent again // the last element will update the full path to the root making the tree consistent again
for (let i = 0; i < elements.length - 1; i++) { for (let i = 0; i < elements.length - 1; i++) {
this._layers[0].push(elements[i]); this._layers[0].push(elements[i]);
let level = 0; let level = 0;
let index = this._layers[0].length - 1; let index = this._layers[0].length - 1;
while (index % 2 === 1) { while (index % 2 === 1) {
level++; level++;
index >>= 1; index >>= 1;
this._layers[level][index] = this._hashFn(this._layers[level - 1][index * 2], this._layers[level - 1][index * 2 + 1]); this._layers[level][index] = this._hashFn(this._layers[level - 1][index * 2], this._layers[level - 1][index * 2 + 1]);
} }
} }
this.insert(elements[elements.length - 1]); this.insert(elements[elements.length - 1]);
} }
indexOf(element, comparator) { indexOf(element, comparator) {
return BaseTree_1$1.BaseTree.indexOf(this._layers[0], element, 0, comparator); return BaseTree_1$1.BaseTree.indexOf(this._layers[0], element, 0, comparator);
} }
proof(element) { proof(element) {
const index = this.indexOf(element); const index = this.indexOf(element);
return this.path(index); return this.path(index);
} }
getTreeEdge(edgeIndex) { getTreeEdge(edgeIndex) {
const edgeElement = this._layers[0][edgeIndex]; const edgeElement = this._layers[0][edgeIndex];
if (edgeElement === undefined) { if (edgeElement === undefined) {
throw new Error('Element not found'); throw new Error('Element not found');
} }
const edgePath = this.path(edgeIndex); const edgePath = this.path(edgeIndex);
return { edgePath, edgeElement, edgeIndex, edgeElementsCount: this._layers[0].length }; return { edgePath, edgeElement, edgeIndex, edgeElementsCount: this._layers[0].length };
} }
/** /**
* 🪓 * 🪓
* @param count * @param count
*/ */
getTreeSlices(count = 4) { getTreeSlices(count = 4) {
const length = this._layers[0].length; const length = this._layers[0].length;
let size = Math.ceil(length / count); let size = Math.ceil(length / count);
if (size % 2) if (size % 2)
size++; size++;
const slices = []; const slices = [];
for (let i = 0; i < length; i += size) { for (let i = 0; i < length; i += size) {
const edgeLeft = i; const edgeLeft = i;
const edgeRight = i + size; const edgeRight = i + size;
slices.push({ edge: this.getTreeEdge(edgeLeft), elements: this.elements.slice(edgeLeft, edgeRight) }); slices.push({ edge: this.getTreeEdge(edgeLeft), elements: this.elements.slice(edgeLeft, edgeRight) });
} }
return slices; return slices;
} }
/** /**
* Serialize entire tree state including intermediate layers into a plain object * Serialize entire tree state including intermediate layers into a plain object
* Deserializing it back will not require to recompute any hashes * Deserializing it back will not require to recompute any hashes
* Elements are not converted to a plain type, this is responsibility of the caller * Elements are not converted to a plain type, this is responsibility of the caller
*/ */
serialize() { serialize() {
return { return {
levels: this.levels, levels: this.levels,
_zeros: this._zeros, _zeros: this._zeros,
_layers: this._layers, _layers: this._layers,
}; };
} }
/** /**
* Deserialize data into a MerkleTree instance * Deserialize data into a MerkleTree instance
* Make sure to provide the same hashFunction as was used in the source tree, * Make sure to provide the same hashFunction as was used in the source tree,
* otherwise the tree state will be invalid * otherwise the tree state will be invalid
*/ */
static deserialize(data, hashFunction) { static deserialize(data, hashFunction) {
const instance = Object.assign(Object.create(this.prototype), data); const instance = Object.assign(Object.create(this.prototype), data);
instance._hashFn = hashFunction || simpleHash_1$1.default; instance._hashFn = hashFunction || simpleHash_1$1.default;
instance.zeroElement = instance._zeros[0]; instance.zeroElement = instance._zeros[0];
return instance; return instance;
} }
toString() { toString() {
return JSON.stringify(this.serialize()); return JSON.stringify(this.serialize());
} }
} }
FixedMerkleTree.default = MerkleTree; FixedMerkleTree.default = MerkleTree;
var PartialMerkleTree$1 = {}; var PartialMerkleTree$1 = {};
var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(PartialMerkleTree$1, "__esModule", { value: true }); Object.defineProperty(PartialMerkleTree$1, "__esModule", { value: true });
PartialMerkleTree$1.PartialMerkleTree = void 0; PartialMerkleTree$1.PartialMerkleTree = void 0;
const simpleHash_1 = __importDefault(simpleHash$1); const simpleHash_1 = __importDefault(simpleHash$1);
const BaseTree_1 = BaseTree$1; const BaseTree_1 = BaseTree$1;
class PartialMerkleTree extends BaseTree_1.BaseTree { class PartialMerkleTree extends BaseTree_1.BaseTree {
constructor(levels, { edgePath, edgeElement, edgeIndex, edgeElementsCount, }, leaves, { hashFunction, zeroElement } = {}) { constructor(levels, { edgePath, edgeElement, edgeIndex, edgeElementsCount, }, leaves, { hashFunction, zeroElement } = {}) {
super(); super();
if (edgeIndex + leaves.length !== edgeElementsCount) if (edgeIndex + leaves.length !== edgeElementsCount)
throw new Error('Invalid number of elements'); throw new Error('Invalid number of elements');
this._edgeLeafProof = edgePath; this._edgeLeafProof = edgePath;
this._initialRoot = edgePath.pathRoot; this._initialRoot = edgePath.pathRoot;
this.zeroElement = zeroElement !== null && zeroElement !== void 0 ? zeroElement : 0; this.zeroElement = zeroElement !== null && zeroElement !== void 0 ? zeroElement : 0;
this._edgeLeaf = { data: edgeElement, index: edgeIndex }; this._edgeLeaf = { data: edgeElement, index: edgeIndex };
this._leavesAfterEdge = leaves; this._leavesAfterEdge = leaves;
this.levels = levels; this.levels = levels;
this._hashFn = hashFunction || simpleHash_1.default; this._hashFn = hashFunction || simpleHash_1.default;
this._createProofMap(); this._createProofMap();
this._buildTree(); this._buildTree();
} }
get edgeIndex() { get edgeIndex() {
return this._edgeLeaf.index; return this._edgeLeaf.index;
} }
get edgeElement() { get edgeElement() {
return this._edgeLeaf.data; return this._edgeLeaf.data;
} }
get edgeLeafProof() { get edgeLeafProof() {
return this._edgeLeafProof; return this._edgeLeafProof;
} }
_createProofMap() { _createProofMap() {
this._proofMap = this.edgeLeafProof.pathPositions.reduce((p, c, i) => { this._proofMap = this.edgeLeafProof.pathPositions.reduce((p, c, i) => {
p.set(i, [c, this.edgeLeafProof.pathElements[i]]); p.set(i, [c, this.edgeLeafProof.pathElements[i]]);
return p; return p;
}, new Map()); }, new Map());
this._proofMap.set(this.levels, [0, this.edgeLeafProof.pathRoot]); this._proofMap.set(this.levels, [0, this.edgeLeafProof.pathRoot]);
} }
_buildTree() { _buildTree() {
const edgeLeafIndex = this._edgeLeaf.index; const edgeLeafIndex = this._edgeLeaf.index;
this._leaves = Array(edgeLeafIndex).concat(this._leavesAfterEdge); this._leaves = Array(edgeLeafIndex).concat(this._leavesAfterEdge);
if (this._proofMap.has(0)) { if (this._proofMap.has(0)) {
const [proofPos, proofEl] = this._proofMap.get(0); const [proofPos, proofEl] = this._proofMap.get(0);
this._leaves[proofPos] = proofEl; this._leaves[proofPos] = proofEl;
} }
this._layers = [this._leaves]; this._layers = [this._leaves];
this._buildZeros(); this._buildZeros();
this._buildHashes(); this._buildHashes();
} }
_buildHashes() { _buildHashes() {
for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) { for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) {
const nodes = this._layers[layerIndex - 1]; const nodes = this._layers[layerIndex - 1];
const currentLayer = this._processNodes(nodes, layerIndex); const currentLayer = this._processNodes(nodes, layerIndex);
if (this._proofMap.has(layerIndex)) { if (this._proofMap.has(layerIndex)) {
const [proofPos, proofEl] = this._proofMap.get(layerIndex); const [proofPos, proofEl] = this._proofMap.get(layerIndex);
if (!currentLayer[proofPos]) if (!currentLayer[proofPos])
currentLayer[proofPos] = proofEl; currentLayer[proofPos] = proofEl;
} }
this._layers[layerIndex] = currentLayer; this._layers[layerIndex] = currentLayer;
} }
} }
/** /**
* Change an element in the tree * Change an element in the tree
* @param {number} index Index of element to change * @param {number} index Index of element to change
* @param element Updated element value * @param element Updated element value
*/ */
update(index, element) { update(index, element) {
if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) { if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) {
throw new Error('Insert index out of bounds: ' + index); throw new Error('Insert index out of bounds: ' + index);
} }
if (index < this._edgeLeaf.index) { if (index < this._edgeLeaf.index) {
throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`); throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`);
} }
this._layers[0][index] = element; this._layers[0][index] = element;
this._processUpdate(index); this._processUpdate(index);
} }
path(index) { path(index) {
var _a; var _a;
if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) { if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) {
throw new Error('Index out of bounds: ' + index); throw new Error('Index out of bounds: ' + index);
} }
if (index < this._edgeLeaf.index) { if (index < this._edgeLeaf.index) {
throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`); throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`);
} }
let elIndex = Number(index); let elIndex = Number(index);
const pathElements = []; const pathElements = [];
const pathIndices = []; const pathIndices = [];
const pathPositions = []; const pathPositions = [];
for (let level = 0; level < this.levels; level++) { for (let level = 0; level < this.levels; level++) {
pathIndices[level] = elIndex % 2; pathIndices[level] = elIndex % 2;
const leafIndex = elIndex ^ 1; const leafIndex = elIndex ^ 1;
if (leafIndex < this._layers[level].length) { if (leafIndex < this._layers[level].length) {
pathElements[level] = this._layers[level][leafIndex]; pathElements[level] = this._layers[level][leafIndex];
pathPositions[level] = leafIndex; pathPositions[level] = leafIndex;
} }
else { else {
pathElements[level] = this._zeros[level]; pathElements[level] = this._zeros[level];
pathPositions[level] = 0; pathPositions[level] = 0;
} }
const [proofPos, proofEl] = this._proofMap.get(level); const [proofPos, proofEl] = this._proofMap.get(level);
pathElements[level] = (_a = pathElements[level]) !== null && _a !== void 0 ? _a : (proofPos === leafIndex ? proofEl : this._zeros[level]); pathElements[level] = (_a = pathElements[level]) !== null && _a !== void 0 ? _a : (proofPos === leafIndex ? proofEl : this._zeros[level]);
elIndex >>= 1; elIndex >>= 1;
} }
return { return {
pathElements, pathElements,
pathIndices, pathIndices,
pathPositions, pathPositions,
pathRoot: this.root, pathRoot: this.root,
}; };
} }
indexOf(element, comparator) { indexOf(element, comparator) {
return BaseTree_1.BaseTree.indexOf(this._layers[0], element, this.edgeIndex, comparator); return BaseTree_1.BaseTree.indexOf(this._layers[0], element, this.edgeIndex, comparator);
} }
proof(element) { proof(element) {
const index = this.indexOf(element); const index = this.indexOf(element);
return this.path(index); return this.path(index);
} }
/** /**
* Shifts edge of tree to left * Shifts edge of tree to left
* @param edge new TreeEdge below current edge * @param edge new TreeEdge below current edge
* @param elements leaves between old and new edge * @param elements leaves between old and new edge
*/ */
shiftEdge(edge, elements) { shiftEdge(edge, elements) {
if (this._edgeLeaf.index <= edge.edgeIndex) { if (this._edgeLeaf.index <= edge.edgeIndex) {
throw new Error(`New edgeIndex should be smaller then ${this._edgeLeaf.index}`); throw new Error(`New edgeIndex should be smaller then ${this._edgeLeaf.index}`);
} }
if (elements.length !== (this._edgeLeaf.index - edge.edgeIndex)) { if (elements.length !== (this._edgeLeaf.index - edge.edgeIndex)) {
throw new Error(`Elements length should be ${this._edgeLeaf.index - edge.edgeIndex}`); throw new Error(`Elements length should be ${this._edgeLeaf.index - edge.edgeIndex}`);
} }
this._edgeLeafProof = edge.edgePath; this._edgeLeafProof = edge.edgePath;
this._edgeLeaf = { index: edge.edgeIndex, data: edge.edgeElement }; this._edgeLeaf = { index: edge.edgeIndex, data: edge.edgeElement };
this._leavesAfterEdge = [...elements, ...this._leavesAfterEdge]; this._leavesAfterEdge = [...elements, ...this._leavesAfterEdge];
this._createProofMap(); this._createProofMap();
this._buildTree(); this._buildTree();
} }
serialize() { serialize() {
return { return {
_edgeLeafProof: this._edgeLeafProof, _edgeLeafProof: this._edgeLeafProof,
_edgeLeaf: this._edgeLeaf, _edgeLeaf: this._edgeLeaf,
_layers: this._layers, _layers: this._layers,
_zeros: this._zeros, _zeros: this._zeros,
levels: this.levels, levels: this.levels,
}; };
} }
static deserialize(data, hashFunction) { static deserialize(data, hashFunction) {
const instance = Object.assign(Object.create(this.prototype), data); const instance = Object.assign(Object.create(this.prototype), data);
instance._hashFn = hashFunction || simpleHash_1.default; instance._hashFn = hashFunction || simpleHash_1.default;
instance._initialRoot = data._edgeLeafProof.pathRoot; instance._initialRoot = data._edgeLeafProof.pathRoot;
instance.zeroElement = instance._zeros[0]; instance.zeroElement = instance._zeros[0];
instance._leavesAfterEdge = instance._layers[0].slice(data._edgeLeaf.index); instance._leavesAfterEdge = instance._layers[0].slice(data._edgeLeaf.index);
instance._createProofMap(); instance._createProofMap();
return instance; return instance;
} }
toString() { toString() {
return JSON.stringify(this.serialize()); return JSON.stringify(this.serialize());
} }
} }
PartialMerkleTree$1.PartialMerkleTree = PartialMerkleTree; PartialMerkleTree$1.PartialMerkleTree = PartialMerkleTree;
(function (exports) { (function (exports) {
var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.MerkleTree = exports.simpleHash = exports.PartialMerkleTree = void 0; exports.MerkleTree = exports.simpleHash = exports.PartialMerkleTree = void 0;
const FixedMerkleTree_1 = __importDefault(FixedMerkleTree); const FixedMerkleTree_1 = __importDefault(FixedMerkleTree);
Object.defineProperty(exports, "MerkleTree", { enumerable: true, get: function () { return FixedMerkleTree_1.default; } }); Object.defineProperty(exports, "MerkleTree", { enumerable: true, get: function () { return FixedMerkleTree_1.default; } });
var PartialMerkleTree_1 = PartialMerkleTree$1; var PartialMerkleTree_1 = PartialMerkleTree$1;
Object.defineProperty(exports, "PartialMerkleTree", { enumerable: true, get: function () { return PartialMerkleTree_1.PartialMerkleTree; } }); Object.defineProperty(exports, "PartialMerkleTree", { enumerable: true, get: function () { return PartialMerkleTree_1.PartialMerkleTree; } });
var simpleHash_1 = simpleHash$1; var simpleHash_1 = simpleHash$1;
Object.defineProperty(exports, "simpleHash", { enumerable: true, get: function () { return simpleHash_1.simpleHash; } }); Object.defineProperty(exports, "simpleHash", { enumerable: true, get: function () { return simpleHash_1.simpleHash; } });
exports.default = FixedMerkleTree_1.default; exports.default = FixedMerkleTree_1.default;
} (lib)); } (lib));

@ -15,160 +15,160 @@ return /******/ (() => { // webpackBootstrap
/***/ ((__unused_webpack_module, exports) => { /***/ ((__unused_webpack_module, exports) => {
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.BaseTree = void 0; exports.BaseTree = void 0;
class BaseTree { class BaseTree {
get capacity() { get capacity() {
return 2 ** this.levels; return 2 ** this.levels;
} }
get layers() { get layers() {
return this._layers.slice(); return this._layers.slice();
} }
get zeros() { get zeros() {
return this._zeros.slice(); return this._zeros.slice();
} }
get elements() { get elements() {
return this._layers[0].slice(); return this._layers[0].slice();
} }
get root() { get root() {
var _a; var _a;
return (_a = this._layers[this.levels][0]) !== null && _a !== void 0 ? _a : this._zeros[this.levels]; return (_a = this._layers[this.levels][0]) !== null && _a !== void 0 ? _a : this._zeros[this.levels];
} }
/** /**
* Find an element in the tree * Find an element in the tree
* @param elements elements of tree * @param elements elements of tree
* @param element An element to find * @param element An element to find
* @param comparator A function that checks leaf value equality * @param comparator A function that checks leaf value equality
* @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 * @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
* @returns {number} Index if element is found, otherwise -1 * @returns {number} Index if element is found, otherwise -1
*/ */
static indexOf(elements, element, fromIndex, comparator) { static indexOf(elements, element, fromIndex, comparator) {
if (comparator) { if (comparator) {
return elements.findIndex((el) => comparator(element, el)); return elements.findIndex((el) => comparator(element, el));
} }
else { else {
return elements.indexOf(element, fromIndex); return elements.indexOf(element, fromIndex);
} }
} }
/** /**
* Insert new element into the tree * Insert new element into the tree
* @param element Element to insert * @param element Element to insert
*/ */
insert(element) { insert(element) {
if (this._layers[0].length >= this.capacity) { if (this._layers[0].length >= this.capacity) {
throw new Error('Tree is full'); throw new Error('Tree is full');
} }
this.update(this._layers[0].length, element); this.update(this._layers[0].length, element);
} }
/* /*
* Insert multiple elements into the tree. * Insert multiple elements into the tree.
* @param {Array} elements Elements to insert * @param {Array} elements Elements to insert
*/ */
bulkInsert(elements) { bulkInsert(elements) {
if (!elements.length) { if (!elements.length) {
return; return;
} }
if (this._layers[0].length + elements.length > this.capacity) { if (this._layers[0].length + elements.length > this.capacity) {
throw new Error('Tree is full'); throw new Error('Tree is full');
} }
// First we insert all elements except the last one // First we insert all elements except the last one
// updating only full subtree hashes (all layers where inserted element has odd index) // updating only full subtree hashes (all layers where inserted element has odd index)
// the last element will update the full path to the root making the tree consistent again // the last element will update the full path to the root making the tree consistent again
for (let i = 0; i < elements.length - 1; i++) { for (let i = 0; i < elements.length - 1; i++) {
this._layers[0].push(elements[i]); this._layers[0].push(elements[i]);
let level = 0; let level = 0;
let index = this._layers[0].length - 1; let index = this._layers[0].length - 1;
while (index % 2 === 1) { while (index % 2 === 1) {
level++; level++;
index >>= 1; index >>= 1;
const left = this._layers[level - 1][index * 2]; const left = this._layers[level - 1][index * 2];
const right = this._layers[level - 1][index * 2 + 1]; const right = this._layers[level - 1][index * 2 + 1];
this._layers[level][index] = this._hashFn(left, right); this._layers[level][index] = this._hashFn(left, right);
} }
} }
this.insert(elements[elements.length - 1]); this.insert(elements[elements.length - 1]);
} }
/** /**
* Change an element in the tree * Change an element in the tree
* @param {number} index Index of element to change * @param {number} index Index of element to change
* @param element Updated element value * @param element Updated element value
*/ */
update(index, element) { update(index, element) {
if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) { if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) {
throw new Error('Insert index out of bounds: ' + index); throw new Error('Insert index out of bounds: ' + index);
} }
this._layers[0][index] = element; this._layers[0][index] = element;
this._processUpdate(index); this._processUpdate(index);
} }
/** /**
* Get merkle path to a leaf * Get merkle path to a leaf
* @param {number} index Leaf index to generate path for * @param {number} index Leaf index to generate path for
* @returns {{pathElements: Object[], pathIndex: number[]}} An object containing adjacent elements and left-right index * @returns {{pathElements: Object[], pathIndex: number[]}} An object containing adjacent elements and left-right index
*/ */
path(index) { path(index) {
if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) { if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) {
throw new Error('Index out of bounds: ' + index); throw new Error('Index out of bounds: ' + index);
} }
let elIndex = +index; let elIndex = +index;
const pathElements = []; const pathElements = [];
const pathIndices = []; const pathIndices = [];
const pathPositions = []; const pathPositions = [];
for (let level = 0; level < this.levels; level++) { for (let level = 0; level < this.levels; level++) {
pathIndices[level] = elIndex % 2; pathIndices[level] = elIndex % 2;
const leafIndex = elIndex ^ 1; const leafIndex = elIndex ^ 1;
if (leafIndex < this._layers[level].length) { if (leafIndex < this._layers[level].length) {
pathElements[level] = this._layers[level][leafIndex]; pathElements[level] = this._layers[level][leafIndex];
pathPositions[level] = leafIndex; pathPositions[level] = leafIndex;
} }
else { else {
pathElements[level] = this._zeros[level]; pathElements[level] = this._zeros[level];
pathPositions[level] = 0; pathPositions[level] = 0;
} }
elIndex >>= 1; elIndex >>= 1;
} }
return { return {
pathElements, pathElements,
pathIndices, pathIndices,
pathPositions, pathPositions,
pathRoot: this.root, pathRoot: this.root,
}; };
} }
_buildZeros() { _buildZeros() {
this._zeros = [this.zeroElement]; this._zeros = [this.zeroElement];
for (let i = 1; i <= this.levels; i++) { for (let i = 1; i <= this.levels; i++) {
this._zeros[i] = this._hashFn(this._zeros[i - 1], this._zeros[i - 1]); this._zeros[i] = this._hashFn(this._zeros[i - 1], this._zeros[i - 1]);
} }
} }
_processNodes(nodes, layerIndex) { _processNodes(nodes, layerIndex) {
const length = nodes.length; const length = nodes.length;
let currentLength = Math.ceil(length / 2); let currentLength = Math.ceil(length / 2);
const currentLayer = new Array(currentLength); const currentLayer = new Array(currentLength);
currentLength--; currentLength--;
const starFrom = length - ((length % 2) ^ 1); const starFrom = length - ((length % 2) ^ 1);
let j = 0; let j = 0;
for (let i = starFrom; i >= 0; i -= 2) { for (let i = starFrom; i >= 0; i -= 2) {
if (nodes[i - 1] === undefined) if (nodes[i - 1] === undefined)
break; break;
const left = nodes[i - 1]; const left = nodes[i - 1];
const right = (i === starFrom && length % 2 === 1) ? this._zeros[layerIndex - 1] : nodes[i]; const right = (i === starFrom && length % 2 === 1) ? this._zeros[layerIndex - 1] : nodes[i];
currentLayer[currentLength - j] = this._hashFn(left, right); currentLayer[currentLength - j] = this._hashFn(left, right);
j++; j++;
} }
return currentLayer; return currentLayer;
} }
_processUpdate(index) { _processUpdate(index) {
for (let level = 1; level <= this.levels; level++) { for (let level = 1; level <= this.levels; level++) {
index >>= 1; index >>= 1;
const left = this._layers[level - 1][index * 2]; const left = this._layers[level - 1][index * 2];
const right = index * 2 + 1 < this._layers[level - 1].length const right = index * 2 + 1 < this._layers[level - 1].length
? this._layers[level - 1][index * 2 + 1] ? this._layers[level - 1][index * 2 + 1]
: this._zeros[level - 1]; : this._zeros[level - 1];
this._layers[level][index] = this._hashFn(left, right); this._layers[level][index] = this._hashFn(left, right);
} }
} }
} }
exports.BaseTree = BaseTree; exports.BaseTree = BaseTree;
/***/ }), /***/ }),
@ -177,120 +177,120 @@ exports.BaseTree = BaseTree;
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict"; "use strict";
var __importDefault = (this && this.__importDefault) || function (mod) { var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
const simpleHash_1 = __importDefault(__webpack_require__(5319)); const simpleHash_1 = __importDefault(__webpack_require__(5319));
const BaseTree_1 = __webpack_require__(7736); const BaseTree_1 = __webpack_require__(7736);
class MerkleTree extends BaseTree_1.BaseTree { class MerkleTree extends BaseTree_1.BaseTree {
constructor(levels, elements = [], { hashFunction = simpleHash_1.default, zeroElement = 0, } = {}) { constructor(levels, elements = [], { hashFunction = simpleHash_1.default, zeroElement = 0, } = {}) {
super(); super();
this.levels = levels; this.levels = levels;
if (elements.length > this.capacity) { if (elements.length > this.capacity) {
throw new Error('Tree is full'); throw new Error('Tree is full');
} }
this._hashFn = hashFunction; this._hashFn = hashFunction;
this.zeroElement = zeroElement; this.zeroElement = zeroElement;
this._layers = []; this._layers = [];
const leaves = elements.slice(); const leaves = elements.slice();
this._layers = [leaves]; this._layers = [leaves];
this._buildZeros(); this._buildZeros();
this._buildHashes(); this._buildHashes();
} }
_buildHashes() { _buildHashes() {
for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) { for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) {
const nodes = this._layers[layerIndex - 1]; const nodes = this._layers[layerIndex - 1];
this._layers[layerIndex] = this._processNodes(nodes, layerIndex); this._layers[layerIndex] = this._processNodes(nodes, layerIndex);
} }
} }
/** /**
* Insert multiple elements into the tree. * Insert multiple elements into the tree.
* @param {Array} elements Elements to insert * @param {Array} elements Elements to insert
*/ */
bulkInsert(elements) { bulkInsert(elements) {
if (!elements.length) { if (!elements.length) {
return; return;
} }
if (this._layers[0].length + elements.length > this.capacity) { if (this._layers[0].length + elements.length > this.capacity) {
throw new Error('Tree is full'); throw new Error('Tree is full');
} }
// First we insert all elements except the last one // First we insert all elements except the last one
// updating only full subtree hashes (all layers where inserted element has odd index) // updating only full subtree hashes (all layers where inserted element has odd index)
// the last element will update the full path to the root making the tree consistent again // the last element will update the full path to the root making the tree consistent again
for (let i = 0; i < elements.length - 1; i++) { for (let i = 0; i < elements.length - 1; i++) {
this._layers[0].push(elements[i]); this._layers[0].push(elements[i]);
let level = 0; let level = 0;
let index = this._layers[0].length - 1; let index = this._layers[0].length - 1;
while (index % 2 === 1) { while (index % 2 === 1) {
level++; level++;
index >>= 1; index >>= 1;
this._layers[level][index] = this._hashFn(this._layers[level - 1][index * 2], this._layers[level - 1][index * 2 + 1]); this._layers[level][index] = this._hashFn(this._layers[level - 1][index * 2], this._layers[level - 1][index * 2 + 1]);
} }
} }
this.insert(elements[elements.length - 1]); this.insert(elements[elements.length - 1]);
} }
indexOf(element, comparator) { indexOf(element, comparator) {
return BaseTree_1.BaseTree.indexOf(this._layers[0], element, 0, comparator); return BaseTree_1.BaseTree.indexOf(this._layers[0], element, 0, comparator);
} }
proof(element) { proof(element) {
const index = this.indexOf(element); const index = this.indexOf(element);
return this.path(index); return this.path(index);
} }
getTreeEdge(edgeIndex) { getTreeEdge(edgeIndex) {
const edgeElement = this._layers[0][edgeIndex]; const edgeElement = this._layers[0][edgeIndex];
if (edgeElement === undefined) { if (edgeElement === undefined) {
throw new Error('Element not found'); throw new Error('Element not found');
} }
const edgePath = this.path(edgeIndex); const edgePath = this.path(edgeIndex);
return { edgePath, edgeElement, edgeIndex, edgeElementsCount: this._layers[0].length }; return { edgePath, edgeElement, edgeIndex, edgeElementsCount: this._layers[0].length };
} }
/** /**
* 🪓 * 🪓
* @param count * @param count
*/ */
getTreeSlices(count = 4) { getTreeSlices(count = 4) {
const length = this._layers[0].length; const length = this._layers[0].length;
let size = Math.ceil(length / count); let size = Math.ceil(length / count);
if (size % 2) if (size % 2)
size++; size++;
const slices = []; const slices = [];
for (let i = 0; i < length; i += size) { for (let i = 0; i < length; i += size) {
const edgeLeft = i; const edgeLeft = i;
const edgeRight = i + size; const edgeRight = i + size;
slices.push({ edge: this.getTreeEdge(edgeLeft), elements: this.elements.slice(edgeLeft, edgeRight) }); slices.push({ edge: this.getTreeEdge(edgeLeft), elements: this.elements.slice(edgeLeft, edgeRight) });
} }
return slices; return slices;
} }
/** /**
* Serialize entire tree state including intermediate layers into a plain object * Serialize entire tree state including intermediate layers into a plain object
* Deserializing it back will not require to recompute any hashes * Deserializing it back will not require to recompute any hashes
* Elements are not converted to a plain type, this is responsibility of the caller * Elements are not converted to a plain type, this is responsibility of the caller
*/ */
serialize() { serialize() {
return { return {
levels: this.levels, levels: this.levels,
_zeros: this._zeros, _zeros: this._zeros,
_layers: this._layers, _layers: this._layers,
}; };
} }
/** /**
* Deserialize data into a MerkleTree instance * Deserialize data into a MerkleTree instance
* Make sure to provide the same hashFunction as was used in the source tree, * Make sure to provide the same hashFunction as was used in the source tree,
* otherwise the tree state will be invalid * otherwise the tree state will be invalid
*/ */
static deserialize(data, hashFunction) { static deserialize(data, hashFunction) {
const instance = Object.assign(Object.create(this.prototype), data); const instance = Object.assign(Object.create(this.prototype), data);
instance._hashFn = hashFunction || simpleHash_1.default; instance._hashFn = hashFunction || simpleHash_1.default;
instance.zeroElement = instance._zeros[0]; instance.zeroElement = instance._zeros[0];
return instance; return instance;
} }
toString() { toString() {
return JSON.stringify(this.serialize()); return JSON.stringify(this.serialize());
} }
} }
exports["default"] = MerkleTree; exports["default"] = MerkleTree;
/***/ }), /***/ }),
@ -299,165 +299,165 @@ exports["default"] = MerkleTree;
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict"; "use strict";
var __importDefault = (this && this.__importDefault) || function (mod) { var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.PartialMerkleTree = void 0; exports.PartialMerkleTree = void 0;
const simpleHash_1 = __importDefault(__webpack_require__(5319)); const simpleHash_1 = __importDefault(__webpack_require__(5319));
const BaseTree_1 = __webpack_require__(7736); const BaseTree_1 = __webpack_require__(7736);
class PartialMerkleTree extends BaseTree_1.BaseTree { class PartialMerkleTree extends BaseTree_1.BaseTree {
constructor(levels, { edgePath, edgeElement, edgeIndex, edgeElementsCount, }, leaves, { hashFunction, zeroElement } = {}) { constructor(levels, { edgePath, edgeElement, edgeIndex, edgeElementsCount, }, leaves, { hashFunction, zeroElement } = {}) {
super(); super();
if (edgeIndex + leaves.length !== edgeElementsCount) if (edgeIndex + leaves.length !== edgeElementsCount)
throw new Error('Invalid number of elements'); throw new Error('Invalid number of elements');
this._edgeLeafProof = edgePath; this._edgeLeafProof = edgePath;
this._initialRoot = edgePath.pathRoot; this._initialRoot = edgePath.pathRoot;
this.zeroElement = zeroElement !== null && zeroElement !== void 0 ? zeroElement : 0; this.zeroElement = zeroElement !== null && zeroElement !== void 0 ? zeroElement : 0;
this._edgeLeaf = { data: edgeElement, index: edgeIndex }; this._edgeLeaf = { data: edgeElement, index: edgeIndex };
this._leavesAfterEdge = leaves; this._leavesAfterEdge = leaves;
this.levels = levels; this.levels = levels;
this._hashFn = hashFunction || simpleHash_1.default; this._hashFn = hashFunction || simpleHash_1.default;
this._createProofMap(); this._createProofMap();
this._buildTree(); this._buildTree();
} }
get edgeIndex() { get edgeIndex() {
return this._edgeLeaf.index; return this._edgeLeaf.index;
} }
get edgeElement() { get edgeElement() {
return this._edgeLeaf.data; return this._edgeLeaf.data;
} }
get edgeLeafProof() { get edgeLeafProof() {
return this._edgeLeafProof; return this._edgeLeafProof;
} }
_createProofMap() { _createProofMap() {
this._proofMap = this.edgeLeafProof.pathPositions.reduce((p, c, i) => { this._proofMap = this.edgeLeafProof.pathPositions.reduce((p, c, i) => {
p.set(i, [c, this.edgeLeafProof.pathElements[i]]); p.set(i, [c, this.edgeLeafProof.pathElements[i]]);
return p; return p;
}, new Map()); }, new Map());
this._proofMap.set(this.levels, [0, this.edgeLeafProof.pathRoot]); this._proofMap.set(this.levels, [0, this.edgeLeafProof.pathRoot]);
} }
_buildTree() { _buildTree() {
const edgeLeafIndex = this._edgeLeaf.index; const edgeLeafIndex = this._edgeLeaf.index;
this._leaves = Array(edgeLeafIndex).concat(this._leavesAfterEdge); this._leaves = Array(edgeLeafIndex).concat(this._leavesAfterEdge);
if (this._proofMap.has(0)) { if (this._proofMap.has(0)) {
const [proofPos, proofEl] = this._proofMap.get(0); const [proofPos, proofEl] = this._proofMap.get(0);
this._leaves[proofPos] = proofEl; this._leaves[proofPos] = proofEl;
} }
this._layers = [this._leaves]; this._layers = [this._leaves];
this._buildZeros(); this._buildZeros();
this._buildHashes(); this._buildHashes();
} }
_buildHashes() { _buildHashes() {
for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) { for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) {
const nodes = this._layers[layerIndex - 1]; const nodes = this._layers[layerIndex - 1];
const currentLayer = this._processNodes(nodes, layerIndex); const currentLayer = this._processNodes(nodes, layerIndex);
if (this._proofMap.has(layerIndex)) { if (this._proofMap.has(layerIndex)) {
const [proofPos, proofEl] = this._proofMap.get(layerIndex); const [proofPos, proofEl] = this._proofMap.get(layerIndex);
if (!currentLayer[proofPos]) if (!currentLayer[proofPos])
currentLayer[proofPos] = proofEl; currentLayer[proofPos] = proofEl;
} }
this._layers[layerIndex] = currentLayer; this._layers[layerIndex] = currentLayer;
} }
} }
/** /**
* Change an element in the tree * Change an element in the tree
* @param {number} index Index of element to change * @param {number} index Index of element to change
* @param element Updated element value * @param element Updated element value
*/ */
update(index, element) { update(index, element) {
if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) { if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) {
throw new Error('Insert index out of bounds: ' + index); throw new Error('Insert index out of bounds: ' + index);
} }
if (index < this._edgeLeaf.index) { if (index < this._edgeLeaf.index) {
throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`); throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`);
} }
this._layers[0][index] = element; this._layers[0][index] = element;
this._processUpdate(index); this._processUpdate(index);
} }
path(index) { path(index) {
var _a; var _a;
if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) { if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) {
throw new Error('Index out of bounds: ' + index); throw new Error('Index out of bounds: ' + index);
} }
if (index < this._edgeLeaf.index) { if (index < this._edgeLeaf.index) {
throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`); throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`);
} }
let elIndex = Number(index); let elIndex = Number(index);
const pathElements = []; const pathElements = [];
const pathIndices = []; const pathIndices = [];
const pathPositions = []; const pathPositions = [];
for (let level = 0; level < this.levels; level++) { for (let level = 0; level < this.levels; level++) {
pathIndices[level] = elIndex % 2; pathIndices[level] = elIndex % 2;
const leafIndex = elIndex ^ 1; const leafIndex = elIndex ^ 1;
if (leafIndex < this._layers[level].length) { if (leafIndex < this._layers[level].length) {
pathElements[level] = this._layers[level][leafIndex]; pathElements[level] = this._layers[level][leafIndex];
pathPositions[level] = leafIndex; pathPositions[level] = leafIndex;
} }
else { else {
pathElements[level] = this._zeros[level]; pathElements[level] = this._zeros[level];
pathPositions[level] = 0; pathPositions[level] = 0;
} }
const [proofPos, proofEl] = this._proofMap.get(level); const [proofPos, proofEl] = this._proofMap.get(level);
pathElements[level] = (_a = pathElements[level]) !== null && _a !== void 0 ? _a : (proofPos === leafIndex ? proofEl : this._zeros[level]); pathElements[level] = (_a = pathElements[level]) !== null && _a !== void 0 ? _a : (proofPos === leafIndex ? proofEl : this._zeros[level]);
elIndex >>= 1; elIndex >>= 1;
} }
return { return {
pathElements, pathElements,
pathIndices, pathIndices,
pathPositions, pathPositions,
pathRoot: this.root, pathRoot: this.root,
}; };
} }
indexOf(element, comparator) { indexOf(element, comparator) {
return BaseTree_1.BaseTree.indexOf(this._layers[0], element, this.edgeIndex, comparator); return BaseTree_1.BaseTree.indexOf(this._layers[0], element, this.edgeIndex, comparator);
} }
proof(element) { proof(element) {
const index = this.indexOf(element); const index = this.indexOf(element);
return this.path(index); return this.path(index);
} }
/** /**
* Shifts edge of tree to left * Shifts edge of tree to left
* @param edge new TreeEdge below current edge * @param edge new TreeEdge below current edge
* @param elements leaves between old and new edge * @param elements leaves between old and new edge
*/ */
shiftEdge(edge, elements) { shiftEdge(edge, elements) {
if (this._edgeLeaf.index <= edge.edgeIndex) { if (this._edgeLeaf.index <= edge.edgeIndex) {
throw new Error(`New edgeIndex should be smaller then ${this._edgeLeaf.index}`); throw new Error(`New edgeIndex should be smaller then ${this._edgeLeaf.index}`);
} }
if (elements.length !== (this._edgeLeaf.index - edge.edgeIndex)) { if (elements.length !== (this._edgeLeaf.index - edge.edgeIndex)) {
throw new Error(`Elements length should be ${this._edgeLeaf.index - edge.edgeIndex}`); throw new Error(`Elements length should be ${this._edgeLeaf.index - edge.edgeIndex}`);
} }
this._edgeLeafProof = edge.edgePath; this._edgeLeafProof = edge.edgePath;
this._edgeLeaf = { index: edge.edgeIndex, data: edge.edgeElement }; this._edgeLeaf = { index: edge.edgeIndex, data: edge.edgeElement };
this._leavesAfterEdge = [...elements, ...this._leavesAfterEdge]; this._leavesAfterEdge = [...elements, ...this._leavesAfterEdge];
this._createProofMap(); this._createProofMap();
this._buildTree(); this._buildTree();
} }
serialize() { serialize() {
return { return {
_edgeLeafProof: this._edgeLeafProof, _edgeLeafProof: this._edgeLeafProof,
_edgeLeaf: this._edgeLeaf, _edgeLeaf: this._edgeLeaf,
_layers: this._layers, _layers: this._layers,
_zeros: this._zeros, _zeros: this._zeros,
levels: this.levels, levels: this.levels,
}; };
} }
static deserialize(data, hashFunction) { static deserialize(data, hashFunction) {
const instance = Object.assign(Object.create(this.prototype), data); const instance = Object.assign(Object.create(this.prototype), data);
instance._hashFn = hashFunction || simpleHash_1.default; instance._hashFn = hashFunction || simpleHash_1.default;
instance._initialRoot = data._edgeLeafProof.pathRoot; instance._initialRoot = data._edgeLeafProof.pathRoot;
instance.zeroElement = instance._zeros[0]; instance.zeroElement = instance._zeros[0];
instance._leavesAfterEdge = instance._layers[0].slice(data._edgeLeaf.index); instance._leavesAfterEdge = instance._layers[0].slice(data._edgeLeaf.index);
instance._createProofMap(); instance._createProofMap();
return instance; return instance;
} }
toString() { toString() {
return JSON.stringify(this.serialize()); return JSON.stringify(this.serialize());
} }
} }
exports.PartialMerkleTree = PartialMerkleTree; exports.PartialMerkleTree = PartialMerkleTree;
/***/ }), /***/ }),
@ -466,19 +466,19 @@ exports.PartialMerkleTree = PartialMerkleTree;
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict"; "use strict";
var __importDefault = (this && this.__importDefault) || function (mod) { var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.MerkleTree = exports.simpleHash = exports.PartialMerkleTree = void 0; exports.MerkleTree = exports.simpleHash = exports.PartialMerkleTree = void 0;
const FixedMerkleTree_1 = __importDefault(__webpack_require__(9093)); const FixedMerkleTree_1 = __importDefault(__webpack_require__(9093));
Object.defineProperty(exports, "MerkleTree", ({ enumerable: true, get: function () { return FixedMerkleTree_1.default; } })); Object.defineProperty(exports, "MerkleTree", ({ enumerable: true, get: function () { return FixedMerkleTree_1.default; } }));
var PartialMerkleTree_1 = __webpack_require__(1230); var PartialMerkleTree_1 = __webpack_require__(1230);
Object.defineProperty(exports, "PartialMerkleTree", ({ enumerable: true, get: function () { return PartialMerkleTree_1.PartialMerkleTree; } })); Object.defineProperty(exports, "PartialMerkleTree", ({ enumerable: true, get: function () { return PartialMerkleTree_1.PartialMerkleTree; } }));
var simpleHash_1 = __webpack_require__(5319); var simpleHash_1 = __webpack_require__(5319);
Object.defineProperty(exports, "simpleHash", ({ enumerable: true, get: function () { return simpleHash_1.simpleHash; } })); Object.defineProperty(exports, "simpleHash", ({ enumerable: true, get: function () { return simpleHash_1.simpleHash; } }));
exports["default"] = FixedMerkleTree_1.default; exports["default"] = FixedMerkleTree_1.default;
/***/ }), /***/ }),
@ -487,27 +487,27 @@ exports["default"] = FixedMerkleTree_1.default;
/***/ ((__unused_webpack_module, exports) => { /***/ ((__unused_webpack_module, exports) => {
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.simpleHash = void 0; exports.simpleHash = void 0;
/*** /***
* This is insecure hash function, just for example only * This is insecure hash function, just for example only
* @param data * @param data
* @param seed * @param seed
* @param hashLength * @param hashLength
*/ */
function simpleHash(data, seed, hashLength = 40) { function simpleHash(data, seed, hashLength = 40) {
const str = data.join(''); const str = data.join('');
let i, l, hval = seed !== null && seed !== void 0 ? seed : 0x811c9dcc5; let i, l, hval = seed !== null && seed !== void 0 ? seed : 0x811c9dcc5;
for (i = 0, l = str.length; i < l; i++) { for (i = 0, l = str.length; i < l; i++) {
hval ^= str.charCodeAt(i); hval ^= str.charCodeAt(i);
hval += (hval << 1) + (hval << 4) + (hval << 6) + (hval << 8) + (hval << 24); hval += (hval << 1) + (hval << 4) + (hval << 6) + (hval << 8) + (hval << 24);
} }
const hash = (hval >>> 0).toString(16); const hash = (hval >>> 0).toString(16);
return BigInt('0x' + hash.padEnd(hashLength - (hash.length - 1), '0')).toString(10); return BigInt('0x' + hash.padEnd(hashLength - (hash.length - 1), '0')).toString(10);
} }
exports.simpleHash = simpleHash; exports.simpleHash = simpleHash;
exports["default"] = (left, right) => simpleHash([left, right]); exports["default"] = (left, right) => simpleHash([left, right]);
/***/ }), /***/ }),

@ -1,6 +1,6 @@
{ {
"name": "@tornado/core", "name": "@tornado/core",
"version": "1.0.6", "version": "1.0.7",
"description": "An SDK for building applications on top of Privacy Pools", "description": "An SDK for building applications on top of Privacy Pools",
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.mjs", "module": "./dist/index.mjs",
@ -32,10 +32,10 @@
], ],
"dependencies": { "dependencies": {
"@metamask/eth-sig-util": "^7.0.3", "@metamask/eth-sig-util": "^7.0.3",
"@tornado/contracts": "git+https://codeberg.org/tornadocash/tornado-contracts.git#6741664a898c1654e742459a2c20e52e4bc104fa", "@tornado/contracts": "^1.0.0",
"@tornado/fixed-merkle-tree": "git+https://codeberg.org/tornadocash/fixed-merkle-tree.git#5c3fca4cb11255760ad5f4fd95d7c6eb45c1fc99", "@tornado/fixed-merkle-tree": "^0.7.3",
"@tornado/snarkjs": "git+https://codeberg.org/tornadocash/snarkjs.git#d3915a760c437cde7bd317f9ea2c627954900656", "@tornado/snarkjs": "^0.1.20",
"@tornado/websnark": "git+https://codeberg.org/tornadocash/websnark.git#b0c9fce5359ceba55167a2ad01a29d1e137843ec", "@tornado/websnark": "^0.0.4",
"ajv": "^8.17.1", "ajv": "^8.17.1",
"bn.js": "^5.2.1", "bn.js": "^5.2.1",
"circomlibjs": "0.1.7", "circomlibjs": "0.1.7",

@ -889,21 +889,24 @@
"@noble/hashes" "~1.4.0" "@noble/hashes" "~1.4.0"
"@scure/base" "~1.1.6" "@scure/base" "~1.1.6"
"@tornado/contracts@git+https://codeberg.org/tornadocash/tornado-contracts.git#6741664a898c1654e742459a2c20e52e4bc104fa": "@tornado/contracts@^1.0.0":
version "1.0.0" version "1.0.0"
resolved "git+https://codeberg.org/tornadocash/tornado-contracts.git#6741664a898c1654e742459a2c20e52e4bc104fa" resolved "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Fcontracts/-/1.0.0/contracts-1.0.0.tgz#4ee8aada3d12bca94b641fbb3d6f552ec3838cbe"
integrity sha512-kdYoEV+9Wm6sTpY4x4I1AB1cNYZ5yS/DehDxzv0cq06a6/80vncnpG22gM9CxkKqqsQb40O8yDSPxIDEFFwi3w==
dependencies: dependencies:
"@openzeppelin/contracts" "5.0.2" "@openzeppelin/contracts" "5.0.2"
"@openzeppelin/contracts-v3" "npm:@openzeppelin/contracts@3.2.0-rc.0" "@openzeppelin/contracts-v3" "npm:@openzeppelin/contracts@3.2.0-rc.0"
ethers "^6.4.0" ethers "^6.4.0"
"@tornado/fixed-merkle-tree@git+https://codeberg.org/tornadocash/fixed-merkle-tree.git#5c3fca4cb11255760ad5f4fd95d7c6eb45c1fc99": "@tornado/fixed-merkle-tree@^0.7.3":
version "0.7.3" version "0.7.3"
resolved "git+https://codeberg.org/tornadocash/fixed-merkle-tree.git#5c3fca4cb11255760ad5f4fd95d7c6eb45c1fc99" resolved "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Ffixed-merkle-tree/-/0.7.3/fixed-merkle-tree-0.7.3.tgz#6636ce9d334553c5f17e5a564fd22f2e9ec04472"
integrity sha512-8UWvIzz0/rMGBkzXACwmCv/5I1VJmnshAKc4C+nkTfOdmnX8Pf1bBa0GlxUIZ25ZFGiU/h2IKEHYckmHovwzEA==
"@tornado/snarkjs@git+https://codeberg.org/tornadocash/snarkjs.git#d3915a760c437cde7bd317f9ea2c627954900656": "@tornado/snarkjs@^0.1.20":
version "0.1.20" version "0.1.20"
resolved "git+https://codeberg.org/tornadocash/snarkjs.git#d3915a760c437cde7bd317f9ea2c627954900656" resolved "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Fsnarkjs/-/0.1.20/snarkjs-0.1.20.tgz#d7610cd3c8dc10598da7dc3e40e5d7470c3aa8c7"
integrity sha512-mn+ePoQjqOHyDyK8AMy8SXYqNSxJWVswWVmMYvuc75/9bBtJ7SNtwrTByxmfWjrf4S3BM3IrGfHqBHEXY6gR4Q==
dependencies: dependencies:
big-integer "^1.6.43" big-integer "^1.6.43"
chai "^4.2.0" chai "^4.2.0"
@ -912,11 +915,12 @@
keccak "^2.0.0" keccak "^2.0.0"
yargs "^12.0.5" yargs "^12.0.5"
"@tornado/websnark@git+https://codeberg.org/tornadocash/websnark.git#b0c9fce5359ceba55167a2ad01a29d1e137843ec": "@tornado/websnark@^0.0.4":
version "0.0.4" version "0.0.4"
resolved "git+https://codeberg.org/tornadocash/websnark.git#b0c9fce5359ceba55167a2ad01a29d1e137843ec" resolved "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Fwebsnark/-/0.0.4/websnark-0.0.4.tgz#4c603259b71172225a70e3d454344fa172710970"
integrity sha512-dHbaS41ILPq5NyVBDW8AmUPoSKvamtkTeIhyuKKmoyOrZMAUhJ9y1B2zRcejUKfhCZkIjAgCt9bvdzdOGGswwQ==
dependencies: dependencies:
"@tornado/snarkjs" "git+https://codeberg.org/tornadocash/snarkjs.git#d3915a760c437cde7bd317f9ea2c627954900656" "@tornado/snarkjs" "^0.1.20"
big-integer "1.6.42" big-integer "1.6.42"
"@typechain/ethers-v6@^0.5.1": "@typechain/ethers-v6@^0.5.1":