MerkleTree.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. const jsStorage = require('./Storage')
  2. const hasherImpl = require('./MiMC')
  3. class MerkleTree {
  4. constructor(n_levels, zero_value, 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 = zero_value || 0
  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. let traverser = new PathTraverser(this.prefix, this.storage, this.zero_values)
  70. const root = await this.storage.get_or_element(
  71. MerkleTree.index_to_key(this.prefix, this.n_levels, 0),
  72. this.zero_values[this.n_levels],
  73. )
  74. const element = await this.storage.get_or_element(
  75. MerkleTree.index_to_key(this.prefix, 0, index),
  76. this.zero_values[0],
  77. )
  78. await this.traverse(index, traverser)
  79. return {
  80. root,
  81. path_elements: traverser.path_elements,
  82. path_index: traverser.path_index,
  83. element
  84. }
  85. }
  86. async update(index, element, insert = false) {
  87. if (!insert && index >= this.totalElements) {
  88. throw Error('Use insert method for new elements.')
  89. } else if(insert && index < this.totalElements) {
  90. throw Error('Use update method for existing elements.')
  91. }
  92. try {
  93. class UpdateTraverser {
  94. constructor(prefix, storage, hasher, element, zero_values) {
  95. this.prefix = prefix
  96. this.current_element = element
  97. this.zero_values = zero_values
  98. this.storage = storage
  99. this.hasher = hasher
  100. this.key_values_to_put = []
  101. }
  102. async handle_index(level, element_index, sibling_index) {
  103. if (level == 0) {
  104. this.original_element = await this.storage.get_or_element(
  105. MerkleTree.index_to_key(this.prefix, level, element_index),
  106. this.zero_values[level],
  107. )
  108. }
  109. const sibling = await this.storage.get_or_element(
  110. MerkleTree.index_to_key(this.prefix, level, sibling_index),
  111. this.zero_values[level],
  112. )
  113. let left, right
  114. if (element_index % 2 == 0) {
  115. left = this.current_element
  116. right = sibling
  117. } else {
  118. left = sibling
  119. right = this.current_element
  120. }
  121. this.key_values_to_put.push({
  122. key: MerkleTree.index_to_key(this.prefix, level, element_index),
  123. value: this.current_element,
  124. })
  125. this.current_element = this.hasher.hash(level, left, right)
  126. }
  127. }
  128. let traverser = new UpdateTraverser(
  129. this.prefix,
  130. this.storage,
  131. this.hasher,
  132. element,
  133. this.zero_values
  134. )
  135. await this.traverse(index, traverser)
  136. traverser.key_values_to_put.push({
  137. key: MerkleTree.index_to_key(this.prefix, this.n_levels, 0),
  138. value: traverser.current_element,
  139. })
  140. await this.storage.put_batch(traverser.key_values_to_put)
  141. } catch(e) {
  142. console.error(e)
  143. }
  144. }
  145. async insert(element) {
  146. const index = this.totalElements
  147. await this.update(index, element, true)
  148. this.totalElements++
  149. }
  150. async traverse(index, handler) {
  151. let current_index = index
  152. for (let i = 0; i < this.n_levels; i++) {
  153. let sibling_index = current_index
  154. if (current_index % 2 == 0) {
  155. sibling_index += 1
  156. } else {
  157. sibling_index -= 1
  158. }
  159. await handler.handle_index(i, current_index, sibling_index)
  160. current_index = Math.floor(current_index / 2)
  161. }
  162. }
  163. getIndexByElement(element) {
  164. for(let i = this.totalElements - 1; i >= 0; i--) {
  165. const elementFromTree = this.storage.get(MerkleTree.index_to_key(this.prefix, 0, i))
  166. if (elementFromTree === element) {
  167. return i
  168. }
  169. }
  170. return false
  171. }
  172. }
  173. module.exports = MerkleTree