github.com/jimmyx0x/go-ethereum@v1.10.28/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 "encoding/json" 21 "math/big" 22 "reflect" 23 "testing" 24 25 "github.com/davecgh/go-spew/spew" 26 "github.com/ethereum/go-ethereum/common" 27 "github.com/ethereum/go-ethereum/consensus/ethash" 28 "github.com/ethereum/go-ethereum/core/rawdb" 29 "github.com/ethereum/go-ethereum/core/vm" 30 "github.com/ethereum/go-ethereum/ethdb" 31 "github.com/ethereum/go-ethereum/params" 32 "github.com/ethereum/go-ethereum/trie" 33 ) 34 35 func TestInvalidCliqueConfig(t *testing.T) { 36 block := DefaultGoerliGenesisBlock() 37 block.ExtraData = []byte{} 38 db := rawdb.NewMemoryDatabase() 39 if _, err := block.Commit(db, trie.NewDatabase(db)); err == nil { 40 t.Fatal("Expected error on invalid clique config") 41 } 42 } 43 44 func TestSetupGenesis(t *testing.T) { 45 var ( 46 customghash = common.HexToHash("0x89c99d90b79719238d2645c7642f2c9295246e80775b38cfd162b696817fbd50") 47 customg = Genesis{ 48 Config: ¶ms.ChainConfig{HomesteadBlock: big.NewInt(3)}, 49 Alloc: GenesisAlloc{ 50 {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}}, 51 }, 52 } 53 oldcustomg = customg 54 ) 55 oldcustomg.Config = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(2)} 56 tests := []struct { 57 name string 58 fn func(ethdb.Database) (*params.ChainConfig, common.Hash, error) 59 wantConfig *params.ChainConfig 60 wantHash common.Hash 61 wantErr error 62 }{ 63 { 64 name: "genesis without ChainConfig", 65 fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { 66 return SetupGenesisBlock(db, trie.NewDatabase(db), new(Genesis)) 67 }, 68 wantErr: errGenesisNoConfig, 69 wantConfig: params.AllEthashProtocolChanges, 70 }, 71 { 72 name: "no block in DB, genesis == nil", 73 fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { 74 return SetupGenesisBlock(db, trie.NewDatabase(db), nil) 75 }, 76 wantHash: params.MainnetGenesisHash, 77 wantConfig: params.MainnetChainConfig, 78 }, 79 { 80 name: "mainnet block in DB, genesis == nil", 81 fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { 82 DefaultGenesisBlock().MustCommit(db) 83 return SetupGenesisBlock(db, trie.NewDatabase(db), nil) 84 }, 85 wantHash: params.MainnetGenesisHash, 86 wantConfig: params.MainnetChainConfig, 87 }, 88 { 89 name: "custom block in DB, genesis == nil", 90 fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { 91 customg.MustCommit(db) 92 return SetupGenesisBlock(db, trie.NewDatabase(db), nil) 93 }, 94 wantHash: customghash, 95 wantConfig: customg.Config, 96 }, 97 { 98 name: "custom block in DB, genesis == ropsten", 99 fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { 100 customg.MustCommit(db) 101 return SetupGenesisBlock(db, trie.NewDatabase(db), DefaultRopstenGenesisBlock()) 102 }, 103 wantErr: &GenesisMismatchError{Stored: customghash, New: params.RopstenGenesisHash}, 104 wantHash: params.RopstenGenesisHash, 105 wantConfig: params.RopstenChainConfig, 106 }, 107 { 108 name: "compatible config in DB", 109 fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { 110 oldcustomg.MustCommit(db) 111 return SetupGenesisBlock(db, trie.NewDatabase(db), &customg) 112 }, 113 wantHash: customghash, 114 wantConfig: customg.Config, 115 }, 116 { 117 name: "incompatible config in DB", 118 fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { 119 // Commit the 'old' genesis block with Homestead transition at #2. 120 // Advance to block #4, past the homestead transition block of customg. 121 genesis := oldcustomg.MustCommit(db) 122 123 bc, _ := NewBlockChain(db, nil, &oldcustomg, nil, ethash.NewFullFaker(), vm.Config{}, nil, nil) 124 defer bc.Stop() 125 126 blocks, _ := GenerateChain(oldcustomg.Config, genesis, ethash.NewFaker(), db, 4, nil) 127 bc.InsertChain(blocks) 128 129 // This should return a compatibility error. 130 return SetupGenesisBlock(db, trie.NewDatabase(db), &customg) 131 }, 132 wantHash: customghash, 133 wantConfig: customg.Config, 134 wantErr: ¶ms.ConfigCompatError{ 135 What: "Homestead fork block", 136 StoredBlock: big.NewInt(2), 137 NewBlock: big.NewInt(3), 138 RewindToBlock: 1, 139 }, 140 }, 141 } 142 143 for _, test := range tests { 144 db := rawdb.NewMemoryDatabase() 145 config, hash, err := test.fn(db) 146 // Check the return values. 147 if !reflect.DeepEqual(err, test.wantErr) { 148 spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true} 149 t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(err), spew.NewFormatter(test.wantErr)) 150 } 151 if !reflect.DeepEqual(config, test.wantConfig) { 152 t.Errorf("%s:\nreturned %v\nwant %v", test.name, config, test.wantConfig) 153 } 154 if hash != test.wantHash { 155 t.Errorf("%s: returned hash %s, want %s", test.name, hash.Hex(), test.wantHash.Hex()) 156 } else if err == nil { 157 // Check database content. 158 stored := rawdb.ReadBlock(db, test.wantHash, 0) 159 if stored.Hash() != test.wantHash { 160 t.Errorf("%s: block in DB has hash %s, want %s", test.name, stored.Hash(), test.wantHash) 161 } 162 } 163 } 164 } 165 166 // TestGenesisHashes checks the congruity of default genesis data to 167 // corresponding hardcoded genesis hash values. 168 func TestGenesisHashes(t *testing.T) { 169 for i, c := range []struct { 170 genesis *Genesis 171 want common.Hash 172 }{ 173 {DefaultGenesisBlock(), params.MainnetGenesisHash}, 174 {DefaultGoerliGenesisBlock(), params.GoerliGenesisHash}, 175 {DefaultRopstenGenesisBlock(), params.RopstenGenesisHash}, 176 {DefaultRinkebyGenesisBlock(), params.RinkebyGenesisHash}, 177 {DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash}, 178 } { 179 // Test via MustCommit 180 if have := c.genesis.MustCommit(rawdb.NewMemoryDatabase()).Hash(); have != c.want { 181 t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex()) 182 } 183 // Test via ToBlock 184 if have := c.genesis.ToBlock().Hash(); have != c.want { 185 t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex()) 186 } 187 } 188 } 189 190 func TestGenesis_Commit(t *testing.T) { 191 genesis := &Genesis{ 192 BaseFee: big.NewInt(params.InitialBaseFee), 193 Config: params.TestChainConfig, 194 // difficulty is nil 195 } 196 197 db := rawdb.NewMemoryDatabase() 198 genesisBlock := genesis.MustCommit(db) 199 200 if genesis.Difficulty != nil { 201 t.Fatalf("assumption wrong") 202 } 203 204 // This value should have been set as default in the ToBlock method. 205 if genesisBlock.Difficulty().Cmp(params.GenesisDifficulty) != 0 { 206 t.Errorf("assumption wrong: want: %d, got: %v", params.GenesisDifficulty, genesisBlock.Difficulty()) 207 } 208 209 // Expect the stored total difficulty to be the difficulty of the genesis block. 210 stored := rawdb.ReadTd(db, genesisBlock.Hash(), genesisBlock.NumberU64()) 211 212 if stored.Cmp(genesisBlock.Difficulty()) != 0 { 213 t.Errorf("inequal difficulty; stored: %v, genesisBlock: %v", stored, genesisBlock.Difficulty()) 214 } 215 } 216 217 func TestReadWriteGenesisAlloc(t *testing.T) { 218 var ( 219 db = rawdb.NewMemoryDatabase() 220 alloc = &GenesisAlloc{ 221 {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}}, 222 {2}: {Balance: big.NewInt(2), Storage: map[common.Hash]common.Hash{{2}: {2}}}, 223 } 224 hash, _ = alloc.deriveHash() 225 ) 226 blob, _ := json.Marshal(alloc) 227 rawdb.WriteGenesisStateSpec(db, hash, blob) 228 229 var reload GenesisAlloc 230 err := reload.UnmarshalJSON(rawdb.ReadGenesisStateSpec(db, hash)) 231 if err != nil { 232 t.Fatalf("Failed to load genesis state %v", err) 233 } 234 if len(reload) != len(*alloc) { 235 t.Fatal("Unexpected genesis allocation") 236 } 237 for addr, account := range reload { 238 want, ok := (*alloc)[addr] 239 if !ok { 240 t.Fatal("Account is not found") 241 } 242 if !reflect.DeepEqual(want, account) { 243 t.Fatal("Unexpected account") 244 } 245 } 246 }