You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

shamap.js 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.SHAMap = exports.Leaf = exports.InnerNode = exports.Node = exports.NodeType = void 0;
  7. const hash_prefix_1 = __importDefault(require("./hash-prefix"));
  8. const sha512Half_1 = __importDefault(require("./sha512Half"));
  9. const HEX_ZERO = '0000000000000000000000000000000000000000000000000000000000000000';
  10. var 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 = {}));
  17. class 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. }
  26. exports.Node = Node;
  27. class 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. }
  81. exports.InnerNode = InnerNode;
  82. class 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. }
  108. exports.Leaf = Leaf;
  109. class 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. }
  120. exports.SHAMap = SHAMap;
  121. //# sourceMappingURL=shamap.js.map