github.com/ethereum/go-ethereum@v1.16.1/core/state/trie_prefetcher_test.go (about)

     1  // Copyright 2021 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 state
    18  
    19  import (
    20  	"math/big"
    21  	"testing"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/core/rawdb"
    25  	"github.com/ethereum/go-ethereum/core/tracing"
    26  	"github.com/ethereum/go-ethereum/core/types"
    27  	"github.com/ethereum/go-ethereum/crypto"
    28  	"github.com/ethereum/go-ethereum/internal/testrand"
    29  	"github.com/ethereum/go-ethereum/triedb"
    30  	"github.com/holiman/uint256"
    31  )
    32  
    33  func filledStateDB() *StateDB {
    34  	state, _ := New(types.EmptyRootHash, NewDatabaseForTesting())
    35  
    36  	// Create an account and check if the retrieved balance is correct
    37  	addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
    38  	skey := common.HexToHash("aaa")
    39  	sval := common.HexToHash("bbb")
    40  
    41  	state.SetBalance(addr, uint256.NewInt(42), tracing.BalanceChangeUnspecified) // Change the account trie
    42  	state.SetCode(addr, []byte("hello"))                                         // Change an external metadata
    43  	state.SetState(addr, skey, sval)                                             // Change the storage trie
    44  	for i := 0; i < 100; i++ {
    45  		sk := common.BigToHash(big.NewInt(int64(i)))
    46  		state.SetState(addr, sk, sk) // Change the storage trie
    47  	}
    48  	return state
    49  }
    50  
    51  func TestUseAfterTerminate(t *testing.T) {
    52  	db := filledStateDB()
    53  	prefetcher := newTriePrefetcher(db.db, db.originalRoot, "", true)
    54  	skey := common.HexToHash("aaa")
    55  
    56  	if err := prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, nil, []common.Hash{skey}, false); err != nil {
    57  		t.Errorf("Prefetch failed before terminate: %v", err)
    58  	}
    59  	prefetcher.terminate(false)
    60  
    61  	if err := prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, nil, []common.Hash{skey}, false); err == nil {
    62  		t.Errorf("Prefetch succeeded after terminate: %v", err)
    63  	}
    64  	if tr := prefetcher.trie(common.Hash{}, db.originalRoot); tr == nil {
    65  		t.Errorf("Prefetcher returned nil trie after terminate")
    66  	}
    67  }
    68  
    69  func TestVerklePrefetcher(t *testing.T) {
    70  	disk := rawdb.NewMemoryDatabase()
    71  	db := triedb.NewDatabase(disk, triedb.VerkleDefaults)
    72  	sdb := NewDatabase(db, nil)
    73  
    74  	state, err := New(types.EmptyRootHash, sdb)
    75  	if err != nil {
    76  		t.Fatalf("failed to initialize state: %v", err)
    77  	}
    78  	// Create an account and check if the retrieved balance is correct
    79  	addr := testrand.Address()
    80  	skey := testrand.Hash()
    81  	sval := testrand.Hash()
    82  
    83  	state.SetBalance(addr, uint256.NewInt(42), tracing.BalanceChangeUnspecified) // Change the account trie
    84  	state.SetCode(addr, []byte("hello"))                                         // Change an external metadata
    85  	state.SetState(addr, skey, sval)                                             // Change the storage trie
    86  	root, _ := state.Commit(0, true, false)
    87  
    88  	state, _ = New(root, sdb)
    89  	sRoot := state.GetStorageRoot(addr)
    90  	fetcher := newTriePrefetcher(sdb, root, "", false)
    91  
    92  	// Read account
    93  	fetcher.prefetch(common.Hash{}, root, common.Address{}, []common.Address{addr}, nil, false)
    94  
    95  	// Read storage slot
    96  	fetcher.prefetch(crypto.Keccak256Hash(addr.Bytes()), sRoot, addr, nil, []common.Hash{skey}, false)
    97  
    98  	fetcher.terminate(false)
    99  	accountTrie := fetcher.trie(common.Hash{}, root)
   100  	storageTrie := fetcher.trie(crypto.Keccak256Hash(addr.Bytes()), sRoot)
   101  
   102  	rootA := accountTrie.Hash()
   103  	rootB := storageTrie.Hash()
   104  	if rootA != rootB {
   105  		t.Fatal("Two different tries are retrieved")
   106  	}
   107  }