Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a MerkleProof.processProof utility function #2841

Merged
merged 14 commits into from Oct 14, 2021
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -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)

Expand Down
4 changes: 4 additions & 0 deletions contracts/mocks/MerkleProofWrapper.sol
Expand Up @@ -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);
}
}
18 changes: 13 additions & 5 deletions contracts/utils/cryptography/MerkleProof.sol
Expand Up @@ -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));
Expand All @@ -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;
}
}