Browse Source

Add a MerkleProof.processProof utility function (#2841)

* Add a MerkleProof.processProof utility function

* Add changelog entry

* fix lint

* return index when processingProof

* fix lint

* fix test

* Apply suggestions from code review

Co-authored-by: Francisco Giordano <frangio.1@gmail.com>

* improve documentation

* Apply suggestions from code review

Co-authored-by: Francisco Giordano <frangio.1@gmail.com>

* remove index - see discussion in the PR

* update changelog

Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
Hadrien Croubois 4 years ago
parent
commit
d244b81972

+ 1 - 0
CHANGELOG.md

@@ -10,6 +10,7 @@
  * `Governor`: shift vote start and end by one block to better match Compound's GovernorBravo and prevent voting at the Governor level if the voting snapshot is not ready. ([#2892](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/#2892))
  * `PaymentSplitter`: now supports ERC20 assets in addition to Ether. ([#2858](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/#2858))
  * `ECDSA`: add a variant of `toEthSignedMessageHash` for arbitrary length message hashing. ([#2865](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/#2865))
+ * `MerkleProof`: add a `processProof` function that returns the rebuilt root hash given a leaf and a proof. ([#2841](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2841))
 
 ## 4.3.2 (2021-09-14)
 

+ 4 - 0
contracts/mocks/MerkleProofWrapper.sol

@@ -12,4 +12,8 @@ contract MerkleProofWrapper {
     ) public pure returns (bool) {
         return MerkleProof.verify(proof, root, leaf);
     }
+
+    function processProof(bytes32[] memory proof, bytes32 leaf) public pure returns (bytes32) {
+        return MerkleProof.processProof(proof, leaf);
+    }
 }

+ 13 - 5
contracts/utils/cryptography/MerkleProof.sol

@@ -23,11 +23,21 @@ library MerkleProof {
         bytes32 root,
         bytes32 leaf
     ) internal pure returns (bool) {
-        bytes32 computedHash = leaf;
+        return processProof(proof, leaf) == root;
+    }
 
+    /**
+     * @dev Returns the rebuilt hash obtained by traversing a Merklee tree up
+     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
+     * hash matches the root of the tree. When processing the proof, the pairs
+     * of leafs & pre-images are assumed to be sorted.
+     *
+     * _Available since v4.4._
+     */
+    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
+        bytes32 computedHash = leaf;
         for (uint256 i = 0; i < proof.length; i++) {
             bytes32 proofElement = proof[i];
-
             if (computedHash <= proofElement) {
                 // Hash(current computed hash + current element of the proof)
                 computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
@@ -36,8 +46,6 @@ library MerkleProof {
                 computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
             }
         }
-
-        // Check if the computed hash (root) is equal to the provided root
-        return computedHash == root;
+        return computedHash;
     }
 }