github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/signer/core/cliui.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:42</date> 10 //</624450110436151296> 11 12 13 package core 14 15 import ( 16 "bufio" 17 "fmt" 18 "os" 19 "strings" 20 21 "sync" 22 23 "github.com/davecgh/go-spew/spew" 24 "github.com/ethereum/go-ethereum/common/hexutil" 25 "github.com/ethereum/go-ethereum/internal/ethapi" 26 "github.com/ethereum/go-ethereum/log" 27 "golang.org/x/crypto/ssh/terminal" 28 ) 29 30 type CommandlineUI struct { 31 in *bufio.Reader 32 mu sync.Mutex 33 } 34 35 func NewCommandlineUI() *CommandlineUI { 36 return &CommandlineUI{in: bufio.NewReader(os.Stdin)} 37 } 38 39 //readstring从stdin读取一行,从空格中剪裁if,强制 40 //非空性。 41 func (ui *CommandlineUI) readString() string { 42 for { 43 fmt.Printf("> ") 44 text, err := ui.in.ReadString('\n') 45 if err != nil { 46 log.Crit("Failed to read user input", "err", err) 47 } 48 if text = strings.TrimSpace(text); text != "" { 49 return text 50 } 51 } 52 } 53 54 //readpassword从stdin读取一行,从尾随的new 55 //行并返回它。输入将不会被回送。 56 func (ui *CommandlineUI) readPassword() string { 57 fmt.Printf("Enter password to approve:\n") 58 fmt.Printf("> ") 59 60 text, err := terminal.ReadPassword(int(os.Stdin.Fd())) 61 if err != nil { 62 log.Crit("Failed to read password", "err", err) 63 } 64 fmt.Println() 65 fmt.Println("-----------------------") 66 return string(text) 67 } 68 69 //readpassword从stdin读取一行,从尾随的new 70 //行并返回它。输入将不会被回送。 71 func (ui *CommandlineUI) readPasswordText(inputstring string) string { 72 fmt.Printf("Enter %s:\n", inputstring) 73 fmt.Printf("> ") 74 text, err := terminal.ReadPassword(int(os.Stdin.Fd())) 75 if err != nil { 76 log.Crit("Failed to read password", "err", err) 77 } 78 fmt.Println("-----------------------") 79 return string(text) 80 } 81 82 func (ui *CommandlineUI) OnInputRequired(info UserInputRequest) (UserInputResponse, error) { 83 fmt.Println(info.Title) 84 fmt.Println(info.Prompt) 85 if info.IsPassword { 86 text, err := terminal.ReadPassword(int(os.Stdin.Fd())) 87 if err != nil { 88 log.Error("Failed to read password", "err", err) 89 } 90 fmt.Println("-----------------------") 91 return UserInputResponse{string(text)}, err 92 } 93 text := ui.readString() 94 fmt.Println("-----------------------") 95 return UserInputResponse{text}, nil 96 } 97 98 //如果用户输入“是”,则confirm返回true,否则返回false 99 func (ui *CommandlineUI) confirm() bool { 100 fmt.Printf("Approve? [y/N]:\n") 101 if ui.readString() == "y" { 102 return true 103 } 104 fmt.Println("-----------------------") 105 return false 106 } 107 108 func showMetadata(metadata Metadata) { 109 fmt.Printf("Request context:\n\t%v -> %v -> %v\n", metadata.Remote, metadata.Scheme, metadata.Local) 110 fmt.Printf("\nAdditional HTTP header data, provided by the external caller:\n") 111 fmt.Printf("\tUser-Agent: %v\n\tOrigin: %v\n", metadata.UserAgent, metadata.Origin) 112 } 113 114 //approvetx提示用户确认请求签署交易 115 func (ui *CommandlineUI) ApproveTx(request *SignTxRequest) (SignTxResponse, error) { 116 ui.mu.Lock() 117 defer ui.mu.Unlock() 118 weival := request.Transaction.Value.ToInt() 119 fmt.Printf("--------- Transaction request-------------\n") 120 if to := request.Transaction.To; to != nil { 121 fmt.Printf("to: %v\n", to.Original()) 122 if !to.ValidChecksum() { 123 fmt.Printf("\nWARNING: Invalid checksum on to-address!\n\n") 124 } 125 } else { 126 fmt.Printf("to: <contact creation>\n") 127 } 128 fmt.Printf("from: %v\n", request.Transaction.From.String()) 129 fmt.Printf("value: %v wei\n", weival) 130 fmt.Printf("gas: %v (%v)\n", request.Transaction.Gas, uint64(request.Transaction.Gas)) 131 fmt.Printf("gasprice: %v wei\n", request.Transaction.GasPrice.ToInt()) 132 fmt.Printf("nonce: %v (%v)\n", request.Transaction.Nonce, uint64(request.Transaction.Nonce)) 133 if request.Transaction.Data != nil { 134 d := *request.Transaction.Data 135 if len(d) > 0 { 136 137 fmt.Printf("data: %v\n", hexutil.Encode(d)) 138 } 139 } 140 if request.Callinfo != nil { 141 fmt.Printf("\nTransaction validation:\n") 142 for _, m := range request.Callinfo { 143 fmt.Printf(" * %s : %s\n", m.Typ, m.Message) 144 } 145 fmt.Println() 146 147 } 148 fmt.Printf("\n") 149 showMetadata(request.Meta) 150 fmt.Printf("-------------------------------------------\n") 151 if !ui.confirm() { 152 return SignTxResponse{request.Transaction, false, ""}, nil 153 } 154 return SignTxResponse{request.Transaction, true, ui.readPassword()}, nil 155 } 156 157 //ApproveSignData提示用户确认请求签署数据 158 func (ui *CommandlineUI) ApproveSignData(request *SignDataRequest) (SignDataResponse, error) { 159 ui.mu.Lock() 160 defer ui.mu.Unlock() 161 162 fmt.Printf("-------- Sign data request--------------\n") 163 fmt.Printf("Account: %s\n", request.Address.String()) 164 fmt.Printf("message: \n%q\n", request.Message) 165 fmt.Printf("raw data: \n%v\n", request.Rawdata) 166 fmt.Printf("message hash: %v\n", request.Hash) 167 fmt.Printf("-------------------------------------------\n") 168 showMetadata(request.Meta) 169 if !ui.confirm() { 170 return SignDataResponse{false, ""}, nil 171 } 172 return SignDataResponse{true, ui.readPassword()}, nil 173 } 174 175 //approveexport提示用户确认导出加密帐户json 176 func (ui *CommandlineUI) ApproveExport(request *ExportRequest) (ExportResponse, error) { 177 ui.mu.Lock() 178 defer ui.mu.Unlock() 179 180 fmt.Printf("-------- Export Account request--------------\n") 181 fmt.Printf("A request has been made to export the (encrypted) keyfile\n") 182 fmt.Printf("Approving this operation means that the caller obtains the (encrypted) contents\n") 183 fmt.Printf("\n") 184 fmt.Printf("Account: %x\n", request.Address) 185 //fmt.printf(“keyfile:\n%v\n”,request.file) 186 fmt.Printf("-------------------------------------------\n") 187 showMetadata(request.Meta) 188 return ExportResponse{ui.confirm()}, nil 189 } 190 191 //approveImport提示用户确认导入账号json 192 func (ui *CommandlineUI) ApproveImport(request *ImportRequest) (ImportResponse, error) { 193 ui.mu.Lock() 194 defer ui.mu.Unlock() 195 196 fmt.Printf("-------- Import Account request--------------\n") 197 fmt.Printf("A request has been made to import an encrypted keyfile\n") 198 fmt.Printf("-------------------------------------------\n") 199 showMetadata(request.Meta) 200 if !ui.confirm() { 201 return ImportResponse{false, "", ""}, nil 202 } 203 return ImportResponse{true, ui.readPasswordText("Old password"), ui.readPasswordText("New password")}, nil 204 } 205 206 //批准提示用户确认列出帐户 207 //用户界面可以修改要列出的科目列表 208 func (ui *CommandlineUI) ApproveListing(request *ListRequest) (ListResponse, error) { 209 210 ui.mu.Lock() 211 defer ui.mu.Unlock() 212 213 fmt.Printf("-------- List Account request--------------\n") 214 fmt.Printf("A request has been made to list all accounts. \n") 215 fmt.Printf("You can select which accounts the caller can see\n") 216 for _, account := range request.Accounts { 217 fmt.Printf(" [x] %v\n", account.Address.Hex()) 218 fmt.Printf(" URL: %v\n", account.URL) 219 fmt.Printf(" Type: %v\n", account.Typ) 220 } 221 fmt.Printf("-------------------------------------------\n") 222 showMetadata(request.Meta) 223 if !ui.confirm() { 224 return ListResponse{nil}, nil 225 } 226 return ListResponse{request.Accounts}, nil 227 } 228 229 //ApproveWaccount提示用户确认创建新帐户,并显示给调用方 230 func (ui *CommandlineUI) ApproveNewAccount(request *NewAccountRequest) (NewAccountResponse, error) { 231 232 ui.mu.Lock() 233 defer ui.mu.Unlock() 234 235 fmt.Printf("-------- New Account request--------------\n\n") 236 fmt.Printf("A request has been made to create a new account. \n") 237 fmt.Printf("Approving this operation means that a new account is created,\n") 238 fmt.Printf("and the address is returned to the external caller\n\n") 239 showMetadata(request.Meta) 240 if !ui.confirm() { 241 return NewAccountResponse{false, ""}, nil 242 } 243 return NewAccountResponse{true, ui.readPassword()}, nil 244 } 245 246 //ShowError向用户显示错误消息 247 func (ui *CommandlineUI) ShowError(message string) { 248 fmt.Printf("-------- Error message from Clef-----------\n") 249 fmt.Println(message) 250 fmt.Printf("-------------------------------------------\n") 251 } 252 253 //ShowInfo向用户显示信息消息 254 func (ui *CommandlineUI) ShowInfo(message string) { 255 fmt.Printf("Info: %v\n", message) 256 } 257 258 func (ui *CommandlineUI) OnApprovedTx(tx ethapi.SignTransactionResult) { 259 fmt.Printf("Transaction signed:\n ") 260 spew.Dump(tx.Tx) 261 } 262 263 func (ui *CommandlineUI) OnSignerStartup(info StartupInfo) { 264 265 fmt.Printf("------- Signer info -------\n") 266 for k, v := range info.Info { 267 fmt.Printf("* %v : %v\n", k, v) 268 } 269 } 270