gitee.com/liu-zhao234568/cntest@v1.0.0/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" 24 "io/ioutil" 25 "math/big" 26 "math/rand" 27 "net/http" 28 "os" 29 "path/filepath" 30 "time" 31 32 "gitee.com/liu-zhao234568/cntest/common" 33 "gitee.com/liu-zhao234568/cntest/core" 34 "gitee.com/liu-zhao234568/cntest/log" 35 "gitee.com/liu-zhao234568/cntest/params" 36 ) 37 38 // makeGenesis creates a new genesis struct based on some user input. 39 func (w *wizard) makeGenesis() { 40 // Construct a default genesis block 41 genesis := &core.Genesis{ 42 Timestamp: uint64(time.Now().Unix()), 43 GasLimit: 4700000, 44 Difficulty: big.NewInt(524288), 45 Alloc: make(core.GenesisAlloc), 46 Config: ¶ms.ChainConfig{ 47 HomesteadBlock: big.NewInt(0), 48 EIP150Block: big.NewInt(0), 49 EIP155Block: big.NewInt(0), 50 EIP158Block: big.NewInt(0), 51 ByzantiumBlock: big.NewInt(0), 52 ConstantinopleBlock: big.NewInt(0), 53 PetersburgBlock: big.NewInt(0), 54 IstanbulBlock: big.NewInt(0), 55 }, 56 } 57 // Figure out which consensus engine to choose 58 fmt.Println() 59 fmt.Println("Which consensus engine to use? (default = clique)") 60 fmt.Println(" 1. Ethash - proof-of-work") 61 fmt.Println(" 2. Clique - proof-of-authority") 62 63 choice := w.read() 64 switch { 65 case choice == "1": 66 // In case of ethash, we're pretty much done 67 genesis.Config.Ethash = new(params.EthashConfig) 68 genesis.ExtraData = make([]byte, 32) 69 70 case choice == "" || choice == "2": 71 // In the case of clique, configure the consensus parameters 72 genesis.Difficulty = big.NewInt(1) 73 genesis.Config.Clique = ¶ms.CliqueConfig{ 74 Period: 15, 75 Epoch: 30000, 76 } 77 fmt.Println() 78 fmt.Println("How many seconds should blocks take? (default = 15)") 79 genesis.Config.Clique.Period = uint64(w.readDefaultInt(15)) 80 81 // We also need the initial list of signers 82 fmt.Println() 83 fmt.Println("Which accounts are allowed to seal? (mandatory at least one)") 84 85 var signers []common.Address 86 for { 87 if address := w.readAddress(); address != nil { 88 signers = append(signers, *address) 89 continue 90 } 91 if len(signers) > 0 { 92 break 93 } 94 } 95 // Sort the signers and embed into the extra-data section 96 for i := 0; i < len(signers); i++ { 97 for j := i + 1; j < len(signers); j++ { 98 if bytes.Compare(signers[i][:], signers[j][:]) > 0 { 99 signers[i], signers[j] = signers[j], signers[i] 100 } 101 } 102 } 103 genesis.ExtraData = make([]byte, 32+len(signers)*common.AddressLength+65) 104 for i, signer := range signers { 105 copy(genesis.ExtraData[32+i*common.AddressLength:], signer[:]) 106 } 107 108 default: 109 log.Crit("Invalid consensus engine choice", "choice", choice) 110 } 111 // Consensus all set, just ask for initial funds and go 112 fmt.Println() 113 fmt.Println("Which accounts should be pre-funded? (advisable at least one)") 114 for { 115 // Read the address of the account to fund 116 if address := w.readAddress(); address != nil { 117 genesis.Alloc[*address] = core.GenesisAccount{ 118 Balance: new(big.Int).Lsh(big.NewInt(1), 256-7), // 2^256 / 128 (allow many pre-funds without balance overflows) 119 } 120 continue 121 } 122 break 123 } 124 fmt.Println() 125 fmt.Println("Should the precompile-addresses (0x1 .. 0xff) be pre-funded with 1 wei? (advisable yes)") 126 if w.readDefaultYesNo(true) { 127 // Add a batch of precompile balances to avoid them getting deleted 128 for i := int64(0); i < 256; i++ { 129 genesis.Alloc[common.BigToAddress(big.NewInt(i))] = core.GenesisAccount{Balance: big.NewInt(1)} 130 } 131 } 132 // Query the user for some custom extras 133 fmt.Println() 134 fmt.Println("Specify your chain/network ID if you want an explicit one (default = random)") 135 genesis.Config.ChainID = new(big.Int).SetUint64(uint64(w.readDefaultInt(rand.Intn(65536)))) 136 137 // All done, store the genesis and flush to disk 138 log.Info("Configured new genesis block") 139 140 w.conf.Genesis = genesis 141 w.conf.flush() 142 } 143 144 // importGenesis imports a Geth genesis spec into puppeth. 145 func (w *wizard) importGenesis() { 146 // Request the genesis JSON spec URL from the user 147 fmt.Println() 148 fmt.Println("Where's the genesis file? (local file or http/https url)") 149 url := w.readURL() 150 151 // Convert the various allowed URLs to a reader stream 152 var reader io.Reader 153 154 switch url.Scheme { 155 case "http", "https": 156 // Remote web URL, retrieve it via an HTTP client 157 res, err := http.Get(url.String()) 158 if err != nil { 159 log.Error("Failed to retrieve remote genesis", "err", err) 160 return 161 } 162 defer res.Body.Close() 163 reader = res.Body 164 165 case "": 166 // Schemaless URL, interpret as a local file 167 file, err := os.Open(url.String()) 168 if err != nil { 169 log.Error("Failed to open local genesis", "err", err) 170 return 171 } 172 defer file.Close() 173 reader = file 174 175 default: 176 log.Error("Unsupported genesis URL scheme", "scheme", url.Scheme) 177 return 178 } 179 // Parse the genesis file and inject it successful 180 var genesis core.Genesis 181 if err := json.NewDecoder(reader).Decode(&genesis); err != nil { 182 log.Error("Invalid genesis spec", "err", err) 183 return 184 } 185 log.Info("Imported genesis block") 186 187 w.conf.Genesis = &genesis 188 w.conf.flush() 189 } 190 191 // manageGenesis permits the modification of chain configuration parameters in 192 // a genesis config and the export of the entire genesis spec. 193 func (w *wizard) manageGenesis() { 194 // Figure out whether to modify or export the genesis 195 fmt.Println() 196 fmt.Println(" 1. Modify existing configurations") 197 fmt.Println(" 2. Export genesis configurations") 198 fmt.Println(" 3. Remove genesis configuration") 199 200 choice := w.read() 201 switch choice { 202 case "1": 203 // Fork rule updating requested, iterate over each fork 204 fmt.Println() 205 fmt.Printf("Which block should Homestead come into effect? (default = %v)\n", w.conf.Genesis.Config.HomesteadBlock) 206 w.conf.Genesis.Config.HomesteadBlock = w.readDefaultBigInt(w.conf.Genesis.Config.HomesteadBlock) 207 208 fmt.Println() 209 fmt.Printf("Which block should EIP150 (Tangerine Whistle) come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP150Block) 210 w.conf.Genesis.Config.EIP150Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP150Block) 211 212 fmt.Println() 213 fmt.Printf("Which block should EIP155 (Spurious Dragon) come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP155Block) 214 w.conf.Genesis.Config.EIP155Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP155Block) 215 216 fmt.Println() 217 fmt.Printf("Which block should EIP158/161 (also Spurious Dragon) come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP158Block) 218 w.conf.Genesis.Config.EIP158Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP158Block) 219 220 fmt.Println() 221 fmt.Printf("Which block should Byzantium come into effect? (default = %v)\n", w.conf.Genesis.Config.ByzantiumBlock) 222 w.conf.Genesis.Config.ByzantiumBlock = w.readDefaultBigInt(w.conf.Genesis.Config.ByzantiumBlock) 223 224 fmt.Println() 225 fmt.Printf("Which block should Constantinople come into effect? (default = %v)\n", w.conf.Genesis.Config.ConstantinopleBlock) 226 w.conf.Genesis.Config.ConstantinopleBlock = w.readDefaultBigInt(w.conf.Genesis.Config.ConstantinopleBlock) 227 if w.conf.Genesis.Config.PetersburgBlock == nil { 228 w.conf.Genesis.Config.PetersburgBlock = w.conf.Genesis.Config.ConstantinopleBlock 229 } 230 fmt.Println() 231 fmt.Printf("Which block should Petersburg come into effect? (default = %v)\n", w.conf.Genesis.Config.PetersburgBlock) 232 w.conf.Genesis.Config.PetersburgBlock = w.readDefaultBigInt(w.conf.Genesis.Config.PetersburgBlock) 233 234 fmt.Println() 235 fmt.Printf("Which block should Istanbul come into effect? (default = %v)\n", w.conf.Genesis.Config.IstanbulBlock) 236 w.conf.Genesis.Config.IstanbulBlock = w.readDefaultBigInt(w.conf.Genesis.Config.IstanbulBlock) 237 238 fmt.Println() 239 fmt.Printf("Which block should Berlin come into effect? (default = %v)\n", w.conf.Genesis.Config.BerlinBlock) 240 w.conf.Genesis.Config.BerlinBlock = w.readDefaultBigInt(w.conf.Genesis.Config.BerlinBlock) 241 242 fmt.Println() 243 fmt.Printf("Which block should London come into effect? (default = %v)\n", w.conf.Genesis.Config.LondonBlock) 244 w.conf.Genesis.Config.LondonBlock = w.readDefaultBigInt(w.conf.Genesis.Config.LondonBlock) 245 246 out, _ := json.MarshalIndent(w.conf.Genesis.Config, "", " ") 247 fmt.Printf("Chain configuration updated:\n\n%s\n", out) 248 249 w.conf.flush() 250 251 case "2": 252 // Save whatever genesis configuration we currently have 253 fmt.Println() 254 fmt.Printf("Which folder to save the genesis specs into? (default = current)\n") 255 fmt.Printf(" Will create %s.json, %s-aleth.json, %s-harmony.json, %s-parity.json\n", w.network, w.network, w.network, w.network) 256 257 folder := w.readDefaultString(".") 258 if err := os.MkdirAll(folder, 0755); err != nil { 259 log.Error("Failed to create spec folder", "folder", folder, "err", err) 260 return 261 } 262 out, _ := json.MarshalIndent(w.conf.Genesis, "", " ") 263 264 // Export the native genesis spec used by puppeth and Geth 265 gethJson := filepath.Join(folder, fmt.Sprintf("%s.json", w.network)) 266 if err := ioutil.WriteFile(gethJson, out, 0644); err != nil { 267 log.Error("Failed to save genesis file", "err", err) 268 return 269 } 270 log.Info("Saved native genesis chain spec", "path", gethJson) 271 272 // Export the genesis spec used by Aleth (formerly C++ Ethereum) 273 if spec, err := newAlethGenesisSpec(w.network, w.conf.Genesis); err != nil { 274 log.Error("Failed to create Aleth chain spec", "err", err) 275 } else { 276 saveGenesis(folder, w.network, "aleth", spec) 277 } 278 // Export the genesis spec used by Parity 279 if spec, err := newParityChainSpec(w.network, w.conf.Genesis, []string{}); err != nil { 280 log.Error("Failed to create Parity chain spec", "err", err) 281 } else { 282 saveGenesis(folder, w.network, "parity", spec) 283 } 284 // Export the genesis spec used by Harmony (formerly EthereumJ) 285 saveGenesis(folder, w.network, "harmony", w.conf.Genesis) 286 287 case "3": 288 // Make sure we don't have any services running 289 if len(w.conf.servers()) > 0 { 290 log.Error("Genesis reset requires all services and servers torn down") 291 return 292 } 293 log.Info("Genesis block destroyed") 294 295 w.conf.Genesis = nil 296 w.conf.flush() 297 default: 298 log.Error("That's not something I can do") 299 return 300 } 301 } 302 303 // saveGenesis JSON encodes an arbitrary genesis spec into a pre-defined file. 304 func saveGenesis(folder, network, client string, spec interface{}) { 305 path := filepath.Join(folder, fmt.Sprintf("%s-%s.json", network, client)) 306 307 out, _ := json.MarshalIndent(spec, "", " ") 308 if err := ioutil.WriteFile(path, out, 0644); err != nil { 309 log.Error("Failed to save genesis file", "client", client, "err", err) 310 return 311 } 312 log.Info("Saved genesis chain spec", "client", client, "path", path) 313 }