UNPKG

@aeternity/aepp-sdk

Version:
198 lines (170 loc) 6.88 kB
import _slicedToArray from "@babel/runtime-corejs3/helpers/slicedToArray"; import _classCallCheck from "@babel/runtime-corejs3/helpers/classCallCheck"; import _createClass from "@babel/runtime-corejs3/helpers/createClass"; import _Object$fromEntries from "@babel/runtime-corejs3/core-js-stable/object/from-entries"; import _mapInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/map"; import _forEachInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/for-each"; import _Object$entries from "@babel/runtime-corejs3/core-js-stable/object/entries"; import _filterInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/filter"; import _sliceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/slice"; import _parseInt from "@babel/runtime-corejs3/core-js-stable/parse-int"; import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes"; /* * ISC License (ISC) * Copyright (c) 2021 aeternity developers * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ import { encode as rlpEncode } from 'rlp'; import { hash } from './crypto-ts'; var NodeType; (function (NodeType) { NodeType[NodeType["Branch"] = 0] = "Branch"; NodeType[NodeType["Extension"] = 1] = "Extension"; NodeType[NodeType["Leaf"] = 2] = "Leaf"; })(NodeType || (NodeType = {})); var MPTree = /*#__PURE__*/function () { /** * Deserialize Merkle Patricia Tree * @rtype (binary: Array) => MPTree * @param {Array} binary - Binary * @return {MPTree} Merkle Patricia Tree */ function MPTree(binary) { var _context, _context2, _this = this; _classCallCheck(this, MPTree); this.rootHash = binary[0].toString('hex'); this.nodes = _Object$fromEntries(_mapInstanceProperty(_context = binary[1]).call(_context, function (node) { return [node[0].toString('hex'), node[1]]; })); if (this.nodes[this.rootHash] === undefined) throw new Error('Can\'t find a node by root hash'); _forEachInstanceProperty(_context2 = _Object$entries(this.nodes)).call(_context2, function (_ref) { var _context3, _context4; var _ref2 = _slicedToArray(_ref, 2), key = _ref2[0], node = _ref2[1]; if (MPTree.nodeHash(node) !== key) throw new Error('Node hash is not equal to provided one'); var _MPTree$parseNode = MPTree.parseNode(node), type = _MPTree$parseNode.type, payload = _MPTree$parseNode.payload; switch (type) { case NodeType.Branch: _forEachInstanceProperty(_context3 = _filterInstanceProperty(_context4 = _sliceInstanceProperty(payload).call(payload, 0, 16)).call(_context4, function (n) { return n.length; })).call(_context3, function (n) { if (_this.nodes[n.toString('hex')] === undefined) { throw new Error('Can\'t find a node by hash in branch node'); } }); break; case NodeType.Extension: if (_this.nodes[payload[0].toString('hex')] === undefined) { throw new Error('Can\'t find a node by hash in extension node'); } } }); } _createClass(MPTree, [{ key: "isEqual", value: function isEqual(tree) { return this.rootHash === tree.rootHash; } }, { key: "serialize", value: /** * Serialize Merkle Patricia Tree * @rtype () => Array * @return {Array} Binary */ function serialize() { var _context5; return [Buffer.from(this.rootHash, 'hex'), _mapInstanceProperty(_context5 = _Object$entries(this.nodes)).call(_context5, function (_ref3) { var _ref4 = _slicedToArray(_ref3, 2), mptHash = _ref4[0], value = _ref4[1]; return [Buffer.from(mptHash, 'hex'), value]; })]; } /** * Retrieve value from Merkle Patricia Tree * @rtype (key: String) => Buffer * @param {String} key - The key of the element to retrieve * @return {Buffer} Value associated to the specified key */ }, { key: "get", value: function get(key) { var searchFrom = this.rootHash; while (true) { var _MPTree$parseNode2 = MPTree.parseNode(this.nodes[searchFrom]), type = _MPTree$parseNode2.type, payload = _MPTree$parseNode2.payload, path = _MPTree$parseNode2.path; switch (type) { case NodeType.Branch: if (key.length === 0) return payload[16]; searchFrom = payload[_parseInt(key[0], 16)].toString('hex'); key = key.substr(1); break; case NodeType.Extension: if (key.substr(0, path === null || path === void 0 ? void 0 : path.length) !== path) return undefined; searchFrom = payload[0].toString('hex'); key = key.substr(path.length); break; case NodeType.Leaf: if (path !== key) return undefined; return payload[0]; } } } }], [{ key: "nodeHash", value: function nodeHash(node) { return Buffer.from(hash(rlpEncode(node))).toString('hex'); } }, { key: "parseNode", value: function parseNode(node) { switch (node.length) { case 17: return { type: NodeType.Branch, payload: node, path: null }; case 2: { var _context6; var path = node[0].toString('hex'); var nibble = _parseInt(path[0], 16); if (nibble > 3) throw new Error("Unknown path nibble: ".concat(nibble)); var type = nibble <= 1 ? NodeType.Extension : NodeType.Leaf; var slice = _includesInstanceProperty(_context6 = [0, 2]).call(_context6, nibble) ? 2 : 1; return { type: type, payload: [node[1]], path: _sliceInstanceProperty(path).call(path, slice) }; } default: throw new Error("Unknown node length: ".concat(node.length)); } } }]); return MPTree; }(); export { MPTree as default }; //# sourceMappingURL=mptree.js.map