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 }