diff --git a/docs/utils/merkletreelib.md b/docs/utils/merkletreelib.md index e04334cb01..1cae65ad48 100644 --- a/docs/utils/merkletreelib.md +++ b/docs/utils/merkletreelib.md @@ -5,11 +5,11 @@ Library for generating Merkle trees. Note: -- Leafs are NOT auto hashed. Note that some libraries hash the leafs by default. +- Leaves are NOT auto hashed. Note that some libraries hash the leaves by default. We leave it up to you to decide if this is needed. -If your leafs are 64 bytes long, do hash them first for safety. +If your leaves are 64 bytes long, do hash them first for safety. See: https://www.rareskills.io/post/merkle-tree-second-preimage-attack -- Leafs are NOT auto globally sorted. Note that some libraries sort the leafs by default. +- Leaves are NOT auto globally sorted. Note that some libraries sort the leaves by default. - The pair hash is pair-sorted-keccak256, which works out-of-the-box with `MerkleProofLib`. - This library is NOT equivalent to OpenZeppelin or Murky. Equivalence is NOT required if you are just using this for pure Solidity testing. @@ -21,10 +21,10 @@ May be relevant for differential testing between Solidity vs external libraries. ## Custom Errors -### MerkleTreeLeafsEmpty() +### MerkleTreeLeavesEmpty() ```solidity -error MerkleTreeLeafsEmpty() +error MerkleTreeLeavesEmpty() ``` At least 1 leaf is required to build the tree. @@ -36,7 +36,7 @@ error MerkleTreeOutOfBoundsAccess() ``` Attempt to access a node with an out-of-bounds index. -Check if the tree has been built and has sufficient leafs and nodes. +Check if the tree has been built and has sufficient leaves and nodes. ### MerkleTreeInvalidLeafIndices() @@ -51,35 +51,38 @@ Leaf indices for multi proof must be strictly ascending and not empty. ### build(bytes32[]) ```solidity -function build(bytes32[] memory leafs) +function build(bytes32[] memory leaves) internal pure - returns (bytes32[] memory result) + returns (bytes32[] memory tree) ``` Builds and return a complete Merkle tree. -To make it a full Merkle tree, use `build(pad(leafs))`. +To make it a full Merkle tree, use `build(pad(leaves))`. ### root(bytes32[]) ```solidity -function root(bytes32[] memory t) internal pure returns (bytes32 result) +function root(bytes32[] memory tree) + internal + pure + returns (bytes32 result) ``` Returns the root. -### numLeafs(bytes32[]) +### numLeaves(bytes32[]) ```solidity -function numLeafs(bytes32[] memory t) internal pure returns (uint256) +function numLeaves(bytes32[] memory tree) internal pure returns (uint256) ``` -Returns the number of leafs. +Returns the number of leaves. ### numInternalNodes(bytes32[]) ```solidity -function numInternalNodes(bytes32[] memory t) +function numInternalNodes(bytes32[] memory tree) internal pure returns (uint256) @@ -90,7 +93,7 @@ Returns the number of internal nodes. ### leaf(bytes32[],uint256) ```solidity -function leaf(bytes32[] memory t, uint256 leafIndex) +function leaf(bytes32[] memory tree, uint256 leafIndex) internal pure returns (bytes32 result) @@ -98,10 +101,21 @@ function leaf(bytes32[] memory t, uint256 leafIndex) Returns the leaf at `leafIndex`. +### gatherLeaves(bytes32[],uint256[]) + +```solidity +function gatherLeaves(bytes32[] memory tree, uint256[] memory leafIndices) + internal + pure + returns (bytes32[] memory result) +``` + +Returns the leaves at `leafIndices`. + ### leafProof(bytes32[],uint256) ```solidity -function leafProof(bytes32[] memory t, uint256 leafIndex) +function leafProof(bytes32[] memory tree, uint256 leafIndex) internal pure returns (bytes32[] memory result) @@ -112,7 +126,7 @@ Returns the proof for the leaf at `leafIndex`. ### nodeProof(bytes32[],uint256) ```solidity -function nodeProof(bytes32[] memory t, uint256 nodeIndex) +function nodeProof(bytes32[] memory tree, uint256 nodeIndex) internal pure returns (bytes32[] memory result) @@ -121,36 +135,36 @@ function nodeProof(bytes32[] memory t, uint256 nodeIndex) Returns the proof for the node at `nodeIndex`. This function can be used to prove the existence of internal nodes. -### leafsMultiProof(bytes32[],uint256[]) +### multiProofForLeaves(bytes32[],uint256[]) ```solidity -function leafsMultiProof(bytes32[] memory t, uint256[] memory leafIndices) - internal - pure - returns (bytes32[] memory proof, bool[] memory flags) +function multiProofForLeaves( + bytes32[] memory tree, + uint256[] memory leafIndices +) internal pure returns (bytes32[] memory proof, bool[] memory flags) ``` -Returns proof and corresponding flags for multiple leafs. +Returns proof and corresponding flags for multiple leaves. The `leafIndices` must be non-empty and sorted in strictly ascending order. ### pad(bytes32[],bytes32) ```solidity -function pad(bytes32[] memory leafs, bytes32 defaultFill) +function pad(bytes32[] memory leaves, bytes32 defaultFill) internal pure returns (bytes32[] memory result) ``` -Returns a copy of leafs, with the length padded to a power of 2. +Returns a copy of leaves, with the length padded to a power of 2. ### pad(bytes32[]) ```solidity -function pad(bytes32[] memory leafs) +function pad(bytes32[] memory leaves) internal pure returns (bytes32[] memory result) ``` -Equivalent to `pad(leafs, bytes32(0))`. \ No newline at end of file +Equivalent to `pad(leaves, bytes32(0))`. \ No newline at end of file diff --git a/src/utils/MerkleTreeLib.sol b/src/utils/MerkleTreeLib.sol index 72a0850a2f..6d12bec529 100644 --- a/src/utils/MerkleTreeLib.sol +++ b/src/utils/MerkleTreeLib.sol @@ -5,11 +5,11 @@ pragma solidity ^0.8.4; /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/MerkleTreeLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/merkle-tree/blob/master/src/core.ts) /// @dev Note: -/// - Leafs are NOT auto hashed. Note that some libraries hash the leafs by default. +/// - Leaves are NOT auto hashed. Note that some libraries hash the leaves by default. /// We leave it up to you to decide if this is needed. -/// If your leafs are 64 bytes long, do hash them first for safety. +/// If your leaves are 64 bytes long, do hash them first for safety. /// See: https://www.rareskills.io/post/merkle-tree-second-preimage-attack -/// - Leafs are NOT auto globally sorted. Note that some libraries sort the leafs by default. +/// - Leaves are NOT auto globally sorted. Note that some libraries sort the leaves by default. /// - The pair hash is pair-sorted-keccak256, which works out-of-the-box with `MerkleProofLib`. /// - This library is NOT equivalent to OpenZeppelin or Murky. /// Equivalence is NOT required if you are just using this for pure Solidity testing. @@ -20,10 +20,10 @@ library MerkleTreeLib { /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev At least 1 leaf is required to build the tree. - error MerkleTreeLeafsEmpty(); + error MerkleTreeLeavesEmpty(); /// @dev Attempt to access a node with an out-of-bounds index. - /// Check if the tree has been built and has sufficient leafs and nodes. + /// Check if the tree has been built and has sufficient leaves and nodes. error MerkleTreeOutOfBoundsAccess(); /// @dev Leaf indices for multi proof must be strictly ascending and not empty. @@ -34,24 +34,24 @@ library MerkleTreeLib { /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Builds and return a complete Merkle tree. - /// To make it a full Merkle tree, use `build(pad(leafs))`. - function build(bytes32[] memory leafs) internal pure returns (bytes32[] memory result) { + /// To make it a full Merkle tree, use `build(pad(leaves))`. + function build(bytes32[] memory leaves) internal pure returns (bytes32[] memory tree) { /// @solidity memory-safe-assembly assembly { - result := mload(0x40) // `nodes`. - let l := mload(leafs) + tree := mload(0x40) // `nodes`. + let l := mload(leaves) if iszero(l) { - mstore(0x00, 0x089aff6e) // `MerkleTreeLeafsEmpty()`. + mstore(0x00, 0xe7171dc4) // `MerkleTreeLeavesEmpty()`. revert(0x1c, 0x04) } let n := sub(add(l, l), 1) - mstore(result, n) // `.length`. - let nodes := add(result, 0x20) + mstore(tree, n) // `.length`. + let nodes := add(tree, 0x20) let f := add(nodes, shl(5, n)) mstore(0x40, f) // Allocate memory. let e := add(0x20, shl(5, l)) for { let i := 0x20 } 1 {} { - mstore(sub(f, i), mload(add(leafs, i))) + mstore(sub(f, i), mload(add(leaves, i))) i := add(i, 0x20) if eq(i, e) { break } } @@ -71,44 +71,75 @@ library MerkleTreeLib { } /// @dev Returns the root. - function root(bytes32[] memory t) internal pure returns (bytes32 result) { + function root(bytes32[] memory tree) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { - result := mload(add(0x20, t)) - if iszero(mload(t)) { + result := mload(add(0x20, tree)) + if iszero(mload(tree)) { mstore(0x00, 0x7a856a38) // `MerkleTreeOutOfBoundsAccess()`. revert(0x1c, 0x04) } } } - /// @dev Returns the number of leafs. - function numLeafs(bytes32[] memory t) internal pure returns (uint256) { + /// @dev Returns the number of leaves. + function numLeaves(bytes32[] memory tree) internal pure returns (uint256) { unchecked { - return t.length - (t.length >> 1); + return tree.length - (tree.length >> 1); } } /// @dev Returns the number of internal nodes. - function numInternalNodes(bytes32[] memory t) internal pure returns (uint256) { - return t.length >> 1; + function numInternalNodes(bytes32[] memory tree) internal pure returns (uint256) { + return tree.length >> 1; } /// @dev Returns the leaf at `leafIndex`. - function leaf(bytes32[] memory t, uint256 leafIndex) internal pure returns (bytes32 result) { + function leaf(bytes32[] memory tree, uint256 leafIndex) + internal + pure + returns (bytes32 result) + { /// @solidity memory-safe-assembly assembly { - let n := mload(t) + let n := mload(tree) if iszero(lt(leafIndex, sub(n, shr(1, n)))) { mstore(0x00, 0x7a856a38) // `MerkleTreeOutOfBoundsAccess()`. revert(0x1c, 0x04) } - result := mload(add(t, shl(5, sub(n, leafIndex)))) + result := mload(add(tree, shl(5, sub(n, leafIndex)))) + } + } + + /// @dev Returns the leaves at `leafIndices`. + function gatherLeaves(bytes32[] memory tree, uint256[] memory leafIndices) + internal + pure + returns (bytes32[] memory result) + { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + let l := mload(leafIndices) + mstore(result, l) // `.length`. + let d := sub(leafIndices, result) + let n := mload(tree) + let o := add(result, 0x20) + for { let i := 0 } iszero(eq(i, l)) { i := add(i, 1) } { + let j := add(o, shl(5, i)) + let leafIndex := mload(add(j, d)) + if iszero(lt(leafIndex, sub(n, shr(1, n)))) { + mstore(0x00, 0x7a856a38) // `MerkleTreeOutOfBoundsAccess()`. + revert(0x1c, 0x04) + } + mstore(j, mload(add(tree, shl(5, sub(n, leafIndex))))) + } + mstore(0x40, add(o, shl(5, l))) // Allocate memory. } } /// @dev Returns the proof for the leaf at `leafIndex`. - function leafProof(bytes32[] memory t, uint256 leafIndex) + function leafProof(bytes32[] memory tree, uint256 leafIndex) internal pure returns (bytes32[] memory result) @@ -116,16 +147,16 @@ library MerkleTreeLib { uint256 nodeIndex; /// @solidity memory-safe-assembly assembly { - let n := mload(t) + let n := mload(tree) nodeIndex := sub(n, add(1, leafIndex)) if iszero(lt(leafIndex, sub(n, shr(1, n)))) { nodeIndex := not(0) } } - result = nodeProof(t, nodeIndex); + result = nodeProof(tree, nodeIndex); } /// @dev Returns the proof for the node at `nodeIndex`. /// This function can be used to prove the existence of internal nodes. - function nodeProof(bytes32[] memory t, uint256 nodeIndex) + function nodeProof(bytes32[] memory tree, uint256 nodeIndex) internal pure returns (bytes32[] memory result) @@ -133,13 +164,13 @@ library MerkleTreeLib { /// @solidity memory-safe-assembly assembly { result := mload(0x40) - if iszero(lt(nodeIndex, mload(t))) { + if iszero(lt(nodeIndex, mload(tree))) { mstore(0x00, 0x7a856a38) // `MerkleTreeOutOfBoundsAccess()`. revert(0x1c, 0x04) } let o := add(result, 0x20) for { let i := nodeIndex } i { i := shr(1, sub(i, 1)) } { - mstore(o, mload(add(t, shl(5, add(i, shl(1, and(1, i))))))) + mstore(o, mload(add(tree, shl(5, add(i, shl(1, and(1, i))))))) o := add(o, 0x20) } mstore(0x40, o) // Allocate memory. @@ -147,9 +178,9 @@ library MerkleTreeLib { } } - /// @dev Returns proof and corresponding flags for multiple leafs. + /// @dev Returns proof and corresponding flags for multiple leaves. /// The `leafIndices` must be non-empty and sorted in strictly ascending order. - function leafsMultiProof(bytes32[] memory t, uint256[] memory leafIndices) + function multiProofForLeaves(bytes32[] memory tree, uint256[] memory leafIndices) internal pure returns (bytes32[] memory proof, bool[] memory flags) @@ -163,7 +194,7 @@ library MerkleTreeLib { let b_ := 0 // Start index of circular buffer. for { let n_ := mload(t_) // Num nodes. - let l_ := sub(n_, shr(1, n_)) // Num leafs. + let l_ := sub(n_, shr(1, n_)) // Num leaves. let p_ := not(0) let i_ := 0 } 1 {} { @@ -207,18 +238,18 @@ library MerkleTreeLib { mstore(0x00, 0xe9729976) // `MerkleTreeInvalidLeafIndices()`. revert(0x1c, 0x04) } - let flagsLen, proofLen := gen(leafIndices, t, 0x00, 0x00) + let flagsLen, proofLen := gen(leafIndices, tree, 0x00, 0x00) proof := mload(0x40) mstore(proof, proofLen) flags := add(add(proof, 0x20), shl(5, proofLen)) mstore(flags, flagsLen) mstore(0x40, add(add(flags, 0x20), shl(5, flagsLen))) // Allocate memory. - flagsLen, proofLen := gen(leafIndices, t, proof, flags) + flagsLen, proofLen := gen(leafIndices, tree, proof, flags) } } - /// @dev Returns a copy of leafs, with the length padded to a power of 2. - function pad(bytes32[] memory leafs, bytes32 defaultFill) + /// @dev Returns a copy of leaves, with the length padded to a power of 2. + function pad(bytes32[] memory leaves, bytes32 defaultFill) internal pure returns (bytes32[] memory result) @@ -226,20 +257,20 @@ library MerkleTreeLib { /// @solidity memory-safe-assembly assembly { result := mload(0x40) - let l := mload(leafs) + let l := mload(leaves) if iszero(l) { - mstore(0x00, 0x089aff6e) // `MerkleTreeLeafsEmpty()`. + mstore(0x00, 0xe7171dc4) // `MerkleTreeLeavesEmpty()`. revert(0x1c, 0x04) } let p := 1 // Padded length. for {} lt(p, l) {} { p := add(p, p) } mstore(result, p) // Store length. mstore(0x40, add(result, add(0x20, shl(5, p)))) // Allocate memory. - let d := sub(result, leafs) - let copyEnd := add(add(leafs, 0x20), shl(5, l)) - let end := add(add(leafs, 0x20), shl(5, p)) + let d := sub(result, leaves) + let copyEnd := add(add(leaves, 0x20), shl(5, l)) + let end := add(add(leaves, 0x20), shl(5, p)) mstore(0x00, defaultFill) - for { let i := add(leafs, 0x20) } 1 {} { + for { let i := add(leaves, 0x20) } 1 {} { mstore(add(i, d), mload(mul(i, lt(i, copyEnd)))) i := add(i, 0x20) if eq(i, end) { break } @@ -247,8 +278,8 @@ library MerkleTreeLib { } } - /// @dev Equivalent to `pad(leafs, bytes32(0))`. - function pad(bytes32[] memory leafs) internal pure returns (bytes32[] memory result) { - result = pad(leafs, bytes32(0)); + /// @dev Equivalent to `pad(leaves, bytes32(0))`. + function pad(bytes32[] memory leaves) internal pure returns (bytes32[] memory result) { + result = pad(leaves, bytes32(0)); } } diff --git a/test/MerkleTreeLib.t.sol b/test/MerkleTreeLib.t.sol index b34adfdac0..bdfbf09aa3 100644 --- a/test/MerkleTreeLib.t.sol +++ b/test/MerkleTreeLib.t.sol @@ -12,48 +12,48 @@ contract MerkleTreeLibTest is SoladyTest { using MerkleTreeLib for bytes32[]; using LibPRNG for *; - function testBuildCompleteMerkleTree(bytes32[] memory leafs, bytes32 r) public { + function testBuildCompleteMerkleTree(bytes32[] memory leaves, bytes32 r) public { _maybeBrutalizeMemory(r); - if (leafs.length <= 1) { - leafs = new bytes32[](1); - leafs[0] = r; + if (leaves.length <= 1) { + leaves = new bytes32[](1); + leaves[0] = r; } - bytes32[] memory t = MerkleTreeLib.build(leafs); - assertEq(t.length, leafs.length * 2 - 1); - if (leafs.length == 1) { + bytes32[] memory t = MerkleTreeLib.build(leaves); + assertEq(t.length, leaves.length * 2 - 1); + if (leaves.length == 1) { assertEq(t[0], r); } else { assertNotEq(t[0], 0); } assertEq(t.root(), t[0]); - assertEq(leafs.length, t.numLeafs()); - assertEq(t.length, t.numLeafs() + t.numInternalNodes()); + assertEq(leaves.length, t.numLeaves()); + assertEq(t.length, t.numLeaves() + t.numInternalNodes()); _checkMemory(t); - if (leafs.length >= 1) { - uint256 i = _randomUniform() % leafs.length; - assertEq(t.leaf(i), leafs[i]); + if (leaves.length >= 1) { + uint256 i = _randomUniform() % leaves.length; + assertEq(t.leaf(i), leaves[i]); } } - function testPad(bytes32[] memory leafs, bytes32 defaultFill, uint256 r) public { + function testPad(bytes32[] memory leaves, bytes32 defaultFill, uint256 r) public { _maybeBrutalizeMemory(r); - if (leafs.length == 0) return; - assertEq(MerkleTreeLib.pad(leafs, defaultFill), _padOriginal(leafs, defaultFill)); + if (leaves.length == 0) return; + assertEq(MerkleTreeLib.pad(leaves, defaultFill), _padOriginal(leaves, defaultFill)); _checkMemory(); } - function _padOriginal(bytes32[] memory leafs, bytes32 defaultFill) + function _padOriginal(bytes32[] memory leaves, bytes32 defaultFill) internal pure returns (bytes32[] memory result) { unchecked { uint256 p = 1; - while (p < leafs.length) p = p << 1; + while (p < leaves.length) p = p << 1; result = new bytes32[](p); for (uint256 i; i < p; ++i) { - if (i < leafs.length) { - result[i] = leafs[i]; + if (i < leaves.length) { + result[i] = leaves[i]; } else { result[i] = defaultFill; } @@ -71,87 +71,87 @@ contract MerkleTreeLibTest is SoladyTest { if (h & 0x0f == 0) _brutalizeMemory(); } - function testBuildAndGetLeaf(bytes32[] memory leafs, uint256 leafIndex) public { - if (leafs.length == 0) return; + function testBuildAndGetLeaf(bytes32[] memory leaves, uint256 leafIndex) public { + if (leaves.length == 0) return; - if (leafIndex < leafs.length) { - assertEq(this.buildAndGetLeaf(leafs, leafIndex), leafs[leafIndex]); + if (leafIndex < leaves.length) { + assertEq(this.buildAndGetLeaf(leaves, leafIndex), leaves[leafIndex]); } else { vm.expectRevert(MerkleTreeLib.MerkleTreeOutOfBoundsAccess.selector); - this.buildAndGetLeaf(leafs, leafIndex); + this.buildAndGetLeaf(leaves, leafIndex); } } - function buildAndGetLeaf(bytes32[] memory leafs, uint256 leafIndex) + function buildAndGetLeaf(bytes32[] memory leaves, uint256 leafIndex) public pure returns (bytes32) { - return MerkleTreeLib.build(leafs).leaf(leafIndex); + return MerkleTreeLib.build(leaves).leaf(leafIndex); } - function _maybePad(bytes32[] memory leafs) internal returns (bytes32[] memory) { + function _maybePad(bytes32[] memory leaves) internal returns (bytes32[] memory) { if (_randomChance(2)) { if (_randomChance(2)) { - return leafs.pad(); + return leaves.pad(); } - return leafs.pad(bytes32(_random())); + return leaves.pad(bytes32(_random())); } - return leafs; + return leaves; } - function testBuildAndGetLeafProof(bytes32[] memory leafs, uint256 leafIndex) public { - if (leafs.length == 0) return _testBuildAndGetRoot(leafs); - leafs = _maybePad(leafs); - bytes32[] memory t = MerkleTreeLib.build(leafs); - if (leafIndex < leafs.length) { - bytes32[] memory proof = this.buildAndGetLeafProof(leafs, leafIndex); - assertTrue(MerkleProofLib.verify(proof, t.root(), leafs[leafIndex])); + function testBuildAndGetLeafProof(bytes32[] memory leaves, uint256 leafIndex) public { + if (leaves.length == 0) return _testBuildAndGetRoot(leaves); + leaves = _maybePad(leaves); + bytes32[] memory t = MerkleTreeLib.build(leaves); + if (leafIndex < leaves.length) { + bytes32[] memory proof = this.buildAndGetLeafProof(leaves, leafIndex); + assertTrue(MerkleProofLib.verify(proof, t.root(), leaves[leafIndex])); } else { vm.expectRevert(MerkleTreeLib.MerkleTreeOutOfBoundsAccess.selector); - this.buildAndGetLeafProof(leafs, leafIndex); + this.buildAndGetLeafProof(leaves, leafIndex); } } - function buildAndGetLeafProof(bytes32[] memory leafs, uint256 leafIndex) + function buildAndGetLeafProof(bytes32[] memory leaves, uint256 leafIndex) public pure returns (bytes32[] memory proof) { - bytes32[] memory t = MerkleTreeLib.build(leafs); + bytes32[] memory t = MerkleTreeLib.build(leaves); proof = t.leafProof(leafIndex); _checkMemory(); } - function testBuildAndGetNodeProof(bytes32[] memory leafs, uint256 nodeIndex) public { - if (leafs.length == 0) return _testBuildAndGetRoot(leafs); - bytes32[] memory t = MerkleTreeLib.build(leafs); + function testBuildAndGetNodeProof(bytes32[] memory leaves, uint256 nodeIndex) public { + if (leaves.length == 0) return _testBuildAndGetRoot(leaves); + bytes32[] memory t = MerkleTreeLib.build(leaves); if (nodeIndex < t.length) { - bytes32[] memory proof = this.buildAndGetNodeProof(leafs, nodeIndex); + bytes32[] memory proof = this.buildAndGetNodeProof(leaves, nodeIndex); assertTrue(MerkleProofLib.verify(proof, t.root(), t[nodeIndex])); } else { vm.expectRevert(MerkleTreeLib.MerkleTreeOutOfBoundsAccess.selector); - this.buildAndGetNodeProof(leafs, nodeIndex); + this.buildAndGetNodeProof(leaves, nodeIndex); } } - function buildAndGetNodeProof(bytes32[] memory leafs, uint256 nodeIndex) + function buildAndGetNodeProof(bytes32[] memory leaves, uint256 nodeIndex) public pure returns (bytes32[] memory proof) { - bytes32[] memory t = MerkleTreeLib.build(leafs); + bytes32[] memory t = MerkleTreeLib.build(leaves); proof = t.nodeProof(nodeIndex); _checkMemory(); } - function _testBuildAndGetRoot(bytes32[] memory leafs) internal { - vm.expectRevert(MerkleTreeLib.MerkleTreeLeafsEmpty.selector); - this.buildAndGetRoot(leafs); + function _testBuildAndGetRoot(bytes32[] memory leaves) internal { + vm.expectRevert(MerkleTreeLib.MerkleTreeLeavesEmpty.selector); + this.buildAndGetRoot(leaves); } - function buildAndGetRoot(bytes32[] memory leafs) public pure returns (bytes32) { - return MerkleTreeLib.build(leafs).root(); + function buildAndGetRoot(bytes32[] memory leaves) public pure returns (bytes32) { + return MerkleTreeLib.build(leaves).root(); } function testGetRootFromEmptyTree() public { @@ -164,7 +164,7 @@ contract MerkleTreeLibTest is SoladyTest { } struct TestMultiProofTemps { - bytes32[] leafs; + bytes32[] leaves; uint256[] leafIndices; bytes32[] gathered; bytes32[] tree; @@ -175,24 +175,24 @@ contract MerkleTreeLibTest is SoladyTest { function testBuildAndGetLeafsMultiProof(bytes32 r) public { _maybeBrutalizeMemory(r); TestMultiProofTemps memory t; - t.leafs = new bytes32[](_bound(_random(), 1, 128)); - for (uint256 i; i < t.leafs.length; ++i) { - t.leafs[i] = bytes32(_random()); + t.leaves = new bytes32[](_bound(_random(), 1, 128)); + for (uint256 i; i < t.leaves.length; ++i) { + t.leaves[i] = bytes32(_random()); } - t.leafs = _maybePad(t.leafs); - t.leafIndices = _generateUniqueLeafIndices(t.leafs); - t.tree = MerkleTreeLib.build(t.leafs); - (t.proof, t.flags) = t.tree.leafsMultiProof(t.leafIndices); - t.gathered = _gatherLeafs(t.leafs, t.leafIndices); + t.leaves = _maybePad(t.leaves); + t.leafIndices = _generateUniqueLeafIndices(t.leaves); + t.tree = MerkleTreeLib.build(t.leaves); + (t.proof, t.flags) = t.tree.multiProofForLeaves(t.leafIndices); + t.gathered = t.tree.gatherLeaves(t.leafIndices); assertTrue(MerkleProofLib.verifyMultiProof(t.proof, t.tree.root(), t.gathered, t.flags)); } - function _generateUniqueLeafIndices(bytes32[] memory leafs) + function _generateUniqueLeafIndices(bytes32[] memory leaves) internal returns (uint256[] memory indices) { - indices = new uint256[](leafs.length); - for (uint256 i; i < leafs.length; ++i) { + indices = new uint256[](leaves.length); + for (uint256 i; i < leaves.length; ++i) { indices[i] = i; } LibPRNG.PRNG memory prng; @@ -206,23 +206,12 @@ contract MerkleTreeLibTest is SoladyTest { LibSort.sort(indices); } - function _gatherLeafs(bytes32[] memory leafs, uint256[] memory indices) - internal - pure - returns (bytes32[] memory gathered) - { - gathered = new bytes32[](indices.length); - for (uint256 i; i < indices.length; ++i) { - gathered[i] = leafs[indices[i]]; - } - } - function testMultiProofRevertsForEmptyLeafs() public { vm.expectRevert(MerkleTreeLib.MerkleTreeInvalidLeafIndices.selector); this.multiProofRevertsForEmptyLeafs(); } function multiProofRevertsForEmptyLeafs() public pure { - (new bytes32[](1)).leafsMultiProof(new uint256[](0)); + (new bytes32[](1)).multiProofForLeaves(new uint256[](0)); } }