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

     1  // Copyright 2019 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 snapshot
    18  
    19  import (
    20  	"fmt"
    21  	"os"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/ethereum/go-ethereum/common"
    26  	"github.com/ethereum/go-ethereum/core/rawdb"
    27  	"github.com/ethereum/go-ethereum/core/types"
    28  	"github.com/ethereum/go-ethereum/ethdb"
    29  	"github.com/ethereum/go-ethereum/log"
    30  	"github.com/ethereum/go-ethereum/rlp"
    31  	"github.com/ethereum/go-ethereum/trie"
    32  	"github.com/ethereum/go-ethereum/trie/trienode"
    33  	"github.com/ethereum/go-ethereum/triedb"
    34  	"github.com/ethereum/go-ethereum/triedb/hashdb"
    35  	"github.com/ethereum/go-ethereum/triedb/pathdb"
    36  	"github.com/holiman/uint256"
    37  	"golang.org/x/crypto/sha3"
    38  )
    39  
    40  func hashData(input []byte) common.Hash {
    41  	var hasher = sha3.NewLegacyKeccak256()
    42  	var hash common.Hash
    43  	hasher.Reset()
    44  	hasher.Write(input)
    45  	hasher.Sum(hash[:0])
    46  	return hash
    47  }
    48  
    49  // Tests that snapshot generation from an empty database.
    50  func TestGeneration(t *testing.T) {
    51  	testGeneration(t, rawdb.HashScheme)
    52  	testGeneration(t, rawdb.PathScheme)
    53  }
    54  
    55  func testGeneration(t *testing.T, scheme string) {
    56  	// We can't use statedb to make a test trie (circular dependency), so make
    57  	// a fake one manually. We're going with a small account trie of 3 accounts,
    58  	// two of which also has the same 3-slot storage trie attached.
    59  	var helper = newHelper(scheme)
    60  	stRoot := helper.makeStorageTrie("", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false)
    61  
    62  	helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
    63  	helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
    64  	helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
    65  
    66  	helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
    67  	helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
    68  
    69  	root, snap := helper.CommitAndGenerate()
    70  	if have, want := root, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"); have != want {
    71  		t.Fatalf("have %#x want %#x", have, want)
    72  	}
    73  	select {
    74  	case <-snap.genPending:
    75  		// Snapshot generation succeeded
    76  
    77  	case <-time.After(3 * time.Second):
    78  		t.Errorf("Snapshot generation failed")
    79  	}
    80  	checkSnapRoot(t, snap, root)
    81  
    82  	// Signal abortion to the generator and wait for it to tear down
    83  	stop := make(chan *generatorStats)
    84  	snap.genAbort <- stop
    85  	<-stop
    86  }
    87  
    88  // Tests that snapshot generation with existent flat state.
    89  func TestGenerateExistentState(t *testing.T) {
    90  	testGenerateExistentState(t, rawdb.HashScheme)
    91  	testGenerateExistentState(t, rawdb.PathScheme)
    92  }
    93  
    94  func testGenerateExistentState(t *testing.T, scheme string) {
    95  	// We can't use statedb to make a test trie (circular dependency), so make
    96  	// a fake one manually. We're going with a small account trie of 3 accounts,
    97  	// two of which also has the same 3-slot storage trie attached.
    98  	var helper = newHelper(scheme)
    99  
   100  	stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   101  	helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   102  	helper.addSnapAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   103  	helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   104  
   105  	helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
   106  	helper.addSnapAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
   107  
   108  	stRoot = helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   109  	helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   110  	helper.addSnapAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   111  	helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   112  
   113  	root, snap := helper.CommitAndGenerate()
   114  	select {
   115  	case <-snap.genPending:
   116  		// Snapshot generation succeeded
   117  
   118  	case <-time.After(3 * time.Second):
   119  		t.Errorf("Snapshot generation failed")
   120  	}
   121  	checkSnapRoot(t, snap, root)
   122  
   123  	// Signal abortion to the generator and wait for it to tear down
   124  	stop := make(chan *generatorStats)
   125  	snap.genAbort <- stop
   126  	<-stop
   127  }
   128  
   129  func checkSnapRoot(t *testing.T, snap *diskLayer, trieRoot common.Hash) {
   130  	t.Helper()
   131  
   132  	accIt := snap.AccountIterator(common.Hash{})
   133  	defer accIt.Release()
   134  
   135  	snapRoot, err := generateTrieRoot(nil, "", accIt, common.Hash{}, stackTrieGenerate,
   136  		func(db ethdb.KeyValueWriter, accountHash, codeHash common.Hash, stat *generateStats) (common.Hash, error) {
   137  			storageIt := snap.StorageIterator(accountHash, common.Hash{})
   138  			defer storageIt.Release()
   139  
   140  			hash, err := generateTrieRoot(nil, "", storageIt, accountHash, stackTrieGenerate, nil, stat, false)
   141  			if err != nil {
   142  				return common.Hash{}, err
   143  			}
   144  			return hash, nil
   145  		}, newGenerateStats(), true)
   146  	if err != nil {
   147  		t.Fatal(err)
   148  	}
   149  	if snapRoot != trieRoot {
   150  		t.Fatalf("snaproot: %#x != trieroot #%x", snapRoot, trieRoot)
   151  	}
   152  	if err := CheckDanglingStorage(snap.diskdb); err != nil {
   153  		t.Fatalf("Detected dangling storages: %v", err)
   154  	}
   155  }
   156  
   157  type testHelper struct {
   158  	diskdb  ethdb.Database
   159  	triedb  *triedb.Database
   160  	accTrie *trie.StateTrie
   161  	nodes   *trienode.MergedNodeSet
   162  	states  *triedb.StateSet
   163  }
   164  
   165  func newHelper(scheme string) *testHelper {
   166  	diskdb := rawdb.NewMemoryDatabase()
   167  	config := &triedb.Config{}
   168  	if scheme == rawdb.PathScheme {
   169  		config.PathDB = &pathdb.Config{
   170  			SnapshotNoBuild: true,
   171  			NoAsyncFlush:    true,
   172  		} // disable caching
   173  	} else {
   174  		config.HashDB = &hashdb.Config{} // disable caching
   175  	}
   176  	db := triedb.NewDatabase(diskdb, config)
   177  	accTrie, _ := trie.NewStateTrie(trie.StateTrieID(types.EmptyRootHash), db)
   178  	return &testHelper{
   179  		diskdb:  diskdb,
   180  		triedb:  db,
   181  		accTrie: accTrie,
   182  		nodes:   trienode.NewMergedNodeSet(),
   183  		states:  triedb.NewStateSet(),
   184  	}
   185  }
   186  
   187  func (t *testHelper) addTrieAccount(acckey string, acc *types.StateAccount) {
   188  	val, _ := rlp.EncodeToBytes(acc)
   189  	t.accTrie.MustUpdate([]byte(acckey), val)
   190  
   191  	accHash := hashData([]byte(acckey))
   192  	t.states.Accounts[accHash] = val
   193  	t.states.AccountsOrigin[common.BytesToAddress([]byte(acckey))] = nil
   194  }
   195  
   196  func (t *testHelper) addSnapAccount(acckey string, acc *types.StateAccount) {
   197  	key := hashData([]byte(acckey))
   198  	rawdb.WriteAccountSnapshot(t.diskdb, key, types.SlimAccountRLP(*acc))
   199  }
   200  
   201  func (t *testHelper) addAccount(acckey string, acc *types.StateAccount) {
   202  	t.addTrieAccount(acckey, acc)
   203  	t.addSnapAccount(acckey, acc)
   204  }
   205  
   206  func (t *testHelper) addSnapStorage(accKey string, keys []string, vals []string) {
   207  	accHash := hashData([]byte(accKey))
   208  	for i, key := range keys {
   209  		rawdb.WriteStorageSnapshot(t.diskdb, accHash, hashData([]byte(key)), []byte(vals[i]))
   210  	}
   211  }
   212  
   213  func (t *testHelper) makeStorageTrie(accKey string, keys []string, vals []string, commit bool) common.Hash {
   214  	owner := hashData([]byte(accKey))
   215  	addr := common.BytesToAddress([]byte(accKey))
   216  	id := trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash)
   217  	stTrie, _ := trie.NewStateTrie(id, t.triedb)
   218  	for i, k := range keys {
   219  		stTrie.MustUpdate([]byte(k), []byte(vals[i]))
   220  		if t.states.Storages[owner] == nil {
   221  			t.states.Storages[owner] = make(map[common.Hash][]byte)
   222  		}
   223  		if t.states.StoragesOrigin[addr] == nil {
   224  			t.states.StoragesOrigin[addr] = make(map[common.Hash][]byte)
   225  		}
   226  		t.states.Storages[owner][hashData([]byte(k))] = []byte(vals[i])
   227  		t.states.StoragesOrigin[addr][hashData([]byte(k))] = nil
   228  	}
   229  	if !commit {
   230  		return stTrie.Hash()
   231  	}
   232  	root, nodes := stTrie.Commit(false)
   233  	if nodes != nil {
   234  		t.nodes.Merge(nodes)
   235  	}
   236  	return root
   237  }
   238  
   239  func (t *testHelper) Commit() common.Hash {
   240  	root, nodes := t.accTrie.Commit(true)
   241  	if nodes != nil {
   242  		t.nodes.Merge(nodes)
   243  	}
   244  	t.triedb.Update(root, types.EmptyRootHash, 0, t.nodes, t.states)
   245  	t.triedb.Commit(root, false)
   246  	return root
   247  }
   248  
   249  func (t *testHelper) CommitAndGenerate() (common.Hash, *diskLayer) {
   250  	root := t.Commit()
   251  	snap := generateSnapshot(t.diskdb, t.triedb, 16, root)
   252  	return root, snap
   253  }
   254  
   255  // Tests that snapshot generation with existent flat state, where the flat state
   256  // contains some errors:
   257  // - the contract with empty storage root but has storage entries in the disk
   258  // - the contract with non empty storage root but empty storage slots
   259  // - the contract(non-empty storage) misses some storage slots
   260  //   - miss in the beginning
   261  //   - miss in the middle
   262  //   - miss in the end
   263  //
   264  // - the contract(non-empty storage) has wrong storage slots
   265  //   - wrong slots in the beginning
   266  //   - wrong slots in the middle
   267  //   - wrong slots in the end
   268  //
   269  // - the contract(non-empty storage) has extra storage slots
   270  //   - extra slots in the beginning
   271  //   - extra slots in the middle
   272  //   - extra slots in the end
   273  func TestGenerateExistentStateWithWrongStorage(t *testing.T) {
   274  	testGenerateExistentStateWithWrongStorage(t, rawdb.HashScheme)
   275  	testGenerateExistentStateWithWrongStorage(t, rawdb.PathScheme)
   276  }
   277  
   278  func testGenerateExistentStateWithWrongStorage(t *testing.T, scheme string) {
   279  	helper := newHelper(scheme)
   280  
   281  	// Account one, empty root but non-empty database
   282  	helper.addAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
   283  	helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   284  
   285  	// Account two, non empty root but empty database
   286  	stRoot := helper.makeStorageTrie("acc-2", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   287  	helper.addAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   288  
   289  	// Miss slots
   290  	{
   291  		// Account three, non empty root but misses slots in the beginning
   292  		helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   293  		helper.addAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   294  		helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"})
   295  
   296  		// Account four, non empty root but misses slots in the middle
   297  		helper.makeStorageTrie("acc-4", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   298  		helper.addAccount("acc-4", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   299  		helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"})
   300  
   301  		// Account five, non empty root but misses slots in the end
   302  		helper.makeStorageTrie("acc-5", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   303  		helper.addAccount("acc-5", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   304  		helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"})
   305  	}
   306  
   307  	// Wrong storage slots
   308  	{
   309  		// Account six, non empty root but wrong slots in the beginning
   310  		helper.makeStorageTrie("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   311  		helper.addAccount("acc-6", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   312  		helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"})
   313  
   314  		// Account seven, non empty root but wrong slots in the middle
   315  		helper.makeStorageTrie("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   316  		helper.addAccount("acc-7", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   317  		helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"})
   318  
   319  		// Account eight, non empty root but wrong slots in the end
   320  		helper.makeStorageTrie("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   321  		helper.addAccount("acc-8", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   322  		helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"})
   323  
   324  		// Account 9, non empty root but rotated slots
   325  		helper.makeStorageTrie("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   326  		helper.addAccount("acc-9", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   327  		helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"})
   328  	}
   329  
   330  	// Extra storage slots
   331  	{
   332  		// Account 10, non empty root but extra slots in the beginning
   333  		helper.makeStorageTrie("acc-10", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   334  		helper.addAccount("acc-10", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   335  		helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"})
   336  
   337  		// Account 11, non empty root but extra slots in the middle
   338  		helper.makeStorageTrie("acc-11", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   339  		helper.addAccount("acc-11", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   340  		helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"})
   341  
   342  		// Account 12, non empty root but extra slots in the end
   343  		helper.makeStorageTrie("acc-12", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   344  		helper.addAccount("acc-12", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   345  		helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"})
   346  	}
   347  
   348  	root, snap := helper.CommitAndGenerate()
   349  	t.Logf("Root: %#x\n", root) // Root = 0x8746cce9fd9c658b2cfd639878ed6584b7a2b3e73bb40f607fcfa156002429a0
   350  
   351  	select {
   352  	case <-snap.genPending:
   353  		// Snapshot generation succeeded
   354  
   355  	case <-time.After(3 * time.Second):
   356  		t.Errorf("Snapshot generation failed")
   357  	}
   358  	checkSnapRoot(t, snap, root)
   359  	// Signal abortion to the generator and wait for it to tear down
   360  	stop := make(chan *generatorStats)
   361  	snap.genAbort <- stop
   362  	<-stop
   363  }
   364  
   365  // Tests that snapshot generation with existent flat state, where the flat state
   366  // contains some errors:
   367  // - miss accounts
   368  // - wrong accounts
   369  // - extra accounts
   370  func TestGenerateExistentStateWithWrongAccounts(t *testing.T) {
   371  	testGenerateExistentStateWithWrongAccounts(t, rawdb.HashScheme)
   372  	testGenerateExistentStateWithWrongAccounts(t, rawdb.PathScheme)
   373  }
   374  
   375  func testGenerateExistentStateWithWrongAccounts(t *testing.T, scheme string) {
   376  	helper := newHelper(scheme)
   377  
   378  	helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   379  	helper.makeStorageTrie("acc-2", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   380  	helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   381  	helper.makeStorageTrie("acc-4", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   382  	stRoot := helper.makeStorageTrie("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   383  
   384  	// Trie accounts [acc-1, acc-2, acc-3, acc-4, acc-6]
   385  	// Extra accounts [acc-0, acc-5, acc-7]
   386  
   387  	// Missing accounts, only in the trie
   388  	{
   389  		helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Beginning
   390  		helper.addTrieAccount("acc-4", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Middle
   391  		helper.addTrieAccount("acc-6", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // End
   392  	}
   393  
   394  	// Wrong accounts
   395  	{
   396  		helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   397  		helper.addSnapAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")})
   398  
   399  		helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   400  		helper.addSnapAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
   401  	}
   402  
   403  	// Extra accounts, only in the snap
   404  	{
   405  		helper.addSnapAccount("acc-0", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})              // before the beginning
   406  		helper.addSnapAccount("acc-5", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: common.Hex2Bytes("0x1234")})  // Middle
   407  		helper.addSnapAccount("acc-7", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // after the end
   408  	}
   409  
   410  	root, snap := helper.CommitAndGenerate()
   411  	t.Logf("Root: %#x\n", root) // Root = 0x825891472281463511e7ebcc7f109e4f9200c20fa384754e11fd605cd98464e8
   412  
   413  	select {
   414  	case <-snap.genPending:
   415  		// Snapshot generation succeeded
   416  
   417  	case <-time.After(3 * time.Second):
   418  		t.Errorf("Snapshot generation failed")
   419  	}
   420  	checkSnapRoot(t, snap, root)
   421  
   422  	// Signal abortion to the generator and wait for it to tear down
   423  	stop := make(chan *generatorStats)
   424  	snap.genAbort <- stop
   425  	<-stop
   426  }
   427  
   428  // Tests that snapshot generation errors out correctly in case of a missing trie
   429  // node in the account trie.
   430  func TestGenerateCorruptAccountTrie(t *testing.T) {
   431  	testGenerateCorruptAccountTrie(t, rawdb.HashScheme)
   432  	testGenerateCorruptAccountTrie(t, rawdb.PathScheme)
   433  }
   434  
   435  func testGenerateCorruptAccountTrie(t *testing.T, scheme string) {
   436  	// We can't use statedb to make a test trie (circular dependency), so make
   437  	// a fake one manually. We're going with a small account trie of 3 accounts,
   438  	// without any storage slots to keep the test smaller.
   439  	helper := newHelper(scheme)
   440  
   441  	helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074
   442  	helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
   443  	helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
   444  
   445  	root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
   446  
   447  	// Delete an account trie node and ensure the generator chokes
   448  	targetPath := []byte{0xc}
   449  	targetHash := common.HexToHash("0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7")
   450  
   451  	rawdb.DeleteTrieNode(helper.diskdb, common.Hash{}, targetPath, targetHash, scheme)
   452  
   453  	snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root)
   454  	select {
   455  	case <-snap.genPending:
   456  		// Snapshot generation succeeded
   457  		t.Errorf("Snapshot generated against corrupt account trie")
   458  
   459  	case <-time.After(time.Second):
   460  		// Not generated fast enough, hopefully blocked inside on missing trie node fail
   461  	}
   462  	// Signal abortion to the generator and wait for it to tear down
   463  	stop := make(chan *generatorStats)
   464  	snap.genAbort <- stop
   465  	<-stop
   466  }
   467  
   468  // Tests that snapshot generation errors out correctly in case of a missing root
   469  // trie node for a storage trie. It's similar to internal corruption but it is
   470  // handled differently inside the generator.
   471  func TestGenerateMissingStorageTrie(t *testing.T) {
   472  	testGenerateMissingStorageTrie(t, rawdb.HashScheme)
   473  	testGenerateMissingStorageTrie(t, rawdb.PathScheme)
   474  }
   475  
   476  func testGenerateMissingStorageTrie(t *testing.T, scheme string) {
   477  	// We can't use statedb to make a test trie (circular dependency), so make
   478  	// a fake one manually. We're going with a small account trie of 3 accounts,
   479  	// two of which also has the same 3-slot storage trie attached.
   480  	var (
   481  		acc1   = hashData([]byte("acc-1"))
   482  		acc3   = hashData([]byte("acc-3"))
   483  		helper = newHelper(scheme)
   484  	)
   485  	stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)                         // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
   486  	helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})              // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
   487  	helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
   488  	stRoot = helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   489  	helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
   490  
   491  	root := helper.Commit()
   492  
   493  	// Delete storage trie root of account one and three.
   494  	rawdb.DeleteTrieNode(helper.diskdb, acc1, nil, stRoot, scheme)
   495  	rawdb.DeleteTrieNode(helper.diskdb, acc3, nil, stRoot, scheme)
   496  
   497  	snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root)
   498  	select {
   499  	case <-snap.genPending:
   500  		// Snapshot generation succeeded
   501  		t.Errorf("Snapshot generated against corrupt storage trie")
   502  
   503  	case <-time.After(time.Second):
   504  		// Not generated fast enough, hopefully blocked inside on missing trie node fail
   505  	}
   506  	// Signal abortion to the generator and wait for it to tear down
   507  	stop := make(chan *generatorStats)
   508  	snap.genAbort <- stop
   509  	<-stop
   510  }
   511  
   512  // Tests that snapshot generation errors out correctly in case of a missing trie
   513  // node in a storage trie.
   514  func TestGenerateCorruptStorageTrie(t *testing.T) {
   515  	testGenerateCorruptStorageTrie(t, rawdb.HashScheme)
   516  	testGenerateCorruptStorageTrie(t, rawdb.PathScheme)
   517  }
   518  
   519  func testGenerateCorruptStorageTrie(t *testing.T, scheme string) {
   520  	// We can't use statedb to make a test trie (circular dependency), so make
   521  	// a fake one manually. We're going with a small account trie of 3 accounts,
   522  	// two of which also has the same 3-slot storage trie attached.
   523  	helper := newHelper(scheme)
   524  
   525  	stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)                         // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
   526  	helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})              // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
   527  	helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
   528  	stRoot = helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   529  	helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
   530  
   531  	root := helper.Commit()
   532  
   533  	// Delete a node in the storage trie.
   534  	targetPath := []byte{0x4}
   535  	targetHash := common.HexToHash("0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371")
   536  	rawdb.DeleteTrieNode(helper.diskdb, hashData([]byte("acc-1")), targetPath, targetHash, scheme)
   537  	rawdb.DeleteTrieNode(helper.diskdb, hashData([]byte("acc-3")), targetPath, targetHash, scheme)
   538  
   539  	snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root)
   540  	select {
   541  	case <-snap.genPending:
   542  		// Snapshot generation succeeded
   543  		t.Errorf("Snapshot generated against corrupt storage trie")
   544  
   545  	case <-time.After(time.Second):
   546  		// Not generated fast enough, hopefully blocked inside on missing trie node fail
   547  	}
   548  	// Signal abortion to the generator and wait for it to tear down
   549  	stop := make(chan *generatorStats)
   550  	snap.genAbort <- stop
   551  	<-stop
   552  }
   553  
   554  // Tests that snapshot generation when an extra account with storage exists in the snap state.
   555  func TestGenerateWithExtraAccounts(t *testing.T) {
   556  	testGenerateWithExtraAccounts(t, rawdb.HashScheme)
   557  	testGenerateWithExtraAccounts(t, rawdb.PathScheme)
   558  }
   559  
   560  func testGenerateWithExtraAccounts(t *testing.T, scheme string) {
   561  	helper := newHelper(scheme)
   562  	{
   563  		// Account one in the trie
   564  		stRoot := helper.makeStorageTrie("acc-1",
   565  			[]string{"key-1", "key-2", "key-3", "key-4", "key-5"},
   566  			[]string{"val-1", "val-2", "val-3", "val-4", "val-5"},
   567  			true,
   568  		)
   569  		acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
   570  		val, _ := rlp.EncodeToBytes(acc)
   571  		helper.accTrie.MustUpdate([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
   572  
   573  		// Identical in the snap
   574  		key := hashData([]byte("acc-1"))
   575  		rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
   576  		rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-1")), []byte("val-1"))
   577  		rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-2")), []byte("val-2"))
   578  		rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-3")), []byte("val-3"))
   579  		rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-4")), []byte("val-4"))
   580  		rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-5")), []byte("val-5"))
   581  	}
   582  	{
   583  		// Account two exists only in the snapshot
   584  		stRoot := helper.makeStorageTrie("acc-2",
   585  			[]string{"key-1", "key-2", "key-3", "key-4", "key-5"},
   586  			[]string{"val-1", "val-2", "val-3", "val-4", "val-5"},
   587  			true,
   588  		)
   589  		acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
   590  		val, _ := rlp.EncodeToBytes(acc)
   591  		key := hashData([]byte("acc-2"))
   592  		rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
   593  		rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-1")), []byte("b-val-1"))
   594  		rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-2")), []byte("b-val-2"))
   595  		rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-3")), []byte("b-val-3"))
   596  	}
   597  	root := helper.Commit()
   598  
   599  	// To verify the test: If we now inspect the snap db, there should exist extraneous storage items
   600  	if data := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data == nil {
   601  		t.Fatalf("expected snap storage to exist")
   602  	}
   603  	snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root)
   604  	select {
   605  	case <-snap.genPending:
   606  		// Snapshot generation succeeded
   607  
   608  	case <-time.After(3 * time.Second):
   609  		t.Errorf("Snapshot generation failed")
   610  	}
   611  	checkSnapRoot(t, snap, root)
   612  
   613  	// Signal abortion to the generator and wait for it to tear down
   614  	stop := make(chan *generatorStats)
   615  	snap.genAbort <- stop
   616  	<-stop
   617  	// If we now inspect the snap db, there should exist no extraneous storage items
   618  	if data := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil {
   619  		t.Fatalf("expected slot to be removed, got %v", string(data))
   620  	}
   621  }
   622  
   623  func enableLogging() {
   624  	log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true)))
   625  }
   626  
   627  // Tests that snapshot generation when an extra account with storage exists in the snap state.
   628  func TestGenerateWithManyExtraAccounts(t *testing.T) {
   629  	testGenerateWithManyExtraAccounts(t, rawdb.HashScheme)
   630  	testGenerateWithManyExtraAccounts(t, rawdb.PathScheme)
   631  }
   632  
   633  func testGenerateWithManyExtraAccounts(t *testing.T, scheme string) {
   634  	if false {
   635  		enableLogging()
   636  	}
   637  	helper := newHelper(scheme)
   638  	{
   639  		// Account one in the trie
   640  		stRoot := helper.makeStorageTrie("acc-1",
   641  			[]string{"key-1", "key-2", "key-3"},
   642  			[]string{"val-1", "val-2", "val-3"},
   643  			true,
   644  		)
   645  		acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
   646  		val, _ := rlp.EncodeToBytes(acc)
   647  		helper.accTrie.MustUpdate([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
   648  
   649  		// Identical in the snap
   650  		key := hashData([]byte("acc-1"))
   651  		rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
   652  		rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-1")), []byte("val-1"))
   653  		rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-2")), []byte("val-2"))
   654  		rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-3")), []byte("val-3"))
   655  	}
   656  	{
   657  		// 100 accounts exist only in snapshot
   658  		for i := 0; i < 1000; i++ {
   659  			acc := &types.StateAccount{Balance: uint256.NewInt(uint64(i)), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
   660  			val, _ := rlp.EncodeToBytes(acc)
   661  			key := hashData(fmt.Appendf(nil, "acc-%d", i))
   662  			rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
   663  		}
   664  	}
   665  	root, snap := helper.CommitAndGenerate()
   666  	select {
   667  	case <-snap.genPending:
   668  		// Snapshot generation succeeded
   669  
   670  	case <-time.After(3 * time.Second):
   671  		t.Errorf("Snapshot generation failed")
   672  	}
   673  	checkSnapRoot(t, snap, root)
   674  	// Signal abortion to the generator and wait for it to tear down
   675  	stop := make(chan *generatorStats)
   676  	snap.genAbort <- stop
   677  	<-stop
   678  }
   679  
   680  // Tests this case
   681  // maxAccountRange 3
   682  // snapshot-accounts: 01, 02, 03, 04, 05, 06, 07
   683  // trie-accounts:             03,             07
   684  //
   685  // We iterate three snapshot storage slots (max = 3) from the database. They are 0x01, 0x02, 0x03.
   686  // The trie has a lot of deletions.
   687  // So in trie, we iterate 2 entries 0x03, 0x07. We create the 0x07 in the database and abort the procedure, because the trie is exhausted.
   688  // But in the database, we still have the stale storage slots 0x04, 0x05. They are not iterated yet, but the procedure is finished.
   689  func TestGenerateWithExtraBeforeAndAfter(t *testing.T) {
   690  	testGenerateWithExtraBeforeAndAfter(t, rawdb.HashScheme)
   691  	testGenerateWithExtraBeforeAndAfter(t, rawdb.PathScheme)
   692  }
   693  
   694  func testGenerateWithExtraBeforeAndAfter(t *testing.T, scheme string) {
   695  	accountCheckRange = 3
   696  	if false {
   697  		enableLogging()
   698  	}
   699  	helper := newHelper(scheme)
   700  	{
   701  		acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
   702  		val, _ := rlp.EncodeToBytes(acc)
   703  		helper.accTrie.MustUpdate(common.HexToHash("0x03").Bytes(), val)
   704  		helper.accTrie.MustUpdate(common.HexToHash("0x07").Bytes(), val)
   705  
   706  		rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x01"), val)
   707  		rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x02"), val)
   708  		rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x03"), val)
   709  		rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x04"), val)
   710  		rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x05"), val)
   711  		rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x06"), val)
   712  		rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x07"), val)
   713  	}
   714  	root, snap := helper.CommitAndGenerate()
   715  	select {
   716  	case <-snap.genPending:
   717  		// Snapshot generation succeeded
   718  
   719  	case <-time.After(3 * time.Second):
   720  		t.Errorf("Snapshot generation failed")
   721  	}
   722  	checkSnapRoot(t, snap, root)
   723  	// Signal abortion to the generator and wait for it to tear down
   724  	stop := make(chan *generatorStats)
   725  	snap.genAbort <- stop
   726  	<-stop
   727  }
   728  
   729  // TestGenerateWithMalformedSnapdata tests what happes if we have some junk
   730  // in the snapshot database, which cannot be parsed back to an account
   731  func TestGenerateWithMalformedSnapdata(t *testing.T) {
   732  	testGenerateWithMalformedSnapdata(t, rawdb.HashScheme)
   733  	testGenerateWithMalformedSnapdata(t, rawdb.PathScheme)
   734  }
   735  
   736  func testGenerateWithMalformedSnapdata(t *testing.T, scheme string) {
   737  	accountCheckRange = 3
   738  	if false {
   739  		enableLogging()
   740  	}
   741  	helper := newHelper(scheme)
   742  	{
   743  		acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
   744  		val, _ := rlp.EncodeToBytes(acc)
   745  		helper.accTrie.MustUpdate(common.HexToHash("0x03").Bytes(), val)
   746  
   747  		junk := make([]byte, 100)
   748  		copy(junk, []byte{0xde, 0xad})
   749  		rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x02"), junk)
   750  		rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x03"), junk)
   751  		rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x04"), junk)
   752  		rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x05"), junk)
   753  	}
   754  	root, snap := helper.CommitAndGenerate()
   755  	select {
   756  	case <-snap.genPending:
   757  		// Snapshot generation succeeded
   758  
   759  	case <-time.After(3 * time.Second):
   760  		t.Errorf("Snapshot generation failed")
   761  	}
   762  	checkSnapRoot(t, snap, root)
   763  	// Signal abortion to the generator and wait for it to tear down
   764  	stop := make(chan *generatorStats)
   765  	snap.genAbort <- stop
   766  	<-stop
   767  	// If we now inspect the snap db, there should exist no extraneous storage items
   768  	if data := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil {
   769  		t.Fatalf("expected slot to be removed, got %v", string(data))
   770  	}
   771  }
   772  
   773  func TestGenerateFromEmptySnap(t *testing.T) {
   774  	testGenerateFromEmptySnap(t, rawdb.HashScheme)
   775  	testGenerateFromEmptySnap(t, rawdb.PathScheme)
   776  }
   777  
   778  func testGenerateFromEmptySnap(t *testing.T, scheme string) {
   779  	//enableLogging()
   780  	accountCheckRange = 10
   781  	storageCheckRange = 20
   782  	helper := newHelper(scheme)
   783  	// Add 1K accounts to the trie
   784  	for i := 0; i < 400; i++ {
   785  		stRoot := helper.makeStorageTrie(fmt.Sprintf("acc-%d", i), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   786  		helper.addTrieAccount(fmt.Sprintf("acc-%d", i),
   787  			&types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   788  	}
   789  	root, snap := helper.CommitAndGenerate()
   790  	t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4
   791  
   792  	select {
   793  	case <-snap.genPending:
   794  		// Snapshot generation succeeded
   795  
   796  	case <-time.After(3 * time.Second):
   797  		t.Errorf("Snapshot generation failed")
   798  	}
   799  	checkSnapRoot(t, snap, root)
   800  	// Signal abortion to the generator and wait for it to tear down
   801  	stop := make(chan *generatorStats)
   802  	snap.genAbort <- stop
   803  	<-stop
   804  }
   805  
   806  // Tests that snapshot generation with existent flat state, where the flat state
   807  // storage is correct, but incomplete.
   808  // The incomplete part is on the second range
   809  // snap: [ 0x01, 0x02, 0x03, 0x04] , [ 0x05, 0x06, 0x07, {missing}] (with storageCheck = 4)
   810  // trie:  0x01, 0x02, 0x03, 0x04,  0x05, 0x06, 0x07, 0x08
   811  // This hits a case where the snap verification passes, but there are more elements in the trie
   812  // which we must also add.
   813  func TestGenerateWithIncompleteStorage(t *testing.T) {
   814  	testGenerateWithIncompleteStorage(t, rawdb.HashScheme)
   815  	testGenerateWithIncompleteStorage(t, rawdb.PathScheme)
   816  }
   817  
   818  func testGenerateWithIncompleteStorage(t *testing.T, scheme string) {
   819  	storageCheckRange = 4
   820  	helper := newHelper(scheme)
   821  	stKeys := []string{"1", "2", "3", "4", "5", "6", "7", "8"}
   822  	stVals := []string{"v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"}
   823  	// We add 8 accounts, each one is missing exactly one of the storage slots. This means
   824  	// we don't have to order the keys and figure out exactly which hash-key winds up
   825  	// on the sensitive spots at the boundaries
   826  	for i := 0; i < 8; i++ {
   827  		accKey := fmt.Sprintf("acc-%d", i)
   828  		stRoot := helper.makeStorageTrie(accKey, stKeys, stVals, true)
   829  		helper.addAccount(accKey, &types.StateAccount{Balance: uint256.NewInt(uint64(i)), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   830  		var moddedKeys []string
   831  		var moddedVals []string
   832  		for ii := 0; ii < 8; ii++ {
   833  			if ii != i {
   834  				moddedKeys = append(moddedKeys, stKeys[ii])
   835  				moddedVals = append(moddedVals, stVals[ii])
   836  			}
   837  		}
   838  		helper.addSnapStorage(accKey, moddedKeys, moddedVals)
   839  	}
   840  	root, snap := helper.CommitAndGenerate()
   841  	t.Logf("Root: %#x\n", root) // Root: 0xca73f6f05ba4ca3024ef340ef3dfca8fdabc1b677ff13f5a9571fd49c16e67ff
   842  
   843  	select {
   844  	case <-snap.genPending:
   845  		// Snapshot generation succeeded
   846  
   847  	case <-time.After(3 * time.Second):
   848  		t.Errorf("Snapshot generation failed")
   849  	}
   850  	checkSnapRoot(t, snap, root)
   851  	// Signal abortion to the generator and wait for it to tear down
   852  	stop := make(chan *generatorStats)
   853  	snap.genAbort <- stop
   854  	<-stop
   855  }
   856  
   857  func incKey(key []byte) []byte {
   858  	for i := len(key) - 1; i >= 0; i-- {
   859  		key[i]++
   860  		if key[i] != 0x0 {
   861  			break
   862  		}
   863  	}
   864  	return key
   865  }
   866  
   867  func decKey(key []byte) []byte {
   868  	for i := len(key) - 1; i >= 0; i-- {
   869  		key[i]--
   870  		if key[i] != 0xff {
   871  			break
   872  		}
   873  	}
   874  	return key
   875  }
   876  
   877  func populateDangling(disk ethdb.KeyValueStore) {
   878  	populate := func(accountHash common.Hash, keys []string, vals []string) {
   879  		for i, key := range keys {
   880  			rawdb.WriteStorageSnapshot(disk, accountHash, hashData([]byte(key)), []byte(vals[i]))
   881  		}
   882  	}
   883  	// Dangling storages of the "first" account
   884  	populate(common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   885  
   886  	// Dangling storages of the "last" account
   887  	populate(common.HexToHash("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   888  
   889  	// Dangling storages around the account 1
   890  	hash := decKey(hashData([]byte("acc-1")).Bytes())
   891  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   892  	hash = incKey(hashData([]byte("acc-1")).Bytes())
   893  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   894  
   895  	// Dangling storages around the account 2
   896  	hash = decKey(hashData([]byte("acc-2")).Bytes())
   897  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   898  	hash = incKey(hashData([]byte("acc-2")).Bytes())
   899  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   900  
   901  	// Dangling storages around the account 3
   902  	hash = decKey(hashData([]byte("acc-3")).Bytes())
   903  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   904  	hash = incKey(hashData([]byte("acc-3")).Bytes())
   905  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   906  
   907  	// Dangling storages of the random account
   908  	populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   909  	populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   910  	populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   911  }
   912  
   913  // Tests that snapshot generation with dangling storages. Dangling storage means
   914  // the storage data is existent while the corresponding account data is missing.
   915  //
   916  // This test will populate some dangling storages to see if they can be cleaned up.
   917  func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) {
   918  	testGenerateCompleteSnapshotWithDanglingStorage(t, rawdb.HashScheme)
   919  	testGenerateCompleteSnapshotWithDanglingStorage(t, rawdb.PathScheme)
   920  }
   921  
   922  func testGenerateCompleteSnapshotWithDanglingStorage(t *testing.T, scheme string) {
   923  	var helper = newHelper(scheme)
   924  
   925  	stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   926  	helper.addAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   927  	helper.addAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
   928  
   929  	helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   930  	helper.addAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   931  
   932  	helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   933  	helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   934  
   935  	populateDangling(helper.diskdb)
   936  
   937  	root, snap := helper.CommitAndGenerate()
   938  	select {
   939  	case <-snap.genPending:
   940  		// Snapshot generation succeeded
   941  
   942  	case <-time.After(3 * time.Second):
   943  		t.Errorf("Snapshot generation failed")
   944  	}
   945  	checkSnapRoot(t, snap, root)
   946  
   947  	// Signal abortion to the generator and wait for it to tear down
   948  	stop := make(chan *generatorStats)
   949  	snap.genAbort <- stop
   950  	<-stop
   951  }
   952  
   953  // Tests that snapshot generation with dangling storages. Dangling storage means
   954  // the storage data is existent while the corresponding account data is missing.
   955  //
   956  // This test will populate some dangling storages to see if they can be cleaned up.
   957  func TestGenerateBrokenSnapshotWithDanglingStorage(t *testing.T) {
   958  	testGenerateBrokenSnapshotWithDanglingStorage(t, rawdb.HashScheme)
   959  	testGenerateBrokenSnapshotWithDanglingStorage(t, rawdb.PathScheme)
   960  }
   961  
   962  func testGenerateBrokenSnapshotWithDanglingStorage(t *testing.T, scheme string) {
   963  	var helper = newHelper(scheme)
   964  
   965  	stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   966  	helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   967  	helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
   968  
   969  	helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   970  	helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   971  
   972  	populateDangling(helper.diskdb)
   973  
   974  	root, snap := helper.CommitAndGenerate()
   975  	select {
   976  	case <-snap.genPending:
   977  		// Snapshot generation succeeded
   978  
   979  	case <-time.After(3 * time.Second):
   980  		t.Errorf("Snapshot generation failed")
   981  	}
   982  	checkSnapRoot(t, snap, root)
   983  
   984  	// Signal abortion to the generator and wait for it to tear down
   985  	stop := make(chan *generatorStats)
   986  	snap.genAbort <- stop
   987  	<-stop
   988  }