github.com/tirogen/go-ethereum@v1.10.12-0.20221226051715-250cfede41b6/cmd/devp2p/internal/ethtest/snap.go (about) 1 // Copyright 2022 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package ethtest 18 19 import ( 20 "bytes" 21 "errors" 22 "fmt" 23 "math/rand" 24 25 "github.com/tirogen/go-ethereum/common" 26 "github.com/tirogen/go-ethereum/crypto" 27 "github.com/tirogen/go-ethereum/eth/protocols/snap" 28 "github.com/tirogen/go-ethereum/internal/utesting" 29 "github.com/tirogen/go-ethereum/light" 30 "github.com/tirogen/go-ethereum/trie" 31 "golang.org/x/crypto/sha3" 32 ) 33 34 func (s *Suite) TestSnapStatus(t *utesting.T) { 35 conn, err := s.dialSnap() 36 if err != nil { 37 t.Fatalf("dial failed: %v", err) 38 } 39 defer conn.Close() 40 if err := conn.peer(s.chain, nil); err != nil { 41 t.Fatalf("peering failed: %v", err) 42 } 43 } 44 45 type accRangeTest struct { 46 nBytes uint64 47 root common.Hash 48 origin common.Hash 49 limit common.Hash 50 51 expAccounts int 52 expFirst common.Hash 53 expLast common.Hash 54 } 55 56 // TestSnapGetAccountRange various forms of GetAccountRange requests. 57 func (s *Suite) TestSnapGetAccountRange(t *utesting.T) { 58 var ( 59 root = s.chain.RootAt(999) 60 ffHash = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") 61 zero = common.Hash{} 62 firstKeyMinus1 = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf29") 63 firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a") 64 firstKeyPlus1 = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2b") 65 secondKey = common.HexToHash("0x09e47cd5056a689e708f22fe1f932709a320518e444f5f7d8d46a3da523d6606") 66 storageRoot = common.HexToHash("0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790") 67 ) 68 for i, tc := range []accRangeTest{ 69 // Tests decreasing the number of bytes 70 {4000, root, zero, ffHash, 76, firstKey, common.HexToHash("0xd2669dcf3858e7f1eecb8b5fedbf22fbea3e9433848a75035f79d68422c2dcda")}, 71 {3000, root, zero, ffHash, 57, firstKey, common.HexToHash("0x9b63fa753ece5cb90657d02ecb15df4dc1508d8c1d187af1bf7f1a05e747d3c7")}, 72 {2000, root, zero, ffHash, 38, firstKey, common.HexToHash("0x5e6140ecae4354a9e8f47559a8c6209c1e0e69cb077b067b528556c11698b91f")}, 73 {1, root, zero, ffHash, 1, firstKey, firstKey}, 74 75 // Tests variations of the range 76 // 77 // [00b to firstkey]: should return [firstkey, secondkey], where secondkey is out of bounds 78 {4000, root, common.HexToHash("0x00bf000000000000000000000000000000000000000000000000000000000000"), common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2b"), 2, firstKey, secondKey}, 79 // [00b0 to 0bf0]: where both are before firstkey. Should return firstKey (even though it's out of bounds) 80 {4000, root, common.HexToHash("0x00b0000000000000000000000000000000000000000000000000000000000000"), common.HexToHash("0x00bf100000000000000000000000000000000000000000000000000000000000"), 1, firstKey, firstKey}, 81 {4000, root, zero, zero, 1, firstKey, firstKey}, 82 {4000, root, firstKey, ffHash, 76, firstKey, common.HexToHash("0xd2669dcf3858e7f1eecb8b5fedbf22fbea3e9433848a75035f79d68422c2dcda")}, 83 {4000, root, firstKeyPlus1, ffHash, 76, secondKey, common.HexToHash("0xd28f55d3b994f16389f36944ad685b48e0fc3f8fbe86c3ca92ebecadf16a783f")}, 84 85 // Test different root hashes 86 // 87 // A stateroot that does not exist 88 {4000, common.Hash{0x13, 37}, zero, ffHash, 0, zero, zero}, 89 // The genesis stateroot (we expect it to not be served) 90 {4000, s.chain.RootAt(0), zero, ffHash, 0, zero, zero}, 91 // A 127 block old stateroot, expected to be served 92 {4000, s.chain.RootAt(999 - 127), zero, ffHash, 77, firstKey, common.HexToHash("0xe4c6fdef5dd4e789a2612390806ee840b8ec0fe52548f8b4efe41abb20c37aac")}, 93 // A root which is not actually an account root, but a storage root 94 {4000, storageRoot, zero, ffHash, 0, zero, zero}, 95 96 // And some non-sensical requests 97 // 98 // range from [0xFF to 0x00], wrong order. Expect not to be serviced 99 {4000, root, ffHash, zero, 0, zero, zero}, 100 // range from [firstkey, firstkey-1], wrong order. Expect to get first key. 101 {4000, root, firstKey, firstKeyMinus1, 1, firstKey, firstKey}, 102 // range from [firstkey, 0], wrong order. Expect to get first key. 103 {4000, root, firstKey, zero, 1, firstKey, firstKey}, 104 // Max bytes: 0. Expect to deliver one account. 105 {0, root, zero, ffHash, 1, firstKey, firstKey}, 106 } { 107 tc := tc 108 if err := s.snapGetAccountRange(t, &tc); err != nil { 109 t.Errorf("test %d \n root: %x\n range: %#x - %#x\n bytes: %d\nfailed: %v", i, tc.root, tc.origin, tc.limit, tc.nBytes, err) 110 } 111 } 112 } 113 114 type stRangesTest struct { 115 root common.Hash 116 accounts []common.Hash 117 origin []byte 118 limit []byte 119 nBytes uint64 120 121 expSlots int 122 } 123 124 // TestSnapGetStorageRanges various forms of GetStorageRanges requests. 125 func (s *Suite) TestSnapGetStorageRanges(t *utesting.T) { 126 var ( 127 ffHash = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") 128 zero = common.Hash{} 129 firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a") 130 secondKey = common.HexToHash("0x09e47cd5056a689e708f22fe1f932709a320518e444f5f7d8d46a3da523d6606") 131 ) 132 for i, tc := range []stRangesTest{ 133 { 134 root: s.chain.RootAt(999), 135 accounts: []common.Hash{secondKey, firstKey}, 136 origin: zero[:], 137 limit: ffHash[:], 138 nBytes: 500, 139 expSlots: 0, 140 }, 141 142 /* 143 Some tests against this account: 144 { 145 "balance": "0", 146 "nonce": 1, 147 "root": "0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790", 148 "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", 149 "storage": { 150 "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace": "02", 151 "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6": "01", 152 "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b": "03" 153 }, 154 "key": "0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844" 155 } 156 */ 157 { // [:] -> [slot1, slot2, slot3] 158 root: s.chain.RootAt(999), 159 accounts: []common.Hash{common.HexToHash("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844")}, 160 origin: zero[:], 161 limit: ffHash[:], 162 nBytes: 500, 163 expSlots: 3, 164 }, 165 { // [slot1:] -> [slot1, slot2, slot3] 166 root: s.chain.RootAt(999), 167 accounts: []common.Hash{common.HexToHash("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844")}, 168 origin: common.FromHex("0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace"), 169 limit: ffHash[:], 170 nBytes: 500, 171 expSlots: 3, 172 }, 173 { // [slot1+ :] -> [slot2, slot3] 174 root: s.chain.RootAt(999), 175 accounts: []common.Hash{common.HexToHash("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844")}, 176 origin: common.FromHex("0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf"), 177 limit: ffHash[:], 178 nBytes: 500, 179 expSlots: 2, 180 }, 181 { // [slot1:slot2] -> [slot1, slot2] 182 root: s.chain.RootAt(999), 183 accounts: []common.Hash{common.HexToHash("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844")}, 184 origin: common.FromHex("0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace"), 185 limit: common.FromHex("0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6"), 186 nBytes: 500, 187 expSlots: 2, 188 }, 189 { // [slot1+:slot2+] -> [slot2, slot3] 190 root: s.chain.RootAt(999), 191 accounts: []common.Hash{common.HexToHash("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844")}, 192 origin: common.FromHex("0x4fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), 193 limit: common.FromHex("0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf7"), 194 nBytes: 500, 195 expSlots: 2, 196 }, 197 } { 198 tc := tc 199 if err := s.snapGetStorageRanges(t, &tc); err != nil { 200 t.Errorf("test %d \n root: %x\n range: %#x - %#x\n bytes: %d\n #accounts: %d\nfailed: %v", 201 i, tc.root, tc.origin, tc.limit, tc.nBytes, len(tc.accounts), err) 202 } 203 } 204 } 205 206 type byteCodesTest struct { 207 nBytes uint64 208 hashes []common.Hash 209 210 expHashes int 211 } 212 213 var ( 214 // emptyRoot is the known root hash of an empty trie. 215 emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") 216 // emptyCode is the known hash of the empty EVM bytecode. 217 emptyCode = common.HexToHash("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470") 218 ) 219 220 // TestSnapGetByteCodes various forms of GetByteCodes requests. 221 func (s *Suite) TestSnapGetByteCodes(t *utesting.T) { 222 // The halfchain import should yield these bytecodes 223 var hcBytecodes []common.Hash 224 for _, s := range []string{ 225 "0x200c90460d8b0063210d5f5b9918e053c8f2c024485e0f1b48be8b1fc71b1317", 226 "0x20ba67ed4ac6aff626e0d1d4db623e2fada9593daeefc4a6eb4b70e6cff986f3", 227 "0x24b5b4902cb3d897c1cee9f16be8e897d8fa277c04c6dc8214f18295fca5de44", 228 "0x320b9d0a2be39b8a1c858f9f8cb96b1df0983071681de07ded3a7c0d05db5fd6", 229 "0x48cb0d5275936a24632babc7408339f9f7b051274809de565b8b0db76e97e03c", 230 "0x67c7a6f5cdaa43b4baa0e15b2be63346d1b9ce9f2c3d7e5804e0cacd44ee3b04", 231 "0x6d8418059bdc8c3fabf445e6bfc662af3b6a4ae45999b953996e42c7ead2ab49", 232 "0x7043422e5795d03f17ee0463a37235258e609fdd542247754895d72695e3e142", 233 "0x727f9e6f0c4bac1ff8d72c2972122d9c8d37ccb37e04edde2339e8da193546f1", 234 "0x86ccd5e23c78568a8334e0cebaf3e9f48c998307b0bfb1c378cee83b4bfb29cb", 235 "0x8fc89b00d6deafd4c4279531e743365626dbfa28845ec697919d305c2674302d", 236 "0x92cfc353bcb9746bb6f9996b6b9df779c88af2e9e0eeac44879ca19887c9b732", 237 "0x941b4872104f0995a4898fcf0f615ea6bf46bfbdfcf63ea8f2fd45b3f3286b77", 238 "0xa02fe8f41159bb39d2b704c633c3d6389cf4bfcb61a2539a9155f60786cf815f", 239 "0xa4b94e0afdffcb0af599677709dac067d3145489ea7aede57672bee43e3b7373", 240 "0xaf4e64edd3234c1205b725e42963becd1085f013590bd7ed93f8d711c5eb65fb", 241 "0xb69a18fa855b742031420081999086f6fb56c3930ae8840944e8b8ae9931c51e", 242 "0xc246c217bc73ce6666c93a93a94faa5250564f50a3fdc27ea74c231c07fe2ca6", 243 "0xcd6e4ab2c3034df2a8a1dfaaeb1c4baecd162a93d22de35e854ee2945cbe0c35", 244 "0xe24b692d09d6fc2f3d1a6028c400a27c37d7cbb11511907c013946d6ce263d3b", 245 "0xe440c5f0e8603fd1ed25976eee261ccee8038cf79d6a4c0eb31b2bf883be737f", 246 "0xe6eacbc509203d21ac814b350e72934fde686b7f673c19be8cf956b0c70078ce", 247 "0xe8530de4371467b5be7ea0e69e675ab36832c426d6c1ce9513817c0f0ae1486b", 248 "0xe85d487abbbc83bf3423cf9731360cf4f5a37220e18e5add54e72ee20861196a", 249 "0xf195ea389a5eea28db0be93660014275b158963dec44af1dfa7d4743019a9a49", 250 } { 251 hcBytecodes = append(hcBytecodes, common.HexToHash(s)) 252 } 253 254 for i, tc := range []byteCodesTest{ 255 // A few stateroots 256 { 257 nBytes: 10000, hashes: []common.Hash{s.chain.RootAt(0), s.chain.RootAt(999)}, 258 expHashes: 0, 259 }, 260 { 261 nBytes: 10000, hashes: []common.Hash{s.chain.RootAt(0), s.chain.RootAt(0)}, 262 expHashes: 0, 263 }, 264 // Empties 265 { 266 nBytes: 10000, hashes: []common.Hash{emptyRoot}, 267 expHashes: 0, 268 }, 269 { 270 nBytes: 10000, hashes: []common.Hash{emptyCode}, 271 expHashes: 1, 272 }, 273 { 274 nBytes: 10000, hashes: []common.Hash{emptyCode, emptyCode, emptyCode}, 275 expHashes: 3, 276 }, 277 // The existing bytecodes 278 { 279 nBytes: 10000, hashes: hcBytecodes, 280 expHashes: len(hcBytecodes), 281 }, 282 // The existing, with limited byte arg 283 { 284 nBytes: 1, hashes: hcBytecodes, 285 expHashes: 1, 286 }, 287 { 288 nBytes: 0, hashes: hcBytecodes, 289 expHashes: 1, 290 }, 291 { 292 nBytes: 1000, hashes: []common.Hash{hcBytecodes[0], hcBytecodes[0], hcBytecodes[0], hcBytecodes[0]}, 293 expHashes: 4, 294 }, 295 } { 296 tc := tc 297 if err := s.snapGetByteCodes(t, &tc); err != nil { 298 t.Errorf("test %d \n bytes: %d\n #hashes: %d\nfailed: %v", i, tc.nBytes, len(tc.hashes), err) 299 } 300 } 301 } 302 303 type trieNodesTest struct { 304 root common.Hash 305 paths []snap.TrieNodePathSet 306 nBytes uint64 307 308 expHashes []common.Hash 309 expReject bool 310 } 311 312 func decodeNibbles(nibbles []byte, bytes []byte) { 313 for bi, ni := 0, 0; ni < len(nibbles); bi, ni = bi+1, ni+2 { 314 bytes[bi] = nibbles[ni]<<4 | nibbles[ni+1] 315 } 316 } 317 318 // hasTerm returns whether a hex key has the terminator flag. 319 func hasTerm(s []byte) bool { 320 return len(s) > 0 && s[len(s)-1] == 16 321 } 322 323 func keybytesToHex(str []byte) []byte { 324 l := len(str)*2 + 1 325 var nibbles = make([]byte, l) 326 for i, b := range str { 327 nibbles[i*2] = b / 16 328 nibbles[i*2+1] = b % 16 329 } 330 nibbles[l-1] = 16 331 return nibbles 332 } 333 334 func hexToCompact(hex []byte) []byte { 335 terminator := byte(0) 336 if hasTerm(hex) { 337 terminator = 1 338 hex = hex[:len(hex)-1] 339 } 340 buf := make([]byte, len(hex)/2+1) 341 buf[0] = terminator << 5 // the flag byte 342 if len(hex)&1 == 1 { 343 buf[0] |= 1 << 4 // odd flag 344 buf[0] |= hex[0] // first nibble is contained in the first byte 345 hex = hex[1:] 346 } 347 decodeNibbles(hex, buf[1:]) 348 return buf 349 } 350 351 // TestSnapTrieNodes various forms of GetTrieNodes requests. 352 func (s *Suite) TestSnapTrieNodes(t *utesting.T) { 353 key := common.FromHex("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a") 354 // helper function to iterate the key, and generate the compact-encoded 355 // trie paths along the way. 356 pathTo := func(length int) snap.TrieNodePathSet { 357 hex := keybytesToHex(key)[:length] 358 hex[len(hex)-1] = 0 // remove term flag 359 hKey := hexToCompact(hex) 360 return snap.TrieNodePathSet{hKey} 361 } 362 var accPaths []snap.TrieNodePathSet 363 for i := 1; i <= 65; i++ { 364 accPaths = append(accPaths, pathTo(i)) 365 } 366 empty := emptyCode 367 for i, tc := range []trieNodesTest{ 368 { 369 root: s.chain.RootAt(999), 370 paths: nil, 371 nBytes: 500, 372 expHashes: nil, 373 }, 374 { 375 root: s.chain.RootAt(999), 376 paths: []snap.TrieNodePathSet{ 377 {}, // zero-length pathset should 'abort' and kick us off 378 {[]byte{0}}, 379 }, 380 nBytes: 5000, 381 expHashes: []common.Hash{}, 382 expReject: true, 383 }, 384 { 385 root: s.chain.RootAt(999), 386 paths: []snap.TrieNodePathSet{ 387 {[]byte{0}}, 388 {[]byte{1}, []byte{0}}, 389 }, 390 nBytes: 5000, 391 //0x6b3724a41b8c38b46d4d02fba2bb2074c47a507eb16a9a4b978f91d32e406faf 392 expHashes: []common.Hash{s.chain.RootAt(999)}, 393 }, 394 { // nonsensically long path 395 root: s.chain.RootAt(999), 396 paths: []snap.TrieNodePathSet{ 397 {[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 398 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8}}, 399 }, 400 nBytes: 5000, 401 expHashes: []common.Hash{common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")}, 402 }, 403 { 404 root: s.chain.RootAt(0), 405 paths: []snap.TrieNodePathSet{ 406 {[]byte{0}}, 407 {[]byte{1}, []byte{0}}, 408 }, 409 nBytes: 5000, 410 expHashes: []common.Hash{ 411 common.HexToHash("0x1ee1bb2fbac4d46eab331f3e8551e18a0805d084ed54647883aa552809ca968d"), 412 }, 413 }, 414 { 415 // The leaf is only a couple of levels down, so the continued trie traversal causes lookup failures. 416 root: s.chain.RootAt(999), 417 paths: accPaths, 418 nBytes: 5000, 419 expHashes: []common.Hash{ 420 common.HexToHash("0xbcefee69b37cca1f5bf3a48aebe08b35f2ea1864fa958bb0723d909a0e0d28d8"), 421 common.HexToHash("0x4fb1e4e2391e4b4da471d59641319b8fa25d76c973d4bec594d7b00a69ae5135"), 422 empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, 423 empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, 424 empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, 425 empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, 426 empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, 427 empty, empty, empty}, 428 }, 429 { 430 // Basically the same as above, with different ordering 431 root: s.chain.RootAt(999), 432 paths: []snap.TrieNodePathSet{ 433 accPaths[10], accPaths[1], accPaths[0], 434 }, 435 nBytes: 5000, 436 expHashes: []common.Hash{ 437 empty, 438 common.HexToHash("0x4fb1e4e2391e4b4da471d59641319b8fa25d76c973d4bec594d7b00a69ae5135"), 439 common.HexToHash("0xbcefee69b37cca1f5bf3a48aebe08b35f2ea1864fa958bb0723d909a0e0d28d8"), 440 }, 441 }, 442 { 443 /* 444 A test against this account, requesting trie nodes for the storage trie 445 { 446 "balance": "0", 447 "nonce": 1, 448 "root": "0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790", 449 "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", 450 "storage": { 451 "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace": "02", 452 "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6": "01", 453 "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b": "03" 454 }, 455 "key": "0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844" 456 } 457 */ 458 root: s.chain.RootAt(999), 459 paths: []snap.TrieNodePathSet{ 460 { 461 common.FromHex("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844"), 462 []byte{0}, 463 }, 464 }, 465 nBytes: 5000, 466 expHashes: []common.Hash{ 467 common.HexToHash("0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790"), 468 }, 469 }, 470 }[7:] { 471 tc := tc 472 if err := s.snapGetTrieNodes(t, &tc); err != nil { 473 t.Errorf("test %d \n #hashes %x\n root: %#x\n bytes: %d\nfailed: %v", i, len(tc.expHashes), tc.root, tc.nBytes, err) 474 } 475 } 476 } 477 478 func (s *Suite) snapGetAccountRange(t *utesting.T, tc *accRangeTest) error { 479 conn, err := s.dialSnap() 480 if err != nil { 481 t.Fatalf("dial failed: %v", err) 482 } 483 defer conn.Close() 484 if err = conn.peer(s.chain, nil); err != nil { 485 t.Fatalf("peering failed: %v", err) 486 } 487 // write request 488 req := &GetAccountRange{ 489 ID: uint64(rand.Int63()), 490 Root: tc.root, 491 Origin: tc.origin, 492 Limit: tc.limit, 493 Bytes: tc.nBytes, 494 } 495 resp, err := conn.snapRequest(req, req.ID, s.chain) 496 if err != nil { 497 return fmt.Errorf("account range request failed: %v", err) 498 } 499 var res *snap.AccountRangePacket 500 if r, ok := resp.(*AccountRange); !ok { 501 return fmt.Errorf("account range response wrong: %T %v", resp, resp) 502 } else { 503 res = (*snap.AccountRangePacket)(r) 504 } 505 if exp, got := tc.expAccounts, len(res.Accounts); exp != got { 506 return fmt.Errorf("expected %d accounts, got %d", exp, got) 507 } 508 // Check that the encoding order is correct 509 for i := 1; i < len(res.Accounts); i++ { 510 if bytes.Compare(res.Accounts[i-1].Hash[:], res.Accounts[i].Hash[:]) >= 0 { 511 return fmt.Errorf("accounts not monotonically increasing: #%d [%x] vs #%d [%x]", i-1, res.Accounts[i-1].Hash[:], i, res.Accounts[i].Hash[:]) 512 } 513 } 514 var ( 515 hashes []common.Hash 516 accounts [][]byte 517 proof = res.Proof 518 ) 519 hashes, accounts, err = res.Unpack() 520 if err != nil { 521 return err 522 } 523 if len(hashes) == 0 && len(accounts) == 0 && len(proof) == 0 { 524 return nil 525 } 526 if len(hashes) > 0 { 527 if exp, got := tc.expFirst, res.Accounts[0].Hash; exp != got { 528 return fmt.Errorf("expected first account %#x, got %#x", exp, got) 529 } 530 if exp, got := tc.expLast, res.Accounts[len(res.Accounts)-1].Hash; exp != got { 531 return fmt.Errorf("expected last account %#x, got %#x", exp, got) 532 } 533 } 534 // Reconstruct a partial trie from the response and verify it 535 keys := make([][]byte, len(hashes)) 536 for i, key := range hashes { 537 keys[i] = common.CopyBytes(key[:]) 538 } 539 nodes := make(light.NodeList, len(proof)) 540 for i, node := range proof { 541 nodes[i] = node 542 } 543 proofdb := nodes.NodeSet() 544 545 var end []byte 546 if len(keys) > 0 { 547 end = keys[len(keys)-1] 548 } 549 _, err = trie.VerifyRangeProof(tc.root, tc.origin[:], end, keys, accounts, proofdb) 550 return err 551 } 552 553 func (s *Suite) snapGetStorageRanges(t *utesting.T, tc *stRangesTest) error { 554 conn, err := s.dialSnap() 555 if err != nil { 556 t.Fatalf("dial failed: %v", err) 557 } 558 defer conn.Close() 559 if err = conn.peer(s.chain, nil); err != nil { 560 t.Fatalf("peering failed: %v", err) 561 } 562 // write request 563 req := &GetStorageRanges{ 564 ID: uint64(rand.Int63()), 565 Root: tc.root, 566 Accounts: tc.accounts, 567 Origin: tc.origin, 568 Limit: tc.limit, 569 Bytes: tc.nBytes, 570 } 571 resp, err := conn.snapRequest(req, req.ID, s.chain) 572 if err != nil { 573 return fmt.Errorf("account range request failed: %v", err) 574 } 575 var res *snap.StorageRangesPacket 576 if r, ok := resp.(*StorageRanges); !ok { 577 return fmt.Errorf("account range response wrong: %T %v", resp, resp) 578 } else { 579 res = (*snap.StorageRangesPacket)(r) 580 } 581 gotSlots := 0 582 // Ensure the ranges are monotonically increasing 583 for i, slots := range res.Slots { 584 gotSlots += len(slots) 585 for j := 1; j < len(slots); j++ { 586 if bytes.Compare(slots[j-1].Hash[:], slots[j].Hash[:]) >= 0 { 587 return fmt.Errorf("storage slots not monotonically increasing for account #%d: #%d [%x] vs #%d [%x]", i, j-1, slots[j-1].Hash[:], j, slots[j].Hash[:]) 588 } 589 } 590 } 591 if exp, got := tc.expSlots, gotSlots; exp != got { 592 return fmt.Errorf("expected %d slots, got %d", exp, got) 593 } 594 return nil 595 } 596 597 func (s *Suite) snapGetByteCodes(t *utesting.T, tc *byteCodesTest) error { 598 conn, err := s.dialSnap() 599 if err != nil { 600 t.Fatalf("dial failed: %v", err) 601 } 602 defer conn.Close() 603 if err = conn.peer(s.chain, nil); err != nil { 604 t.Fatalf("peering failed: %v", err) 605 } 606 // write request 607 req := &GetByteCodes{ 608 ID: uint64(rand.Int63()), 609 Hashes: tc.hashes, 610 Bytes: tc.nBytes, 611 } 612 resp, err := conn.snapRequest(req, req.ID, s.chain) 613 if err != nil { 614 return fmt.Errorf("getBytecodes request failed: %v", err) 615 } 616 var res *snap.ByteCodesPacket 617 if r, ok := resp.(*ByteCodes); !ok { 618 return fmt.Errorf("bytecodes response wrong: %T %v", resp, resp) 619 } else { 620 res = (*snap.ByteCodesPacket)(r) 621 } 622 if exp, got := tc.expHashes, len(res.Codes); exp != got { 623 for i, c := range res.Codes { 624 fmt.Printf("%d. %#x\n", i, c) 625 } 626 return fmt.Errorf("expected %d bytecodes, got %d", exp, got) 627 } 628 // Cross reference the requested bytecodes with the response to find gaps 629 // that the serving node is missing 630 var ( 631 bytecodes = res.Codes 632 hasher = sha3.NewLegacyKeccak256().(crypto.KeccakState) 633 hash = make([]byte, 32) 634 codes = make([][]byte, len(req.Hashes)) 635 ) 636 637 for i, j := 0, 0; i < len(bytecodes); i++ { 638 // Find the next hash that we've been served, leaving misses with nils 639 hasher.Reset() 640 hasher.Write(bytecodes[i]) 641 hasher.Read(hash) 642 643 for j < len(req.Hashes) && !bytes.Equal(hash, req.Hashes[j][:]) { 644 j++ 645 } 646 if j < len(req.Hashes) { 647 codes[j] = bytecodes[i] 648 j++ 649 continue 650 } 651 // We've either ran out of hashes, or got unrequested data 652 return errors.New("unexpected bytecode") 653 } 654 655 return nil 656 } 657 658 func (s *Suite) snapGetTrieNodes(t *utesting.T, tc *trieNodesTest) error { 659 conn, err := s.dialSnap() 660 if err != nil { 661 t.Fatalf("dial failed: %v", err) 662 } 663 defer conn.Close() 664 if err = conn.peer(s.chain, nil); err != nil { 665 t.Fatalf("peering failed: %v", err) 666 } 667 // write request 668 req := &GetTrieNodes{ 669 ID: uint64(rand.Int63()), 670 Root: tc.root, 671 Paths: tc.paths, 672 Bytes: tc.nBytes, 673 } 674 resp, err := conn.snapRequest(req, req.ID, s.chain) 675 if err != nil { 676 if tc.expReject { 677 return nil 678 } 679 return fmt.Errorf("trienodes request failed: %v", err) 680 } 681 var res *snap.TrieNodesPacket 682 if r, ok := resp.(*TrieNodes); !ok { 683 return fmt.Errorf("trienodes response wrong: %T %v", resp, resp) 684 } else { 685 res = (*snap.TrieNodesPacket)(r) 686 } 687 688 // Check the correctness 689 690 // Cross reference the requested trienodes with the response to find gaps 691 // that the serving node is missing 692 hasher := sha3.NewLegacyKeccak256().(crypto.KeccakState) 693 hash := make([]byte, 32) 694 trienodes := res.Nodes 695 if got, want := len(trienodes), len(tc.expHashes); got != want { 696 return fmt.Errorf("wrong trienode count, got %d, want %d\n", got, want) 697 } 698 for i, trienode := range trienodes { 699 hasher.Reset() 700 hasher.Write(trienode) 701 hasher.Read(hash) 702 if got, want := hash, tc.expHashes[i]; !bytes.Equal(got, want[:]) { 703 fmt.Printf("hash %d wrong, got %#x, want %#x\n", i, got, want) 704 err = fmt.Errorf("hash %d wrong, got %#x, want %#x", i, got, want) 705 } 706 } 707 return err 708 }