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