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