github.com/ethereum/go-ethereum@v1.16.1/triedb/pathdb/generate_test.go (about)

     1  // Copyright 2024 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 pathdb
    18  
    19  import (
    20  	"fmt"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/core/rawdb"
    26  	"github.com/ethereum/go-ethereum/core/types"
    27  	"github.com/ethereum/go-ethereum/crypto"
    28  	"github.com/ethereum/go-ethereum/ethdb"
    29  	"github.com/ethereum/go-ethereum/internal/testrand"
    30  	"github.com/ethereum/go-ethereum/rlp"
    31  	"github.com/ethereum/go-ethereum/trie"
    32  	"github.com/ethereum/go-ethereum/trie/trienode"
    33  	"github.com/holiman/uint256"
    34  )
    35  
    36  func hashData(input []byte) common.Hash {
    37  	return crypto.Keccak256Hash(input)
    38  }
    39  
    40  type genTester struct {
    41  	diskdb   ethdb.Database
    42  	db       *Database
    43  	acctTrie *trie.Trie
    44  	nodes    *trienode.MergedNodeSet
    45  	states   *StateSetWithOrigin
    46  }
    47  
    48  func newGenTester() *genTester {
    49  	disk := rawdb.NewMemoryDatabase()
    50  	config := *Defaults
    51  	config.SnapshotNoBuild = true // no background generation
    52  	config.NoAsyncFlush = true    // no async flush
    53  	db := New(disk, &config, false)
    54  	tr, _ := trie.New(trie.StateTrieID(types.EmptyRootHash), db)
    55  	return &genTester{
    56  		diskdb:   disk,
    57  		db:       db,
    58  		acctTrie: tr,
    59  		nodes:    trienode.NewMergedNodeSet(),
    60  		states:   NewStateSetWithOrigin(nil, nil, nil, nil, false),
    61  	}
    62  }
    63  
    64  func (t *genTester) addTrieAccount(acckey string, acc *types.StateAccount) {
    65  	var (
    66  		addr   = common.BytesToAddress([]byte(acckey))
    67  		key    = hashData([]byte(acckey))
    68  		val, _ = rlp.EncodeToBytes(acc)
    69  	)
    70  	t.acctTrie.MustUpdate(key.Bytes(), val)
    71  
    72  	t.states.accountData[key] = val
    73  	t.states.accountOrigin[addr] = nil
    74  }
    75  
    76  func (t *genTester) addSnapAccount(acckey string, acc *types.StateAccount) {
    77  	key := hashData([]byte(acckey))
    78  	rawdb.WriteAccountSnapshot(t.diskdb, key, types.SlimAccountRLP(*acc))
    79  }
    80  
    81  func (t *genTester) addAccount(acckey string, acc *types.StateAccount) {
    82  	t.addTrieAccount(acckey, acc)
    83  	t.addSnapAccount(acckey, acc)
    84  }
    85  
    86  func (t *genTester) addSnapStorage(accKey string, keys []string, vals []string) {
    87  	accHash := hashData([]byte(accKey))
    88  	for i, key := range keys {
    89  		rawdb.WriteStorageSnapshot(t.diskdb, accHash, hashData([]byte(key)), []byte(vals[i]))
    90  	}
    91  }
    92  
    93  func (t *genTester) makeStorageTrie(accKey string, keys []string, vals []string, commit bool) common.Hash {
    94  	var (
    95  		owner = hashData([]byte(accKey))
    96  		addr  = common.BytesToAddress([]byte(accKey))
    97  		id    = trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash)
    98  		tr, _ = trie.New(id, t.db)
    99  
   100  		storages       = make(map[common.Hash][]byte)
   101  		storageOrigins = make(map[common.Hash][]byte)
   102  	)
   103  	for i, k := range keys {
   104  		key := hashData([]byte(k))
   105  		tr.MustUpdate(key.Bytes(), []byte(vals[i]))
   106  		storages[key] = []byte(vals[i])
   107  		storageOrigins[key] = nil
   108  	}
   109  	if !commit {
   110  		return tr.Hash()
   111  	}
   112  	root, nodes := tr.Commit(false)
   113  	if nodes != nil {
   114  		t.nodes.Merge(nodes)
   115  	}
   116  	t.states.storageData[owner] = storages
   117  	t.states.storageOrigin[addr] = storageOrigins
   118  	return root
   119  }
   120  
   121  func (t *genTester) Commit() common.Hash {
   122  	root, nodes := t.acctTrie.Commit(true)
   123  	if nodes != nil {
   124  		t.nodes.Merge(nodes)
   125  	}
   126  	t.db.Update(root, types.EmptyRootHash, 0, t.nodes, t.states)
   127  	t.db.Commit(root, false)
   128  	return root
   129  }
   130  
   131  func (t *genTester) CommitAndGenerate() (common.Hash, *diskLayer) {
   132  	root := t.Commit()
   133  	dl := generateSnapshot(t.db, root, false)
   134  	return root, dl
   135  }
   136  
   137  // Tests that snapshot generation from an empty database.
   138  func TestGeneration(t *testing.T) {
   139  	helper := newGenTester()
   140  	stRoot := helper.makeStorageTrie("", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false)
   141  
   142  	helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   143  	helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
   144  	helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   145  
   146  	helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   147  	helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   148  
   149  	root, dl := helper.CommitAndGenerate()
   150  	if have, want := root, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"); have != want {
   151  		t.Fatalf("have %#x want %#x", have, want)
   152  	}
   153  	select {
   154  	case <-dl.generator.done:
   155  		// Snapshot generation succeeded
   156  	case <-time.After(3 * time.Second):
   157  		t.Errorf("Snapshot generation failed")
   158  	}
   159  	// TODO(rjl493456442) enable the snapshot tests
   160  	// checkSnapRoot(t, snap, root)
   161  
   162  	// Signal abortion to the generator and wait for it to tear down
   163  	dl.generator.stop()
   164  }
   165  
   166  // Tests that snapshot generation with existent flat state, where the flat state
   167  // contains some errors:
   168  // - the contract with empty storage root but has storage entries in the disk
   169  // - the contract with non empty storage root but empty storage slots
   170  // - the contract(non-empty storage) misses some storage slots
   171  //   - miss in the beginning
   172  //   - miss in the middle
   173  //   - miss in the end
   174  //
   175  // - the contract(non-empty storage) has wrong storage slots
   176  //   - wrong slots in the beginning
   177  //   - wrong slots in the middle
   178  //   - wrong slots in the end
   179  //
   180  // - the contract(non-empty storage) has extra storage slots
   181  //   - extra slots in the beginning
   182  //   - extra slots in the middle
   183  //   - extra slots in the end
   184  func TestGenerateExistentStateWithWrongStorage(t *testing.T) {
   185  	helper := newGenTester()
   186  
   187  	// Account one, empty storage trie root but non-empty flat states
   188  	helper.addAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
   189  	helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   190  
   191  	// Account two, non-empty storage trie root but empty flat states
   192  	stRoot := helper.makeStorageTrie("acc-2", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   193  	helper.addAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   194  
   195  	// Miss slots
   196  	{
   197  		// Account three, non-empty root but misses slots in the beginning
   198  		helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   199  		helper.addAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   200  		helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"})
   201  
   202  		// Account four, non-empty root but misses slots in the middle
   203  		helper.makeStorageTrie("acc-4", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   204  		helper.addAccount("acc-4", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   205  		helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"})
   206  
   207  		// Account five, non-empty root but misses slots in the end
   208  		helper.makeStorageTrie("acc-5", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   209  		helper.addAccount("acc-5", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   210  		helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"})
   211  	}
   212  
   213  	// Wrong storage slots
   214  	{
   215  		// Account six, non-empty root but wrong slots in the beginning
   216  		helper.makeStorageTrie("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   217  		helper.addAccount("acc-6", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   218  		helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"})
   219  
   220  		// Account seven, non-empty root but wrong slots in the middle
   221  		helper.makeStorageTrie("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   222  		helper.addAccount("acc-7", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   223  		helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"})
   224  
   225  		// Account eight, non-empty root but wrong slots in the end
   226  		helper.makeStorageTrie("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   227  		helper.addAccount("acc-8", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   228  		helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"})
   229  
   230  		// Account 9, non-empty root but rotated slots
   231  		helper.makeStorageTrie("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   232  		helper.addAccount("acc-9", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   233  		helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"})
   234  	}
   235  
   236  	// Extra storage slots
   237  	{
   238  		// Account 10, non-empty root but extra slots in the beginning
   239  		helper.makeStorageTrie("acc-10", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   240  		helper.addAccount("acc-10", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   241  		helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"})
   242  
   243  		// Account 11, non-empty root but extra slots in the middle
   244  		helper.makeStorageTrie("acc-11", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   245  		helper.addAccount("acc-11", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   246  		helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"})
   247  
   248  		// Account 12, non-empty root but extra slots in the end
   249  		helper.makeStorageTrie("acc-12", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   250  		helper.addAccount("acc-12", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   251  		helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"})
   252  	}
   253  
   254  	root, dl := helper.CommitAndGenerate()
   255  	t.Logf("Root: %#x\n", root) // Root = 0x8746cce9fd9c658b2cfd639878ed6584b7a2b3e73bb40f607fcfa156002429a0
   256  
   257  	select {
   258  	case <-dl.generator.done:
   259  		// Snapshot generation succeeded
   260  
   261  	case <-time.After(3 * time.Second):
   262  		t.Errorf("Snapshot generation failed")
   263  	}
   264  	// TODO(rjl493456442) enable the snapshot tests
   265  	// checkSnapRoot(t, snap, root)
   266  
   267  	// Signal abortion to the generator and wait for it to tear down
   268  	dl.generator.stop()
   269  }
   270  
   271  // Tests that snapshot generation with existent flat state, where the flat state
   272  // contains some errors:
   273  // - miss accounts
   274  // - wrong accounts
   275  // - extra accounts
   276  func TestGenerateExistentStateWithWrongAccounts(t *testing.T) {
   277  	helper := newGenTester()
   278  
   279  	// Trie accounts [acc-1, acc-2, acc-3, acc-4, acc-6]
   280  	helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   281  	helper.makeStorageTrie("acc-2", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   282  	helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   283  	helper.makeStorageTrie("acc-4", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   284  	stRoot := helper.makeStorageTrie("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   285  
   286  	// Missing accounts, only in the trie
   287  	{
   288  		helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Beginning
   289  		helper.addTrieAccount("acc-4", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Middle
   290  		helper.addTrieAccount("acc-6", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // End
   291  	}
   292  
   293  	// Wrong accounts
   294  	{
   295  		helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   296  		helper.addSnapAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")})
   297  
   298  		helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   299  		helper.addSnapAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
   300  	}
   301  
   302  	// Extra accounts, only in the snap
   303  	{
   304  		helper.addSnapAccount("acc-0", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})              // before the beginning
   305  		helper.addSnapAccount("acc-5", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: common.Hex2Bytes("0x1234")})  // Middle
   306  		helper.addSnapAccount("acc-7", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // after the end
   307  	}
   308  
   309  	root, dl := helper.CommitAndGenerate()
   310  	t.Logf("Root: %#x\n", root) // Root = 0x825891472281463511e7ebcc7f109e4f9200c20fa384754e11fd605cd98464e8
   311  
   312  	select {
   313  	case <-dl.generator.done:
   314  		// Snapshot generation succeeded
   315  
   316  	case <-time.After(3 * time.Second):
   317  		t.Errorf("Snapshot generation failed")
   318  	}
   319  	// TODO(rjl493456442) enable the snapshot tests
   320  	// checkSnapRoot(t, snap, root)
   321  
   322  	// Signal abortion to the generator and wait for it to tear down
   323  	dl.generator.stop()
   324  }
   325  
   326  func TestGenerateCorruptAccountTrie(t *testing.T) {
   327  	helper := newGenTester()
   328  	helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074
   329  	helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
   330  	helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
   331  
   332  	root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
   333  
   334  	// Delete an account trie node and ensure the generator chokes
   335  	path := []byte{0xc}
   336  	if !rawdb.HasAccountTrieNode(helper.diskdb, path) {
   337  		t.Logf("Invalid node path to delete, %v", path)
   338  	}
   339  	rawdb.DeleteAccountTrieNode(helper.diskdb, path)
   340  	helper.db.tree.bottom().resetCache()
   341  
   342  	dl := generateSnapshot(helper.db, root, false)
   343  	select {
   344  	case <-dl.generator.done:
   345  		// Snapshot generation succeeded
   346  		t.Errorf("Snapshot generated against corrupt account trie")
   347  
   348  	case <-time.After(time.Second):
   349  		// Not generated fast enough, hopefully blocked inside on missing trie node fail
   350  	}
   351  	// Signal abortion to the generator and wait for it to tear down
   352  	dl.generator.stop()
   353  }
   354  
   355  func TestGenerateMissingStorageTrie(t *testing.T) {
   356  	var (
   357  		acc1   = hashData([]byte("acc-1"))
   358  		acc3   = hashData([]byte("acc-3"))
   359  		helper = newGenTester()
   360  	)
   361  	stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)                         // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
   362  	helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})              // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
   363  	helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
   364  	stRoot = helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   365  	helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
   366  
   367  	root := helper.Commit()
   368  
   369  	// Delete storage trie root of account one and three.
   370  	rawdb.DeleteStorageTrieNode(helper.diskdb, acc1, nil)
   371  	rawdb.DeleteStorageTrieNode(helper.diskdb, acc3, nil)
   372  	helper.db.tree.bottom().resetCache()
   373  
   374  	dl := generateSnapshot(helper.db, root, false)
   375  	select {
   376  	case <-dl.generator.done:
   377  		// Snapshot generation succeeded
   378  		t.Errorf("Snapshot generated against corrupt storage trie")
   379  
   380  	case <-time.After(time.Second):
   381  		// Not generated fast enough, hopefully blocked inside on missing trie node fail
   382  	}
   383  	// Signal abortion to the generator and wait for it to tear down
   384  	dl.generator.stop()
   385  }
   386  
   387  func TestGenerateCorruptStorageTrie(t *testing.T) {
   388  	helper := newGenTester()
   389  
   390  	stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)                         // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
   391  	helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})              // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
   392  	helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
   393  	stRoot = helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   394  	helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
   395  
   396  	root := helper.Commit()
   397  
   398  	// Delete a node in the storage trie.
   399  	path := []byte{0x4}
   400  	if !rawdb.HasStorageTrieNode(helper.diskdb, hashData([]byte("acc-1")), path) {
   401  		t.Logf("Invalid node path to delete, %v", path)
   402  	}
   403  	rawdb.DeleteStorageTrieNode(helper.diskdb, hashData([]byte("acc-1")), []byte{0x4})
   404  
   405  	if !rawdb.HasStorageTrieNode(helper.diskdb, hashData([]byte("acc-3")), path) {
   406  		t.Logf("Invalid node path to delete, %v", path)
   407  	}
   408  	rawdb.DeleteStorageTrieNode(helper.diskdb, hashData([]byte("acc-3")), []byte{0x4})
   409  
   410  	helper.db.tree.bottom().resetCache()
   411  
   412  	dl := generateSnapshot(helper.db, root, false)
   413  	select {
   414  	case <-dl.generator.done:
   415  		// Snapshot generation succeeded
   416  		t.Errorf("Snapshot generated against corrupt storage trie")
   417  
   418  	case <-time.After(time.Second):
   419  		// Not generated fast enough, hopefully blocked inside on missing trie node fail
   420  	}
   421  	// Signal abortion to the generator and wait for it to tear down
   422  	dl.generator.stop()
   423  }
   424  
   425  func TestGenerateWithExtraAccounts(t *testing.T) {
   426  	helper := newGenTester()
   427  
   428  	// Account one in the trie
   429  	stRoot := helper.makeStorageTrie("acc-1",
   430  		[]string{"key-1", "key-2", "key-3", "key-4", "key-5"},
   431  		[]string{"val-1", "val-2", "val-3", "val-4", "val-5"},
   432  		true,
   433  	)
   434  	acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
   435  	val, _ := rlp.EncodeToBytes(acc)
   436  	helper.acctTrie.MustUpdate(hashData([]byte("acc-1")).Bytes(), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
   437  
   438  	// Identical in the snap
   439  	key := hashData([]byte("acc-1"))
   440  	rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
   441  	rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-1")), []byte("val-1"))
   442  	rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-2")), []byte("val-2"))
   443  	rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-3")), []byte("val-3"))
   444  	rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-4")), []byte("val-4"))
   445  	rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-5")), []byte("val-5"))
   446  
   447  	// Account two exists only in the snapshot
   448  	stRoot = helper.makeStorageTrie("acc-2",
   449  		[]string{"key-1", "key-2", "key-3", "key-4", "key-5"},
   450  		[]string{"val-1", "val-2", "val-3", "val-4", "val-5"},
   451  		true,
   452  	)
   453  	acc = &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
   454  	val, _ = rlp.EncodeToBytes(acc)
   455  	key = hashData([]byte("acc-2"))
   456  	rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
   457  	rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-1")), []byte("b-val-1"))
   458  	rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-2")), []byte("b-val-2"))
   459  	rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-3")), []byte("b-val-3"))
   460  
   461  	root := helper.Commit()
   462  
   463  	// To verify the test: If we now inspect the snap db, there should exist extraneous storage items
   464  	if data := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data == nil {
   465  		t.Fatalf("expected snap storage to exist")
   466  	}
   467  	dl := generateSnapshot(helper.db, root, false)
   468  	select {
   469  	case <-dl.generator.done:
   470  		// Snapshot generation succeeded
   471  
   472  	case <-time.After(3 * time.Second):
   473  		t.Errorf("Snapshot generation failed")
   474  	}
   475  	// TODO(rjl493456442) enable the snapshot tests
   476  	// checkSnapRoot(t, snap, root)
   477  
   478  	// Signal abortion to the generator and wait for it to tear down
   479  	dl.generator.stop()
   480  
   481  	// If we now inspect the snap db, there should exist no extraneous storage items
   482  	if data := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil {
   483  		t.Fatalf("expected slot to be removed, got %v", string(data))
   484  	}
   485  }
   486  
   487  func TestGenerateWithManyExtraAccounts(t *testing.T) {
   488  	helper := newGenTester()
   489  
   490  	// Account one in the trie
   491  	stRoot := helper.makeStorageTrie("acc-1",
   492  		[]string{"key-1", "key-2", "key-3"},
   493  		[]string{"val-1", "val-2", "val-3"},
   494  		true,
   495  	)
   496  	acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
   497  	val, _ := rlp.EncodeToBytes(acc)
   498  	helper.acctTrie.MustUpdate(hashData([]byte("acc-1")).Bytes(), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
   499  
   500  	// Identical in the snap
   501  	key := hashData([]byte("acc-1"))
   502  	rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
   503  	rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-1")), []byte("val-1"))
   504  	rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-2")), []byte("val-2"))
   505  	rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-3")), []byte("val-3"))
   506  
   507  	// 100 accounts exist only in snapshot
   508  	for i := 0; i < 1000; i++ {
   509  		acc := &types.StateAccount{Balance: uint256.NewInt(uint64(i)), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
   510  		val, _ := rlp.EncodeToBytes(acc)
   511  		key := hashData([]byte(fmt.Sprintf("acc-%d", i)))
   512  		rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
   513  	}
   514  
   515  	_, dl := helper.CommitAndGenerate()
   516  	select {
   517  	case <-dl.generator.done:
   518  		// Snapshot generation succeeded
   519  
   520  	case <-time.After(3 * time.Second):
   521  		t.Errorf("Snapshot generation failed")
   522  	}
   523  	// TODO(rjl493456442) enable the snapshot tests
   524  	// checkSnapRoot(t, snap, root)
   525  
   526  	// Signal abortion to the generator and wait for it to tear down
   527  	dl.generator.stop()
   528  }
   529  
   530  func TestGenerateWithExtraBeforeAndAfter(t *testing.T) {
   531  	helper := newGenTester()
   532  
   533  	acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
   534  	val, _ := rlp.EncodeToBytes(acc)
   535  
   536  	acctHashA := hashData([]byte("acc-1"))
   537  	acctHashB := hashData([]byte("acc-2"))
   538  
   539  	helper.acctTrie.MustUpdate(acctHashA.Bytes(), val)
   540  	helper.acctTrie.MustUpdate(acctHashB.Bytes(), val)
   541  
   542  	rawdb.WriteAccountSnapshot(helper.diskdb, acctHashA, val)
   543  	rawdb.WriteAccountSnapshot(helper.diskdb, acctHashB, val)
   544  
   545  	for i := 0; i < 16; i++ {
   546  		rawdb.WriteAccountSnapshot(helper.diskdb, common.Hash{byte(i)}, val)
   547  	}
   548  	_, dl := helper.CommitAndGenerate()
   549  	select {
   550  	case <-dl.generator.done:
   551  		// Snapshot generation succeeded
   552  
   553  	case <-time.After(3 * time.Second):
   554  		t.Errorf("Snapshot generation failed")
   555  	}
   556  	// TODO(rjl493456442) enable the snapshot tests
   557  	// checkSnapRoot(t, snap, root)
   558  
   559  	// Signal abortion to the generator and wait for it to tear down
   560  	dl.generator.stop()
   561  }
   562  
   563  func TestGenerateWithMalformedStateData(t *testing.T) {
   564  	helper := newGenTester()
   565  
   566  	acctHash := hashData([]byte("acc"))
   567  	acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
   568  	val, _ := rlp.EncodeToBytes(acc)
   569  	helper.acctTrie.MustUpdate(acctHash.Bytes(), val)
   570  
   571  	junk := make([]byte, 100)
   572  	copy(junk, []byte{0xde, 0xad})
   573  	rawdb.WriteAccountSnapshot(helper.diskdb, acctHash, junk)
   574  	for i := 0; i < 16; i++ {
   575  		rawdb.WriteAccountSnapshot(helper.diskdb, common.Hash{byte(i)}, junk)
   576  	}
   577  
   578  	_, dl := helper.CommitAndGenerate()
   579  	select {
   580  	case <-dl.generator.done:
   581  		// Snapshot generation succeeded
   582  
   583  	case <-time.After(3 * time.Second):
   584  		t.Errorf("Snapshot generation failed")
   585  	}
   586  	// TODO(rjl493456442) enable the snapshot tests
   587  	// checkSnapRoot(t, snap, root)
   588  
   589  	// Signal abortion to the generator and wait for it to tear down
   590  	dl.generator.stop()
   591  }
   592  
   593  func TestGenerateFromEmptySnap(t *testing.T) {
   594  	helper := newGenTester()
   595  
   596  	for i := 0; i < 400; i++ {
   597  		stRoot := helper.makeStorageTrie(fmt.Sprintf("acc-%d", i), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   598  		helper.addTrieAccount(fmt.Sprintf("acc-%d", i), &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   599  	}
   600  	root, snap := helper.CommitAndGenerate()
   601  	t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4
   602  
   603  	select {
   604  	case <-snap.generator.done:
   605  		// Snapshot generation succeeded
   606  
   607  	case <-time.After(3 * time.Second):
   608  		t.Errorf("Snapshot generation failed")
   609  	}
   610  	// TODO(rjl493456442) enable the snapshot tests
   611  	// checkSnapRoot(t, snap, root)
   612  
   613  	// Signal abortion to the generator and wait for it to tear down
   614  	snap.generator.stop()
   615  }
   616  
   617  func TestGenerateWithIncompleteStorage(t *testing.T) {
   618  	helper := newGenTester()
   619  	stKeys := []string{"1", "2", "3", "4", "5", "6", "7", "8"}
   620  	stVals := []string{"v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"}
   621  
   622  	// We add 8 accounts, each one is missing exactly one of the storage slots. This means
   623  	// we don't have to order the keys and figure out exactly which hash-key winds up
   624  	// on the sensitive spots at the boundaries
   625  	for i := 0; i < 8; i++ {
   626  		accKey := fmt.Sprintf("acc-%d", i)
   627  		stRoot := helper.makeStorageTrie(accKey, stKeys, stVals, true)
   628  		helper.addAccount(accKey, &types.StateAccount{Balance: uint256.NewInt(uint64(i)), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   629  		var moddedKeys []string
   630  		var moddedVals []string
   631  		for ii := 0; ii < 8; ii++ {
   632  			if ii != i {
   633  				moddedKeys = append(moddedKeys, stKeys[ii])
   634  				moddedVals = append(moddedVals, stVals[ii])
   635  			}
   636  		}
   637  		helper.addSnapStorage(accKey, moddedKeys, moddedVals)
   638  	}
   639  	root, dl := helper.CommitAndGenerate()
   640  	t.Logf("Root: %#x\n", root) // Root: 0xca73f6f05ba4ca3024ef340ef3dfca8fdabc1b677ff13f5a9571fd49c16e67ff
   641  
   642  	select {
   643  	case <-dl.generator.done:
   644  		// Snapshot generation succeeded
   645  
   646  	case <-time.After(3 * time.Second):
   647  		t.Errorf("Snapshot generation failed")
   648  	}
   649  	// TODO(rjl493456442) enable the snapshot tests
   650  	// checkSnapRoot(t, snap, root)
   651  
   652  	// Signal abortion to the generator and wait for it to tear down
   653  	dl.generator.stop()
   654  }
   655  
   656  func incKey(key []byte) []byte {
   657  	for i := len(key) - 1; i >= 0; i-- {
   658  		key[i]++
   659  		if key[i] != 0x0 {
   660  			break
   661  		}
   662  	}
   663  	return key
   664  }
   665  
   666  func decKey(key []byte) []byte {
   667  	for i := len(key) - 1; i >= 0; i-- {
   668  		key[i]--
   669  		if key[i] != 0xff {
   670  			break
   671  		}
   672  	}
   673  	return key
   674  }
   675  
   676  func populateDangling(disk ethdb.KeyValueStore) {
   677  	populate := func(accountHash common.Hash, keys []string, vals []string) {
   678  		for i, key := range keys {
   679  			rawdb.WriteStorageSnapshot(disk, accountHash, hashData([]byte(key)), []byte(vals[i]))
   680  		}
   681  	}
   682  	// Dangling storages of the "first" account
   683  	populate(common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   684  
   685  	// Dangling storages of the "last" account
   686  	populate(common.HexToHash("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   687  
   688  	// Dangling storages around the account 1
   689  	hash := decKey(hashData([]byte("acc-1")).Bytes())
   690  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   691  	hash = incKey(hashData([]byte("acc-1")).Bytes())
   692  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   693  
   694  	// Dangling storages around the account 2
   695  	hash = decKey(hashData([]byte("acc-2")).Bytes())
   696  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   697  	hash = incKey(hashData([]byte("acc-2")).Bytes())
   698  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   699  
   700  	// Dangling storages around the account 3
   701  	hash = decKey(hashData([]byte("acc-3")).Bytes())
   702  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   703  	hash = incKey(hashData([]byte("acc-3")).Bytes())
   704  	populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   705  
   706  	// Dangling storages of the random account
   707  	populate(testrand.Hash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   708  	populate(testrand.Hash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   709  	populate(testrand.Hash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   710  }
   711  
   712  func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) {
   713  	var helper = newGenTester()
   714  
   715  	stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   716  	helper.addAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   717  	helper.addAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
   718  
   719  	helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   720  	helper.addAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   721  
   722  	helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   723  	helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
   724  
   725  	populateDangling(helper.diskdb)
   726  
   727  	_, dl := helper.CommitAndGenerate()
   728  	select {
   729  	case <-dl.generator.done:
   730  		// Snapshot generation succeeded
   731  
   732  	case <-time.After(3 * time.Second):
   733  		t.Errorf("Snapshot generation failed")
   734  	}
   735  	// TODO(rjl493456442) enable the snapshot tests
   736  	// checkSnapRoot(t, snap, root)
   737  
   738  	// Signal abortion to the generator and wait for it to tear down
   739  	dl.generator.stop()
   740  }
   741  
   742  func TestGenerateBrokenSnapshotWithDanglingStorage(t *testing.T) {
   743  	var helper = newGenTester()
   744  
   745  	stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   746  	helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   747  	helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
   748  
   749  	helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
   750  	helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
   751  
   752  	populateDangling(helper.diskdb)
   753  
   754  	_, dl := helper.CommitAndGenerate()
   755  	select {
   756  	case <-dl.generator.done:
   757  		// Snapshot generation succeeded
   758  
   759  	case <-time.After(3 * time.Second):
   760  		t.Errorf("Snapshot generation failed")
   761  	}
   762  	// TODO(rjl493456442) enable the snapshot tests
   763  	// checkSnapRoot(t, snap, root)
   764  
   765  	// Signal abortion to the generator and wait for it to tear down
   766  	dl.generator.stop()
   767  }