github.com/aidoskuneen/adk-node@v0.0.0-20220315131952-2e32567cb7f4/core/state/snapshot/generate_test.go (about)

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