UNPKG

@chainsafe/eth2.0-utils

Version:

Utilities required across multiple lodestar packages

132 lines (98 loc) 3.08 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LightProgressiveMerkleTree = void 0; var _crypto = require("../crypto"); var _math = require("../math"); var _assert = _interopRequireDefault(require("assert")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } /** * Only usable if we need proof and root of adding single element. * Element proof gets invalid if you add another element. */ class LightProgressiveMerkleTree { constructor(depth) { _defineProperty(this, "_depth", void 0); _defineProperty(this, "_count", void 0); _defineProperty(this, "_branch", void 0); _defineProperty(this, "_zerohashes", void 0); (0, _assert.default)(depth <= 52, "tree depth must be less than 53"); this._depth = depth; this._count = 0; this._branch = Array.from({ length: depth }, () => Buffer.alloc(32)); this._zerohashes = Array.from({ length: depth }, () => Buffer.alloc(32)); for (let i = 0; i < depth - 1; i++) { this._zerohashes[i + 1] = this._branch[i + 1] = (0, _crypto.hash)(Buffer.concat([this._zerohashes[i], this._zerohashes[i]])); } } count() { return this._count; } depth() { return this._depth; } push(item) { const depth = this._depth; const proof = this._proof(); this._count++; let i = 0; let powerOfTwo = 2; for (let j = 0; j < depth; j++) { if (this._count % powerOfTwo !== 0) { break; } i++; powerOfTwo *= 2; } let value = item; for (let j = 0; j < depth; j++) { if (j < i) { value = (0, _crypto.hash)(Buffer.concat([this._branch[j], value])); } else { break; } } this._branch[i] = value; return proof; } clone() { const cloned = Object.create(LightProgressiveMerkleTree.prototype); cloned._depth = this._depth; cloned._count = this._count; cloned._branch = this._branch.slice(); cloned._zerohashes = this._zerohashes; return cloned; } root() { let root = Buffer.alloc(32); let size = this._count; for (let i = 0; i < this._depth; i++) { if (size % 2 === 1) { root = (0, _crypto.hash)(Buffer.concat([this._branch[i], root])); } else { root = (0, _crypto.hash)(Buffer.concat([root, this._zerohashes[i]])); } size = (0, _math.intDiv)(size, 2); } return root; } _proof() { let size = this._count; const proof = this._branch.slice(); for (let i = 0; i < this._depth; i++) { if (size % 2 === 0) { proof[i] = this._zerohashes[i]; } size = (0, _math.intDiv)(size, 2); } return proof; } } exports.LightProgressiveMerkleTree = LightProgressiveMerkleTree; //# sourceMappingURL=lightMerkleTree.js.map