MerkleTree.sol 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.0;
  3. import {Hashes} from "../cryptography/Hashes.sol";
  4. import {Arrays} from "../Arrays.sol";
  5. import {Panic} from "../Panic.sol";
  6. /**
  7. * @dev Library for managing https://wikipedia.org/wiki/Merkle_Tree[Merkle Tree] data structures.
  8. *
  9. * Each tree is a complete binary tree with the ability to sequentially insert leaves, changing them from a zero to a
  10. * non-zero value and updating its root. This structure allows inserting commitments (or other entries) that are not
  11. * stored, but can be proven to be part of the tree at a later time. See {MerkleProof}.
  12. *
  13. * A tree is defined by the following parameters:
  14. *
  15. * * Depth: The number of levels in the tree, it also defines the maximum number of leaves as 2**depth.
  16. * * Zero value: The value that represents an empty leaf. Used to avoid regular zero values to be part of the tree.
  17. * * Hashing function: A cryptographic hash function used to produce internal nodes.
  18. *
  19. * _Available since v5.1._
  20. */
  21. library MerkleTree {
  22. /**
  23. * @dev A complete `bytes32` Merkle tree.
  24. *
  25. * The `sides` and `zero` arrays are set to have a length equal to the depth of the tree during setup.
  26. *
  27. * The hashing function used during initialization to compute the `zeros` values (value of a node at a given depth
  28. * for which the subtree is full of zero leaves). This function is kept in the structure for handling insertions.
  29. *
  30. * Struct members have an underscore prefix indicating that they are "private" and should not be read or written to
  31. * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and
  32. * lead to unexpected behavior.
  33. *
  34. * NOTE: The `root` is kept up to date after each insertion without keeping track of its history. Consider
  35. * using a secondary structure to store a list of historical roots (e.g. a mapping, {BitMaps} or {Checkpoints}).
  36. *
  37. * WARNING: Updating any of the tree's parameters after the first insertion will result in a corrupted tree.
  38. */
  39. struct Bytes32PushTree {
  40. bytes32 _root;
  41. uint256 _nextLeafIndex;
  42. bytes32[] _sides;
  43. bytes32[] _zeros;
  44. function(bytes32, bytes32) view returns (bytes32) _fnHash;
  45. }
  46. /**
  47. * @dev Initialize a {Bytes32PushTree} using {Hashes-commutativeKeccak256} to hash internal nodes.
  48. * The capacity of the tree (i.e. number of leaves) is set to `2**levels`.
  49. *
  50. * Calling this function on MerkleTree that was already setup and used will reset it to a blank state.
  51. *
  52. * IMPORTANT: The zero value should be carefully chosen since it will be stored in the tree representing
  53. * empty leaves. It should be a value that is not expected to be part of the tree.
  54. */
  55. function setup(Bytes32PushTree storage self, uint8 levels, bytes32 zero) internal {
  56. return setup(self, levels, zero, Hashes.commutativeKeccak256);
  57. }
  58. /**
  59. * @dev Same as {setup}, but allows to specify a custom hashing function.
  60. *
  61. * IMPORTANT: Providing a custom hashing function is a security-sensitive operation since it may
  62. * compromise the soundness of the tree. Consider using functions from {Hashes}.
  63. */
  64. function setup(
  65. Bytes32PushTree storage self,
  66. uint8 levels,
  67. bytes32 zero,
  68. function(bytes32, bytes32) view returns (bytes32) fnHash
  69. ) internal {
  70. // Store depth in the dynamic array
  71. Arrays.unsafeSetLength(self._sides, levels);
  72. Arrays.unsafeSetLength(self._zeros, levels);
  73. // Build each root of zero-filled subtrees
  74. bytes32 currentZero = zero;
  75. for (uint32 i = 0; i < levels; ++i) {
  76. Arrays.unsafeAccess(self._zeros, i).value = currentZero;
  77. currentZero = fnHash(currentZero, currentZero);
  78. }
  79. // Set the first root
  80. self._root = currentZero;
  81. self._nextLeafIndex = 0;
  82. self._fnHash = fnHash;
  83. }
  84. /**
  85. * @dev Insert a new leaf in the tree, and compute the new root. Returns the position of the inserted leaf in the
  86. * tree, and the resulting root.
  87. *
  88. * Hashing the leaf before calling this function is recommended as a protection against
  89. * second pre-image attacks.
  90. */
  91. function push(Bytes32PushTree storage self, bytes32 leaf) internal returns (uint256 index, bytes32 newRoot) {
  92. // Cache read
  93. uint256 levels = self._zeros.length;
  94. function(bytes32, bytes32) view returns (bytes32) fnHash = self._fnHash;
  95. // Get leaf index
  96. uint256 leafIndex = self._nextLeafIndex++;
  97. // Check if tree is full.
  98. if (leafIndex >= 1 << levels) {
  99. Panic.panic(Panic.RESOURCE_ERROR);
  100. }
  101. // Rebuild branch from leaf to root
  102. uint256 currentIndex = leafIndex;
  103. bytes32 currentLevelHash = leaf;
  104. for (uint32 i = 0; i < levels; i++) {
  105. // Reaching the parent node, is currentLevelHash the left child?
  106. bool isLeft = currentIndex % 2 == 0;
  107. // If so, next time we will come from the right, so we need to save it
  108. if (isLeft) {
  109. Arrays.unsafeAccess(self._sides, i).value = currentLevelHash;
  110. }
  111. // Compute the current node hash by using the hash function
  112. // with either the its sibling (side) or the zero value for that level.
  113. currentLevelHash = fnHash(
  114. isLeft ? currentLevelHash : Arrays.unsafeAccess(self._sides, i).value,
  115. isLeft ? Arrays.unsafeAccess(self._zeros, i).value : currentLevelHash
  116. );
  117. // Update node index
  118. currentIndex >>= 1;
  119. }
  120. // Record new root
  121. self._root = currentLevelHash;
  122. return (leafIndex, currentLevelHash);
  123. }
  124. /**
  125. * @dev Tree's current root
  126. */
  127. function root(Bytes32PushTree storage self) internal view returns (bytes32) {
  128. return self._root;
  129. }
  130. /**
  131. * @dev Tree's depth (set at initialization)
  132. */
  133. function depth(Bytes32PushTree storage self) internal view returns (uint256) {
  134. return self._zeros.length;
  135. }
  136. }