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  }