github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/test/libraries/trie/MerkleTrie.t.sol (about) 1 // SPDX-License-Identifier: MIT 2 pragma solidity 0.8.15; 3 4 import { Test } from "forge-std/Test.sol"; 5 import { MerkleTrie } from "src/libraries/trie/MerkleTrie.sol"; 6 import { FFIInterface } from "test/setup/FFIInterface.sol"; 7 8 contract MerkleTrie_get_Test is Test { 9 FFIInterface constant ffi = FFIInterface(address(uint160(uint256(keccak256(abi.encode("optimism.ffi")))))); 10 11 function setUp() public { 12 vm.etch(address(ffi), vm.getDeployedCode("FFIInterface.sol:FFIInterface")); 13 vm.label(address(ffi), "FFIInterface"); 14 } 15 16 function test_get_validProof1_succeeds() external { 17 bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f; 18 bytes memory key = hex"6b6579326262"; 19 bytes memory val = hex"6176616c32"; 20 bytes[] memory proof = new bytes[](3); 21 proof[0] = hex"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386"; 22 proof[1] = 23 hex"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080"; 24 proof[2] = hex"ca83206262856176616c32"; 25 26 assertEq(val, MerkleTrie.get(key, proof, root)); 27 } 28 29 function test_get_validProof2_succeeds() external { 30 bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f; 31 bytes memory key = hex"6b6579316161"; 32 bytes memory val = hex"303132333435363738393031323334353637383930313233343536373839303132333435363738397878"; 33 bytes[] memory proof = new bytes[](3); 34 proof[0] = hex"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386"; 35 proof[1] = 36 hex"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080"; 37 proof[2] = hex"ef83206161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878"; 38 39 assertEq(val, MerkleTrie.get(key, proof, root)); 40 } 41 42 function test_get_validProof3_succeeds() external { 43 bytes32 root = 0xf838216fa749aefa91e0b672a9c06d3e6e983f913d7107b5dab4af60b5f5abed; 44 bytes memory key = hex"6b6579316161"; 45 bytes memory val = hex"303132333435363738393031323334353637383930313233343536373839303132333435363738397878"; 46 bytes[] memory proof = new bytes[](1); 47 proof[0] = 48 hex"f387206b6579316161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878"; 49 50 assertEq(val, MerkleTrie.get(key, proof, root)); 51 } 52 53 function test_get_validProof4_succeeds() external { 54 bytes32 root = 0x37956bab6bba472308146808d5311ac19cb4a7daae5df7efcc0f32badc97f55e; 55 bytes memory key = hex"6b6579316161"; 56 bytes memory val = hex"3031323334"; 57 bytes[] memory proof = new bytes[](1); 58 proof[0] = hex"ce87206b6579316161853031323334"; 59 60 assertEq(val, MerkleTrie.get(key, proof, root)); 61 } 62 63 function test_get_validProof5_succeeds() external { 64 bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89; 65 bytes memory key = hex"6b657931"; 66 bytes memory val = 67 hex"30313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67"; 68 bytes[] memory proof = new bytes[](3); 69 proof[0] = hex"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779"; 70 proof[1] = 71 hex"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080"; 72 proof[2] = 73 hex"f862808080808080a057895fdbd71e2c67c2f9274a56811ff5cf458720a7fa713a135e3890f8cafcf8808080808080808080b130313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67"; 74 75 assertEq(val, MerkleTrie.get(key, proof, root)); 76 } 77 78 function test_get_validProof6_succeeds() external { 79 bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89; 80 bytes memory key = hex"6b657932"; 81 bytes memory val = hex"73686f7274"; 82 bytes[] memory proof = new bytes[](3); 83 proof[0] = hex"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779"; 84 proof[1] = 85 hex"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080"; 86 proof[2] = hex"df808080808080c9823262856176616c338080808080808080808573686f7274"; 87 88 assertEq(val, MerkleTrie.get(key, proof, root)); 89 } 90 91 function test_get_validProof7_succeeds() external { 92 bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89; 93 bytes memory key = hex"6b657933"; 94 bytes memory val = hex"31323334353637383930313233343536373839303132333435363738393031"; 95 bytes[] memory proof = new bytes[](3); 96 proof[0] = hex"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779"; 97 proof[1] = 98 hex"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080"; 99 proof[2] = 100 hex"f839808080808080c9823363856176616c338080808080808080809f31323334353637383930313233343536373839303132333435363738393031"; 101 102 assertEq(val, MerkleTrie.get(key, proof, root)); 103 } 104 105 function test_get_validProof8_succeeds() external { 106 bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978; 107 bytes memory key = hex"61"; 108 bytes memory val = hex"61"; 109 bytes[] memory proof = new bytes[](3); 110 proof[0] = hex"d916d780c22061c22062c2206380808080808080808080808080"; 111 proof[1] = hex"d780c22061c22062c2206380808080808080808080808080"; 112 proof[2] = hex"c22061"; 113 114 assertEq(val, MerkleTrie.get(key, proof, root)); 115 } 116 117 function test_get_validProof9_succeeds() external { 118 bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978; 119 bytes memory key = hex"62"; 120 bytes memory val = hex"62"; 121 bytes[] memory proof = new bytes[](3); 122 proof[0] = hex"d916d780c22061c22062c2206380808080808080808080808080"; 123 proof[1] = hex"d780c22061c22062c2206380808080808080808080808080"; 124 proof[2] = hex"c22062"; 125 126 assertEq(val, MerkleTrie.get(key, proof, root)); 127 } 128 129 function test_get_validProof10_succeeds() external { 130 bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978; 131 bytes memory key = hex"63"; 132 bytes memory val = hex"63"; 133 bytes[] memory proof = new bytes[](3); 134 proof[0] = hex"d916d780c22061c22062c2206380808080808080808080808080"; 135 proof[1] = hex"d780c22061c22062c2206380808080808080808080808080"; 136 proof[2] = hex"c22063"; 137 138 assertEq(val, MerkleTrie.get(key, proof, root)); 139 } 140 141 function test_get_nonexistentKey1_reverts() external { 142 bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f; 143 bytes memory key = hex"6b657932"; 144 bytes[] memory proof = new bytes[](3); 145 proof[0] = hex"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386"; 146 proof[1] = 147 hex"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080"; 148 proof[2] = hex"ca83206262856176616c32"; 149 150 vm.expectRevert("MerkleTrie: path remainder must share all nibbles with key"); 151 MerkleTrie.get(key, proof, root); 152 } 153 154 function test_get_nonexistentKey2_reverts() external { 155 bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f; 156 bytes memory key = hex"616e7972616e646f6d6b6579"; 157 bytes[] memory proof = new bytes[](1); 158 proof[0] = hex"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386"; 159 160 vm.expectRevert("MerkleTrie: path remainder must share all nibbles with key"); 161 MerkleTrie.get(key, proof, root); 162 } 163 164 function test_get_wrongKeyProof_reverts() external { 165 bytes32 root = 0x2858eebfa9d96c8a9e6a0cae9d86ec9189127110f132d63f07d3544c2a75a696; 166 bytes memory key = hex"6b6579316161"; 167 bytes[] memory proof = new bytes[](3); 168 proof[0] = hex"e216a04892c039d654f1be9af20e88ae53e9ab5fa5520190e0fb2f805823e45ebad22f"; 169 proof[1] = 170 hex"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080"; 171 proof[2] = hex"d687206e6f746865728d33343938683472697568677765"; 172 173 vm.expectRevert("MerkleTrie: invalid internal node hash"); 174 MerkleTrie.get(key, proof, root); 175 } 176 177 function test_get_corruptedProof_reverts() external { 178 bytes32 root = 0x2858eebfa9d96c8a9e6a0cae9d86ec9189127110f132d63f07d3544c2a75a696; 179 bytes memory key = hex"6b6579326262"; 180 bytes[] memory proof = new bytes[](5); 181 proof[0] = hex"2fd2ba5ee42358802ffbe0900152a55fabe953ae880ef29abef154d639c09248a016e2"; 182 proof[1] = 183 hex"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080"; 184 proof[2] = hex"e583165793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386"; 185 proof[3] = 186 hex"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080"; 187 proof[4] = hex"ca83206262856176616c32"; 188 189 vm.expectRevert("RLPReader: decoded item type for list is not a list item"); 190 MerkleTrie.get(key, proof, root); 191 } 192 193 function test_get_invalidDataRemainder_reverts() external { 194 bytes32 root = 0x278c88eb59beba4f8b94f940c41614bb0dd80c305859ebffcd6ce07c93ca3749; 195 bytes memory key = hex"aa"; 196 bytes[] memory proof = new bytes[](3); 197 proof[0] = hex"d91ad780808080808080808080c32081aac32081ab8080808080"; 198 proof[1] = hex"d780808080808080808080c32081aac32081ab8080808080"; 199 proof[2] = hex"c32081aa000000000000000000000000000000"; 200 201 vm.expectRevert("RLPReader: list item has an invalid data remainder"); 202 MerkleTrie.get(key, proof, root); 203 } 204 205 function test_get_invalidInternalNodeHash_reverts() external { 206 bytes32 root = 0xa827dff1a657bb9bb9a1c3abe9db173e2f1359f15eb06f1647ea21ac7c95d8fa; 207 bytes memory key = hex"aa"; 208 bytes[] memory proof = new bytes[](3); 209 proof[0] = hex"e21aa09862c6b113008c4204c13755693cbb868acc25ebaa98db11df8c89a0c0dd3157"; 210 proof[1] = 211 hex"f380808080808080808080a0de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f00c220118080808080"; 212 proof[2] = hex"de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f"; 213 214 vm.expectRevert("MerkleTrie: invalid internal node hash"); 215 MerkleTrie.get(key, proof, root); 216 } 217 218 function test_get_zeroBranchValueLength_reverts() external { 219 bytes32 root = 0xe04b3589eef96b237cd49ccb5dcf6e654a47682bfa0961d563ab843f7ad1e035; 220 bytes memory key = hex"aa"; 221 bytes[] memory proof = new bytes[](2); 222 proof[0] = hex"dd8200aad98080808080808080808080c43b82aabbc43c82aacc80808080"; 223 proof[1] = hex"d98080808080808080808080c43b82aabbc43c82aacc80808080"; 224 225 vm.expectRevert("MerkleTrie: value length must be greater than zero (branch)"); 226 MerkleTrie.get(key, proof, root); 227 } 228 229 function test_get_zeroLengthKey_reverts() external { 230 bytes32 root = 0x54157fd62cdf2f474e7bfec2d3cd581e807bee38488c9590cb887add98936b73; 231 bytes memory key = hex""; 232 bytes[] memory proof = new bytes[](1); 233 proof[0] = hex"c78320f00082b443"; 234 235 vm.expectRevert("MerkleTrie: empty key"); 236 MerkleTrie.get(key, proof, root); 237 } 238 239 function test_get_smallerPathThanKey1_reverts() external { 240 bytes32 root = 0xa513ba530659356fb7588a2c831944e80fd8aedaa5a4dc36f918152be2be0605; 241 bytes memory key = hex"01"; 242 bytes[] memory proof = new bytes[](3); 243 proof[0] = hex"db10d9c32081bbc582202381aa808080808080808080808080808080"; 244 proof[1] = hex"d9c32081bbc582202381aa808080808080808080808080808080"; 245 proof[2] = hex"c582202381aa"; 246 247 vm.expectRevert("MerkleTrie: path remainder must share all nibbles with key"); 248 MerkleTrie.get(key, proof, root); 249 } 250 251 function test_get_smallerPathThanKey2_reverts() external { 252 bytes32 root = 0xa06abffaec4ebe8ccde595f4547b864b4421b21c1fc699973f94710c9bc17979; 253 bytes memory key = hex"aa"; 254 bytes[] memory proof = new bytes[](3); 255 proof[0] = hex"e21aa07ea462226a3dc0a46afb4ded39306d7a84d311ada3557dfc75a909fd25530905"; 256 proof[1] = 257 hex"f380808080808080808080a027f11bd3af96d137b9287632f44dd00fea1ca1bd70386c30985ede8cc287476e808080c220338080"; 258 proof[2] = hex"e48200bba0a6911545ed01c2d3f4e15b8b27c7bfba97738bd5e6dd674dd07033428a4c53af"; 259 260 vm.expectRevert("MerkleTrie: path remainder must share all nibbles with key"); 261 MerkleTrie.get(key, proof, root); 262 } 263 264 function test_get_extraProofElements_reverts() external { 265 bytes32 root = 0x278c88eb59beba4f8b94f940c41614bb0dd80c305859ebffcd6ce07c93ca3749; 266 bytes memory key = hex"aa"; 267 bytes[] memory proof = new bytes[](4); 268 proof[0] = hex"d91ad780808080808080808080c32081aac32081ab8080808080"; 269 proof[1] = hex"d780808080808080808080c32081aac32081ab8080808080"; 270 proof[2] = hex"c32081aa"; 271 proof[3] = hex"c32081aa"; 272 273 vm.expectRevert("MerkleTrie: value node must be last node in proof (leaf)"); 274 MerkleTrie.get(key, proof, root); 275 } 276 277 /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. 278 function testFuzz_get_validProofs_succeeds(bytes4) external { 279 // Generate a test case with a valid proof of inclusion for the k/v pair in the trie. 280 (bytes32 root, bytes memory key, bytes memory val, bytes[] memory proof) = ffi.getMerkleTrieFuzzCase("valid"); 281 282 // Assert that our expected value is equal to our actual value. 283 assertEq(val, MerkleTrie.get(key, proof, root)); 284 } 285 286 /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. 287 function testFuzz_get_invalidRoot_reverts(bytes4) external { 288 // Get a random test case with a valid trie / proof 289 (bytes32 root, bytes memory key,, bytes[] memory proof) = ffi.getMerkleTrieFuzzCase("valid"); 290 291 bytes32 rootHash = keccak256(abi.encodePacked(root)); 292 vm.expectRevert("MerkleTrie: invalid root hash"); 293 MerkleTrie.get(key, proof, rootHash); 294 } 295 296 /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. 297 function testFuzz_get_extraProofElements_reverts(bytes4) external { 298 // Generate an invalid test case with an extra proof element attached to an otherwise 299 // valid proof of inclusion for the passed k/v. 300 (bytes32 root, bytes memory key,, bytes[] memory proof) = ffi.getMerkleTrieFuzzCase("extra_proof_elems"); 301 302 vm.expectRevert("MerkleTrie: value node must be last node in proof (leaf)"); 303 MerkleTrie.get(key, proof, root); 304 } 305 306 /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. 307 function testFuzz_get_invalidLargeInternalHash_reverts(bytes4) external { 308 // Generate an invalid test case where a long proof element is incorrect for the root. 309 (bytes32 root, bytes memory key,, bytes[] memory proof) = 310 ffi.getMerkleTrieFuzzCase("invalid_large_internal_hash"); 311 312 vm.expectRevert("MerkleTrie: invalid large internal hash"); 313 MerkleTrie.get(key, proof, root); 314 } 315 316 /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. 317 function testFuzz_get_invalidInternalNodeHash_reverts(bytes4) external { 318 // Generate an invalid test case where a small proof element is incorrect for the root. 319 (bytes32 root, bytes memory key,, bytes[] memory proof) = 320 ffi.getMerkleTrieFuzzCase("invalid_internal_node_hash"); 321 322 vm.expectRevert("MerkleTrie: invalid internal node hash"); 323 MerkleTrie.get(key, proof, root); 324 } 325 326 /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. 327 function testFuzz_get_corruptedProof_reverts(bytes4) external { 328 // Generate an invalid test case where the proof is malformed. 329 (bytes32 root, bytes memory key,, bytes[] memory proof) = ffi.getMerkleTrieFuzzCase("corrupted_proof"); 330 331 vm.expectRevert("RLPReader: decoded item type for list is not a list item"); 332 MerkleTrie.get(key, proof, root); 333 } 334 335 /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. 336 function testFuzz_get_invalidDataRemainder_reverts(bytes4) external { 337 // Generate an invalid test case where a random element of the proof has more bytes than the 338 // length designates within the RLP list encoding. 339 (bytes32 root, bytes memory key,, bytes[] memory proof) = ffi.getMerkleTrieFuzzCase("invalid_data_remainder"); 340 341 vm.expectRevert("RLPReader: list item has an invalid data remainder"); 342 MerkleTrie.get(key, proof, root); 343 } 344 345 /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. 346 function testFuzz_get_prefixedValidKey_reverts(bytes4) external { 347 // Get a random test case with a valid trie / proof and a valid key that is prefixed 348 // with random bytes 349 (bytes32 root, bytes memory key,, bytes[] memory proof) = ffi.getMerkleTrieFuzzCase("prefixed_valid_key"); 350 351 // Ambiguous revert check- all that we care is that it *does* fail. This case may 352 // fail within different branches. 353 vm.expectRevert(); 354 MerkleTrie.get(key, proof, root); 355 } 356 357 /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. 358 function testFuzz_get_emptyKey_reverts(bytes4) external { 359 // Get a random test case with a valid trie / proof and an empty key 360 (bytes32 root, bytes memory key,, bytes[] memory proof) = ffi.getMerkleTrieFuzzCase("empty_key"); 361 362 vm.expectRevert("MerkleTrie: empty key"); 363 MerkleTrie.get(key, proof, root); 364 } 365 366 /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. 367 function testFuzz_get_partialProof_reverts(bytes4) external { 368 // Get a random test case with a valid trie / partially correct proof 369 (bytes32 root, bytes memory key,, bytes[] memory proof) = ffi.getMerkleTrieFuzzCase("partial_proof"); 370 371 vm.expectRevert("MerkleTrie: ran out of proof elements"); 372 MerkleTrie.get(key, proof, root); 373 } 374 }