github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/signer/rules/rules_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  //</624450110952050688>
    11  
    12  //
    13  package rules
    14  
    15  import (
    16  	"fmt"
    17  	"math/big"
    18  	"strings"
    19  	"testing"
    20  
    21  	"github.com/ethereum/go-ethereum/accounts"
    22  	"github.com/ethereum/go-ethereum/common"
    23  	"github.com/ethereum/go-ethereum/common/hexutil"
    24  	"github.com/ethereum/go-ethereum/core/types"
    25  	"github.com/ethereum/go-ethereum/internal/ethapi"
    26  	"github.com/ethereum/go-ethereum/signer/core"
    27  	"github.com/ethereum/go-ethereum/signer/storage"
    28  )
    29  
    30  const JS = `
    31  /*
    32  这是一个JavaScript规则文件的示例实现。
    33  
    34  当签名者通过外部API接收到请求时,将计算相应的方法。
    35  可能发生三件事:
    36  
    37  1。方法返回“批准”。这意味着操作是允许的。
    38  2。方法返回“reject”。这意味着操作被拒绝。
    39  三。其他任何内容;其他返回值[*],方法未实现或在处理过程中发生异常。这意味着
    40  操作将继续通过用户选择的常规UI方法进行手动处理。
    41  
    42  [*]注意:未来版本的规则集可能会使用更复杂的基于JSON的返回值,因此可能不会
    43  只响应批准/拒绝/手动,但也修改响应。例如,选择只列出一个,而不是全部
    44  列表请求中的帐户。以上几点将继续适用于非基于JSON的响应(“批准”/“拒绝”)。
    45  
    46  */
    47  
    48  
    49  function ApproveListing(request){
    50  	console.log("In js approve listing");
    51  	console.log(request.accounts[3].Address)
    52  	console.log(request.meta.Remote)
    53  	return "Approve"
    54  }
    55  
    56  function ApproveTx(request){
    57  	console.log("test");
    58  	console.log("from");
    59  	return "Reject";
    60  }
    61  
    62  function test(thing){
    63  	console.log(thing.String())
    64  }
    65  
    66  `
    67  
    68  func mixAddr(a string) (*common.MixedcaseAddress, error) {
    69  	return common.NewMixedcaseAddressFromString(a)
    70  }
    71  
    72  type alwaysDenyUI struct{}
    73  
    74  func (alwaysDenyUI) OnInputRequired(info core.UserInputRequest) (core.UserInputResponse, error) {
    75  	return core.UserInputResponse{}, nil
    76  }
    77  
    78  func (alwaysDenyUI) OnSignerStartup(info core.StartupInfo) {
    79  }
    80  
    81  func (alwaysDenyUI) OnMasterPassword(request *core.PasswordRequest) (core.PasswordResponse, error) {
    82  	return core.PasswordResponse{}, nil
    83  }
    84  
    85  func (alwaysDenyUI) ApproveTx(request *core.SignTxRequest) (core.SignTxResponse, error) {
    86  	return core.SignTxResponse{Transaction: request.Transaction, Approved: false, Password: ""}, nil
    87  }
    88  
    89  func (alwaysDenyUI) ApproveSignData(request *core.SignDataRequest) (core.SignDataResponse, error) {
    90  	return core.SignDataResponse{Approved: false, Password: ""}, nil
    91  }
    92  
    93  func (alwaysDenyUI) ApproveExport(request *core.ExportRequest) (core.ExportResponse, error) {
    94  	return core.ExportResponse{Approved: false}, nil
    95  }
    96  
    97  func (alwaysDenyUI) ApproveImport(request *core.ImportRequest) (core.ImportResponse, error) {
    98  	return core.ImportResponse{Approved: false, OldPassword: "", NewPassword: ""}, nil
    99  }
   100  
   101  func (alwaysDenyUI) ApproveListing(request *core.ListRequest) (core.ListResponse, error) {
   102  	return core.ListResponse{Accounts: nil}, nil
   103  }
   104  
   105  func (alwaysDenyUI) ApproveNewAccount(request *core.NewAccountRequest) (core.NewAccountResponse, error) {
   106  	return core.NewAccountResponse{Approved: false, Password: ""}, nil
   107  }
   108  
   109  func (alwaysDenyUI) ShowError(message string) {
   110  	panic("implement me")
   111  }
   112  
   113  func (alwaysDenyUI) ShowInfo(message string) {
   114  	panic("implement me")
   115  }
   116  
   117  func (alwaysDenyUI) OnApprovedTx(tx ethapi.SignTransactionResult) {
   118  	panic("implement me")
   119  }
   120  
   121  func initRuleEngine(js string) (*rulesetUI, error) {
   122  	r, err := NewRuleEvaluator(&alwaysDenyUI{}, storage.NewEphemeralStorage(), storage.NewEphemeralStorage())
   123  	if err != nil {
   124  		return nil, fmt.Errorf("failed to create js engine: %v", err)
   125  	}
   126  	if err = r.Init(js); err != nil {
   127  		return nil, fmt.Errorf("failed to load bootstrap js: %v", err)
   128  	}
   129  	return r, nil
   130  }
   131  
   132  func TestListRequest(t *testing.T) {
   133  	accs := make([]core.Account, 5)
   134  
   135  	for i := range accs {
   136  		addr := fmt.Sprintf("000000000000000000000000000000000000000%x", i)
   137  		acc := core.Account{
   138  			Address: common.BytesToAddress(common.Hex2Bytes(addr)),
   139  			URL:     accounts.URL{Scheme: "test", Path: fmt.Sprintf("acc-%d", i)},
   140  		}
   141  		accs[i] = acc
   142  	}
   143  
   144  	js := `function ApproveListing(){ return "Approve" }`
   145  
   146  	r, err := initRuleEngine(js)
   147  	if err != nil {
   148  		t.Errorf("Couldn't create evaluator %v", err)
   149  		return
   150  	}
   151  	resp, _ := r.ApproveListing(&core.ListRequest{
   152  		Accounts: accs,
   153  		Meta:     core.Metadata{Remote: "remoteip", Local: "localip", Scheme: "inproc"},
   154  	})
   155  	if len(resp.Accounts) != len(accs) {
   156  		t.Errorf("Expected check to resolve to 'Approve'")
   157  	}
   158  }
   159  
   160  func TestSignTxRequest(t *testing.T) {
   161  
   162  	js := `
   163  	function ApproveTx(r){
   164  		console.log("transaction.from", r.transaction.from);
   165  		console.log("transaction.to", r.transaction.to);
   166  		console.log("transaction.value", r.transaction.value);
   167  		console.log("transaction.nonce", r.transaction.nonce);
   168  		if(r.transaction.from.toLowerCase()=="0x0000000000000000000000000000000000001337"){ return "Approve"}
   169  		if(r.transaction.from.toLowerCase()=="0x000000000000000000000000000000000000dead"){ return "Reject"}
   170  	}`
   171  
   172  	r, err := initRuleEngine(js)
   173  	if err != nil {
   174  		t.Errorf("Couldn't create evaluator %v", err)
   175  		return
   176  	}
   177  	to, err := mixAddr("000000000000000000000000000000000000dead")
   178  	if err != nil {
   179  		t.Error(err)
   180  		return
   181  	}
   182  	from, err := mixAddr("0000000000000000000000000000000000001337")
   183  
   184  	if err != nil {
   185  		t.Error(err)
   186  		return
   187  	}
   188  	fmt.Printf("to %v", to.Address().String())
   189  	resp, err := r.ApproveTx(&core.SignTxRequest{
   190  		Transaction: core.SendTxArgs{
   191  			From: *from,
   192  			To:   to},
   193  		Callinfo: nil,
   194  		Meta:     core.Metadata{Remote: "remoteip", Local: "localip", Scheme: "inproc"},
   195  	})
   196  	if err != nil {
   197  		t.Errorf("Unexpected error %v", err)
   198  	}
   199  	if !resp.Approved {
   200  		t.Errorf("Expected check to resolve to 'Approve'")
   201  	}
   202  }
   203  
   204  type dummyUI struct {
   205  	calls []string
   206  }
   207  
   208  func (d *dummyUI) OnInputRequired(info core.UserInputRequest) (core.UserInputResponse, error) {
   209  	d.calls = append(d.calls, "OnInputRequired")
   210  	return core.UserInputResponse{}, nil
   211  }
   212  
   213  func (d *dummyUI) ApproveTx(request *core.SignTxRequest) (core.SignTxResponse, error) {
   214  	d.calls = append(d.calls, "ApproveTx")
   215  	return core.SignTxResponse{}, core.ErrRequestDenied
   216  }
   217  
   218  func (d *dummyUI) ApproveSignData(request *core.SignDataRequest) (core.SignDataResponse, error) {
   219  	d.calls = append(d.calls, "ApproveSignData")
   220  	return core.SignDataResponse{}, core.ErrRequestDenied
   221  }
   222  
   223  func (d *dummyUI) ApproveExport(request *core.ExportRequest) (core.ExportResponse, error) {
   224  	d.calls = append(d.calls, "ApproveExport")
   225  	return core.ExportResponse{}, core.ErrRequestDenied
   226  }
   227  
   228  func (d *dummyUI) ApproveImport(request *core.ImportRequest) (core.ImportResponse, error) {
   229  	d.calls = append(d.calls, "ApproveImport")
   230  	return core.ImportResponse{}, core.ErrRequestDenied
   231  }
   232  
   233  func (d *dummyUI) ApproveListing(request *core.ListRequest) (core.ListResponse, error) {
   234  	d.calls = append(d.calls, "ApproveListing")
   235  	return core.ListResponse{}, core.ErrRequestDenied
   236  }
   237  
   238  func (d *dummyUI) ApproveNewAccount(request *core.NewAccountRequest) (core.NewAccountResponse, error) {
   239  	d.calls = append(d.calls, "ApproveNewAccount")
   240  	return core.NewAccountResponse{}, core.ErrRequestDenied
   241  }
   242  
   243  func (d *dummyUI) ShowError(message string) {
   244  	d.calls = append(d.calls, "ShowError")
   245  }
   246  
   247  func (d *dummyUI) ShowInfo(message string) {
   248  	d.calls = append(d.calls, "ShowInfo")
   249  }
   250  
   251  func (d *dummyUI) OnApprovedTx(tx ethapi.SignTransactionResult) {
   252  	d.calls = append(d.calls, "OnApprovedTx")
   253  }
   254  
   255  func (d *dummyUI) OnMasterPassword(request *core.PasswordRequest) (core.PasswordResponse, error) {
   256  	return core.PasswordResponse{}, nil
   257  }
   258  
   259  func (d *dummyUI) OnSignerStartup(info core.StartupInfo) {
   260  }
   261  
   262  //TestForwarding测试规则引擎是否正确地将请求分派给下一个调用方
   263  func TestForwarding(t *testing.T) {
   264  
   265  	js := ""
   266  	ui := &dummyUI{make([]string, 0)}
   267  	jsBackend := storage.NewEphemeralStorage()
   268  	credBackend := storage.NewEphemeralStorage()
   269  	r, err := NewRuleEvaluator(ui, jsBackend, credBackend)
   270  	if err != nil {
   271  		t.Fatalf("Failed to create js engine: %v", err)
   272  	}
   273  	if err = r.Init(js); err != nil {
   274  		t.Fatalf("Failed to load bootstrap js: %v", err)
   275  	}
   276  	r.ApproveSignData(nil)
   277  	r.ApproveTx(nil)
   278  	r.ApproveImport(nil)
   279  	r.ApproveNewAccount(nil)
   280  	r.ApproveListing(nil)
   281  	r.ApproveExport(nil)
   282  	r.ShowError("test")
   283  	r.ShowInfo("test")
   284  
   285  //这个没有转发
   286  	r.OnApprovedTx(ethapi.SignTransactionResult{})
   287  
   288  	expCalls := 8
   289  	if len(ui.calls) != expCalls {
   290  
   291  		t.Errorf("Expected %d forwarded calls, got %d: %s", expCalls, len(ui.calls), strings.Join(ui.calls, ","))
   292  
   293  	}
   294  
   295  }
   296  
   297  func TestMissingFunc(t *testing.T) {
   298  	r, err := initRuleEngine(JS)
   299  	if err != nil {
   300  		t.Errorf("Couldn't create evaluator %v", err)
   301  		return
   302  	}
   303  
   304  	_, err = r.execute("MissingMethod", "test")
   305  
   306  	if err == nil {
   307  		t.Error("Expected error")
   308  	}
   309  
   310  	approved, err := r.checkApproval("MissingMethod", nil, nil)
   311  	if err == nil {
   312  		t.Errorf("Expected missing method to yield error'")
   313  	}
   314  	if approved {
   315  		t.Errorf("Expected missing method to cause non-approval")
   316  	}
   317  	fmt.Printf("Err %v", err)
   318  
   319  }
   320  func TestStorage(t *testing.T) {
   321  
   322  	js := `
   323  	function testStorage(){
   324  		storage.Put("mykey", "myvalue")
   325  		a = storage.Get("mykey")
   326  
   327  storage.Put("mykey", ["a", "list"])  	//应生成“a,list”
   328  		a += storage.Get("mykey")
   329  
   330  
   331  storage.Put("mykey", {"an": "object"}) 	//应导致“[对象对象]”
   332  		a += storage.Get("mykey")
   333  
   334  
   335  storage.Put("mykey", JSON.stringify({"an": "object"})) //应导致“”an“:”对象“”
   336  		a += storage.Get("mykey")
   337  
   338  a += storage.Get("missingkey")		//缺少键应导致空字符串
   339  storage.Put("","missing key==noop") //无法使用0长度密钥存储
   340  a += storage.Get("")				//应导致“”。
   341  
   342  		var b = new BigNumber(2)
   343  var c = new BigNumber(16)//“0xF0”,16)
   344  		var d = b.plus(c)
   345  		console.log(d)
   346  		return a
   347  	}
   348  `
   349  	r, err := initRuleEngine(js)
   350  	if err != nil {
   351  		t.Errorf("Couldn't create evaluator %v", err)
   352  		return
   353  	}
   354  
   355  	v, err := r.execute("testStorage", nil)
   356  
   357  	if err != nil {
   358  		t.Errorf("Unexpected error %v", err)
   359  	}
   360  
   361  	retval, err := v.ToString()
   362  
   363  	if err != nil {
   364  		t.Errorf("Unexpected error %v", err)
   365  	}
   366  	exp := `myvaluea,list[object Object]{"an":"object"}`
   367  	if retval != exp {
   368  		t.Errorf("Unexpected data, expected '%v', got '%v'", exp, retval)
   369  	}
   370  	fmt.Printf("Err %v", err)
   371  
   372  }
   373  
   374  const ExampleTxWindow = `
   375  	function big(str){
   376  		if(str.slice(0,2) == "0x"){ return new BigNumber(str.slice(2),16)}
   377  		return new BigNumber(str)
   378  	}
   379  
   380  //时间窗口:1周
   381  	var window = 1000* 3600*24*7;
   382  
   383  //极限:1醚
   384  	var limit = new BigNumber("1e18");
   385  
   386  	function isLimitOk(transaction){
   387  		var value = big(transaction.value)
   388  //启动窗口功能
   389  		var windowstart = new Date().getTime() - window;
   390  
   391  		var txs = [];
   392  		var stored = storage.Get('txs');
   393  
   394  		if(stored != ""){
   395  			txs = JSON.parse(stored)
   396  		}
   397  //首先,删除时间窗口之外的所有内容
   398  		var newtxs = txs.filter(function(tx){return tx.tstamp > windowstart});
   399  		console.log(txs, newtxs.length);
   400  
   401  //第二,合计当前总额
   402  		sum = new BigNumber(0)
   403  
   404  		sum = newtxs.reduce(function(agg, tx){ return big(tx.value).plus(agg)}, sum);
   405  		console.log("ApproveTx > Sum so far", sum);
   406  		console.log("ApproveTx > Requested", value.toNumber());
   407  
   408  //我们会超过每周限额吗?
   409  		return sum.plus(value).lt(limit)
   410  
   411  	}
   412  	function ApproveTx(r){
   413  		console.log(r)
   414  		console.log(typeof(r))
   415  		if (isLimitOk(r.transaction)){
   416  			return "Approve"
   417  		}
   418  		return "Nope"
   419  	}
   420  
   421   /*
   422   *OnApprovedTx(str)在交易被批准和签署后调用。参数
   423    *“response_str”包含将发送给外部调用方的返回值。
   424   *此方法的返回值为ignore-进行此回调的原因是允许
   425   *用于跟踪已批准交易的规则集。
   426   *
   427   *在执行速率限制规则时,应使用此回调。
   428   *如果规则的响应既不包含“批准”也不包含“拒绝”,则发送将进入手动处理。如果用户
   429   *然后接受事务,将调用此方法。
   430   *
   431   *tldr;使用此方法跟踪已签名的事务,而不是使用approvetx中的数据。
   432   **/
   433  
   434   	function OnApprovedTx(resp){
   435  		var value = big(resp.tx.value)
   436  		var txs = []
   437  //加载存储的事务
   438  		var stored = storage.Get('txs');
   439  		if(stored != ""){
   440  			txs = JSON.parse(stored)
   441  		}
   442  //将此添加到存储
   443  		txs.push({tstamp: new Date().getTime(), value: value});
   444  		storage.Put("txs", JSON.stringify(txs));
   445  	}
   446  
   447  `
   448  
   449  func dummyTx(value hexutil.Big) *core.SignTxRequest {
   450  
   451  	to, _ := mixAddr("000000000000000000000000000000000000dead")
   452  	from, _ := mixAddr("000000000000000000000000000000000000dead")
   453  	n := hexutil.Uint64(3)
   454  	gas := hexutil.Uint64(21000)
   455  	gasPrice := hexutil.Big(*big.NewInt(2000000))
   456  
   457  	return &core.SignTxRequest{
   458  		Transaction: core.SendTxArgs{
   459  			From:     *from,
   460  			To:       to,
   461  			Value:    value,
   462  			Nonce:    n,
   463  			GasPrice: gasPrice,
   464  			Gas:      gas,
   465  		},
   466  		Callinfo: []core.ValidationInfo{
   467  			{Typ: "Warning", Message: "All your base are bellong to us"},
   468  		},
   469  		Meta: core.Metadata{Remote: "remoteip", Local: "localip", Scheme: "inproc"},
   470  	}
   471  }
   472  func dummyTxWithV(value uint64) *core.SignTxRequest {
   473  
   474  	v := big.NewInt(0).SetUint64(value)
   475  	h := hexutil.Big(*v)
   476  	return dummyTx(h)
   477  }
   478  func dummySigned(value *big.Int) *types.Transaction {
   479  	to := common.HexToAddress("000000000000000000000000000000000000dead")
   480  	gas := uint64(21000)
   481  	gasPrice := big.NewInt(2000000)
   482  	data := make([]byte, 0)
   483  	return types.NewTransaction(3, to, value, gas, gasPrice, data)
   484  
   485  }
   486  func TestLimitWindow(t *testing.T) {
   487  
   488  	r, err := initRuleEngine(ExampleTxWindow)
   489  	if err != nil {
   490  		t.Errorf("Couldn't create evaluator %v", err)
   491  		return
   492  	}
   493  
   494  //0.3乙醚:429D069189E0000 wei
   495  	v := big.NewInt(0).SetBytes(common.Hex2Bytes("0429D069189E0000"))
   496  	h := hexutil.Big(*v)
   497  //前三个应该成功
   498  	for i := 0; i < 3; i++ {
   499  		unsigned := dummyTx(h)
   500  		resp, err := r.ApproveTx(unsigned)
   501  		if err != nil {
   502  			t.Errorf("Unexpected error %v", err)
   503  		}
   504  		if !resp.Approved {
   505  			t.Errorf("Expected check to resolve to 'Approve'")
   506  		}
   507  //创建虚拟签名事务
   508  
   509  		response := ethapi.SignTransactionResult{
   510  			Tx:  dummySigned(v),
   511  			Raw: common.Hex2Bytes("deadbeef"),
   512  		}
   513  		r.OnApprovedTx(response)
   514  	}
   515  //第四个应该失败
   516  	resp, _ := r.ApproveTx(dummyTx(h))
   517  	if resp.Approved {
   518  		t.Errorf("Expected check to resolve to 'Reject'")
   519  	}
   520  
   521  }
   522  
   523  //dontcallme用作不希望调用的下一个处理程序-它调用测试失败
   524  type dontCallMe struct {
   525  	t *testing.T
   526  }
   527  
   528  func (d *dontCallMe) OnInputRequired(info core.UserInputRequest) (core.UserInputResponse, error) {
   529  	d.t.Fatalf("Did not expect next-handler to be called")
   530  	return core.UserInputResponse{}, nil
   531  }
   532  
   533  func (d *dontCallMe) OnSignerStartup(info core.StartupInfo) {
   534  }
   535  
   536  func (d *dontCallMe) OnMasterPassword(request *core.PasswordRequest) (core.PasswordResponse, error) {
   537  	return core.PasswordResponse{}, nil
   538  }
   539  
   540  func (d *dontCallMe) ApproveTx(request *core.SignTxRequest) (core.SignTxResponse, error) {
   541  	d.t.Fatalf("Did not expect next-handler to be called")
   542  	return core.SignTxResponse{}, core.ErrRequestDenied
   543  }
   544  
   545  func (d *dontCallMe) ApproveSignData(request *core.SignDataRequest) (core.SignDataResponse, error) {
   546  	d.t.Fatalf("Did not expect next-handler to be called")
   547  	return core.SignDataResponse{}, core.ErrRequestDenied
   548  }
   549  
   550  func (d *dontCallMe) ApproveExport(request *core.ExportRequest) (core.ExportResponse, error) {
   551  	d.t.Fatalf("Did not expect next-handler to be called")
   552  	return core.ExportResponse{}, core.ErrRequestDenied
   553  }
   554  
   555  func (d *dontCallMe) ApproveImport(request *core.ImportRequest) (core.ImportResponse, error) {
   556  	d.t.Fatalf("Did not expect next-handler to be called")
   557  	return core.ImportResponse{}, core.ErrRequestDenied
   558  }
   559  
   560  func (d *dontCallMe) ApproveListing(request *core.ListRequest) (core.ListResponse, error) {
   561  	d.t.Fatalf("Did not expect next-handler to be called")
   562  	return core.ListResponse{}, core.ErrRequestDenied
   563  }
   564  
   565  func (d *dontCallMe) ApproveNewAccount(request *core.NewAccountRequest) (core.NewAccountResponse, error) {
   566  	d.t.Fatalf("Did not expect next-handler to be called")
   567  	return core.NewAccountResponse{}, core.ErrRequestDenied
   568  }
   569  
   570  func (d *dontCallMe) ShowError(message string) {
   571  	d.t.Fatalf("Did not expect next-handler to be called")
   572  }
   573  
   574  func (d *dontCallMe) ShowInfo(message string) {
   575  	d.t.Fatalf("Did not expect next-handler to be called")
   576  }
   577  
   578  func (d *dontCallMe) OnApprovedTx(tx ethapi.SignTransactionResult) {
   579  	d.t.Fatalf("Did not expect next-handler to be called")
   580  }
   581  
   582  //testcontext清除了规则引擎不在多个请求上保留变量的测试。
   583  //如果是这样,那就不好了,因为开发人员可能会依赖它来存储数据,
   584  //而不是使用基于磁盘的数据存储
   585  func TestContextIsCleared(t *testing.T) {
   586  
   587  	js := `
   588  	function ApproveTx(){
   589  		if (typeof foobar == 'undefined') {
   590  			foobar = "Approve"
   591   		}
   592  		console.log(foobar)
   593  		if (foobar == "Approve"){
   594  			foobar = "Reject"
   595  		}else{
   596  			foobar = "Approve"
   597  		}
   598  		return foobar
   599  	}
   600  	`
   601  	ui := &dontCallMe{t}
   602  	r, err := NewRuleEvaluator(ui, storage.NewEphemeralStorage(), storage.NewEphemeralStorage())
   603  	if err != nil {
   604  		t.Fatalf("Failed to create js engine: %v", err)
   605  	}
   606  	if err = r.Init(js); err != nil {
   607  		t.Fatalf("Failed to load bootstrap js: %v", err)
   608  	}
   609  	tx := dummyTxWithV(0)
   610  	r1, _ := r.ApproveTx(tx)
   611  	r2, _ := r.ApproveTx(tx)
   612  	if r1.Approved != r2.Approved {
   613  		t.Errorf("Expected execution context to be cleared between executions")
   614  	}
   615  }
   616  
   617  func TestSignData(t *testing.T) {
   618  
   619  	js := `function ApproveListing(){
   620      return "Approve"
   621  }
   622  function ApproveSignData(r){
   623      if( r.address.toLowerCase() == "0x694267f14675d7e1b9494fd8d72fefe1755710fa")
   624      {
   625          if(r.message.indexOf("bazonk") >= 0){
   626              return "Approve"
   627          }
   628          return "Reject"
   629      }
   630  //否则进入手动处理
   631  }`
   632  	r, err := initRuleEngine(js)
   633  	if err != nil {
   634  		t.Errorf("Couldn't create evaluator %v", err)
   635  		return
   636  	}
   637  	message := []byte("baz bazonk foo")
   638  	hash, msg := core.SignHash(message)
   639  	raw := hexutil.Bytes(message)
   640  	addr, _ := mixAddr("0x694267f14675d7e1b9494fd8d72fefe1755710fa")
   641  
   642  	fmt.Printf("address %v %v\n", addr.String(), addr.Original())
   643  	resp, err := r.ApproveSignData(&core.SignDataRequest{
   644  		Address: *addr,
   645  		Message: msg,
   646  		Hash:    hash,
   647  		Meta:    core.Metadata{Remote: "remoteip", Local: "localip", Scheme: "inproc"},
   648  		Rawdata: raw,
   649  	})
   650  	if err != nil {
   651  		t.Fatalf("Unexpected error %v", err)
   652  	}
   653  	if !resp.Approved {
   654  		t.Fatalf("Expected approved")
   655  	}
   656  }
   657