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