github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/cmd/puppeth/wizard_genesis.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:33</date> 10 //</624450069973700608> 11 12 13 package main 14 15 import ( 16 "bytes" 17 "encoding/json" 18 "fmt" 19 "io" 20 "io/ioutil" 21 "math/big" 22 "math/rand" 23 "net/http" 24 "os" 25 "path/filepath" 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 // 35 func (w *wizard) makeGenesis() { 36 // 37 genesis := &core.Genesis{ 38 Timestamp: uint64(time.Now().Unix()), 39 GasLimit: 4700000, 40 Difficulty: big.NewInt(524288), 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 ConstantinopleBlock: big.NewInt(5), 49 }, 50 } 51 // 52 fmt.Println() 53 fmt.Println("Which consensus engine to use? (default = clique)") 54 fmt.Println(" 1. Ethash - proof-of-work") 55 fmt.Println(" 2. Clique - proof-of-authority") 56 57 choice := w.read() 58 switch { 59 case choice == "1": 60 // 61 genesis.Config.Ethash = new(params.EthashConfig) 62 genesis.ExtraData = make([]byte, 32) 63 64 case choice == "" || choice == "2": 65 // 66 genesis.Difficulty = big.NewInt(1) 67 genesis.Config.Clique = ¶ms.CliqueConfig{ 68 Period: 15, 69 Epoch: 30000, 70 } 71 fmt.Println() 72 fmt.Println("How many seconds should blocks take? (default = 15)") 73 genesis.Config.Clique.Period = uint64(w.readDefaultInt(15)) 74 75 //我们还需要签名者的初始列表 76 fmt.Println() 77 fmt.Println("Which accounts are allowed to seal? (mandatory at least one)") 78 79 var signers []common.Address 80 for { 81 if address := w.readAddress(); address != nil { 82 signers = append(signers, *address) 83 continue 84 } 85 if len(signers) > 0 { 86 break 87 } 88 } 89 //对签名者排序并嵌入到额外的数据部分 90 for i := 0; i < len(signers); i++ { 91 for j := i + 1; j < len(signers); j++ { 92 if bytes.Compare(signers[i][:], signers[j][:]) > 0 { 93 signers[i], signers[j] = signers[j], signers[i] 94 } 95 } 96 } 97 genesis.ExtraData = make([]byte, 32+len(signers)*common.AddressLength+65) 98 for i, signer := range signers { 99 copy(genesis.ExtraData[32+i*common.AddressLength:], signer[:]) 100 } 101 102 default: 103 log.Crit("Invalid consensus engine choice", "choice", choice) 104 } 105 //协商一致,只需申请初始资金就可以了。 106 fmt.Println() 107 fmt.Println("Which accounts should be pre-funded? (advisable at least one)") 108 for { 109 //读取要资助的帐户的地址 110 if address := w.readAddress(); address != nil { 111 genesis.Alloc[*address] = core.GenesisAccount{ 112 Balance: new(big.Int).Lsh(big.NewInt(1), 256-7), //2^256/128(允许多个预付款没有余额溢出) 113 } 114 continue 115 } 116 break 117 } 118 fmt.Println() 119 fmt.Println("Should the precompile-addresses (0x1 .. 0xff) be pre-funded with 1 wei? (advisable yes)") 120 if w.readDefaultYesNo(true) { 121 //添加一批预编译余额以避免删除它们 122 for i := int64(0); i < 256; i++ { 123 genesis.Alloc[common.BigToAddress(big.NewInt(i))] = core.GenesisAccount{Balance: big.NewInt(1)} 124 } 125 } 126 //向用户查询一些自定义附加项 127 fmt.Println() 128 fmt.Println("Specify your chain/network ID if you want an explicit one (default = random)") 129 genesis.Config.ChainID = new(big.Int).SetUint64(uint64(w.readDefaultInt(rand.Intn(65536)))) 130 131 //全部完成,存储Genesis并刷新到磁盘 132 log.Info("Configured new genesis block") 133 134 w.conf.Genesis = genesis 135 w.conf.flush() 136 } 137 138 // 139 func (w *wizard) importGenesis() { 140 // 141 fmt.Println() 142 fmt.Println("Where's the genesis file? (local file or http/https url)") 143 url := w.readURL() 144 145 // 146 var reader io.Reader 147 148 switch url.Scheme { 149 case "http", "https": 150 // 151 res, err := http.Get(url.String()) 152 if err != nil { 153 log.Error("Failed to retrieve remote genesis", "err", err) 154 return 155 } 156 defer res.Body.Close() 157 reader = res.Body 158 159 case "": 160 // 161 file, err := os.Open(url.String()) 162 if err != nil { 163 log.Error("Failed to open local genesis", "err", err) 164 return 165 } 166 defer file.Close() 167 reader = file 168 169 default: 170 log.Error("Unsupported genesis URL scheme", "scheme", url.Scheme) 171 return 172 } 173 // 174 var genesis core.Genesis 175 if err := json.NewDecoder(reader).Decode(&genesis); err != nil { 176 log.Error("Invalid genesis spec: %v", err) 177 return 178 } 179 log.Info("Imported genesis block") 180 181 w.conf.Genesis = &genesis 182 w.conf.flush() 183 } 184 185 //ManageGenesis允许在 186 //一个Genesis配置和整个Genesis规范的导出。 187 func (w *wizard) manageGenesis() { 188 //确定是修改还是导出Genesis 189 fmt.Println() 190 fmt.Println(" 1. Modify existing fork rules") 191 fmt.Println(" 2. Export genesis configurations") 192 fmt.Println(" 3. Remove genesis configuration") 193 194 choice := w.read() 195 switch choice { 196 case "1": 197 //请求了fork规则更新,对每个fork进行迭代 198 fmt.Println() 199 fmt.Printf("Which block should Homestead come into effect? (default = %v)\n", w.conf.Genesis.Config.HomesteadBlock) 200 w.conf.Genesis.Config.HomesteadBlock = w.readDefaultBigInt(w.conf.Genesis.Config.HomesteadBlock) 201 202 fmt.Println() 203 fmt.Printf("Which block should EIP150 (Tangerine Whistle) come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP150Block) 204 w.conf.Genesis.Config.EIP150Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP150Block) 205 206 fmt.Println() 207 fmt.Printf("Which block should EIP155 (Spurious Dragon) come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP155Block) 208 w.conf.Genesis.Config.EIP155Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP155Block) 209 210 fmt.Println() 211 fmt.Printf("Which block should EIP158/161 (also Spurious Dragon) come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP158Block) 212 w.conf.Genesis.Config.EIP158Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP158Block) 213 214 fmt.Println() 215 fmt.Printf("Which block should Byzantium come into effect? (default = %v)\n", w.conf.Genesis.Config.ByzantiumBlock) 216 w.conf.Genesis.Config.ByzantiumBlock = w.readDefaultBigInt(w.conf.Genesis.Config.ByzantiumBlock) 217 218 fmt.Println() 219 fmt.Printf("Which block should Constantinople come into effect? (default = %v)\n", w.conf.Genesis.Config.ConstantinopleBlock) 220 w.conf.Genesis.Config.ConstantinopleBlock = w.readDefaultBigInt(w.conf.Genesis.Config.ConstantinopleBlock) 221 222 out, _ := json.MarshalIndent(w.conf.Genesis.Config, "", " ") 223 fmt.Printf("Chain configuration updated:\n\n%s\n", out) 224 225 case "2": 226 //保存我们当前的Genesis配置 227 fmt.Println() 228 fmt.Printf("Which folder to save the genesis specs into? (default = current)\n") 229 fmt.Printf(" Will create %s.json, %s-aleth.json, %s-harmony.json, %s-parity.json\n", w.network, w.network, w.network, w.network) 230 231 folder := w.readDefaultString(".") 232 if err := os.MkdirAll(folder, 0755); err != nil { 233 log.Error("Failed to create spec folder", "folder", folder, "err", err) 234 return 235 } 236 out, _ := json.MarshalIndent(w.conf.Genesis, "", " ") 237 238 // 239 gethJson := filepath.Join(folder, fmt.Sprintf("%s.json", w.network)) 240 if err := ioutil.WriteFile((gethJson), out, 0644); err != nil { 241 log.Error("Failed to save genesis file", "err", err) 242 return 243 } 244 log.Info("Saved native genesis chain spec", "path", gethJson) 245 246 // 247 if spec, err := newAlethGenesisSpec(w.network, w.conf.Genesis); err != nil { 248 log.Error("Failed to create Aleth chain spec", "err", err) 249 } else { 250 saveGenesis(folder, w.network, "aleth", spec) 251 } 252 // 253 if spec, err := newParityChainSpec(w.network, w.conf.Genesis, []string{}); err != nil { 254 log.Error("Failed to create Parity chain spec", "err", err) 255 } else { 256 saveGenesis(folder, w.network, "parity", spec) 257 } 258 // 259 saveGenesis(folder, w.network, "harmony", w.conf.Genesis) 260 261 case "3": 262 // 263 if len(w.conf.servers()) > 0 { 264 log.Error("Genesis reset requires all services and servers torn down") 265 return 266 } 267 log.Info("Genesis block destroyed") 268 269 w.conf.Genesis = nil 270 w.conf.flush() 271 default: 272 log.Error("That's not something I can do") 273 return 274 } 275 } 276 277 // 278 func saveGenesis(folder, network, client string, spec interface{}) { 279 path := filepath.Join(folder, fmt.Sprintf("%s-%s.json", network, client)) 280 281 out, _ := json.Marshal(spec) 282 if err := ioutil.WriteFile(path, out, 0644); err != nil { 283 log.Error("Failed to save genesis file", "client", client, "err", err) 284 return 285 } 286 log.Info("Saved genesis chain spec", "client", client, "path", path) 287 } 288