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 }