github.com/iotexproject/iotex-core@v1.14.1-rc1/api/web3server_test.go (about)

     1  package api
     2  
     3  import (
     4  	"context"
     5  	"encoding/hex"
     6  	"fmt"
     7  	"io"
     8  	"math/big"
     9  	"math/rand"
    10  	"net/http"
    11  	"net/http/httptest"
    12  	"strconv"
    13  	"strings"
    14  	"testing"
    15  	"time"
    16  
    17  	"github.com/ethereum/go-ethereum/eth/tracers/logger"
    18  	"github.com/golang/mock/gomock"
    19  	"github.com/pkg/errors"
    20  	"github.com/stretchr/testify/require"
    21  	"github.com/tidwall/gjson"
    22  	"google.golang.org/protobuf/proto"
    23  
    24  	"github.com/iotexproject/go-pkgs/hash"
    25  	"github.com/iotexproject/go-pkgs/util"
    26  	"github.com/iotexproject/iotex-proto/golang/iotexapi"
    27  	"github.com/iotexproject/iotex-proto/golang/iotextypes"
    28  
    29  	"github.com/iotexproject/iotex-core/action"
    30  	apitypes "github.com/iotexproject/iotex-core/api/types"
    31  	"github.com/iotexproject/iotex-core/blockchain/block"
    32  	"github.com/iotexproject/iotex-core/blockchain/genesis"
    33  	"github.com/iotexproject/iotex-core/test/identityset"
    34  	"github.com/iotexproject/iotex-core/test/mock/mock_apicoreservice"
    35  	mock_apitypes "github.com/iotexproject/iotex-core/test/mock/mock_apiresponder"
    36  	"github.com/iotexproject/iotex-core/testutil"
    37  )
    38  
    39  func TestGetWeb3Reqs(t *testing.T) {
    40  	require := require.New(t)
    41  	testData := []struct {
    42  		testName  string
    43  		req       *http.Request
    44  		hasHeader bool
    45  		hasError  bool
    46  	}{
    47  		{
    48  			testName:  "EmptyData",
    49  			req:       httptest.NewRequest(http.MethodPost, "http://url.com", strings.NewReader("")),
    50  			hasHeader: true,
    51  			hasError:  true,
    52  		},
    53  		{
    54  			testName:  "InvalidHttpMethod",
    55  			req:       httptest.NewRequest(http.MethodPut, "http://url.com", strings.NewReader("")),
    56  			hasHeader: false,
    57  			hasError:  true,
    58  		},
    59  		{
    60  			testName:  "MissingIdField",
    61  			req:       httptest.NewRequest(http.MethodPost, "http://url.com", strings.NewReader(`{"jsonrpc":"2.0","method":"web3_clientVersion"}`)),
    62  			hasHeader: true,
    63  			hasError:  true,
    64  		},
    65  		{
    66  			testName:  "MissingMethodField",
    67  			req:       httptest.NewRequest(http.MethodPost, "http://url.com", strings.NewReader(`{"jsonrpc":"2.0","id":67}`)),
    68  			hasHeader: true,
    69  			hasError:  true,
    70  		},
    71  		{
    72  			testName:  "MissingParamsField",
    73  			req:       httptest.NewRequest(http.MethodPost, "http://url.com", strings.NewReader(`{"jsonrpc":"2.0","method":"web3_clientVersion","id":67}`)),
    74  			hasHeader: true,
    75  			hasError:  false,
    76  		},
    77  		{
    78  			testName:  "Valid",
    79  			req:       httptest.NewRequest(http.MethodPost, "http://url.com", strings.NewReader(`{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":67}`)),
    80  			hasHeader: true,
    81  			hasError:  false,
    82  		},
    83  	}
    84  
    85  	for _, test := range testData {
    86  		t.Run(test.testName, func(t *testing.T) {
    87  			if test.hasHeader {
    88  				test.req.Header.Set("Content-Type", "application/json")
    89  			}
    90  			_, err := parseWeb3Reqs(test.req.Body)
    91  			if test.hasError {
    92  				require.Error(err)
    93  			} else {
    94  				require.NoError(err)
    95  			}
    96  		})
    97  	}
    98  }
    99  
   100  func TestHandlePost(t *testing.T) {
   101  	require := require.New(t)
   102  	ctrl := gomock.NewController(t)
   103  	defer ctrl.Finish()
   104  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   105  	core.EXPECT().Track(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return().AnyTimes()
   106  	svr := newHTTPHandler(NewWeb3Handler(core, "", _defaultBatchRequestLimit))
   107  	getServerResp := func(svr *hTTPHandler, req *http.Request) *httptest.ResponseRecorder {
   108  		req.Header.Set("Content-Type", "application/json")
   109  		resp := httptest.NewRecorder()
   110  		svr.ServeHTTP(resp, req)
   111  		return resp
   112  	}
   113  
   114  	// web3 req without params
   115  	request2, _ := http.NewRequest(http.MethodPost, "http://url.com", strings.NewReader(`{"jsonrpc":"2.0","method":"eth_getBalance","id":67}`))
   116  	response2 := getServerResp(svr, request2)
   117  	bodyBytes2, _ := io.ReadAll(response2.Body)
   118  	require.Contains(string(bodyBytes2), "invalid format")
   119  
   120  	// missing web3 method
   121  	request3, _ := http.NewRequest(http.MethodPost, "http://url.com", strings.NewReader(`{"jsonrpc":"2.0","method":"web3_foo","params":[],"id":67}`))
   122  	response3 := getServerResp(svr, request3)
   123  	bodyBytes3, _ := io.ReadAll(response3.Body)
   124  	require.Contains(string(bodyBytes3), "method not found")
   125  
   126  	// single web3 req
   127  	request4, _ := http.NewRequest(http.MethodPost, "http://url.com", strings.NewReader(`{"jsonrpc":"2.0","method":"eth_mining","params":[],"id":67}`))
   128  	response4 := getServerResp(svr, request4)
   129  	bodyBytes4, _ := io.ReadAll(response4.Body)
   130  	require.Contains(string(bodyBytes4), "result")
   131  
   132  	// multiple web3 req
   133  	request5, _ := http.NewRequest(http.MethodPost, "http://url.com", strings.NewReader(`[{"jsonrpc":"2.0","method":"eth_mining","params":[],"id":1}, {"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":2}]`))
   134  	response5 := getServerResp(svr, request5)
   135  	bodyBytes5, _ := io.ReadAll(response5.Body)
   136  	require.True(gjson.Valid(string(bodyBytes5)))
   137  	require.Equal(2, len(gjson.Parse(string(bodyBytes5)).Array()))
   138  
   139  	// multiple web3 req with big batch
   140  	apitypes.MaxResponseSize = 1024 // fake max response size
   141  	request8, _ := http.NewRequest(http.MethodPost, "http://url.com", strings.NewReader(`[`+strings.Repeat(`{"jsonrpc":"2.0","method":"eth_mining","params":[],"id":1},`, 90)+`{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":2}]`))
   142  	response8 := getServerResp(svr, request8)
   143  	bodyBytes8, _ := io.ReadAll(response8.Body)
   144  	require.Equal(len(bodyBytes8), 0)
   145  
   146  	// multiple web3 req2
   147  	request6, _ := http.NewRequest(http.MethodPost, "http://url.com", strings.NewReader(`[{"jsonrpc":"2.0","method":"eth_mining","params":[],"id":1}]`))
   148  	response6 := getServerResp(svr, request6)
   149  	bodyBytes6, _ := io.ReadAll(response6.Body)
   150  	require.True(gjson.Valid(string(bodyBytes6)))
   151  	require.Equal(1, len(gjson.Parse(string(bodyBytes6)).Array()))
   152  
   153  	// web3 req without params
   154  	request7, _ := http.NewRequest(http.MethodPost, "http://url.com", strings.NewReader(`{"jsonrpc":"2.0","method":"web3_clientVersion","id":67}`))
   155  	core.EXPECT().ServerMeta().Return("mock str1", "mock str2", "mock str3", "mock str4", "mock str5")
   156  	response7 := getServerResp(svr, request7)
   157  	bodyBytes7, _ := io.ReadAll(response7.Body)
   158  	require.Contains(string(bodyBytes7), "result")
   159  
   160  	// multiple web3 req with big batch
   161  	apitypes.MaxResponseSize = 1024 * 1024 * 100 // fake max response size
   162  	request9, _ := http.NewRequest(http.MethodPost, "http://url.com", strings.NewReader(`[`+strings.Repeat(`{"jsonrpc":"2.0","method":"eth_mining","params":[],"id":1},`, 102)+`{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":2}]`))
   163  	response9 := getServerResp(svr, request9)
   164  	bodyBytes9, _ := io.ReadAll(response9.Body)
   165  	require.True(gjson.Valid(string(bodyBytes9)))
   166  	require.Contains(string(bodyBytes9), errMsgBatchTooLarge.Error())
   167  }
   168  
   169  func TestGasPrice(t *testing.T) {
   170  	require := require.New(t)
   171  	ctrl := gomock.NewController(t)
   172  	defer ctrl.Finish()
   173  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   174  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   175  	core.EXPECT().SuggestGasPrice().Return(uint64(1), nil)
   176  	ret, err := web3svr.gasPrice()
   177  	require.NoError(err)
   178  	require.Equal("0x1", ret.(string))
   179  
   180  	core.EXPECT().SuggestGasPrice().Return(uint64(0), errors.New("mock gas price error"))
   181  	_, err = web3svr.gasPrice()
   182  	require.Equal("mock gas price error", err.Error())
   183  }
   184  
   185  func TestGetChainID(t *testing.T) {
   186  	require := require.New(t)
   187  	ctrl := gomock.NewController(t)
   188  	defer ctrl.Finish()
   189  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   190  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   191  	core.EXPECT().EVMNetworkID().Return(uint32(1))
   192  	ret, err := web3svr.getChainID()
   193  	require.NoError(err)
   194  	require.Equal("0x1", ret.(string))
   195  }
   196  
   197  func TestGetBlockNumber(t *testing.T) {
   198  	require := require.New(t)
   199  	ctrl := gomock.NewController(t)
   200  	defer ctrl.Finish()
   201  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   202  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   203  	core.EXPECT().TipHeight().Return(uint64(1))
   204  	ret, err := web3svr.getBlockNumber()
   205  	require.NoError(err)
   206  	require.Equal("0x1", ret.(string))
   207  }
   208  
   209  func TestGetBlockByNumber(t *testing.T) {
   210  	require := require.New(t)
   211  	ctrl := gomock.NewController(t)
   212  	defer ctrl.Finish()
   213  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   214  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   215  
   216  	tsf, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0))
   217  	require.NoError(err)
   218  	tsfhash, err := tsf.Hash()
   219  	require.NoError(err)
   220  	receipts := []*action.Receipt{
   221  		{BlockHeight: 1, ActionHash: tsfhash},
   222  		{BlockHeight: 2, ActionHash: tsfhash},
   223  	}
   224  	blk, err := block.NewTestingBuilder().
   225  		SetHeight(1).
   226  		SetVersion(111).
   227  		SetPrevBlockHash(hash.ZeroHash256).
   228  		SetTimeStamp(time.Now()).
   229  		SetReceipts(receipts).
   230  		AddActions(tsf).
   231  		SignAndBuild(identityset.PrivateKey(0))
   232  	require.NoError(err)
   233  	core.EXPECT().BlockByHeight(gomock.Any()).Return(&apitypes.BlockWithReceipts{
   234  		Block:    &blk,
   235  		Receipts: receipts,
   236  	}, nil)
   237  	core.EXPECT().EVMNetworkID().Return(uint32(0))
   238  
   239  	t.Run("nil params", func(t *testing.T) {
   240  		inNil := gjson.Parse(`{"params":[]}`)
   241  		_, err := web3svr.getBlockByNumber(&inNil)
   242  		require.EqualError(err, errInvalidFormat.Error())
   243  	})
   244  
   245  	t.Run("nil params", func(t *testing.T) {
   246  		in := gjson.Parse(`{"params":["1", true]}`)
   247  		ret, err := web3svr.getBlockByNumber(&in)
   248  		require.NoError(err)
   249  		rlt, ok := ret.(*getBlockResult)
   250  		require.True(ok)
   251  		require.Equal(blk.Header, rlt.blk.Header)
   252  		require.Equal(receipts, rlt.blk.Receipts)
   253  		require.Len(rlt.transactions, 1)
   254  		tsrlt, ok := rlt.transactions[0].(*getTransactionResult)
   255  		require.True(ok)
   256  		require.Equal(receipts[0], tsrlt.receipt)
   257  	})
   258  }
   259  
   260  func TestGetBalance(t *testing.T) {
   261  	require := require.New(t)
   262  	ctrl := gomock.NewController(t)
   263  	defer ctrl.Finish()
   264  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   265  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   266  	balance := "111111111111111111"
   267  	core.EXPECT().Account(gomock.Any()).Return(&iotextypes.AccountMeta{Balance: balance}, nil, nil)
   268  
   269  	in := gjson.Parse(`{"params":["0xDa7e12Ef57c236a06117c5e0d04a228e7181CF36", 1]}`)
   270  	ret, err := web3svr.getBalance(&in)
   271  	require.NoError(err)
   272  	ans, ok := new(big.Int).SetString(balance, 10)
   273  	require.True(ok)
   274  	require.Equal("0x"+fmt.Sprintf("%x", ans), ret.(string))
   275  }
   276  
   277  func TestGetTransactionCount(t *testing.T) {
   278  	require := require.New(t)
   279  	ctrl := gomock.NewController(t)
   280  	defer ctrl.Finish()
   281  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   282  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   283  	core.EXPECT().PendingNonce(gomock.Any()).Return(uint64(2), nil)
   284  
   285  	inNil := gjson.Parse(`{"params":[]}`)
   286  	ret, err := web3svr.getTransactionCount(&inNil)
   287  	require.EqualError(err, errInvalidFormat.Error())
   288  
   289  	in := gjson.Parse(`{"params":["0xDa7e12Ef57c236a06117c5e0d04a228e7181CF36", 1]}`)
   290  	ret, err = web3svr.getTransactionCount(&in)
   291  	require.NoError(err)
   292  	require.Equal("0x2", ret.(string))
   293  }
   294  
   295  func TestCall(t *testing.T) {
   296  	require := require.New(t)
   297  	ctrl := gomock.NewController(t)
   298  	defer ctrl.Finish()
   299  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   300  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   301  
   302  	t.Run("to is StakingProtocol addr", func(t *testing.T) {
   303  		meta := &iotextypes.AccountMeta{
   304  			Address: "io000000000000000000000000stakingprotocol",
   305  			Balance: "100000000000000000000",
   306  		}
   307  		metaBytes, _ := proto.Marshal(meta)
   308  		core.EXPECT().ReadState(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&iotexapi.ReadStateResponse{
   309  			Data: metaBytes,
   310  		}, nil)
   311  		in := gjson.Parse(`{"params":[{
   312  			"from":     "",
   313  			"to":       "0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12",
   314  			"gas":      "0x4e20",
   315  			"gasPrice": "0xe8d4a51000",
   316  			"value":    "0x1",
   317  			"data":     "d201114a"
   318  		   },
   319  		   1]}`)
   320  		ret, err := web3svr.call(&in)
   321  		require.NoError(err)
   322  		require.Equal("0x0000000000000000000000000000000000000000000000056bc75e2d63100000", ret.(string))
   323  	})
   324  
   325  	t.Run("to is RewardingProtocol addr", func(t *testing.T) {
   326  		amount := big.NewInt(10000)
   327  		core.EXPECT().ReadState(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&iotexapi.ReadStateResponse{
   328  			Data: []byte(amount.String()),
   329  		}, nil)
   330  		in := gjson.Parse(`{"params":[{
   331  			"from":     "",
   332  			"to":       "0xA576C141e5659137ddDa4223d209d4744b2106BE",
   333  			"gas":      "0x4e20",
   334  			"gasPrice": "0xe8d4a51000",
   335  			"value":    "0x1",
   336  			"data":     "ad7a672f"
   337  		   },
   338  		   1]}`)
   339  		ret, err := web3svr.call(&in)
   340  		require.NoError(err)
   341  		require.Equal("0x0000000000000000000000000000000000000000000000000000000000002710", ret.(string))
   342  	})
   343  
   344  	t.Run("to is contract addr", func(t *testing.T) {
   345  		core.EXPECT().ReadContract(gomock.Any(), gomock.Any(), gomock.Any()).Return("111111", nil, nil)
   346  		in := gjson.Parse(`{"params":[{
   347  			"from":     "",
   348  			"to":       "0x7c13866F9253DEf79e20034eDD011e1d69E67fe5",
   349  			"gas":      "0x4e20",
   350  			"gasPrice": "0xe8d4a51000",
   351  			"value":    "0x1",
   352  			"data":     "0x1"
   353  		   },
   354  		   1]}`)
   355  		ret, err := web3svr.call(&in)
   356  		require.NoError(err)
   357  		require.Equal("0x111111", ret.(string))
   358  	})
   359  
   360  	t.Run("revert call", func(t *testing.T) {
   361  		receipt := &iotextypes.Receipt{
   362  			Status:             0,
   363  			BlkHeight:          0,
   364  			ActHash:            nil,
   365  			GasConsumed:        0,
   366  			ContractAddress:    "",
   367  			Logs:               nil,
   368  			ExecutionRevertMsg: "revert call",
   369  			TxIndex:            0,
   370  		}
   371  		core.EXPECT().ReadContract(gomock.Any(), gomock.Any(), gomock.Any()).Return("", receipt, nil)
   372  		in := gjson.Parse(`{"params":[{
   373  			"from":     "",
   374  			"to":       "0x7c13866F9253DEf79e20034eDD011e1d69E67fe5",
   375  			"gas":      "0x4e20",
   376  			"gasPrice": "0xe8d4a51000",
   377  			"value":    "0x1",
   378  			"data":     "0x1"
   379  		   },
   380  		   1]}`)
   381  		_, err := web3svr.call(&in)
   382  		require.EqualError(err, "rpc error: code = InvalidArgument desc = execution reverted: "+receipt.GetExecutionRevertMsg())
   383  	})
   384  }
   385  
   386  func TestEstimateGas(t *testing.T) {
   387  	require := require.New(t)
   388  	ctrl := gomock.NewController(t)
   389  	defer ctrl.Finish()
   390  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   391  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   392  	core.EXPECT().ChainID().Return(uint32(1)).Times(2)
   393  
   394  	t.Run("estimate execution", func(t *testing.T) {
   395  		core.EXPECT().Account(gomock.Any()).Return(&iotextypes.AccountMeta{IsContract: true}, nil, nil)
   396  		core.EXPECT().EstimateExecutionGasConsumption(gomock.Any(), gomock.Any(), gomock.Any()).Return(uint64(11000), nil)
   397  
   398  		in := gjson.Parse(`{"params":[{
   399  			"from":     "",
   400  			"to":       "0x7c13866F9253DEf79e20034eDD011e1d69E67fe5",
   401  			"gas":      "0x4e20",
   402  			"gasPrice": "0xe8d4a51000",
   403  			"value":    "0x1",
   404  			"data":     "0x6d4ce63c"
   405  		   },
   406  		   1]}`)
   407  		ret, err := web3svr.estimateGas(&in)
   408  		require.NoError(err)
   409  		require.Equal(uint64ToHex(uint64(21000)), ret.(string))
   410  	})
   411  
   412  	t.Run("estimate nonexecution", func(t *testing.T) {
   413  		core.EXPECT().Account(gomock.Any()).Return(&iotextypes.AccountMeta{IsContract: false}, nil, nil)
   414  		core.EXPECT().EstimateGasForNonExecution(gomock.Any()).Return(uint64(36000), nil)
   415  
   416  		in := gjson.Parse(`{"params":[{
   417  			"from":     "",
   418  			"to":       "0x7c13866F9253DEf79e20034eDD011e1d69E67fe5",
   419  			"gas":      "0x4e20",
   420  			"gasPrice": "0xe8d4a51000",
   421  			"value":    "0x1",
   422  			"data":     "0x1123123c"
   423  		   },
   424  		   1]}`)
   425  		ret, err := web3svr.estimateGas(&in)
   426  		require.NoError(err)
   427  		require.Equal(uint64ToHex(uint64(36000)), ret.(string))
   428  	})
   429  }
   430  
   431  func TestSendRawTransaction(t *testing.T) {
   432  	require := require.New(t)
   433  	ctrl := gomock.NewController(t)
   434  	defer ctrl.Finish()
   435  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   436  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   437  	core.EXPECT().Genesis().Return(genesis.Default)
   438  	core.EXPECT().TipHeight().Return(uint64(0))
   439  	core.EXPECT().EVMNetworkID().Return(uint32(1))
   440  	core.EXPECT().ChainID().Return(uint32(1))
   441  	core.EXPECT().Account(gomock.Any()).Return(&iotextypes.AccountMeta{IsContract: true}, nil, nil)
   442  	core.EXPECT().SendAction(gomock.Any(), gomock.Any()).Return("111111111111111", nil)
   443  
   444  	t.Run("nil params", func(t *testing.T) {
   445  		inNil := gjson.Parse(`{"params":[]}`)
   446  		_, err := web3svr.sendRawTransaction(&inNil)
   447  		require.EqualError(err, errInvalidFormat.Error())
   448  	})
   449  
   450  	t.Run("send tx", func(t *testing.T) {
   451  		in := gjson.Parse(`{"params":["f8600180830186a09412745fec82b585f239c01090882eb40702c32b04808025a0b0e1aab5b64d744ae01fc9f1c3e9919844a799e90c23129d611f7efe6aec8a29a0195e28d22d9b280e00d501ff63525bb76f5c87b8646c89d5d9c5485edcb1b498"]}`)
   452  		ret, err := web3svr.sendRawTransaction(&in)
   453  		require.NoError(err)
   454  		require.Equal("0x111111111111111", ret.(string))
   455  	})
   456  }
   457  
   458  func TestGetCode(t *testing.T) {
   459  	require := require.New(t)
   460  	ctrl := gomock.NewController(t)
   461  	defer ctrl.Finish()
   462  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   463  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   464  	code := "608060405234801561001057600080fd5b50610150806100206contractbytecode"
   465  	data, _ := hex.DecodeString(code)
   466  	core.EXPECT().Account(gomock.Any()).Return(&iotextypes.AccountMeta{ContractByteCode: data}, nil, nil)
   467  
   468  	t.Run("nil params", func(t *testing.T) {
   469  		inNil := gjson.Parse(`{"params":[]}`)
   470  		_, err := web3svr.getCode(&inNil)
   471  		require.EqualError(err, errInvalidFormat.Error())
   472  	})
   473  
   474  	t.Run("get code", func(t *testing.T) {
   475  		in := gjson.Parse(`{"params":["0x7c13866F9253DEf79e20034eDD011e1d69E67fe5"]}`)
   476  		ret, err := web3svr.getCode(&in)
   477  		require.NoError(err)
   478  		require.Contains(code, util.Remove0xPrefix(ret.(string)))
   479  	})
   480  }
   481  
   482  func TestGetNodeInfo(t *testing.T) {
   483  	require := require.New(t)
   484  	ctrl := gomock.NewController(t)
   485  	defer ctrl.Finish()
   486  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   487  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   488  	core.EXPECT().ServerMeta().Return("111", "", "", "222", "")
   489  	ret, err := web3svr.getNodeInfo()
   490  	require.NoError(err)
   491  	require.Equal("111/222", ret.(string))
   492  }
   493  
   494  func TestGetNetworkID(t *testing.T) {
   495  	require := require.New(t)
   496  	ctrl := gomock.NewController(t)
   497  	defer ctrl.Finish()
   498  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   499  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   500  	core.EXPECT().EVMNetworkID().Return(uint32(123))
   501  	ret, err := web3svr.getNetworkID()
   502  	require.NoError(err)
   503  	require.Equal("123", ret.(string))
   504  }
   505  
   506  func TestIsSyncing(t *testing.T) {
   507  	require := require.New(t)
   508  	ctrl := gomock.NewController(t)
   509  	defer ctrl.Finish()
   510  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   511  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   512  	core.EXPECT().SyncingProgress().Return(uint64(1), uint64(2), uint64(3))
   513  	ret, err := web3svr.isSyncing()
   514  	require.NoError(err)
   515  	rlt, ok := ret.(*getSyncingResult)
   516  	require.True(ok)
   517  	require.Equal("0x1", rlt.StartingBlock)
   518  	require.Equal("0x2", rlt.CurrentBlock)
   519  	require.Equal("0x3", rlt.HighestBlock)
   520  }
   521  
   522  func TestGetBlockTransactionCountByHash(t *testing.T) {
   523  	require := require.New(t)
   524  	ctrl := gomock.NewController(t)
   525  	defer ctrl.Finish()
   526  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   527  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   528  
   529  	tsf, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0))
   530  	require.NoError(err)
   531  	blk, err := block.NewTestingBuilder().
   532  		SetHeight(1).
   533  		SetVersion(111).
   534  		SetPrevBlockHash(hash.ZeroHash256).
   535  		SetTimeStamp(time.Now()).
   536  		AddActions(tsf).
   537  		SignAndBuild(identityset.PrivateKey(0))
   538  	require.NoError(err)
   539  	core.EXPECT().BlockByHash(gomock.Any()).Return(&apitypes.BlockWithReceipts{
   540  		Block: &blk,
   541  	}, nil)
   542  
   543  	t.Run("nil params", func(t *testing.T) {
   544  		inNil := gjson.Parse(`{"params":[]}`)
   545  		_, err := web3svr.getBlockTransactionCountByHash(&inNil)
   546  		require.EqualError(err, errInvalidFormat.Error())
   547  	})
   548  
   549  	t.Run("get block", func(t *testing.T) {
   550  		blkHash := blk.HashBlock()
   551  		in := gjson.Parse(fmt.Sprintf(`{"params":["0x%s", true]}`, hex.EncodeToString(blkHash[:])))
   552  		ret, err := web3svr.getBlockTransactionCountByHash(&in)
   553  		require.NoError(err)
   554  		require.Equal("0x1", ret.(string))
   555  	})
   556  }
   557  
   558  func TestGetBlockByHash(t *testing.T) {
   559  	require := require.New(t)
   560  	ctrl := gomock.NewController(t)
   561  	defer ctrl.Finish()
   562  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   563  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   564  
   565  	tsf, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0))
   566  	require.NoError(err)
   567  	tsfhash, err := tsf.Hash()
   568  	require.NoError(err)
   569  	receipts := []*action.Receipt{
   570  		{BlockHeight: 1, ActionHash: tsfhash},
   571  		{BlockHeight: 2, ActionHash: tsfhash},
   572  	}
   573  	blk, err := block.NewTestingBuilder().
   574  		SetHeight(1).
   575  		SetVersion(111).
   576  		SetPrevBlockHash(hash.ZeroHash256).
   577  		SetTimeStamp(time.Now()).
   578  		SetReceipts(receipts).
   579  		AddActions(tsf).
   580  		SignAndBuild(identityset.PrivateKey(0))
   581  	require.NoError(err)
   582  	core.EXPECT().BlockByHash(gomock.Any()).Return(&apitypes.BlockWithReceipts{
   583  		Block:    &blk,
   584  		Receipts: receipts,
   585  	}, nil)
   586  	core.EXPECT().EVMNetworkID().Return(uint32(0))
   587  
   588  	t.Run("nil params", func(t *testing.T) {
   589  		inNil := gjson.Parse(`{"params":[]}`)
   590  		_, err := web3svr.getBlockByHash(&inNil)
   591  		require.EqualError(err, errInvalidFormat.Error())
   592  	})
   593  
   594  	t.Run("get block", func(t *testing.T) {
   595  		blkHash := blk.HashBlock()
   596  		in := gjson.Parse(fmt.Sprintf(`{"params":["0x%s", true]}`, hex.EncodeToString(blkHash[:])))
   597  		ret, err := web3svr.getBlockByHash(&in)
   598  		require.NoError(err)
   599  		rlt, ok := ret.(*getBlockResult)
   600  		require.True(ok)
   601  		require.Equal(blk.Header, rlt.blk.Header)
   602  		require.Equal(receipts, rlt.blk.Receipts)
   603  		require.Len(rlt.transactions, 1)
   604  		tsrlt, ok := rlt.transactions[0].(*getTransactionResult)
   605  		require.True(ok)
   606  		require.Equal(receipts[0], tsrlt.receipt)
   607  	})
   608  }
   609  
   610  func TestGetTransactionByHash(t *testing.T) {
   611  	require := require.New(t)
   612  	ctrl := gomock.NewController(t)
   613  	defer ctrl.Finish()
   614  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   615  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   616  
   617  	selp, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0))
   618  	require.NoError(err)
   619  	txHash, err := selp.Hash()
   620  	require.NoError(err)
   621  	receipt := &action.Receipt{
   622  		Status:          1,
   623  		BlockHeight:     1,
   624  		ActionHash:      txHash,
   625  		GasConsumed:     1,
   626  		ContractAddress: "test",
   627  		TxIndex:         1,
   628  	}
   629  	blk, err := block.NewTestingBuilder().
   630  		SetHeight(1).
   631  		SetVersion(111).
   632  		SetPrevBlockHash(hash.ZeroHash256).
   633  		SetTimeStamp(time.Now()).
   634  		AddActions(selp).
   635  		SignAndBuild(identityset.PrivateKey(0))
   636  	require.NoError(err)
   637  	core.EXPECT().ActionByActionHash(gomock.Any()).Return(selp, &blk, uint32(0), nil)
   638  	core.EXPECT().ReceiptByActionHash(gomock.Any()).Return(receipt, nil)
   639  	core.EXPECT().EVMNetworkID().Return(uint32(0))
   640  
   641  	inNil := gjson.Parse(`{"params":[]}`)
   642  	ret, err := web3svr.getTransactionByHash(&inNil)
   643  	require.EqualError(err, errInvalidFormat.Error())
   644  
   645  	in := gjson.Parse(fmt.Sprintf(`{"params":["0x%s", true]}`, hex.EncodeToString(txHash[:])))
   646  	ret, err = web3svr.getTransactionByHash(&in)
   647  	require.NoError(err)
   648  	rlt, ok := ret.(*getTransactionResult)
   649  	require.True(ok)
   650  	require.Equal(receipt, rlt.receipt)
   651  
   652  	// get pending transaction
   653  	core.EXPECT().ActionByActionHash(gomock.Any()).Return(nil, nil, uint32(0), ErrNotFound)
   654  	core.EXPECT().PendingActionByActionHash(gomock.Any()).Return(selp, nil)
   655  	core.EXPECT().EVMNetworkID().Return(uint32(0))
   656  	ret, err = web3svr.getTransactionByHash(&in)
   657  	require.NoError(err)
   658  	rlt, ok = ret.(*getTransactionResult)
   659  	require.True(ok)
   660  	require.Nil(rlt.blockHash)
   661  	require.Nil(rlt.receipt)
   662  
   663  	// get pending contract deploy transaction
   664  	selp, err = action.SignedExecution("", identityset.PrivateKey(27), 1, big.NewInt(1), 10000, big.NewInt(0), []byte("test"))
   665  	require.NoError(err)
   666  	txHash, err = selp.Hash()
   667  	require.NoError(err)
   668  	core.EXPECT().ActionByActionHash(gomock.Any()).Return(nil, nil, uint32(0), ErrNotFound)
   669  	core.EXPECT().PendingActionByActionHash(gomock.Any()).Return(selp, nil)
   670  	core.EXPECT().EVMNetworkID().Return(uint32(0))
   671  	ret, err = web3svr.getTransactionByHash(&in)
   672  	require.NoError(err)
   673  	rlt, ok = ret.(*getTransactionResult)
   674  	require.True(ok)
   675  	require.Nil(rlt.blockHash)
   676  	require.Nil(rlt.receipt)
   677  	require.Nil(rlt.to)
   678  }
   679  
   680  func TestGetLogs(t *testing.T) {
   681  	require := require.New(t)
   682  	ctrl := gomock.NewController(t)
   683  	defer ctrl.Finish()
   684  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   685  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   686  
   687  	logs := []*action.Log{
   688  		{
   689  			Address:     "_topic1",
   690  			BlockHeight: 1,
   691  			Topics: []hash.Hash256{
   692  				hash.Hash256b([]byte("_topic1")),
   693  				hash.Hash256b([]byte("_topic11")),
   694  			},
   695  		},
   696  		{
   697  			Address:     "_topic2",
   698  			BlockHeight: 2,
   699  			Topics: []hash.Hash256{
   700  				hash.Hash256b([]byte("_topic2")),
   701  				hash.Hash256b([]byte("_topic22")),
   702  			},
   703  		},
   704  	}
   705  	blkHash1 := hash.Hash256b([]byte("_block1"))
   706  	blkHash2 := hash.Hash256b([]byte("_block2"))
   707  	hashes := []hash.Hash256{
   708  		blkHash1,
   709  		blkHash2,
   710  	}
   711  	core.EXPECT().LogsInRange(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(logs, hashes, nil)
   712  
   713  	ret, err := web3svr.getLogs(&filterObject{
   714  		FromBlock: "1",
   715  		ToBlock:   "2",
   716  		Address:   []string{"0x0000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000002"},
   717  		Topics:    [][]string{{byteToHex([]byte("_topic1")), byteToHex([]byte("_topic2")), byteToHex([]byte("_topic3"))}, {byteToHex([]byte("_topic4"))}},
   718  	})
   719  	require.NoError(err)
   720  	rlt, ok := ret.([]*getLogsResult)
   721  	require.True(ok)
   722  	require.Len(rlt, 2)
   723  	require.Equal("_topic1", rlt[0].log.Address)
   724  	require.Equal(blkHash1, rlt[0].blockHash)
   725  	require.Equal("_topic2", rlt[1].log.Address)
   726  	require.Equal(blkHash2, rlt[1].blockHash)
   727  }
   728  
   729  func TestGetTransactionReceipt(t *testing.T) {
   730  	require := require.New(t)
   731  	ctrl := gomock.NewController(t)
   732  	defer ctrl.Finish()
   733  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   734  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   735  
   736  	selp, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0))
   737  	require.NoError(err)
   738  	txHash, err := selp.Hash()
   739  	require.NoError(err)
   740  	receipt := &action.Receipt{
   741  		Status:          1,
   742  		BlockHeight:     1,
   743  		ActionHash:      txHash,
   744  		GasConsumed:     1,
   745  		ContractAddress: "test",
   746  		TxIndex:         1,
   747  	}
   748  	blk, err := block.NewTestingBuilder().
   749  		SetHeight(1).
   750  		SetVersion(111).
   751  		SetPrevBlockHash(hash.ZeroHash256).
   752  		SetTimeStamp(time.Now()).
   753  		AddActions(selp).
   754  		SignAndBuild(identityset.PrivateKey(0))
   755  	require.NoError(err)
   756  	core.EXPECT().ActionByActionHash(gomock.Any()).Return(selp, &blk, uint32(0), nil)
   757  	core.EXPECT().ReceiptByActionHash(gomock.Any()).Return(receipt, nil)
   758  
   759  	t.Run("nil params", func(t *testing.T) {
   760  		inNil := gjson.Parse(`{"params":[]}`)
   761  		_, err := web3svr.getTransactionReceipt(&inNil)
   762  		require.EqualError(err, errInvalidFormat.Error())
   763  	})
   764  
   765  	t.Run("get tx", func(t *testing.T) {
   766  		in := gjson.Parse(fmt.Sprintf(`{"params":["0x%s", true]}`, hex.EncodeToString(txHash[:])))
   767  		ret, err := web3svr.getTransactionReceipt(&in)
   768  		require.NoError(err)
   769  		rlt, ok := ret.(*getReceiptResult)
   770  		require.True(ok)
   771  		require.Equal(receipt, rlt.receipt)
   772  		require.Equal("", rlt.logsBloom)
   773  		require.Nil(blk.Header.LogsBloomfilter())
   774  	})
   775  }
   776  
   777  func TestGetBlockTransactionCountByNumber(t *testing.T) {
   778  	require := require.New(t)
   779  	ctrl := gomock.NewController(t)
   780  	defer ctrl.Finish()
   781  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   782  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   783  
   784  	tsf, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0))
   785  	require.NoError(err)
   786  	blk, err := block.NewTestingBuilder().
   787  		SetHeight(1).
   788  		SetVersion(111).
   789  		SetPrevBlockHash(hash.ZeroHash256).
   790  		SetTimeStamp(time.Now()).
   791  		AddActions(tsf, tsf).
   792  		SignAndBuild(identityset.PrivateKey(0))
   793  	require.NoError(err)
   794  	core.EXPECT().BlockByHeight(gomock.Any()).Return(&apitypes.BlockWithReceipts{
   795  		Block: &blk,
   796  	}, nil)
   797  
   798  	t.Run("nil params", func(t *testing.T) {
   799  		inNil := gjson.Parse(`{"params":[]}`)
   800  		_, err := web3svr.getBlockTransactionCountByNumber(&inNil)
   801  		require.EqualError(err, errInvalidFormat.Error())
   802  	})
   803  
   804  	t.Run("get block", func(t *testing.T) {
   805  		in := gjson.Parse(`{"params":["0x1"]}`)
   806  		ret, err := web3svr.getBlockTransactionCountByNumber(&in)
   807  		require.NoError(err)
   808  		require.Equal("0x2", ret.(string))
   809  	})
   810  }
   811  
   812  func TestGetTransactionByBlockHashAndIndex(t *testing.T) {
   813  	require := require.New(t)
   814  	ctrl := gomock.NewController(t)
   815  	defer ctrl.Finish()
   816  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   817  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   818  
   819  	tsf, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0))
   820  	require.NoError(err)
   821  	tsfhash, err := tsf.Hash()
   822  	require.NoError(err)
   823  	blk, err := block.NewTestingBuilder().
   824  		SetHeight(1).
   825  		SetVersion(111).
   826  		SetPrevBlockHash(hash.ZeroHash256).
   827  		SetTimeStamp(time.Now()).
   828  		AddActions(tsf).
   829  		SignAndBuild(identityset.PrivateKey(0))
   830  	require.NoError(err)
   831  	receipts := []*action.Receipt{
   832  		{BlockHeight: 1, ActionHash: tsfhash},
   833  		{BlockHeight: 2, ActionHash: tsfhash},
   834  	}
   835  	core.EXPECT().BlockByHash(gomock.Any()).Return(&apitypes.BlockWithReceipts{
   836  		Block:    &blk,
   837  		Receipts: receipts,
   838  	}, nil)
   839  	core.EXPECT().EVMNetworkID().Return(uint32(0))
   840  
   841  	t.Run("nil params", func(t *testing.T) {
   842  		inNil := gjson.Parse(`{"params":[]}`)
   843  		_, err := web3svr.getTransactionByBlockHashAndIndex(&inNil)
   844  		require.EqualError(err, errInvalidFormat.Error())
   845  	})
   846  
   847  	t.Run("get tx", func(t *testing.T) {
   848  		blkHash := blk.HashBlock()
   849  		in := gjson.Parse(fmt.Sprintf(`{"params":["0x%s", "0"]}`, hex.EncodeToString(blkHash[:])))
   850  		ret, err := web3svr.getTransactionByBlockHashAndIndex(&in)
   851  		require.NoError(err)
   852  		rlt, ok := ret.(*getTransactionResult)
   853  		require.True(ok)
   854  		require.Equal(receipts[0], rlt.receipt)
   855  		require.Equal(blkHash, *rlt.blockHash)
   856  	})
   857  }
   858  
   859  func TestGetTransactionByBlockNumberAndIndex(t *testing.T) {
   860  	require := require.New(t)
   861  	ctrl := gomock.NewController(t)
   862  	defer ctrl.Finish()
   863  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   864  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   865  
   866  	tsf, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0))
   867  	require.NoError(err)
   868  	tsfhash, err := tsf.Hash()
   869  	require.NoError(err)
   870  	blk, err := block.NewTestingBuilder().
   871  		SetHeight(1).
   872  		SetVersion(111).
   873  		SetPrevBlockHash(hash.ZeroHash256).
   874  		SetTimeStamp(time.Now()).
   875  		AddActions(tsf).
   876  		SignAndBuild(identityset.PrivateKey(0))
   877  	require.NoError(err)
   878  	receipts := []*action.Receipt{
   879  		{BlockHeight: 1, ActionHash: tsfhash},
   880  		{BlockHeight: 2, ActionHash: tsfhash},
   881  	}
   882  	core.EXPECT().BlockByHeight(gomock.Any()).Return(&apitypes.BlockWithReceipts{
   883  		Block:    &blk,
   884  		Receipts: receipts,
   885  	}, nil)
   886  	core.EXPECT().EVMNetworkID().Return(uint32(0))
   887  
   888  	t.Run("nil params", func(t *testing.T) {
   889  		inNil := gjson.Parse(`{"params":[]}`)
   890  		_, err := web3svr.getTransactionByBlockNumberAndIndex(&inNil)
   891  		require.EqualError(err, errInvalidFormat.Error())
   892  	})
   893  
   894  	t.Run("get tx", func(t *testing.T) {
   895  		in := gjson.Parse(`{"params":["0x1", "0"]}`)
   896  		ret, err := web3svr.getTransactionByBlockNumberAndIndex(&in)
   897  		require.NoError(err)
   898  		rlt, ok := ret.(*getTransactionResult)
   899  		require.True(ok)
   900  		require.Equal(receipts[0], rlt.receipt)
   901  		require.Equal(blk.HashBlock(), *rlt.blockHash)
   902  	})
   903  }
   904  
   905  func TestGetStorageAt(t *testing.T) {
   906  	require := require.New(t)
   907  	ctrl := gomock.NewController(t)
   908  	defer ctrl.Finish()
   909  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   910  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
   911  	val := []byte("test")
   912  	core.EXPECT().ReadContractStorage(gomock.Any(), gomock.Any(), gomock.Any()).Return(val, nil)
   913  
   914  	in := gjson.Parse(`{"params":["0x123456789abc", "0"]}`)
   915  	ret, err := web3svr.getStorageAt(&in)
   916  	require.NoError(err)
   917  	require.Equal("0x"+hex.EncodeToString(val), ret.(string))
   918  }
   919  
   920  func TestNewfilter(t *testing.T) {
   921  	require := require.New(t)
   922  	ctrl := gomock.NewController(t)
   923  	defer ctrl.Finish()
   924  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   925  	web3svr := &web3Handler{core, newAPICache(1*time.Second, ""), _defaultBatchRequestLimit}
   926  
   927  	ret, err := web3svr.newFilter(&filterObject{
   928  		FromBlock: "1",
   929  		ToBlock:   "2",
   930  		Address:   []string{"0x0000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000002"},
   931  		Topics:    [][]string{{byteToHex([]byte("_topic1")), byteToHex([]byte("_topic2")), byteToHex([]byte("_topic3"))}, {byteToHex([]byte("_topic4"))}},
   932  	})
   933  	require.NoError(err)
   934  	require.Equal("0x6e86c450ba48d23a459b74581736ca033ed60ef2a3d5ae09c316f77f67d7fad7", ret.(string))
   935  }
   936  
   937  func TestNewBlockFilter(t *testing.T) {
   938  	require := require.New(t)
   939  	ctrl := gomock.NewController(t)
   940  	defer ctrl.Finish()
   941  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   942  	web3svr := &web3Handler{core, newAPICache(1*time.Second, ""), _defaultBatchRequestLimit}
   943  	core.EXPECT().TipHeight().Return(uint64(123))
   944  
   945  	ret, err := web3svr.newBlockFilter()
   946  	require.NoError(err)
   947  	require.Equal("0x4c6ace15a9c5b9d3c89e786b7b6dfaf1bdc5807b8d7da0292db94d473f349101", ret.(string))
   948  }
   949  
   950  func TestUninstallFilter(t *testing.T) {
   951  	require := require.New(t)
   952  	ctrl := gomock.NewController(t)
   953  	defer ctrl.Finish()
   954  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   955  	web3svr := &web3Handler{core, newAPICache(1*time.Second, ""), _defaultBatchRequestLimit}
   956  
   957  	require.NoError(web3svr.cache.Set("123456789abc", []byte("test")))
   958  
   959  	t.Run("nil params", func(t *testing.T) {
   960  		inNil := gjson.Parse(`{"params":[]}`)
   961  		_, err := web3svr.uninstallFilter(&inNil)
   962  		require.EqualError(err, errInvalidFormat.Error())
   963  	})
   964  
   965  	t.Run("uninstall filter", func(t *testing.T) {
   966  		in := gjson.Parse(`{"params":["0x123456789abc"]}`)
   967  		ret, err := web3svr.uninstallFilter(&in)
   968  		require.NoError(err)
   969  		require.True(ret.(bool))
   970  	})
   971  }
   972  
   973  func TestGetFilterChanges(t *testing.T) {
   974  	require := require.New(t)
   975  	ctrl := gomock.NewController(t)
   976  	defer ctrl.Finish()
   977  	core := mock_apicoreservice.NewMockCoreService(ctrl)
   978  	web3svr := &web3Handler{core, newAPICache(1*time.Second, ""), _defaultBatchRequestLimit}
   979  	core.EXPECT().TipHeight().Return(uint64(0)).Times(3)
   980  
   981  	t.Run("log filterType", func(t *testing.T) {
   982  		logs := []*action.Log{
   983  			{
   984  				Address:     "_topic1",
   985  				BlockHeight: 1,
   986  				Topics: []hash.Hash256{
   987  					hash.Hash256b([]byte("_topic1")),
   988  					hash.Hash256b([]byte("_topic11")),
   989  				},
   990  			},
   991  			{
   992  				Address:     "_topic2",
   993  				BlockHeight: 2,
   994  				Topics: []hash.Hash256{
   995  					hash.Hash256b([]byte("_topic2")),
   996  					hash.Hash256b([]byte("_topic22")),
   997  				},
   998  			},
   999  		}
  1000  		blkHash1 := hash.Hash256b([]byte("_block1"))
  1001  		blkHash2 := hash.Hash256b([]byte("_block2"))
  1002  		hashes := []hash.Hash256{
  1003  			blkHash1,
  1004  			blkHash2,
  1005  		}
  1006  		core.EXPECT().LogsInRange(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(logs, hashes, nil)
  1007  
  1008  		require.NoError(web3svr.cache.Set("123456789abc", []byte(`{"logHeight":0,"filterType":"log","fromBlock":"0x1"}`)))
  1009  		in := gjson.Parse(`{"params":["0x123456789abc"]}`)
  1010  		ret, err := web3svr.getFilterChanges(&in)
  1011  		require.NoError(err)
  1012  		rlt, ok := ret.([]*getLogsResult)
  1013  		require.True(ok)
  1014  		require.Len(rlt, 2)
  1015  		require.Equal("_topic1", rlt[0].log.Address)
  1016  		require.Equal(blkHash1, rlt[0].blockHash)
  1017  		require.Equal("_topic2", rlt[1].log.Address)
  1018  		require.Equal(blkHash2, rlt[1].blockHash)
  1019  	})
  1020  
  1021  	t.Run("block filterType", func(t *testing.T) {
  1022  		tsf, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0))
  1023  		require.NoError(err)
  1024  		tsfhash, err := tsf.Hash()
  1025  		require.NoError(err)
  1026  		blk, err := block.NewTestingBuilder().
  1027  			SetHeight(1).
  1028  			SetVersion(111).
  1029  			SetPrevBlockHash(hash.ZeroHash256).
  1030  			SetTimeStamp(time.Now()).
  1031  			AddActions(tsf).
  1032  			SignAndBuild(identityset.PrivateKey(0))
  1033  		require.NoError(err)
  1034  		receipts := []*action.Receipt{
  1035  			{BlockHeight: 1, ActionHash: tsfhash},
  1036  			{BlockHeight: 2, ActionHash: tsfhash},
  1037  		}
  1038  		core.EXPECT().BlockByHeightRange(gomock.Any(), gomock.Any()).Return(
  1039  			[]*apitypes.BlockWithReceipts{
  1040  				{
  1041  					Block:    &blk,
  1042  					Receipts: receipts,
  1043  				},
  1044  			}, nil)
  1045  
  1046  		require.NoError(web3svr.cache.Set("123456789abc", []byte(`{"logHeight":0,"filterType":"block","fromBlock":"0x1"}`)))
  1047  		in := gjson.Parse(`{"params":["0x123456789abc"]}`)
  1048  		ret, err := web3svr.getFilterChanges(&in)
  1049  		require.NoError(err)
  1050  		rlt, ok := ret.([]string)
  1051  		require.True(ok)
  1052  		require.Len(rlt, 1)
  1053  		blkHash := blk.HashBlock()
  1054  		require.Equal("0x"+hex.EncodeToString(blkHash[:]), rlt[0])
  1055  	})
  1056  }
  1057  
  1058  func TestGetFilterLogs(t *testing.T) {
  1059  	require := require.New(t)
  1060  	ctrl := gomock.NewController(t)
  1061  	defer ctrl.Finish()
  1062  	core := mock_apicoreservice.NewMockCoreService(ctrl)
  1063  	web3svr := &web3Handler{core, newAPICache(1*time.Second, ""), _defaultBatchRequestLimit}
  1064  
  1065  	logs := []*action.Log{
  1066  		{
  1067  			Address:     "_topic1",
  1068  			BlockHeight: 1,
  1069  			Topics: []hash.Hash256{
  1070  				hash.Hash256b([]byte("_topic1")),
  1071  				hash.Hash256b([]byte("_topic11")),
  1072  			},
  1073  		},
  1074  		{
  1075  			Address:     "_topic2",
  1076  			BlockHeight: 2,
  1077  			Topics: []hash.Hash256{
  1078  				hash.Hash256b([]byte("_topic2")),
  1079  				hash.Hash256b([]byte("_topic22")),
  1080  			},
  1081  		},
  1082  	}
  1083  	blkHash1 := hash.Hash256b([]byte("_block1"))
  1084  	blkHash2 := hash.Hash256b([]byte("_block2"))
  1085  	hashes := []hash.Hash256{
  1086  		blkHash1,
  1087  		blkHash2,
  1088  	}
  1089  	core.EXPECT().TipHeight().Return(uint64(0))
  1090  	core.EXPECT().LogsInRange(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(logs, hashes, nil)
  1091  
  1092  	require.NoError(web3svr.cache.Set("123456789abc", []byte(`{"logHeight":0,"filterType":"log","fromBlock":"0x1"}`)))
  1093  
  1094  	t.Run("nil params", func(t *testing.T) {
  1095  		inNil := gjson.Parse(`{"params":[]}`)
  1096  		_, err := web3svr.getFilterLogs(&inNil)
  1097  		require.EqualError(err, errInvalidFormat.Error())
  1098  	})
  1099  
  1100  	t.Run("get filter log", func(t *testing.T) {
  1101  		in := gjson.Parse(`{"params":["0x123456789abc"]}`)
  1102  		ret, err := web3svr.getFilterLogs(&in)
  1103  		require.NoError(err)
  1104  		rlt, ok := ret.([]*getLogsResult)
  1105  		require.True(ok)
  1106  		require.Len(rlt, 2)
  1107  		require.Equal("_topic1", rlt[0].log.Address)
  1108  		require.Equal(blkHash1, rlt[0].blockHash)
  1109  		require.Equal("_topic2", rlt[1].log.Address)
  1110  		require.Equal(blkHash2, rlt[1].blockHash)
  1111  	})
  1112  }
  1113  
  1114  func TestSubscribe(t *testing.T) {
  1115  	require := require.New(t)
  1116  	ctrl := gomock.NewController(t)
  1117  	defer ctrl.Finish()
  1118  	core := mock_apicoreservice.NewMockCoreService(ctrl)
  1119  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
  1120  
  1121  	listener := mock_apitypes.NewMockListener(ctrl)
  1122  	listener.EXPECT().AddResponder(gomock.Any()).Return("streamid_1", nil).Times(3)
  1123  	core.EXPECT().ChainListener().Return(listener).Times(3)
  1124  	writer := mock_apitypes.NewMockWeb3ResponseWriter(ctrl)
  1125  
  1126  	t.Run("newHeads subscription", func(t *testing.T) {
  1127  		in := gjson.Parse(`{"params":["newHeads"]}`)
  1128  		ret, err := web3svr.subscribe(&in, writer)
  1129  		require.NoError(err)
  1130  		require.Equal("streamid_1", ret.(string))
  1131  	})
  1132  
  1133  	t.Run("logs subscription", func(t *testing.T) {
  1134  		in := gjson.Parse(`{"params":["logs",{"fromBlock":"1","fromBlock":"2","address":["0x0000000000000000000000000000000000000001"],"topics":[["0x5f746f70696331"]]}]}`)
  1135  		ret, err := web3svr.subscribe(&in, writer)
  1136  		require.NoError(err)
  1137  		require.Equal("streamid_1", ret.(string))
  1138  	})
  1139  
  1140  	t.Run("logs topic not array", func(t *testing.T) {
  1141  		in := gjson.Parse(`{"params":["logs",{"fromBlock":"1","fromBlock":"2","address":["0x0000000000000000000000000000000000000001"],"topics":["0x5f746f70696331"]}]}`)
  1142  		ret, err := web3svr.subscribe(&in, writer)
  1143  		require.NoError(err)
  1144  		require.Equal("streamid_1", ret.(string))
  1145  	})
  1146  
  1147  	t.Run("nil params", func(t *testing.T) {
  1148  		inNil := gjson.Parse(`{"params":[]}`)
  1149  		_, err := web3svr.subscribe(&inNil, writer)
  1150  		require.EqualError(err, errInvalidFormat.Error())
  1151  	})
  1152  
  1153  	t.Run("nil logs", func(t *testing.T) {
  1154  		inNil := gjson.Parse(`{"params":["logs"]}`)
  1155  		_, err := web3svr.subscribe(&inNil, writer)
  1156  		require.EqualError(err, errInvalidFormat.Error())
  1157  	})
  1158  }
  1159  
  1160  func TestUnsubscribe(t *testing.T) {
  1161  	require := require.New(t)
  1162  	ctrl := gomock.NewController(t)
  1163  	defer ctrl.Finish()
  1164  	core := mock_apicoreservice.NewMockCoreService(ctrl)
  1165  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
  1166  
  1167  	listener := mock_apitypes.NewMockListener(ctrl)
  1168  	listener.EXPECT().RemoveResponder(gomock.Any()).Return(true, nil)
  1169  	core.EXPECT().ChainListener().Return(listener)
  1170  
  1171  	t.Run("nil params", func(t *testing.T) {
  1172  		inNil := gjson.Parse(`{"params":[]}`)
  1173  		_, err := web3svr.unsubscribe(&inNil)
  1174  		require.EqualError(err, errInvalidFormat.Error())
  1175  	})
  1176  
  1177  	t.Run("unsubscribe", func(t *testing.T) {
  1178  		in := gjson.Parse(`{"params":["0x123456789abc"]}`)
  1179  		ret, err := web3svr.unsubscribe(&in)
  1180  		require.NoError(err)
  1181  		require.True(ret.(bool))
  1182  	})
  1183  }
  1184  
  1185  func TestLocalAPICache(t *testing.T) {
  1186  	require := require.New(t)
  1187  	testKey, testData := strconv.Itoa(rand.Int()), []byte(strconv.Itoa(rand.Int()))
  1188  	cacheLocal := newAPICache(1*time.Second, "")
  1189  	_, exist := cacheLocal.Get(testKey)
  1190  	require.False(exist)
  1191  	err := cacheLocal.Set(testKey, testData)
  1192  	require.NoError(err)
  1193  	data, _ := cacheLocal.Get(testKey)
  1194  	require.Equal(testData, data)
  1195  	cacheLocal.Del(testKey)
  1196  	_, exist = cacheLocal.Get(testKey)
  1197  	require.False(exist)
  1198  }
  1199  
  1200  func TestDebugTraceTransaction(t *testing.T) {
  1201  	require := require.New(t)
  1202  	ctrl := gomock.NewController(t)
  1203  	defer ctrl.Finish()
  1204  	core := mock_apicoreservice.NewMockCoreService(ctrl)
  1205  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
  1206  
  1207  	ctx := context.Background()
  1208  	tsf, err := action.SignedExecution(identityset.Address(29).String(),
  1209  		identityset.PrivateKey(29), 1, big.NewInt(0), testutil.TestGasLimit,
  1210  		big.NewInt(testutil.TestGasPriceInt64), []byte{})
  1211  	require.NoError(err)
  1212  	tsfhash, err := tsf.Hash()
  1213  	require.NoError(err)
  1214  	receipt := &action.Receipt{Status: 1, BlockHeight: 1, ActionHash: tsfhash, GasConsumed: 100000}
  1215  	structLogger := &logger.StructLogger{}
  1216  
  1217  	core.EXPECT().TraceTransaction(ctx, gomock.Any(), gomock.Any()).AnyTimes().Return([]byte{0x01}, receipt, structLogger, nil)
  1218  
  1219  	t.Run("nil params", func(t *testing.T) {
  1220  		inNil := gjson.Parse(`{"params":[]}`)
  1221  		_, err := web3svr.traceTransaction(ctx, &inNil)
  1222  		require.EqualError(err, errInvalidFormat.Error())
  1223  	})
  1224  
  1225  	t.Run("trace tx", func(t *testing.T) {
  1226  		in := gjson.Parse(`{"params":["` + hex.EncodeToString(tsfhash[:]) + `"]}`)
  1227  		ret, err := web3svr.traceTransaction(ctx, &in)
  1228  		require.NoError(err)
  1229  		rlt, ok := ret.(*debugTraceTransactionResult)
  1230  		require.True(ok)
  1231  		require.Equal("0x01", rlt.ReturnValue)
  1232  		require.False(rlt.Failed)
  1233  		require.Equal(uint64(100000), rlt.Gas)
  1234  		require.Empty(rlt.Revert)
  1235  		require.Equal(0, len(rlt.StructLogs))
  1236  	})
  1237  }
  1238  
  1239  func TestDebugTraceCall(t *testing.T) {
  1240  	require := require.New(t)
  1241  	ctrl := gomock.NewController(t)
  1242  	defer ctrl.Finish()
  1243  	core := mock_apicoreservice.NewMockCoreService(ctrl)
  1244  	web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit}
  1245  
  1246  	ctx := context.Background()
  1247  	tsf, err := action.SignedExecution(identityset.Address(29).String(),
  1248  		identityset.PrivateKey(29), 1, big.NewInt(0), testutil.TestGasLimit,
  1249  		big.NewInt(testutil.TestGasPriceInt64), []byte{})
  1250  	require.NoError(err)
  1251  	tsfhash, err := tsf.Hash()
  1252  	require.NoError(err)
  1253  	receipt := &action.Receipt{Status: 1, BlockHeight: 1, ActionHash: tsfhash, GasConsumed: 100000}
  1254  	structLogger := &logger.StructLogger{}
  1255  
  1256  	core.EXPECT().TraceCall(ctx, gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return([]byte{0x01}, receipt, structLogger, nil)
  1257  
  1258  	in := gjson.Parse(`{"method":"debug_traceCall","params":[{"from":null,"to":"0x6b175474e89094c44da98b954eedeac495271d0f","data":"0x70a082310000000000000000000000006E0d01A76C3Cf4288372a29124A26D4353EE51BE"}, {"blockNumber":1}],"id":1,"jsonrpc":"2.0"}`)
  1259  	ret, err := web3svr.traceCall(ctx, &in)
  1260  	require.NoError(err)
  1261  	rlt, ok := ret.(*debugTraceTransactionResult)
  1262  	require.True(ok)
  1263  	require.Equal("0x01", rlt.ReturnValue)
  1264  	require.False(rlt.Failed)
  1265  	require.Equal(uint64(100000), rlt.Gas)
  1266  	require.Empty(rlt.Revert)
  1267  	require.Equal(0, len(rlt.StructLogs))
  1268  }
  1269  
  1270  func TestResponseIDMatchTypeWithRequest(t *testing.T) {
  1271  	require := require.New(t)
  1272  	ctrl := gomock.NewController(t)
  1273  	defer ctrl.Finish()
  1274  	core := mock_apicoreservice.NewMockCoreService(ctrl)
  1275  	core.EXPECT().TipHeight().Return(uint64(1)).AnyTimes()
  1276  	core.EXPECT().Track(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return().AnyTimes()
  1277  	svr := newHTTPHandler(NewWeb3Handler(core, "", _defaultBatchRequestLimit))
  1278  	getServerResp := func(svr *hTTPHandler, req *http.Request) *httptest.ResponseRecorder {
  1279  		req.Header.Set("Content-Type", "application/json")
  1280  		resp := httptest.NewRecorder()
  1281  		svr.ServeHTTP(resp, req)
  1282  		return resp
  1283  	}
  1284  	tests := []struct {
  1285  		req string
  1286  		sub string
  1287  	}{
  1288  		{`{"jsonrpc":"2.0","method":"eth_blockNumber","id":1}`, `"id":1`},
  1289  		{`{"jsonrpc":"2.0","method":"eth_blockNumber","id":"1"}`, `"id":"1"`},
  1290  		{`{"jsonrpc":"2.0","method":"eth_blockNumber","id":"0x32"}`, `"id":"0x32"`},
  1291  		{`{"jsonrpc":"2.0","method":"eth_blockNumber","id":[]}`, `error`},
  1292  		{`{"jsonrpc":"2.0","method":"eth_blockNumber","id":[1]}`, `error`},
  1293  		{`{"jsonrpc":"2.0","method":"eth_blockNumber","id":0x32}`, `error`},
  1294  		{`{"jsonrpc":"2.0","method":"eth_blockNumber","id":{1}}`, `error`},
  1295  	}
  1296  	for _, tt := range tests {
  1297  		request, _ := http.NewRequest(http.MethodPost, "http://url.com", strings.NewReader(tt.req))
  1298  		response := getServerResp(svr, request)
  1299  		bodyBytes, _ := io.ReadAll(response.Body)
  1300  		require.Contains(string(bodyBytes), tt.sub)
  1301  	}
  1302  }