diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..05ba80e --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +@tornado:registry=https://git.tornado.ws/api/packages/tornado-packages/npm/ \ No newline at end of file diff --git a/dist/tornado.umd.js b/dist/tornado.umd.js index 42c9400..b69edc8 100644 --- a/dist/tornado.umd.js +++ b/dist/tornado.umd.js @@ -9508,160 +9508,160 @@ exports.bytes = exports.stringToBytes; /***/ ((__unused_webpack_module, exports) => { "use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.BaseTree = void 0; -class BaseTree { - get capacity() { - return 2 ** this.levels; - } - get layers() { - return this._layers.slice(); - } - get zeros() { - return this._zeros.slice(); - } - get elements() { - return this._layers[0].slice(); - } - get root() { - var _a; - return (_a = this._layers[this.levels][0]) !== null && _a !== void 0 ? _a : this._zeros[this.levels]; - } - /** - * Find an element in the tree - * @param elements elements of tree - * @param element An element to find - * @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 - * @returns {number} Index if element is found, otherwise -1 - */ - static indexOf(elements, element, fromIndex, comparator) { - if (comparator) { - return elements.findIndex((el) => comparator(element, el)); - } - else { - return elements.indexOf(element, fromIndex); - } - } - /** - * Insert new element into the tree - * @param element Element to insert - */ - insert(element) { - if (this._layers[0].length >= this.capacity) { - throw new Error('Tree is full'); - } - this.update(this._layers[0].length, element); - } - /* - * Insert multiple elements into the tree. - * @param {Array} elements Elements to insert - */ - bulkInsert(elements) { - if (!elements.length) { - return; - } - if (this._layers[0].length + elements.length > this.capacity) { - throw new Error('Tree is full'); - } - // First we insert all elements except the last one - // 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 - for (let i = 0; i < elements.length - 1; i++) { - this._layers[0].push(elements[i]); - let level = 0; - let index = this._layers[0].length - 1; - while (index % 2 === 1) { - level++; - index >>= 1; - const left = this._layers[level - 1][index * 2]; - const right = this._layers[level - 1][index * 2 + 1]; - this._layers[level][index] = this._hashFn(left, right); - } - } - this.insert(elements[elements.length - 1]); - } - /** - * Change an element in the tree - * @param {number} index Index of element to change - * @param element Updated element value - */ - update(index, element) { - if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) { - throw new Error('Insert index out of bounds: ' + index); - } - this._layers[0][index] = element; - this._processUpdate(index); - } - /** - * Get merkle path to a leaf - * @param {number} index Leaf index to generate path for - * @returns {{pathElements: Object[], pathIndex: number[]}} An object containing adjacent elements and left-right index - */ - path(index) { - if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) { - throw new Error('Index out of bounds: ' + index); - } - let elIndex = +index; - const pathElements = []; - const pathIndices = []; - const pathPositions = []; - for (let level = 0; level < this.levels; level++) { - pathIndices[level] = elIndex % 2; - const leafIndex = elIndex ^ 1; - if (leafIndex < this._layers[level].length) { - pathElements[level] = this._layers[level][leafIndex]; - pathPositions[level] = leafIndex; - } - else { - pathElements[level] = this._zeros[level]; - pathPositions[level] = 0; - } - elIndex >>= 1; - } - return { - pathElements, - pathIndices, - pathPositions, - pathRoot: this.root, - }; - } - _buildZeros() { - this._zeros = [this.zeroElement]; - for (let i = 1; i <= this.levels; i++) { - this._zeros[i] = this._hashFn(this._zeros[i - 1], this._zeros[i - 1]); - } - } - _processNodes(nodes, layerIndex) { - const length = nodes.length; - let currentLength = Math.ceil(length / 2); - const currentLayer = new Array(currentLength); - currentLength--; - const starFrom = length - ((length % 2) ^ 1); - let j = 0; - for (let i = starFrom; i >= 0; i -= 2) { - if (nodes[i - 1] === undefined) - break; - const left = nodes[i - 1]; - const right = (i === starFrom && length % 2 === 1) ? this._zeros[layerIndex - 1] : nodes[i]; - currentLayer[currentLength - j] = this._hashFn(left, right); - j++; - } - return currentLayer; - } - _processUpdate(index) { - for (let level = 1; level <= this.levels; level++) { - index >>= 1; - const left = this._layers[level - 1][index * 2]; - const right = index * 2 + 1 < this._layers[level - 1].length - ? this._layers[level - 1][index * 2 + 1] - : this._zeros[level - 1]; - this._layers[level][index] = this._hashFn(left, right); - } - } -} -exports.BaseTree = BaseTree; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.BaseTree = void 0; +class BaseTree { + get capacity() { + return 2 ** this.levels; + } + get layers() { + return this._layers.slice(); + } + get zeros() { + return this._zeros.slice(); + } + get elements() { + return this._layers[0].slice(); + } + get root() { + var _a; + return (_a = this._layers[this.levels][0]) !== null && _a !== void 0 ? _a : this._zeros[this.levels]; + } + /** + * Find an element in the tree + * @param elements elements of tree + * @param element An element to find + * @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 + * @returns {number} Index if element is found, otherwise -1 + */ + static indexOf(elements, element, fromIndex, comparator) { + if (comparator) { + return elements.findIndex((el) => comparator(element, el)); + } + else { + return elements.indexOf(element, fromIndex); + } + } + /** + * Insert new element into the tree + * @param element Element to insert + */ + insert(element) { + if (this._layers[0].length >= this.capacity) { + throw new Error('Tree is full'); + } + this.update(this._layers[0].length, element); + } + /* + * Insert multiple elements into the tree. + * @param {Array} elements Elements to insert + */ + bulkInsert(elements) { + if (!elements.length) { + return; + } + if (this._layers[0].length + elements.length > this.capacity) { + throw new Error('Tree is full'); + } + // First we insert all elements except the last one + // 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 + for (let i = 0; i < elements.length - 1; i++) { + this._layers[0].push(elements[i]); + let level = 0; + let index = this._layers[0].length - 1; + while (index % 2 === 1) { + level++; + index >>= 1; + const left = this._layers[level - 1][index * 2]; + const right = this._layers[level - 1][index * 2 + 1]; + this._layers[level][index] = this._hashFn(left, right); + } + } + this.insert(elements[elements.length - 1]); + } + /** + * Change an element in the tree + * @param {number} index Index of element to change + * @param element Updated element value + */ + update(index, element) { + if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) { + throw new Error('Insert index out of bounds: ' + index); + } + this._layers[0][index] = element; + this._processUpdate(index); + } + /** + * Get merkle path to a leaf + * @param {number} index Leaf index to generate path for + * @returns {{pathElements: Object[], pathIndex: number[]}} An object containing adjacent elements and left-right index + */ + path(index) { + if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) { + throw new Error('Index out of bounds: ' + index); + } + let elIndex = +index; + const pathElements = []; + const pathIndices = []; + const pathPositions = []; + for (let level = 0; level < this.levels; level++) { + pathIndices[level] = elIndex % 2; + const leafIndex = elIndex ^ 1; + if (leafIndex < this._layers[level].length) { + pathElements[level] = this._layers[level][leafIndex]; + pathPositions[level] = leafIndex; + } + else { + pathElements[level] = this._zeros[level]; + pathPositions[level] = 0; + } + elIndex >>= 1; + } + return { + pathElements, + pathIndices, + pathPositions, + pathRoot: this.root, + }; + } + _buildZeros() { + this._zeros = [this.zeroElement]; + for (let i = 1; i <= this.levels; i++) { + this._zeros[i] = this._hashFn(this._zeros[i - 1], this._zeros[i - 1]); + } + } + _processNodes(nodes, layerIndex) { + const length = nodes.length; + let currentLength = Math.ceil(length / 2); + const currentLayer = new Array(currentLength); + currentLength--; + const starFrom = length - ((length % 2) ^ 1); + let j = 0; + for (let i = starFrom; i >= 0; i -= 2) { + if (nodes[i - 1] === undefined) + break; + const left = nodes[i - 1]; + const right = (i === starFrom && length % 2 === 1) ? this._zeros[layerIndex - 1] : nodes[i]; + currentLayer[currentLength - j] = this._hashFn(left, right); + j++; + } + return currentLayer; + } + _processUpdate(index) { + for (let level = 1; level <= this.levels; level++) { + index >>= 1; + const left = this._layers[level - 1][index * 2]; + const right = index * 2 + 1 < this._layers[level - 1].length + ? this._layers[level - 1][index * 2 + 1] + : this._zeros[level - 1]; + this._layers[level][index] = this._hashFn(left, right); + } + } +} +exports.BaseTree = BaseTree; /***/ }), @@ -9670,120 +9670,120 @@ exports.BaseTree = BaseTree; /***/ (function(__unused_webpack_module, exports, __webpack_require__) { "use strict"; - -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -const simpleHash_1 = __importDefault(__webpack_require__(5319)); -const BaseTree_1 = __webpack_require__(7736); -class MerkleTree extends BaseTree_1.BaseTree { - constructor(levels, elements = [], { hashFunction = simpleHash_1.default, zeroElement = 0, } = {}) { - super(); - this.levels = levels; - if (elements.length > this.capacity) { - throw new Error('Tree is full'); - } - this._hashFn = hashFunction; - this.zeroElement = zeroElement; - this._layers = []; - const leaves = elements.slice(); - this._layers = [leaves]; - this._buildZeros(); - this._buildHashes(); - } - _buildHashes() { - for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) { - const nodes = this._layers[layerIndex - 1]; - this._layers[layerIndex] = this._processNodes(nodes, layerIndex); - } - } - /** - * Insert multiple elements into the tree. - * @param {Array} elements Elements to insert - */ - bulkInsert(elements) { - if (!elements.length) { - return; - } - if (this._layers[0].length + elements.length > this.capacity) { - throw new Error('Tree is full'); - } - // First we insert all elements except the last one - // 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 - for (let i = 0; i < elements.length - 1; i++) { - this._layers[0].push(elements[i]); - let level = 0; - let index = this._layers[0].length - 1; - while (index % 2 === 1) { - level++; - index >>= 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]); - } - indexOf(element, comparator) { - return BaseTree_1.BaseTree.indexOf(this._layers[0], element, 0, comparator); - } - proof(element) { - const index = this.indexOf(element); - return this.path(index); - } - getTreeEdge(edgeIndex) { - const edgeElement = this._layers[0][edgeIndex]; - if (edgeElement === undefined) { - throw new Error('Element not found'); - } - const edgePath = this.path(edgeIndex); - return { edgePath, edgeElement, edgeIndex, edgeElementsCount: this._layers[0].length }; - } - /** - * 🪓 - * @param count - */ - getTreeSlices(count = 4) { - const length = this._layers[0].length; - let size = Math.ceil(length / count); - if (size % 2) - size++; - const slices = []; - for (let i = 0; i < length; i += size) { - const edgeLeft = i; - const edgeRight = i + size; - slices.push({ edge: this.getTreeEdge(edgeLeft), elements: this.elements.slice(edgeLeft, edgeRight) }); - } - return slices; - } - /** - * Serialize entire tree state including intermediate layers into a plain object - * Deserializing it back will not require to recompute any hashes - * Elements are not converted to a plain type, this is responsibility of the caller - */ - serialize() { - return { - levels: this.levels, - _zeros: this._zeros, - _layers: this._layers, - }; - } - /** - * Deserialize data into a MerkleTree instance - * Make sure to provide the same hashFunction as was used in the source tree, - * otherwise the tree state will be invalid - */ - static deserialize(data, hashFunction) { - const instance = Object.assign(Object.create(this.prototype), data); - instance._hashFn = hashFunction || simpleHash_1.default; - instance.zeroElement = instance._zeros[0]; - return instance; - } - toString() { - return JSON.stringify(this.serialize()); - } -} -exports["default"] = MerkleTree; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const simpleHash_1 = __importDefault(__webpack_require__(5319)); +const BaseTree_1 = __webpack_require__(7736); +class MerkleTree extends BaseTree_1.BaseTree { + constructor(levels, elements = [], { hashFunction = simpleHash_1.default, zeroElement = 0, } = {}) { + super(); + this.levels = levels; + if (elements.length > this.capacity) { + throw new Error('Tree is full'); + } + this._hashFn = hashFunction; + this.zeroElement = zeroElement; + this._layers = []; + const leaves = elements.slice(); + this._layers = [leaves]; + this._buildZeros(); + this._buildHashes(); + } + _buildHashes() { + for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) { + const nodes = this._layers[layerIndex - 1]; + this._layers[layerIndex] = this._processNodes(nodes, layerIndex); + } + } + /** + * Insert multiple elements into the tree. + * @param {Array} elements Elements to insert + */ + bulkInsert(elements) { + if (!elements.length) { + return; + } + if (this._layers[0].length + elements.length > this.capacity) { + throw new Error('Tree is full'); + } + // First we insert all elements except the last one + // 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 + for (let i = 0; i < elements.length - 1; i++) { + this._layers[0].push(elements[i]); + let level = 0; + let index = this._layers[0].length - 1; + while (index % 2 === 1) { + level++; + index >>= 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]); + } + indexOf(element, comparator) { + return BaseTree_1.BaseTree.indexOf(this._layers[0], element, 0, comparator); + } + proof(element) { + const index = this.indexOf(element); + return this.path(index); + } + getTreeEdge(edgeIndex) { + const edgeElement = this._layers[0][edgeIndex]; + if (edgeElement === undefined) { + throw new Error('Element not found'); + } + const edgePath = this.path(edgeIndex); + return { edgePath, edgeElement, edgeIndex, edgeElementsCount: this._layers[0].length }; + } + /** + * 🪓 + * @param count + */ + getTreeSlices(count = 4) { + const length = this._layers[0].length; + let size = Math.ceil(length / count); + if (size % 2) + size++; + const slices = []; + for (let i = 0; i < length; i += size) { + const edgeLeft = i; + const edgeRight = i + size; + slices.push({ edge: this.getTreeEdge(edgeLeft), elements: this.elements.slice(edgeLeft, edgeRight) }); + } + return slices; + } + /** + * Serialize entire tree state including intermediate layers into a plain object + * Deserializing it back will not require to recompute any hashes + * Elements are not converted to a plain type, this is responsibility of the caller + */ + serialize() { + return { + levels: this.levels, + _zeros: this._zeros, + _layers: this._layers, + }; + } + /** + * Deserialize data into a MerkleTree instance + * Make sure to provide the same hashFunction as was used in the source tree, + * otherwise the tree state will be invalid + */ + static deserialize(data, hashFunction) { + const instance = Object.assign(Object.create(this.prototype), data); + instance._hashFn = hashFunction || simpleHash_1.default; + instance.zeroElement = instance._zeros[0]; + return instance; + } + toString() { + return JSON.stringify(this.serialize()); + } +} +exports["default"] = MerkleTree; /***/ }), @@ -9792,165 +9792,165 @@ exports["default"] = MerkleTree; /***/ (function(__unused_webpack_module, exports, __webpack_require__) { "use strict"; - -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.PartialMerkleTree = void 0; -const simpleHash_1 = __importDefault(__webpack_require__(5319)); -const BaseTree_1 = __webpack_require__(7736); -class PartialMerkleTree extends BaseTree_1.BaseTree { - constructor(levels, { edgePath, edgeElement, edgeIndex, edgeElementsCount, }, leaves, { hashFunction, zeroElement } = {}) { - super(); - if (edgeIndex + leaves.length !== edgeElementsCount) - throw new Error('Invalid number of elements'); - this._edgeLeafProof = edgePath; - this._initialRoot = edgePath.pathRoot; - this.zeroElement = zeroElement !== null && zeroElement !== void 0 ? zeroElement : 0; - this._edgeLeaf = { data: edgeElement, index: edgeIndex }; - this._leavesAfterEdge = leaves; - this.levels = levels; - this._hashFn = hashFunction || simpleHash_1.default; - this._createProofMap(); - this._buildTree(); - } - get edgeIndex() { - return this._edgeLeaf.index; - } - get edgeElement() { - return this._edgeLeaf.data; - } - get edgeLeafProof() { - return this._edgeLeafProof; - } - _createProofMap() { - this._proofMap = this.edgeLeafProof.pathPositions.reduce((p, c, i) => { - p.set(i, [c, this.edgeLeafProof.pathElements[i]]); - return p; - }, new Map()); - this._proofMap.set(this.levels, [0, this.edgeLeafProof.pathRoot]); - } - _buildTree() { - const edgeLeafIndex = this._edgeLeaf.index; - this._leaves = Array(edgeLeafIndex).concat(this._leavesAfterEdge); - if (this._proofMap.has(0)) { - const [proofPos, proofEl] = this._proofMap.get(0); - this._leaves[proofPos] = proofEl; - } - this._layers = [this._leaves]; - this._buildZeros(); - this._buildHashes(); - } - _buildHashes() { - for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) { - const nodes = this._layers[layerIndex - 1]; - const currentLayer = this._processNodes(nodes, layerIndex); - if (this._proofMap.has(layerIndex)) { - const [proofPos, proofEl] = this._proofMap.get(layerIndex); - if (!currentLayer[proofPos]) - currentLayer[proofPos] = proofEl; - } - this._layers[layerIndex] = currentLayer; - } - } - /** - * Change an element in the tree - * @param {number} index Index of element to change - * @param element Updated element value - */ - update(index, element) { - if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) { - throw new Error('Insert index out of bounds: ' + index); - } - if (index < this._edgeLeaf.index) { - throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`); - } - this._layers[0][index] = element; - this._processUpdate(index); - } - path(index) { - var _a; - if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) { - throw new Error('Index out of bounds: ' + index); - } - if (index < this._edgeLeaf.index) { - throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`); - } - let elIndex = Number(index); - const pathElements = []; - const pathIndices = []; - const pathPositions = []; - for (let level = 0; level < this.levels; level++) { - pathIndices[level] = elIndex % 2; - const leafIndex = elIndex ^ 1; - if (leafIndex < this._layers[level].length) { - pathElements[level] = this._layers[level][leafIndex]; - pathPositions[level] = leafIndex; - } - else { - pathElements[level] = this._zeros[level]; - pathPositions[level] = 0; - } - const [proofPos, proofEl] = this._proofMap.get(level); - pathElements[level] = (_a = pathElements[level]) !== null && _a !== void 0 ? _a : (proofPos === leafIndex ? proofEl : this._zeros[level]); - elIndex >>= 1; - } - return { - pathElements, - pathIndices, - pathPositions, - pathRoot: this.root, - }; - } - indexOf(element, comparator) { - return BaseTree_1.BaseTree.indexOf(this._layers[0], element, this.edgeIndex, comparator); - } - proof(element) { - const index = this.indexOf(element); - return this.path(index); - } - /** - * Shifts edge of tree to left - * @param edge new TreeEdge below current edge - * @param elements leaves between old and new edge - */ - shiftEdge(edge, elements) { - if (this._edgeLeaf.index <= edge.edgeIndex) { - throw new Error(`New edgeIndex should be smaller then ${this._edgeLeaf.index}`); - } - if (elements.length !== (this._edgeLeaf.index - edge.edgeIndex)) { - throw new Error(`Elements length should be ${this._edgeLeaf.index - edge.edgeIndex}`); - } - this._edgeLeafProof = edge.edgePath; - this._edgeLeaf = { index: edge.edgeIndex, data: edge.edgeElement }; - this._leavesAfterEdge = [...elements, ...this._leavesAfterEdge]; - this._createProofMap(); - this._buildTree(); - } - serialize() { - return { - _edgeLeafProof: this._edgeLeafProof, - _edgeLeaf: this._edgeLeaf, - _layers: this._layers, - _zeros: this._zeros, - levels: this.levels, - }; - } - static deserialize(data, hashFunction) { - const instance = Object.assign(Object.create(this.prototype), data); - instance._hashFn = hashFunction || simpleHash_1.default; - instance._initialRoot = data._edgeLeafProof.pathRoot; - instance.zeroElement = instance._zeros[0]; - instance._leavesAfterEdge = instance._layers[0].slice(data._edgeLeaf.index); - instance._createProofMap(); - return instance; - } - toString() { - return JSON.stringify(this.serialize()); - } -} -exports.PartialMerkleTree = PartialMerkleTree; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PartialMerkleTree = void 0; +const simpleHash_1 = __importDefault(__webpack_require__(5319)); +const BaseTree_1 = __webpack_require__(7736); +class PartialMerkleTree extends BaseTree_1.BaseTree { + constructor(levels, { edgePath, edgeElement, edgeIndex, edgeElementsCount, }, leaves, { hashFunction, zeroElement } = {}) { + super(); + if (edgeIndex + leaves.length !== edgeElementsCount) + throw new Error('Invalid number of elements'); + this._edgeLeafProof = edgePath; + this._initialRoot = edgePath.pathRoot; + this.zeroElement = zeroElement !== null && zeroElement !== void 0 ? zeroElement : 0; + this._edgeLeaf = { data: edgeElement, index: edgeIndex }; + this._leavesAfterEdge = leaves; + this.levels = levels; + this._hashFn = hashFunction || simpleHash_1.default; + this._createProofMap(); + this._buildTree(); + } + get edgeIndex() { + return this._edgeLeaf.index; + } + get edgeElement() { + return this._edgeLeaf.data; + } + get edgeLeafProof() { + return this._edgeLeafProof; + } + _createProofMap() { + this._proofMap = this.edgeLeafProof.pathPositions.reduce((p, c, i) => { + p.set(i, [c, this.edgeLeafProof.pathElements[i]]); + return p; + }, new Map()); + this._proofMap.set(this.levels, [0, this.edgeLeafProof.pathRoot]); + } + _buildTree() { + const edgeLeafIndex = this._edgeLeaf.index; + this._leaves = Array(edgeLeafIndex).concat(this._leavesAfterEdge); + if (this._proofMap.has(0)) { + const [proofPos, proofEl] = this._proofMap.get(0); + this._leaves[proofPos] = proofEl; + } + this._layers = [this._leaves]; + this._buildZeros(); + this._buildHashes(); + } + _buildHashes() { + for (let layerIndex = 1; layerIndex <= this.levels; layerIndex++) { + const nodes = this._layers[layerIndex - 1]; + const currentLayer = this._processNodes(nodes, layerIndex); + if (this._proofMap.has(layerIndex)) { + const [proofPos, proofEl] = this._proofMap.get(layerIndex); + if (!currentLayer[proofPos]) + currentLayer[proofPos] = proofEl; + } + this._layers[layerIndex] = currentLayer; + } + } + /** + * Change an element in the tree + * @param {number} index Index of element to change + * @param element Updated element value + */ + update(index, element) { + if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) { + throw new Error('Insert index out of bounds: ' + index); + } + if (index < this._edgeLeaf.index) { + throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`); + } + this._layers[0][index] = element; + this._processUpdate(index); + } + path(index) { + var _a; + if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) { + throw new Error('Index out of bounds: ' + index); + } + if (index < this._edgeLeaf.index) { + throw new Error(`Index ${index} is below the edge: ${this._edgeLeaf.index}`); + } + let elIndex = Number(index); + const pathElements = []; + const pathIndices = []; + const pathPositions = []; + for (let level = 0; level < this.levels; level++) { + pathIndices[level] = elIndex % 2; + const leafIndex = elIndex ^ 1; + if (leafIndex < this._layers[level].length) { + pathElements[level] = this._layers[level][leafIndex]; + pathPositions[level] = leafIndex; + } + else { + pathElements[level] = this._zeros[level]; + pathPositions[level] = 0; + } + const [proofPos, proofEl] = this._proofMap.get(level); + pathElements[level] = (_a = pathElements[level]) !== null && _a !== void 0 ? _a : (proofPos === leafIndex ? proofEl : this._zeros[level]); + elIndex >>= 1; + } + return { + pathElements, + pathIndices, + pathPositions, + pathRoot: this.root, + }; + } + indexOf(element, comparator) { + return BaseTree_1.BaseTree.indexOf(this._layers[0], element, this.edgeIndex, comparator); + } + proof(element) { + const index = this.indexOf(element); + return this.path(index); + } + /** + * Shifts edge of tree to left + * @param edge new TreeEdge below current edge + * @param elements leaves between old and new edge + */ + shiftEdge(edge, elements) { + if (this._edgeLeaf.index <= edge.edgeIndex) { + throw new Error(`New edgeIndex should be smaller then ${this._edgeLeaf.index}`); + } + if (elements.length !== (this._edgeLeaf.index - edge.edgeIndex)) { + throw new Error(`Elements length should be ${this._edgeLeaf.index - edge.edgeIndex}`); + } + this._edgeLeafProof = edge.edgePath; + this._edgeLeaf = { index: edge.edgeIndex, data: edge.edgeElement }; + this._leavesAfterEdge = [...elements, ...this._leavesAfterEdge]; + this._createProofMap(); + this._buildTree(); + } + serialize() { + return { + _edgeLeafProof: this._edgeLeafProof, + _edgeLeaf: this._edgeLeaf, + _layers: this._layers, + _zeros: this._zeros, + levels: this.levels, + }; + } + static deserialize(data, hashFunction) { + const instance = Object.assign(Object.create(this.prototype), data); + instance._hashFn = hashFunction || simpleHash_1.default; + instance._initialRoot = data._edgeLeafProof.pathRoot; + instance.zeroElement = instance._zeros[0]; + instance._leavesAfterEdge = instance._layers[0].slice(data._edgeLeaf.index); + instance._createProofMap(); + return instance; + } + toString() { + return JSON.stringify(this.serialize()); + } +} +exports.PartialMerkleTree = PartialMerkleTree; /***/ }), @@ -9959,19 +9959,19 @@ exports.PartialMerkleTree = PartialMerkleTree; /***/ (function(__unused_webpack_module, exports, __webpack_require__) { "use strict"; - -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.MerkleTree = exports.simpleHash = exports.PartialMerkleTree = void 0; -const FixedMerkleTree_1 = __importDefault(__webpack_require__(9093)); -Object.defineProperty(exports, "MerkleTree", ({ enumerable: true, get: function () { return FixedMerkleTree_1.default; } })); -var PartialMerkleTree_1 = __webpack_require__(91230); -Object.defineProperty(exports, "PartialMerkleTree", ({ enumerable: true, get: function () { return PartialMerkleTree_1.PartialMerkleTree; } })); -var simpleHash_1 = __webpack_require__(5319); -Object.defineProperty(exports, "simpleHash", ({ enumerable: true, get: function () { return simpleHash_1.simpleHash; } })); -exports["default"] = FixedMerkleTree_1.default; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.MerkleTree = exports.simpleHash = exports.PartialMerkleTree = void 0; +const FixedMerkleTree_1 = __importDefault(__webpack_require__(9093)); +Object.defineProperty(exports, "MerkleTree", ({ enumerable: true, get: function () { return FixedMerkleTree_1.default; } })); +var PartialMerkleTree_1 = __webpack_require__(91230); +Object.defineProperty(exports, "PartialMerkleTree", ({ enumerable: true, get: function () { return PartialMerkleTree_1.PartialMerkleTree; } })); +var simpleHash_1 = __webpack_require__(5319); +Object.defineProperty(exports, "simpleHash", ({ enumerable: true, get: function () { return simpleHash_1.simpleHash; } })); +exports["default"] = FixedMerkleTree_1.default; /***/ }), @@ -9980,27 +9980,27 @@ exports["default"] = FixedMerkleTree_1.default; /***/ ((__unused_webpack_module, exports) => { "use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.simpleHash = void 0; -/*** - * This is insecure hash function, just for example only - * @param data - * @param seed - * @param hashLength - */ -function simpleHash(data, seed, hashLength = 40) { - const str = data.join(''); - let i, l, hval = seed !== null && seed !== void 0 ? seed : 0x811c9dcc5; - for (i = 0, l = str.length; i < l; i++) { - hval ^= str.charCodeAt(i); - hval += (hval << 1) + (hval << 4) + (hval << 6) + (hval << 8) + (hval << 24); - } - const hash = (hval >>> 0).toString(16); - return BigInt('0x' + hash.padEnd(hashLength - (hash.length - 1), '0')).toString(10); -} -exports.simpleHash = simpleHash; -exports["default"] = (left, right) => simpleHash([left, right]); + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.simpleHash = void 0; +/*** + * This is insecure hash function, just for example only + * @param data + * @param seed + * @param hashLength + */ +function simpleHash(data, seed, hashLength = 40) { + const str = data.join(''); + let i, l, hval = seed !== null && seed !== void 0 ? seed : 0x811c9dcc5; + for (i = 0, l = str.length; i < l; i++) { + hval ^= str.charCodeAt(i); + hval += (hval << 1) + (hval << 4) + (hval << 6) + (hval << 8) + (hval << 24); + } + const hash = (hval >>> 0).toString(16); + return BigInt('0x' + hash.padEnd(hashLength - (hash.length - 1), '0')).toString(10); +} +exports.simpleHash = simpleHash; +exports["default"] = (left, right) => simpleHash([left, right]); /***/ }), diff --git a/package.json b/package.json index d34a055..5f87488 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,10 @@ ], "dependencies": { "@metamask/eth-sig-util": "^8.0.0", - "@tornado/contracts": "git+https://codeberg.org/tornadocash/tornado-contracts.git#1b1d707878c16a3dc60d295299d4f0e7ce6ba831", - "@tornado/fixed-merkle-tree": "git+https://codeberg.org/tornadocash/fixed-merkle-tree.git#5c3fca4cb11255760ad5f4fd95d7c6eb45c1fc99", - "@tornado/snarkjs": "git+https://codeberg.org/tornadocash/snarkjs.git#d3915a760c437cde7bd317f9ea2c627954900656", - "@tornado/websnark": "git+https://codeberg.org/tornadocash/websnark.git#b0c9fce5359ceba55167a2ad01a29d1e137843ec", + "@tornado/contracts": "git+https://git.tornado.ws/tornadocontrib/tornado-contracts.git#1b1d707878c16a3dc60d295299d4f0e7ce6ba831", + "@tornado/fixed-merkle-tree": "^0.7.3", + "@tornado/snarkjs": "^0.1.20", + "@tornado/websnark": "^0.0.4", "ajv": "^8.17.1", "bn.js": "^5.2.1", "circomlibjs": "0.1.7", diff --git a/yarn.lock b/yarn.lock index cdb8723..470b102 100644 --- a/yarn.lock +++ b/yarn.lock @@ -872,21 +872,23 @@ "@noble/hashes" "~1.4.0" "@scure/base" "~1.1.6" -"@tornado/contracts@git+https://codeberg.org/tornadocash/tornado-contracts.git#1b1d707878c16a3dc60d295299d4f0e7ce6ba831": +"@tornado/contracts@git+https://git.tornado.ws/tornadocontrib/tornado-contracts.git#1b1d707878c16a3dc60d295299d4f0e7ce6ba831": version "1.0.2" - resolved "git+https://codeberg.org/tornadocash/tornado-contracts.git#1b1d707878c16a3dc60d295299d4f0e7ce6ba831" + resolved "git+https://git.tornado.ws/tornadocontrib/tornado-contracts.git#1b1d707878c16a3dc60d295299d4f0e7ce6ba831" dependencies: "@openzeppelin/contracts" "5.0.2" "@openzeppelin/contracts-v3" "npm:@openzeppelin/contracts@3.2.0-rc.0" ethers "^6.13.4" -"@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" - 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" - 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: big-integer "^1.6.43" chai "^4.2.0" @@ -895,11 +897,12 @@ keccak "^2.0.0" yargs "^12.0.5" -"@tornado/websnark@git+https://codeberg.org/tornadocash/websnark.git#b0c9fce5359ceba55167a2ad01a29d1e137843ec": +"@tornado/websnark@^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: - "@tornado/snarkjs" "git+https://codeberg.org/tornadocash/snarkjs.git#d3915a760c437cde7bd317f9ea2c627954900656" + "@tornado/snarkjs" "^0.1.20" big-integer "1.6.42" "@typechain/ethers-v6@^0.5.1":