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 }