github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/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  	"strings"
    27  
    28  	"github.com/intfoundation/intchain/common"
    29  	"github.com/intfoundation/intchain/common/hexutil"
    30  	"github.com/intfoundation/intchain/common/math"
    31  	"github.com/intfoundation/intchain/core/rawdb"
    32  	"github.com/intfoundation/intchain/core/state"
    33  	"github.com/intfoundation/intchain/core/types"
    34  	"github.com/intfoundation/intchain/intdb"
    35  	"github.com/intfoundation/intchain/log"
    36  	"github.com/intfoundation/intchain/params"
    37  	"github.com/intfoundation/intchain/rlp"
    38  )
    39  
    40  //go:generate gencodec -type Genesis -field-override genesisSpecMarshaling -out gen_genesis.go
    41  //go:generate 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  }
    64  
    65  // 写入时使用
    66  //type GenesisWrite struct {
    67  //	Config     *params.ChainConfig `json:"config"`
    68  //	Nonce      uint64              `json:"nonce"`
    69  //	Timestamp  uint64              `json:"timestamp"`
    70  //	ExtraData  []byte              `json:"extraData"`
    71  //	GasLimit   uint64              `json:"gasLimit"   gencodec:"required"`
    72  //	Difficulty *big.Int            `json:"difficulty" gencodec:"required"`
    73  //	Mixhash    common.Hash         `json:"mixHash"`
    74  //	Coinbase   string              `json:"coinbase"`
    75  //	Alloc      GenesisAllocWrite   `json:"alloc"      gencodec:"required"`
    76  //
    77  //	// These fields are used for consensus tests. Please don't use them
    78  //	// in actual genesis blocks.
    79  //	Number     uint64      `json:"number"`
    80  //	GasUsed    uint64      `json:"gasUsed"`
    81  //	ParentHash common.Hash `json:"parentHash"`
    82  //}
    83  
    84  // GenesisAlloc specifies the initial state that is part of the genesis block.
    85  type GenesisAlloc map[common.Address]GenesisAccount
    86  
    87  //// 写入时使用
    88  //type GenesisAllocWrite map[string]GenesisAccount
    89  
    90  func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error {
    91  	m := make(map[common.UnprefixedAddress]GenesisAccount)
    92  	if err := json.Unmarshal(data, &m); err != nil {
    93  		return err
    94  	}
    95  	*ga = make(GenesisAlloc)
    96  	for addr, a := range m {
    97  		(*ga)[common.Address(addr)] = a
    98  	}
    99  	return nil
   100  }
   101  
   102  // GenesisAccount is an account in the state of the genesis block.
   103  type GenesisAccount struct {
   104  	Code    []byte                      `json:"code,omitempty"`
   105  	Storage map[common.Hash]common.Hash `json:"storage,omitempty"`
   106  	Balance *big.Int                    `json:"balance" gencodec:"required"`
   107  	Nonce   uint64                      `json:"nonce,omitempty"`
   108  
   109  	// Stack
   110  	Amount *big.Int `json:"amount,omitempty"`
   111  	// Delegate
   112  	DelegateBalance *big.Int `json:"delegate,omitempty"`
   113  	// Proxied Balance
   114  	DepositProxiedDetail map[common.Address]*big.Int `json:"proxiedList,omitempty"`
   115  	// Candidate
   116  	Candidate  bool  `json:"candidate,omitempty"`
   117  	Commission uint8 `json:"commission,omitempty"`
   118  
   119  	PrivateKey []byte `json:"secretKey,omitempty"` // for tests
   120  }
   121  
   122  // field type overrides for gencodec
   123  type genesisSpecMarshaling struct {
   124  	Nonce      math.HexOrDecimal64
   125  	Timestamp  math.HexOrDecimal64
   126  	ExtraData  hexutil.Bytes
   127  	GasLimit   math.HexOrDecimal64
   128  	GasUsed    math.HexOrDecimal64
   129  	Number     math.HexOrDecimal64
   130  	Difficulty *math.HexOrDecimal256
   131  	Alloc      map[common.UnprefixedAddress]GenesisAccount
   132  }
   133  
   134  type genesisAccountMarshaling struct {
   135  	Code       hexutil.Bytes
   136  	Balance    *math.HexOrDecimal256
   137  	Nonce      math.HexOrDecimal64
   138  	Amount     *math.HexOrDecimal256
   139  	Storage    map[storageJSON]storageJSON
   140  	PrivateKey hexutil.Bytes
   141  }
   142  
   143  // storageJSON represents a 256 bit byte array, but allows less than 256 bits when
   144  // unmarshaling from hex.
   145  type storageJSON common.Hash
   146  
   147  func (h *storageJSON) UnmarshalText(text []byte) error {
   148  	text = bytes.TrimPrefix(text, []byte("0x"))
   149  	if len(text) > 64 {
   150  		return fmt.Errorf("too many hex characters in storage key/value %q", text)
   151  	}
   152  	offset := len(h) - len(text)/2 // pad on the left
   153  	if _, err := hex.Decode(h[offset:], text); err != nil {
   154  		return fmt.Errorf("invalid hex storage key/value %q", text)
   155  	}
   156  	return nil
   157  }
   158  
   159  func (h storageJSON) MarshalText() ([]byte, error) {
   160  	return hexutil.Bytes(h[:]).MarshalText()
   161  }
   162  
   163  // GenesisMismatchError is raised when trying to overwrite an existing
   164  // genesis block with an incompatible one.
   165  type GenesisMismatchError struct {
   166  	Stored, New common.Hash
   167  }
   168  
   169  func (e *GenesisMismatchError) Error() string {
   170  	return fmt.Sprintf("database already contains an incompatible genesis block (have %x, new %x)", e.Stored[:8], e.New[:8])
   171  }
   172  
   173  // SetupGenesisBlock writes or updates the genesis block in db.
   174  // The block that will be used is:
   175  //
   176  //                          genesis == nil       genesis != nil
   177  //                       +------------------------------------------
   178  //     db has no genesis |  main-net default  |  genesis
   179  //     db has genesis    |  from DB           |  genesis (if compatible)
   180  //
   181  // The stored chain configuration will be updated if it is compatible (i.e. does not
   182  // specify a fork block below the local head block). In case of a conflict, the
   183  // error is a *params.ConfigCompatError and the new, unwritten config is returned.
   184  //
   185  // The returned chain configuration is never nil.
   186  func SetupGenesisBlock(db intdb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) {
   187  	if genesis != nil && genesis.Config == nil {
   188  		return nil, common.Hash{}, errGenesisNoConfig
   189  	}
   190  
   191  	// Just commit the new block if there is no stored genesis block.
   192  	stored := rawdb.ReadCanonicalHash(db, 0)
   193  	if (stored == common.Hash{}) {
   194  		if genesis == nil {
   195  			log.Info("Writing default main-net genesis block")
   196  			genesis = DefaultGenesisBlock()
   197  		} else {
   198  			log.Info("Writing custom genesis block")
   199  		}
   200  		block, err := genesis.Commit(db)
   201  		return genesis.Config, block.Hash(), err
   202  	}
   203  
   204  	// Check whether the genesis block is already written.
   205  	if genesis != nil {
   206  		hash := genesis.ToBlock(nil).Hash()
   207  		if hash != stored {
   208  			return genesis.Config, hash, &GenesisMismatchError{stored, hash}
   209  		}
   210  	}
   211  
   212  	// Get the existing chain configuration.
   213  	newcfg := genesis.configOrDefault(stored)
   214  	storedcfg := rawdb.ReadChainConfig(db, stored)
   215  	if storedcfg == nil {
   216  		log.Warn("Found genesis block without chain config")
   217  		rawdb.WriteChainConfig(db, stored, newcfg)
   218  		return newcfg, stored, nil
   219  	}
   220  	// Special case: don't change the existing config of a non-mainnet chain if no new
   221  	// config is supplied. These chains would get AllProtocolChanges (and a compat error)
   222  	// if we just continued here.
   223  	if genesis == nil && stored != params.MainnetGenesisHash {
   224  		return storedcfg, stored, nil
   225  	}
   226  
   227  	// Check config compatibility and write the config. Compatibility errors
   228  	// are returned to the caller unless we're already at block zero.
   229  	height := rawdb.ReadHeaderNumber(db, rawdb.ReadHeadHeaderHash(db))
   230  	if height == nil {
   231  		return newcfg, stored, fmt.Errorf("missing block number for head header hash")
   232  	}
   233  	compatErr := storedcfg.CheckCompatible(newcfg, *height)
   234  	if compatErr != nil && *height != 0 && compatErr.RewindTo != 0 {
   235  		return newcfg, stored, compatErr
   236  	}
   237  	rawdb.WriteChainConfig(db, stored, newcfg)
   238  	return newcfg, stored, nil
   239  }
   240  
   241  func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
   242  	switch {
   243  	case g != nil:
   244  		return g.Config
   245  	case ghash == params.MainnetGenesisHash:
   246  		return params.MainnetChainConfig
   247  	case ghash == params.TestnetGenesisHash:
   248  		return params.TestnetChainConfig
   249  	default:
   250  		return nil
   251  	}
   252  }
   253  
   254  // ToBlock creates the genesis block and writes state of a genesis specification
   255  // to the given database (or discards it if nil).
   256  func (g *Genesis) ToBlock(db intdb.Database) *types.Block {
   257  	if db == nil {
   258  		db = rawdb.NewMemoryDatabase()
   259  	}
   260  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
   261  	for addr, account := range g.Alloc {
   262  		statedb.AddBalance(addr, account.Balance)
   263  		// Deposit Balance for POS
   264  		statedb.AddDepositBalance(addr, account.Amount)
   265  
   266  		// Delegate Balance
   267  		if account.DelegateBalance != nil {
   268  			statedb.AddDelegateBalance(addr, account.DelegateBalance)
   269  		}
   270  
   271  		// Deposit Proxied Detail
   272  		if account.DepositProxiedDetail != nil {
   273  			for proxiedAddr, depositProxiedBalance := range account.DepositProxiedDetail {
   274  				statedb.AddDepositProxiedBalanceByUser(addr, proxiedAddr, depositProxiedBalance)
   275  			}
   276  		}
   277  
   278  		// Candidate, set empty pubkey for genesis candidate
   279  		if account.Candidate {
   280  			statedb.ApplyForCandidate(addr, "", account.Commission)
   281  		}
   282  
   283  		statedb.SetCode(addr, account.Code)
   284  		statedb.SetNonce(addr, account.Nonce)
   285  		for key, value := range account.Storage {
   286  			statedb.SetState(addr, key, value)
   287  		}
   288  	}
   289  	root := statedb.IntermediateRoot(false)
   290  	head := &types.Header{
   291  		Number:     new(big.Int).SetUint64(g.Number),
   292  		Nonce:      types.EncodeNonce(g.Nonce),
   293  		Time:       new(big.Int).SetUint64(g.Timestamp),
   294  		ParentHash: g.ParentHash,
   295  		Extra:      g.ExtraData,
   296  		GasLimit:   g.GasLimit,
   297  		GasUsed:    g.GasUsed,
   298  		Difficulty: g.Difficulty,
   299  		MixDigest:  g.Mixhash,
   300  		Coinbase:   g.Coinbase,
   301  		Root:       root,
   302  	}
   303  	if g.GasLimit == 0 {
   304  		head.GasLimit = params.GenesisGasLimit
   305  	}
   306  	if g.Difficulty == nil {
   307  		head.Difficulty = params.GenesisDifficulty
   308  	}
   309  	statedb.Commit(false)
   310  	statedb.Database().TrieDB().Commit(root, true)
   311  
   312  	return types.NewBlock(head, nil, nil, nil)
   313  }
   314  
   315  // Commit writes the block and state of a genesis specification to the database.
   316  // The block is committed as the canonical head block.
   317  func (g *Genesis) Commit(db intdb.Database) (*types.Block, error) {
   318  	block := g.ToBlock(db)
   319  	if block.Number().Sign() != 0 {
   320  		return nil, fmt.Errorf("can't commit genesis block with number > 0")
   321  	}
   322  	rawdb.WriteTd(db, block.Hash(), block.NumberU64(), g.Difficulty)
   323  	rawdb.WriteBlock(db, block)
   324  	rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil)
   325  	rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64())
   326  	rawdb.WriteHeadBlockHash(db, block.Hash())
   327  	rawdb.WriteHeadHeaderHash(db, block.Hash())
   328  
   329  	config := g.Config
   330  
   331  	rawdb.WriteChainConfig(db, block.Hash(), config)
   332  	return block, nil
   333  }
   334  
   335  // MustCommit writes the genesis block and state to db, panicking on error.
   336  // The block is committed as the canonical head block.
   337  func (g *Genesis) MustCommit(db intdb.Database) *types.Block {
   338  	block, err := g.Commit(db)
   339  	if err != nil {
   340  		panic(err)
   341  	}
   342  	return block
   343  }
   344  
   345  // GenesisBlockForTesting creates and writes a block in which addr has the given wei balance.
   346  func GenesisBlockForTesting(db intdb.Database, addr common.Address, balance *big.Int) *types.Block {
   347  	g := Genesis{Alloc: GenesisAlloc{addr: {Balance: balance}}}
   348  	return g.MustCommit(db)
   349  }
   350  
   351  // DefaultGenesisBlock returns the Ethereum main net genesis block.
   352  func DefaultGenesisBlock() *Genesis {
   353  	return &Genesis{
   354  		Config:     params.MainnetChainConfig,
   355  		Nonce:      66,
   356  		ExtraData:  hexutil.MustDecode("0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"),
   357  		GasLimit:   5000,
   358  		Difficulty: big.NewInt(17179869184),
   359  		Alloc:      decodePrealloc(mainnetAllocData),
   360  	}
   361  }
   362  
   363  // DefaultTestnetGenesisBlock returns the Ropsten network genesis block.
   364  func DefaultTestnetGenesisBlock() *Genesis {
   365  	return &Genesis{
   366  		Config:     params.TestnetChainConfig,
   367  		Nonce:      66,
   368  		ExtraData:  hexutil.MustDecode("0x3535353535353535353535353535353535353535353535353535353535353535"),
   369  		GasLimit:   16777216,
   370  		Difficulty: big.NewInt(1048576),
   371  		Alloc:      decodePrealloc(testnetAllocData),
   372  	}
   373  }
   374  
   375  func decodePrealloc(data string) GenesisAlloc {
   376  	var p []struct{ Addr, Balance *big.Int }
   377  	if err := rlp.NewStream(strings.NewReader(data), 0).Decode(&p); err != nil {
   378  		panic(err)
   379  	}
   380  	ga := make(GenesisAlloc, len(p))
   381  	for _, account := range p {
   382  		ga[common.BigToAddress(account.Addr)] = GenesisAccount{Balance: account.Balance}
   383  	}
   384  	return ga
   385  }