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