github.com/electroneum/electroneum-sc@v0.0.0-20230105223411-3bc1d078281e/core/genesis.go (about) 1 // Copyright 2014 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/hex" 22 "encoding/json" 23 "errors" 24 "fmt" 25 "math/big" 26 27 "github.com/electroneum/electroneum-sc/common" 28 "github.com/electroneum/electroneum-sc/common/hexutil" 29 "github.com/electroneum/electroneum-sc/common/math" 30 "github.com/electroneum/electroneum-sc/core/rawdb" 31 "github.com/electroneum/electroneum-sc/core/state" 32 "github.com/electroneum/electroneum-sc/core/types" 33 "github.com/electroneum/electroneum-sc/crypto" 34 "github.com/electroneum/electroneum-sc/ethdb" 35 "github.com/electroneum/electroneum-sc/log" 36 "github.com/electroneum/electroneum-sc/params" 37 "github.com/electroneum/electroneum-sc/trie" 38 ) 39 40 //go:generate go run github.com/fjl/gencodec -type Genesis -field-override genesisSpecMarshaling -out gen_genesis.go 41 //go:generate go run github.com/fjl/gencodec -type GenesisAccount -field-override genesisAccountMarshaling -out gen_genesis_account.go 42 43 var errGenesisNoConfig = errors.New("genesis has no chain configuration") 44 45 // Genesis specifies the header fields, state of a genesis block. It also defines hard 46 // fork switch-over blocks through the chain configuration. 47 type Genesis struct { 48 Config *params.ChainConfig `json:"config"` 49 Nonce uint64 `json:"nonce"` 50 Timestamp uint64 `json:"timestamp"` 51 ExtraData []byte `json:"extraData"` 52 GasLimit uint64 `json:"gasLimit" gencodec:"required"` 53 Difficulty *big.Int `json:"difficulty" gencodec:"required"` 54 Mixhash common.Hash `json:"mixHash"` 55 Coinbase common.Address `json:"coinbase"` 56 Alloc GenesisAlloc `json:"alloc" gencodec:"required"` 57 58 // These fields are used for consensus tests. Please don't use them 59 // in actual genesis blocks. 60 Number uint64 `json:"number"` 61 GasUsed uint64 `json:"gasUsed"` 62 ParentHash common.Hash `json:"parentHash"` 63 BaseFee *big.Int `json:"baseFeePerGas"` 64 } 65 66 // GenesisAlloc specifies the initial state that is part of the genesis block. 67 type GenesisAlloc map[common.Address]GenesisAccount 68 69 func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error { 70 m := make(map[common.UnprefixedAddress]GenesisAccount) 71 if err := json.Unmarshal(data, &m); err != nil { 72 return err 73 } 74 *ga = make(GenesisAlloc) 75 for addr, a := range m { 76 (*ga)[common.Address(addr)] = a 77 } 78 return nil 79 } 80 81 // flush adds allocated genesis accounts into a fresh new statedb and 82 // commit the state changes into the given database handler. 83 func (ga *GenesisAlloc) flush(db ethdb.Database) (common.Hash, error) { 84 statedb, err := state.New(common.Hash{}, state.NewDatabase(db), nil) 85 if err != nil { 86 return common.Hash{}, err 87 } 88 for addr, account := range *ga { 89 statedb.AddBalance(addr, account.Balance) 90 statedb.SetCode(addr, account.Code) 91 statedb.SetNonce(addr, account.Nonce) 92 for key, value := range account.Storage { 93 statedb.SetState(addr, key, value) 94 } 95 } 96 root, err := statedb.Commit(false) 97 if err != nil { 98 return common.Hash{}, err 99 } 100 err = statedb.Database().TrieDB().Commit(root, true, nil) 101 if err != nil { 102 return common.Hash{}, err 103 } 104 return root, nil 105 } 106 107 // write writes the json marshaled genesis state into database 108 // with the given block hash as the unique identifier. 109 func (ga *GenesisAlloc) write(db ethdb.KeyValueWriter, hash common.Hash) error { 110 blob, err := json.Marshal(ga) 111 if err != nil { 112 return err 113 } 114 rawdb.WriteGenesisState(db, hash, blob) 115 return nil 116 } 117 118 // CommitGenesisState loads the stored genesis state with the given block 119 // hash and commits them into the given database handler. 120 func CommitGenesisState(db ethdb.Database, hash common.Hash) error { 121 var alloc GenesisAlloc 122 blob := rawdb.ReadGenesisState(db, hash) 123 if len(blob) != 0 { 124 if err := alloc.UnmarshalJSON(blob); err != nil { 125 return err 126 } 127 } else { 128 // Genesis allocation is missing and there are several possibilities: 129 // the node is legacy which doesn't persist the genesis allocation or 130 // the persisted allocation is just lost. 131 // - supported networks(mainnet, testnets), recover with defined allocations 132 // - private network, can't recover 133 var genesis *Genesis 134 switch hash { 135 case params.MainnetGenesisHash: 136 genesis = DefaultGenesisBlock() 137 case params.StagenetGenesisHash: 138 genesis = DefaultStagenetGenesisBlock() 139 case params.TestnetGenesisHash: 140 genesis = DefaultTestnetGenesisBlock() 141 } 142 if genesis != nil { 143 alloc = genesis.Alloc 144 } else { 145 return errors.New("not found") 146 } 147 } 148 _, err := alloc.flush(db) 149 return err 150 } 151 152 // GenesisAccount is an account in the state of the genesis block. 153 type GenesisAccount struct { 154 Code []byte `json:"code,omitempty"` 155 Storage map[common.Hash]common.Hash `json:"storage,omitempty"` 156 Balance *big.Int `json:"balance" gencodec:"required"` 157 Nonce uint64 `json:"nonce,omitempty"` 158 PrivateKey []byte `json:"secretKey,omitempty"` // for tests 159 } 160 161 // field type overrides for gencodec 162 type genesisSpecMarshaling struct { 163 Nonce math.HexOrDecimal64 164 Timestamp math.HexOrDecimal64 165 ExtraData hexutil.Bytes 166 GasLimit math.HexOrDecimal64 167 GasUsed math.HexOrDecimal64 168 Number math.HexOrDecimal64 169 Difficulty *math.HexOrDecimal256 170 BaseFee *math.HexOrDecimal256 171 Alloc map[common.UnprefixedAddress]GenesisAccount 172 } 173 174 type genesisAccountMarshaling struct { 175 Code hexutil.Bytes 176 Balance *math.HexOrDecimal256 177 Nonce math.HexOrDecimal64 178 Storage map[storageJSON]storageJSON 179 PrivateKey hexutil.Bytes 180 } 181 182 // storageJSON represents a 256 bit byte array, but allows less than 256 bits when 183 // unmarshaling from hex. 184 type storageJSON common.Hash 185 186 func (h *storageJSON) UnmarshalText(text []byte) error { 187 text = bytes.TrimPrefix(text, []byte("0x")) 188 if len(text) > 64 { 189 return fmt.Errorf("too many hex characters in storage key/value %q", text) 190 } 191 offset := len(h) - len(text)/2 // pad on the left 192 if _, err := hex.Decode(h[offset:], text); err != nil { 193 fmt.Println(err) 194 return fmt.Errorf("invalid hex storage key/value %q", text) 195 } 196 return nil 197 } 198 199 func (h storageJSON) MarshalText() ([]byte, error) { 200 return hexutil.Bytes(h[:]).MarshalText() 201 } 202 203 // GenesisMismatchError is raised when trying to overwrite an existing 204 // genesis block with an incompatible one. 205 type GenesisMismatchError struct { 206 Stored, New common.Hash 207 } 208 209 func (e *GenesisMismatchError) Error() string { 210 return fmt.Sprintf("database contains incompatible genesis (have %x, new %x)", e.Stored, e.New) 211 } 212 213 // SetupGenesisBlock writes or updates the genesis block in db. 214 // The block that will be used is: 215 // 216 // genesis == nil genesis != nil 217 // +------------------------------------------ 218 // db has no genesis | main-net default | genesis 219 // db has genesis | from DB | genesis (if compatible) 220 // 221 // The stored chain configuration will be updated if it is compatible (i.e. does not 222 // specify a fork block below the local head block). In case of a conflict, the 223 // error is a *params.ConfigCompatError and the new, unwritten config is returned. 224 // 225 // The returned chain configuration is never nil. 226 func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) { 227 return SetupGenesisBlockWithOverride(db, genesis, nil, nil) 228 } 229 230 func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, overrideArrowGlacier, overrideTerminalTotalDifficulty *big.Int) (*params.ChainConfig, common.Hash, error) { 231 if genesis != nil && genesis.Config == nil { 232 return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig 233 } 234 // Just commit the new block if there is no stored genesis block. 235 stored := rawdb.ReadCanonicalHash(db, 0) 236 if (stored == common.Hash{}) { 237 if genesis == nil { 238 log.Info("Writing default main-net genesis block") 239 genesis = DefaultGenesisBlock() 240 } else { 241 log.Info("Writing custom genesis block") 242 } 243 block, err := genesis.Commit(db) 244 if err != nil { 245 return genesis.Config, common.Hash{}, err 246 } 247 return genesis.Config, block.Hash(), nil 248 } 249 // We have the genesis block in database(perhaps in ancient database) 250 // but the corresponding state is missing. 251 header := rawdb.ReadHeader(db, stored, 0) 252 if _, err := state.New(header.Root, state.NewDatabaseWithConfig(db, nil), nil); err != nil { 253 if genesis == nil { 254 genesis = DefaultGenesisBlock() 255 } 256 // Ensure the stored genesis matches with the given one. 257 hash := genesis.ToBlock(nil).Hash() 258 if hash != stored { 259 return genesis.Config, hash, &GenesisMismatchError{stored, hash} 260 } 261 block, err := genesis.Commit(db) 262 if err != nil { 263 return genesis.Config, hash, err 264 } 265 return genesis.Config, block.Hash(), nil 266 } 267 // Check whether the genesis block is already written. 268 if genesis != nil { 269 hash := genesis.ToBlock(nil).Hash() 270 if hash != stored { 271 return genesis.Config, hash, &GenesisMismatchError{stored, hash} 272 } 273 } 274 // Get the existing chain configuration. 275 newcfg := genesis.configOrDefault(stored) 276 if overrideArrowGlacier != nil { 277 newcfg.ArrowGlacierBlock = overrideArrowGlacier 278 } 279 if overrideTerminalTotalDifficulty != nil { 280 newcfg.TerminalTotalDifficulty = overrideTerminalTotalDifficulty 281 } 282 if err := newcfg.CheckConfigForkOrder(); err != nil { 283 return newcfg, common.Hash{}, err 284 } 285 storedcfg := rawdb.ReadChainConfig(db, stored) 286 if storedcfg == nil { 287 log.Warn("Found genesis block without chain config") 288 rawdb.WriteChainConfig(db, stored, newcfg) 289 return newcfg, stored, nil 290 } 291 // Special case: if a private network is being used (no genesis and also no 292 // mainnet hash in the database), we must not apply the `configOrDefault` 293 // chain config as that would be AllProtocolChanges (applying any new fork 294 // on top of an existing private network genesis block). In that case, only 295 // apply the overrides. 296 if genesis == nil && stored != params.MainnetGenesisHash { 297 newcfg = storedcfg 298 if overrideArrowGlacier != nil { 299 newcfg.ArrowGlacierBlock = overrideArrowGlacier 300 } 301 if overrideTerminalTotalDifficulty != nil { 302 newcfg.TerminalTotalDifficulty = overrideTerminalTotalDifficulty 303 } 304 } 305 // Check config compatibility and write the config. Compatibility errors 306 // are returned to the caller unless we're already at block zero. 307 height := rawdb.ReadHeaderNumber(db, rawdb.ReadHeadHeaderHash(db)) 308 if height == nil { 309 return newcfg, stored, fmt.Errorf("missing block number for head header hash") 310 } 311 compatErr := storedcfg.CheckCompatible(newcfg, *height) 312 if compatErr != nil && *height != 0 && compatErr.RewindTo != 0 { 313 return newcfg, stored, compatErr 314 } 315 rawdb.WriteChainConfig(db, stored, newcfg) 316 return newcfg, stored, nil 317 } 318 319 func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig { 320 switch { 321 case g != nil: 322 return g.Config 323 case ghash == params.MainnetGenesisHash: 324 return params.MainnetChainConfig 325 case ghash == params.StagenetGenesisHash: 326 return params.StagenetChainConfig 327 case ghash == params.TestnetGenesisHash: 328 return params.TestnetChainConfig 329 default: 330 return params.AllEthashProtocolChanges 331 } 332 } 333 334 // ToBlock creates the genesis block and writes state of a genesis specification 335 // to the given database (or discards it if nil). 336 func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { 337 if db == nil { 338 db = rawdb.NewMemoryDatabase() 339 } 340 root, err := g.Alloc.flush(db) 341 if err != nil { 342 panic(err) 343 } 344 head := &types.Header{ 345 Number: new(big.Int).SetUint64(g.Number), 346 Nonce: types.EncodeNonce(g.Nonce), 347 Time: g.Timestamp, 348 ParentHash: g.ParentHash, 349 Extra: g.ExtraData, 350 GasLimit: g.GasLimit, 351 GasUsed: g.GasUsed, 352 BaseFee: g.BaseFee, 353 Difficulty: g.Difficulty, 354 MixDigest: g.Mixhash, 355 Coinbase: g.Coinbase, 356 Root: root, 357 } 358 if g.GasLimit == 0 { 359 head.GasLimit = params.GenesisGasLimit 360 } 361 if g.Difficulty == nil && g.Mixhash == (common.Hash{}) { 362 head.Difficulty = params.GenesisDifficulty 363 } 364 if g.Config != nil && g.Config.IsLondon(common.Big0) { 365 if g.BaseFee != nil { 366 head.BaseFee = g.BaseFee 367 } else { 368 head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee) 369 } 370 } 371 return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)) 372 } 373 374 // Commit writes the block and state of a genesis specification to the database. 375 // The block is committed as the canonical head block. 376 func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) { 377 block := g.ToBlock(db) 378 if block.Number().Sign() != 0 { 379 return nil, errors.New("can't commit genesis block with number > 0") 380 } 381 config := g.Config 382 if config == nil { 383 config = params.AllEthashProtocolChanges 384 } 385 if err := config.CheckConfigForkOrder(); err != nil { 386 return nil, err 387 } 388 if config.Clique != nil && len(block.Extra()) < 32+crypto.SignatureLength { 389 return nil, errors.New("can't start clique chain without signers") 390 } 391 if err := g.Alloc.write(db, block.Hash()); err != nil { 392 return nil, err 393 } 394 rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty()) 395 rawdb.WriteBlock(db, block) 396 rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil) 397 rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64()) 398 rawdb.WriteHeadBlockHash(db, block.Hash()) 399 rawdb.WriteHeadFastBlockHash(db, block.Hash()) 400 rawdb.WriteHeadHeaderHash(db, block.Hash()) 401 rawdb.WriteChainConfig(db, block.Hash(), config) 402 return block, nil 403 } 404 405 // MustCommit writes the genesis block and state to db, panicking on error. 406 // The block is committed as the canonical head block. 407 func (g *Genesis) MustCommit(db ethdb.Database) *types.Block { 408 block, err := g.Commit(db) 409 if err != nil { 410 panic(err) 411 } 412 return block 413 } 414 415 // GenesisBlockForTesting creates and writes a block in which addr has the given wei balance. 416 func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block { 417 g := Genesis{ 418 Alloc: GenesisAlloc{addr: {Balance: balance}}, 419 BaseFee: big.NewInt(params.InitialBaseFee), 420 } 421 return g.MustCommit(db) 422 } 423 424 // DefaultGenesisBlock returns the Electroneum-sc mainnet genesis block. 425 func DefaultGenesisBlock() *Genesis { 426 return &Genesis{ 427 Config: params.MainnetChainConfig, 428 Nonce: 0, 429 Timestamp: 1492009146, 430 ExtraData: hexutil.MustDecode("0xf87aa00000000000000000000000000000000000000000000000000000000000000000f854944c7968f79c1a414c34cd4d3c1ac7a3a8413da50c946c3d358156962440424c8c2bd5a8c79664b9956d94f27ed0217ec98beec0478a221e07471885d639a2944dd607ce3b4ec9e22fd3ce59c672fafee09cf332c080c0"), 431 GasLimit: 16234336, 432 Difficulty: big.NewInt(1), 433 Mixhash: common.HexToHash("0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365"), 434 Coinbase: common.Address{}, 435 Alloc: GenesisAlloc{}, //TODO: get etn circulating supply allocated to the bridge address 436 } 437 } 438 439 // DefaultStagenetGenesisBlock returns the test network genesis block. 440 func DefaultStagenetGenesisBlock() *Genesis { 441 return &Genesis{ 442 Config: params.StagenetChainConfig, 443 Nonce: 0, 444 Timestamp: 1655988355, 445 ExtraData: hexutil.MustDecode("0xf88fa00000000000000000000000000000000000000000000000000000000000000000f86994c21ee98b5a90a6a45aba37fa5eddf90f5e8e181694ff0d56bd960c455a71f908496c79e8eafec34ccf9407afbe0d7d36b80454be1e185f55e02b9453625a944f9a82d7e094de7fb70d9ce2033ec0d65ac311249497f060952b1008c75cb030e3599725ad5cc306a2c080c0"), 446 GasLimit: 16234336, 447 Difficulty: big.NewInt(1), 448 Mixhash: common.HexToHash("0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365"), 449 Coinbase: common.Address{}, 450 Alloc: GenesisAlloc{ 451 common.HexToAddress("0x72f1a0bAA7f1C79129A391C2F32bCD8247A18a63"): {Balance: math.MustParseBig256("1000000000000000000000000000")}, 452 common.HexToAddress("0xf29A0844926Fe8d63e5B211978B26E3f6d9e9fd5"): {Balance: math.MustParseBig256("1000000000000000000000000000")}, 453 }, 454 } 455 } 456 457 // DefaultTestnetGenesisBlock returns the stage network genesis block. 458 func DefaultTestnetGenesisBlock() *Genesis { 459 return &Genesis{ 460 Config: params.TestnetChainConfig, 461 Nonce: 0, 462 Timestamp: 1655988353, 463 ExtraData: hexutil.MustDecode("0xf88fa00000000000000000000000000000000000000000000000000000000000000000f86994c21ee98b5a90a6a45aba37fa5eddf90f5e8e181694ff0d56bd960c455a71f908496c79e8eafec34ccf9407afbe0d7d36b80454be1e185f55e02b9453625a944f9a82d7e094de7fb70d9ce2033ec0d65ac311249497f060952b1008c75cb030e3599725ad5cc306a2c080c0"), 464 GasLimit: 16234336, 465 Difficulty: big.NewInt(1), 466 Mixhash: common.HexToHash("0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365"), 467 Coinbase: common.Address{}, 468 Alloc: GenesisAlloc{ 469 common.HexToAddress("0x72f1a0bAA7f1C79129A391C2F32bCD8247A18a63"): {Balance: math.MustParseBig256("1000000000000000000000000000")}, 470 common.HexToAddress("0xf29A0844926Fe8d63e5B211978B26E3f6d9e9fd5"): {Balance: math.MustParseBig256("1000000000000000000000000000")}, 471 }, 472 } 473 } 474 475 // DeveloperGenesisBlock returns the 'geth --dev' genesis block. 476 func DeveloperGenesisBlock(period uint64, gasLimit uint64, faucet common.Address) *Genesis { 477 // Override the default period to the user requested one 478 config := *params.AllCliqueProtocolChanges 479 config.Clique = ¶ms.CliqueConfig{ 480 Period: period, 481 Epoch: config.Clique.Epoch, 482 } 483 484 // Assemble and return the genesis with the precompiles and faucet pre-funded 485 return &Genesis{ 486 Config: &config, 487 ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, crypto.SignatureLength)...), 488 GasLimit: gasLimit, 489 BaseFee: big.NewInt(params.InitialBaseFee), 490 Difficulty: big.NewInt(1), 491 Alloc: map[common.Address]GenesisAccount{ 492 common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, // ECRecover 493 common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, // SHA256 494 common.BytesToAddress([]byte{3}): {Balance: big.NewInt(1)}, // RIPEMD 495 common.BytesToAddress([]byte{4}): {Balance: big.NewInt(1)}, // Identity 496 common.BytesToAddress([]byte{5}): {Balance: big.NewInt(1)}, // ModExp 497 common.BytesToAddress([]byte{6}): {Balance: big.NewInt(1)}, // ECAdd 498 common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul 499 common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing 500 common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b 501 faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))}, 502 }, 503 } 504 } 505 506 /* 507 func decodePrealloc(data string) GenesisAlloc { 508 var p []struct{ Addr, Balance *big.Int } 509 if err := rlp.NewStream(strings.NewReader(data), 0).Decode(&p); err != nil { 510 panic(err) 511 } 512 ga := make(GenesisAlloc, len(p)) 513 for _, account := range p { 514 ga[common.BigToAddress(account.Addr)] = GenesisAccount{Balance: account.Balance} 515 } 516 return ga 517 } 518 */