Skip to content

Commit 6912e91

Browse files
authored
✨ MerkleTreeLib pad default variant (#1437)
1 parent 4fa3ac6 commit 6912e91

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

docs/utils/merkletreelib.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,17 @@
33
Library for generating Merkle trees.
44

55

6+
<b>Note:</b>
67

8+
- Leafs are NOT auto hashed. Note that some libraries hash the leafs by default.
9+
We leave it up to you to decide if this is needed.
10+
If your leafs are 64 bytes long, do hash them first for safety.
11+
See: https://www.rareskills.io/post/merkle-tree-second-preimage-attack
12+
- Leafs are NOT auto globally sorted. Note that some libraries sort the leafs by default.
13+
- The pair hash is pair-sorted-keccak256, which works out-of-the-box with `MerkleProofLib`.
14+
- This library is NOT equivalent to OpenZeppelin or Murky.
15+
Equivalence is NOT required if you are just using this for pure Solidity testing.
16+
May be relevant for differential testing between Solidity vs external libraries.
717

818

919

@@ -132,4 +142,15 @@ function pad(bytes32[] memory leafs, bytes32 defaultFill)
132142
returns (bytes32[] memory result)
133143
```
134144

135-
Returns a copy of leafs, with the length padded to a power of 2.
145+
Returns a copy of leafs, with the length padded to a power of 2.
146+
147+
### pad(bytes32[])
148+
149+
```solidity
150+
function pad(bytes32[] memory leafs)
151+
internal
152+
pure
153+
returns (bytes32[] memory result)
154+
```
155+
156+
Equivalent to `pad(leafs, bytes32(0))`.

src/utils/MerkleTreeLib.sol

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ pragma solidity ^0.8.4;
44
/// @notice Library for generating Merkle trees.
55
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/MerkleTreeLib.sol)
66
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/merkle-tree/blob/master/src/core.ts)
7+
/// @dev Note:
8+
/// - Leafs are NOT auto hashed. Note that some libraries hash the leafs by default.
9+
/// We leave it up to you to decide if this is needed.
10+
/// If your leafs are 64 bytes long, do hash them first for safety.
11+
/// See: https://www.rareskills.io/post/merkle-tree-second-preimage-attack
12+
/// - Leafs are NOT auto globally sorted. Note that some libraries sort the leafs by default.
13+
/// - The pair hash is pair-sorted-keccak256, which works out-of-the-box with `MerkleProofLib`.
14+
/// - This library is NOT equivalent to OpenZeppelin or Murky.
15+
/// Equivalence is NOT required if you are just using this for pure Solidity testing.
16+
/// May be relevant for differential testing between Solidity vs external libraries.
717
library MerkleTreeLib {
818
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
919
/* CUSTOM ERRORS */
@@ -244,4 +254,9 @@ library MerkleTreeLib {
244254
}
245255
}
246256
}
257+
258+
/// @dev Equivalent to `pad(leafs, bytes32(0))`.
259+
function pad(bytes32[] memory leafs) internal pure returns (bytes32[] memory result) {
260+
result = pad(leafs, bytes32(0));
261+
}
247262
}

test/MerkleTreeLib.t.sol

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,19 @@ contract MerkleTreeLibTest is SoladyTest {
9090
return MerkleTreeLib.build(leafs).leaf(leafIndex);
9191
}
9292

93+
function _maybePad(bytes32[] memory leafs) internal returns (bytes32[] memory) {
94+
if (_randomChance(2)) {
95+
if (_randomChance(2)) {
96+
return leafs.pad();
97+
}
98+
return leafs.pad(bytes32(_random()));
99+
}
100+
return leafs;
101+
}
102+
93103
function testBuildAndGetLeafProof(bytes32[] memory leafs, uint256 leafIndex) public {
94104
if (leafs.length == 0) return _testBuildAndGetRoot(leafs);
105+
leafs = _maybePad(leafs);
95106
bytes32[] memory t = MerkleTreeLib.build(leafs);
96107
if (leafIndex < leafs.length) {
97108
bytes32[] memory proof = this.buildAndGetLeafProof(leafs, leafIndex);
@@ -161,12 +172,14 @@ contract MerkleTreeLibTest is SoladyTest {
161172
bool[] flags;
162173
}
163174

164-
function testBuildAndGetLeafsMultiProof(bytes32) public {
175+
function testBuildAndGetLeafsMultiProof(bytes32 r) public {
176+
_maybeBrutalizeMemory(r);
165177
TestMultiProofTemps memory t;
166178
t.leafs = new bytes32[](_bound(_random(), 1, 128));
167179
for (uint256 i; i < t.leafs.length; ++i) {
168180
t.leafs[i] = bytes32(_random());
169181
}
182+
t.leafs = _maybePad(t.leafs);
170183
t.leafIndices = _generateUniqueLeafIndices(t.leafs);
171184
t.tree = MerkleTreeLib.build(t.leafs);
172185
(t.proof, t.flags) = t.tree.leafsMultiProof(t.leafIndices);

0 commit comments

Comments
 (0)