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  }