github.com/klaytn/klaytn@v1.10.2/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); 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) 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 342 stateDB.Commit(false) 343 stateDB.Database().TrieDB().Commit(root, true, g.Number) 344 345 return types.NewBlock(head, nil, nil) 346 } 347 348 // Commit writes the block and state of a genesis specification to the database. 349 // The block is committed as the canonical head block. 350 func (g *Genesis) Commit(baseStateRoot common.Hash, db database.DBManager) (*types.Block, error) { 351 block := g.ToBlock(baseStateRoot, db) 352 if block.Number().Sign() != 0 { 353 return nil, fmt.Errorf("can't commit genesis block with number > 0") 354 } 355 db.WriteTd(block.Hash(), block.NumberU64(), g.BlockScore) 356 db.WriteBlock(block) 357 db.WriteReceipts(block.Hash(), block.NumberU64(), nil) 358 db.WriteCanonicalHash(block.Hash(), block.NumberU64()) 359 db.WriteHeadBlockHash(block.Hash()) 360 db.WriteHeadHeaderHash(block.Hash()) 361 362 config := g.Config 363 if config == nil { 364 config = params.AllGxhashProtocolChanges 365 } 366 if err := config.CheckConfigForkOrder(); err != nil { 367 return nil, err 368 } 369 db.WriteChainConfig(block.Hash(), config) 370 return block, nil 371 } 372 373 // MustCommit writes the genesis block and state to db, panicking on error. 374 // The block is committed as the canonical head block. 375 func (g *Genesis) MustCommit(db database.DBManager) *types.Block { 376 config := g.Config 377 if config == nil { 378 config = params.AllGxhashProtocolChanges 379 } 380 InitDeriveSha(config) 381 382 block, err := g.Commit(common.Hash{}, db) 383 if err != nil { 384 panic(err) 385 } 386 return block 387 } 388 389 // GenesisBlockForTesting creates and writes a block in which addr has the given peb balance. 390 func GenesisBlockForTesting(db database.DBManager, addr common.Address, balance *big.Int) *types.Block { 391 g := Genesis{Alloc: GenesisAlloc{addr: {Balance: balance}}} 392 return g.MustCommit(db) 393 } 394 395 // DefaultGenesisBlock returns the Cypress mainnet genesis block. 396 // It is also used for default genesis block. 397 func DefaultGenesisBlock() *Genesis { 398 ret := &Genesis{} 399 if err := json.Unmarshal(cypressGenesisJson, &ret); err != nil { 400 logger.Error("Error in Unmarshalling Cypress Genesis Json", "err", err) 401 } 402 ret.Config = params.CypressChainConfig 403 return ret 404 } 405 406 // DefaultBaobabGenesisBlock returns the Baobab testnet genesis block. 407 func DefaultBaobabGenesisBlock() *Genesis { 408 ret := &Genesis{} 409 if err := json.Unmarshal(baobabGenesisJson, &ret); err != nil { 410 logger.Error("Error in Unmarshalling Baobab Genesis Json", "err", err) 411 return nil 412 } 413 ret.Config = params.BaobabChainConfig 414 return ret 415 } 416 417 func decodePrealloc(data string) GenesisAlloc { 418 var p []struct{ Addr, Balance *big.Int } 419 if err := rlp.NewStream(strings.NewReader(data), 0).Decode(&p); err != nil { 420 panic(err) 421 } 422 ga := make(GenesisAlloc, len(p)) 423 for _, account := range p { 424 ga[common.BigToAddress(account.Addr)] = GenesisAccount{Balance: account.Balance} 425 } 426 return ga 427 } 428 429 type GovernanceSet map[string]interface{} 430 431 func SetGenesisGovernance(genesis *Genesis) []byte { 432 g := make(GovernanceSet) 433 governance := genesis.Config.Governance 434 g["governance.governancemode"] = governance.GovernanceMode 435 g["governance.governingnode"] = governance.GoverningNode 436 g["governance.unitprice"] = genesis.Config.UnitPrice 437 g["reward.mintingamount"] = governance.Reward.MintingAmount.String() 438 g["reward.minimumstake"] = governance.Reward.MinimumStake.String() 439 g["reward.ratio"] = governance.Reward.Ratio 440 g["reward.useginicoeff"] = governance.Reward.UseGiniCoeff 441 g["reward.deferredtxfee"] = governance.Reward.DeferredTxFee 442 g["reward.stakingupdateinterval"] = governance.Reward.StakingUpdateInterval 443 g["reward.proposerupdateinterval"] = governance.Reward.ProposerUpdateInterval 444 g["istanbul.epoch"] = genesis.Config.Istanbul.Epoch 445 g["istanbul.policy"] = genesis.Config.Istanbul.ProposerPolicy 446 g["istanbul.committeesize"] = genesis.Config.Istanbul.SubGroupSize 447 448 data, err := json.Marshal(g) 449 if err != nil { 450 logger.Crit("Error in marshaling governance data", "err", err) 451 } 452 ret, err := rlp.EncodeToBytes(data) 453 if err != nil { 454 logger.Crit("Error in RLP Encoding governance data", "err", err) 455 } 456 return ret 457 }