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