github.com/electroneum/electroneum-sc@v0.0.0-20230105223411-3bc1d078281e/core/state/snapshot/generate_test.go (about)

     1  // Copyright 2019 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package snapshot
    18  
    19  import (
    20  	"fmt"
    21  	"math/big"
    22  	"os"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/electroneum/electroneum-sc/common"
    27  	"github.com/electroneum/electroneum-sc/core/rawdb"
    28  	"github.com/electroneum/electroneum-sc/ethdb"
    29  	"github.com/electroneum/electroneum-sc/ethdb/memorydb"
    30  	"github.com/electroneum/electroneum-sc/log"
    31  	"github.com/electroneum/electroneum-sc/rlp"
    32  	"github.com/electroneum/electroneum-sc/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  
   152  	accIt := snap.AccountIterator(common.Hash{})
   153  	defer accIt.Release()
   154  
   155  	snapRoot, err := generateTrieRoot(nil, accIt, common.Hash{}, stackTrieGenerate,
   156  		func(db ethdb.KeyValueWriter, accountHash, codeHash common.Hash, stat *generateStats) (common.Hash, error) {
   157  			storageIt, _ := snap.StorageIterator(accountHash, common.Hash{})
   158  			defer storageIt.Release()
   159  
   160  			hash, err := generateTrieRoot(nil, storageIt, accountHash, stackTrieGenerate, nil, stat, false)
   161  			if err != nil {
   162  				return common.Hash{}, err
   163  			}
   164  			return hash, nil
   165  		}, newGenerateStats(), true)
   166  
   167  	if err != nil {
   168  		t.Fatal(err)
   169  	}
   170  	if snapRoot != trieRoot {
   171  		t.Fatalf("snaproot: %#x != trieroot #%x", snapRoot, trieRoot)
   172  	}
   173  	if err := CheckDanglingStorage(snap.diskdb); err != nil {
   174  		t.Fatalf("Detected dangling storages %v", err)
   175  	}
   176  }
   177  
   178  type testHelper struct {
   179  	diskdb  *memorydb.Database
   180  	triedb  *trie.Database
   181  	accTrie *trie.SecureTrie
   182  }
   183  
   184  func newHelper() *testHelper {
   185  	diskdb := memorydb.New()
   186  	triedb := trie.NewDatabase(diskdb)
   187  	accTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   188  	return &testHelper{
   189  		diskdb:  diskdb,
   190  		triedb:  triedb,
   191  		accTrie: accTrie,
   192  	}
   193  }
   194  
   195  func (t *testHelper) addTrieAccount(acckey string, acc *Account) {
   196  	val, _ := rlp.EncodeToBytes(acc)
   197  	t.accTrie.Update([]byte(acckey), val)
   198  }
   199  
   200  func (t *testHelper) addSnapAccount(acckey string, acc *Account) {
   201  	val, _ := rlp.EncodeToBytes(acc)
   202  	key := hashData([]byte(acckey))
   203  	rawdb.WriteAccountSnapshot(t.diskdb, key, val)
   204  }
   205  
   206  func (t *testHelper) addAccount(acckey string, acc *Account) {
   207  	t.addTrieAccount(acckey, acc)
   208  	t.addSnapAccount(acckey, acc)
   209  }
   210  
   211  func (t *testHelper) addSnapStorage(accKey string, keys []string, vals []string) {
   212  	accHash := hashData([]byte(accKey))
   213  	for i, key := range keys {
   214  		rawdb.WriteStorageSnapshot(t.diskdb, accHash, hashData([]byte(key)), []byte(vals[i]))
   215  	}
   216  }
   217  
   218  func (t *testHelper) makeStorageTrie(keys []string, vals []string) []byte {
   219  	stTrie, _ := trie.NewSecure(common.Hash{}, t.triedb)
   220  	for i, k := range keys {
   221  		stTrie.Update([]byte(k), []byte(vals[i]))
   222  	}
   223  	root, _, _ := stTrie.Commit(nil)
   224  	return root.Bytes()
   225  }
   226  
   227  func (t *testHelper) Generate() (common.Hash, *diskLayer) {
   228  	root, _, _ := t.accTrie.Commit(nil)
   229  	t.triedb.Commit(root, false, nil)
   230  	snap := generateSnapshot(t.diskdb, t.triedb, 16, root)
   231  	return root, snap
   232  }
   233  
   234  // Tests that snapshot generation with existent flat state, where the flat state
   235  // contains some errors:
   236  // - the contract with empty storage root but has storage entries in the disk
   237  // - the contract with non empty storage root but empty storage slots
   238  // - the contract(non-empty storage) misses some storage slots
   239  //   - miss in the beginning
   240  //   - miss in the middle
   241  //   - miss in the end
   242  //
   243  // - the contract(non-empty storage) has wrong storage slots
   244  //   - wrong slots in the beginning
   245  //   - wrong slots in the middle
   246  //   - wrong slots in the end
   247  //
   248  // - the contract(non-empty storage) has extra storage slots
   249  //   - extra slots in the beginning
   250  //   - extra slots in the middle
   251  //   - extra slots in the end
   252  func TestGenerateExistentStateWithWrongStorage(t *testing.T) {
   253  	helper := newHelper()
   254  	stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   255  
   256  	// Account one, empty root but non-empty database
   257  	helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
   258  	helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   259  
   260  	// Account two, non empty root but empty database
   261  	helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   262  
   263  	// Miss slots
   264  	{
   265  		// Account three, non empty root but misses slots in the beginning
   266  		helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   267  		helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"})
   268  
   269  		// Account four, non empty root but misses slots in the middle
   270  		helper.addAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   271  		helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"})
   272  
   273  		// Account five, non empty root but misses slots in the end
   274  		helper.addAccount("acc-5", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   275  		helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"})
   276  	}
   277  
   278  	// Wrong storage slots
   279  	{
   280  		// Account six, non empty root but wrong slots in the beginning
   281  		helper.addAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   282  		helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"})
   283  
   284  		// Account seven, non empty root but wrong slots in the middle
   285  		helper.addAccount("acc-7", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   286  		helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"})
   287  
   288  		// Account eight, non empty root but wrong slots in the end
   289  		helper.addAccount("acc-8", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   290  		helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"})
   291  
   292  		// Account 9, non empty root but rotated slots
   293  		helper.addAccount("acc-9", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   294  		helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"})
   295  	}
   296  
   297  	// Extra storage slots
   298  	{
   299  		// Account 10, non empty root but extra slots in the beginning
   300  		helper.addAccount("acc-10", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   301  		helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"})
   302  
   303  		// Account 11, non empty root but extra slots in the middle
   304  		helper.addAccount("acc-11", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   305  		helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"})
   306  
   307  		// Account 12, non empty root but extra slots in the end
   308  		helper.addAccount("acc-12", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   309  		helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"})
   310  	}
   311  
   312  	root, snap := helper.Generate()
   313  	t.Logf("Root: %#x\n", root) // Root = 0x8746cce9fd9c658b2cfd639878ed6584b7a2b3e73bb40f607fcfa156002429a0
   314  
   315  	select {
   316  	case <-snap.genPending:
   317  		// Snapshot generation succeeded
   318  
   319  	case <-time.After(3 * time.Second):
   320  		t.Errorf("Snapshot generation failed")
   321  	}
   322  	checkSnapRoot(t, snap, root)
   323  	// Signal abortion to the generator and wait for it to tear down
   324  	stop := make(chan *generatorStats)
   325  	snap.genAbort <- stop
   326  	<-stop
   327  }
   328  
   329  // Tests that snapshot generation with existent flat state, where the flat state
   330  // contains some errors:
   331  // - miss accounts
   332  // - wrong accounts
   333  // - extra accounts
   334  func TestGenerateExistentStateWithWrongAccounts(t *testing.T) {
   335  	helper := newHelper()
   336  	stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   337  
   338  	// Trie accounts [acc-1, acc-2, acc-3, acc-4, acc-6]
   339  	// Extra accounts [acc-0, acc-5, acc-7]
   340  
   341  	// Missing accounts, only in the trie
   342  	{
   343  		helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // Beginning
   344  		helper.addTrieAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // Middle
   345  		helper.addTrieAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // End
   346  	}
   347  
   348  	// Wrong accounts
   349  	{
   350  		helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   351  		helper.addSnapAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")})
   352  
   353  		helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   354  		helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
   355  	}
   356  
   357  	// Extra accounts, only in the snap
   358  	{
   359  		helper.addSnapAccount("acc-0", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyRoot.Bytes()})                     // before the beginning
   360  		helper.addSnapAccount("acc-5", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: common.Hex2Bytes("0x1234")}) // Middle
   361  		helper.addSnapAccount("acc-7", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyRoot.Bytes()})          // after the end
   362  	}
   363  
   364  	root, snap := helper.Generate()
   365  	t.Logf("Root: %#x\n", root) // Root = 0x825891472281463511e7ebcc7f109e4f9200c20fa384754e11fd605cd98464e8
   366  
   367  	select {
   368  	case <-snap.genPending:
   369  		// Snapshot generation succeeded
   370  
   371  	case <-time.After(3 * time.Second):
   372  		t.Errorf("Snapshot generation failed")
   373  	}
   374  	checkSnapRoot(t, snap, root)
   375  
   376  	// Signal abortion to the generator and wait for it to tear down
   377  	stop := make(chan *generatorStats)
   378  	snap.genAbort <- stop
   379  	<-stop
   380  }
   381  
   382  // Tests that snapshot generation errors out correctly in case of a missing trie
   383  // node in the account trie.
   384  func TestGenerateCorruptAccountTrie(t *testing.T) {
   385  	// We can't use statedb to make a test trie (circular dependency), so make
   386  	// a fake one manually. We're going with a small account trie of 3 accounts,
   387  	// without any storage slots to keep the test smaller.
   388  	var (
   389  		diskdb = memorydb.New()
   390  		triedb = trie.NewDatabase(diskdb)
   391  	)
   392  	tr, _ := trie.NewSecure(common.Hash{}, triedb)
   393  	acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   394  	val, _ := rlp.EncodeToBytes(acc)
   395  	tr.Update([]byte("acc-1"), val) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074
   396  
   397  	acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   398  	val, _ = rlp.EncodeToBytes(acc)
   399  	tr.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
   400  
   401  	acc = &Account{Balance: big.NewInt(3), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   402  	val, _ = rlp.EncodeToBytes(acc)
   403  	tr.Update([]byte("acc-3"), val) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
   404  	tr.Commit(nil)                  // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
   405  
   406  	// Delete an account trie leaf and ensure the generator chokes
   407  	triedb.Commit(common.HexToHash("0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978"), false, nil)
   408  	diskdb.Delete(common.HexToHash("0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7").Bytes())
   409  
   410  	snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978"))
   411  	select {
   412  	case <-snap.genPending:
   413  		// Snapshot generation succeeded
   414  		t.Errorf("Snapshot generated against corrupt account trie")
   415  
   416  	case <-time.After(time.Second):
   417  		// Not generated fast enough, hopefully blocked inside on missing trie node fail
   418  	}
   419  	// Signal abortion to the generator and wait for it to tear down
   420  	stop := make(chan *generatorStats)
   421  	snap.genAbort <- stop
   422  	<-stop
   423  }
   424  
   425  // Tests that snapshot generation errors out correctly in case of a missing root
   426  // trie node for a storage trie. It's similar to internal corruption but it is
   427  // handled differently inside the generator.
   428  func TestGenerateMissingStorageTrie(t *testing.T) {
   429  	// We can't use statedb to make a test trie (circular dependency), so make
   430  	// a fake one manually. We're going with a small account trie of 3 accounts,
   431  	// two of which also has the same 3-slot storage trie attached.
   432  	var (
   433  		diskdb = memorydb.New()
   434  		triedb = trie.NewDatabase(diskdb)
   435  	)
   436  	stTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   437  	stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0
   438  	stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371
   439  	stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78
   440  	stTrie.Commit(nil)                              // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
   441  
   442  	accTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   443  	acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   444  	val, _ := rlp.EncodeToBytes(acc)
   445  	accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
   446  
   447  	acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   448  	val, _ = rlp.EncodeToBytes(acc)
   449  	accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
   450  
   451  	acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   452  	val, _ = rlp.EncodeToBytes(acc)
   453  	accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
   454  	accTrie.Commit(nil)                  // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd
   455  
   456  	// We can only corrupt the disk database, so flush the tries out
   457  	triedb.Reference(
   458  		common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"),
   459  		common.HexToHash("0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e"),
   460  	)
   461  	triedb.Reference(
   462  		common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"),
   463  		common.HexToHash("0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2"),
   464  	)
   465  	triedb.Commit(common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), false, nil)
   466  
   467  	// Delete a storage trie root and ensure the generator chokes
   468  	diskdb.Delete(common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67").Bytes())
   469  
   470  	snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"))
   471  	select {
   472  	case <-snap.genPending:
   473  		// Snapshot generation succeeded
   474  		t.Errorf("Snapshot generated against corrupt storage trie")
   475  
   476  	case <-time.After(time.Second):
   477  		// Not generated fast enough, hopefully blocked inside on missing trie node fail
   478  	}
   479  	// Signal abortion to the generator and wait for it to tear down
   480  	stop := make(chan *generatorStats)
   481  	snap.genAbort <- stop
   482  	<-stop
   483  }
   484  
   485  // Tests that snapshot generation errors out correctly in case of a missing trie
   486  // node in a storage trie.
   487  func TestGenerateCorruptStorageTrie(t *testing.T) {
   488  	// We can't use statedb to make a test trie (circular dependency), so make
   489  	// a fake one manually. We're going with a small account trie of 3 accounts,
   490  	// two of which also has the same 3-slot storage trie attached.
   491  	var (
   492  		diskdb = memorydb.New()
   493  		triedb = trie.NewDatabase(diskdb)
   494  	)
   495  	stTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   496  	stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0
   497  	stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371
   498  	stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78
   499  	stTrie.Commit(nil)                              // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
   500  
   501  	accTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   502  	acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   503  	val, _ := rlp.EncodeToBytes(acc)
   504  	accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
   505  
   506  	acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   507  	val, _ = rlp.EncodeToBytes(acc)
   508  	accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
   509  
   510  	acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   511  	val, _ = rlp.EncodeToBytes(acc)
   512  	accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
   513  	accTrie.Commit(nil)                  // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd
   514  
   515  	// We can only corrupt the disk database, so flush the tries out
   516  	triedb.Reference(
   517  		common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"),
   518  		common.HexToHash("0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e"),
   519  	)
   520  	triedb.Reference(
   521  		common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"),
   522  		common.HexToHash("0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2"),
   523  	)
   524  	triedb.Commit(common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), false, nil)
   525  
   526  	// Delete a storage trie leaf and ensure the generator chokes
   527  	diskdb.Delete(common.HexToHash("0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371").Bytes())
   528  
   529  	snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"))
   530  	select {
   531  	case <-snap.genPending:
   532  		// Snapshot generation succeeded
   533  		t.Errorf("Snapshot generated against corrupt storage trie")
   534  
   535  	case <-time.After(time.Second):
   536  		// Not generated fast enough, hopefully blocked inside on missing trie node fail
   537  	}
   538  	// Signal abortion to the generator and wait for it to tear down
   539  	stop := make(chan *generatorStats)
   540  	snap.genAbort <- stop
   541  	<-stop
   542  }
   543  
   544  func getStorageTrie(n int, triedb *trie.Database) *trie.SecureTrie {
   545  	stTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   546  	for i := 0; i < n; i++ {
   547  		k := fmt.Sprintf("key-%d", i)
   548  		v := fmt.Sprintf("val-%d", i)
   549  		stTrie.Update([]byte(k), []byte(v))
   550  	}
   551  	stTrie.Commit(nil)
   552  	return stTrie
   553  }
   554  
   555  // Tests that snapshot generation when an extra account with storage exists in the snap state.
   556  func TestGenerateWithExtraAccounts(t *testing.T) {
   557  	var (
   558  		diskdb = memorydb.New()
   559  		triedb = trie.NewDatabase(diskdb)
   560  		stTrie = getStorageTrie(5, triedb)
   561  	)
   562  	accTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   563  	{ // Account one in the trie
   564  		acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   565  		val, _ := rlp.EncodeToBytes(acc)
   566  		accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
   567  		// Identical in the snap
   568  		key := hashData([]byte("acc-1"))
   569  		rawdb.WriteAccountSnapshot(diskdb, key, val)
   570  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-1")), []byte("val-1"))
   571  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-2")), []byte("val-2"))
   572  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-3")), []byte("val-3"))
   573  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-4")), []byte("val-4"))
   574  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-5")), []byte("val-5"))
   575  	}
   576  	{ // Account two exists only in the snapshot
   577  		acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   578  		val, _ := rlp.EncodeToBytes(acc)
   579  		key := hashData([]byte("acc-2"))
   580  		rawdb.WriteAccountSnapshot(diskdb, key, val)
   581  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("b-key-1")), []byte("b-val-1"))
   582  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("b-key-2")), []byte("b-val-2"))
   583  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("b-key-3")), []byte("b-val-3"))
   584  	}
   585  	root, _, _ := accTrie.Commit(nil)
   586  	t.Logf("root: %x", root)
   587  	triedb.Commit(root, false, nil)
   588  	// To verify the test: If we now inspect the snap db, there should exist extraneous storage items
   589  	if data := rawdb.ReadStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data == nil {
   590  		t.Fatalf("expected snap storage to exist")
   591  	}
   592  
   593  	snap := generateSnapshot(diskdb, triedb, 16, root)
   594  	select {
   595  	case <-snap.genPending:
   596  		// Snapshot generation succeeded
   597  
   598  	case <-time.After(3 * time.Second):
   599  		t.Errorf("Snapshot generation failed")
   600  	}
   601  	checkSnapRoot(t, snap, root)
   602  	// Signal abortion to the generator and wait for it to tear down
   603  	stop := make(chan *generatorStats)
   604  	snap.genAbort <- stop
   605  	<-stop
   606  	// If we now inspect the snap db, there should exist no extraneous storage items
   607  	if data := rawdb.ReadStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil {
   608  		t.Fatalf("expected slot to be removed, got %v", string(data))
   609  	}
   610  }
   611  
   612  func enableLogging() {
   613  	log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
   614  }
   615  
   616  // Tests that snapshot generation when an extra account with storage exists in the snap state.
   617  func TestGenerateWithManyExtraAccounts(t *testing.T) {
   618  	if false {
   619  		enableLogging()
   620  	}
   621  	var (
   622  		diskdb = memorydb.New()
   623  		triedb = trie.NewDatabase(diskdb)
   624  		stTrie = getStorageTrie(3, triedb)
   625  	)
   626  	accTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   627  	{ // Account one in the trie
   628  		acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   629  		val, _ := rlp.EncodeToBytes(acc)
   630  		accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
   631  		// Identical in the snap
   632  		key := hashData([]byte("acc-1"))
   633  		rawdb.WriteAccountSnapshot(diskdb, key, val)
   634  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-1")), []byte("val-1"))
   635  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-2")), []byte("val-2"))
   636  		rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-3")), []byte("val-3"))
   637  	}
   638  	{ // 100 accounts exist only in snapshot
   639  		for i := 0; i < 1000; i++ {
   640  			//acc := &Account{Balance: big.NewInt(int64(i)), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   641  			acc := &Account{Balance: big.NewInt(int64(i)), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   642  			val, _ := rlp.EncodeToBytes(acc)
   643  			key := hashData([]byte(fmt.Sprintf("acc-%d", i)))
   644  			rawdb.WriteAccountSnapshot(diskdb, key, val)
   645  		}
   646  	}
   647  	root, _, _ := accTrie.Commit(nil)
   648  	t.Logf("root: %x", root)
   649  	triedb.Commit(root, false, nil)
   650  
   651  	snap := generateSnapshot(diskdb, triedb, 16, root)
   652  	select {
   653  	case <-snap.genPending:
   654  		// Snapshot generation succeeded
   655  
   656  	case <-time.After(3 * time.Second):
   657  		t.Errorf("Snapshot generation failed")
   658  	}
   659  	checkSnapRoot(t, snap, root)
   660  	// Signal abortion to the generator and wait for it to tear down
   661  	stop := make(chan *generatorStats)
   662  	snap.genAbort <- stop
   663  	<-stop
   664  }
   665  
   666  // Tests this case
   667  // maxAccountRange 3
   668  // snapshot-accounts: 01, 02, 03, 04, 05, 06, 07
   669  // trie-accounts:             03,             07
   670  //
   671  // We iterate three snapshot storage slots (max = 3) from the database. They are 0x01, 0x02, 0x03.
   672  // The trie has a lot of deletions.
   673  // 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.
   674  // But in the database, we still have the stale storage slots 0x04, 0x05. They are not iterated yet, but the procedure is finished.
   675  func TestGenerateWithExtraBeforeAndAfter(t *testing.T) {
   676  	accountCheckRange = 3
   677  	if false {
   678  		enableLogging()
   679  	}
   680  	var (
   681  		diskdb = memorydb.New()
   682  		triedb = trie.NewDatabase(diskdb)
   683  	)
   684  	accTrie, _ := trie.New(common.Hash{}, triedb)
   685  	{
   686  		acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   687  		val, _ := rlp.EncodeToBytes(acc)
   688  		accTrie.Update(common.HexToHash("0x03").Bytes(), val)
   689  		accTrie.Update(common.HexToHash("0x07").Bytes(), val)
   690  
   691  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x01"), val)
   692  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x02"), val)
   693  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x03"), val)
   694  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x04"), val)
   695  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x05"), val)
   696  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x06"), val)
   697  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x07"), val)
   698  	}
   699  
   700  	root, _, _ := accTrie.Commit(nil)
   701  	t.Logf("root: %x", root)
   702  	triedb.Commit(root, false, nil)
   703  
   704  	snap := generateSnapshot(diskdb, triedb, 16, root)
   705  	select {
   706  	case <-snap.genPending:
   707  		// Snapshot generation succeeded
   708  
   709  	case <-time.After(3 * time.Second):
   710  		t.Errorf("Snapshot generation failed")
   711  	}
   712  	checkSnapRoot(t, snap, root)
   713  	// Signal abortion to the generator and wait for it to tear down
   714  	stop := make(chan *generatorStats)
   715  	snap.genAbort <- stop
   716  	<-stop
   717  }
   718  
   719  // TestGenerateWithMalformedSnapdata tests what happes if we have some junk
   720  // in the snapshot database, which cannot be parsed back to an account
   721  func TestGenerateWithMalformedSnapdata(t *testing.T) {
   722  	accountCheckRange = 3
   723  	if false {
   724  		enableLogging()
   725  	}
   726  	var (
   727  		diskdb = memorydb.New()
   728  		triedb = trie.NewDatabase(diskdb)
   729  	)
   730  	accTrie, _ := trie.New(common.Hash{}, triedb)
   731  	{
   732  		acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   733  		val, _ := rlp.EncodeToBytes(acc)
   734  		accTrie.Update(common.HexToHash("0x03").Bytes(), val)
   735  
   736  		junk := make([]byte, 100)
   737  		copy(junk, []byte{0xde, 0xad})
   738  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x02"), junk)
   739  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x03"), junk)
   740  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x04"), junk)
   741  		rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x05"), junk)
   742  	}
   743  
   744  	root, _, _ := accTrie.Commit(nil)
   745  	t.Logf("root: %x", root)
   746  	triedb.Commit(root, false, nil)
   747  
   748  	snap := generateSnapshot(diskdb, triedb, 16, root)
   749  	select {
   750  	case <-snap.genPending:
   751  		// Snapshot generation succeeded
   752  
   753  	case <-time.After(3 * time.Second):
   754  		t.Errorf("Snapshot generation failed")
   755  	}
   756  	checkSnapRoot(t, snap, root)
   757  	// Signal abortion to the generator and wait for it to tear down
   758  	stop := make(chan *generatorStats)
   759  	snap.genAbort <- stop
   760  	<-stop
   761  	// If we now inspect the snap db, there should exist no extraneous storage items
   762  	if data := rawdb.ReadStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil {
   763  		t.Fatalf("expected slot to be removed, got %v", string(data))
   764  	}
   765  }
   766  
   767  func TestGenerateFromEmptySnap(t *testing.T) {
   768  	//enableLogging()
   769  	accountCheckRange = 10
   770  	storageCheckRange = 20
   771  	helper := newHelper()
   772  	stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   773  	// Add 1K accounts to the trie
   774  	for i := 0; i < 400; i++ {
   775  		helper.addTrieAccount(fmt.Sprintf("acc-%d", i),
   776  			&Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   777  	}
   778  	root, snap := helper.Generate()
   779  	t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4
   780  
   781  	select {
   782  	case <-snap.genPending:
   783  		// Snapshot generation succeeded
   784  
   785  	case <-time.After(3 * time.Second):
   786  		t.Errorf("Snapshot generation failed")
   787  	}
   788  	checkSnapRoot(t, snap, root)
   789  	// Signal abortion to the generator and wait for it to tear down
   790  	stop := make(chan *generatorStats)
   791  	snap.genAbort <- stop
   792  	<-stop
   793  }
   794  
   795  // Tests that snapshot generation with existent flat state, where the flat state
   796  // storage is correct, but incomplete.
   797  // The incomplete part is on the second range
   798  // snap: [ 0x01, 0x02, 0x03, 0x04] , [ 0x05, 0x06, 0x07, {missing}] (with storageCheck = 4)
   799  // trie:  0x01, 0x02, 0x03, 0x04,  0x05, 0x06, 0x07, 0x08
   800  // This hits a case where the snap verification passes, but there are more elements in the trie
   801  // which we must also add.
   802  func TestGenerateWithIncompleteStorage(t *testing.T) {
   803  	storageCheckRange = 4
   804  	helper := newHelper()
   805  	stKeys := []string{"1", "2", "3", "4", "5", "6", "7", "8"}
   806  	stVals := []string{"v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"}
   807  	stRoot := helper.makeStorageTrie(stKeys, stVals)
   808  	// We add 8 accounts, each one is missing exactly one of the storage slots. This means
   809  	// we don't have to order the keys and figure out exactly which hash-key winds up
   810  	// on the sensitive spots at the boundaries
   811  	for i := 0; i < 8; i++ {
   812  		accKey := fmt.Sprintf("acc-%d", i)
   813  		helper.addAccount(accKey, &Account{Balance: big.NewInt(int64(i)), Root: stRoot, CodeHash: emptyCode.Bytes()})
   814  		var moddedKeys []string
   815  		var moddedVals []string
   816  		for ii := 0; ii < 8; ii++ {
   817  			if ii != i {
   818  				moddedKeys = append(moddedKeys, stKeys[ii])
   819  				moddedVals = append(moddedVals, stVals[ii])
   820  			}
   821  		}
   822  		helper.addSnapStorage(accKey, moddedKeys, moddedVals)
   823  	}
   824  
   825  	root, snap := helper.Generate()
   826  	t.Logf("Root: %#x\n", root) // Root: 0xca73f6f05ba4ca3024ef340ef3dfca8fdabc1b677ff13f5a9571fd49c16e67ff
   827  
   828  	select {
   829  	case <-snap.genPending:
   830  		// Snapshot generation succeeded
   831  
   832  	case <-time.After(3 * time.Second):
   833  		t.Errorf("Snapshot generation failed")
   834  	}
   835  	checkSnapRoot(t, snap, root)
   836  	// Signal abortion to the generator and wait for it to tear down
   837  	stop := make(chan *generatorStats)
   838  	snap.genAbort <- stop
   839  	<-stop
   840  }
   841  
   842  func incKey(key []byte) []byte {
   843  	for i := len(key) - 1; i >= 0; i-- {
   844  		key[i]++
   845  		if key[i] != 0x0 {
   846  			break
   847  		}
   848  	}
   849  	return key
   850  }
   851  
   852  func decKey(key []byte) []byte {
   853  	for i := len(key) - 1; i >= 0; i-- {
   854  		key[i]--
   855  		if key[i] != 0xff {
   856  			break
   857  		}
   858  	}
   859  	return key
   860  }
   861  
   862  func populateDangling(disk ethdb.KeyValueStore) {
   863  	populate := func(accountHash common.Hash, keys []string, vals []string) {
   864  		for i, key := range keys {
   865  			rawdb.WriteStorageSnapshot(disk, accountHash, hashData([]byte(key)), []byte(vals[i]))
   866  		}
   867  	}
   868  	// Dangling storages of the "first" account
   869  	populate(common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   870  
   871  	// Dangling storages of the "last" account
   872  	populate(common.HexToHash("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   873  
   874  	// Dangling storages around the account 1
   875  	hash := decKey(hashData([]byte("acc-1")).Bytes())
   876  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   877  	hash = incKey(hashData([]byte("acc-1")).Bytes())
   878  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   879  
   880  	// Dangling storages around the account 2
   881  	hash = decKey(hashData([]byte("acc-2")).Bytes())
   882  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   883  	hash = incKey(hashData([]byte("acc-2")).Bytes())
   884  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   885  
   886  	// Dangling storages around the account 3
   887  	hash = decKey(hashData([]byte("acc-3")).Bytes())
   888  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   889  	hash = incKey(hashData([]byte("acc-3")).Bytes())
   890  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   891  
   892  	// Dangling storages of the random account
   893  	populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   894  	populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   895  	populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   896  }
   897  
   898  // Tests that snapshot generation with dangling storages. Dangling storage means
   899  // the storage data is existent while the corresponding account data is missing.
   900  //
   901  // This test will populate some dangling storages to see if they can be cleaned up.
   902  func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) {
   903  	var helper = newHelper()
   904  	stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   905  
   906  	helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   907  	helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
   908  	helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   909  
   910  	helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   911  	helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   912  
   913  	populateDangling(helper.diskdb)
   914  
   915  	root, snap := helper.Generate()
   916  	select {
   917  	case <-snap.genPending:
   918  		// Snapshot generation succeeded
   919  
   920  	case <-time.After(3 * time.Second):
   921  		t.Errorf("Snapshot generation failed")
   922  	}
   923  	checkSnapRoot(t, snap, root)
   924  
   925  	// Signal abortion to the generator and wait for it to tear down
   926  	stop := make(chan *generatorStats)
   927  	snap.genAbort <- stop
   928  	<-stop
   929  }
   930  
   931  // Tests that snapshot generation with dangling storages. Dangling storage means
   932  // the storage data is existent while the corresponding account data is missing.
   933  //
   934  // This test will populate some dangling storages to see if they can be cleaned up.
   935  func TestGenerateBrokenSnapshotWithDanglingStorage(t *testing.T) {
   936  	var helper = newHelper()
   937  	stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   938  
   939  	helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
   940  	helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
   941  	helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()})
   942  
   943  	populateDangling(helper.diskdb)
   944  
   945  	root, snap := helper.Generate()
   946  	select {
   947  	case <-snap.genPending:
   948  		// Snapshot generation succeeded
   949  
   950  	case <-time.After(3 * time.Second):
   951  		t.Errorf("Snapshot generation failed")
   952  	}
   953  	checkSnapRoot(t, snap, root)
   954  
   955  	// Signal abortion to the generator and wait for it to tear down
   956  	stop := make(chan *generatorStats)
   957  	snap.genAbort <- stop
   958  	<-stop
   959  }