github.com/klaytn/klaytn@v1.12.1/snapshot/generate_test.go (about)

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