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