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