github.com/ethereum/go-ethereum@v1.16.1/core/state/sync_test.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package state
    18  
    19  import (
    20  	"bytes"
    21  	"testing"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/core/rawdb"
    25  	"github.com/ethereum/go-ethereum/core/types"
    26  	"github.com/ethereum/go-ethereum/crypto"
    27  	"github.com/ethereum/go-ethereum/ethdb"
    28  	"github.com/ethereum/go-ethereum/rlp"
    29  	"github.com/ethereum/go-ethereum/trie"
    30  	"github.com/ethereum/go-ethereum/triedb"
    31  	"github.com/ethereum/go-ethereum/triedb/hashdb"
    32  	"github.com/ethereum/go-ethereum/triedb/pathdb"
    33  	"github.com/holiman/uint256"
    34  )
    35  
    36  // testAccount is the data associated with an account used by the state tests.
    37  type testAccount struct {
    38  	address common.Address
    39  	balance *uint256.Int
    40  	nonce   uint64
    41  	code    []byte
    42  }
    43  
    44  // makeTestState create a sample test state to test node-wise reconstruction.
    45  func makeTestState(scheme string) (ethdb.Database, Database, *triedb.Database, common.Hash, []*testAccount) {
    46  	// Create an empty state
    47  	config := &triedb.Config{Preimages: true}
    48  	if scheme == rawdb.PathScheme {
    49  		pconfig := *pathdb.Defaults
    50  		pconfig.NoAsyncFlush = true
    51  		config.PathDB = &pconfig
    52  	} else {
    53  		config.HashDB = hashdb.Defaults
    54  	}
    55  	db := rawdb.NewMemoryDatabase()
    56  	nodeDb := triedb.NewDatabase(db, config)
    57  	sdb := NewDatabase(nodeDb, nil)
    58  	state, _ := New(types.EmptyRootHash, sdb)
    59  
    60  	// Fill it with some arbitrary data
    61  	var accounts []*testAccount
    62  	for i := byte(0); i < 96; i++ {
    63  		obj := state.getOrNewStateObject(common.BytesToAddress([]byte{i}))
    64  		acc := &testAccount{address: common.BytesToAddress([]byte{i})}
    65  
    66  		obj.AddBalance(uint256.NewInt(uint64(11 * i)))
    67  		acc.balance = uint256.NewInt(uint64(11 * i))
    68  
    69  		obj.SetNonce(uint64(42 * i))
    70  		acc.nonce = uint64(42 * i)
    71  
    72  		if i%3 == 0 {
    73  			obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i}), []byte{i, i, i, i, i})
    74  			acc.code = []byte{i, i, i, i, i}
    75  		}
    76  		if i%5 == 0 {
    77  			for j := byte(0); j < 5; j++ {
    78  				hash := crypto.Keccak256Hash([]byte{i, i, i, i, i, j, j})
    79  				obj.SetState(hash, hash)
    80  			}
    81  		}
    82  		accounts = append(accounts, acc)
    83  	}
    84  	root, _ := state.Commit(0, false, false)
    85  
    86  	// Return the generated state
    87  	return db, sdb, nodeDb, root, accounts
    88  }
    89  
    90  // checkStateAccounts cross references a reconstructed state with an expected
    91  // account array.
    92  func checkStateAccounts(t *testing.T, db ethdb.Database, scheme string, root common.Hash, accounts []*testAccount) {
    93  	var config triedb.Config
    94  	if scheme == rawdb.PathScheme {
    95  		config.PathDB = pathdb.Defaults
    96  	}
    97  	// Check root availability and state contents
    98  	state, err := New(root, NewDatabase(triedb.NewDatabase(db, &config), nil))
    99  	if err != nil {
   100  		t.Fatalf("failed to create state trie at %x: %v", root, err)
   101  	}
   102  	if err := checkStateConsistency(db, scheme, root); err != nil {
   103  		t.Fatalf("inconsistent state trie at %x: %v", root, err)
   104  	}
   105  	for i, acc := range accounts {
   106  		if balance := state.GetBalance(acc.address); balance.Cmp(acc.balance) != 0 {
   107  			t.Errorf("account %d: balance mismatch: have %v, want %v", i, balance, acc.balance)
   108  		}
   109  		if nonce := state.GetNonce(acc.address); nonce != acc.nonce {
   110  			t.Errorf("account %d: nonce mismatch: have %v, want %v", i, nonce, acc.nonce)
   111  		}
   112  		if code := state.GetCode(acc.address); !bytes.Equal(code, acc.code) {
   113  			t.Errorf("account %d: code mismatch: have %x, want %x", i, code, acc.code)
   114  		}
   115  	}
   116  }
   117  
   118  // checkStateConsistency checks that all data of a state root is present.
   119  func checkStateConsistency(db ethdb.Database, scheme string, root common.Hash) error {
   120  	config := &triedb.Config{Preimages: true}
   121  	if scheme == rawdb.PathScheme {
   122  		config.PathDB = pathdb.Defaults
   123  	}
   124  	state, err := New(root, NewDatabase(triedb.NewDatabase(db, config), nil))
   125  	if err != nil {
   126  		return err
   127  	}
   128  	it := newNodeIterator(state)
   129  	for it.Next() {
   130  	}
   131  	return it.Error
   132  }
   133  
   134  // Tests that an empty state is not scheduled for syncing.
   135  func TestEmptyStateSync(t *testing.T) {
   136  	dbA := triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil)
   137  	dbB := triedb.NewDatabase(rawdb.NewMemoryDatabase(), &triedb.Config{PathDB: pathdb.Defaults})
   138  
   139  	sync := NewStateSync(types.EmptyRootHash, rawdb.NewMemoryDatabase(), nil, dbA.Scheme())
   140  	if paths, nodes, codes := sync.Missing(1); len(paths) != 0 || len(nodes) != 0 || len(codes) != 0 {
   141  		t.Errorf("content requested for empty state: %v, %v, %v", nodes, paths, codes)
   142  	}
   143  	sync = NewStateSync(types.EmptyRootHash, rawdb.NewMemoryDatabase(), nil, dbB.Scheme())
   144  	if paths, nodes, codes := sync.Missing(1); len(paths) != 0 || len(nodes) != 0 || len(codes) != 0 {
   145  		t.Errorf("content requested for empty state: %v, %v, %v", nodes, paths, codes)
   146  	}
   147  }
   148  
   149  // Tests that given a root hash, a state can sync iteratively on a single thread,
   150  // requesting retrieval tasks and returning all of them in one go.
   151  func TestIterativeStateSyncIndividual(t *testing.T) {
   152  	testIterativeStateSync(t, 1, false, false, rawdb.HashScheme)
   153  	testIterativeStateSync(t, 1, false, false, rawdb.PathScheme)
   154  }
   155  func TestIterativeStateSyncBatched(t *testing.T) {
   156  	testIterativeStateSync(t, 100, false, false, rawdb.HashScheme)
   157  	testIterativeStateSync(t, 100, false, false, rawdb.PathScheme)
   158  }
   159  func TestIterativeStateSyncIndividualFromDisk(t *testing.T) {
   160  	testIterativeStateSync(t, 1, true, false, rawdb.HashScheme)
   161  	testIterativeStateSync(t, 1, true, false, rawdb.PathScheme)
   162  }
   163  func TestIterativeStateSyncBatchedFromDisk(t *testing.T) {
   164  	testIterativeStateSync(t, 100, true, false, rawdb.HashScheme)
   165  	testIterativeStateSync(t, 100, true, false, rawdb.PathScheme)
   166  }
   167  func TestIterativeStateSyncIndividualByPath(t *testing.T) {
   168  	testIterativeStateSync(t, 1, false, true, rawdb.HashScheme)
   169  	testIterativeStateSync(t, 1, false, true, rawdb.PathScheme)
   170  }
   171  func TestIterativeStateSyncBatchedByPath(t *testing.T) {
   172  	testIterativeStateSync(t, 100, false, true, rawdb.HashScheme)
   173  	testIterativeStateSync(t, 100, false, true, rawdb.PathScheme)
   174  }
   175  
   176  // stateElement represents the element in the state trie(bytecode or trie node).
   177  type stateElement struct {
   178  	path     string
   179  	hash     common.Hash
   180  	code     common.Hash
   181  	syncPath trie.SyncPath
   182  }
   183  
   184  func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool, scheme string) {
   185  	// Create a random state to copy
   186  	srcDisk, srcDb, ndb, srcRoot, srcAccounts := makeTestState(scheme)
   187  	if commit {
   188  		ndb.Commit(srcRoot, false)
   189  	}
   190  	srcTrie, _ := trie.New(trie.StateTrieID(srcRoot), ndb)
   191  
   192  	// Create a destination state and sync with the scheduler
   193  	dstDb := rawdb.NewMemoryDatabase()
   194  	sched := NewStateSync(srcRoot, dstDb, nil, ndb.Scheme())
   195  
   196  	var (
   197  		nodeElements []stateElement
   198  		codeElements []stateElement
   199  	)
   200  	paths, nodes, codes := sched.Missing(count)
   201  	for i := 0; i < len(paths); i++ {
   202  		nodeElements = append(nodeElements, stateElement{
   203  			path:     paths[i],
   204  			hash:     nodes[i],
   205  			syncPath: trie.NewSyncPath([]byte(paths[i])),
   206  		})
   207  	}
   208  	for i := 0; i < len(codes); i++ {
   209  		codeElements = append(codeElements, stateElement{code: codes[i]})
   210  	}
   211  	reader, err := ndb.NodeReader(srcRoot)
   212  	if err != nil {
   213  		t.Fatalf("state is not existent, %#x", srcRoot)
   214  	}
   215  	cReader, err := srcDb.Reader(srcRoot)
   216  	if err != nil {
   217  		t.Fatalf("state is not existent, %#x", srcRoot)
   218  	}
   219  	for len(nodeElements)+len(codeElements) > 0 {
   220  		var (
   221  			nodeResults = make([]trie.NodeSyncResult, len(nodeElements))
   222  			codeResults = make([]trie.CodeSyncResult, len(codeElements))
   223  		)
   224  		for i, element := range codeElements {
   225  			data, err := cReader.Code(common.Address{}, element.code)
   226  			if err != nil || len(data) == 0 {
   227  				t.Fatalf("failed to retrieve contract bytecode for hash %x", element.code)
   228  			}
   229  			codeResults[i] = trie.CodeSyncResult{Hash: element.code, Data: data}
   230  		}
   231  		for i, node := range nodeElements {
   232  			if bypath {
   233  				if len(node.syncPath) == 1 {
   234  					data, _, err := srcTrie.GetNode(node.syncPath[0])
   235  					if err != nil {
   236  						t.Fatalf("failed to retrieve node data for path %x: %v", node.syncPath[0], err)
   237  					}
   238  					nodeResults[i] = trie.NodeSyncResult{Path: node.path, Data: data}
   239  				} else {
   240  					var acc types.StateAccount
   241  					if err := rlp.DecodeBytes(srcTrie.MustGet(node.syncPath[0]), &acc); err != nil {
   242  						t.Fatalf("failed to decode account on path %x: %v", node.syncPath[0], err)
   243  					}
   244  					id := trie.StorageTrieID(srcRoot, common.BytesToHash(node.syncPath[0]), acc.Root)
   245  					stTrie, err := trie.New(id, ndb)
   246  					if err != nil {
   247  						t.Fatalf("failed to retrieve storage trie for path %x: %v", node.syncPath[1], err)
   248  					}
   249  					data, _, err := stTrie.GetNode(node.syncPath[1])
   250  					if err != nil {
   251  						t.Fatalf("failed to retrieve node data for path %x: %v", node.syncPath[1], err)
   252  					}
   253  					nodeResults[i] = trie.NodeSyncResult{Path: node.path, Data: data}
   254  				}
   255  			} else {
   256  				owner, inner := trie.ResolvePath([]byte(node.path))
   257  				data, err := reader.Node(owner, inner, node.hash)
   258  				if err != nil {
   259  					t.Fatalf("failed to retrieve node data for key %v", []byte(node.path))
   260  				}
   261  				nodeResults[i] = trie.NodeSyncResult{Path: node.path, Data: data}
   262  			}
   263  		}
   264  		for _, result := range codeResults {
   265  			if err := sched.ProcessCode(result); err != nil {
   266  				t.Errorf("failed to process result %v", err)
   267  			}
   268  		}
   269  		for _, result := range nodeResults {
   270  			if err := sched.ProcessNode(result); err != nil {
   271  				t.Errorf("failed to process result %v", err)
   272  			}
   273  		}
   274  		batch := dstDb.NewBatch()
   275  		if err := sched.Commit(batch); err != nil {
   276  			t.Fatalf("failed to commit data: %v", err)
   277  		}
   278  		batch.Write()
   279  
   280  		paths, nodes, codes = sched.Missing(count)
   281  		nodeElements = nodeElements[:0]
   282  		for i := 0; i < len(paths); i++ {
   283  			nodeElements = append(nodeElements, stateElement{
   284  				path:     paths[i],
   285  				hash:     nodes[i],
   286  				syncPath: trie.NewSyncPath([]byte(paths[i])),
   287  			})
   288  		}
   289  		codeElements = codeElements[:0]
   290  		for i := 0; i < len(codes); i++ {
   291  			codeElements = append(codeElements, stateElement{
   292  				code: codes[i],
   293  			})
   294  		}
   295  	}
   296  	// Copy the preimages from source db in order to traverse the state.
   297  	srcDb.TrieDB().WritePreimages()
   298  	copyPreimages(srcDisk, dstDb)
   299  
   300  	// Cross check that the two states are in sync
   301  	checkStateAccounts(t, dstDb, ndb.Scheme(), srcRoot, srcAccounts)
   302  }
   303  
   304  // Tests that the trie scheduler can correctly reconstruct the state even if only
   305  // partial results are returned, and the others sent only later.
   306  func TestIterativeDelayedStateSync(t *testing.T) {
   307  	testIterativeDelayedStateSync(t, rawdb.HashScheme)
   308  	testIterativeDelayedStateSync(t, rawdb.PathScheme)
   309  }
   310  
   311  func testIterativeDelayedStateSync(t *testing.T, scheme string) {
   312  	// Create a random state to copy
   313  	srcDisk, srcDb, ndb, srcRoot, srcAccounts := makeTestState(scheme)
   314  
   315  	// Create a destination state and sync with the scheduler
   316  	dstDb := rawdb.NewMemoryDatabase()
   317  	sched := NewStateSync(srcRoot, dstDb, nil, ndb.Scheme())
   318  
   319  	var (
   320  		nodeElements []stateElement
   321  		codeElements []stateElement
   322  	)
   323  	paths, nodes, codes := sched.Missing(0)
   324  	for i := 0; i < len(paths); i++ {
   325  		nodeElements = append(nodeElements, stateElement{
   326  			path:     paths[i],
   327  			hash:     nodes[i],
   328  			syncPath: trie.NewSyncPath([]byte(paths[i])),
   329  		})
   330  	}
   331  	for i := 0; i < len(codes); i++ {
   332  		codeElements = append(codeElements, stateElement{code: codes[i]})
   333  	}
   334  	reader, err := ndb.NodeReader(srcRoot)
   335  	if err != nil {
   336  		t.Fatalf("state is not existent, %#x", srcRoot)
   337  	}
   338  	cReader, err := srcDb.Reader(srcRoot)
   339  	if err != nil {
   340  		t.Fatalf("state is not existent, %#x", srcRoot)
   341  	}
   342  	for len(nodeElements)+len(codeElements) > 0 {
   343  		// Sync only half of the scheduled nodes
   344  		var nodeProcessed int
   345  		var codeProcessed int
   346  		if len(codeElements) > 0 {
   347  			codeResults := make([]trie.CodeSyncResult, len(codeElements)/2+1)
   348  			for i, element := range codeElements[:len(codeResults)] {
   349  				data, err := cReader.Code(common.Address{}, element.code)
   350  				if err != nil || len(data) == 0 {
   351  					t.Fatalf("failed to retrieve contract bytecode for %x", element.code)
   352  				}
   353  				codeResults[i] = trie.CodeSyncResult{Hash: element.code, Data: data}
   354  			}
   355  			for _, result := range codeResults {
   356  				if err := sched.ProcessCode(result); err != nil {
   357  					t.Fatalf("failed to process result %v", err)
   358  				}
   359  			}
   360  			codeProcessed = len(codeResults)
   361  		}
   362  		if len(nodeElements) > 0 {
   363  			nodeResults := make([]trie.NodeSyncResult, len(nodeElements)/2+1)
   364  			for i, element := range nodeElements[:len(nodeResults)] {
   365  				owner, inner := trie.ResolvePath([]byte(element.path))
   366  				data, err := reader.Node(owner, inner, element.hash)
   367  				if err != nil {
   368  					t.Fatalf("failed to retrieve contract bytecode for %x", element.code)
   369  				}
   370  				nodeResults[i] = trie.NodeSyncResult{Path: element.path, Data: data}
   371  			}
   372  			for _, result := range nodeResults {
   373  				if err := sched.ProcessNode(result); err != nil {
   374  					t.Fatalf("failed to process result %v", err)
   375  				}
   376  			}
   377  			nodeProcessed = len(nodeResults)
   378  		}
   379  		batch := dstDb.NewBatch()
   380  		if err := sched.Commit(batch); err != nil {
   381  			t.Fatalf("failed to commit data: %v", err)
   382  		}
   383  		batch.Write()
   384  
   385  		paths, nodes, codes = sched.Missing(0)
   386  		nodeElements = nodeElements[nodeProcessed:]
   387  		for i := 0; i < len(paths); i++ {
   388  			nodeElements = append(nodeElements, stateElement{
   389  				path:     paths[i],
   390  				hash:     nodes[i],
   391  				syncPath: trie.NewSyncPath([]byte(paths[i])),
   392  			})
   393  		}
   394  		codeElements = codeElements[codeProcessed:]
   395  		for i := 0; i < len(codes); i++ {
   396  			codeElements = append(codeElements, stateElement{
   397  				code: codes[i],
   398  			})
   399  		}
   400  	}
   401  	// Copy the preimages from source db in order to traverse the state.
   402  	srcDb.TrieDB().WritePreimages()
   403  	copyPreimages(srcDisk, dstDb)
   404  
   405  	// Cross check that the two states are in sync
   406  	checkStateAccounts(t, dstDb, ndb.Scheme(), srcRoot, srcAccounts)
   407  }
   408  
   409  // Tests that given a root hash, a trie can sync iteratively on a single thread,
   410  // requesting retrieval tasks and returning all of them in one go, however in a
   411  // random order.
   412  func TestIterativeRandomStateSyncIndividual(t *testing.T) {
   413  	testIterativeRandomStateSync(t, 1, rawdb.HashScheme)
   414  	testIterativeRandomStateSync(t, 1, rawdb.PathScheme)
   415  }
   416  func TestIterativeRandomStateSyncBatched(t *testing.T) {
   417  	testIterativeRandomStateSync(t, 100, rawdb.HashScheme)
   418  	testIterativeRandomStateSync(t, 100, rawdb.PathScheme)
   419  }
   420  
   421  func testIterativeRandomStateSync(t *testing.T, count int, scheme string) {
   422  	// Create a random state to copy
   423  	srcDisk, srcDb, ndb, srcRoot, srcAccounts := makeTestState(scheme)
   424  
   425  	// Create a destination state and sync with the scheduler
   426  	dstDb := rawdb.NewMemoryDatabase()
   427  	sched := NewStateSync(srcRoot, dstDb, nil, ndb.Scheme())
   428  
   429  	nodeQueue := make(map[string]stateElement)
   430  	codeQueue := make(map[common.Hash]struct{})
   431  	paths, nodes, codes := sched.Missing(count)
   432  	for i, path := range paths {
   433  		nodeQueue[path] = stateElement{
   434  			path:     path,
   435  			hash:     nodes[i],
   436  			syncPath: trie.NewSyncPath([]byte(path)),
   437  		}
   438  	}
   439  	for _, hash := range codes {
   440  		codeQueue[hash] = struct{}{}
   441  	}
   442  	reader, err := ndb.NodeReader(srcRoot)
   443  	if err != nil {
   444  		t.Fatalf("state is not existent, %#x", srcRoot)
   445  	}
   446  	cReader, err := srcDb.Reader(srcRoot)
   447  	if err != nil {
   448  		t.Fatalf("state is not existent, %#x", srcRoot)
   449  	}
   450  	for len(nodeQueue)+len(codeQueue) > 0 {
   451  		// Fetch all the queued nodes in a random order
   452  		if len(codeQueue) > 0 {
   453  			results := make([]trie.CodeSyncResult, 0, len(codeQueue))
   454  			for hash := range codeQueue {
   455  				data, err := cReader.Code(common.Address{}, hash)
   456  				if err != nil || len(data) == 0 {
   457  					t.Fatalf("failed to retrieve node data for %x", hash)
   458  				}
   459  				results = append(results, trie.CodeSyncResult{Hash: hash, Data: data})
   460  			}
   461  			for _, result := range results {
   462  				if err := sched.ProcessCode(result); err != nil {
   463  					t.Fatalf("failed to process result %v", err)
   464  				}
   465  			}
   466  		}
   467  		if len(nodeQueue) > 0 {
   468  			results := make([]trie.NodeSyncResult, 0, len(nodeQueue))
   469  			for path, element := range nodeQueue {
   470  				owner, inner := trie.ResolvePath([]byte(element.path))
   471  				data, err := reader.Node(owner, inner, element.hash)
   472  				if err != nil {
   473  					t.Fatalf("failed to retrieve node data for %x %v %v", element.hash, []byte(element.path), element.path)
   474  				}
   475  				results = append(results, trie.NodeSyncResult{Path: path, Data: data})
   476  			}
   477  			for _, result := range results {
   478  				if err := sched.ProcessNode(result); err != nil {
   479  					t.Fatalf("failed to process result %v", err)
   480  				}
   481  			}
   482  		}
   483  		batch := dstDb.NewBatch()
   484  		if err := sched.Commit(batch); err != nil {
   485  			t.Fatalf("failed to commit data: %v", err)
   486  		}
   487  		batch.Write()
   488  
   489  		nodeQueue = make(map[string]stateElement)
   490  		codeQueue = make(map[common.Hash]struct{})
   491  		paths, nodes, codes := sched.Missing(count)
   492  		for i, path := range paths {
   493  			nodeQueue[path] = stateElement{
   494  				path:     path,
   495  				hash:     nodes[i],
   496  				syncPath: trie.NewSyncPath([]byte(path)),
   497  			}
   498  		}
   499  		for _, hash := range codes {
   500  			codeQueue[hash] = struct{}{}
   501  		}
   502  	}
   503  	// Copy the preimages from source db in order to traverse the state.
   504  	srcDb.TrieDB().WritePreimages()
   505  	copyPreimages(srcDisk, dstDb)
   506  
   507  	// Cross check that the two states are in sync
   508  	checkStateAccounts(t, dstDb, ndb.Scheme(), srcRoot, srcAccounts)
   509  }
   510  
   511  // Tests that the trie scheduler can correctly reconstruct the state even if only
   512  // partial results are returned (Even those randomly), others sent only later.
   513  func TestIterativeRandomDelayedStateSync(t *testing.T) {
   514  	testIterativeRandomDelayedStateSync(t, rawdb.HashScheme)
   515  	testIterativeRandomDelayedStateSync(t, rawdb.PathScheme)
   516  }
   517  
   518  func testIterativeRandomDelayedStateSync(t *testing.T, scheme string) {
   519  	// Create a random state to copy
   520  	srcDisk, srcDb, ndb, srcRoot, srcAccounts := makeTestState(scheme)
   521  
   522  	// Create a destination state and sync with the scheduler
   523  	dstDb := rawdb.NewMemoryDatabase()
   524  	sched := NewStateSync(srcRoot, dstDb, nil, ndb.Scheme())
   525  
   526  	nodeQueue := make(map[string]stateElement)
   527  	codeQueue := make(map[common.Hash]struct{})
   528  	paths, nodes, codes := sched.Missing(0)
   529  	for i, path := range paths {
   530  		nodeQueue[path] = stateElement{
   531  			path:     path,
   532  			hash:     nodes[i],
   533  			syncPath: trie.NewSyncPath([]byte(path)),
   534  		}
   535  	}
   536  	for _, hash := range codes {
   537  		codeQueue[hash] = struct{}{}
   538  	}
   539  	reader, err := ndb.NodeReader(srcRoot)
   540  	if err != nil {
   541  		t.Fatalf("state is not existent, %#x", srcRoot)
   542  	}
   543  	cReader, err := srcDb.Reader(srcRoot)
   544  	if err != nil {
   545  		t.Fatalf("state is not existent, %#x", srcRoot)
   546  	}
   547  	for len(nodeQueue)+len(codeQueue) > 0 {
   548  		// Sync only half of the scheduled nodes, even those in random order
   549  		if len(codeQueue) > 0 {
   550  			results := make([]trie.CodeSyncResult, 0, len(codeQueue)/2+1)
   551  			for hash := range codeQueue {
   552  				delete(codeQueue, hash)
   553  
   554  				data, err := cReader.Code(common.Address{}, hash)
   555  				if err != nil || len(data) == 0 {
   556  					t.Fatalf("failed to retrieve node data for %x", hash)
   557  				}
   558  				results = append(results, trie.CodeSyncResult{Hash: hash, Data: data})
   559  
   560  				if len(results) >= cap(results) {
   561  					break
   562  				}
   563  			}
   564  			for _, result := range results {
   565  				if err := sched.ProcessCode(result); err != nil {
   566  					t.Fatalf("failed to process result %v", err)
   567  				}
   568  			}
   569  		}
   570  		if len(nodeQueue) > 0 {
   571  			results := make([]trie.NodeSyncResult, 0, len(nodeQueue)/2+1)
   572  			for path, element := range nodeQueue {
   573  				delete(nodeQueue, path)
   574  
   575  				owner, inner := trie.ResolvePath([]byte(element.path))
   576  				data, err := reader.Node(owner, inner, element.hash)
   577  				if err != nil {
   578  					t.Fatalf("failed to retrieve node data for %x", element.hash)
   579  				}
   580  				results = append(results, trie.NodeSyncResult{Path: path, Data: data})
   581  
   582  				if len(results) >= cap(results) {
   583  					break
   584  				}
   585  			}
   586  			// Feed the retrieved results back and queue new tasks
   587  			for _, result := range results {
   588  				if err := sched.ProcessNode(result); err != nil {
   589  					t.Fatalf("failed to process result %v", err)
   590  				}
   591  			}
   592  		}
   593  		batch := dstDb.NewBatch()
   594  		if err := sched.Commit(batch); err != nil {
   595  			t.Fatalf("failed to commit data: %v", err)
   596  		}
   597  		batch.Write()
   598  
   599  		paths, nodes, codes := sched.Missing(0)
   600  		for i, path := range paths {
   601  			nodeQueue[path] = stateElement{
   602  				path:     path,
   603  				hash:     nodes[i],
   604  				syncPath: trie.NewSyncPath([]byte(path)),
   605  			}
   606  		}
   607  		for _, hash := range codes {
   608  			codeQueue[hash] = struct{}{}
   609  		}
   610  	}
   611  	// Copy the preimages from source db in order to traverse the state.
   612  	srcDb.TrieDB().WritePreimages()
   613  	copyPreimages(srcDisk, dstDb)
   614  
   615  	// Cross check that the two states are in sync
   616  	checkStateAccounts(t, dstDb, ndb.Scheme(), srcRoot, srcAccounts)
   617  }
   618  
   619  // Tests that at any point in time during a sync, only complete sub-tries are in
   620  // the database.
   621  func TestIncompleteStateSync(t *testing.T) {
   622  	testIncompleteStateSync(t, rawdb.HashScheme)
   623  	testIncompleteStateSync(t, rawdb.PathScheme)
   624  }
   625  
   626  func testIncompleteStateSync(t *testing.T, scheme string) {
   627  	// Create a random state to copy
   628  	db, srcDb, ndb, srcRoot, srcAccounts := makeTestState(scheme)
   629  
   630  	// isCodeLookup to save some hashing
   631  	var isCode = make(map[common.Hash]struct{})
   632  	for _, acc := range srcAccounts {
   633  		if len(acc.code) > 0 {
   634  			isCode[crypto.Keccak256Hash(acc.code)] = struct{}{}
   635  		}
   636  	}
   637  	isCode[types.EmptyCodeHash] = struct{}{}
   638  
   639  	// Create a destination state and sync with the scheduler
   640  	dstDb := rawdb.NewMemoryDatabase()
   641  	sched := NewStateSync(srcRoot, dstDb, nil, ndb.Scheme())
   642  
   643  	var (
   644  		addedCodes  []common.Hash
   645  		addedPaths  []string
   646  		addedHashes []common.Hash
   647  	)
   648  	reader, err := ndb.NodeReader(srcRoot)
   649  	if err != nil {
   650  		t.Fatalf("state is not available %x", srcRoot)
   651  	}
   652  	cReader, err := srcDb.Reader(srcRoot)
   653  	if err != nil {
   654  		t.Fatalf("state is not existent, %#x", srcRoot)
   655  	}
   656  	nodeQueue := make(map[string]stateElement)
   657  	codeQueue := make(map[common.Hash]struct{})
   658  	paths, nodes, codes := sched.Missing(1)
   659  	for i, path := range paths {
   660  		nodeQueue[path] = stateElement{
   661  			path:     path,
   662  			hash:     nodes[i],
   663  			syncPath: trie.NewSyncPath([]byte(path)),
   664  		}
   665  	}
   666  	for _, hash := range codes {
   667  		codeQueue[hash] = struct{}{}
   668  	}
   669  	for len(nodeQueue)+len(codeQueue) > 0 {
   670  		// Fetch a batch of state nodes
   671  		if len(codeQueue) > 0 {
   672  			results := make([]trie.CodeSyncResult, 0, len(codeQueue))
   673  			for hash := range codeQueue {
   674  				data, err := cReader.Code(common.Address{}, hash)
   675  				if err != nil || len(data) == 0 {
   676  					t.Fatalf("failed to retrieve node data for %x", hash)
   677  				}
   678  				results = append(results, trie.CodeSyncResult{Hash: hash, Data: data})
   679  				addedCodes = append(addedCodes, hash)
   680  			}
   681  			// Process each of the state nodes
   682  			for _, result := range results {
   683  				if err := sched.ProcessCode(result); err != nil {
   684  					t.Fatalf("failed to process result %v", err)
   685  				}
   686  			}
   687  		}
   688  		if len(nodeQueue) > 0 {
   689  			results := make([]trie.NodeSyncResult, 0, len(nodeQueue))
   690  			for path, element := range nodeQueue {
   691  				owner, inner := trie.ResolvePath([]byte(element.path))
   692  				data, err := reader.Node(owner, inner, element.hash)
   693  				if err != nil {
   694  					t.Fatalf("failed to retrieve node data for %x", element.hash)
   695  				}
   696  				results = append(results, trie.NodeSyncResult{Path: path, Data: data})
   697  
   698  				if element.hash != srcRoot {
   699  					addedPaths = append(addedPaths, element.path)
   700  					addedHashes = append(addedHashes, element.hash)
   701  				}
   702  			}
   703  			// Process each of the state nodes
   704  			for _, result := range results {
   705  				if err := sched.ProcessNode(result); err != nil {
   706  					t.Fatalf("failed to process result %v", err)
   707  				}
   708  			}
   709  		}
   710  		batch := dstDb.NewBatch()
   711  		if err := sched.Commit(batch); err != nil {
   712  			t.Fatalf("failed to commit data: %v", err)
   713  		}
   714  		batch.Write()
   715  
   716  		// Fetch the next batch to retrieve
   717  		nodeQueue = make(map[string]stateElement)
   718  		codeQueue = make(map[common.Hash]struct{})
   719  		paths, nodes, codes := sched.Missing(1)
   720  		for i, path := range paths {
   721  			nodeQueue[path] = stateElement{
   722  				path:     path,
   723  				hash:     nodes[i],
   724  				syncPath: trie.NewSyncPath([]byte(path)),
   725  			}
   726  		}
   727  		for _, hash := range codes {
   728  			codeQueue[hash] = struct{}{}
   729  		}
   730  	}
   731  	// Copy the preimages from source db in order to traverse the state.
   732  	srcDb.TrieDB().WritePreimages()
   733  	copyPreimages(db, dstDb)
   734  
   735  	// Sanity check that removing any node from the database is detected
   736  	for _, node := range addedCodes {
   737  		val := rawdb.ReadCode(dstDb, node)
   738  		if len(val) == 0 {
   739  			t.Logf("no code: %v", node)
   740  		} else {
   741  			t.Logf("has code: %v", node)
   742  		}
   743  		rawdb.DeleteCode(dstDb, node)
   744  		if err := checkStateConsistency(dstDb, ndb.Scheme(), srcRoot); err == nil {
   745  			t.Errorf("trie inconsistency not caught, missing: %x", node)
   746  		}
   747  		rawdb.WriteCode(dstDb, node, val)
   748  	}
   749  	for i, path := range addedPaths {
   750  		owner, inner := trie.ResolvePath([]byte(path))
   751  		hash := addedHashes[i]
   752  		val := rawdb.ReadTrieNode(dstDb, owner, inner, hash, scheme)
   753  		if val == nil {
   754  			t.Error("missing trie node")
   755  		}
   756  		rawdb.DeleteTrieNode(dstDb, owner, inner, hash, scheme)
   757  		if err := checkStateConsistency(dstDb, scheme, srcRoot); err == nil {
   758  			t.Errorf("trie inconsistency not caught, missing: %v", path)
   759  		}
   760  		rawdb.WriteTrieNode(dstDb, owner, inner, hash, val, scheme)
   761  	}
   762  }
   763  
   764  func copyPreimages(srcDb, dstDb ethdb.Database) {
   765  	it := srcDb.NewIterator(rawdb.PreimagePrefix, nil)
   766  	defer it.Release()
   767  
   768  	preimages := make(map[common.Hash][]byte)
   769  	for it.Next() {
   770  		hash := it.Key()[len(rawdb.PreimagePrefix):]
   771  		preimages[common.BytesToHash(hash)] = common.CopyBytes(it.Value())
   772  	}
   773  	rawdb.WritePreimages(dstDb, preimages)
   774  }