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>
This commit is contained in:
@ -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))
|
* `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))
|
* `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))
|
* `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.3.2 (2021-09-14)
|
||||||
|
|
||||||
|
|||||||
@ -12,4 +12,8 @@ contract MerkleProofWrapper {
|
|||||||
) public pure returns (bool) {
|
) public pure returns (bool) {
|
||||||
return MerkleProof.verify(proof, root, leaf);
|
return MerkleProof.verify(proof, root, leaf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function processProof(bytes32[] memory proof, bytes32 leaf) public pure returns (bytes32) {
|
||||||
|
return MerkleProof.processProof(proof, leaf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,11 +23,21 @@ library MerkleProof {
|
|||||||
bytes32 root,
|
bytes32 root,
|
||||||
bytes32 leaf
|
bytes32 leaf
|
||||||
) internal pure returns (bool) {
|
) 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++) {
|
for (uint256 i = 0; i < proof.length; i++) {
|
||||||
bytes32 proofElement = proof[i];
|
bytes32 proofElement = proof[i];
|
||||||
|
|
||||||
if (computedHash <= proofElement) {
|
if (computedHash <= proofElement) {
|
||||||
// Hash(current computed hash + current element of the proof)
|
// Hash(current computed hash + current element of the proof)
|
||||||
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
|
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
|
||||||
@ -36,8 +46,6 @@ library MerkleProof {
|
|||||||
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
|
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return computedHash;
|
||||||
// Check if the computed hash (root) is equal to the provided root
|
|
||||||
return computedHash == root;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user