Skip to content

Commit 4f42cfa

Browse files
committed
test: Merkle libs
1 parent 4dc5078 commit 4f42cfa

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

cartesi-rollups/contracts/test/Merkle.t.sol

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,75 @@ import {MerkleConstants} from "src/MerkleConstants.sol";
99
import {PristineMerkleTree} from "src/PristineMerkleTree.sol";
1010
import {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+
1224
contract 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

Comments
 (0)