github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/cmd/puppeth/wizard.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 //</624450069743013888> 11 12 13 package main 14 15 import ( 16 "bufio" 17 "encoding/json" 18 "fmt" 19 "io/ioutil" 20 "math/big" 21 "net" 22 "net/url" 23 "os" 24 "path/filepath" 25 "sort" 26 "strconv" 27 "strings" 28 "sync" 29 30 "github.com/ethereum/go-ethereum/common" 31 "github.com/ethereum/go-ethereum/core" 32 "github.com/ethereum/go-ethereum/log" 33 "golang.org/x/crypto/ssh/terminal" 34 ) 35 36 //config包含Puppeth需要保存的所有配置 37 // 38 type config struct { 39 path string // 40 bootnodes []string //所有节点始终连接到的引导节点 41 ethstats string //要为节点部署缓存的ethstats设置 42 43 Genesis *core.Genesis `json:"genesis,omitempty"` //用于节点部署的缓存Genesis块 44 Servers map[string][]byte `json:"servers,omitempty"` 45 } 46 47 //服务器检索按字母顺序排序的服务器列表。 48 func (c config) servers() []string { 49 servers := make([]string, 0, len(c.Servers)) 50 for server := range c.Servers { 51 servers = append(servers, server) 52 } 53 sort.Strings(servers) 54 55 return servers 56 } 57 58 //flush将配置的内容转储到磁盘。 59 func (c config) flush() { 60 os.MkdirAll(filepath.Dir(c.path), 0755) 61 62 out, _ := json.MarshalIndent(c, "", " ") 63 if err := ioutil.WriteFile(c.path, out, 0644); err != nil { 64 log.Warn("Failed to save puppeth configs", "file", c.path, "err", err) 65 } 66 } 67 68 type wizard struct { 69 network string //要管理的网络名称 70 conf config //以前运行的配置 71 72 servers map[string]*sshClient //ssh连接到要管理的服务器 73 services map[string][]string //已知正在服务器上运行的以太坊服务 74 75 in *bufio.Reader //包装stdin以允许读取用户输入 76 lock sync.Mutex //锁定以在并发服务发现期间保护配置 77 } 78 79 //读取从stdin中读取一行,如果从空格中删除,则进行剪裁。 80 func (w *wizard) read() string { 81 fmt.Printf("> ") 82 text, err := w.in.ReadString('\n') 83 if err != nil { 84 log.Crit("Failed to read user input", "err", err) 85 } 86 return strings.TrimSpace(text) 87 } 88 89 // 90 //非空性。 91 func (w *wizard) readString() string { 92 for { 93 fmt.Printf("> ") 94 text, err := w.in.ReadString('\n') 95 if err != nil { 96 log.Crit("Failed to read user input", "err", err) 97 } 98 if text = strings.TrimSpace(text); text != "" { 99 return text 100 } 101 } 102 } 103 104 //readdefaultstring从stdin读取一行,从空格中剪裁if。如果 105 //输入空行,返回默认值。 106 func (w *wizard) readDefaultString(def string) string { 107 fmt.Printf("> ") 108 text, err := w.in.ReadString('\n') 109 if err != nil { 110 log.Crit("Failed to read user input", "err", err) 111 } 112 if text = strings.TrimSpace(text); text != "" { 113 return text 114 } 115 return def 116 } 117 118 // 119 // 120 // 121 func (w *wizard) readDefaultYesNo(def bool) bool { 122 for { 123 fmt.Printf("> ") 124 text, err := w.in.ReadString('\n') 125 if err != nil { 126 log.Crit("Failed to read user input", "err", err) 127 } 128 if text = strings.ToLower(strings.TrimSpace(text)); text == "" { 129 return def 130 } 131 if text == "y" || text == "yes" { 132 return true 133 } 134 if text == "n" || text == "no" { 135 return false 136 } 137 log.Error("Invalid input, expected 'y', 'yes', 'n', 'no' or empty") 138 } 139 } 140 141 // 142 // 143 func (w *wizard) readURL() *url.URL { 144 for { 145 fmt.Printf("> ") 146 text, err := w.in.ReadString('\n') 147 if err != nil { 148 log.Crit("Failed to read user input", "err", err) 149 } 150 uri, err := url.Parse(strings.TrimSpace(text)) 151 if err != nil { 152 log.Error("Invalid input, expected URL", "err", err) 153 continue 154 } 155 return uri 156 } 157 } 158 159 //readint从stdin读取一行,从空格中剪裁if,强制执行 160 // 161 func (w *wizard) readInt() int { 162 for { 163 fmt.Printf("> ") 164 text, err := w.in.ReadString('\n') 165 if err != nil { 166 log.Crit("Failed to read user input", "err", err) 167 } 168 if text = strings.TrimSpace(text); text == "" { 169 continue 170 } 171 val, err := strconv.Atoi(strings.TrimSpace(text)) 172 if err != nil { 173 log.Error("Invalid input, expected integer", "err", err) 174 continue 175 } 176 return val 177 } 178 } 179 180 // 181 // 182 //返回。 183 func (w *wizard) readDefaultInt(def int) int { 184 for { 185 fmt.Printf("> ") 186 text, err := w.in.ReadString('\n') 187 if err != nil { 188 log.Crit("Failed to read user input", "err", err) 189 } 190 if text = strings.TrimSpace(text); text == "" { 191 return def 192 } 193 val, err := strconv.Atoi(strings.TrimSpace(text)) 194 if err != nil { 195 log.Error("Invalid input, expected integer", "err", err) 196 continue 197 } 198 return val 199 } 200 } 201 202 // 203 // 204 // 205 func (w *wizard) readDefaultBigInt(def *big.Int) *big.Int { 206 for { 207 fmt.Printf("> ") 208 text, err := w.in.ReadString('\n') 209 if err != nil { 210 log.Crit("Failed to read user input", "err", err) 211 } 212 if text = strings.TrimSpace(text); text == "" { 213 return def 214 } 215 val, ok := new(big.Int).SetString(text, 0) 216 if !ok { 217 log.Error("Invalid input, expected big integer") 218 continue 219 } 220 return val 221 } 222 } 223 224 /* 225 226 227 228 229 230 231 如果犯错!= nIL{ 232 233 234 如果text=strings.trimspace(text);text=“” 235 持续 236 } 237 val,err:=strconv.parsefloat(strings.trimspace(text),64) 238 如果犯错!= nIL{ 239 log.error(“输入无效,应为float”,“err”,err) 240 持续 241 242 返回瓦尔 243 244 245 */ 246 247 248 //readdefaultfloat从stdin读取一行,从空格中剪裁if,强制 249 // 250 func (w *wizard) readDefaultFloat(def float64) float64 { 251 for { 252 fmt.Printf("> ") 253 text, err := w.in.ReadString('\n') 254 if err != nil { 255 log.Crit("Failed to read user input", "err", err) 256 } 257 if text = strings.TrimSpace(text); text == "" { 258 return def 259 } 260 val, err := strconv.ParseFloat(strings.TrimSpace(text), 64) 261 if err != nil { 262 log.Error("Invalid input, expected float", "err", err) 263 continue 264 } 265 return val 266 } 267 } 268 269 //readpassword从stdin读取一行,从尾随的new 270 // 271 func (w *wizard) readPassword() string { 272 fmt.Printf("> ") 273 text, err := terminal.ReadPassword(int(os.Stdin.Fd())) 274 if err != nil { 275 log.Crit("Failed to read password", "err", err) 276 } 277 fmt.Println() 278 return string(text) 279 } 280 281 // 282 //发送到以太坊地址。 283 func (w *wizard) readAddress() *common.Address { 284 for { 285 //从用户处读取地址 286 fmt.Printf("> 0x") 287 text, err := w.in.ReadString('\n') 288 if err != nil { 289 log.Crit("Failed to read user input", "err", err) 290 } 291 if text = strings.TrimSpace(text); text == "" { 292 return nil 293 } 294 // 295 if len(text) != 40 { 296 log.Error("Invalid address length, please retry") 297 continue 298 } 299 bigaddr, _ := new(big.Int).SetString(text, 16) 300 address := common.BigToAddress(bigaddr) 301 return &address 302 } 303 } 304 305 // 306 //将其转换为以太坊地址。如果输入空行,则默认 307 // 308 func (w *wizard) readDefaultAddress(def common.Address) common.Address { 309 for { 310 //从用户处读取地址 311 fmt.Printf("> 0x") 312 text, err := w.in.ReadString('\n') 313 if err != nil { 314 log.Crit("Failed to read user input", "err", err) 315 } 316 if text = strings.TrimSpace(text); text == "" { 317 return def 318 } 319 // 320 if len(text) != 40 { 321 log.Error("Invalid address length, please retry") 322 continue 323 } 324 bigaddr, _ := new(big.Int).SetString(text, 16) 325 return common.BigToAddress(bigaddr) 326 } 327 } 328 329 // 330 func (w *wizard) readJSON() string { 331 var blob json.RawMessage 332 333 for { 334 fmt.Printf("> ") 335 if err := json.NewDecoder(w.in).Decode(&blob); err != nil { 336 log.Error("Invalid JSON, please try again", "err", err) 337 continue 338 } 339 return string(blob) 340 } 341 } 342 343 // 344 // 345 //用户输入格式(而不是返回go net.ip)与 346 // 347 func (w *wizard) readIPAddress() string { 348 for { 349 //从用户读取IP地址 350 fmt.Printf("> ") 351 text, err := w.in.ReadString('\n') 352 if err != nil { 353 log.Crit("Failed to read user input", "err", err) 354 } 355 if text = strings.TrimSpace(text); text == "" { 356 return "" 357 } 358 // 359 if ip := net.ParseIP(text); ip == nil { 360 log.Error("Invalid IP address, please retry") 361 continue 362 } 363 return text 364 } 365 } 366