github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/signer/core/api_test.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 //</624450110339682304> 11 12 // 13 package core 14 15 import ( 16 "bytes" 17 "context" 18 "errors" 19 "fmt" 20 "io/ioutil" 21 "math/big" 22 "os" 23 "path/filepath" 24 "testing" 25 "time" 26 27 "github.com/ethereum/go-ethereum/accounts/keystore" 28 "github.com/ethereum/go-ethereum/cmd/utils" 29 "github.com/ethereum/go-ethereum/common" 30 "github.com/ethereum/go-ethereum/common/hexutil" 31 "github.com/ethereum/go-ethereum/core/types" 32 "github.com/ethereum/go-ethereum/internal/ethapi" 33 "github.com/ethereum/go-ethereum/rlp" 34 ) 35 36 //用于测试 37 type HeadlessUI struct { 38 controller chan string 39 } 40 41 func (ui *HeadlessUI) OnInputRequired(info UserInputRequest) (UserInputResponse, error) { 42 return UserInputResponse{}, errors.New("not implemented") 43 } 44 45 func (ui *HeadlessUI) OnSignerStartup(info StartupInfo) { 46 } 47 48 func (ui *HeadlessUI) OnApprovedTx(tx ethapi.SignTransactionResult) { 49 fmt.Printf("OnApproved()\n") 50 } 51 52 func (ui *HeadlessUI) ApproveTx(request *SignTxRequest) (SignTxResponse, error) { 53 54 switch <-ui.controller { 55 case "Y": 56 return SignTxResponse{request.Transaction, true, <-ui.controller}, nil 57 case "M": //修改 58 old := big.Int(request.Transaction.Value) 59 newVal := big.NewInt(0).Add(&old, big.NewInt(1)) 60 request.Transaction.Value = hexutil.Big(*newVal) 61 return SignTxResponse{request.Transaction, true, <-ui.controller}, nil 62 default: 63 return SignTxResponse{request.Transaction, false, ""}, nil 64 } 65 } 66 67 func (ui *HeadlessUI) ApproveSignData(request *SignDataRequest) (SignDataResponse, error) { 68 if "Y" == <-ui.controller { 69 return SignDataResponse{true, <-ui.controller}, nil 70 } 71 return SignDataResponse{false, ""}, nil 72 } 73 74 func (ui *HeadlessUI) ApproveExport(request *ExportRequest) (ExportResponse, error) { 75 return ExportResponse{<-ui.controller == "Y"}, nil 76 77 } 78 79 func (ui *HeadlessUI) ApproveImport(request *ImportRequest) (ImportResponse, error) { 80 if "Y" == <-ui.controller { 81 return ImportResponse{true, <-ui.controller, <-ui.controller}, nil 82 } 83 return ImportResponse{false, "", ""}, nil 84 } 85 86 func (ui *HeadlessUI) ApproveListing(request *ListRequest) (ListResponse, error) { 87 switch <-ui.controller { 88 case "A": 89 return ListResponse{request.Accounts}, nil 90 case "1": 91 l := make([]Account, 1) 92 l[0] = request.Accounts[1] 93 return ListResponse{l}, nil 94 default: 95 return ListResponse{nil}, nil 96 } 97 } 98 99 func (ui *HeadlessUI) ApproveNewAccount(request *NewAccountRequest) (NewAccountResponse, error) { 100 if "Y" == <-ui.controller { 101 return NewAccountResponse{true, <-ui.controller}, nil 102 } 103 return NewAccountResponse{false, ""}, nil 104 } 105 106 func (ui *HeadlessUI) ShowError(message string) { 107 //stdout用于通信 108 fmt.Fprintln(os.Stderr, message) 109 } 110 111 func (ui *HeadlessUI) ShowInfo(message string) { 112 //stdout用于通信 113 fmt.Fprintln(os.Stderr, message) 114 } 115 116 func tmpDirName(t *testing.T) string { 117 d, err := ioutil.TempDir("", "eth-keystore-test") 118 if err != nil { 119 t.Fatal(err) 120 } 121 d, err = filepath.EvalSymlinks(d) 122 if err != nil { 123 t.Fatal(err) 124 } 125 return d 126 } 127 128 func setup(t *testing.T) (*SignerAPI, chan string) { 129 130 controller := make(chan string, 20) 131 132 db, err := NewAbiDBFromFile("../../cmd/clef/4byte.json") 133 if err != nil { 134 utils.Fatalf(err.Error()) 135 } 136 var ( 137 ui = &HeadlessUI{controller} 138 api = NewSignerAPI( 139 1, 140 tmpDirName(t), 141 true, 142 ui, 143 db, 144 true, true) 145 ) 146 return api, controller 147 } 148 func createAccount(control chan string, api *SignerAPI, t *testing.T) { 149 150 control <- "Y" 151 control <- "a_long_password" 152 _, err := api.New(context.Background()) 153 if err != nil { 154 t.Fatal(err) 155 } 156 //允许传播更改的一段时间 157 time.Sleep(250 * time.Millisecond) 158 } 159 160 func failCreateAccountWithPassword(control chan string, api *SignerAPI, password string, t *testing.T) { 161 162 control <- "Y" 163 control <- password 164 control <- "Y" 165 control <- password 166 control <- "Y" 167 control <- password 168 169 acc, err := api.New(context.Background()) 170 if err == nil { 171 t.Fatal("Should have returned an error") 172 } 173 if acc.Address != (common.Address{}) { 174 t.Fatal("Empty address should be returned") 175 } 176 } 177 178 func failCreateAccount(control chan string, api *SignerAPI, t *testing.T) { 179 control <- "N" 180 acc, err := api.New(context.Background()) 181 if err != ErrRequestDenied { 182 t.Fatal(err) 183 } 184 if acc.Address != (common.Address{}) { 185 t.Fatal("Empty address should be returned") 186 } 187 } 188 189 func list(control chan string, api *SignerAPI, t *testing.T) []common.Address { 190 control <- "A" 191 list, err := api.List(context.Background()) 192 if err != nil { 193 t.Fatal(err) 194 } 195 return list 196 } 197 198 func TestNewAcc(t *testing.T) { 199 api, control := setup(t) 200 verifyNum := func(num int) { 201 if list := list(control, api, t); len(list) != num { 202 t.Errorf("Expected %d accounts, got %d", num, len(list)) 203 } 204 } 205 //测试创建和创建拒绝 206 createAccount(control, api, t) 207 createAccount(control, api, t) 208 failCreateAccount(control, api, t) 209 failCreateAccount(control, api, t) 210 createAccount(control, api, t) 211 failCreateAccount(control, api, t) 212 createAccount(control, api, t) 213 failCreateAccount(control, api, t) 214 215 verifyNum(4) 216 217 //由于密码错误,无法创建此文件 218 failCreateAccountWithPassword(control, api, "short", t) 219 failCreateAccountWithPassword(control, api, "longerbutbad\rfoo", t) 220 221 verifyNum(4) 222 223 //测试列表: 224 //列出一个帐户 225 control <- "1" 226 list, err := api.List(context.Background()) 227 if err != nil { 228 t.Fatal(err) 229 } 230 if len(list) != 1 { 231 t.Fatalf("List should only show one Account") 232 } 233 //拒绝上市 234 control <- "Nope" 235 list, err = api.List(context.Background()) 236 if len(list) != 0 { 237 t.Fatalf("List should be empty") 238 } 239 if err != ErrRequestDenied { 240 t.Fatal("Expected deny") 241 } 242 } 243 244 func TestSignData(t *testing.T) { 245 api, control := setup(t) 246 //创建两个帐户 247 createAccount(control, api, t) 248 createAccount(control, api, t) 249 control <- "1" 250 list, err := api.List(context.Background()) 251 if err != nil { 252 t.Fatal(err) 253 } 254 a := common.NewMixedcaseAddress(list[0]) 255 256 control <- "Y" 257 control <- "wrongpassword" 258 h, err := api.Sign(context.Background(), a, []byte("EHLO world")) 259 if h != nil { 260 t.Errorf("Expected nil-data, got %x", h) 261 } 262 if err != keystore.ErrDecrypt { 263 t.Errorf("Expected ErrLocked! %v", err) 264 } 265 control <- "No way" 266 h, err = api.Sign(context.Background(), a, []byte("EHLO world")) 267 if h != nil { 268 t.Errorf("Expected nil-data, got %x", h) 269 } 270 if err != ErrRequestDenied { 271 t.Errorf("Expected ErrRequestDenied! %v", err) 272 } 273 control <- "Y" 274 control <- "a_long_password" 275 h, err = api.Sign(context.Background(), a, []byte("EHLO world")) 276 if err != nil { 277 t.Fatal(err) 278 } 279 if h == nil || len(h) != 65 { 280 t.Errorf("Expected 65 byte signature (got %d bytes)", len(h)) 281 } 282 } 283 func mkTestTx(from common.MixedcaseAddress) SendTxArgs { 284 to := common.NewMixedcaseAddress(common.HexToAddress("0x1337")) 285 gas := hexutil.Uint64(21000) 286 gasPrice := (hexutil.Big)(*big.NewInt(2000000000)) 287 value := (hexutil.Big)(*big.NewInt(1e18)) 288 nonce := (hexutil.Uint64)(0) 289 data := hexutil.Bytes(common.Hex2Bytes("01020304050607080a")) 290 tx := SendTxArgs{ 291 From: from, 292 To: &to, 293 Gas: gas, 294 GasPrice: gasPrice, 295 Value: value, 296 Data: &data, 297 Nonce: nonce} 298 return tx 299 } 300 301 func TestSignTx(t *testing.T) { 302 var ( 303 list []common.Address 304 res, res2 *ethapi.SignTransactionResult 305 err error 306 ) 307 308 api, control := setup(t) 309 createAccount(control, api, t) 310 control <- "A" 311 list, err = api.List(context.Background()) 312 if err != nil { 313 t.Fatal(err) 314 } 315 a := common.NewMixedcaseAddress(list[0]) 316 317 methodSig := "test(uint)" 318 tx := mkTestTx(a) 319 320 control <- "Y" 321 control <- "wrongpassword" 322 res, err = api.SignTransaction(context.Background(), tx, &methodSig) 323 if res != nil { 324 t.Errorf("Expected nil-response, got %v", res) 325 } 326 if err != keystore.ErrDecrypt { 327 t.Errorf("Expected ErrLocked! %v", err) 328 } 329 control <- "No way" 330 res, err = api.SignTransaction(context.Background(), tx, &methodSig) 331 if res != nil { 332 t.Errorf("Expected nil-response, got %v", res) 333 } 334 if err != ErrRequestDenied { 335 t.Errorf("Expected ErrRequestDenied! %v", err) 336 } 337 control <- "Y" 338 control <- "a_long_password" 339 res, err = api.SignTransaction(context.Background(), tx, &methodSig) 340 341 if err != nil { 342 t.Fatal(err) 343 } 344 parsedTx := &types.Transaction{} 345 rlp.Decode(bytes.NewReader(res.Raw), parsedTx) 346 347 //用户界面不应修改Tx 348 if parsedTx.Value().Cmp(tx.Value.ToInt()) != 0 { 349 t.Errorf("Expected value to be unchanged, expected %v got %v", tx.Value, parsedTx.Value()) 350 } 351 control <- "Y" 352 control <- "a_long_password" 353 354 res2, err = api.SignTransaction(context.Background(), tx, &methodSig) 355 if err != nil { 356 t.Fatal(err) 357 } 358 if !bytes.Equal(res.Raw, res2.Raw) { 359 t.Error("Expected tx to be unmodified by UI") 360 } 361 362 //Tx由用户界面修改 363 control <- "M" 364 control <- "a_long_password" 365 366 res2, err = api.SignTransaction(context.Background(), tx, &methodSig) 367 if err != nil { 368 t.Fatal(err) 369 } 370 parsedTx2 := &types.Transaction{} 371 rlp.Decode(bytes.NewReader(res.Raw), parsedTx2) 372 373 //用户界面应修改Tx 374 if parsedTx2.Value().Cmp(tx.Value.ToInt()) != 0 { 375 t.Errorf("Expected value to be unchanged, got %v", parsedTx.Value()) 376 } 377 if bytes.Equal(res.Raw, res2.Raw) { 378 t.Error("Expected tx to be modified by UI") 379 } 380 381 } 382 383 /* 384 func测试同步响应(t*testing.t) 385 386 //设置一个帐户 387 API,控件:=设置(T) 388 创建帐户(控件、API、T) 389 390 //两个事务,第二个事务的值大于第一个事务的值 391 tx1:=mktestx()。 392 newval:=big.newint(0).add((*big.int)(tx1.value),big.newint(1)) 393 tx2:=mktestx()。 394 tx2.value=(*hexUtil.big)(newval) 395 396 控件<-“w”//等待 397 控制<-“Y”// 398 控件<-“a_long_password” 399 控制<-“Y”// 400 控件<-“a_long_password” 401 402 无功误差 403 404 h1,err:=api.signTransaction(context.background(),common.hextoAddress(“1111”),tx1,nil) 405 h2,错误:=api.signTransaction(context.background(),common.hextoAddress(“2222”),tx2,nil) 406 407 408 } 409 **/ 410 411