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