github.com/klaytn/klaytn@v1.12.1/blockchain/genesis.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2014 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from core/genesis.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package blockchain 22 23 import ( 24 "bytes" 25 "encoding/hex" 26 "encoding/json" 27 "errors" 28 "fmt" 29 "math/big" 30 "strings" 31 32 "github.com/klaytn/klaytn/blockchain/state" 33 "github.com/klaytn/klaytn/blockchain/types" 34 "github.com/klaytn/klaytn/common" 35 "github.com/klaytn/klaytn/common/hexutil" 36 "github.com/klaytn/klaytn/common/math" 37 "github.com/klaytn/klaytn/params" 38 "github.com/klaytn/klaytn/rlp" 39 "github.com/klaytn/klaytn/storage/database" 40 ) 41 42 //go:generate gencodec -type Genesis -field-override genesisSpecMarshaling -out gen_genesis.go 43 //go:generate gencodec -type GenesisAccount -field-override genesisAccountMarshaling -out gen_genesis_account.go 44 45 var ( 46 errGenesisNoConfig = errors.New("genesis has no chain configuration") 47 errNoGenesis = errors.New("genesis block is not provided") 48 ) 49 50 // Genesis specifies the header fields, state of a genesis block. It also defines hard 51 // fork switch-over blocks through the chain configuration. 52 type Genesis struct { 53 Config *params.ChainConfig `json:"config"` 54 Timestamp uint64 `json:"timestamp"` 55 ExtraData []byte `json:"extraData"` 56 Governance []byte `json:"governanceData"` 57 BlockScore *big.Int `json:"blockScore"` 58 Alloc GenesisAlloc `json:"alloc" gencodec:"required"` 59 60 // These fields are used for consensus tests. Please don't use them 61 // in actual genesis blocks. 62 Number uint64 `json:"number"` 63 GasUsed uint64 `json:"gasUsed"` 64 ParentHash common.Hash `json:"parentHash"` 65 } 66 67 // GenesisAlloc specifies the initial state that is part of the genesis block. 68 type GenesisAlloc map[common.Address]GenesisAccount 69 70 func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error { 71 m := make(map[common.UnprefixedAddress]GenesisAccount) 72 if err := json.Unmarshal(data, &m); err != nil { 73 return err 74 } 75 *ga = make(GenesisAlloc) 76 for addr, a := range m { 77 (*ga)[common.Address(addr)] = a 78 } 79 return nil 80 } 81 82 // GenesisAccount is an account in the state of the genesis block. 83 type GenesisAccount struct { 84 Code []byte `json:"code,omitempty"` 85 Storage map[common.Hash]common.Hash `json:"storage,omitempty"` 86 Balance *big.Int `json:"balance" gencodec:"required"` 87 Nonce uint64 `json:"nonce,omitempty"` 88 PrivateKey []byte `json:"secretKey,omitempty"` // for tests 89 } 90 91 // field type overrides for gencodec 92 type genesisSpecMarshaling struct { 93 Timestamp math.HexOrDecimal64 94 ExtraData hexutil.Bytes 95 GasUsed math.HexOrDecimal64 96 Number math.HexOrDecimal64 97 BlockScore *math.HexOrDecimal256 98 Alloc map[common.UnprefixedAddress]GenesisAccount 99 } 100 101 type genesisAccountMarshaling struct { 102 Code hexutil.Bytes 103 Balance *math.HexOrDecimal256 104 Nonce math.HexOrDecimal64 105 Storage map[storageJSON]storageJSON 106 PrivateKey hexutil.Bytes 107 } 108 109 // storageJSON represents a 256 bit byte array, but allows less than 256 bits when 110 // unmarshaling from hex. 111 type storageJSON common.Hash 112 113 func (h *storageJSON) UnmarshalText(text []byte) error { 114 text = bytes.TrimPrefix(text, []byte("0x")) 115 if len(text) > 64 { 116 return fmt.Errorf("too many hex characters in storage key/value %q", text) 117 } 118 offset := len(h) - len(text)/2 // pad on the left 119 if _, err := hex.Decode(h[offset:], text); err != nil { 120 fmt.Println(err) 121 return fmt.Errorf("invalid hex storage key/value %q", text) 122 } 123 return nil 124 } 125 126 func (h storageJSON) MarshalText() ([]byte, error) { 127 return hexutil.Bytes(h[:]).MarshalText() 128 } 129 130 // GenesisMismatchError is raised when trying to overwrite an existing 131 // genesis block with an incompatible one. 132 type GenesisMismatchError struct { 133 Stored, New common.Hash 134 } 135 136 func (e *GenesisMismatchError) Error() string { 137 return fmt.Sprintf("database already contains an incompatible genesis block (have %x, new %x)", e.Stored[:8], e.New[:8]) 138 } 139 140 // findBlockWithState returns the latest block with state. 141 func findBlockWithState(db database.DBManager) *types.Block { 142 headBlock := db.ReadBlockByHash(db.ReadHeadBlockHash()) 143 if headBlock == nil { 144 headBlock = db.ReadBlockByHash(db.ReadHeadBlockBackupHash()) 145 if headBlock == nil { 146 logger.Crit("failed to read head block by head block hash") 147 } 148 } 149 150 startBlock := headBlock 151 for _, err := state.New(headBlock.Root(), state.NewDatabase(db), nil, nil); err != nil; { 152 if headBlock.NumberU64() == 0 { 153 logger.Crit("failed to find state from the head block to the genesis block", 154 "headBlockNum", headBlock.NumberU64(), 155 "headBlockHash", headBlock.Hash().String(), "headBlockRoot", headBlock.Root().String()) 156 } 157 headBlock = db.ReadBlockByNumber(headBlock.NumberU64() - 1) 158 if headBlock == nil { 159 logger.Crit("failed to read previous block by head block number") 160 } 161 logger.Warn("found previous block", "blockNum", headBlock.NumberU64()) 162 } 163 logger.Info("found the latest block with state", 164 "blockNum", headBlock.NumberU64(), "startedNum", startBlock.NumberU64()) 165 return headBlock 166 } 167 168 // SetupGenesisBlock writes or updates the genesis block in db. 169 // The block that will be used is: 170 // 171 // genesis == nil genesis != nil 172 // +------------------------------------------------------------------- 173 // db has no genesis | main-net default, baobab if specified | genesis 174 // db has genesis | from DB | genesis (if compatible) 175 // 176 // The stored chain configuration will be updated if it is compatible (i.e. does not 177 // specify a fork block below the local head block). In case of a conflict, the 178 // error is a *params.ConfigCompatError and the new, unwritten config is returned. 179 // 180 // The returned chain configuration is never nil. 181 func SetupGenesisBlock(db database.DBManager, genesis *Genesis, networkId uint64, isPrivate, overwriteGenesis bool) (*params.ChainConfig, common.Hash, error) { 182 if genesis != nil && genesis.Config == nil { 183 return params.AllGxhashProtocolChanges, common.Hash{}, errGenesisNoConfig 184 } 185 186 // Just commit the new block if there is no stored genesis block. 187 stored := db.ReadCanonicalHash(0) 188 if (stored == common.Hash{}) { 189 if genesis == nil { 190 switch { 191 case isPrivate: 192 logger.Error("No genesis is provided. --networkid should be omitted if you want to use preconfigured network") 193 return params.AllGxhashProtocolChanges, common.Hash{}, errNoGenesis 194 case networkId == params.BaobabNetworkId: 195 logger.Info("Writing default baobab genesis block") 196 genesis = DefaultBaobabGenesisBlock() 197 case networkId == params.CypressNetworkId: 198 fallthrough 199 default: 200 logger.Info("Writing default main-net genesis block") 201 genesis = DefaultGenesisBlock() 202 } 203 if genesis.Config.Governance != nil { 204 genesis.Governance = SetGenesisGovernance(genesis) 205 } 206 } else { 207 logger.Info("Writing custom genesis block") 208 } 209 // Initialize DeriveSha implementation 210 InitDeriveSha(genesis.Config) 211 block, err := genesis.Commit(common.Hash{}, db) 212 if err != nil { 213 return genesis.Config, common.Hash{}, err 214 } 215 return genesis.Config, block.Hash(), err 216 } 217 218 // Check whether the genesis block is already written. 219 if genesis != nil { 220 // If overwriteGenesis is true, overwrite existing genesis block with the new one. 221 // This is to run a test with pre-existing data. 222 if overwriteGenesis { 223 headBlock := findBlockWithState(db) 224 logger.Warn("Trying to overwrite original genesis block with the new one", 225 "headBlockHash", headBlock.Hash().String(), "headBlockNum", headBlock.NumberU64()) 226 newGenesisBlock, err := genesis.Commit(headBlock.Root(), db) 227 return genesis.Config, newGenesisBlock.Hash(), err 228 } 229 // This is the usual path which does not overwrite genesis block with the new one. 230 InitDeriveSha(genesis.Config) 231 hash := genesis.ToBlock(common.Hash{}, nil).Hash() 232 if hash != stored { 233 return genesis.Config, hash, &GenesisMismatchError{stored, hash} 234 } 235 } 236 237 // Get the existing chain configuration. 238 newcfg := genesis.configOrDefault(stored) 239 if err := newcfg.CheckConfigForkOrder(); err != nil { 240 return newcfg, common.Hash{}, err 241 } 242 storedcfg := db.ReadChainConfig(stored) 243 if storedcfg == nil { 244 logger.Info("Found genesis block without chain config") 245 db.WriteChainConfig(stored, newcfg) 246 return newcfg, stored, nil 247 } else { 248 if storedcfg.Governance == nil { 249 logger.Crit("Failed to read governance. storedcfg.Governance == nil") 250 } 251 if storedcfg.Governance.Reward == nil { 252 logger.Crit("Failed to read governance. storedcfg.Governance.Reward == nil") 253 } 254 if storedcfg.Governance.Reward.StakingUpdateInterval != 0 { 255 params.SetStakingUpdateInterval(storedcfg.Governance.Reward.StakingUpdateInterval) 256 } 257 if storedcfg.Governance.Reward.ProposerUpdateInterval != 0 { 258 params.SetProposerUpdateInterval(storedcfg.Governance.Reward.ProposerUpdateInterval) 259 } 260 } 261 // Special case: don't change the existing config of a non-mainnet chain if no new 262 // config is supplied. These chains would get AllProtocolChanges (and a compat error) 263 // if we just continued here. 264 if genesis == nil && params.CypressGenesisHash != stored && params.BaobabGenesisHash != stored { 265 return storedcfg, stored, nil 266 } 267 268 // Check config compatibility and write the config. Compatibility errors 269 // are returned to the caller unless we're already at block zero. 270 height := db.ReadHeaderNumber(db.ReadHeadHeaderHash()) 271 if height == nil { 272 return newcfg, stored, fmt.Errorf("missing block number for head header hash") 273 } 274 compatErr := storedcfg.CheckCompatible(newcfg, *height) 275 if compatErr != nil && *height != 0 && compatErr.RewindTo != 0 { 276 return newcfg, stored, compatErr 277 } 278 db.WriteChainConfig(stored, newcfg) 279 return newcfg, stored, nil 280 } 281 282 func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig { 283 switch { 284 case g != nil: 285 return g.Config 286 case ghash == params.CypressGenesisHash: 287 return params.CypressChainConfig 288 case ghash == params.BaobabGenesisHash: 289 return params.BaobabChainConfig 290 default: 291 return params.AllGxhashProtocolChanges 292 } 293 } 294 295 // ToBlock creates the genesis block and writes state of a genesis specification 296 // to the given database (or discards it if nil). 297 func (g *Genesis) ToBlock(baseStateRoot common.Hash, db database.DBManager) *types.Block { 298 if db == nil { 299 db = database.NewMemoryDBManager() 300 } 301 stateDB, _ := state.New(baseStateRoot, state.NewDatabase(db), nil, nil) 302 for addr, account := range g.Alloc { 303 if len(account.Code) != 0 { 304 originalCode := stateDB.GetCode(addr) 305 stateDB.SetCode(addr, account.Code) 306 // If originalCode is not nil, 307 // just update the code and don't change the other states 308 if originalCode != nil { 309 logger.Warn("this address already has a not nil code, now the code of this address has been changed", "addr", addr.String()) 310 continue 311 } 312 } 313 for key, value := range account.Storage { 314 stateDB.SetState(addr, key, value) 315 } 316 stateDB.AddBalance(addr, account.Balance) 317 stateDB.SetNonce(addr, account.Nonce) 318 } 319 root := stateDB.IntermediateRoot(false) 320 head := &types.Header{ 321 Number: new(big.Int).SetUint64(g.Number), 322 Time: new(big.Int).SetUint64(g.Timestamp), 323 TimeFoS: 0, 324 ParentHash: g.ParentHash, 325 Extra: g.ExtraData, 326 Governance: g.Governance, 327 GasUsed: g.GasUsed, 328 BlockScore: g.BlockScore, 329 Root: root, 330 } 331 if g.BlockScore == nil { 332 head.BlockScore = params.GenesisBlockScore 333 } 334 if g.Config != nil && g.Config.IsMagmaForkEnabled(common.Big0) { 335 if g.Config.Governance != nil && g.Config.Governance.KIP71 != nil { 336 head.BaseFee = new(big.Int).SetUint64(g.Config.Governance.KIP71.LowerBoundBaseFee) 337 } else { 338 head.BaseFee = new(big.Int).SetUint64(params.DefaultLowerBoundBaseFee) 339 } 340 } 341 if g.Config != nil && g.Config.IsRandaoForkEnabled(common.Big0) { 342 head.RandomReveal = params.ZeroRandomReveal 343 head.MixHash = params.ZeroMixHash 344 } 345 346 stateDB.Commit(false) 347 stateDB.Database().TrieDB().Commit(root, true, g.Number) 348 349 return types.NewBlock(head, nil, nil) 350 } 351 352 // Commit writes the block and state of a genesis specification to the database. 353 // The block is committed as the canonical head block. 354 func (g *Genesis) Commit(baseStateRoot common.Hash, db database.DBManager) (*types.Block, error) { 355 block := g.ToBlock(baseStateRoot, db) 356 if block.Number().Sign() != 0 { 357 return nil, fmt.Errorf("can't commit genesis block with number > 0") 358 } 359 db.WriteTd(block.Hash(), block.NumberU64(), g.BlockScore) 360 db.WriteBlock(block) 361 db.WriteReceipts(block.Hash(), block.NumberU64(), nil) 362 db.WriteCanonicalHash(block.Hash(), block.NumberU64()) 363 db.WriteHeadBlockHash(block.Hash()) 364 db.WriteHeadHeaderHash(block.Hash()) 365 366 config := g.Config 367 if config == nil { 368 config = params.AllGxhashProtocolChanges 369 } 370 if err := config.CheckConfigForkOrder(); err != nil { 371 return nil, err 372 } 373 db.WriteChainConfig(block.Hash(), config) 374 return block, nil 375 } 376 377 // MustCommit writes the genesis block and state to db, panicking on error. 378 // The block is committed as the canonical head block. 379 func (g *Genesis) MustCommit(db database.DBManager) *types.Block { 380 config := g.Config 381 if config == nil { 382 config = params.AllGxhashProtocolChanges 383 } 384 InitDeriveSha(config) 385 386 block, err := g.Commit(common.Hash{}, db) 387 if err != nil { 388 panic(err) 389 } 390 return block 391 } 392 393 // GenesisBlockForTesting creates and writes a block in which addr has the given peb balance. 394 func GenesisBlockForTesting(db database.DBManager, addr common.Address, balance *big.Int) *types.Block { 395 g := Genesis{Alloc: GenesisAlloc{addr: {Balance: balance}}} 396 return g.MustCommit(db) 397 } 398 399 // DefaultGenesisBlock returns the Cypress mainnet genesis block. 400 // It is also used for default genesis block. 401 func DefaultGenesisBlock() *Genesis { 402 ret := &Genesis{} 403 if err := json.Unmarshal(cypressGenesisJson, &ret); err != nil { 404 logger.Error("Error in Unmarshalling Cypress Genesis Json", "err", err) 405 } 406 ret.Config = params.CypressChainConfig 407 return ret 408 } 409 410 // DefaultBaobabGenesisBlock returns the Baobab testnet genesis block. 411 func DefaultBaobabGenesisBlock() *Genesis { 412 ret := &Genesis{} 413 if err := json.Unmarshal(baobabGenesisJson, &ret); err != nil { 414 logger.Error("Error in Unmarshalling Baobab Genesis Json", "err", err) 415 return nil 416 } 417 ret.Config = params.BaobabChainConfig 418 return ret 419 } 420 421 func decodePrealloc(data string) GenesisAlloc { 422 var p []struct{ Addr, Balance *big.Int } 423 if err := rlp.NewStream(strings.NewReader(data), 0).Decode(&p); err != nil { 424 panic(err) 425 } 426 ga := make(GenesisAlloc, len(p)) 427 for _, account := range p { 428 ga[common.BigToAddress(account.Addr)] = GenesisAccount{Balance: account.Balance} 429 } 430 return ga 431 } 432 433 type GovernanceSet map[string]interface{} 434 435 func SetGenesisGovernance(genesis *Genesis) []byte { 436 g := make(GovernanceSet) 437 governance := genesis.Config.Governance 438 g["governance.governancemode"] = governance.GovernanceMode 439 g["governance.governingnode"] = governance.GoverningNode 440 g["governance.unitprice"] = genesis.Config.UnitPrice 441 g["reward.mintingamount"] = governance.Reward.MintingAmount.String() 442 g["reward.minimumstake"] = governance.Reward.MinimumStake.String() 443 g["reward.ratio"] = governance.Reward.Ratio 444 g["reward.useginicoeff"] = governance.Reward.UseGiniCoeff 445 g["reward.deferredtxfee"] = governance.Reward.DeferredTxFee 446 g["reward.stakingupdateinterval"] = governance.Reward.StakingUpdateInterval 447 g["reward.proposerupdateinterval"] = governance.Reward.ProposerUpdateInterval 448 g["istanbul.epoch"] = genesis.Config.Istanbul.Epoch 449 g["istanbul.policy"] = genesis.Config.Istanbul.ProposerPolicy 450 g["istanbul.committeesize"] = genesis.Config.Istanbul.SubGroupSize 451 452 data, err := json.Marshal(g) 453 if err != nil { 454 logger.Crit("Error in marshaling governance data", "err", err) 455 } 456 ret, err := rlp.EncodeToBytes(data) 457 if err != nil { 458 logger.Crit("Error in RLP Encoding governance data", "err", err) 459 } 460 return ret 461 }