github.com/tuotoo/go-ethereum@v1.7.4-0.20171121184211-049797d40a24/cmd/puppeth/wizard_genesis.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU 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 // go-ethereum 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 General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "bytes" 21 "encoding/json" 22 "fmt" 23 "io/ioutil" 24 "math/big" 25 "math/rand" 26 "time" 27 28 "github.com/ethereum/go-ethereum/common" 29 "github.com/ethereum/go-ethereum/core" 30 "github.com/ethereum/go-ethereum/log" 31 "github.com/ethereum/go-ethereum/params" 32 ) 33 34 // makeGenesis creates a new genesis struct based on some user input. 35 func (w *wizard) makeGenesis() { 36 // Construct a default genesis block 37 genesis := &core.Genesis{ 38 Timestamp: uint64(time.Now().Unix()), 39 GasLimit: 4700000, 40 Difficulty: big.NewInt(1048576), 41 Alloc: make(core.GenesisAlloc), 42 Config: ¶ms.ChainConfig{ 43 HomesteadBlock: big.NewInt(1), 44 EIP150Block: big.NewInt(2), 45 EIP155Block: big.NewInt(3), 46 EIP158Block: big.NewInt(3), 47 ByzantiumBlock: big.NewInt(4), 48 }, 49 } 50 // Figure out which consensus engine to choose 51 fmt.Println() 52 fmt.Println("Which consensus engine to use? (default = clique)") 53 fmt.Println(" 1. Ethash - proof-of-work") 54 fmt.Println(" 2. Clique - proof-of-authority") 55 56 choice := w.read() 57 switch { 58 case choice == "1": 59 // In case of ethash, we're pretty much done 60 genesis.Config.Ethash = new(params.EthashConfig) 61 genesis.ExtraData = make([]byte, 32) 62 63 case choice == "" || choice == "2": 64 // In the case of clique, configure the consensus parameters 65 genesis.Difficulty = big.NewInt(1) 66 genesis.Config.Clique = ¶ms.CliqueConfig{ 67 Period: 15, 68 Epoch: 30000, 69 } 70 fmt.Println() 71 fmt.Println("How many seconds should blocks take? (default = 15)") 72 genesis.Config.Clique.Period = uint64(w.readDefaultInt(15)) 73 74 // We also need the initial list of signers 75 fmt.Println() 76 fmt.Println("Which accounts are allowed to seal? (mandatory at least one)") 77 78 var signers []common.Address 79 for { 80 if address := w.readAddress(); address != nil { 81 signers = append(signers, *address) 82 continue 83 } 84 if len(signers) > 0 { 85 break 86 } 87 } 88 // Sort the signers and embed into the extra-data section 89 for i := 0; i < len(signers); i++ { 90 for j := i + 1; j < len(signers); j++ { 91 if bytes.Compare(signers[i][:], signers[j][:]) > 0 { 92 signers[i], signers[j] = signers[j], signers[i] 93 } 94 } 95 } 96 genesis.ExtraData = make([]byte, 32+len(signers)*common.AddressLength+65) 97 for i, signer := range signers { 98 copy(genesis.ExtraData[32+i*common.AddressLength:], signer[:]) 99 } 100 101 default: 102 log.Crit("Invalid consensus engine choice", "choice", choice) 103 } 104 // Consensus all set, just ask for initial funds and go 105 fmt.Println() 106 fmt.Println("Which accounts should be pre-funded? (advisable at least one)") 107 for { 108 // Read the address of the account to fund 109 if address := w.readAddress(); address != nil { 110 genesis.Alloc[*address] = core.GenesisAccount{ 111 Balance: new(big.Int).Lsh(big.NewInt(1), 256-7), // 2^256 / 128 (allow many pre-funds without balance overflows) 112 } 113 continue 114 } 115 break 116 } 117 // Add a batch of precompile balances to avoid them getting deleted 118 for i := int64(0); i < 256; i++ { 119 genesis.Alloc[common.BigToAddress(big.NewInt(i))] = core.GenesisAccount{Balance: big.NewInt(1)} 120 } 121 fmt.Println() 122 123 // Query the user for some custom extras 124 fmt.Println() 125 fmt.Println("Specify your chain/network ID if you want an explicit one (default = random)") 126 genesis.Config.ChainId = new(big.Int).SetUint64(uint64(w.readDefaultInt(rand.Intn(65536)))) 127 128 fmt.Println() 129 fmt.Println("Anything fun to embed into the genesis block? (max 32 bytes)") 130 131 extra := w.read() 132 if len(extra) > 32 { 133 extra = extra[:32] 134 } 135 genesis.ExtraData = append([]byte(extra), genesis.ExtraData[len(extra):]...) 136 137 // All done, store the genesis and flush to disk 138 w.conf.genesis = genesis 139 } 140 141 // manageGenesis permits the modification of chain configuration parameters in 142 // a genesis config and the export of the entire genesis spec. 143 func (w *wizard) manageGenesis() { 144 // Figure out whether to modify or export the genesis 145 fmt.Println() 146 fmt.Println(" 1. Modify existing fork rules") 147 fmt.Println(" 2. Export genesis configuration") 148 149 choice := w.read() 150 switch { 151 case choice == "1": 152 // Fork rule updating requested, iterate over each fork 153 fmt.Println() 154 fmt.Printf("Which block should Homestead come into effect? (default = %v)\n", w.conf.genesis.Config.HomesteadBlock) 155 w.conf.genesis.Config.HomesteadBlock = w.readDefaultBigInt(w.conf.genesis.Config.HomesteadBlock) 156 157 fmt.Println() 158 fmt.Printf("Which block should EIP150 come into effect? (default = %v)\n", w.conf.genesis.Config.EIP150Block) 159 w.conf.genesis.Config.EIP150Block = w.readDefaultBigInt(w.conf.genesis.Config.EIP150Block) 160 161 fmt.Println() 162 fmt.Printf("Which block should EIP155 come into effect? (default = %v)\n", w.conf.genesis.Config.EIP155Block) 163 w.conf.genesis.Config.EIP155Block = w.readDefaultBigInt(w.conf.genesis.Config.EIP155Block) 164 165 fmt.Println() 166 fmt.Printf("Which block should EIP158 come into effect? (default = %v)\n", w.conf.genesis.Config.EIP158Block) 167 w.conf.genesis.Config.EIP158Block = w.readDefaultBigInt(w.conf.genesis.Config.EIP158Block) 168 169 fmt.Println() 170 fmt.Printf("Which block should Byzantium come into effect? (default = %v)\n", w.conf.genesis.Config.ByzantiumBlock) 171 w.conf.genesis.Config.ByzantiumBlock = w.readDefaultBigInt(w.conf.genesis.Config.ByzantiumBlock) 172 173 out, _ := json.MarshalIndent(w.conf.genesis.Config, "", " ") 174 fmt.Printf("Chain configuration updated:\n\n%s\n", out) 175 176 case choice == "2": 177 // Save whatever genesis configuration we currently have 178 fmt.Println() 179 fmt.Printf("Which file to save the genesis into? (default = %s.json)\n", w.network) 180 out, _ := json.MarshalIndent(w.conf.genesis, "", " ") 181 if err := ioutil.WriteFile(w.readDefaultString(fmt.Sprintf("%s.json", w.network)), out, 0644); err != nil { 182 log.Error("Failed to save genesis file", "err", err) 183 } 184 log.Info("Exported existing genesis block") 185 186 default: 187 log.Error("That's not something I can do") 188 } 189 }