github.com/waltonchain/waltonchain_gwtc_src@v1.1.4-0.20201225072101-8a298c95a819/cmd/puppeth/wizard.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of go-wtc. 3 // 4 // go-wtc 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-wtc 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-wtc. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "bufio" 21 "encoding/json" 22 "fmt" 23 "io/ioutil" 24 "math/big" 25 "net" 26 "os" 27 "path/filepath" 28 "sort" 29 "strconv" 30 "strings" 31 "syscall" 32 33 "github.com/wtc/go-wtc/common" 34 "github.com/wtc/go-wtc/core" 35 "github.com/wtc/go-wtc/log" 36 "golang.org/x/crypto/ssh/terminal" 37 ) 38 39 // config contains all the configurations needed by puppeth that should be saved 40 // between sessions. 41 type config struct { 42 path string // File containing the configuration values 43 genesis *core.Genesis // Genesis block to cache for node deploys 44 bootFull []string // Bootnodes to always connect to by full nodes 45 bootLight []string // Bootnodes to always connect to by light nodes 46 ethstats string // Ethstats settings to cache for node deploys 47 48 Servers map[string][]byte `json:"servers,omitempty"` 49 } 50 51 // servers retrieves an alphabetically sorted list of servers. 52 func (c config) servers() []string { 53 servers := make([]string, 0, len(c.Servers)) 54 for server := range c.Servers { 55 servers = append(servers, server) 56 } 57 sort.Strings(servers) 58 59 return servers 60 } 61 62 // flush dumps the contents of config to disk. 63 func (c config) flush() { 64 os.MkdirAll(filepath.Dir(c.path), 0755) 65 66 out, _ := json.MarshalIndent(c, "", " ") 67 if err := ioutil.WriteFile(c.path, out, 0644); err != nil { 68 log.Warn("Failed to save puppeth configs", "file", c.path, "err", err) 69 } 70 } 71 72 type wizard struct { 73 network string // Network name to manage 74 conf config // Configurations from previous runs 75 76 servers map[string]*sshClient // SSH connections to servers to administer 77 services map[string][]string // Wtc services known to be running on servers 78 79 in *bufio.Reader // Wrapper around stdin to allow reading user input 80 } 81 82 // read reads a single line from stdin, trimming if from spaces. 83 func (w *wizard) read() string { 84 fmt.Printf("> ") 85 text, err := w.in.ReadString('\n') 86 if err != nil { 87 log.Crit("Failed to read user input", "err", err) 88 } 89 return strings.TrimSpace(text) 90 } 91 92 // readString reads a single line from stdin, trimming if from spaces, enforcing 93 // non-emptyness. 94 func (w *wizard) readString() string { 95 for { 96 fmt.Printf("> ") 97 text, err := w.in.ReadString('\n') 98 if err != nil { 99 log.Crit("Failed to read user input", "err", err) 100 } 101 if text = strings.TrimSpace(text); text != "" { 102 return text 103 } 104 } 105 } 106 107 // readDefaultString reads a single line from stdin, trimming if from spaces. If 108 // an empty line is entered, the default value is returned. 109 func (w *wizard) readDefaultString(def string) string { 110 fmt.Printf("> ") 111 text, err := w.in.ReadString('\n') 112 if err != nil { 113 log.Crit("Failed to read user input", "err", err) 114 } 115 if text = strings.TrimSpace(text); text != "" { 116 return text 117 } 118 return def 119 } 120 121 // readInt reads a single line from stdin, trimming if from spaces, enforcing it 122 // to parse into an integer. 123 func (w *wizard) readInt() int { 124 for { 125 fmt.Printf("> ") 126 text, err := w.in.ReadString('\n') 127 if err != nil { 128 log.Crit("Failed to read user input", "err", err) 129 } 130 if text = strings.TrimSpace(text); text == "" { 131 continue 132 } 133 val, err := strconv.Atoi(strings.TrimSpace(text)) 134 if err != nil { 135 log.Error("Invalid input, expected integer", "err", err) 136 continue 137 } 138 return val 139 } 140 } 141 142 // readDefaultInt reads a single line from stdin, trimming if from spaces, enforcing 143 // it to parse into an integer. If an empty line is entered, the default value is 144 // returned. 145 func (w *wizard) readDefaultInt(def int) int { 146 for { 147 fmt.Printf("> ") 148 text, err := w.in.ReadString('\n') 149 if err != nil { 150 log.Crit("Failed to read user input", "err", err) 151 } 152 if text = strings.TrimSpace(text); text == "" { 153 return def 154 } 155 val, err := strconv.Atoi(strings.TrimSpace(text)) 156 if err != nil { 157 log.Error("Invalid input, expected integer", "err", err) 158 continue 159 } 160 return val 161 } 162 } 163 164 /* 165 // readFloat reads a single line from stdin, trimming if from spaces, enforcing it 166 // to parse into a float. 167 func (w *wizard) readFloat() float64 { 168 for { 169 fmt.Printf("> ") 170 text, err := w.in.ReadString('\n') 171 if err != nil { 172 log.Crit("Failed to read user input", "err", err) 173 } 174 if text = strings.TrimSpace(text); text == "" { 175 continue 176 } 177 val, err := strconv.ParseFloat(strings.TrimSpace(text), 64) 178 if err != nil { 179 log.Error("Invalid input, expected float", "err", err) 180 continue 181 } 182 return val 183 } 184 } 185 */ 186 187 // readDefaultFloat reads a single line from stdin, trimming if from spaces, enforcing 188 // it to parse into a float. If an empty line is entered, the default value is returned. 189 func (w *wizard) readDefaultFloat(def float64) float64 { 190 for { 191 fmt.Printf("> ") 192 text, err := w.in.ReadString('\n') 193 if err != nil { 194 log.Crit("Failed to read user input", "err", err) 195 } 196 if text = strings.TrimSpace(text); text == "" { 197 return def 198 } 199 val, err := strconv.ParseFloat(strings.TrimSpace(text), 64) 200 if err != nil { 201 log.Error("Invalid input, expected float", "err", err) 202 continue 203 } 204 return val 205 } 206 } 207 208 // readPassword reads a single line from stdin, trimming it from the trailing new 209 // line and returns it. The input will not be echoed. 210 func (w *wizard) readPassword() string { 211 fmt.Printf("> ") 212 text, err := terminal.ReadPassword(int(syscall.Stdin)) 213 if err != nil { 214 log.Crit("Failed to read password", "err", err) 215 } 216 fmt.Println() 217 return string(text) 218 } 219 220 // readAddress reads a single line from stdin, trimming if from spaces and converts 221 // it to an Wtc address. 222 func (w *wizard) readAddress() *common.Address { 223 for { 224 // Read the address from the user 225 fmt.Printf("> 0x") 226 text, err := w.in.ReadString('\n') 227 if err != nil { 228 log.Crit("Failed to read user input", "err", err) 229 } 230 if text = strings.TrimSpace(text); text == "" { 231 return nil 232 } 233 // Make sure it looks ok and return it if so 234 if len(text) != 40 { 235 log.Error("Invalid address length, please retry") 236 continue 237 } 238 bigaddr, _ := new(big.Int).SetString(text, 16) 239 address := common.BigToAddress(bigaddr) 240 return &address 241 } 242 } 243 244 // readDefaultAddress reads a single line from stdin, trimming if from spaces and 245 // converts it to an Wtc address. If an empty line is entered, the default 246 // value is returned. 247 func (w *wizard) readDefaultAddress(def common.Address) common.Address { 248 for { 249 // Read the address from the user 250 fmt.Printf("> 0x") 251 text, err := w.in.ReadString('\n') 252 if err != nil { 253 log.Crit("Failed to read user input", "err", err) 254 } 255 if text = strings.TrimSpace(text); text == "" { 256 return def 257 } 258 // Make sure it looks ok and return it if so 259 if len(text) != 40 { 260 log.Error("Invalid address length, please retry") 261 continue 262 } 263 bigaddr, _ := new(big.Int).SetString(text, 16) 264 return common.BigToAddress(bigaddr) 265 } 266 } 267 268 // readJSON reads a raw JSON message and returns it. 269 func (w *wizard) readJSON() string { 270 var blob json.RawMessage 271 272 for { 273 fmt.Printf("> ") 274 if err := json.NewDecoder(w.in).Decode(&blob); err != nil { 275 log.Error("Invalid JSON, please try again", "err", err) 276 continue 277 } 278 return string(blob) 279 } 280 } 281 282 // readIPAddress reads a single line from stdin, trimming if from spaces and 283 // converts it to a network IP address. 284 func (w *wizard) readIPAddress() net.IP { 285 for { 286 // Read the IP address from the user 287 fmt.Printf("> ") 288 text, err := w.in.ReadString('\n') 289 if err != nil { 290 log.Crit("Failed to read user input", "err", err) 291 } 292 if text = strings.TrimSpace(text); text == "" { 293 return nil 294 } 295 // Make sure it looks ok and return it if so 296 ip := net.ParseIP(text) 297 if ip == nil { 298 log.Error("Invalid IP address, please retry") 299 continue 300 } 301 return ip 302 } 303 }