Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

shamap.js 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.ShaMapLeaf = exports.ShaMapNode = exports.ShaMap = void 0;
  4. const assert_1 = require("assert");
  5. const types_1 = require("./types");
  6. const hash_prefixes_1 = require("./hash-prefixes");
  7. const hashes_1 = require("./hashes");
  8. const buffer_1 = require("buffer/");
  9. /**
  10. * Abstract class describing a SHAMapNode
  11. */
  12. class ShaMapNode {
  13. }
  14. exports.ShaMapNode = ShaMapNode;
  15. /**
  16. * Class describing a Leaf of SHAMap
  17. */
  18. class ShaMapLeaf extends ShaMapNode {
  19. constructor(index, item) {
  20. super();
  21. this.index = index;
  22. this.item = item;
  23. }
  24. /**
  25. * @returns true as ShaMapLeaf is a leaf node
  26. */
  27. isLeaf() {
  28. return true;
  29. }
  30. /**
  31. * @returns false as ShaMapLeaf is not an inner node
  32. */
  33. isInner() {
  34. return false;
  35. }
  36. /**
  37. * Get the prefix of the this.item
  38. *
  39. * @returns The hash prefix, unless this.item is undefined, then it returns an empty Buffer
  40. */
  41. hashPrefix() {
  42. return this.item === undefined ? buffer_1.Buffer.alloc(0) : this.item.hashPrefix();
  43. }
  44. /**
  45. * Hash the bytes representation of this
  46. *
  47. * @returns hash of this.item concatenated with this.index
  48. */
  49. hash() {
  50. const hash = hashes_1.Sha512Half.put(this.hashPrefix());
  51. this.toBytesSink(hash);
  52. return hash.finish();
  53. }
  54. /**
  55. * Write the bytes representation of this to a BytesList
  56. * @param list BytesList to write bytes to
  57. */
  58. toBytesSink(list) {
  59. if (this.item !== undefined) {
  60. this.item.toBytesSink(list);
  61. }
  62. this.index.toBytesSink(list);
  63. }
  64. }
  65. exports.ShaMapLeaf = ShaMapLeaf;
  66. /**
  67. * Class defining an Inner Node of a SHAMap
  68. */
  69. class ShaMapInner extends ShaMapNode {
  70. constructor(depth = 0) {
  71. super();
  72. this.depth = depth;
  73. this.slotBits = 0;
  74. this.branches = Array(16);
  75. }
  76. /**
  77. * @returns true as ShaMapInner is an inner node
  78. */
  79. isInner() {
  80. return true;
  81. }
  82. /**
  83. * @returns false as ShaMapInner is not a leaf node
  84. */
  85. isLeaf() {
  86. return false;
  87. }
  88. /**
  89. * Get the hash prefix for this node
  90. *
  91. * @returns hash prefix describing an inner node
  92. */
  93. hashPrefix() {
  94. return hash_prefixes_1.HashPrefix.innerNode;
  95. }
  96. /**
  97. * Set a branch of this node to be another node
  98. *
  99. * @param slot Slot to add branch to this.branches
  100. * @param branch Branch to add
  101. */
  102. setBranch(slot, branch) {
  103. this.slotBits = this.slotBits | (1 << slot);
  104. this.branches[slot] = branch;
  105. }
  106. /**
  107. * @returns true if node is empty
  108. */
  109. empty() {
  110. return this.slotBits === 0;
  111. }
  112. /**
  113. * Compute the hash of this node
  114. *
  115. * @returns The hash of this node
  116. */
  117. hash() {
  118. if (this.empty()) {
  119. return types_1.coreTypes.Hash256.ZERO_256;
  120. }
  121. const hash = hashes_1.Sha512Half.put(this.hashPrefix());
  122. this.toBytesSink(hash);
  123. return hash.finish();
  124. }
  125. /**
  126. * Writes the bytes representation of this node to a BytesList
  127. *
  128. * @param list BytesList to write bytes to
  129. */
  130. toBytesSink(list) {
  131. for (let i = 0; i < this.branches.length; i++) {
  132. const branch = this.branches[i];
  133. const hash = branch ? branch.hash() : types_1.coreTypes.Hash256.ZERO_256;
  134. hash.toBytesSink(list);
  135. }
  136. }
  137. /**
  138. * Add item to the SHAMap
  139. *
  140. * @param index Hash of the index of the item being inserted
  141. * @param item Item to insert in the map
  142. * @param leaf Leaf node to insert when branch doesn't exist
  143. */
  144. addItem(index, item, leaf) {
  145. assert_1.strict.ok(index !== undefined);
  146. if (index !== undefined) {
  147. const nibble = index.nibblet(this.depth);
  148. const existing = this.branches[nibble];
  149. if (existing === undefined) {
  150. this.setBranch(nibble, leaf || new ShaMapLeaf(index, item));
  151. }
  152. else if (existing instanceof ShaMapLeaf) {
  153. const newInner = new ShaMapInner(this.depth + 1);
  154. newInner.addItem(existing.index, undefined, existing);
  155. newInner.addItem(index, item, leaf);
  156. this.setBranch(nibble, newInner);
  157. }
  158. else if (existing instanceof ShaMapInner) {
  159. existing.addItem(index, item, leaf);
  160. }
  161. else {
  162. throw new Error('invalid ShaMap.addItem call');
  163. }
  164. }
  165. }
  166. }
  167. class ShaMap extends ShaMapInner {
  168. }
  169. exports.ShaMap = ShaMap;
  170. //# sourceMappingURL=shamap.js.map