github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/core/genesis.go (about)

     1  package core
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"fmt"
     7  	"math/big"
     8  
     9  	"github.com/unicornultrafoundation/go-u2u/common"
    10  	"github.com/unicornultrafoundation/go-u2u/common/hexutil"
    11  	"github.com/unicornultrafoundation/go-u2u/common/math"
    12  	"github.com/unicornultrafoundation/go-u2u/core/rawdb"
    13  	"github.com/unicornultrafoundation/go-u2u/core/state"
    14  	"github.com/unicornultrafoundation/go-u2u/core/types"
    15  	"github.com/unicornultrafoundation/go-u2u/crypto"
    16  	"github.com/unicornultrafoundation/go-u2u/ethdb"
    17  	"github.com/unicornultrafoundation/go-u2u/params"
    18  	"github.com/unicornultrafoundation/go-u2u/trie"
    19  )
    20  
    21  // Genesis specifies the header fields, state of a genesis block. It also defines hard
    22  // fork switch-over blocks through the chain configuration.
    23  type Genesis struct {
    24  	Config     *params.ChainConfig `json:"config"`
    25  	Nonce      uint64              `json:"nonce"`
    26  	Timestamp  uint64              `json:"timestamp"`
    27  	ExtraData  []byte              `json:"extraData"`
    28  	GasLimit   uint64              `json:"gasLimit"   gencodec:"required"`
    29  	Difficulty *big.Int            `json:"difficulty" gencodec:"required"`
    30  	Mixhash    common.Hash         `json:"mixHash"`
    31  	Coinbase   common.Address      `json:"coinbase"`
    32  	Alloc      GenesisAlloc        `json:"alloc"      gencodec:"required"`
    33  
    34  	// These fields are used for consensus tests. Please don't use them
    35  	// in actual genesis blocks.
    36  	Number        uint64      `json:"number"`
    37  	GasUsed       uint64      `json:"gasUsed"`
    38  	ParentHash    common.Hash `json:"parentHash"`
    39  	BaseFee       *big.Int    `json:"baseFeePerGas"` // EIP-1559
    40  	ExcessBlobGas *uint64     `json:"excessBlobGas"` // EIP-4844
    41  	BlobGasUsed   *uint64     `json:"blobGasUsed"`   // EIP-4844
    42  }
    43  
    44  // ToBlock creates the genesis block and writes state of a genesis specification
    45  // to the given database (or discards it if nil).
    46  func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
    47  	if db == nil {
    48  		db = rawdb.NewMemoryDatabase()
    49  	}
    50  	statedb, err := state.New(common.Hash{}, state.NewDatabase(db), nil)
    51  	if err != nil {
    52  		panic(err)
    53  	}
    54  	for addr, account := range g.Alloc {
    55  		statedb.AddBalance(addr, account.Balance)
    56  		statedb.SetCode(addr, account.Code)
    57  		statedb.SetNonce(addr, account.Nonce)
    58  		for key, value := range account.Storage {
    59  			statedb.SetState(addr, key, value)
    60  		}
    61  	}
    62  	root := statedb.IntermediateRoot(false)
    63  	head := &types.Header{
    64  		Number:     new(big.Int).SetUint64(g.Number),
    65  		Nonce:      types.EncodeNonce(g.Nonce),
    66  		Time:       g.Timestamp,
    67  		ParentHash: g.ParentHash,
    68  		Extra:      g.ExtraData,
    69  		GasLimit:   g.GasLimit,
    70  		GasUsed:    g.GasUsed,
    71  		BaseFee:    g.BaseFee,
    72  		Difficulty: g.Difficulty,
    73  		MixDigest:  g.Mixhash,
    74  		Coinbase:   g.Coinbase,
    75  		Root:       root,
    76  	}
    77  	if g.GasLimit == 0 {
    78  		head.GasLimit = params.GenesisGasLimit
    79  	}
    80  	if g.Difficulty == nil {
    81  		head.Difficulty = params.GenesisDifficulty
    82  	}
    83  	if g.Config != nil && g.Config.IsLondon(common.Big0) {
    84  		if g.BaseFee != nil {
    85  			head.BaseFee = g.BaseFee
    86  		} else {
    87  			head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee)
    88  		}
    89  	}
    90  	statedb.Commit(false)
    91  	statedb.Database().TrieDB().Commit(root, true, nil)
    92  
    93  	return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil))
    94  }
    95  
    96  // Commit writes the block and state of a genesis specification to the database.
    97  // The block is committed as the canonical head block.
    98  func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
    99  	block := g.ToBlock(db)
   100  	if block.Number().Sign() != 0 {
   101  		return nil, fmt.Errorf("can't commit genesis block with number > 0")
   102  	}
   103  	config := g.Config
   104  	if config == nil {
   105  		config = params.AllProtocolChanges
   106  	}
   107  	if err := config.CheckConfigForkOrder(); err != nil {
   108  		return nil, err
   109  	}
   110  	rawdb.WriteTd(db, block.Hash(), block.NumberU64(), g.Difficulty)
   111  	rawdb.WriteBlock(db, block)
   112  	rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil)
   113  	rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64())
   114  	rawdb.WriteHeadBlockHash(db, block.Hash())
   115  	rawdb.WriteHeadFastBlockHash(db, block.Hash())
   116  	rawdb.WriteHeadHeaderHash(db, block.Hash())
   117  	rawdb.WriteChainConfig(db, block.Hash(), config)
   118  	return block, nil
   119  }
   120  
   121  // MustCommit writes the genesis block and state to db, panicking on error.
   122  // The block is committed as the canonical head block.
   123  func (g *Genesis) MustCommit(db ethdb.Database) *types.Block {
   124  	block, err := g.Commit(db)
   125  	if err != nil {
   126  		panic(err)
   127  	}
   128  	return block
   129  }
   130  
   131  // GenesisBlockForTesting creates and writes a block in which addr has the given wei balance.
   132  func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block {
   133  	g := Genesis{
   134  		Alloc:   GenesisAlloc{addr: {Balance: balance}},
   135  		BaseFee: big.NewInt(params.InitialBaseFee),
   136  	}
   137  	return g.MustCommit(db)
   138  }
   139  
   140  // DeveloperGenesisBlock returns the 'geth --dev' genesis block.
   141  func DeveloperGenesisBlock(faucet common.Address) *Genesis {
   142  	// Assemble and return the genesis with the precompiles and faucet pre-funded
   143  	return &Genesis{
   144  		Config:     params.AllProtocolChanges,
   145  		ExtraData:  append(append(make([]byte, 32), faucet[:]...), make([]byte, crypto.SignatureLength)...),
   146  		GasLimit:   11500000,
   147  		BaseFee:    big.NewInt(params.InitialBaseFee),
   148  		Difficulty: big.NewInt(1),
   149  		Alloc: map[common.Address]GenesisAccount{
   150  			common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, // ECRecover
   151  			common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, // SHA256
   152  			common.BytesToAddress([]byte{3}): {Balance: big.NewInt(1)}, // RIPEMD
   153  			common.BytesToAddress([]byte{4}): {Balance: big.NewInt(1)}, // Identity
   154  			common.BytesToAddress([]byte{5}): {Balance: big.NewInt(1)}, // ModExp
   155  			common.BytesToAddress([]byte{6}): {Balance: big.NewInt(1)}, // ECAdd
   156  			common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
   157  			common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
   158  			common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b
   159  			faucet:                           {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))},
   160  		},
   161  	}
   162  }
   163  
   164  // GenesisAlloc specifies the initial state that is part of the genesis block.
   165  type GenesisAlloc map[common.Address]GenesisAccount
   166  
   167  // GenesisAccount is an account in the state of the genesis block.
   168  type GenesisAccount struct {
   169  	Code       []byte                      `json:"code,omitempty"`
   170  	Storage    map[common.Hash]common.Hash `json:"storage,omitempty"`
   171  	Balance    *big.Int                    `json:"balance" gencodec:"required"`
   172  	Nonce      uint64                      `json:"nonce,omitempty"`
   173  	PrivateKey []byte                      `json:"secretKey,omitempty"` // for tests
   174  }
   175  
   176  // field type overrides for gencodec
   177  type genesisSpecMarshaling struct {
   178  	Nonce      math.HexOrDecimal64
   179  	Timestamp  math.HexOrDecimal64
   180  	ExtraData  hexutil.Bytes
   181  	GasLimit   math.HexOrDecimal64
   182  	GasUsed    math.HexOrDecimal64
   183  	Number     math.HexOrDecimal64
   184  	Difficulty *math.HexOrDecimal256
   185  	BaseFee    *math.HexOrDecimal256
   186  	Alloc      map[common.UnprefixedAddress]GenesisAccount
   187  }
   188  
   189  type genesisAccountMarshaling struct {
   190  	Code       hexutil.Bytes
   191  	Balance    *math.HexOrDecimal256
   192  	Nonce      math.HexOrDecimal64
   193  	Storage    map[storageJSON]storageJSON
   194  	PrivateKey hexutil.Bytes
   195  }
   196  
   197  // storageJSON represents a 256 bit byte array, but allows less than 256 bits when
   198  // unmarshaling from hex.
   199  type storageJSON common.Hash
   200  
   201  func (h *storageJSON) UnmarshalText(text []byte) error {
   202  	text = bytes.TrimPrefix(text, []byte("0x"))
   203  	if len(text) > 64 {
   204  		return fmt.Errorf("too many hex characters in storage key/value %q", text)
   205  	}
   206  	offset := len(h) - len(text)/2 // pad on the left
   207  	if _, err := hex.Decode(h[offset:], text); err != nil {
   208  		fmt.Println(err)
   209  		return fmt.Errorf("invalid hex storage key/value %q", text)
   210  	}
   211  	return nil
   212  }
   213  
   214  func (h storageJSON) MarshalText() ([]byte, error) {
   215  	return hexutil.Bytes(h[:]).MarshalText()
   216  }