MerkleTree.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. const jsStorage = require('./Storage')
  2. const hasherImpl = require('./MiMC')
  3. class MerkleTree {
  4. constructor(n_levels, defaultElements, prefix, storage, hasher) {
  5. this.prefix = prefix
  6. this.storage = storage || new jsStorage()
  7. this.hasher = hasher || new hasherImpl()
  8. this.n_levels = n_levels
  9. this.zero_values = []
  10. this.totalElements = 0
  11. let current_zero_value = '21663839004416932945382355908790599225266501822907911457504978515578255421292'
  12. this.zero_values.push(current_zero_value)
  13. for (let i = 0; i < n_levels; i++) {
  14. current_zero_value = this.hasher.hash(i, current_zero_value, current_zero_value)
  15. this.zero_values.push(
  16. current_zero_value.toString(),
  17. )
  18. }
  19. if (defaultElements) {
  20. let level = 0
  21. this.totalElements = defaultElements.length
  22. defaultElements.forEach((element, i) => {
  23. this.storage.put(MerkleTree.index_to_key(prefix, level, i), element)
  24. })
  25. level++
  26. let numberOfElementsInLevel = Math.ceil(defaultElements.length / 2)
  27. for (level; level <= this.n_levels; level++) {
  28. for(let i = 0; i < numberOfElementsInLevel; i++) {
  29. const leftKey = MerkleTree.index_to_key(prefix, level - 1, 2 * i)
  30. const rightKey = MerkleTree.index_to_key(prefix, level - 1, 2 * i + 1)
  31. const left = this.storage.get(leftKey)
  32. const right = this.storage.get_or_element(rightKey, this.zero_values[level - 1])
  33. const subRoot = this.hasher.hash(null, left, right)
  34. this.storage.put(MerkleTree.index_to_key(prefix, level, i), subRoot)
  35. }
  36. numberOfElementsInLevel = Math.ceil(numberOfElementsInLevel / 2)
  37. }
  38. }
  39. }
  40. static index_to_key(prefix, level, index) {
  41. const key = `${prefix}_tree_${level}_${index}`
  42. return key
  43. }
  44. async root() {
  45. let root = await this.storage.get_or_element(
  46. MerkleTree.index_to_key(this.prefix, this.n_levels, 0),
  47. this.zero_values[this.n_levels],
  48. )
  49. return root
  50. }
  51. async path(index) {
  52. class PathTraverser {
  53. constructor(prefix, storage, zero_values) {
  54. this.prefix = prefix
  55. this.storage = storage
  56. this.zero_values = zero_values
  57. this.path_elements = []
  58. this.path_index = []
  59. }
  60. async handle_index(level, element_index, sibling_index) {
  61. const sibling = await this.storage.get_or_element(
  62. MerkleTree.index_to_key(this.prefix, level, sibling_index),
  63. this.zero_values[level],
  64. )
  65. this.path_elements.push(sibling)
  66. this.path_index.push(element_index % 2)
  67. }
  68. }
  69. index = Number(index)
  70. let traverser = new PathTraverser(this.prefix, this.storage, this.zero_values)
  71. const root = await this.storage.get_or_element(
  72. MerkleTree.index_to_key(this.prefix, this.n_levels, 0),
  73. this.zero_values[this.n_levels],
  74. )
  75. const element = await this.storage.get_or_element(
  76. MerkleTree.index_to_key(this.prefix, 0, index),
  77. this.zero_values[0],
  78. )
  79. await this.traverse(index, traverser)
  80. return {
  81. root,
  82. path_elements: traverser.path_elements,
  83. path_index: traverser.path_index,
  84. element
  85. }
  86. }
  87. async update(index, element, insert = false) {
  88. if (!insert && index >= this.totalElements) {
  89. throw Error('Use insert method for new elements.')
  90. } else if(insert && index < this.totalElements) {
  91. throw Error('Use update method for existing elements.')
  92. }
  93. try {
  94. class UpdateTraverser {
  95. constructor(prefix, storage, hasher, element, zero_values) {
  96. this.prefix = prefix
  97. this.current_element = element
  98. this.zero_values = zero_values
  99. this.storage = storage
  100. this.hasher = hasher
  101. this.key_values_to_put = []
  102. }
  103. async handle_index(level, element_index, sibling_index) {
  104. if (level == 0) {
  105. this.original_element = await this.storage.get_or_element(
  106. MerkleTree.index_to_key(this.prefix, level, element_index),
  107. this.zero_values[level],
  108. )
  109. }
  110. const sibling = await this.storage.get_or_element(
  111. MerkleTree.index_to_key(this.prefix, level, sibling_index),
  112. this.zero_values[level],
  113. )
  114. let left, right
  115. if (element_index % 2 == 0) {
  116. left = this.current_element
  117. right = sibling
  118. } else {
  119. left = sibling
  120. right = this.current_element
  121. }
  122. this.key_values_to_put.push({
  123. key: MerkleTree.index_to_key(this.prefix, level, element_index),
  124. value: this.current_element,
  125. })
  126. this.current_element = this.hasher.hash(level, left, right)
  127. }
  128. }
  129. let traverser = new UpdateTraverser(
  130. this.prefix,
  131. this.storage,
  132. this.hasher,
  133. element,
  134. this.zero_values
  135. )
  136. await this.traverse(index, traverser)
  137. traverser.key_values_to_put.push({
  138. key: MerkleTree.index_to_key(this.prefix, this.n_levels, 0),
  139. value: traverser.current_element,
  140. })
  141. await this.storage.put_batch(traverser.key_values_to_put)
  142. } catch(e) {
  143. console.error(e)
  144. }
  145. }
  146. async insert(element) {
  147. const index = this.totalElements
  148. await this.update(index, element, true)
  149. this.totalElements++
  150. }
  151. async traverse(index, handler) {
  152. let current_index = index
  153. for (let i = 0; i < this.n_levels; i++) {
  154. let sibling_index = current_index
  155. if (current_index % 2 == 0) {
  156. sibling_index += 1
  157. } else {
  158. sibling_index -= 1
  159. }
  160. await handler.handle_index(i, current_index, sibling_index)
  161. current_index = Math.floor(current_index / 2)
  162. }
  163. }
  164. getIndexByElement(element) {
  165. for(let i = this.totalElements - 1; i >= 0; i--) {
  166. const elementFromTree = this.storage.get(MerkleTree.index_to_key(this.prefix, 0, i))
  167. if (elementFromTree === element) {
  168. return i
  169. }
  170. }
  171. return false
  172. }
  173. }
  174. module.exports = MerkleTree