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  }