github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/core/genesis_test.go (about) 1 // Copyright 2017 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 core 18 19 import ( 20 "bytes" 21 "encoding/json" 22 "math/big" 23 "reflect" 24 "testing" 25 26 "github.com/davecgh/go-spew/spew" 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/consensus/ethash" 29 "github.com/ethereum/go-ethereum/core/rawdb" 30 "github.com/ethereum/go-ethereum/core/types" 31 "github.com/ethereum/go-ethereum/core/vm" 32 "github.com/ethereum/go-ethereum/ethdb" 33 "github.com/ethereum/go-ethereum/params" 34 "github.com/ethereum/go-ethereum/triedb" 35 "github.com/ethereum/go-ethereum/triedb/pathdb" 36 ) 37 38 func TestInvalidCliqueConfig(t *testing.T) { 39 block := DefaultGoerliGenesisBlock() 40 block.ExtraData = []byte{} 41 db := rawdb.NewMemoryDatabase() 42 if _, err := block.Commit(db, triedb.NewDatabase(db, nil)); err == nil { 43 t.Fatal("Expected error on invalid clique config") 44 } 45 } 46 47 func TestSetupGenesis(t *testing.T) { 48 testSetupGenesis(t, rawdb.HashScheme) 49 testSetupGenesis(t, rawdb.PathScheme) 50 } 51 52 func testSetupGenesis(t *testing.T, scheme string) { 53 var ( 54 customghash = common.HexToHash("0x89c99d90b79719238d2645c7642f2c9295246e80775b38cfd162b696817fbd50") 55 customg = Genesis{ 56 Config: ¶ms.ChainConfig{HomesteadBlock: big.NewInt(3)}, 57 Alloc: types.GenesisAlloc{ 58 {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}}, 59 }, 60 } 61 oldcustomg = customg 62 ) 63 oldcustomg.Config = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(2)} 64 65 tests := []struct { 66 name string 67 fn func(ethdb.Database) (*params.ChainConfig, common.Hash, error) 68 wantConfig *params.ChainConfig 69 wantHash common.Hash 70 wantErr error 71 }{ 72 { 73 name: "genesis without ChainConfig", 74 fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { 75 return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), new(Genesis)) 76 }, 77 wantErr: errGenesisNoConfig, 78 wantConfig: params.AllEthashProtocolChanges, 79 }, 80 { 81 name: "no block in DB, genesis == nil", 82 fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { 83 return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil) 84 }, 85 wantHash: params.MainnetGenesisHash, 86 wantConfig: params.MainnetChainConfig, 87 }, 88 { 89 name: "mainnet block in DB, genesis == nil", 90 fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { 91 DefaultGenesisBlock().MustCommit(db, triedb.NewDatabase(db, newDbConfig(scheme))) 92 return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil) 93 }, 94 wantHash: params.MainnetGenesisHash, 95 wantConfig: params.MainnetChainConfig, 96 }, 97 { 98 name: "custom block in DB, genesis == nil", 99 fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { 100 tdb := triedb.NewDatabase(db, newDbConfig(scheme)) 101 customg.Commit(db, tdb) 102 return SetupGenesisBlock(db, tdb, nil) 103 }, 104 wantHash: customghash, 105 wantConfig: customg.Config, 106 }, 107 { 108 name: "custom block in DB, genesis == goerli", 109 fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { 110 tdb := triedb.NewDatabase(db, newDbConfig(scheme)) 111 customg.Commit(db, tdb) 112 return SetupGenesisBlock(db, tdb, DefaultGoerliGenesisBlock()) 113 }, 114 wantErr: &GenesisMismatchError{Stored: customghash, New: params.GoerliGenesisHash}, 115 wantHash: params.GoerliGenesisHash, 116 wantConfig: params.GoerliChainConfig, 117 }, 118 { 119 name: "compatible config in DB", 120 fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { 121 tdb := triedb.NewDatabase(db, newDbConfig(scheme)) 122 oldcustomg.Commit(db, tdb) 123 return SetupGenesisBlock(db, tdb, &customg) 124 }, 125 wantHash: customghash, 126 wantConfig: customg.Config, 127 }, 128 { 129 name: "incompatible config in DB", 130 fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { 131 // Commit the 'old' genesis block with Homestead transition at #2. 132 // Advance to block #4, past the homestead transition block of customg. 133 tdb := triedb.NewDatabase(db, newDbConfig(scheme)) 134 oldcustomg.Commit(db, tdb) 135 136 bc, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), &oldcustomg, nil, ethash.NewFullFaker(), vm.Config{}, nil, nil) 137 defer bc.Stop() 138 139 _, blocks, _ := GenerateChainWithGenesis(&oldcustomg, ethash.NewFaker(), 4, nil) 140 bc.InsertChain(blocks) 141 142 // This should return a compatibility error. 143 return SetupGenesisBlock(db, tdb, &customg) 144 }, 145 wantHash: customghash, 146 wantConfig: customg.Config, 147 wantErr: ¶ms.ConfigCompatError{ 148 What: "Homestead fork block", 149 StoredBlock: big.NewInt(2), 150 NewBlock: big.NewInt(3), 151 RewindToBlock: 1, 152 }, 153 }, 154 } 155 156 for _, test := range tests { 157 db := rawdb.NewMemoryDatabase() 158 config, hash, err := test.fn(db) 159 // Check the return values. 160 if !reflect.DeepEqual(err, test.wantErr) { 161 spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true} 162 t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(err), spew.NewFormatter(test.wantErr)) 163 } 164 if !reflect.DeepEqual(config, test.wantConfig) { 165 t.Errorf("%s:\nreturned %v\nwant %v", test.name, config, test.wantConfig) 166 } 167 if hash != test.wantHash { 168 t.Errorf("%s: returned hash %s, want %s", test.name, hash.Hex(), test.wantHash.Hex()) 169 } else if err == nil { 170 // Check database content. 171 stored := rawdb.ReadBlock(db, test.wantHash, 0) 172 if stored.Hash() != test.wantHash { 173 t.Errorf("%s: block in DB has hash %s, want %s", test.name, stored.Hash(), test.wantHash) 174 } 175 } 176 } 177 } 178 179 // TestGenesisHashes checks the congruity of default genesis data to 180 // corresponding hardcoded genesis hash values. 181 func TestGenesisHashes(t *testing.T) { 182 for i, c := range []struct { 183 genesis *Genesis 184 want common.Hash 185 }{ 186 {DefaultGenesisBlock(), params.MainnetGenesisHash}, 187 {DefaultGoerliGenesisBlock(), params.GoerliGenesisHash}, 188 {DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash}, 189 } { 190 // Test via MustCommit 191 db := rawdb.NewMemoryDatabase() 192 if have := c.genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults)).Hash(); have != c.want { 193 t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex()) 194 } 195 // Test via ToBlock 196 if have := c.genesis.ToBlock().Hash(); have != c.want { 197 t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex()) 198 } 199 } 200 } 201 202 func TestGenesis_Commit(t *testing.T) { 203 genesis := &Genesis{ 204 BaseFee: big.NewInt(params.InitialBaseFee), 205 Config: params.TestChainConfig, 206 // difficulty is nil 207 } 208 209 db := rawdb.NewMemoryDatabase() 210 genesisBlock := genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults)) 211 212 if genesis.Difficulty != nil { 213 t.Fatalf("assumption wrong") 214 } 215 216 // This value should have been set as default in the ToBlock method. 217 if genesisBlock.Difficulty().Cmp(params.GenesisDifficulty) != 0 { 218 t.Errorf("assumption wrong: want: %d, got: %v", params.GenesisDifficulty, genesisBlock.Difficulty()) 219 } 220 221 // Expect the stored total difficulty to be the difficulty of the genesis block. 222 stored := rawdb.ReadTd(db, genesisBlock.Hash(), genesisBlock.NumberU64()) 223 224 if stored.Cmp(genesisBlock.Difficulty()) != 0 { 225 t.Errorf("inequal difficulty; stored: %v, genesisBlock: %v", stored, genesisBlock.Difficulty()) 226 } 227 } 228 229 func TestReadWriteGenesisAlloc(t *testing.T) { 230 var ( 231 db = rawdb.NewMemoryDatabase() 232 alloc = &types.GenesisAlloc{ 233 {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}}, 234 {2}: {Balance: big.NewInt(2), Storage: map[common.Hash]common.Hash{{2}: {2}}}, 235 } 236 hash, _ = hashAlloc(alloc, false) 237 ) 238 blob, _ := json.Marshal(alloc) 239 rawdb.WriteGenesisStateSpec(db, hash, blob) 240 241 var reload types.GenesisAlloc 242 err := reload.UnmarshalJSON(rawdb.ReadGenesisStateSpec(db, hash)) 243 if err != nil { 244 t.Fatalf("Failed to load genesis state %v", err) 245 } 246 if len(reload) != len(*alloc) { 247 t.Fatal("Unexpected genesis allocation") 248 } 249 for addr, account := range reload { 250 want, ok := (*alloc)[addr] 251 if !ok { 252 t.Fatal("Account is not found") 253 } 254 if !reflect.DeepEqual(want, account) { 255 t.Fatal("Unexpected account") 256 } 257 } 258 } 259 260 func newDbConfig(scheme string) *triedb.Config { 261 if scheme == rawdb.HashScheme { 262 return triedb.HashDefaults 263 } 264 return &triedb.Config{PathDB: pathdb.Defaults} 265 } 266 267 func TestVerkleGenesisCommit(t *testing.T) { 268 var verkleTime uint64 = 0 269 verkleConfig := ¶ms.ChainConfig{ 270 ChainID: big.NewInt(1), 271 HomesteadBlock: big.NewInt(0), 272 DAOForkBlock: nil, 273 DAOForkSupport: false, 274 EIP150Block: big.NewInt(0), 275 EIP155Block: big.NewInt(0), 276 EIP158Block: big.NewInt(0), 277 ByzantiumBlock: big.NewInt(0), 278 ConstantinopleBlock: big.NewInt(0), 279 PetersburgBlock: big.NewInt(0), 280 IstanbulBlock: big.NewInt(0), 281 MuirGlacierBlock: big.NewInt(0), 282 BerlinBlock: big.NewInt(0), 283 LondonBlock: big.NewInt(0), 284 ArrowGlacierBlock: big.NewInt(0), 285 GrayGlacierBlock: big.NewInt(0), 286 MergeNetsplitBlock: nil, 287 ShanghaiTime: &verkleTime, 288 CancunTime: &verkleTime, 289 PragueTime: &verkleTime, 290 VerkleTime: &verkleTime, 291 TerminalTotalDifficulty: big.NewInt(0), 292 TerminalTotalDifficultyPassed: true, 293 Ethash: nil, 294 Clique: nil, 295 } 296 297 genesis := &Genesis{ 298 BaseFee: big.NewInt(params.InitialBaseFee), 299 Config: verkleConfig, 300 Timestamp: verkleTime, 301 Difficulty: big.NewInt(0), 302 Alloc: types.GenesisAlloc{ 303 {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}}, 304 }, 305 } 306 307 expected := common.Hex2Bytes("14398d42be3394ff8d50681816a4b7bf8d8283306f577faba2d5bc57498de23b") 308 got := genesis.ToBlock().Root().Bytes() 309 if !bytes.Equal(got, expected) { 310 t.Fatalf("invalid genesis state root, expected %x, got %x", expected, got) 311 } 312 313 db := rawdb.NewMemoryDatabase() 314 triedb := triedb.NewDatabase(db, &triedb.Config{IsVerkle: true, PathDB: pathdb.Defaults}) 315 block := genesis.MustCommit(db, triedb) 316 if !bytes.Equal(block.Root().Bytes(), expected) { 317 t.Fatalf("invalid genesis state root, expected %x, got %x", expected, got) 318 } 319 320 // Test that the trie is verkle 321 if !triedb.IsVerkle() { 322 t.Fatalf("expected trie to be verkle") 323 } 324 325 if !rawdb.HasAccountTrieNode(db, nil) { 326 t.Fatal("could not find node") 327 } 328 }