UNPKG

4.35 kBJavaScriptView Raw
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3 return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6exports.SHAMap = exports.Leaf = exports.InnerNode = exports.Node = exports.NodeType = void 0;
7const hash_prefix_1 = __importDefault(require("./hash-prefix"));
8const sha512Half_1 = __importDefault(require("./sha512Half"));
9const HEX_ZERO = '0000000000000000000000000000000000000000000000000000000000000000';
10var NodeType;
11(function (NodeType) {
12 NodeType[NodeType["INNER"] = 1] = "INNER";
13 NodeType[NodeType["TRANSACTION_NO_METADATA"] = 2] = "TRANSACTION_NO_METADATA";
14 NodeType[NodeType["TRANSACTION_METADATA"] = 3] = "TRANSACTION_METADATA";
15 NodeType[NodeType["ACCOUNT_STATE"] = 4] = "ACCOUNT_STATE";
16})(NodeType = exports.NodeType || (exports.NodeType = {}));
17class Node {
18 constructor() { }
19 addItem(_tag, _node) {
20 throw new Error('Called unimplemented virtual method SHAMapTreeNode#addItem.');
21 }
22 get hash() {
23 throw new Error('Called unimplemented virtual method SHAMapTreeNode#hash.');
24 }
25}
26exports.Node = Node;
27class InnerNode extends Node {
28 constructor(depth = 0) {
29 super();
30 this.leaves = {};
31 this.type = NodeType.INNER;
32 this.depth = depth;
33 this.empty = true;
34 }
35 addItem(tag, node) {
36 const existingNode = this.getNode(parseInt(tag[this.depth], 16));
37 if (existingNode) {
38 if (existingNode instanceof InnerNode) {
39 existingNode.addItem(tag, node);
40 }
41 else if (existingNode instanceof Leaf) {
42 if (existingNode.tag === tag) {
43 throw new Error('Tried to add a node to a SHAMap that was already in there.');
44 }
45 else {
46 const newInnerNode = new InnerNode(this.depth + 1);
47 newInnerNode.addItem(existingNode.tag, existingNode);
48 newInnerNode.addItem(tag, node);
49 this.setNode(parseInt(tag[this.depth], 16), newInnerNode);
50 }
51 }
52 }
53 else {
54 this.setNode(parseInt(tag[this.depth], 16), node);
55 }
56 }
57 setNode(slot, node) {
58 if (slot < 0 || slot > 15) {
59 throw new Error('Invalid slot: slot must be between 0-15.');
60 }
61 this.leaves[slot] = node;
62 this.empty = false;
63 }
64 getNode(slot) {
65 if (slot < 0 || slot > 15) {
66 throw new Error('Invalid slot: slot must be between 0-15.');
67 }
68 return this.leaves[slot];
69 }
70 get hash() {
71 if (this.empty)
72 return HEX_ZERO;
73 let hex = '';
74 for (let i = 0; i < 16; i++) {
75 hex += this.leaves[i] ? this.leaves[i].hash : HEX_ZERO;
76 }
77 const prefix = hash_prefix_1.default.INNER_NODE.toString(16);
78 return sha512Half_1.default(prefix + hex);
79 }
80}
81exports.InnerNode = InnerNode;
82class Leaf extends Node {
83 constructor(tag, data, type) {
84 super();
85 this.tag = tag;
86 this.type = type;
87 this.data = data;
88 }
89 get hash() {
90 switch (this.type) {
91 case NodeType.ACCOUNT_STATE: {
92 const leafPrefix = hash_prefix_1.default.LEAF_NODE.toString(16);
93 return sha512Half_1.default(leafPrefix + this.data + this.tag);
94 }
95 case NodeType.TRANSACTION_NO_METADATA: {
96 const txIDPrefix = hash_prefix_1.default.TRANSACTION_ID.toString(16);
97 return sha512Half_1.default(txIDPrefix + this.data);
98 }
99 case NodeType.TRANSACTION_METADATA: {
100 const txNodePrefix = hash_prefix_1.default.TRANSACTION_NODE.toString(16);
101 return sha512Half_1.default(txNodePrefix + this.data + this.tag);
102 }
103 default:
104 throw new Error('Tried to hash a SHAMap node of unknown type.');
105 }
106 }
107}
108exports.Leaf = Leaf;
109class SHAMap {
110 constructor() {
111 this.root = new InnerNode(0);
112 }
113 addItem(tag, data, type) {
114 this.root.addItem(tag, new Leaf(tag, data, type));
115 }
116 get hash() {
117 return this.root.hash;
118 }
119}
120exports.SHAMap = SHAMap;
121//# sourceMappingURL=shamap.js.map
\No newline at end of file