github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/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 12:09:46</date> 10 //</624342666540224512> 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" 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 //如果用户输入“是”,则confirm返回true,否则返回false 83 func (ui *CommandlineUI) confirm() bool { 84 fmt.Printf("Approve? [y/N]:\n") 85 if ui.readString() == "y" { 86 return true 87 } 88 fmt.Println("-----------------------") 89 return false 90 } 91 92 func showMetadata(metadata Metadata) { 93 fmt.Printf("Request context:\n\t%v -> %v -> %v\n", metadata.Remote, metadata.Scheme, metadata.Local) 94 } 95 96 //approvetx提示用户确认请求签署交易 97 func (ui *CommandlineUI) ApproveTx(request *SignTxRequest) (SignTxResponse, error) { 98 ui.mu.Lock() 99 defer ui.mu.Unlock() 100 weival := request.Transaction.Value.ToInt() 101 fmt.Printf("--------- Transaction request-------------\n") 102 if to := request.Transaction.To; to != nil { 103 fmt.Printf("to: %v\n", to.Original()) 104 if !to.ValidChecksum() { 105 fmt.Printf("\nWARNING: Invalid checksum on to-address!\n\n") 106 } 107 } else { 108 fmt.Printf("to: <contact creation>\n") 109 } 110 fmt.Printf("from: %v\n", request.Transaction.From.String()) 111 fmt.Printf("value: %v wei\n", weival) 112 if request.Transaction.Data != nil { 113 d := *request.Transaction.Data 114 if len(d) > 0 { 115 fmt.Printf("data: %v\n", common.Bytes2Hex(d)) 116 } 117 } 118 if request.Callinfo != nil { 119 fmt.Printf("\nTransaction validation:\n") 120 for _, m := range request.Callinfo { 121 fmt.Printf(" * %s : %s", m.Typ, m.Message) 122 } 123 fmt.Println() 124 125 } 126 fmt.Printf("\n") 127 showMetadata(request.Meta) 128 fmt.Printf("-------------------------------------------\n") 129 if !ui.confirm() { 130 return SignTxResponse{request.Transaction, false, ""}, nil 131 } 132 return SignTxResponse{request.Transaction, true, ui.readPassword()}, nil 133 } 134 135 //ApproveSignData提示用户确认请求签署数据 136 func (ui *CommandlineUI) ApproveSignData(request *SignDataRequest) (SignDataResponse, error) { 137 ui.mu.Lock() 138 defer ui.mu.Unlock() 139 140 fmt.Printf("-------- Sign data request--------------\n") 141 fmt.Printf("Account: %s\n", request.Address.String()) 142 fmt.Printf("message: \n%q\n", request.Message) 143 fmt.Printf("raw data: \n%v\n", request.Rawdata) 144 fmt.Printf("message hash: %v\n", request.Hash) 145 fmt.Printf("-------------------------------------------\n") 146 showMetadata(request.Meta) 147 if !ui.confirm() { 148 return SignDataResponse{false, ""}, nil 149 } 150 return SignDataResponse{true, ui.readPassword()}, nil 151 } 152 153 //approveexport提示用户确认导出加密帐户json 154 func (ui *CommandlineUI) ApproveExport(request *ExportRequest) (ExportResponse, error) { 155 ui.mu.Lock() 156 defer ui.mu.Unlock() 157 158 fmt.Printf("-------- Export Account request--------------\n") 159 fmt.Printf("A request has been made to export the (encrypted) keyfile\n") 160 fmt.Printf("Approving this operation means that the caller obtains the (encrypted) contents\n") 161 fmt.Printf("\n") 162 fmt.Printf("Account: %x\n", request.Address) 163 //fmt.printf(“keyfile:\n%v\n”,request.file) 164 fmt.Printf("-------------------------------------------\n") 165 showMetadata(request.Meta) 166 return ExportResponse{ui.confirm()}, nil 167 } 168 169 //approveImport提示用户确认导入账号json 170 func (ui *CommandlineUI) ApproveImport(request *ImportRequest) (ImportResponse, error) { 171 ui.mu.Lock() 172 defer ui.mu.Unlock() 173 174 fmt.Printf("-------- Import Account request--------------\n") 175 fmt.Printf("A request has been made to import an encrypted keyfile\n") 176 fmt.Printf("-------------------------------------------\n") 177 showMetadata(request.Meta) 178 if !ui.confirm() { 179 return ImportResponse{false, "", ""}, nil 180 } 181 return ImportResponse{true, ui.readPasswordText("Old password"), ui.readPasswordText("New password")}, nil 182 } 183 184 //批准提示用户确认列出帐户 185 //用户界面可以修改要列出的科目列表 186 func (ui *CommandlineUI) ApproveListing(request *ListRequest) (ListResponse, error) { 187 188 ui.mu.Lock() 189 defer ui.mu.Unlock() 190 191 fmt.Printf("-------- List Account request--------------\n") 192 fmt.Printf("A request has been made to list all accounts. \n") 193 fmt.Printf("You can select which accounts the caller can see\n") 194 for _, account := range request.Accounts { 195 fmt.Printf("\t[x] %v\n", account.Address.Hex()) 196 } 197 fmt.Printf("-------------------------------------------\n") 198 showMetadata(request.Meta) 199 if !ui.confirm() { 200 return ListResponse{nil}, nil 201 } 202 return ListResponse{request.Accounts}, nil 203 } 204 205 //ApproveWaccount提示用户确认创建新帐户,并显示给调用方 206 func (ui *CommandlineUI) ApproveNewAccount(request *NewAccountRequest) (NewAccountResponse, error) { 207 208 ui.mu.Lock() 209 defer ui.mu.Unlock() 210 211 fmt.Printf("-------- New Account request--------------\n") 212 fmt.Printf("A request has been made to create a new. \n") 213 fmt.Printf("Approving this operation means that a new Account is created,\n") 214 fmt.Printf("and the address show to the caller\n") 215 showMetadata(request.Meta) 216 if !ui.confirm() { 217 return NewAccountResponse{false, ""}, nil 218 } 219 return NewAccountResponse{true, ui.readPassword()}, nil 220 } 221 222 //ShowError向用户显示错误消息 223 func (ui *CommandlineUI) ShowError(message string) { 224 225 fmt.Printf("ERROR: %v\n", message) 226 } 227 228 //ShowInfo向用户显示信息消息 229 func (ui *CommandlineUI) ShowInfo(message string) { 230 fmt.Printf("Info: %v\n", message) 231 } 232 233 func (ui *CommandlineUI) OnApprovedTx(tx ethapi.SignTransactionResult) { 234 fmt.Printf("Transaction signed:\n ") 235 spew.Dump(tx.Tx) 236 } 237 238 func (ui *CommandlineUI) OnSignerStartup(info StartupInfo) { 239 240 fmt.Printf("------- Signer info -------\n") 241 for k, v := range info.Info { 242 fmt.Printf("* %v : %v\n", k, v) 243 } 244 } 245