github.com/murrekatt/go-ethereum@v1.5.8-0.20170123175102-fc52f2c007fb/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  	"compress/bzip2"
    21  	"compress/gzip"
    22  	"encoding/base64"
    23  	"encoding/json"
    24  	"fmt"
    25  	"io"
    26  	"io/ioutil"
    27  	"math/big"
    28  	"strings"
    29  
    30  	"github.com/ethereum/go-ethereum/common"
    31  	"github.com/ethereum/go-ethereum/core/state"
    32  	"github.com/ethereum/go-ethereum/core/types"
    33  	"github.com/ethereum/go-ethereum/ethdb"
    34  	"github.com/ethereum/go-ethereum/logger"
    35  	"github.com/ethereum/go-ethereum/logger/glog"
    36  	"github.com/ethereum/go-ethereum/params"
    37  )
    38  
    39  // WriteGenesisBlock writes the genesis block to the database as block number 0
    40  func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block, error) {
    41  	contents, err := ioutil.ReadAll(reader)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  
    46  	var genesis struct {
    47  		ChainConfig *params.ChainConfig `json:"config"`
    48  		Nonce       string
    49  		Timestamp   string
    50  		ParentHash  string
    51  		ExtraData   string
    52  		GasLimit    string
    53  		Difficulty  string
    54  		Mixhash     string
    55  		Coinbase    string
    56  		Alloc       map[string]struct {
    57  			Code    string
    58  			Storage map[string]string
    59  			Balance string
    60  		}
    61  	}
    62  
    63  	if err := json.Unmarshal(contents, &genesis); err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	// creating with empty hash always works
    68  	statedb, _ := state.New(common.Hash{}, chainDb)
    69  	for addr, account := range genesis.Alloc {
    70  		address := common.HexToAddress(addr)
    71  		statedb.AddBalance(address, common.String2Big(account.Balance))
    72  		statedb.SetCode(address, common.Hex2Bytes(account.Code))
    73  		for key, value := range account.Storage {
    74  			statedb.SetState(address, common.HexToHash(key), common.HexToHash(value))
    75  		}
    76  	}
    77  	root, stateBatch := statedb.CommitBatch(false)
    78  
    79  	difficulty := common.String2Big(genesis.Difficulty)
    80  	block := types.NewBlock(&types.Header{
    81  		Nonce:      types.EncodeNonce(common.String2Big(genesis.Nonce).Uint64()),
    82  		Time:       common.String2Big(genesis.Timestamp),
    83  		ParentHash: common.HexToHash(genesis.ParentHash),
    84  		Extra:      common.FromHex(genesis.ExtraData),
    85  		GasLimit:   common.String2Big(genesis.GasLimit),
    86  		Difficulty: difficulty,
    87  		MixDigest:  common.HexToHash(genesis.Mixhash),
    88  		Coinbase:   common.HexToAddress(genesis.Coinbase),
    89  		Root:       root,
    90  	}, nil, nil, nil)
    91  
    92  	if block := GetBlock(chainDb, block.Hash(), block.NumberU64()); block != nil {
    93  		glog.V(logger.Info).Infoln("Genesis block already in chain. Writing canonical number")
    94  		err := WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64())
    95  		if err != nil {
    96  			return nil, err
    97  		}
    98  		return block, nil
    99  	}
   100  
   101  	if err := stateBatch.Write(); err != nil {
   102  		return nil, fmt.Errorf("cannot write state: %v", err)
   103  	}
   104  	if err := WriteTd(chainDb, block.Hash(), block.NumberU64(), difficulty); err != nil {
   105  		return nil, err
   106  	}
   107  	if err := WriteBlock(chainDb, block); err != nil {
   108  		return nil, err
   109  	}
   110  	if err := WriteBlockReceipts(chainDb, block.Hash(), block.NumberU64(), nil); err != nil {
   111  		return nil, err
   112  	}
   113  	if err := WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64()); err != nil {
   114  		return nil, err
   115  	}
   116  	if err := WriteHeadBlockHash(chainDb, block.Hash()); err != nil {
   117  		return nil, err
   118  	}
   119  	if err := WriteChainConfig(chainDb, block.Hash(), genesis.ChainConfig); err != nil {
   120  		return nil, err
   121  	}
   122  
   123  	return block, nil
   124  }
   125  
   126  // GenesisBlockForTesting creates a block in which addr has the given wei balance.
   127  // The state trie of the block is written to db. the passed db needs to contain a state root
   128  func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block {
   129  	statedb, _ := state.New(common.Hash{}, db)
   130  	obj := statedb.GetOrNewStateObject(addr)
   131  	obj.SetBalance(balance)
   132  	root, err := statedb.Commit(false)
   133  	if err != nil {
   134  		panic(fmt.Sprintf("cannot write state: %v", err))
   135  	}
   136  	block := types.NewBlock(&types.Header{
   137  		Difficulty: params.GenesisDifficulty,
   138  		GasLimit:   params.GenesisGasLimit,
   139  		Root:       root,
   140  	}, nil, nil, nil)
   141  	return block
   142  }
   143  
   144  type GenesisAccount struct {
   145  	Address common.Address
   146  	Balance *big.Int
   147  }
   148  
   149  func WriteGenesisBlockForTesting(db ethdb.Database, accounts ...GenesisAccount) *types.Block {
   150  	accountJson := "{"
   151  	for i, account := range accounts {
   152  		if i != 0 {
   153  			accountJson += ","
   154  		}
   155  		accountJson += fmt.Sprintf(`"0x%x":{"balance":"0x%x"}`, account.Address, account.Balance.Bytes())
   156  	}
   157  	accountJson += "}"
   158  
   159  	testGenesis := fmt.Sprintf(`{
   160  	"nonce":"0x%x",
   161  	"gasLimit":"0x%x",
   162  	"difficulty":"0x%x",
   163  	"alloc": %s
   164  }`, types.EncodeNonce(0), params.GenesisGasLimit.Bytes(), params.GenesisDifficulty.Bytes(), accountJson)
   165  	block, _ := WriteGenesisBlock(db, strings.NewReader(testGenesis))
   166  	return block
   167  }
   168  
   169  // WriteDefaultGenesisBlock assembles the official Ethereum genesis block and
   170  // writes it - along with all associated state - into a chain database.
   171  func WriteDefaultGenesisBlock(chainDb ethdb.Database) (*types.Block, error) {
   172  	return WriteGenesisBlock(chainDb, strings.NewReader(DefaultGenesisBlock()))
   173  }
   174  
   175  // WriteTestNetGenesisBlock assembles the test network genesis block and
   176  // writes it - along with all associated state - into a chain database.
   177  func WriteTestNetGenesisBlock(chainDb ethdb.Database) (*types.Block, error) {
   178  	return WriteGenesisBlock(chainDb, strings.NewReader(DefaultTestnetGenesisBlock()))
   179  }
   180  
   181  // DefaultGenesisBlock assembles a JSON string representing the default Ethereum
   182  // genesis block.
   183  func DefaultGenesisBlock() string {
   184  	reader, err := gzip.NewReader(base64.NewDecoder(base64.StdEncoding, strings.NewReader(defaultGenesisBlock)))
   185  	if err != nil {
   186  		panic(fmt.Sprintf("failed to access default genesis: %v", err))
   187  	}
   188  	blob, err := ioutil.ReadAll(reader)
   189  	if err != nil {
   190  		panic(fmt.Sprintf("failed to load default genesis: %v", err))
   191  	}
   192  	return string(blob)
   193  }
   194  
   195  // DefaultTestnetGenesisBlock assembles a JSON string representing the default Ethereum
   196  // test network genesis block.
   197  func DefaultTestnetGenesisBlock() string {
   198  	reader := bzip2.NewReader(base64.NewDecoder(base64.StdEncoding, strings.NewReader(defaultTestnetGenesisBlock)))
   199  	blob, err := ioutil.ReadAll(reader)
   200  	if err != nil {
   201  		panic(fmt.Sprintf("failed to load default genesis: %v", err))
   202  	}
   203  	return string(blob)
   204  }
   205  
   206  // DevGenesisBlock assembles a JSON string representing a local dev genesis block.
   207  func DevGenesisBlock() string {
   208  	reader := bzip2.NewReader(base64.NewDecoder(base64.StdEncoding, strings.NewReader(defaultDevnetGenesisBlock)))
   209  	blob, err := ioutil.ReadAll(reader)
   210  	if err != nil {
   211  		panic(fmt.Sprintf("failed to load dev genesis: %v", err))
   212  	}
   213  	return string(blob)
   214  }