github.com/ethereum/go-ethereum@v1.16.1/trie/verkle_test.go (about) 1 // Copyright 2023 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 trie 18 19 import ( 20 "bytes" 21 "reflect" 22 "testing" 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/trie/utils" 29 "github.com/holiman/uint256" 30 ) 31 32 var ( 33 accounts = map[common.Address]*types.StateAccount{ 34 {1}: { 35 Nonce: 100, 36 Balance: uint256.NewInt(100), 37 CodeHash: common.Hash{0x1}.Bytes(), 38 }, 39 {2}: { 40 Nonce: 200, 41 Balance: uint256.NewInt(200), 42 CodeHash: common.Hash{0x2}.Bytes(), 43 }, 44 } 45 storages = map[common.Address]map[common.Hash][]byte{ 46 {1}: { 47 common.Hash{10}: []byte{10}, 48 common.Hash{11}: []byte{11}, 49 common.MaxHash: []byte{0xff}, 50 }, 51 {2}: { 52 common.Hash{20}: []byte{20}, 53 common.Hash{21}: []byte{21}, 54 common.MaxHash: []byte{0xff}, 55 }, 56 } 57 ) 58 59 func TestVerkleTreeReadWrite(t *testing.T) { 60 db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.PathScheme) 61 tr, _ := NewVerkleTrie(types.EmptyVerkleHash, db, utils.NewPointCache(100)) 62 63 for addr, acct := range accounts { 64 if err := tr.UpdateAccount(addr, acct, 0); err != nil { 65 t.Fatalf("Failed to update account, %v", err) 66 } 67 for key, val := range storages[addr] { 68 if err := tr.UpdateStorage(addr, key.Bytes(), val); err != nil { 69 t.Fatalf("Failed to update account, %v", err) 70 } 71 } 72 } 73 74 for addr, acct := range accounts { 75 stored, err := tr.GetAccount(addr) 76 if err != nil { 77 t.Fatalf("Failed to get account, %v", err) 78 } 79 if !reflect.DeepEqual(stored, acct) { 80 t.Fatal("account is not matched") 81 } 82 for key, val := range storages[addr] { 83 stored, err := tr.GetStorage(addr, key.Bytes()) 84 if err != nil { 85 t.Fatalf("Failed to get storage, %v", err) 86 } 87 if !bytes.Equal(stored, val) { 88 t.Fatal("storage is not matched") 89 } 90 } 91 } 92 } 93 94 func TestVerkleRollBack(t *testing.T) { 95 db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.PathScheme) 96 tr, _ := NewVerkleTrie(types.EmptyVerkleHash, db, utils.NewPointCache(100)) 97 98 for addr, acct := range accounts { 99 // create more than 128 chunks of code 100 code := make([]byte, 129*32) 101 for i := 0; i < len(code); i += 2 { 102 code[i] = 0x60 103 code[i+1] = byte(i % 256) 104 } 105 if err := tr.UpdateAccount(addr, acct, len(code)); err != nil { 106 t.Fatalf("Failed to update account, %v", err) 107 } 108 for key, val := range storages[addr] { 109 if err := tr.UpdateStorage(addr, key.Bytes(), val); err != nil { 110 t.Fatalf("Failed to update account, %v", err) 111 } 112 } 113 hash := crypto.Keccak256Hash(code) 114 if err := tr.UpdateContractCode(addr, hash, code); err != nil { 115 t.Fatalf("Failed to update contract, %v", err) 116 } 117 } 118 119 // Check that things were created 120 for addr, acct := range accounts { 121 stored, err := tr.GetAccount(addr) 122 if err != nil { 123 t.Fatalf("Failed to get account, %v", err) 124 } 125 if !reflect.DeepEqual(stored, acct) { 126 t.Fatal("account is not matched") 127 } 128 for key, val := range storages[addr] { 129 stored, err := tr.GetStorage(addr, key.Bytes()) 130 if err != nil { 131 t.Fatalf("Failed to get storage, %v", err) 132 } 133 if !bytes.Equal(stored, val) { 134 t.Fatal("storage is not matched") 135 } 136 } 137 } 138 139 // ensure there is some code in the 2nd group of the 1st account 140 keyOf2ndGroup := utils.CodeChunkKeyWithEvaluatedAddress(tr.cache.Get(common.Address{1}.Bytes()), uint256.NewInt(128)) 141 chunk, err := tr.root.Get(keyOf2ndGroup, nil) 142 if err != nil { 143 t.Fatalf("Failed to get account, %v", err) 144 } 145 if len(chunk) == 0 { 146 t.Fatal("account was not created ") 147 } 148 149 // Rollback first account and check that it is gone 150 addr1 := common.Address{1} 151 err = tr.RollBackAccount(addr1) 152 if err != nil { 153 t.Fatalf("error rolling back address 1: %v", err) 154 } 155 156 // ensure the account is gone 157 stored, err := tr.GetAccount(addr1) 158 if err != nil { 159 t.Fatalf("Failed to get account, %v", err) 160 } 161 if stored != nil { 162 t.Fatal("account was not deleted") 163 } 164 165 // ensure that the last code chunk is also gone from the tree 166 chunk, err = tr.root.Get(keyOf2ndGroup, nil) 167 if err != nil { 168 t.Fatalf("Failed to get account, %v", err) 169 } 170 if len(chunk) != 0 { 171 t.Fatal("account was not deleted") 172 } 173 }