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