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