gitlab.com/flarenetwork/coreth@v0.1.1/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/ethereum/go-ethereum/common"
    38  	"github.com/ethereum/go-ethereum/common/hexutil"
    39  	"github.com/ethereum/go-ethereum/common/math"
    40  	"github.com/ethereum/go-ethereum/ethdb"
    41  	"github.com/ethereum/go-ethereum/log"
    42  	"github.com/ethereum/go-ethereum/trie"
    43  	"gitlab.com/flarenetwork/coreth/core/rawdb"
    44  	"gitlab.com/flarenetwork/coreth/core/state"
    45  	"gitlab.com/flarenetwork/coreth/core/types"
    46  	"gitlab.com/flarenetwork/coreth/params"
    47  )
    48  
    49  //go:generate gencodec -type Genesis -field-override genesisSpecMarshaling -out gen_genesis.go
    50  //go:generate 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(perhaps in ancient database)
   183  	// but the corresponding state is missing.
   184  	header := rawdb.ReadHeader(db, stored, 0)
   185  	if _, err := state.New(header.Root, state.NewDatabase(db), nil); err != nil {
   186  		// Ensure the stored genesis matches with the given one.
   187  		hash := genesis.ToBlock(nil).Hash()
   188  		if hash != stored {
   189  			return genesis.Config, &GenesisMismatchError{stored, hash}
   190  		}
   191  		_, err := genesis.Commit(db)
   192  		return genesis.Config, err
   193  	}
   194  	// Check whether the genesis block is already written.
   195  	hash := genesis.ToBlock(nil).Hash()
   196  	if hash != stored {
   197  		return genesis.Config, &GenesisMismatchError{stored, hash}
   198  	}
   199  	// Get the existing chain configuration.
   200  	newcfg := genesis.Config
   201  	if err := newcfg.CheckConfigForkOrder(); err != nil {
   202  		return newcfg, err
   203  	}
   204  	storedcfg := rawdb.ReadChainConfig(db, stored)
   205  	if storedcfg == nil {
   206  		log.Warn("Found genesis block without chain config")
   207  		rawdb.WriteChainConfig(db, stored, newcfg)
   208  		return newcfg, nil
   209  	}
   210  
   211  	// Check config compatibility and write the config. Compatibility errors
   212  	// are returned to the caller unless we're already at block zero.
   213  	height := rawdb.ReadHeaderNumber(db, rawdb.ReadHeadHeaderHash(db))
   214  	if height == nil {
   215  		return newcfg, fmt.Errorf("missing block number for head header hash")
   216  	}
   217  	compatErr := storedcfg.CheckCompatible(newcfg, *height)
   218  	if compatErr != nil && *height != 0 && compatErr.RewindTo != 0 {
   219  		return newcfg, compatErr
   220  	}
   221  	rawdb.WriteChainConfig(db, stored, newcfg)
   222  	return newcfg, nil
   223  }
   224  
   225  // ToBlock creates the genesis block and writes state of a genesis specification
   226  // to the given database (or discards it if nil).
   227  func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
   228  	if db == nil {
   229  		db = rawdb.NewMemoryDatabase()
   230  	}
   231  	statedb, err := state.New(common.Hash{}, state.NewDatabase(db), nil)
   232  	if err != nil {
   233  		panic(err)
   234  	}
   235  	for addr, account := range g.Alloc {
   236  		statedb.AddBalance(addr, account.Balance)
   237  		statedb.SetCode(addr, account.Code)
   238  		statedb.SetNonce(addr, account.Nonce)
   239  		for key, value := range account.Storage {
   240  			statedb.SetState(addr, key, value)
   241  		}
   242  		if account.MCBalance != nil {
   243  			for coinID, value := range account.MCBalance {
   244  				statedb.AddBalanceMultiCoin(addr, coinID, value)
   245  			}
   246  		}
   247  	}
   248  	root := statedb.IntermediateRoot(false)
   249  	head := &types.Header{
   250  		Number:     new(big.Int).SetUint64(g.Number),
   251  		Nonce:      types.EncodeNonce(g.Nonce),
   252  		Time:       g.Timestamp,
   253  		ParentHash: g.ParentHash,
   254  		Extra:      g.ExtraData,
   255  		GasLimit:   g.GasLimit,
   256  		GasUsed:    g.GasUsed,
   257  		BaseFee:    g.BaseFee,
   258  		Difficulty: g.Difficulty,
   259  		MixDigest:  g.Mixhash,
   260  		Coinbase:   g.Coinbase,
   261  		Root:       root,
   262  	}
   263  	if g.GasLimit == 0 {
   264  		head.GasLimit = params.GenesisGasLimit
   265  	}
   266  	if g.Difficulty == nil {
   267  		head.Difficulty = params.GenesisDifficulty
   268  	}
   269  	if g.Config != nil && g.Config.IsApricotPhase3(common.Big0) {
   270  		if g.BaseFee != nil {
   271  			head.BaseFee = g.BaseFee
   272  		} else {
   273  			head.BaseFee = big.NewInt(params.ApricotPhase3InitialBaseFee)
   274  		}
   275  	}
   276  	statedb.Commit(false)
   277  	statedb.Database().TrieDB().Commit(root, true, nil)
   278  
   279  	return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil), nil, false)
   280  }
   281  
   282  // Commit writes the block and state of a genesis specification to the database.
   283  // The block is committed as the canonical head block.
   284  func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
   285  	block := g.ToBlock(db)
   286  	if block.Number().Sign() != 0 {
   287  		return nil, fmt.Errorf("can't commit genesis block with number > 0")
   288  	}
   289  	config := g.Config
   290  	if config == nil {
   291  		return nil, errGenesisNoConfig
   292  	}
   293  	if err := config.CheckConfigForkOrder(); err != nil {
   294  		return nil, err
   295  	}
   296  	rawdb.WriteTd(db, block.Hash(), block.NumberU64(), g.Difficulty)
   297  	rawdb.WriteBlock(db, block)
   298  	rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil)
   299  	rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64())
   300  	rawdb.WriteHeadBlockHash(db, block.Hash())
   301  	rawdb.WriteHeadFastBlockHash(db, block.Hash())
   302  	rawdb.WriteHeadHeaderHash(db, block.Hash())
   303  	rawdb.WriteChainConfig(db, block.Hash(), config)
   304  	return block, nil
   305  }
   306  
   307  // MustCommit writes the genesis block and state to db, panicking on error.
   308  // The block is committed as the canonical head block.
   309  func (g *Genesis) MustCommit(db ethdb.Database) *types.Block {
   310  	block, err := g.Commit(db)
   311  	if err != nil {
   312  		panic(err)
   313  	}
   314  	return block
   315  }
   316  
   317  // GenesisBlockForTesting creates and writes a block in which addr has the given wei balance.
   318  func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block {
   319  	g := Genesis{
   320  		Alloc:   GenesisAlloc{addr: {Balance: balance}},
   321  		BaseFee: big.NewInt(params.ApricotPhase3InitialBaseFee),
   322  	}
   323  	return g.MustCommit(db)
   324  }