github.com/daethereum/go-dae@v2.2.3+incompatible/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/daethereum/go-dae/common" 26 "github.com/daethereum/go-dae/crypto" 27 "github.com/daethereum/go-dae/eth/protocols/snap" 28 "github.com/daethereum/go-dae/internal/utesting" 29 "github.com/daethereum/go-dae/light" 30 "github.com/daethereum/go-dae/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 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 // TestSnapGetStorageRange 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 }, 412 { 413 // The leaf is only a couple of levels down, so the continued trie traversal causes lookup failures. 414 root: s.chain.RootAt(999), 415 paths: accPaths, 416 nBytes: 5000, 417 expHashes: []common.Hash{ 418 common.HexToHash("0xbcefee69b37cca1f5bf3a48aebe08b35f2ea1864fa958bb0723d909a0e0d28d8"), 419 common.HexToHash("0x4fb1e4e2391e4b4da471d59641319b8fa25d76c973d4bec594d7b00a69ae5135"), 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, 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}, 426 }, 427 { 428 // Basically the same as above, with different ordering 429 root: s.chain.RootAt(999), 430 paths: []snap.TrieNodePathSet{ 431 accPaths[10], accPaths[1], accPaths[0], 432 }, 433 nBytes: 5000, 434 expHashes: []common.Hash{ 435 empty, 436 common.HexToHash("0x4fb1e4e2391e4b4da471d59641319b8fa25d76c973d4bec594d7b00a69ae5135"), 437 common.HexToHash("0xbcefee69b37cca1f5bf3a48aebe08b35f2ea1864fa958bb0723d909a0e0d28d8"), 438 }, 439 }, 440 } { 441 tc := tc 442 if err := s.snapGetTrieNodes(t, &tc); err != nil { 443 t.Errorf("test %d \n #hashes %x\n root: %#x\n bytes: %d\nfailed: %v", i, len(tc.expHashes), tc.root, tc.nBytes, err) 444 } 445 } 446 } 447 448 func (s *Suite) snapGetAccountRange(t *utesting.T, tc *accRangeTest) error { 449 conn, err := s.dialSnap() 450 if err != nil { 451 t.Fatalf("dial failed: %v", err) 452 } 453 defer conn.Close() 454 if err = conn.peer(s.chain, nil); err != nil { 455 t.Fatalf("peering failed: %v", err) 456 } 457 // write request 458 req := &GetAccountRange{ 459 ID: uint64(rand.Int63()), 460 Root: tc.root, 461 Origin: tc.origin, 462 Limit: tc.limit, 463 Bytes: tc.nBytes, 464 } 465 resp, err := conn.snapRequest(req, req.ID, s.chain) 466 if err != nil { 467 return fmt.Errorf("account range request failed: %v", err) 468 } 469 var res *snap.AccountRangePacket 470 if r, ok := resp.(*AccountRange); !ok { 471 return fmt.Errorf("account range response wrong: %T %v", resp, resp) 472 } else { 473 res = (*snap.AccountRangePacket)(r) 474 } 475 if exp, got := tc.expAccounts, len(res.Accounts); exp != got { 476 return fmt.Errorf("expected %d accounts, got %d", exp, got) 477 } 478 // Check that the encoding order is correct 479 for i := 1; i < len(res.Accounts); i++ { 480 if bytes.Compare(res.Accounts[i-1].Hash[:], res.Accounts[i].Hash[:]) >= 0 { 481 return fmt.Errorf("accounts not monotonically increasing: #%d [%x] vs #%d [%x]", i-1, res.Accounts[i-1].Hash[:], i, res.Accounts[i].Hash[:]) 482 } 483 } 484 var ( 485 hashes []common.Hash 486 accounts [][]byte 487 proof = res.Proof 488 ) 489 hashes, accounts, err = res.Unpack() 490 if err != nil { 491 return err 492 } 493 if len(hashes) == 0 && len(accounts) == 0 && len(proof) == 0 { 494 return nil 495 } 496 if len(hashes) > 0 { 497 if exp, got := tc.expFirst, res.Accounts[0].Hash; exp != got { 498 return fmt.Errorf("expected first account %#x, got %#x", exp, got) 499 } 500 if exp, got := tc.expLast, res.Accounts[len(res.Accounts)-1].Hash; exp != got { 501 return fmt.Errorf("expected last account %#x, got %#x", exp, got) 502 } 503 } 504 // Reconstruct a partial trie from the response and verify it 505 keys := make([][]byte, len(hashes)) 506 for i, key := range hashes { 507 keys[i] = common.CopyBytes(key[:]) 508 } 509 nodes := make(light.NodeList, len(proof)) 510 for i, node := range proof { 511 nodes[i] = node 512 } 513 proofdb := nodes.NodeSet() 514 515 var end []byte 516 if len(keys) > 0 { 517 end = keys[len(keys)-1] 518 } 519 _, err = trie.VerifyRangeProof(tc.root, tc.origin[:], end, keys, accounts, proofdb) 520 return err 521 } 522 523 func (s *Suite) snapGetStorageRanges(t *utesting.T, tc *stRangesTest) error { 524 conn, err := s.dialSnap() 525 if err != nil { 526 t.Fatalf("dial failed: %v", err) 527 } 528 defer conn.Close() 529 if err = conn.peer(s.chain, nil); err != nil { 530 t.Fatalf("peering failed: %v", err) 531 } 532 // write request 533 req := &GetStorageRanges{ 534 ID: uint64(rand.Int63()), 535 Root: tc.root, 536 Accounts: tc.accounts, 537 Origin: tc.origin, 538 Limit: tc.limit, 539 Bytes: tc.nBytes, 540 } 541 resp, err := conn.snapRequest(req, req.ID, s.chain) 542 if err != nil { 543 return fmt.Errorf("account range request failed: %v", err) 544 } 545 var res *snap.StorageRangesPacket 546 if r, ok := resp.(*StorageRanges); !ok { 547 return fmt.Errorf("account range response wrong: %T %v", resp, resp) 548 } else { 549 res = (*snap.StorageRangesPacket)(r) 550 } 551 gotSlots := 0 552 // Ensure the ranges are monotonically increasing 553 for i, slots := range res.Slots { 554 gotSlots += len(slots) 555 for j := 1; j < len(slots); j++ { 556 if bytes.Compare(slots[j-1].Hash[:], slots[j].Hash[:]) >= 0 { 557 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[:]) 558 } 559 } 560 } 561 if exp, got := tc.expSlots, gotSlots; exp != got { 562 return fmt.Errorf("expected %d slots, got %d", exp, got) 563 } 564 return nil 565 } 566 567 func (s *Suite) snapGetByteCodes(t *utesting.T, tc *byteCodesTest) error { 568 conn, err := s.dialSnap() 569 if err != nil { 570 t.Fatalf("dial failed: %v", err) 571 } 572 defer conn.Close() 573 if err = conn.peer(s.chain, nil); err != nil { 574 t.Fatalf("peering failed: %v", err) 575 } 576 // write request 577 req := &GetByteCodes{ 578 ID: uint64(rand.Int63()), 579 Hashes: tc.hashes, 580 Bytes: tc.nBytes, 581 } 582 resp, err := conn.snapRequest(req, req.ID, s.chain) 583 if err != nil { 584 return fmt.Errorf("getBytecodes request failed: %v", err) 585 } 586 var res *snap.ByteCodesPacket 587 if r, ok := resp.(*ByteCodes); !ok { 588 return fmt.Errorf("bytecodes response wrong: %T %v", resp, resp) 589 } else { 590 res = (*snap.ByteCodesPacket)(r) 591 } 592 if exp, got := tc.expHashes, len(res.Codes); exp != got { 593 for i, c := range res.Codes { 594 fmt.Printf("%d. %#x\n", i, c) 595 } 596 return fmt.Errorf("expected %d bytecodes, got %d", exp, got) 597 } 598 // Cross reference the requested bytecodes with the response to find gaps 599 // that the serving node is missing 600 var ( 601 bytecodes = res.Codes 602 hasher = sha3.NewLegacyKeccak256().(crypto.KeccakState) 603 hash = make([]byte, 32) 604 codes = make([][]byte, len(req.Hashes)) 605 ) 606 607 for i, j := 0, 0; i < len(bytecodes); i++ { 608 // Find the next hash that we've been served, leaving misses with nils 609 hasher.Reset() 610 hasher.Write(bytecodes[i]) 611 hasher.Read(hash) 612 613 for j < len(req.Hashes) && !bytes.Equal(hash, req.Hashes[j][:]) { 614 j++ 615 } 616 if j < len(req.Hashes) { 617 codes[j] = bytecodes[i] 618 j++ 619 continue 620 } 621 // We've either ran out of hashes, or got unrequested data 622 return errors.New("unexpected bytecode") 623 } 624 625 return nil 626 } 627 628 func (s *Suite) snapGetTrieNodes(t *utesting.T, tc *trieNodesTest) error { 629 conn, err := s.dialSnap() 630 if err != nil { 631 t.Fatalf("dial failed: %v", err) 632 } 633 defer conn.Close() 634 if err = conn.peer(s.chain, nil); err != nil { 635 t.Fatalf("peering failed: %v", err) 636 } 637 // write request 638 req := &GetTrieNodes{ 639 ID: uint64(rand.Int63()), 640 Root: tc.root, 641 Paths: tc.paths, 642 Bytes: tc.nBytes, 643 } 644 resp, err := conn.snapRequest(req, req.ID, s.chain) 645 if err != nil { 646 if tc.expReject { 647 return nil 648 } 649 return fmt.Errorf("trienodes request failed: %v", err) 650 } 651 var res *snap.TrieNodesPacket 652 if r, ok := resp.(*TrieNodes); !ok { 653 return fmt.Errorf("trienodes response wrong: %T %v", resp, resp) 654 } else { 655 res = (*snap.TrieNodesPacket)(r) 656 } 657 658 // Check the correctness 659 660 // Cross reference the requested trienodes with the response to find gaps 661 // that the serving node is missing 662 hasher := sha3.NewLegacyKeccak256().(crypto.KeccakState) 663 hash := make([]byte, 32) 664 trienodes := res.Nodes 665 if got, want := len(trienodes), len(tc.expHashes); got != want { 666 return fmt.Errorf("wrong trienode count, got %d, want %d\n", got, want) 667 } 668 for i, trienode := range trienodes { 669 hasher.Reset() 670 hasher.Write(trienode) 671 hasher.Read(hash) 672 if got, want := hash, tc.expHashes[i]; !bytes.Equal(got, want[:]) { 673 fmt.Printf("hash %d wrong, got %#x, want %#x\n", i, got, want) 674 err = fmt.Errorf("hash %d wrong, got %#x, want %#x", i, got, want) 675 } 676 } 677 return err 678 }