MerkleTree.sol 7.7 KB

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