gitlab.com/flarenetwork/coreth@v0.1.1/core/state/snapshot/generate_test.go (about)

     1  // (c) 2019-2020, Ava Labs, Inc.
     2  //
     3  // This file is a derived work, based on the go-ethereum library whose original
     4  // notices appear below.
     5  //
     6  // It is distributed under a license compatible with the licensing terms of the
     7  // original code from which it is derived.
     8  //
     9  // Much love to the original authors for their work.
    10  // **********
    11  // Copyright 2020 The go-ethereum Authors
    12  // This file is part of the go-ethereum library.
    13  //
    14  // The go-ethereum library is free software: you can redistribute it and/or modify
    15  // it under the terms of the GNU Lesser General Public License as published by
    16  // the Free Software Foundation, either version 3 of the License, or
    17  // (at your option) any later version.
    18  //
    19  // The go-ethereum library is distributed in the hope that it will be useful,
    20  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    22  // GNU Lesser General Public License for more details.
    23  //
    24  // You should have received a copy of the GNU Lesser General Public License
    25  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    26  
    27  package snapshot
    28  
    29  import (
    30  	"fmt"
    31  	"math/big"
    32  	"os"
    33  	"testing"
    34  	"time"
    35  
    36  	"github.com/ethereum/go-ethereum/common"
    37  	"github.com/ethereum/go-ethereum/core/rawdb"
    38  	"github.com/ethereum/go-ethereum/ethdb"
    39  	"github.com/ethereum/go-ethereum/ethdb/memorydb"
    40  	"github.com/ethereum/go-ethereum/log"
    41  	"github.com/ethereum/go-ethereum/rlp"
    42  	"github.com/ethereum/go-ethereum/trie"
    43  	"golang.org/x/crypto/sha3"
    44  )
    45  
    46  // Tests that snapshot generation from an empty database.
    47  func TestGeneration(t *testing.T) {
    48  	// We can't use statedb to make a test trie (circular dependency), so make
    49  	// a fake one manually. We're going with a small account trie of 3 accounts,
    50  	// two of which also has the same 3-slot storage trie attached.
    51  	var (
    52  		diskdb = memorydb.New()
    53  		triedb = trie.NewDatabase(diskdb)
    54  	)
    55  	stTrie, _ := trie.NewSecure(common.Hash{}, triedb)
    56  	stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0
    57  	stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371
    58  	stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78
    59  	stTrie.Commit(nil)                              // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
    60  
    61  	accTrie, _ := trie.NewSecure(common.Hash{}, triedb)
    62  	acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
    63  	val, _ := rlp.EncodeToBytes(acc)
    64  	accTrie.Update([]byte("acc-1"), val)
    65  
    66  	acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
    67  	val, _ = rlp.EncodeToBytes(acc)
    68  	accTrie.Update([]byte("acc-2"), val)
    69  
    70  	acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
    71  	val, _ = rlp.EncodeToBytes(acc)
    72  	accTrie.Update([]byte("acc-3"), val)
    73  	root, _ := accTrie.Commit(nil) // Root: 0xa819054cfef894169a5b56ccc4e5e06f14829d4a57498e8b9fb13ff21491828d
    74  	triedb.Commit(root, false, nil)
    75  
    76  	if have, want := root, common.HexToHash("0xa819054cfef894169a5b56ccc4e5e06f14829d4a57498e8b9fb13ff21491828d"); have != want {
    77  		t.Fatalf("have %#x want %#x", have, want)
    78  	}
    79  	snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xdeadbeef"), root, nil)
    80  	select {
    81  	case <-snap.genPending:
    82  		// Snapshot generation succeeded
    83  
    84  	case <-time.After(250 * time.Millisecond):
    85  		t.Errorf("Snapshot generation failed")
    86  	}
    87  	checkSnapRoot(t, snap, root)
    88  	// Signal abortion to the generator and wait for it to tear down
    89  	stop := make(chan struct{})
    90  	snap.genAbort <- stop
    91  	<-stop
    92  }
    93  
    94  func hashData(input []byte) common.Hash {
    95  	var hasher = sha3.NewLegacyKeccak256()
    96  	var hash common.Hash
    97  	hasher.Reset()
    98  	hasher.Write(input)
    99  	hasher.Sum(hash[:0])
   100  	return hash
   101  }
   102  
   103  // Tests that snapshot generation with existent flat state.
   104  func TestGenerateExistentState(t *testing.T) {
   105  	// We can't use statedb to make a test trie (circular dependency), so make
   106  	// a fake one manually. We're going with a small account trie of 3 accounts,
   107  	// two of which also has the same 3-slot storage trie attached.
   108  	var (
   109  		diskdb = memorydb.New()
   110  		triedb = trie.NewDatabase(diskdb)
   111  	)
   112  	stTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   113  	stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0
   114  	stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371
   115  	stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78
   116  	stTrie.Commit(nil)                              // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
   117  
   118  	accTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   119  	acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   120  	val, _ := rlp.EncodeToBytes(acc)
   121  	accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
   122  	rawdb.WriteAccountSnapshot(diskdb, hashData([]byte("acc-1")), val)
   123  	rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-1")), hashData([]byte("key-1")), []byte("val-1"))
   124  	rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-1")), hashData([]byte("key-2")), []byte("val-2"))
   125  	rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-1")), hashData([]byte("key-3")), []byte("val-3"))
   126  
   127  	acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   128  	val, _ = rlp.EncodeToBytes(acc)
   129  	accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
   130  	diskdb.Put(hashData([]byte("acc-2")).Bytes(), val)
   131  	rawdb.WriteAccountSnapshot(diskdb, hashData([]byte("acc-2")), val)
   132  
   133  	acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   134  	val, _ = rlp.EncodeToBytes(acc)
   135  	accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
   136  	rawdb.WriteAccountSnapshot(diskdb, hashData([]byte("acc-3")), val)
   137  	rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-3")), hashData([]byte("key-1")), []byte("val-1"))
   138  	rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-3")), hashData([]byte("key-2")), []byte("val-2"))
   139  	rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-3")), hashData([]byte("key-3")), []byte("val-3"))
   140  
   141  	root, _ := accTrie.Commit(nil) // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd
   142  	triedb.Commit(root, false, nil)
   143  
   144  	snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xdeadbeef"), root, nil)
   145  	select {
   146  	case <-snap.genPending:
   147  		// Snapshot generation succeeded
   148  
   149  	case <-time.After(250 * time.Millisecond):
   150  		t.Errorf("Snapshot generation failed")
   151  	}
   152  	checkSnapRoot(t, snap, root)
   153  	// Signal abortion to the generator and wait for it to tear down
   154  	stop := make(chan struct{})
   155  	snap.genAbort <- stop
   156  	<-stop
   157  }
   158  
   159  func checkSnapRoot(t *testing.T, snap *diskLayer, trieRoot common.Hash) {
   160  	t.Helper()
   161  	accIt := snap.AccountIterator(common.Hash{})
   162  	defer accIt.Release()
   163  	snapRoot, err := generateTrieRoot(nil, accIt, common.Hash{}, stackTrieGenerate,
   164  		func(db ethdb.KeyValueWriter, accountHash, codeHash common.Hash, stat *generateStats) (common.Hash, error) {
   165  			storageIt, _ := snap.StorageIterator(accountHash, common.Hash{})
   166  			defer storageIt.Release()
   167  
   168  			hash, err := generateTrieRoot(nil, storageIt, accountHash, stackTrieGenerate, nil, stat, false)
   169  			if err != nil {
   170  				return common.Hash{}, err
   171  			}
   172  			return hash, nil
   173  		}, newGenerateStats(), true)
   174  
   175  	if err != nil {
   176  		t.Fatal(err)
   177  	}
   178  	if snapRoot != trieRoot {
   179  		t.Fatalf("snaproot: %#x != trieroot #%x", snapRoot, trieRoot)
   180  	}
   181  }
   182  
   183  type testHelper struct {
   184  	diskdb  *memorydb.Database
   185  	triedb  *trie.Database
   186  	accTrie *trie.SecureTrie
   187  }
   188  
   189  func newHelper() *testHelper {
   190  	diskdb := memorydb.New()
   191  	triedb := trie.NewDatabase(diskdb)
   192  	accTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   193  	return &testHelper{
   194  		diskdb:  diskdb,
   195  		triedb:  triedb,
   196  		accTrie: accTrie,
   197  	}
   198  }
   199  
   200  func (t *testHelper) addTrieAccount(acckey string, acc *Account) {
   201  	val, _ := rlp.EncodeToBytes(acc)
   202  	t.accTrie.Update([]byte(acckey), val)
   203  }
   204  
   205  func (t *testHelper) addSnapAccount(acckey string, acc *Account) {
   206  	val, _ := rlp.EncodeToBytes(acc)
   207  	key := hashData([]byte(acckey))
   208  	rawdb.WriteAccountSnapshot(t.diskdb, key, val)
   209  }
   210  
   211  func (t *testHelper) addAccount(acckey string, acc *Account) {
   212  	t.addTrieAccount(acckey, acc)
   213  	t.addSnapAccount(acckey, acc)
   214  }
   215  
   216  func (t *testHelper) addSnapStorage(accKey string, keys []string, vals []string) {
   217  	accHash := hashData([]byte(accKey))
   218  	for i, key := range keys {
   219  		rawdb.WriteStorageSnapshot(t.diskdb, accHash, hashData([]byte(key)), []byte(vals[i]))
   220  	}
   221  }
   222  
   223  func (t *testHelper) makeStorageTrie(keys []string, vals []string) []byte {
   224  	stTrie, _ := trie.NewSecure(common.Hash{}, t.triedb)
   225  	for i, k := range keys {
   226  		stTrie.Update([]byte(k), []byte(vals[i]))
   227  	}
   228  	root, _ := stTrie.Commit(nil)
   229  	return root.Bytes()
   230  }
   231  
   232  func (t *testHelper) Generate() (common.Hash, *diskLayer) {
   233  	root, _ := t.accTrie.Commit(nil)
   234  	t.triedb.Commit(root, false, nil)
   235  	snap := generateSnapshot(t.diskdb, t.triedb, 16, common.HexToHash("0xdeadbeef"), root, nil)
   236  	return root, snap
   237  }
   238  
   239  // Tests that snapshot generation with existent flat state, where the flat state
   240  // contains some errors:
   241  // - the contract with empty storage root but has storage entries in the disk
   242  // - the contract with non empty storage root but empty storage slots
   243  // - the contract(non-empty storage) misses some storage slots
   244  //   - miss in the beginning
   245  //   - miss in the middle
   246  //   - miss in the end
   247  // - the contract(non-empty storage) has wrong storage slots
   248  //   - wrong slots in the beginning
   249  //   - wrong slots in the middle
   250  //   - wrong slots in the end
   251  // - the contract(non-empty storage) has extra storage slots
   252  //   - extra slots in the beginning
   253  //   - extra slots in the middle
   254  //   - extra slots in the end
   255  func TestGenerateExistentStateWithWrongStorage(t *testing.T) {
   256  	helper := newHelper()
   257  	stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   258  
   259  	// Account one, empty root but non-empty database
   260  	helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
   261  	helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   262  
   263  	// Account two, non empty root but empty database
   264  	helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   265  
   266  	// Miss slots
   267  	{
   268  		// Account three, non empty root but misses slots in the beginning
   269  		helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   270  		helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"})
   271  
   272  		// Account four, non empty root but misses slots in the middle
   273  		helper.addAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   274  		helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"})
   275  
   276  		// Account five, non empty root but misses slots in the end
   277  		helper.addAccount("acc-5", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   278  		helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"})
   279  	}
   280  
   281  	// Wrong storage slots
   282  	{
   283  		// Account six, non empty root but wrong slots in the beginning
   284  		helper.addAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   285  		helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"})
   286  
   287  		// Account seven, non empty root but wrong slots in the middle
   288  		helper.addAccount("acc-7", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   289  		helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"})
   290  
   291  		// Account eight, non empty root but wrong slots in the end
   292  		helper.addAccount("acc-8", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   293  		helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"})
   294  
   295  		// Account 9, non empty root but rotated slots
   296  		helper.addAccount("acc-9", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   297  		helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"})
   298  	}
   299  
   300  	// Extra storage slots
   301  	{
   302  		// Account 10, non empty root but extra slots in the beginning
   303  		helper.addAccount("acc-10", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   304  		helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"})
   305  
   306  		// Account 11, non empty root but extra slots in the middle
   307  		helper.addAccount("acc-11", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   308  		helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"})
   309  
   310  		// Account 12, non empty root but extra slots in the end
   311  		helper.addAccount("acc-12", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   312  		helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"})
   313  	}
   314  
   315  	root, snap := helper.Generate()
   316  	t.Logf("Root: %#x\n", root) // Root = 0x8746cce9fd9c658b2cfd639878ed6584b7a2b3e73bb40f607fcfa156002429a0
   317  
   318  	select {
   319  	case <-snap.genPending:
   320  		// Snapshot generation succeeded
   321  
   322  	case <-time.After(250 * time.Millisecond):
   323  		t.Errorf("Snapshot generation failed")
   324  	}
   325  	checkSnapRoot(t, snap, root)
   326  	// Signal abortion to the generator and wait for it to tear down
   327  	stop := make(chan struct{})
   328  	snap.genAbort <- stop
   329  	<-stop
   330  }
   331  
   332  // Tests that snapshot generation with existent flat state, where the flat state
   333  // contains some errors:
   334  // - miss accounts
   335  // - wrong accounts
   336  // - extra accounts
   337  func TestGenerateExistentStateWithWrongAccounts(t *testing.T) {
   338  	helper := newHelper()
   339  	stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   340  
   341  	// Trie accounts [acc-1, acc-2, acc-3, acc-4, acc-6]
   342  	// Extra accounts [acc-0, acc-5, acc-7]
   343  
   344  	// Missing accounts, only in the trie
   345  	{
   346  		helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // Beginning
   347  		helper.addTrieAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // Middle
   348  		helper.addTrieAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // End
   349  	}
   350  
   351  	// Wrong accounts
   352  	{
   353  		helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   354  		helper.addSnapAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")})
   355  
   356  		helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   357  		helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
   358  	}
   359  
   360  	// Extra accounts, only in the snap
   361  	{
   362  		helper.addSnapAccount("acc-0", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyRoot.Bytes()})                     // before the beginning
   363  		helper.addSnapAccount("acc-5", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: common.Hex2Bytes("0x1234")}) // Middle
   364  		helper.addSnapAccount("acc-7", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyRoot.Bytes()})          // after the end
   365  	}
   366  
   367  	root, snap := helper.Generate()
   368  	t.Logf("Root: %#x\n", root) // Root = 0x825891472281463511e7ebcc7f109e4f9200c20fa384754e11fd605cd98464e8
   369  
   370  	select {
   371  	case <-snap.genPending:
   372  		// Snapshot generation succeeded
   373  
   374  	case <-time.After(250 * time.Millisecond):
   375  		t.Errorf("Snapshot generation failed")
   376  	}
   377  	checkSnapRoot(t, snap, root)
   378  
   379  	// Signal abortion to the generator and wait for it to tear down
   380  	stop := make(chan struct{})
   381  	snap.genAbort <- stop
   382  	<-stop
   383  }
   384  
   385  // Tests that snapshot generation errors out correctly in case of a missing trie
   386  // node in the account trie.
   387  func TestGenerateCorruptAccountTrie(t *testing.T) {
   388  	// We can't use statedb to make a test trie (circular dependency), so make
   389  	// a fake one manually. We're going with a small account trie of 3 accounts,
   390  	// without any storage slots to keep the test smaller.
   391  	var (
   392  		diskdb = memorydb.New()
   393  		triedb = trie.NewDatabase(diskdb)
   394  	)
   395  	tr, _ := trie.NewSecure(common.Hash{}, triedb)
   396  	acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   397  	val, _ := rlp.EncodeToBytes(acc)
   398  	tr.Update([]byte("acc-1"), val) // 0x7dd654835190324640832972b7c4c6eaa0c50541e36766d054ed57721f1dc7eb
   399  
   400  	acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   401  	val, _ = rlp.EncodeToBytes(acc)
   402  	tr.Update([]byte("acc-2"), val) // 0xf73118e0254ce091588d66038744a0afae5f65a194de67cff310c683ae43329e
   403  
   404  	acc = &Account{Balance: big.NewInt(3), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   405  	val, _ = rlp.EncodeToBytes(acc)
   406  	tr.Update([]byte("acc-3"), val) // 0x515d3de35e143cd976ad476398d910aa7bf8a02e8fd7eb9e3baacddbbcbfcb41
   407  	tr.Commit(nil)                  // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
   408  
   409  	// Delete an account trie leaf and ensure the generator chokes
   410  	triedb.Commit(common.HexToHash("0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978"), false, nil)
   411  	diskdb.Delete(common.HexToHash("0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7").Bytes())
   412  
   413  	snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xdeadbeef"), common.HexToHash("0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978"), nil)
   414  	select {
   415  	case <-snap.genPending:
   416  		// Snapshot generation succeeded
   417  		t.Errorf("Snapshot generated against corrupt account trie")
   418  
   419  	case <-time.After(250 * time.Millisecond):
   420  		// Not generated fast enough, hopefully blocked inside on missing trie node fail
   421  	}
   422  	// Signal abortion to the generator and wait for it to tear down
   423  	stop := make(chan struct{})
   424  	snap.genAbort <- stop
   425  	<-stop
   426  }
   427  
   428  // Tests that snapshot generation errors out correctly in case of a missing root
   429  // trie node for a storage trie. It's similar to internal corruption but it is
   430  // handled differently inside the generator.
   431  func TestGenerateMissingStorageTrie(t *testing.T) {
   432  	// We can't use statedb to make a test trie (circular dependency), so make
   433  	// a fake one manually. We're going with a small account trie of 3 accounts,
   434  	// two of which also has the same 3-slot storage trie attached.
   435  	var (
   436  		diskdb = memorydb.New()
   437  		triedb = trie.NewDatabase(diskdb)
   438  	)
   439  	stTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   440  	stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0
   441  	stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371
   442  	stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78
   443  	stTrie.Commit(nil)                              // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
   444  
   445  	accTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   446  	acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   447  	val, _ := rlp.EncodeToBytes(acc)
   448  	accTrie.Update([]byte("acc-1"), val) // 0x547b07c3a71669c00eda14077d85c7fd14575b92d459572540b25b9a11914dcb
   449  
   450  	acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   451  	val, _ = rlp.EncodeToBytes(acc)
   452  	accTrie.Update([]byte("acc-2"), val) // 0xf73118e0254ce091588d66038744a0afae5f65a194de67cff310c683ae43329e
   453  
   454  	acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   455  	val, _ = rlp.EncodeToBytes(acc)
   456  	accTrie.Update([]byte("acc-3"), val) // 0x70da4ebd7602dd313c936b39000ed9ab7f849986a90ea934f0c3ec4cc9840441
   457  	accTrie.Commit(nil)                  // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd
   458  
   459  	// We can only corrupt the disk database, so flush the tries out
   460  	triedb.Reference(
   461  		common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"),
   462  		common.HexToHash("0xa819054cfef894169a5b56ccc4e5e06f14829d4a57498e8b9fb13ff21491828d"),
   463  	)
   464  	triedb.Commit(common.HexToHash("0xa819054cfef894169a5b56ccc4e5e06f14829d4a57498e8b9fb13ff21491828d"), false, nil)
   465  
   466  	// Delete a storage trie root and ensure the generator chokes
   467  	diskdb.Delete(common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67").Bytes())
   468  
   469  	snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xdeadbeef"), common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), nil)
   470  	select {
   471  	case <-snap.genPending:
   472  		// Snapshot generation succeeded
   473  		t.Errorf("Snapshot generated against corrupt storage trie")
   474  
   475  	case <-time.After(250 * time.Millisecond):
   476  		// Not generated fast enough, hopefully blocked inside on missing trie node fail
   477  	}
   478  	// Signal abortion to the generator and wait for it to tear down
   479  	stop := make(chan struct{})
   480  	snap.genAbort <- stop
   481  	<-stop
   482  }
   483  
   484  // Tests that snapshot generation errors out correctly in case of a missing trie
   485  // node in a storage trie.
   486  func TestGenerateCorruptStorageTrie(t *testing.T) {
   487  	// We can't use statedb to make a test trie (circular dependency), so make
   488  	// a fake one manually. We're going with a small account trie of 3 accounts,
   489  	// two of which also has the same 3-slot storage trie attached.
   490  	var (
   491  		diskdb = memorydb.New()
   492  		triedb = trie.NewDatabase(diskdb)
   493  	)
   494  	stTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   495  	stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0
   496  	stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371
   497  	stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78
   498  	stTrie.Commit(nil)                              // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
   499  
   500  	accTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   501  	acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   502  	val, _ := rlp.EncodeToBytes(acc)
   503  	accTrie.Update([]byte("acc-1"), val) // 0x547b07c3a71669c00eda14077d85c7fd14575b92d459572540b25b9a11914dcb
   504  
   505  	acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   506  	val, _ = rlp.EncodeToBytes(acc)
   507  	accTrie.Update([]byte("acc-2"), val) // 0xf73118e0254ce091588d66038744a0afae5f65a194de67cff310c683ae43329e
   508  
   509  	acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   510  	val, _ = rlp.EncodeToBytes(acc)
   511  	accTrie.Update([]byte("acc-3"), val) // 0x70da4ebd7602dd313c936b39000ed9ab7f849986a90ea934f0c3ec4cc9840441
   512  	accTrie.Commit(nil)                  // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd
   513  
   514  	// We can only corrupt the disk database, so flush the tries out
   515  	triedb.Reference(
   516  		common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"),
   517  		common.HexToHash("0xa819054cfef894169a5b56ccc4e5e06f14829d4a57498e8b9fb13ff21491828d"),
   518  	)
   519  	triedb.Commit(common.HexToHash("0xa819054cfef894169a5b56ccc4e5e06f14829d4a57498e8b9fb13ff21491828d"), false, nil)
   520  
   521  	// Delete a storage trie leaf and ensure the generator chokes
   522  	diskdb.Delete(common.HexToHash("0x16691bc8a441197767e40bb66f521b92952edaf1462813f4f5bcca39aae72ffa").Bytes())
   523  
   524  	snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xdeadbeef"), common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), nil)
   525  	select {
   526  	case <-snap.genPending:
   527  		// Snapshot generation succeeded
   528  		t.Errorf("Snapshot generated against corrupt storage trie")
   529  
   530  	case <-time.After(250 * time.Millisecond):
   531  		// Not generated fast enough, hopefully blocked inside on missing trie node fail
   532  	}
   533  	// Signal abortion to the generator and wait for it to tear down
   534  	stop := make(chan struct{})
   535  	snap.genAbort <- stop
   536  	<-stop
   537  }
   538  
   539  func getStorageTrie(n int, triedb *trie.Database) *trie.SecureTrie {
   540  	stTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   541  	for i := 0; i < n; i++ {
   542  		k := fmt.Sprintf("key-%d", i)
   543  		v := fmt.Sprintf("val-%d", i)
   544  		stTrie.Update([]byte(k), []byte(v))
   545  	}
   546  	stTrie.Commit(nil)
   547  	return stTrie
   548  }
   549  
   550  // Tests that snapshot generation when an extra account with storage exists in the snap state.
   551  func TestGenerateWithExtraAccounts(t *testing.T) {
   552  	var (
   553  		diskdb = memorydb.New()
   554  		triedb = trie.NewDatabase(diskdb)
   555  		stTrie = getStorageTrie(5, triedb)
   556  	)
   557  	accTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   558  	{ // Account one in the trie
   559  		acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   560  		val, _ := rlp.EncodeToBytes(acc)
   561  		accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
   562  		// Identical in the snap
   563  		key := hashData([]byte("acc-1"))
   564  		rawdb.WriteAccountSnapshot(diskdb, key, val)
   565  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-1")), []byte("val-1"))
   566  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-2")), []byte("val-2"))
   567  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-3")), []byte("val-3"))
   568  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-4")), []byte("val-4"))
   569  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-5")), []byte("val-5"))
   570  	}
   571  	{ // Account two exists only in the snapshot
   572  		acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   573  		val, _ := rlp.EncodeToBytes(acc)
   574  		key := hashData([]byte("acc-2"))
   575  		rawdb.WriteAccountSnapshot(diskdb, key, val)
   576  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("b-key-1")), []byte("b-val-1"))
   577  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("b-key-2")), []byte("b-val-2"))
   578  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("b-key-3")), []byte("b-val-3"))
   579  	}
   580  	root, _ := accTrie.Commit(nil)
   581  	t.Logf("root: %x", root)
   582  	triedb.Commit(root, false, nil)
   583  	// To verify the test: If we now inspect the snap db, there should exist extraneous storage items
   584  	if data := rawdb.ReadStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data == nil {
   585  		t.Fatalf("expected snap storage to exist")
   586  	}
   587  
   588  	snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xdeadbeef"), root, nil)
   589  	select {
   590  	case <-snap.genPending:
   591  		// Snapshot generation succeeded
   592  
   593  	case <-time.After(250 * time.Millisecond):
   594  		t.Errorf("Snapshot generation failed")
   595  	}
   596  	checkSnapRoot(t, snap, root)
   597  	// Signal abortion to the generator and wait for it to tear down
   598  	stop := make(chan struct{})
   599  	snap.genAbort <- stop
   600  	<-stop
   601  	// If we now inspect the snap db, there should exist no extraneous storage items
   602  	if data := rawdb.ReadStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil {
   603  		t.Fatalf("expected slot to be removed, got %v", string(data))
   604  	}
   605  }
   606  
   607  func enableLogging() {
   608  	log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
   609  }
   610  
   611  // Tests that snapshot generation when an extra account with storage exists in the snap state.
   612  func TestGenerateWithManyExtraAccounts(t *testing.T) {
   613  	if false {
   614  		enableLogging()
   615  	}
   616  	var (
   617  		diskdb = memorydb.New()
   618  		triedb = trie.NewDatabase(diskdb)
   619  		stTrie = getStorageTrie(3, triedb)
   620  	)
   621  	accTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   622  	{ // Account one in the trie
   623  		acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   624  		val, _ := rlp.EncodeToBytes(acc)
   625  		accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
   626  		// Identical in the snap
   627  		key := hashData([]byte("acc-1"))
   628  		rawdb.WriteAccountSnapshot(diskdb, key, val)
   629  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-1")), []byte("val-1"))
   630  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-2")), []byte("val-2"))
   631  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-3")), []byte("val-3"))
   632  	}
   633  	{ // 100 accounts exist only in snapshot
   634  		for i := 0; i < 1000; i++ {
   635  			//acc := &Account{Balance: big.NewInt(int64(i)), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   636  			acc := &Account{Balance: big.NewInt(int64(i)), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   637  			val, _ := rlp.EncodeToBytes(acc)
   638  			key := hashData([]byte(fmt.Sprintf("acc-%d", i)))
   639  			rawdb.WriteAccountSnapshot(diskdb, key, val)
   640  		}
   641  	}
   642  	root, _ := accTrie.Commit(nil)
   643  	t.Logf("root: %x", root)
   644  	triedb.Commit(root, false, nil)
   645  
   646  	snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xdeadbeef"), root, nil)
   647  	select {
   648  	case <-snap.genPending:
   649  		// Snapshot generation succeeded
   650  
   651  	case <-time.After(5 * time.Second):
   652  		t.Errorf("Snapshot generation failed")
   653  	}
   654  	checkSnapRoot(t, snap, root)
   655  	// Signal abortion to the generator and wait for it to tear down
   656  	stop := make(chan struct{})
   657  	snap.genAbort <- stop
   658  	<-stop
   659  }
   660  
   661  // Tests this case
   662  // maxAccountRange 3
   663  // snapshot-accounts: 01, 02, 03, 04, 05, 06, 07
   664  // trie-accounts:             03,             07
   665  //
   666  // We iterate three snapshot storage slots (max = 3) from the database. They are 0x01, 0x02, 0x03.
   667  // The trie has a lot of deletions.
   668  // 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.
   669  // But in the database, we still have the stale storage slots 0x04, 0x05. They are not iterated yet, but the procedure is finished.
   670  func TestGenerateWithExtraBeforeAndAfter(t *testing.T) {
   671  	if false {
   672  		enableLogging()
   673  	}
   674  	var (
   675  		diskdb = memorydb.New()
   676  		triedb = trie.NewDatabase(diskdb)
   677  	)
   678  	accTrie, _ := trie.New(common.Hash{}, triedb)
   679  	{
   680  		acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   681  		val, _ := rlp.EncodeToBytes(acc)
   682  		accTrie.Update(common.HexToHash("0x03").Bytes(), val)
   683  		accTrie.Update(common.HexToHash("0x07").Bytes(), val)
   684  
   685  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x01"), val)
   686  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x02"), val)
   687  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x03"), val)
   688  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x04"), val)
   689  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x05"), val)
   690  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x06"), val)
   691  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x07"), val)
   692  	}
   693  
   694  	root, _ := accTrie.Commit(nil)
   695  	t.Logf("root: %x", root)
   696  	triedb.Commit(root, false, nil)
   697  
   698  	snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xdeadbeef"), root, nil)
   699  	select {
   700  	case <-snap.genPending:
   701  		// Snapshot generation succeeded
   702  
   703  	case <-time.After(250 * time.Millisecond):
   704  		t.Errorf("Snapshot generation failed")
   705  	}
   706  	checkSnapRoot(t, snap, root)
   707  	// Signal abortion to the generator and wait for it to tear down
   708  	stop := make(chan struct{})
   709  	snap.genAbort <- stop
   710  	<-stop
   711  }
   712  
   713  // TestGenerateWithMalformedSnapdata tests what happes if we have some junk
   714  // in the snapshot database, which cannot be parsed back to an account
   715  func TestGenerateWithMalformedSnapdata(t *testing.T) {
   716  	if false {
   717  		enableLogging()
   718  	}
   719  	var (
   720  		diskdb = memorydb.New()
   721  		triedb = trie.NewDatabase(diskdb)
   722  	)
   723  	accTrie, _ := trie.New(common.Hash{}, triedb)
   724  	{
   725  		acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   726  		val, _ := rlp.EncodeToBytes(acc)
   727  		accTrie.Update(common.HexToHash("0x03").Bytes(), val)
   728  
   729  		junk := make([]byte, 100)
   730  		copy(junk, []byte{0xde, 0xad})
   731  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x02"), junk)
   732  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x03"), junk)
   733  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x04"), junk)
   734  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x05"), junk)
   735  	}
   736  
   737  	root, _ := accTrie.Commit(nil)
   738  	t.Logf("root: %x", root)
   739  	triedb.Commit(root, false, nil)
   740  
   741  	snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xdeadbeef"), root, nil)
   742  	select {
   743  	case <-snap.genPending:
   744  		// Snapshot generation succeeded
   745  
   746  	case <-time.After(250 * time.Millisecond):
   747  		t.Errorf("Snapshot generation failed")
   748  	}
   749  	checkSnapRoot(t, snap, root)
   750  	// Signal abortion to the generator and wait for it to tear down
   751  	stop := make(chan struct{})
   752  	snap.genAbort <- stop
   753  	<-stop
   754  	// If we now inspect the snap db, there should exist no extraneous storage items
   755  	if data := rawdb.ReadStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil {
   756  		t.Fatalf("expected slot to be removed, got %v", string(data))
   757  	}
   758  }
   759  
   760  func TestGenerateFromEmptySnap(t *testing.T) {
   761  	//enableLogging()
   762  	helper := newHelper()
   763  	stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   764  	// Add 1K accounts to the trie
   765  	for i := 0; i < 400; i++ {
   766  		helper.addTrieAccount(fmt.Sprintf("acc-%d", i),
   767  			&Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   768  	}
   769  	root, snap := helper.Generate()
   770  	t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4
   771  
   772  	select {
   773  	case <-snap.genPending:
   774  		// Snapshot generation succeeded
   775  
   776  	case <-time.After(1 * time.Second):
   777  		t.Errorf("Snapshot generation failed")
   778  	}
   779  	checkSnapRoot(t, snap, root)
   780  	// Signal abortion to the generator and wait for it to tear down
   781  	stop := make(chan struct{})
   782  	snap.genAbort <- stop
   783  	<-stop
   784  }
   785  
   786  // Tests that snapshot generation with existent flat state, where the flat state
   787  // storage is correct, but incomplete.
   788  // The incomplete part is on the second range
   789  // snap: [ 0x01, 0x02, 0x03, 0x04] , [ 0x05, 0x06, 0x07, {missing}] (with storageCheck = 4)
   790  // trie:  0x01, 0x02, 0x03, 0x04,  0x05, 0x06, 0x07, 0x08
   791  // This hits a case where the snap verification passes, but there are more elements in the trie
   792  // which we must also add.
   793  func TestGenerateWithIncompleteStorage(t *testing.T) {
   794  	helper := newHelper()
   795  	stKeys := []string{"1", "2", "3", "4", "5", "6", "7", "8"}
   796  	stVals := []string{"v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"}
   797  	stRoot := helper.makeStorageTrie(stKeys, stVals)
   798  	// We add 8 accounts, each one is missing exactly one of the storage slots. This means
   799  	// we don't have to order the keys and figure out exactly which hash-key winds up
   800  	// on the sensitive spots at the boundaries
   801  	for i := 0; i < 8; i++ {
   802  		accKey := fmt.Sprintf("acc-%d", i)
   803  		helper.addAccount(accKey, &Account{Balance: big.NewInt(int64(i)), Root: stRoot, CodeHash: emptyCode.Bytes()})
   804  		var moddedKeys []string
   805  		var moddedVals []string
   806  		for ii := 0; ii < 8; ii++ {
   807  			if ii != i {
   808  				moddedKeys = append(moddedKeys, stKeys[ii])
   809  				moddedVals = append(moddedVals, stVals[ii])
   810  			}
   811  		}
   812  		helper.addSnapStorage(accKey, moddedKeys, moddedVals)
   813  	}
   814  
   815  	root, snap := helper.Generate()
   816  	t.Logf("Root: %#x\n", root) // Root: 0xca73f6f05ba4ca3024ef340ef3dfca8fdabc1b677ff13f5a9571fd49c16e67ff
   817  
   818  	select {
   819  	case <-snap.genPending:
   820  		// Snapshot generation succeeded
   821  
   822  	case <-time.After(250 * time.Millisecond):
   823  		t.Errorf("Snapshot generation failed")
   824  	}
   825  	checkSnapRoot(t, snap, root)
   826  	// Signal abortion to the generator and wait for it to tear down
   827  	stop := make(chan struct{})
   828  	snap.genAbort <- stop
   829  	<-stop
   830  }