github.com/MetalBlockchain/subnet-evm@v0.4.9/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  	_ "embed"
    32  	"encoding/hex"
    33  	"encoding/json"
    34  	"errors"
    35  	"fmt"
    36  	"math/big"
    37  	"time"
    38  
    39  	"github.com/MetalBlockchain/subnet-evm/core/rawdb"
    40  	"github.com/MetalBlockchain/subnet-evm/core/state"
    41  	"github.com/MetalBlockchain/subnet-evm/core/types"
    42  	"github.com/MetalBlockchain/subnet-evm/ethdb"
    43  	"github.com/MetalBlockchain/subnet-evm/params"
    44  	"github.com/MetalBlockchain/subnet-evm/trie"
    45  	"github.com/ethereum/go-ethereum/common"
    46  	"github.com/ethereum/go-ethereum/common/hexutil"
    47  	"github.com/ethereum/go-ethereum/common/math"
    48  	"github.com/ethereum/go-ethereum/crypto"
    49  	"github.com/ethereum/go-ethereum/log"
    50  )
    51  
    52  //go:generate go run github.com/fjl/gencodec -type Genesis -field-override genesisSpecMarshaling -out gen_genesis.go
    53  //go:generate go run github.com/fjl/gencodec -type GenesisAccount -field-override genesisAccountMarshaling -out gen_genesis_account.go
    54  
    55  var errGenesisNoConfig = errors.New("genesis has no chain configuration")
    56  
    57  type Airdrop struct {
    58  	// Address strings are hex-formatted common.Address
    59  	Address common.Address `json:"address"`
    60  }
    61  
    62  // Genesis specifies the header fields, state of a genesis block. It also defines hard
    63  // fork switch-over blocks through the chain configuration.
    64  type Genesis struct {
    65  	Config        *params.ChainConfig `json:"config"`
    66  	Nonce         uint64              `json:"nonce"`
    67  	Timestamp     uint64              `json:"timestamp"`
    68  	ExtraData     []byte              `json:"extraData"`
    69  	GasLimit      uint64              `json:"gasLimit"   gencodec:"required"`
    70  	Difficulty    *big.Int            `json:"difficulty" gencodec:"required"`
    71  	Mixhash       common.Hash         `json:"mixHash"`
    72  	Coinbase      common.Address      `json:"coinbase"`
    73  	Alloc         GenesisAlloc        `json:"alloc"      gencodec:"required"`
    74  	AirdropHash   common.Hash         `json:"airdropHash"`
    75  	AirdropAmount *big.Int            `json:"airdropAmount"`
    76  	AirdropData   []byte              `json:"-"` // provided in a separate file, not serialized in this struct.
    77  
    78  	// These fields are used for consensus tests. Please don't use them
    79  	// in actual genesis blocks.
    80  	Number     uint64      `json:"number"`
    81  	GasUsed    uint64      `json:"gasUsed"`
    82  	ParentHash common.Hash `json:"parentHash"`
    83  	BaseFee    *big.Int    `json:"baseFeePerGas"`
    84  }
    85  
    86  // GenesisAlloc specifies the initial state that is part of the genesis block.
    87  type GenesisAlloc map[common.Address]GenesisAccount
    88  
    89  func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error {
    90  	m := make(map[common.UnprefixedAddress]GenesisAccount)
    91  	if err := json.Unmarshal(data, &m); err != nil {
    92  		return err
    93  	}
    94  	*ga = make(GenesisAlloc)
    95  	for addr, a := range m {
    96  		(*ga)[common.Address(addr)] = a
    97  	}
    98  	return nil
    99  }
   100  
   101  // GenesisAccount is an account in the state of the genesis block.
   102  type GenesisAccount struct {
   103  	Code       []byte                      `json:"code,omitempty"`
   104  	Storage    map[common.Hash]common.Hash `json:"storage,omitempty"`
   105  	Balance    *big.Int                    `json:"balance" gencodec:"required"`
   106  	Nonce      uint64                      `json:"nonce,omitempty"`
   107  	PrivateKey []byte                      `json:"secretKey,omitempty"` // for tests
   108  }
   109  
   110  // field type overrides for gencodec
   111  type genesisSpecMarshaling struct {
   112  	Nonce         math.HexOrDecimal64
   113  	Timestamp     math.HexOrDecimal64
   114  	ExtraData     hexutil.Bytes
   115  	GasLimit      math.HexOrDecimal64
   116  	GasUsed       math.HexOrDecimal64
   117  	Number        math.HexOrDecimal64
   118  	Difficulty    *math.HexOrDecimal256
   119  	BaseFee       *math.HexOrDecimal256
   120  	Alloc         map[common.UnprefixedAddress]GenesisAccount
   121  	AirdropAmount *math.HexOrDecimal256
   122  }
   123  
   124  type genesisAccountMarshaling struct {
   125  	Code       hexutil.Bytes
   126  	Balance    *math.HexOrDecimal256
   127  	Nonce      math.HexOrDecimal64
   128  	Storage    map[storageJSON]storageJSON
   129  	PrivateKey hexutil.Bytes
   130  }
   131  
   132  // storageJSON represents a 256 bit byte array, but allows less than 256 bits when
   133  // unmarshaling from hex.
   134  type storageJSON common.Hash
   135  
   136  func (h *storageJSON) UnmarshalText(text []byte) error {
   137  	text = bytes.TrimPrefix(text, []byte("0x"))
   138  	if len(text) > 64 {
   139  		return fmt.Errorf("too many hex characters in storage key/value %q", text)
   140  	}
   141  	offset := len(h) - len(text)/2 // pad on the left
   142  	if _, err := hex.Decode(h[offset:], text); err != nil {
   143  		fmt.Println(err)
   144  		return fmt.Errorf("invalid hex storage key/value %q", text)
   145  	}
   146  	return nil
   147  }
   148  
   149  func (h storageJSON) MarshalText() ([]byte, error) {
   150  	return hexutil.Bytes(h[:]).MarshalText()
   151  }
   152  
   153  // GenesisMismatchError is raised when trying to overwrite an existing
   154  // genesis block with an incompatible one.
   155  type GenesisMismatchError struct {
   156  	Stored, New common.Hash
   157  }
   158  
   159  func (e *GenesisMismatchError) Error() string {
   160  	return fmt.Sprintf("database contains incompatible genesis (have %x, new %x)", e.Stored, e.New)
   161  }
   162  
   163  // SetupGenesisBlock writes or updates the genesis block in db.
   164  // The block that will be used is:
   165  //
   166  //	                     genesis == nil       genesis != nil
   167  //	                  +------------------------------------------
   168  //	db has no genesis |  main-net default  |  genesis
   169  //	db has genesis    |  from DB           |  genesis (if compatible)
   170  
   171  // The argument [genesis] must be specified and must contain a valid chain config.
   172  // If the genesis block has already been set up, then we verify the hash matches the genesis passed in
   173  // and that the chain config contained in genesis is backwards compatible with what is stored in the database.
   174  //
   175  // The stored chain configuration will be updated if it is compatible (i.e. does not
   176  // specify a fork block below the local head block). In case of a conflict, the
   177  // error is a *params.ConfigCompatError and the new, unwritten config is returned.
   178  func SetupGenesisBlock(
   179  	db ethdb.Database, genesis *Genesis, lastAcceptedHash common.Hash, skipChainConfigCheckCompatible bool,
   180  ) (*params.ChainConfig, error) {
   181  	if genesis == nil {
   182  		return nil, ErrNoGenesis
   183  	}
   184  	if genesis.Config == nil {
   185  		return nil, errGenesisNoConfig
   186  	}
   187  	// Make sure genesis gas limit is consistent in SubnetEVM fork
   188  	gasLimitConfig := genesis.Config.FeeConfig.GasLimit.Uint64()
   189  	if gasLimitConfig != genesis.GasLimit {
   190  		return nil, fmt.Errorf("gas limit in fee config (%d) does not match gas limit in header (%d)", gasLimitConfig, genesis.GasLimit)
   191  	}
   192  
   193  	// Verify config
   194  	if err := genesis.Config.Verify(); err != nil {
   195  		return nil, err
   196  	}
   197  	// Just commit the new block if there is no stored genesis block.
   198  	stored := rawdb.ReadCanonicalHash(db, 0)
   199  	if (stored == common.Hash{}) {
   200  		log.Info("Writing genesis to database")
   201  		_, err := genesis.Commit(db)
   202  		if err != nil {
   203  			return genesis.Config, err
   204  		}
   205  		return genesis.Config, nil
   206  	}
   207  	// We have the genesis block in database but the corresponding state is missing.
   208  	header := rawdb.ReadHeader(db, stored, 0)
   209  	if _, err := state.New(header.Root, state.NewDatabase(db), nil); err != nil {
   210  		// Ensure the stored genesis matches with the given one.
   211  		hash := genesis.ToBlock(nil).Hash()
   212  		if hash != stored {
   213  			return genesis.Config, &GenesisMismatchError{stored, hash}
   214  		}
   215  		_, err := genesis.Commit(db)
   216  		return genesis.Config, err
   217  	}
   218  	// Check whether the genesis block is already written.
   219  	hash := genesis.ToBlock(nil).Hash()
   220  	if hash != stored {
   221  		return genesis.Config, &GenesisMismatchError{stored, hash}
   222  	}
   223  	// Get the existing chain configuration.
   224  	newcfg := genesis.Config
   225  	if err := newcfg.CheckConfigForkOrder(); err != nil {
   226  		return newcfg, err
   227  	}
   228  	storedcfg := rawdb.ReadChainConfig(db, stored)
   229  	// If there is no previously stored chain config, write the chain config to disk.
   230  	if storedcfg == nil {
   231  		// Note: this can happen since we did not previously write the genesis block and chain config in the same batch.
   232  		log.Warn("Found genesis block without chain config")
   233  		rawdb.WriteChainConfig(db, stored, newcfg)
   234  		return newcfg, nil
   235  	}
   236  
   237  	// Check config compatibility and write the config. Compatibility errors
   238  	// are returned to the caller unless we're already at block zero.
   239  
   240  	// we use last accepted block for cfg compatibility check. Note this allows
   241  	// the node to continue if it previously halted due to attempting to process blocks with
   242  	// an incorrect chain config.
   243  	lastBlock := ReadBlockByHash(db, lastAcceptedHash)
   244  	// this should never happen, but we check anyway
   245  	// when we start syncing from scratch, the last accepted block
   246  	// will be genesis block
   247  	if lastBlock == nil {
   248  		return newcfg, fmt.Errorf("missing last accepted block")
   249  	}
   250  
   251  	height := lastBlock.NumberU64()
   252  	timestamp := lastBlock.Time()
   253  	if skipChainConfigCheckCompatible {
   254  		log.Info("skipping verifying activated network upgrades on chain config")
   255  	} else {
   256  		compatErr := storedcfg.CheckCompatible(newcfg, height, timestamp)
   257  		if compatErr != nil && height != 0 && compatErr.RewindTo != 0 {
   258  			return newcfg, compatErr
   259  		}
   260  	}
   261  	rawdb.WriteChainConfig(db, stored, newcfg)
   262  	return newcfg, nil
   263  }
   264  
   265  // ToBlock creates the genesis block and writes state of a genesis specification
   266  // to the given database (or discards it if nil).
   267  func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
   268  	if db == nil {
   269  		db = rawdb.NewMemoryDatabase()
   270  	}
   271  	statedb, err := state.New(common.Hash{}, state.NewDatabase(db), nil)
   272  	if err != nil {
   273  		panic(err)
   274  	}
   275  	if g.AirdropHash != (common.Hash{}) {
   276  		t := time.Now()
   277  		h := common.BytesToHash(crypto.Keccak256(g.AirdropData))
   278  		if g.AirdropHash != h {
   279  			panic(fmt.Sprintf("expected standard allocation %s but got %s", g.AirdropHash, h))
   280  		}
   281  		airdrop := []*Airdrop{}
   282  		if err := json.Unmarshal(g.AirdropData, &airdrop); err != nil {
   283  			panic(err)
   284  		}
   285  		for _, alloc := range airdrop {
   286  			statedb.SetBalance(alloc.Address, g.AirdropAmount)
   287  		}
   288  		log.Debug(
   289  			"applied airdrop allocation",
   290  			"hash", h, "addrs", len(airdrop), "balance", g.AirdropAmount,
   291  			"t", time.Since(t),
   292  		)
   293  	}
   294  
   295  	head := &types.Header{
   296  		Number:     new(big.Int).SetUint64(g.Number),
   297  		Nonce:      types.EncodeNonce(g.Nonce),
   298  		Time:       g.Timestamp,
   299  		ParentHash: g.ParentHash,
   300  		Extra:      g.ExtraData,
   301  		GasLimit:   g.GasLimit,
   302  		GasUsed:    g.GasUsed,
   303  		BaseFee:    g.BaseFee,
   304  		Difficulty: g.Difficulty,
   305  		MixDigest:  g.Mixhash,
   306  		Coinbase:   g.Coinbase,
   307  	}
   308  
   309  	// Configure any stateful precompiles that should be enabled in the genesis.
   310  	g.Config.CheckConfigurePrecompiles(nil, types.NewBlockWithHeader(head), statedb)
   311  
   312  	// Do custom allocation after airdrop in case an address shows up in standard
   313  	// allocation
   314  	for addr, account := range g.Alloc {
   315  		statedb.SetBalance(addr, account.Balance)
   316  		statedb.SetCode(addr, account.Code)
   317  		statedb.SetNonce(addr, account.Nonce)
   318  		for key, value := range account.Storage {
   319  			statedb.SetState(addr, key, value)
   320  		}
   321  	}
   322  	root := statedb.IntermediateRoot(false)
   323  	head.Root = root
   324  
   325  	if g.GasLimit == 0 {
   326  		head.GasLimit = params.GenesisGasLimit
   327  	}
   328  	if g.Difficulty == nil {
   329  		head.Difficulty = params.GenesisDifficulty
   330  	}
   331  	if g.Config != nil && g.Config.IsSubnetEVM(common.Big0) {
   332  		if g.BaseFee != nil {
   333  			head.BaseFee = g.BaseFee
   334  		} else {
   335  			head.BaseFee = new(big.Int).Set(g.Config.FeeConfig.MinBaseFee)
   336  		}
   337  	}
   338  	statedb.Commit(false, false)
   339  	if err := statedb.Database().TrieDB().Commit(root, true, nil); err != nil {
   340  		panic(fmt.Sprintf("unable to commit genesis block: %v", err))
   341  	}
   342  
   343  	return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil))
   344  }
   345  
   346  // Commit writes the block and state of a genesis specification to the database.
   347  // The block is committed as the canonical head block.
   348  func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
   349  	block := g.ToBlock(db)
   350  	if block.Number().Sign() != 0 {
   351  		return nil, errors.New("can't commit genesis block with number > 0")
   352  	}
   353  	config := g.Config
   354  	if config == nil {
   355  		return nil, errGenesisNoConfig
   356  	}
   357  	if err := config.CheckConfigForkOrder(); err != nil {
   358  		return nil, err
   359  	}
   360  	batch := db.NewBatch()
   361  	rawdb.WriteBlock(batch, block)
   362  	rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), nil)
   363  	rawdb.WriteCanonicalHash(batch, block.Hash(), block.NumberU64())
   364  	rawdb.WriteHeadBlockHash(batch, block.Hash())
   365  	rawdb.WriteHeadHeaderHash(batch, block.Hash())
   366  	rawdb.WriteChainConfig(batch, block.Hash(), config)
   367  	if err := batch.Write(); err != nil {
   368  		return nil, fmt.Errorf("failed to write genesis block: %w", err)
   369  	}
   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 ethdb.Database) *types.Block {
   376  	block, err := g.Commit(db)
   377  	if err != nil {
   378  		panic(err)
   379  	}
   380  	return block
   381  }
   382  
   383  // GenesisBlockForTesting creates and writes a block in which addr has the given wei balance.
   384  func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block {
   385  	g := Genesis{
   386  		Config:  params.TestChainConfig,
   387  		Alloc:   GenesisAlloc{addr: {Balance: balance}},
   388  		BaseFee: new(big.Int).Set(params.TestMaxBaseFee),
   389  	}
   390  	return g.MustCommit(db)
   391  }
   392  
   393  // ReadBlockByHash reads the block with the given hash from the database.
   394  func ReadBlockByHash(db ethdb.Reader, hash common.Hash) *types.Block {
   395  	blockNumber := rawdb.ReadHeaderNumber(db, hash)
   396  	if blockNumber == nil {
   397  		return nil
   398  	}
   399  	return rawdb.ReadBlock(db, hash, *blockNumber)
   400  }