github.com/dim4egster/coreth@v0.10.2/core/genesis.go (about)

     1  // (c) 2019-2020, Ava Labs, Inc.
     2  //
     3  // This file is a derived work, based on the go-ethereum library whose original
     4  // notices appear below.
     5  //
     6  // It is distributed under a license compatible with the licensing terms of the
     7  // original code from which it is derived.
     8  //
     9  // Much love to the original authors for their work.
    10  // **********
    11  // Copyright 2014 The go-ethereum Authors
    12  // This file is part of the go-ethereum library.
    13  //
    14  // The go-ethereum library is free software: you can redistribute it and/or modify
    15  // it under the terms of the GNU Lesser General Public License as published by
    16  // the Free Software Foundation, either version 3 of the License, or
    17  // (at your option) any later version.
    18  //
    19  // The go-ethereum library is distributed in the hope that it will be useful,
    20  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    22  // GNU Lesser General Public License for more details.
    23  //
    24  // You should have received a copy of the GNU Lesser General Public License
    25  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    26  
    27  package core
    28  
    29  import (
    30  	"bytes"
    31  	"encoding/hex"
    32  	"encoding/json"
    33  	"errors"
    34  	"fmt"
    35  	"math/big"
    36  
    37  	"github.com/dim4egster/coreth/core/rawdb"
    38  	"github.com/dim4egster/coreth/core/state"
    39  	"github.com/dim4egster/coreth/core/types"
    40  	"github.com/dim4egster/coreth/ethdb"
    41  	"github.com/dim4egster/coreth/params"
    42  	"github.com/dim4egster/coreth/trie"
    43  	"github.com/ethereum/go-ethereum/common"
    44  	"github.com/ethereum/go-ethereum/common/hexutil"
    45  	"github.com/ethereum/go-ethereum/common/math"
    46  	"github.com/ethereum/go-ethereum/log"
    47  )
    48  
    49  //go:generate go run github.com/fjl/gencodec -type Genesis -field-override genesisSpecMarshaling -out gen_genesis.go
    50  //go:generate go run github.com/fjl/gencodec -type GenesisAccount -field-override genesisAccountMarshaling -out gen_genesis_account.go
    51  
    52  var errGenesisNoConfig = errors.New("genesis has no chain configuration")
    53  
    54  // Genesis specifies the header fields, state of a genesis block. It also defines hard
    55  // fork switch-over blocks through the chain configuration.
    56  type Genesis struct {
    57  	Config     *params.ChainConfig `json:"config"`
    58  	Nonce      uint64              `json:"nonce"`
    59  	Timestamp  uint64              `json:"timestamp"`
    60  	ExtraData  []byte              `json:"extraData"`
    61  	GasLimit   uint64              `json:"gasLimit"   gencodec:"required"`
    62  	Difficulty *big.Int            `json:"difficulty" gencodec:"required"`
    63  	Mixhash    common.Hash         `json:"mixHash"`
    64  	Coinbase   common.Address      `json:"coinbase"`
    65  	Alloc      GenesisAlloc        `json:"alloc"      gencodec:"required"`
    66  
    67  	// These fields are used for consensus tests. Please don't use them
    68  	// in actual genesis blocks.
    69  	Number     uint64      `json:"number"`
    70  	GasUsed    uint64      `json:"gasUsed"`
    71  	ParentHash common.Hash `json:"parentHash"`
    72  	BaseFee    *big.Int    `json:"baseFeePerGas"`
    73  }
    74  
    75  // GenesisAlloc specifies the initial state that is part of the genesis block.
    76  type GenesisAlloc map[common.Address]GenesisAccount
    77  
    78  func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error {
    79  	m := make(map[common.UnprefixedAddress]GenesisAccount)
    80  	if err := json.Unmarshal(data, &m); err != nil {
    81  		return err
    82  	}
    83  	*ga = make(GenesisAlloc)
    84  	for addr, a := range m {
    85  		(*ga)[common.Address(addr)] = a
    86  	}
    87  	return nil
    88  }
    89  
    90  type GenesisMultiCoinBalance map[common.Hash]*big.Int
    91  
    92  // GenesisAccount is an account in the state of the genesis block.
    93  type GenesisAccount struct {
    94  	Code       []byte                      `json:"code,omitempty"`
    95  	Storage    map[common.Hash]common.Hash `json:"storage,omitempty"`
    96  	Balance    *big.Int                    `json:"balance" gencodec:"required"`
    97  	MCBalance  GenesisMultiCoinBalance     `json:"mcbalance,omitempty"`
    98  	Nonce      uint64                      `json:"nonce,omitempty"`
    99  	PrivateKey []byte                      `json:"secretKey,omitempty"` // for tests
   100  }
   101  
   102  // field type overrides for gencodec
   103  type genesisSpecMarshaling struct {
   104  	Nonce      math.HexOrDecimal64
   105  	Timestamp  math.HexOrDecimal64
   106  	ExtraData  hexutil.Bytes
   107  	GasLimit   math.HexOrDecimal64
   108  	GasUsed    math.HexOrDecimal64
   109  	Number     math.HexOrDecimal64
   110  	Difficulty *math.HexOrDecimal256
   111  	BaseFee    *math.HexOrDecimal256
   112  	Alloc      map[common.UnprefixedAddress]GenesisAccount
   113  }
   114  
   115  type genesisAccountMarshaling struct {
   116  	Code       hexutil.Bytes
   117  	Balance    *math.HexOrDecimal256
   118  	Nonce      math.HexOrDecimal64
   119  	Storage    map[storageJSON]storageJSON
   120  	PrivateKey hexutil.Bytes
   121  }
   122  
   123  // storageJSON represents a 256 bit byte array, but allows less than 256 bits when
   124  // unmarshaling from hex.
   125  type storageJSON common.Hash
   126  
   127  func (h *storageJSON) UnmarshalText(text []byte) error {
   128  	text = bytes.TrimPrefix(text, []byte("0x"))
   129  	if len(text) > 64 {
   130  		return fmt.Errorf("too many hex characters in storage key/value %q", text)
   131  	}
   132  	offset := len(h) - len(text)/2 // pad on the left
   133  	if _, err := hex.Decode(h[offset:], text); err != nil {
   134  		fmt.Println(err)
   135  		return fmt.Errorf("invalid hex storage key/value %q", text)
   136  	}
   137  	return nil
   138  }
   139  
   140  func (h storageJSON) MarshalText() ([]byte, error) {
   141  	return hexutil.Bytes(h[:]).MarshalText()
   142  }
   143  
   144  // GenesisMismatchError is raised when trying to overwrite an existing
   145  // genesis block with an incompatible one.
   146  type GenesisMismatchError struct {
   147  	Stored, New common.Hash
   148  }
   149  
   150  func (e *GenesisMismatchError) Error() string {
   151  	return fmt.Sprintf("database contains incompatible genesis (have %x, new %x)", e.Stored, e.New)
   152  }
   153  
   154  // SetupGenesisBlock writes or updates the genesis block in db.
   155  // The block that will be used is:
   156  //
   157  //	                     genesis == nil       genesis != nil
   158  //	                  +------------------------------------------
   159  //	db has no genesis |  main-net default  |  genesis
   160  //	db has genesis    |  from DB           |  genesis (if compatible)
   161  //
   162  // The stored chain configuration will be updated if it is compatible (i.e. does not
   163  // specify a fork block below the local head block). In case of a conflict, the
   164  // error is a *params.ConfigCompatError and the new, unwritten config is returned.
   165  func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, error) {
   166  	if genesis == nil {
   167  		return nil, ErrNoGenesis
   168  	}
   169  	if genesis.Config == nil {
   170  		return nil, errGenesisNoConfig
   171  	}
   172  	// Just commit the new block if there is no stored genesis block.
   173  	stored := rawdb.ReadCanonicalHash(db, 0)
   174  	if (stored == common.Hash{}) {
   175  		log.Info("Writing genesis to database")
   176  		_, err := genesis.Commit(db)
   177  		if err != nil {
   178  			return genesis.Config, err
   179  		}
   180  		return genesis.Config, nil
   181  	}
   182  	// We have the genesis block in database but the corresponding state is missing.
   183  	header := rawdb.ReadHeader(db, stored, 0)
   184  	if _, err := state.New(header.Root, state.NewDatabase(db), nil); err != nil {
   185  		// Ensure the stored genesis matches with the given one.
   186  		hash := genesis.ToBlock(nil).Hash()
   187  		if hash != stored {
   188  			return genesis.Config, &GenesisMismatchError{stored, hash}
   189  		}
   190  		_, err := genesis.Commit(db)
   191  		return genesis.Config, err
   192  	}
   193  	// Check whether the genesis block is already written.
   194  	hash := genesis.ToBlock(nil).Hash()
   195  	if hash != stored {
   196  		return genesis.Config, &GenesisMismatchError{stored, hash}
   197  	}
   198  	// Get the existing chain configuration.
   199  	newcfg := genesis.Config
   200  	if err := newcfg.CheckConfigForkOrder(); err != nil {
   201  		return newcfg, err
   202  	}
   203  	storedcfg := rawdb.ReadChainConfig(db, stored)
   204  	if storedcfg == nil {
   205  		log.Warn("Found genesis block without chain config")
   206  		rawdb.WriteChainConfig(db, stored, newcfg)
   207  		return newcfg, nil
   208  	}
   209  
   210  	// Check config compatibility and write the config. Compatibility errors
   211  	// are returned to the caller unless we're already at block zero.
   212  	headBlock := rawdb.ReadHeadBlock(db)
   213  	if headBlock == nil {
   214  		return newcfg, fmt.Errorf("missing head block")
   215  	}
   216  	height := headBlock.NumberU64()
   217  	timestamp := headBlock.Time()
   218  	compatErr := storedcfg.CheckCompatible(newcfg, height, timestamp)
   219  	if compatErr != nil && height != 0 && compatErr.RewindTo != 0 {
   220  		return newcfg, compatErr
   221  	}
   222  	rawdb.WriteChainConfig(db, stored, newcfg)
   223  	return newcfg, nil
   224  }
   225  
   226  // ToBlock creates the genesis block and writes state of a genesis specification
   227  // to the given database (or discards it if nil).
   228  func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
   229  	if db == nil {
   230  		db = rawdb.NewMemoryDatabase()
   231  	}
   232  	statedb, err := state.New(common.Hash{}, state.NewDatabase(db), nil)
   233  	if err != nil {
   234  		panic(err)
   235  	}
   236  
   237  	head := &types.Header{
   238  		Number:     new(big.Int).SetUint64(g.Number),
   239  		Nonce:      types.EncodeNonce(g.Nonce),
   240  		Time:       g.Timestamp,
   241  		ParentHash: g.ParentHash,
   242  		Extra:      g.ExtraData,
   243  		GasLimit:   g.GasLimit,
   244  		GasUsed:    g.GasUsed,
   245  		BaseFee:    g.BaseFee,
   246  		Difficulty: g.Difficulty,
   247  		MixDigest:  g.Mixhash,
   248  		Coinbase:   g.Coinbase,
   249  	}
   250  
   251  	// Configure any stateful precompiles that should be enabled in the genesis.
   252  	g.Config.CheckConfigurePrecompiles(nil, types.NewBlockWithHeader(head), statedb)
   253  
   254  	for addr, account := range g.Alloc {
   255  		statedb.AddBalance(addr, account.Balance)
   256  		statedb.SetCode(addr, account.Code)
   257  		statedb.SetNonce(addr, account.Nonce)
   258  		for key, value := range account.Storage {
   259  			statedb.SetState(addr, key, value)
   260  		}
   261  		if account.MCBalance != nil {
   262  			for coinID, value := range account.MCBalance {
   263  				statedb.AddBalanceMultiCoin(addr, coinID, value)
   264  			}
   265  		}
   266  	}
   267  	root := statedb.IntermediateRoot(false)
   268  	head.Root = root
   269  
   270  	if g.GasLimit == 0 {
   271  		head.GasLimit = params.GenesisGasLimit
   272  	}
   273  	if g.Difficulty == nil {
   274  		head.Difficulty = params.GenesisDifficulty
   275  	}
   276  	if g.Config != nil && g.Config.IsApricotPhase3(common.Big0) {
   277  		if g.BaseFee != nil {
   278  			head.BaseFee = g.BaseFee
   279  		} else {
   280  			head.BaseFee = big.NewInt(params.ApricotPhase3InitialBaseFee)
   281  		}
   282  	}
   283  	statedb.Commit(false, false)
   284  	if err := statedb.Database().TrieDB().Commit(root, true, nil); err != nil {
   285  		panic(fmt.Sprintf("unable to commit genesis block: %v", err))
   286  	}
   287  
   288  	return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil), nil, false)
   289  }
   290  
   291  // Commit writes the block and state of a genesis specification to the database.
   292  // The block is committed as the canonical head block.
   293  func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
   294  	block := g.ToBlock(db)
   295  	if block.Number().Sign() != 0 {
   296  		return nil, errors.New("can't commit genesis block with number > 0")
   297  	}
   298  	config := g.Config
   299  	if config == nil {
   300  		return nil, errGenesisNoConfig
   301  	}
   302  	if err := config.CheckConfigForkOrder(); err != nil {
   303  		return nil, err
   304  	}
   305  	rawdb.WriteBlock(db, block)
   306  	rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil)
   307  	rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64())
   308  	rawdb.WriteHeadBlockHash(db, block.Hash())
   309  	rawdb.WriteHeadHeaderHash(db, block.Hash())
   310  	rawdb.WriteChainConfig(db, block.Hash(), config)
   311  	return block, nil
   312  }
   313  
   314  // MustCommit writes the genesis block and state to db, panicking on error.
   315  // The block is committed as the canonical head block.
   316  func (g *Genesis) MustCommit(db ethdb.Database) *types.Block {
   317  	block, err := g.Commit(db)
   318  	if err != nil {
   319  		panic(err)
   320  	}
   321  	return block
   322  }
   323  
   324  // GenesisBlockForTesting creates and writes a block in which addr has the given wei balance.
   325  func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block {
   326  	g := Genesis{
   327  		Config:  params.TestChainConfig,
   328  		Alloc:   GenesisAlloc{addr: {Balance: balance}},
   329  		BaseFee: big.NewInt(params.ApricotPhase3InitialBaseFee),
   330  	}
   331  	return g.MustCommit(db)
   332  }