From bd7ca1f4172ba460eee146c3de91a5e5f3bc78ea Mon Sep 17 00:00:00 2001 From: dustinxie Date: Sun, 15 Dec 2024 18:11:41 -0800 Subject: [PATCH] [api] archive-mode for eth_getBalance & eth_call --- api/coreservice.go | 124 ++++++++++++++---- api/coreservice_test.go | 8 +- api/coreservice_with_height.go | 71 ++++++++++ api/grpcserver_integrity_test.go | 2 +- api/grpcserver_test.go | 47 ++++--- .../mock_apicoreservice.go | 40 ++++-- api/serverV2_test.go | 3 +- api/web3server.go | 30 ++++- api/web3server_test.go | 68 +++++----- api/web3server_utils.go | 25 ++++ api/web3server_utils_test.go | 4 +- chainservice/chainservice.go | 3 +- misc/scripts/mockgen.sh | 5 +- server/itx/server.go | 2 +- 14 files changed, 318 insertions(+), 114 deletions(-) create mode 100644 api/coreservice_with_height.go rename {test/mock/mock_apicoreservice => api}/mock_apicoreservice.go (96%) diff --git a/api/coreservice.go b/api/coreservice.go index a65f126572..9b68b636b0 100644 --- a/api/coreservice.go +++ b/api/coreservice.go @@ -65,6 +65,7 @@ import ( "github.com/iotexproject/iotex-core/v2/pkg/log" "github.com/iotexproject/iotex-core/v2/pkg/tracer" "github.com/iotexproject/iotex-core/v2/pkg/unit" + "github.com/iotexproject/iotex-core/v2/pkg/util/byteutil" "github.com/iotexproject/iotex-core/v2/pkg/version" "github.com/iotexproject/iotex-core/v2/server/itx/nodestats" "github.com/iotexproject/iotex-core/v2/state" @@ -81,6 +82,7 @@ const ( type ( // CoreService provides api interface for user to interact with blockchain data CoreService interface { + WithHeight(uint64) CoreServiceReaderWithHeight // Account returns the metadata of an account Account(addr address.Address) (*iotextypes.AccountMeta, *iotextypes.BlockIdentifier, error) // ChainMeta returns blockchain metadata @@ -200,6 +202,7 @@ type ( gs *gasstation.GasStation broadcastHandler BroadcastOutbound cfg Config + archiveSupported bool registry *protocol.Registry chainListener apitypes.Listener electionCommittee committee.Committee @@ -243,13 +246,21 @@ func WithAPIStats(stats *nodestats.APILocalStats) Option { } } +// WithArchiveSupport is the option to enable archive support +func WithArchiveSupport(enabled bool) Option { + return func(svr *coreService) { + svr.archiveSupported = enabled + } +} + type intrinsicGasCalculator interface { IntrinsicGas() (uint64, error) } var ( // ErrNotFound indicates the record isn't found - ErrNotFound = errors.New("not found") + ErrNotFound = errors.New("not found") + ErrArchiveNotSupported = errors.New("archive-mode not supported") ) // newcoreService creates a api server that contains major blockchain components @@ -303,6 +314,10 @@ func newCoreService( return &core, nil } +func (core *coreService) WithHeight(height uint64) CoreServiceReaderWithHeight { + return newCoreServiceWithHeight(core, height) +} + // Account returns the metadata of an account func (core *coreService) Account(addr address.Address) (*iotextypes.AccountMeta, *iotextypes.BlockIdentifier, error) { ctx, span := tracer.NewSpan(context.Background(), "coreService.Account") @@ -311,16 +326,38 @@ func (core *coreService) Account(addr address.Address) (*iotextypes.AccountMeta, if addrStr == address.RewardingPoolAddr || addrStr == address.StakingBucketPoolAddr { return core.getProtocolAccount(ctx, addrStr) } - span.AddEvent("accountutil.AccountStateWithHeight") ctx = genesis.WithGenesisContext(ctx, core.bc.Genesis()) - state, tipHeight, err := accountutil.AccountStateWithHeight(ctx, core.sf, addr) + return core.acccount(ctx, core.bc.TipHeight(), false, core.sf, addr) +} + +func (core *coreService) acccount(ctx context.Context, height uint64, archive bool, sr protocol.StateReader, addr address.Address) (*iotextypes.AccountMeta, *iotextypes.BlockIdentifier, error) { + span := tracer.SpanFromContext(ctx) + span.AddEvent("accountutil.AccountStateWithHeight") + state, height, err := accountutil.AccountStateWithHeight(ctx, sr, addr) if err != nil { return nil, nil, status.Error(codes.NotFound, err.Error()) } span.AddEvent("ap.GetPendingNonce") - pendingNonce, err := core.ap.GetPendingNonce(addrStr) - if err != nil { - return nil, nil, status.Error(codes.Internal, err.Error()) + var ( + addrStr = addr.String() + pendingNonce uint64 + ) + if archive { + state, err := accountutil.AccountState(ctx, sr, addr) + if err != nil { + return nil, nil, status.Error(codes.NotFound, err.Error()) + } + g := core.bc.Genesis() + if g.IsSumatra(height) { + pendingNonce = state.PendingNonceConsideringFreshAccount() + } else { + pendingNonce = state.PendingNonce() + } + } else { + pendingNonce, err = core.ap.GetPendingNonce(addrStr) + if err != nil { + return nil, nil, status.Error(codes.Internal, err.Error()) + } } if core.indexer == nil { return nil, nil, status.Error(codes.NotFound, blockindex.ErrActionIndexNA.Error()) @@ -340,14 +377,14 @@ func (core *coreService) Account(addr address.Address) (*iotextypes.AccountMeta, } if state.IsContract() { var code protocol.SerializableBytes - _, err = core.sf.State(&code, protocol.NamespaceOption(evm.CodeKVNameSpace), protocol.KeyOption(state.CodeHash)) + _, err = sr.State(&code, protocol.NamespaceOption(evm.CodeKVNameSpace), protocol.KeyOption(state.CodeHash)) if err != nil { return nil, nil, status.Error(codes.NotFound, err.Error()) } accountMeta.ContractByteCode = code } span.AddEvent("bc.BlockHeaderByHeight") - header, err := core.bc.BlockHeaderByHeight(tipHeight) + header, err := core.bc.BlockHeaderByHeight(height) if err != nil { return nil, nil, status.Error(codes.NotFound, err.Error()) } @@ -355,7 +392,7 @@ func (core *coreService) Account(addr address.Address) (*iotextypes.AccountMeta, span.AddEvent("coreService.Account.End") return accountMeta, &iotextypes.BlockIdentifier{ Hash: hex.EncodeToString(hash[:]), - Height: tipHeight, + Height: height, }, nil } @@ -518,7 +555,21 @@ func (core *coreService) ReadContract(ctx context.Context, callerAddr address.Ad if !ok { return "", nil, status.Error(codes.InvalidArgument, "expecting action.Execution") } - key := hash.Hash160b(append([]byte(exec.Contract()), exec.Data()...)) + var ( + tipHeight = core.bc.TipHeight() + hdBytes = append(byteutil.Uint64ToBytesBigEndian(tipHeight), []byte(exec.Contract())...) + key = hash.Hash160b(append(hdBytes, exec.Data()...)) + ) + return core.readContract(ctx, key, tipHeight, false, callerAddr, elp) +} + +func (core *coreService) readContract( + ctx context.Context, + key hash.Hash160, + height uint64, + archive bool, + callerAddr address.Address, + elp action.Envelope) (string, *iotextypes.Receipt, error) { // TODO: either moving readcache into the upper layer or change the storage format if d, ok := core.readCache.Get(key); ok { res := iotexapi.ReadContractResponse{} @@ -528,15 +579,17 @@ func (core *coreService) ReadContract(ctx context.Context, callerAddr address.Ad } var ( g = core.bc.Genesis() - blockGasLimit = g.BlockGasLimitByHeight(core.bc.TipHeight()) + blockGasLimit = g.BlockGasLimitByHeight(height) ) if elp.Gas() == 0 || blockGasLimit < elp.Gas() { elp.SetGas(blockGasLimit) } - retval, receipt, err := core.simulateExecution(ctx, callerAddr, elp) + retval, receipt, err := core.simulateExecution(ctx, height, archive, callerAddr, elp) if err != nil { return "", nil, status.Error(codes.Internal, err.Error()) } + // ReadContract() is read-only, if no error returned, we consider it a success + receipt.Status = uint64(iotextypes.ReceiptStatus_Success) res := iotexapi.ReadContractResponse{ Data: hex.EncodeToString(retval), Receipt: receipt.ConvertToReceiptPb(), @@ -1670,7 +1723,7 @@ func (core *coreService) isGasLimitEnough( ) (bool, *action.Receipt, error) { ctx, span := tracer.NewSpan(ctx, "Server.isGasLimitEnough") defer span.End() - _, receipt, err := core.simulateExecution(ctx, caller, elp, opts...) + _, receipt, err := core.simulateExecution(ctx, core.bc.TipHeight(), false, caller, elp, opts...) if err != nil { return false, nil, err } @@ -1815,10 +1868,11 @@ func (core *coreService) ReceiveBlock(blk *block.Block) error { func (core *coreService) SimulateExecution(ctx context.Context, addr address.Address, elp action.Envelope) ([]byte, *action.Receipt, error) { var ( g = core.bc.Genesis() - blockGasLimit = g.BlockGasLimitByHeight(core.bc.TipHeight()) + tipHeight = core.bc.TipHeight() + blockGasLimit = g.BlockGasLimitByHeight(tipHeight) ) elp.SetGas(blockGasLimit) - return core.simulateExecution(ctx, addr, elp) + return core.simulateExecution(ctx, tipHeight, false, addr, elp) } // SyncingProgress returns the syncing status of node @@ -1842,7 +1896,7 @@ func (core *coreService) TraceTransaction(ctx context.Context, actHash string, c } addr, _ := address.FromString(address.ZeroAddress) return core.traceTx(ctx, new(tracers.Context), config, func(ctx context.Context) ([]byte, *action.Receipt, error) { - return core.simulateExecution(ctx, addr, act.Envelope) + return core.simulateExecution(ctx, core.bc.TipHeight(), false, addr, act.Envelope) }) } @@ -1870,7 +1924,7 @@ func (core *coreService) TraceCall(ctx context.Context, elp := (&action.EnvelopeBuilder{}).SetAction(action.NewExecution(contractAddress, amount, data)). SetGasLimit(gasLimit).Build() return core.traceTx(ctx, new(tracers.Context), config, func(ctx context.Context) ([]byte, *action.Receipt, error) { - return core.simulateExecution(ctx, callerAddr, elp) + return core.simulateExecution(ctx, core.bc.TipHeight(), false, callerAddr, elp) }) } @@ -1929,20 +1983,42 @@ func (core *coreService) traceTx(ctx context.Context, txctx *tracers.Context, co return retval, receipt, tracer, err } -func (core *coreService) simulateExecution(ctx context.Context, addr address.Address, elp action.Envelope, opts ...protocol.SimulateOption) ([]byte, *action.Receipt, error) { - ctx, err := core.bc.Context(ctx) +func (core *coreService) simulateExecution( + ctx context.Context, + height uint64, + archive bool, + addr address.Address, + elp action.Envelope, + opts ...protocol.SimulateOption) ([]byte, *action.Receipt, error) { + var ( + err error + ws protocol.StateManager + ) + if archive { + ctx, err = core.bc.ContextAtHeight(ctx, height) + if err != nil { + return nil, nil, status.Error(codes.Internal, err.Error()) + } + ws, err = core.sf.WorkingSetAtHeight(ctx, height) + } else { + ctx, err = core.bc.Context(ctx) + if err != nil { + return nil, nil, status.Error(codes.Internal, err.Error()) + } + ws, err = core.sf.WorkingSet(ctx) + } if err != nil { return nil, nil, status.Error(codes.Internal, err.Error()) } - state, err := accountutil.AccountState(ctx, core.sf, addr) + state, err := accountutil.AccountState(ctx, ws, addr) if err != nil { return nil, nil, status.Error(codes.InvalidArgument, err.Error()) } var pendingNonce uint64 ctx = protocol.WithFeatureCtx(protocol.WithBlockCtx(ctx, protocol.BlockCtx{ - BlockHeight: core.bc.TipHeight(), + BlockHeight: height, })) - if protocol.MustGetFeatureCtx(ctx).RefactorFreshAccountConversion { + if protocol.MustGetFeatureCtx(ctx).UseZeroNonceForFreshAccount { pendingNonce = state.PendingNonceConsideringFreshAccount() } else { pendingNonce = state.PendingNonce() @@ -1953,10 +2029,6 @@ func (core *coreService) simulateExecution(ctx context.Context, addr address.Add GetBlockTime: core.getBlockTime, DepositGasFunc: rewarding.DepositGas, }) - ws, err := core.sf.WorkingSet(ctx) - if err != nil { - return nil, nil, status.Error(codes.Internal, err.Error()) - } return evm.SimulateExecution(ctx, ws, addr, elp, opts...) } diff --git a/api/coreservice_test.go b/api/coreservice_test.go index b6d985f6a9..6264f4333c 100644 --- a/api/coreservice_test.go +++ b/api/coreservice_test.go @@ -488,11 +488,12 @@ func TestEstimateExecutionGasConsumption(t *testing.T) { p := NewPatches() defer p.Reset() - p = p.ApplyFuncReturn(accountutil.AccountState, nil, errors.New(t.Name())) + p = p.ApplyFuncReturn(accountutil.AccountStateWithHeight, nil, uint64(0), errors.New(t.Name())) bc.EXPECT().Genesis().Return(genesis.Genesis{}).Times(1) - bc.EXPECT().TipHeight().Return(uint64(1)).Times(1) + bc.EXPECT().TipHeight().Return(uint64(1)).Times(2) bc.EXPECT().Context(gomock.Any()).Return(ctx, nil).Times(1) + sf.EXPECT().WorkingSet(gomock.Any()).Return(nil, nil).Times(1) elp := (&action.EnvelopeBuilder{}).SetAction(&action.Execution{}).Build() _, err := cs.EstimateExecutionGasConsumption(ctx, elp, &address.AddrV1{}) require.ErrorContains(err, t.Name()) @@ -1022,9 +1023,11 @@ func TestSimulateExecution(t *testing.T) { var ( bc = mock_blockchain.NewMockBlockchain(ctrl) dao = mock_blockdao.NewMockBlockDAO(ctrl) + sf = mock_factory.NewMockFactory(ctrl) cs = &coreService{ bc: bc, dao: dao, + sf: sf, } ctx = context.Background() ) @@ -1037,6 +1040,7 @@ func TestSimulateExecution(t *testing.T) { bc.EXPECT().Genesis().Return(genesis.Genesis{}).Times(1) bc.EXPECT().TipHeight().Return(uint64(1)).Times(1) bc.EXPECT().Context(gomock.Any()).Return(ctx, nil).Times(1) + sf.EXPECT().WorkingSet(gomock.Any()).Return(nil, nil).Times(1) elp := (&action.EnvelopeBuilder{}).SetAction(&action.Execution{}).Build() _, _, err := cs.SimulateExecution(ctx, &address.AddrV1{}, elp) require.ErrorContains(err, t.Name()) diff --git a/api/coreservice_with_height.go b/api/coreservice_with_height.go new file mode 100644 index 0000000000..31d8aa0254 --- /dev/null +++ b/api/coreservice_with_height.go @@ -0,0 +1,71 @@ +package api + +import ( + "context" + + "github.com/iotexproject/go-pkgs/hash" + "github.com/iotexproject/iotex-address/address" + "github.com/iotexproject/iotex-proto/golang/iotextypes" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/iotexproject/iotex-core/v2/action" + "github.com/iotexproject/iotex-core/v2/blockchain/genesis" + "github.com/iotexproject/iotex-core/v2/pkg/log" + "github.com/iotexproject/iotex-core/v2/pkg/tracer" + "github.com/iotexproject/iotex-core/v2/pkg/util/byteutil" +) + +type ( + // CoreServiceReaderWithHeight is an interface for state reader at certain height + CoreServiceReaderWithHeight interface { + Account(address.Address) (*iotextypes.AccountMeta, *iotextypes.BlockIdentifier, error) + ReadContract(context.Context, address.Address, action.Envelope) (string, *iotextypes.Receipt, error) + } + + coreServiceReaderWithHeight struct { + cs *coreService + height uint64 + } +) + +func newCoreServiceWithHeight(cs *coreService, height uint64) *coreServiceReaderWithHeight { + return &coreServiceReaderWithHeight{ + cs: cs, + height: height, + } +} + +func (core *coreServiceReaderWithHeight) Account(addr address.Address) (*iotextypes.AccountMeta, *iotextypes.BlockIdentifier, error) { + if !core.cs.archiveSupported { + return nil, nil, ErrArchiveNotSupported + } + ctx, span := tracer.NewSpan(context.Background(), "coreServiceReaderWithHeight.Account") + defer span.End() + addrStr := addr.String() + if addrStr == address.RewardingPoolAddr || addrStr == address.StakingBucketPoolAddr { + return core.cs.getProtocolAccount(ctx, addrStr) + } + ctx = genesis.WithGenesisContext(ctx, core.cs.bc.Genesis()) + ws, err := core.cs.sf.WorkingSetAtHeight(ctx, core.height) + if err != nil { + return nil, nil, err + } + return core.cs.acccount(ctx, core.height, true, ws, addr) +} + +func (core *coreServiceReaderWithHeight) ReadContract(ctx context.Context, callerAddr address.Address, elp action.Envelope) (string, *iotextypes.Receipt, error) { + if !core.cs.archiveSupported { + return "", nil, ErrArchiveNotSupported + } + log.Logger("api").Debug("receive read smart contract request") + exec, ok := elp.Action().(*action.Execution) + if !ok { + return "", nil, status.Error(codes.InvalidArgument, "expecting action.Execution") + } + var ( + hdBytes = append(byteutil.Uint64ToBytesBigEndian(core.height), []byte(exec.Contract())...) + key = hash.Hash160b(append(hdBytes, exec.Data()...)) + ) + return core.cs.readContract(ctx, key, core.height, true, callerAddr, elp) +} diff --git a/api/grpcserver_integrity_test.go b/api/grpcserver_integrity_test.go index e650f96286..c7e540b07c 100644 --- a/api/grpcserver_integrity_test.go +++ b/api/grpcserver_integrity_test.go @@ -1485,7 +1485,7 @@ func TestGrpcServer_ReadContractIntegrity(t *testing.T) { res, err := grpcHandler.ReadContract(context.Background(), request) require.NoError(err) require.Equal(test.retValue, res.Data) - require.EqualValues(0, res.Receipt.Status) + require.EqualValues(1, res.Receipt.Status) require.Equal(test.actionHash, hex.EncodeToString(res.Receipt.ActHash)) require.Equal(test.gasConsumed, res.Receipt.GasConsumed) } diff --git a/api/grpcserver_test.go b/api/grpcserver_test.go index f1d13ffb27..8cfbe04016 100644 --- a/api/grpcserver_test.go +++ b/api/grpcserver_test.go @@ -24,7 +24,6 @@ import ( "github.com/iotexproject/iotex-core/v2/blockchain/block" "github.com/iotexproject/iotex-core/v2/pkg/version" "github.com/iotexproject/iotex-core/v2/test/identityset" - "github.com/iotexproject/iotex-core/v2/test/mock/mock_apicoreservice" mock_apitypes "github.com/iotexproject/iotex-core/v2/test/mock/mock_apiresponder" ) @@ -32,7 +31,7 @@ func TestGrpcServer_GetAccount(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) t.Run("get acccount", func(t *testing.T) { @@ -80,7 +79,7 @@ func TestGrpcServer_GetActions(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) t.Run("get actions by address tests", func(t *testing.T) { @@ -248,7 +247,7 @@ func TestGrpcServer_GetBlockMetas(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) errStr := "get block metas mock test error" @@ -302,7 +301,7 @@ func TestGrpcServer_GetChainMeta(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) chainMeta := &iotextypes.ChainMeta{ Height: 1000, @@ -323,7 +322,7 @@ func TestGrpcServer_SendAction(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) for _, test := range _sendActionTests { @@ -339,7 +338,7 @@ func TestGrpcServer_StreamBlocks(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) t.Run("addResponder failed", func(t *testing.T) { @@ -371,7 +370,7 @@ func TestGrpcServer_StreamLogs(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) t.Run("StreamLogsEmptyFilter", func(t *testing.T) { @@ -406,7 +405,7 @@ func TestGrpcServer_GetReceiptByAction(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) receipt := &action.Receipt{ Status: 1, @@ -454,7 +453,7 @@ func TestGrpcServer_GetServerMeta(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) core.EXPECT().ServerMeta().Return("packageVersion", "packageCommitID", "gitStatus", "goVersion", "buildTime") @@ -471,7 +470,7 @@ func TestGrpcServer_ReadContract(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) response := &iotextypes.Receipt{ ActHash: []byte("08b0066e10b5607e47159c2cf7ba36e36d0c980f5108dfca0ec20547a7adace4"), @@ -555,7 +554,7 @@ func TestGrpcServer_SuggestGasPrice(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) core.EXPECT().SuggestGasPrice().Return(uint64(1), nil) @@ -572,7 +571,7 @@ func TestGrpcServer_EstimateGasForAction(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) core.EXPECT().EstimateGasForAction(gomock.Any(), gomock.Any()).Return(uint64(10000), nil) @@ -589,7 +588,7 @@ func TestGrpcServer_EstimateActionGasConsumption(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) request := &iotexapi.EstimateActionGasConsumptionRequest{ CallerAddress: identityset.Address(0).String(), @@ -749,7 +748,7 @@ func TestGrpcServer_ReadState(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) core.EXPECT().ReadState(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&iotexapi.ReadStateResponse{ Data: []byte("10100"), @@ -766,7 +765,7 @@ func TestGrpcServer_GetEpochMeta(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) epochData := &iotextypes.EpochData{Num: 7000} blockProducersInfo := []*iotexapi.BlockProducerInfo{{Production: 8000}} @@ -784,7 +783,7 @@ func TestGrpcServer_GetRawBlocks(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) blocks := []*iotexapi.BlockInfo{ @@ -828,7 +827,7 @@ func TestGrpcServer_GetLogs(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) request := &iotexapi.GetLogsRequest{ Filter: &iotexapi.LogsFilter{ @@ -914,7 +913,7 @@ func TestGrpcServer_GetElectionBuckets(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) buckets := []*iotextypes.ElectionBucket{ @@ -935,7 +934,7 @@ func TestGrpcServer_GetTransactionLogByActionHash(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) txLog := &iotextypes.TransactionLog{ @@ -954,7 +953,7 @@ func TestGrpcServer_GetTransactionLogByBlockHeight(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) blockIdentifier := &iotextypes.BlockIdentifier{ @@ -981,7 +980,7 @@ func TestGrpcServer_GetActPoolActions(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) addr1 := identityset.Address(28).String() @@ -1007,7 +1006,7 @@ func TestGrpcServer_ReadContractStorage(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) core.EXPECT().ReadContractStorage(gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte("_data"), nil) @@ -1023,7 +1022,7 @@ func TestGrpcServer_TraceTransactionStructLogs(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) core.EXPECT().TraceTransaction(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil, logger.NewStructLogger(nil), nil) diff --git a/test/mock/mock_apicoreservice/mock_apicoreservice.go b/api/mock_apicoreservice.go similarity index 96% rename from test/mock/mock_apicoreservice/mock_apicoreservice.go rename to api/mock_apicoreservice.go index 9985598d58..f55be22c74 100644 --- a/test/mock/mock_apicoreservice/mock_apicoreservice.go +++ b/api/mock_apicoreservice.go @@ -1,8 +1,8 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./api/coreservice.go -// Package mock_apicoreservice is a generated GoMock package. -package mock_apicoreservice +// Package api is a generated GoMock package. +package api import ( context "context" @@ -17,7 +17,7 @@ import ( action "github.com/iotexproject/iotex-core/v2/action" protocol "github.com/iotexproject/iotex-core/v2/action/protocol" logfilter "github.com/iotexproject/iotex-core/v2/api/logfilter" - apitypes "github.com/iotexproject/iotex-core/v2/api/types" + types "github.com/iotexproject/iotex-core/v2/api/types" block "github.com/iotexproject/iotex-core/v2/blockchain/block" genesis "github.com/iotexproject/iotex-core/v2/blockchain/genesis" iotexapi "github.com/iotexproject/iotex-proto/golang/iotexapi" @@ -141,10 +141,10 @@ func (mr *MockCoreServiceMockRecorder) ActionsInActPool(actHashes interface{}) * } // BlobSidecarsByHeight mocks base method. -func (m *MockCoreService) BlobSidecarsByHeight(height uint64) ([]*apitypes.BlobSidecarResult, error) { +func (m *MockCoreService) BlobSidecarsByHeight(height uint64) ([]*types.BlobSidecarResult, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "BlobSidecarsByHeight", height) - ret0, _ := ret[0].([]*apitypes.BlobSidecarResult) + ret0, _ := ret[0].([]*types.BlobSidecarResult) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -156,10 +156,10 @@ func (mr *MockCoreServiceMockRecorder) BlobSidecarsByHeight(height interface{}) } // BlockByHash mocks base method. -func (m *MockCoreService) BlockByHash(arg0 string) (*apitypes.BlockWithReceipts, error) { +func (m *MockCoreService) BlockByHash(arg0 string) (*types.BlockWithReceipts, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "BlockByHash", arg0) - ret0, _ := ret[0].(*apitypes.BlockWithReceipts) + ret0, _ := ret[0].(*types.BlockWithReceipts) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -171,10 +171,10 @@ func (mr *MockCoreServiceMockRecorder) BlockByHash(arg0 interface{}) *gomock.Cal } // BlockByHeight mocks base method. -func (m *MockCoreService) BlockByHeight(arg0 uint64) (*apitypes.BlockWithReceipts, error) { +func (m *MockCoreService) BlockByHeight(arg0 uint64) (*types.BlockWithReceipts, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "BlockByHeight", arg0) - ret0, _ := ret[0].(*apitypes.BlockWithReceipts) + ret0, _ := ret[0].(*types.BlockWithReceipts) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -186,10 +186,10 @@ func (mr *MockCoreServiceMockRecorder) BlockByHeight(arg0 interface{}) *gomock.C } // BlockByHeightRange mocks base method. -func (m *MockCoreService) BlockByHeightRange(arg0, arg1 uint64) ([]*apitypes.BlockWithReceipts, error) { +func (m *MockCoreService) BlockByHeightRange(arg0, arg1 uint64) ([]*types.BlockWithReceipts, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "BlockByHeightRange", arg0, arg1) - ret0, _ := ret[0].([]*apitypes.BlockWithReceipts) + ret0, _ := ret[0].([]*types.BlockWithReceipts) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -230,10 +230,10 @@ func (mr *MockCoreServiceMockRecorder) ChainID() *gomock.Call { } // ChainListener mocks base method. -func (m *MockCoreService) ChainListener() apitypes.Listener { +func (m *MockCoreService) ChainListener() types.Listener { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChainListener") - ret0, _ := ret[0].(apitypes.Listener) + ret0, _ := ret[0].(types.Listener) return ret0 } @@ -764,6 +764,20 @@ func (mr *MockCoreServiceMockRecorder) UnconfirmedActionsByAddress(address, star return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnconfirmedActionsByAddress", reflect.TypeOf((*MockCoreService)(nil).UnconfirmedActionsByAddress), address, start, count) } +// WithHeight mocks base method. +func (m *MockCoreService) WithHeight(arg0 uint64) CoreServiceReaderWithHeight { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WithHeight", arg0) + ret0, _ := ret[0].(CoreServiceReaderWithHeight) + return ret0 +} + +// WithHeight indicates an expected call of WithHeight. +func (mr *MockCoreServiceMockRecorder) WithHeight(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WithHeight", reflect.TypeOf((*MockCoreService)(nil).WithHeight), arg0) +} + // MockintrinsicGasCalculator is a mock of intrinsicGasCalculator interface. type MockintrinsicGasCalculator struct { ctrl *gomock.Controller diff --git a/api/serverV2_test.go b/api/serverV2_test.go index 42db6a3b67..15b40cff1a 100644 --- a/api/serverV2_test.go +++ b/api/serverV2_test.go @@ -14,7 +14,6 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/time/rate" - "github.com/iotexproject/iotex-core/v2/test/mock/mock_apicoreservice" "github.com/iotexproject/iotex-core/v2/testutil" ) @@ -22,7 +21,7 @@ func TestServerV2(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3Handler := NewWeb3Handler(core, "", _defaultBatchRequestLimit) svr := &ServerV2{ core: core, diff --git a/api/web3server.go b/api/web3server.go index ed452ef9d9..f1836fe2f2 100644 --- a/api/web3server.go +++ b/api/web3server.go @@ -352,7 +352,20 @@ func (svr *web3Handler) getBalance(in *gjson.Result) (interface{}, error) { if err != nil { return nil, err } - accountMeta, _, err := svr.coreService.Account(ioAddr) + bnParam := in.Get("params.1") + bn, err := parseBlockNumber(&bnParam) + if err != nil { + return nil, err + } + var ( + accountMeta *iotextypes.AccountMeta + height, archive = blockNumberToHeight(bn) + ) + if !archive { + accountMeta, _, err = svr.coreService.Account(ioAddr) + } else { + accountMeta, _, err = svr.coreService.WithHeight(height).Account(ioAddr) + } if err != nil { return nil, err } @@ -420,9 +433,18 @@ func (svr *web3Handler) call(ctx context.Context, in *gjson.Result) (interface{} } return "0x" + ret, nil } - elp := (&action.EnvelopeBuilder{}).SetAction(action.NewExecution(to, callMsg.Value, data)). - SetGasLimit(callMsg.Gas).Build() - ret, receipt, err := svr.coreService.ReadContract(ctx, callMsg.From, elp) + var ( + elp = (&action.EnvelopeBuilder{}).SetAction(action.NewExecution(to, callMsg.Value, data)). + SetGasLimit(callMsg.Gas).Build() + ret string + receipt *iotextypes.Receipt + height, archive = blockNumberToHeight(callMsg.BlockNumber) + ) + if !archive { + ret, receipt, err = svr.coreService.ReadContract(context.Background(), callMsg.From, elp) + } else { + ret, receipt, err = svr.coreService.WithHeight(height).ReadContract(context.Background(), callMsg.From, elp) + } if err != nil { return nil, err } diff --git a/api/web3server_test.go b/api/web3server_test.go index 99140cab02..a74b6ee184 100644 --- a/api/web3server_test.go +++ b/api/web3server_test.go @@ -31,7 +31,6 @@ import ( "github.com/iotexproject/iotex-core/v2/blockchain/block" "github.com/iotexproject/iotex-core/v2/blockchain/genesis" "github.com/iotexproject/iotex-core/v2/test/identityset" - "github.com/iotexproject/iotex-core/v2/test/mock/mock_apicoreservice" mock_apitypes "github.com/iotexproject/iotex-core/v2/test/mock/mock_apiresponder" "github.com/iotexproject/iotex-core/v2/testutil" ) @@ -101,7 +100,7 @@ func TestHandlePost(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) core.EXPECT().Track(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return().AnyTimes() svr := newHTTPHandler(NewWeb3Handler(core, "", _defaultBatchRequestLimit)) getServerResp := func(svr *hTTPHandler, req *http.Request) *httptest.ResponseRecorder { @@ -170,7 +169,7 @@ func TestGasPrice(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} core.EXPECT().SuggestGasPrice().Return(uint64(1), nil) ret, err := web3svr.gasPrice() @@ -186,7 +185,7 @@ func TestGetChainID(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} core.EXPECT().EVMNetworkID().Return(uint32(1)) ret, err := web3svr.getChainID() @@ -198,7 +197,7 @@ func TestGetBlockNumber(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} core.EXPECT().TipHeight().Return(uint64(1)) ret, err := web3svr.getBlockNumber() @@ -210,7 +209,7 @@ func TestGetBlockByNumber(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} tsf, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0)) @@ -261,9 +260,10 @@ func TestGetBalance(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} balance := "111111111111111111" + core.EXPECT().WithHeight(gomock.Any()).Return(core).Times(1) core.EXPECT().Account(gomock.Any()).Return(&iotextypes.AccountMeta{Balance: balance}, nil, nil) in := gjson.Parse(`{"params":["0xDa7e12Ef57c236a06117c5e0d04a228e7181CF36", "0x1"]}`) @@ -278,7 +278,7 @@ func TestGetTransactionCount(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} core.EXPECT().PendingNonce(gomock.Any()).Return(uint64(2), nil) @@ -296,7 +296,7 @@ func TestCall(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} t.Run("to is StakingProtocol addr", func(t *testing.T) { @@ -383,7 +383,7 @@ func TestEstimateGas(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} core.EXPECT().ChainID().Return(uint32(1)).Times(2) core.EXPECT().EVMNetworkID().Return(uint32(0)).Times(2) @@ -427,7 +427,7 @@ func TestSendRawTransaction(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} core.EXPECT().Genesis().Return(genesis.Default) core.EXPECT().TipHeight().Return(uint64(0)) @@ -454,7 +454,7 @@ func TestGetCode(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} code := "608060405234801561001057600080fd5b50610150806100206contractbytecode" data, _ := hex.DecodeString(code) @@ -478,7 +478,7 @@ func TestGetNodeInfo(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} core.EXPECT().ServerMeta().Return("111", "", "", "222", "") ret, err := web3svr.getNodeInfo() @@ -490,7 +490,7 @@ func TestGetNetworkID(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} core.EXPECT().EVMNetworkID().Return(uint32(123)) ret, err := web3svr.getNetworkID() @@ -502,7 +502,7 @@ func TestIsSyncing(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} core.EXPECT().SyncingProgress().Return(uint64(1), uint64(2), uint64(3)) ret, err := web3svr.isSyncing() @@ -518,7 +518,7 @@ func TestGetBlockTransactionCountByHash(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} tsf, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0)) @@ -554,7 +554,7 @@ func TestGetBlockByHash(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} tsf, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0)) @@ -606,7 +606,7 @@ func TestGetTransactionByHash(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} selp, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0)) @@ -676,7 +676,7 @@ func TestGetLogs(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} logs := []*action.Log{ @@ -725,7 +725,7 @@ func TestGetTransactionReceipt(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} selp, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0)) @@ -773,7 +773,7 @@ func TestGetBlockTransactionCountByNumber(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} tsf, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0)) @@ -808,7 +808,7 @@ func TestGetTransactionByBlockHashAndIndex(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} tsf, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0)) @@ -855,7 +855,7 @@ func TestGetTransactionByBlockNumberAndIndex(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} tsf, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), uint64(1), big.NewInt(10), []byte{}, uint64(100000), big.NewInt(0)) @@ -901,7 +901,7 @@ func TestGetStorageAt(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} val := []byte("test") core.EXPECT().ReadContractStorage(gomock.Any(), gomock.Any(), gomock.Any()).Return(val, nil) @@ -916,7 +916,7 @@ func TestNewfilter(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, newAPICache(1*time.Second, ""), _defaultBatchRequestLimit} ret, err := web3svr.newFilter(&filterObject{ @@ -933,7 +933,7 @@ func TestNewBlockFilter(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, newAPICache(1*time.Second, ""), _defaultBatchRequestLimit} core.EXPECT().TipHeight().Return(uint64(123)) @@ -946,7 +946,7 @@ func TestUninstallFilter(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, newAPICache(1*time.Second, ""), _defaultBatchRequestLimit} require.NoError(web3svr.cache.Set("123456789abc", []byte("test"))) @@ -969,7 +969,7 @@ func TestGetFilterChanges(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, newAPICache(1*time.Second, ""), _defaultBatchRequestLimit} core.EXPECT().TipHeight().Return(uint64(0)).Times(3) @@ -1054,7 +1054,7 @@ func TestGetFilterLogs(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, newAPICache(1*time.Second, ""), _defaultBatchRequestLimit} logs := []*action.Log{ @@ -1110,7 +1110,7 @@ func TestSubscribe(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} listener := mock_apitypes.NewMockListener(ctrl) @@ -1161,7 +1161,7 @@ func TestUnsubscribe(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} listener := mock_apitypes.NewMockListener(ctrl) @@ -1201,7 +1201,7 @@ func TestDebugTraceTransaction(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} ctx := context.Background() @@ -1240,7 +1240,7 @@ func TestDebugTraceCall(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} ctx := context.Background() @@ -1271,7 +1271,7 @@ func TestResponseIDMatchTypeWithRequest(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) core.EXPECT().TipHeight().Return(uint64(1)).AnyTimes() core.EXPECT().Track(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return().AnyTimes() svr := newHTTPHandler(NewWeb3Handler(core, "", _defaultBatchRequestLimit)) diff --git a/api/web3server_utils.go b/api/web3server_utils.go index dd264b1404..14bae33508 100644 --- a/api/web3server_utils.go +++ b/api/web3server_utils.go @@ -383,6 +383,31 @@ func parseCallObject(in *gjson.Result) (*callMsg, error) { }, nil } +func parseBlockNumber(in *gjson.Result) (rpc.BlockNumber, error) { + if !in.Exists() { + return rpc.LatestBlockNumber, nil + } + var height rpc.BlockNumber + if err := height.UnmarshalJSON([]byte(in.String())); err != nil { + return 0, err + } + if height == rpc.PendingBlockNumber { + return 0, errors.Wrap(errNotImplemented, "pending block number is not supported") + } + return height, nil +} + +func blockNumberToHeight(bn rpc.BlockNumber) (uint64, bool) { + switch bn { + case rpc.SafeBlockNumber, rpc.FinalizedBlockNumber, rpc.LatestBlockNumber: + return 0, false + case rpc.EarliestBlockNumber: + return 1, true + default: + return uint64(bn), true + } +} + func (call *callMsg) toUnsignedTx(chainID uint32) (*types.Transaction, error) { var ( tx *types.Transaction diff --git a/api/web3server_utils_test.go b/api/web3server_utils_test.go index 685874e203..5b13e6976c 100644 --- a/api/web3server_utils_test.go +++ b/api/web3server_utils_test.go @@ -10,8 +10,6 @@ import ( "github.com/iotexproject/iotex-address/address" "github.com/stretchr/testify/require" "github.com/tidwall/gjson" - - "github.com/iotexproject/iotex-core/v2/test/mock/mock_apicoreservice" ) func TestParseCallObject(t *testing.T) { @@ -153,7 +151,7 @@ func TestParseBlockNumber(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - core := mock_apicoreservice.NewMockCoreService(ctrl) + core := NewMockCoreService(ctrl) web3svr := &web3Handler{core, nil, _defaultBatchRequestLimit} t.Run("earliest block number", func(t *testing.T) { diff --git a/chainservice/chainservice.go b/chainservice/chainservice.go index 0a4e234a10..2dc45bad2f 100644 --- a/chainservice/chainservice.go +++ b/chainservice/chainservice.go @@ -216,7 +216,7 @@ func (cs *ChainService) NodeInfoManager() *nodeinfo.InfoManager { func (cs *ChainService) Registry() *protocol.Registry { return cs.registry } // NewAPIServer creates a new api server -func (cs *ChainService) NewAPIServer(cfg api.Config, plugins map[int]interface{}) (*api.ServerV2, error) { +func (cs *ChainService) NewAPIServer(cfg api.Config, archive bool) (*api.ServerV2, error) { if cfg.GRPCPort == 0 && cfg.HTTPPort == 0 { return nil, nil } @@ -227,6 +227,7 @@ func (cs *ChainService) NewAPIServer(cfg api.Config, plugins map[int]interface{} }), api.WithNativeElection(cs.electionCommittee), api.WithAPIStats(cs.apiStats), + api.WithArchiveSupport(archive), } svr, err := api.NewServerV2( diff --git a/misc/scripts/mockgen.sh b/misc/scripts/mockgen.sh index c2f5deb9d7..db12a99ff3 100755 --- a/misc/scripts/mockgen.sh +++ b/misc/scripts/mockgen.sh @@ -127,10 +127,9 @@ mockgen -destination=./test/mock/mock_apiserver/mock_apiserver.go \ -package=mock_apiserver \ StreamBlocksServer -mkdir -p ./test/mock/mock_apicoreservice -mockgen -destination=./test/mock/mock_apicoreservice/mock_apicoreservice.go \ +mockgen -destination=./api/mock_apicoreservice.go \ -source=./api/coreservice.go \ - -package=mock_apicoreservice \ + -package=api \ CoreService mkdir -p ./test/mock/mock_blockindex diff --git a/server/itx/server.go b/server/itx/server.go index 013fe1010c..274cf52d36 100644 --- a/server/itx/server.go +++ b/server/itx/server.go @@ -83,7 +83,7 @@ func newServer(cfg config.Config, testing bool) (*Server, error) { return nil, errors.Wrap(err, "fail to create chain service") } nodeStats := nodestats.NewNodeStats(rpcStats, cs.BlockSync(), p2pAgent) - apiServer, err := cs.NewAPIServer(cfg.API, cfg.Plugins) + apiServer, err := cs.NewAPIServer(cfg.API, cfg.Chain.EnableArchiveMode) if err != nil { return nil, errors.Wrap(err, "failed to create api server") }