@@ -9,10 +9,75 @@ import {MerkleConstants} from "src/MerkleConstants.sol";
99import {PristineMerkleTree} from "src/PristineMerkleTree.sol " ;
1010import {Merkle} from "src/Merkle.sol " ;
1111
12+ contract PristineMerkleTreeContract {
13+ function getNodeAtHeight (uint256 height ) external pure returns (bytes32 ) {
14+ return PristineMerkleTree.getNodeAtHeight (height);
15+ }
16+ }
17+
18+ contract MerkleContract {
19+ function getHashOfLeafAtIndex (bytes calldata data , uint256 leafIndex ) external pure returns (bytes32 ) {
20+ return Merkle.getHashOfLeafAtIndex (data, leafIndex);
21+ }
22+ }
23+
1224contract MerkleTest is Test {
1325 using Merkle for bytes ;
1426
27+ PristineMerkleTreeContract pristineMerkle;
28+ MerkleContract merkle;
29+
30+ function setUp () external {
31+ pristineMerkle = new PristineMerkleTreeContract ();
32+ merkle = new MerkleContract ();
33+ }
34+
1535 function testJoinEquivalence (bytes32 a , bytes32 b ) external pure {
1636 assertEq (Merkle.join (a, b), keccak256 (abi.encodePacked (a, b)));
1737 }
38+
39+ function testPristineMerkleTree () external pure {
40+ bytes32 node = keccak256 (abi.encode (0 ));
41+ for (uint256 height; height <= MerkleConstants.TREE_HEIGHT; ++ height) {
42+ assertEq (PristineMerkleTree.getNodeAtHeight (height), node);
43+ node = Merkle.join (node, node);
44+ }
45+ }
46+
47+ function testPristineMerkleTreeRevert () external {
48+ vm.expectRevert ("Height out of bounds " );
49+ pristineMerkle.getNodeAtHeight (MerkleConstants.TREE_HEIGHT + 1 );
50+ }
51+
52+ function testPristineMerkleTreeRevert (uint256 height ) external {
53+ height = bound (height, MerkleConstants.TREE_HEIGHT + 1 , type (uint256 ).max);
54+ vm.expectRevert ("Height out of bounds " );
55+ pristineMerkle.getNodeAtHeight (height);
56+ }
57+
58+ function testGetHashOfLeafAtIndex (bytes calldata data ) external view {
59+ // whole leaves
60+ for (uint256 leafIndex; leafIndex < (data.length >> MerkleConstants.LOG2_LEAF_SIZE); ++ leafIndex) {
61+ uint256 start = leafIndex << MerkleConstants.LOG2_LEAF_SIZE;
62+ uint256 end = (leafIndex + 1 ) << MerkleConstants.LOG2_LEAF_SIZE;
63+ assertEq (merkle.getHashOfLeafAtIndex (data, leafIndex), keccak256 (data[start:end]));
64+ }
65+ // first empty or pristine leaf
66+ {
67+ uint256 leafIndex = data.length >> MerkleConstants.LOG2_LEAF_SIZE;
68+ uint256 start = leafIndex << MerkleConstants.LOG2_LEAF_SIZE;
69+ assertEq (merkle.getHashOfLeafAtIndex (data, leafIndex), keccak256 (abi.encodePacked (bytes32 (data[start:]))));
70+ }
71+ // first or second pristine leaf
72+ {
73+ uint256 leafIndex = 1 + (data.length >> MerkleConstants.LOG2_LEAF_SIZE);
74+ assertEq (merkle.getHashOfLeafAtIndex (data, leafIndex), pristineMerkle.getNodeAtHeight (0 ));
75+ }
76+ }
77+
78+ function testGetHashOfLeafAtIndex (bytes calldata data , uint256 leafIndex ) external view {
79+ uint256 leafIndexUpperBound = data.length >> MerkleConstants.LOG2_LEAF_SIZE;
80+ leafIndex = bound (leafIndex, 1 + leafIndexUpperBound, type (uint256 ).max);
81+ assertEq (merkle.getHashOfLeafAtIndex (data, leafIndex), pristineMerkle.getNodeAtHeight (0 ));
82+ }
1883}
0 commit comments