MerkleTree.sol 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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. import {StorageSlot} from "../StorageSlot.sol";
  8. /**
  9. * @dev Library for managing https://wikipedia.org/wiki/Merkle_Tree[Merkle Tree] data structures.
  10. *
  11. * Each tree is a complete binary tree with the ability to sequentially insert leaves, changing them from a zero to a
  12. * non-zero value and updating its root. This structure allows inserting commitments (or other entries) that are not
  13. * stored, but can be proven to be part of the tree at a later time if the root is kept. See {MerkleProof}.
  14. *
  15. * A tree is defined by the following parameters:
  16. *
  17. * * Depth: The number of levels in the tree, it also defines the maximum number of leaves as 2**depth.
  18. * * Zero value: The value that represents an empty leaf. Used to avoid regular zero values to be part of the tree.
  19. * * Hashing function: A cryptographic hash function used to produce internal nodes. Defaults to {Hashes-commutativeKeccak256}.
  20. *
  21. * NOTE: Building trees using non-commutative hashing functions (i.e. `H(a, b) != H(b, a)`) is supported. However,
  22. * proving the inclusion of a leaf in such trees is not possible with the {MerkleProof} library since it only supports
  23. * _commutative_ hashing functions.
  24. *
  25. * _Available since v5.1._
  26. */
  27. library MerkleTree {
  28. /// @dev Error emitted when trying to update a leaf that was not previously pushed.
  29. error MerkleTreeUpdateInvalidIndex(uint256 index, uint256 length);
  30. /// @dev Error emitted when the proof used during an update is invalid (could not reproduce the side).
  31. error MerkleTreeUpdateInvalidProof();
  32. /**
  33. * @dev A complete `bytes32` Merkle tree.
  34. *
  35. * The `sides` and `zero` arrays are set to have a length equal to the depth of the tree during setup.
  36. *
  37. * Struct members have an underscore prefix indicating that they are "private" and should not be read or written to
  38. * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and
  39. * lead to unexpected behavior.
  40. *
  41. * NOTE: The `root` and the updates history is not stored within the tree. Consider using a secondary structure to
  42. * store a list of historical roots from the values returned from {setup} and {push} (e.g. a mapping, {BitMaps} or
  43. * {Checkpoints}).
  44. *
  45. * WARNING: Updating any of the tree's parameters after the first insertion will result in a corrupted tree.
  46. */
  47. struct Bytes32PushTree {
  48. uint256 _nextLeafIndex;
  49. bytes32[] _sides;
  50. bytes32[] _zeros;
  51. }
  52. /**
  53. * @dev Initialize a {Bytes32PushTree} using {Hashes-commutativeKeccak256} to hash internal nodes.
  54. * The capacity of the tree (i.e. number of leaves) is set to `2**treeDepth`.
  55. *
  56. * Calling this function on MerkleTree that was already setup and used will reset it to a blank state.
  57. *
  58. * Once a tree is setup, any push to it must use the same hashing function. This means that values
  59. * should be pushed to it using the default {xref-MerkleTree-push-struct-MerkleTree-Bytes32PushTree-bytes32-}[push] function.
  60. *
  61. * IMPORTANT: The zero value should be carefully chosen since it will be stored in the tree representing
  62. * empty leaves. It should be a value that is not expected to be part of the tree.
  63. */
  64. function setup(Bytes32PushTree storage self, uint8 treeDepth, bytes32 zero) internal returns (bytes32 initialRoot) {
  65. return setup(self, treeDepth, zero, Hashes.commutativeKeccak256);
  66. }
  67. /**
  68. * @dev Same as {xref-MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-}[setup], but allows to specify a custom hashing function.
  69. *
  70. * Once a tree is setup, any push to it must use the same hashing function. This means that values
  71. * should be pushed to it using the custom push function, which should be the same one as used during the setup.
  72. *
  73. * IMPORTANT: Providing a custom hashing function is a security-sensitive operation since it may
  74. * compromise the soundness of the tree.
  75. *
  76. * NOTE: Consider verifying that the hashing function does not manipulate the memory state directly and that it
  77. * follows the Solidity memory safety rules. Otherwise, it may lead to unexpected behavior.
  78. */
  79. function setup(
  80. Bytes32PushTree storage self,
  81. uint8 treeDepth,
  82. bytes32 zero,
  83. function(bytes32, bytes32) view returns (bytes32) fnHash
  84. ) internal returns (bytes32 initialRoot) {
  85. // Store depth in the dynamic array
  86. Arrays.unsafeSetLength(self._sides, treeDepth);
  87. Arrays.unsafeSetLength(self._zeros, treeDepth);
  88. // Build each root of zero-filled subtrees
  89. bytes32 currentZero = zero;
  90. for (uint256 i = 0; i < treeDepth; ++i) {
  91. Arrays.unsafeAccess(self._zeros, i).value = currentZero;
  92. currentZero = fnHash(currentZero, currentZero);
  93. }
  94. // Set the first root
  95. self._nextLeafIndex = 0;
  96. return currentZero;
  97. }
  98. /**
  99. * @dev Insert a new leaf in the tree, and compute the new root. Returns the position of the inserted leaf in the
  100. * tree, and the resulting root.
  101. *
  102. * Hashing the leaf before calling this function is recommended as a protection against
  103. * second pre-image attacks.
  104. *
  105. * This variant uses {Hashes-commutativeKeccak256} to hash internal nodes. It should only be used on merkle trees
  106. * that were setup using the same (default) hashing function (i.e. by calling
  107. * {xref-MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-}[the default setup] function).
  108. */
  109. function push(Bytes32PushTree storage self, bytes32 leaf) internal returns (uint256 index, bytes32 newRoot) {
  110. return push(self, leaf, Hashes.commutativeKeccak256);
  111. }
  112. /**
  113. * @dev Insert a new leaf in the tree, and compute the new root. Returns the position of the inserted leaf in the
  114. * tree, and the resulting root.
  115. *
  116. * Hashing the leaf before calling this function is recommended as a protection against
  117. * second pre-image attacks.
  118. *
  119. * This variant uses a custom hashing function to hash internal nodes. It should only be called with the same
  120. * function as the one used during the initial setup of the merkle tree.
  121. */
  122. function push(
  123. Bytes32PushTree storage self,
  124. bytes32 leaf,
  125. function(bytes32, bytes32) view returns (bytes32) fnHash
  126. ) internal returns (uint256 index, bytes32 newRoot) {
  127. // Cache read
  128. uint256 treeDepth = depth(self);
  129. // Get leaf index
  130. index = self._nextLeafIndex++;
  131. // Check if tree is full.
  132. if (index >= 1 << treeDepth) {
  133. Panic.panic(Panic.RESOURCE_ERROR);
  134. }
  135. // Rebuild branch from leaf to root
  136. uint256 currentIndex = index;
  137. bytes32 currentLevelHash = leaf;
  138. for (uint256 i = 0; i < treeDepth; i++) {
  139. // Reaching the parent node, is currentLevelHash the left child?
  140. bool isLeft = currentIndex % 2 == 0;
  141. // If so, next time we will come from the right, so we need to save it
  142. if (isLeft) {
  143. Arrays.unsafeAccess(self._sides, i).value = currentLevelHash;
  144. }
  145. // Compute the current node hash by using the hash function
  146. // with either its sibling (side) or the zero value for that level.
  147. currentLevelHash = fnHash(
  148. isLeft ? currentLevelHash : Arrays.unsafeAccess(self._sides, i).value,
  149. isLeft ? Arrays.unsafeAccess(self._zeros, i).value : currentLevelHash
  150. );
  151. // Update node index
  152. currentIndex >>= 1;
  153. }
  154. return (index, currentLevelHash);
  155. }
  156. /**
  157. * @dev Change the value of the leaf at position `index` from `oldValue` to `newValue`. Returns the recomputed "old"
  158. * root (before the update) and "new" root (after the update). The caller must verify that the reconstructed old
  159. * root is the last known one.
  160. *
  161. * The `proof` must be an up-to-date inclusion proof for the leaf being update. This means that this function is
  162. * vulnerable to front-running. Any {push} or {update} operation (that changes the root of the tree) would render
  163. * all "in flight" updates invalid.
  164. *
  165. * This variant uses {Hashes-commutativeKeccak256} to hash internal nodes. It should only be used on merkle trees
  166. * that were setup using the same (default) hashing function (i.e. by calling
  167. * {xref-MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-}[the default setup] function).
  168. */
  169. function update(
  170. Bytes32PushTree storage self,
  171. uint256 index,
  172. bytes32 oldValue,
  173. bytes32 newValue,
  174. bytes32[] memory proof
  175. ) internal returns (bytes32 oldRoot, bytes32 newRoot) {
  176. return update(self, index, oldValue, newValue, proof, Hashes.commutativeKeccak256);
  177. }
  178. /**
  179. * @dev Change the value of the leaf at position `index` from `oldValue` to `newValue`. Returns the recomputed "old"
  180. * root (before the update) and "new" root (after the update). The caller must verify that the reconstructed old
  181. * root is the last known one.
  182. *
  183. * The `proof` must be an up-to-date inclusion proof for the leaf being update. This means that this function is
  184. * vulnerable to front-running. Any {push} or {update} operation (that changes the root of the tree) would render
  185. * all "in flight" updates invalid.
  186. *
  187. * This variant uses a custom hashing function to hash internal nodes. It should only be called with the same
  188. * function as the one used during the initial setup of the merkle tree.
  189. */
  190. function update(
  191. Bytes32PushTree storage self,
  192. uint256 index,
  193. bytes32 oldValue,
  194. bytes32 newValue,
  195. bytes32[] memory proof,
  196. function(bytes32, bytes32) view returns (bytes32) fnHash
  197. ) internal returns (bytes32 oldRoot, bytes32 newRoot) {
  198. unchecked {
  199. // Check index range
  200. uint256 length = self._nextLeafIndex;
  201. if (index >= length) revert MerkleTreeUpdateInvalidIndex(index, length);
  202. // Cache read
  203. uint256 treeDepth = depth(self);
  204. // Workaround stack too deep
  205. bytes32[] storage sides = self._sides;
  206. // This cannot overflow because: 0 <= index < length
  207. uint256 lastIndex = length - 1;
  208. uint256 currentIndex = index;
  209. bytes32 currentLevelHashOld = oldValue;
  210. bytes32 currentLevelHashNew = newValue;
  211. for (uint32 i = 0; i < treeDepth; i++) {
  212. bool isLeft = currentIndex % 2 == 0;
  213. lastIndex >>= 1;
  214. currentIndex >>= 1;
  215. if (isLeft && currentIndex == lastIndex) {
  216. StorageSlot.Bytes32Slot storage side = Arrays.unsafeAccess(sides, i);
  217. if (side.value != currentLevelHashOld) revert MerkleTreeUpdateInvalidProof();
  218. side.value = currentLevelHashNew;
  219. }
  220. bytes32 sibling = proof[i];
  221. currentLevelHashOld = fnHash(
  222. isLeft ? currentLevelHashOld : sibling,
  223. isLeft ? sibling : currentLevelHashOld
  224. );
  225. currentLevelHashNew = fnHash(
  226. isLeft ? currentLevelHashNew : sibling,
  227. isLeft ? sibling : currentLevelHashNew
  228. );
  229. }
  230. return (currentLevelHashOld, currentLevelHashNew);
  231. }
  232. }
  233. /**
  234. * @dev Tree's depth (set at initialization)
  235. */
  236. function depth(Bytes32PushTree storage self) internal view returns (uint256) {
  237. return self._zeros.length;
  238. }
  239. }