From d32fde51a0fe04d070d10fcaff08d672f038c8ba Mon Sep 17 00:00:00 2001 From: millken Date: Tue, 17 Jan 2023 14:59:48 +0800 Subject: [PATCH 01/11] add web3 api debug_tracetransaction --- api/coreservice.go | 31 +++++++++++++++ api/web3server.go | 39 +++++++++++++++++++ api/web3server_marshal.go | 9 +++++ .../mock_apicoreservice.go | 18 +++++++++ 4 files changed, 97 insertions(+) diff --git a/api/coreservice.go b/api/coreservice.go index 12ab4e8602..9f256081e0 100644 --- a/api/coreservice.go +++ b/api/coreservice.go @@ -15,6 +15,8 @@ import ( "strconv" "time" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/pkg/errors" "go.uber.org/zap" "golang.org/x/sync/errgroup" @@ -26,6 +28,7 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" "github.com/iotexproject/go-pkgs/hash" + "github.com/iotexproject/go-pkgs/util" "github.com/iotexproject/iotex-address/address" "github.com/iotexproject/iotex-election/committee" "github.com/iotexproject/iotex-proto/golang/iotexapi" @@ -140,6 +143,8 @@ type ( ReceiveBlock(blk *block.Block) error // BlockHashByBlockHeight returns block hash by block height BlockHashByBlockHeight(blkHeight uint64) (hash.Hash256, error) + // TraceTransaction returns the trace result of a transaction + TraceTransaction(ctx context.Context, actHash string, config *logger.Config) ([]byte, *action.Receipt, *logger.StructLogger, error) } // coreService implements the CoreService interface @@ -1582,3 +1587,29 @@ func (core *coreService) SyncingProgress() (uint64, uint64, uint64) { startingHeight, currentHeight, targetHeight, _ := core.bs.SyncStatus() return startingHeight, currentHeight, targetHeight } + +// TraceTransaction returns the trace result of transaction +func (core *coreService) TraceTransaction(ctx context.Context, actHash string, config *logger.Config) (retval []byte, receipt *action.Receipt, traces *logger.StructLogger, err error) { + actInfo, err := core.Action(util.Remove0xPrefix(actHash), false) + if err != nil { + return nil, nil, nil, err + } + act, err := (&action.Deserializer{}).SetEvmNetworkID(core.EVMNetworkID()).ActionToSealedEnvelope(actInfo.Action) + if err != nil { + return + } + sc, ok := act.Action().(*action.Execution) + if !ok { + err = status.Error(codes.InvalidArgument, "the type of action is not supported") + return + } + traces = logger.NewStructLogger(nil) + ctx = protocol.WithVMConfigCtx(ctx, vm.Config{ + Debug: true, + Tracer: traces, + NoBaseFee: true, + }) + + retval, receipt, err = core.SimulateExecution(ctx, act.SenderAddress(), sc) + return +} diff --git a/api/web3server.go b/api/web3server.go index ab02014c41..ffbb8804b9 100644 --- a/api/web3server.go +++ b/api/web3server.go @@ -11,6 +11,7 @@ import ( "time" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/iotexproject/go-pkgs/hash" "github.com/iotexproject/go-pkgs/util" "github.com/iotexproject/iotex-address/address" @@ -205,6 +206,8 @@ func (svr *web3Handler) handleWeb3Req(ctx context.Context, web3Req *gjson.Result res, err = svr.subscribe(web3Req, writer) case "eth_unsubscribe": res, err = svr.unsubscribe(web3Req) + case "debug_traceTransaction": + res, err = svr.traceTransaction(ctx, web3Req) case "eth_coinbase", "eth_getUncleCountByBlockHash", "eth_getUncleCountByBlockNumber", "eth_sign", "eth_signTransaction", "eth_sendTransaction", "eth_getUncleByBlockHashAndIndex", "eth_getUncleByBlockNumberAndIndex", "eth_pendingTransactions": @@ -880,6 +883,42 @@ func (svr *web3Handler) unsubscribe(in *gjson.Result) (interface{}, error) { return chainListener.RemoveResponder(id.String()) } +func (svr *web3Handler) traceTransaction(ctx context.Context, in *gjson.Result) (interface{}, error) { + actHash, options := in.Get("params.0"), in.Get("params.1") + if !actHash.Exists() { + return nil, errInvalidFormat + } + hash := util.Remove0xPrefix(actHash.String()) + if len(hash) != 64 { + return nil, errInvalidFormat + } + var ( + enableMemory, disableStack, disableStorage, enableReturnData bool + ) + if options.Exists() { + enableMemory = options.Get("enableMemory").Bool() + disableStack = options.Get("disableStack").Bool() + disableStorage = options.Get("disableStorage").Bool() + enableReturnData = options.Get("enableReturnData").Bool() + } + cfg := &logger.Config{ + EnableMemory: enableMemory, + DisableStack: disableStack, + DisableStorage: disableStorage, + EnableReturnData: enableReturnData, + } + retval, receipt, traces, err := svr.coreService.TraceTransaction(ctx, hash, cfg) + if err != nil { + return nil, err + } + return &debugTraceTransactionResult{ + Failed: receipt.Status != uint64(iotextypes.ReceiptStatus_Success), + ReturnValue: byteToHex(retval), + StructLogs: traces.StructLogs(), + Gas: receipt.GasConsumed, + }, nil +} + func (svr *web3Handler) unimplemented() (interface{}, error) { return nil, errNotImplemented } diff --git a/api/web3server_marshal.go b/api/web3server_marshal.go index 08647de7e7..18044872d1 100644 --- a/api/web3server_marshal.go +++ b/api/web3server_marshal.go @@ -5,6 +5,7 @@ import ( "encoding/json" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/iotexproject/go-pkgs/crypto" "github.com/iotexproject/go-pkgs/hash" "github.com/iotexproject/iotex-address/address" @@ -75,6 +76,14 @@ type ( CurrentBlock string `json:"currentBlock"` HighestBlock string `json:"highestBlock"` } + + debugTraceTransactionResult struct { + Failed bool `json:"failed"` + Revert string `json:"revert"` + ReturnValue string `json:"returnValue"` + Gas uint64 `json:"gas"` + StructLogs []logger.StructLog `json:"structLogs"` + } ) var ( diff --git a/test/mock/mock_apicoreservice/mock_apicoreservice.go b/test/mock/mock_apicoreservice/mock_apicoreservice.go index 6557bda95c..be4540a4af 100644 --- a/test/mock/mock_apicoreservice/mock_apicoreservice.go +++ b/test/mock/mock_apicoreservice/mock_apicoreservice.go @@ -8,6 +8,7 @@ import ( context "context" reflect "reflect" + logger "github.com/ethereum/go-ethereum/eth/tracers/logger" gomock "github.com/golang/mock/gomock" hash "github.com/iotexproject/go-pkgs/hash" address "github.com/iotexproject/iotex-address/address" @@ -589,6 +590,23 @@ func (mr *MockCoreServiceMockRecorder) TipHeight() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TipHeight", reflect.TypeOf((*MockCoreService)(nil).TipHeight)) } +// TraceTransaction mocks base method. +func (m *MockCoreService) TraceTransaction(ctx context.Context, actHash string, config *logger.Config) ([]byte, *action.Receipt, *logger.StructLogger, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TraceTransaction", ctx, actHash, config) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(*action.Receipt) + ret2, _ := ret[2].(*logger.StructLogger) + ret3, _ := ret[3].(error) + return ret0, ret1, ret2, ret3 +} + +// TraceTransaction indicates an expected call of TraceTransaction. +func (mr *MockCoreServiceMockRecorder) TraceTransaction(ctx, actHash, config interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TraceTransaction", reflect.TypeOf((*MockCoreService)(nil).TraceTransaction), ctx, actHash, config) +} + // TransactionLogByActionHash mocks base method. func (m *MockCoreService) TransactionLogByActionHash(actHash string) (*iotextypes.TransactionLog, error) { m.ctrl.T.Helper() From b9324554db11b4814c28e9a4194426d27be8d4d7 Mon Sep 17 00:00:00 2001 From: millken Date: Wed, 18 Jan 2023 10:44:31 +0800 Subject: [PATCH 02/11] fix debugTraceTransactionResult --- api/web3server.go | 24 +++++++++++++++++++++++- api/web3server_marshal.go | 32 +++++++++++++++++++++++++------- go.mod | 2 +- 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/api/web3server.go b/api/web3server.go index ffbb8804b9..d6dfea93b9 100644 --- a/api/web3server.go +++ b/api/web3server.go @@ -10,6 +10,7 @@ import ( "strconv" "time" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/iotexproject/go-pkgs/hash" @@ -911,10 +912,31 @@ func (svr *web3Handler) traceTransaction(ctx context.Context, in *gjson.Result) if err != nil { return nil, err } + + structLogs := make([]StructLog, 0) + for _, s := range traces.StructLogs() { + var enc StructLog + enc.Pc = s.Pc + enc.Op = s.Op + enc.Gas = math.HexOrDecimal64(s.Gas) + enc.GasCost = math.HexOrDecimal64(s.GasCost) + enc.Memory = s.Memory + enc.MemorySize = s.MemorySize + enc.Stack = s.Stack + enc.ReturnData = s.ReturnData + enc.Storage = s.Storage + enc.Depth = s.Depth + enc.RefundCounter = s.RefundCounter + enc.OpName = s.OpName() + enc.ErrorString = s.ErrorString() + structLogs = append(structLogs, enc) + } + return &debugTraceTransactionResult{ Failed: receipt.Status != uint64(iotextypes.ReceiptStatus_Success), + Revert: receipt.ExecutionRevertMsg(), ReturnValue: byteToHex(retval), - StructLogs: traces.StructLogs(), + StructLogs: structLogs, Gas: receipt.GasConsumed, }, nil } diff --git a/api/web3server_marshal.go b/api/web3server_marshal.go index 18044872d1..e3a899b9ea 100644 --- a/api/web3server_marshal.go +++ b/api/web3server_marshal.go @@ -4,8 +4,12 @@ import ( "encoding/hex" "encoding/json" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/tracers/logger" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/holiman/uint256" "github.com/iotexproject/go-pkgs/crypto" "github.com/iotexproject/go-pkgs/hash" "github.com/iotexproject/iotex-address/address" @@ -76,13 +80,27 @@ type ( CurrentBlock string `json:"currentBlock"` HighestBlock string `json:"highestBlock"` } - + StructLog struct { + Pc uint64 `json:"pc"` + Op vm.OpCode `json:"op"` + Gas math.HexOrDecimal64 `json:"gas"` + GasCost math.HexOrDecimal64 `json:"gasCost"` + Memory hexutil.Bytes `json:"memory"` + MemorySize int `json:"memSize"` + Stack []uint256.Int `json:"stack"` + ReturnData hexutil.Bytes `json:"returnData"` + Storage map[common.Hash]common.Hash `json:"storage"` + Depth int `json:"depth"` + RefundCounter uint64 `json:"refund"` + OpName string `json:"opName"` + ErrorString string `json:"error"` + } debugTraceTransactionResult struct { - Failed bool `json:"failed"` - Revert string `json:"revert"` - ReturnValue string `json:"returnValue"` - Gas uint64 `json:"gas"` - StructLogs []logger.StructLog `json:"structLogs"` + Failed bool `json:"failed"` + Revert string `json:"revert"` + ReturnValue string `json:"returnValue"` + Gas uint64 `json:"gas"` + StructLogs []StructLog `json:"structLogs"` } ) diff --git a/go.mod b/go.mod index 2eb7ac6e47..5253941dcd 100644 --- a/go.mod +++ b/go.mod @@ -54,6 +54,7 @@ require ( ) require ( + github.com/holiman/uint256 v1.2.0 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible github.com/shirou/gopsutil/v3 v3.22.2 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.34.0 @@ -94,7 +95,6 @@ require ( github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267 // indirect - github.com/holiman/uint256 v1.2.0 // indirect github.com/huin/goupnp v1.0.3 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/ipfs/go-cid v0.0.7 // indirect From ada78ffc5ae75f8ec833c7a6b28fb73b69d4e9ed Mon Sep 17 00:00:00 2001 From: millken Date: Wed, 18 Jan 2023 11:08:19 +0800 Subject: [PATCH 03/11] fix ci errors --- api/coreservice.go | 2 +- api/web3server.go | 4 ++-- api/web3server_marshal.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/coreservice.go b/api/coreservice.go index 9f256081e0..2f79dce7a0 100644 --- a/api/coreservice.go +++ b/api/coreservice.go @@ -1592,7 +1592,7 @@ func (core *coreService) SyncingProgress() (uint64, uint64, uint64) { func (core *coreService) TraceTransaction(ctx context.Context, actHash string, config *logger.Config) (retval []byte, receipt *action.Receipt, traces *logger.StructLogger, err error) { actInfo, err := core.Action(util.Remove0xPrefix(actHash), false) if err != nil { - return nil, nil, nil, err + return } act, err := (&action.Deserializer{}).SetEvmNetworkID(core.EVMNetworkID()).ActionToSealedEnvelope(actInfo.Action) if err != nil { diff --git a/api/web3server.go b/api/web3server.go index d6dfea93b9..edb1a47ebf 100644 --- a/api/web3server.go +++ b/api/web3server.go @@ -913,9 +913,9 @@ func (svr *web3Handler) traceTransaction(ctx context.Context, in *gjson.Result) return nil, err } - structLogs := make([]StructLog, 0) + structLogs := make([]structLog, 0) for _, s := range traces.StructLogs() { - var enc StructLog + var enc structLog enc.Pc = s.Pc enc.Op = s.Op enc.Gas = math.HexOrDecimal64(s.Gas) diff --git a/api/web3server_marshal.go b/api/web3server_marshal.go index e3a899b9ea..16dde0ecdd 100644 --- a/api/web3server_marshal.go +++ b/api/web3server_marshal.go @@ -80,7 +80,7 @@ type ( CurrentBlock string `json:"currentBlock"` HighestBlock string `json:"highestBlock"` } - StructLog struct { + structLog struct { Pc uint64 `json:"pc"` Op vm.OpCode `json:"op"` Gas math.HexOrDecimal64 `json:"gas"` @@ -100,7 +100,7 @@ type ( Revert string `json:"revert"` ReturnValue string `json:"returnValue"` Gas uint64 `json:"gas"` - StructLogs []StructLog `json:"structLogs"` + StructLogs []structLog `json:"structLogs"` } ) From 4c235994d8811d6f496d2cf07c4934dd9293d0a3 Mon Sep 17 00:00:00 2001 From: millken Date: Wed, 18 Jan 2023 17:40:56 +0800 Subject: [PATCH 04/11] fix insufficient funds --- api/coreservice.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/coreservice.go b/api/coreservice.go index 2f79dce7a0..fa39ae8465 100644 --- a/api/coreservice.go +++ b/api/coreservice.go @@ -1609,7 +1609,7 @@ func (core *coreService) TraceTransaction(ctx context.Context, actHash string, c Tracer: traces, NoBaseFee: true, }) - - retval, receipt, err = core.SimulateExecution(ctx, act.SenderAddress(), sc) + addr, _ := address.FromString(address.ZeroAddress) + retval, receipt, err = core.SimulateExecution(ctx, addr, sc) return } From ea83bdf3c506b890f255f638c8343ccceaaa2d85 Mon Sep 17 00:00:00 2001 From: millken Date: Thu, 19 Jan 2023 16:05:10 +0800 Subject: [PATCH 05/11] fix comments --- api/grpcserver.go | 33 ++++++++------------------------- api/web3server_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/api/grpcserver.go b/api/grpcserver.go index c7d821a5f6..c23a700fc2 100644 --- a/api/grpcserver.go +++ b/api/grpcserver.go @@ -15,13 +15,11 @@ import ( "strconv" "time" - "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/eth/tracers/logger" grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/iotexproject/go-pkgs/hash" - "github.com/iotexproject/go-pkgs/util" "github.com/iotexproject/iotex-address/address" "github.com/iotexproject/iotex-proto/golang/iotexapi" "github.com/iotexproject/iotex-proto/golang/iotextypes" @@ -39,7 +37,6 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" "github.com/iotexproject/iotex-core/action" - "github.com/iotexproject/iotex-core/action/protocol" "github.com/iotexproject/iotex-core/api/logfilter" apitypes "github.com/iotexproject/iotex-core/api/types" "github.com/iotexproject/iotex-core/blockchain/block" @@ -659,32 +656,18 @@ func (svr *gRPCHandler) ReadContractStorage(ctx context.Context, in *iotexapi.Re // TraceTransactionStructLogs get trace transaction struct logs func (svr *gRPCHandler) TraceTransactionStructLogs(ctx context.Context, in *iotexapi.TraceTransactionStructLogsRequest) (*iotexapi.TraceTransactionStructLogsResponse, error) { - actInfo, err := svr.coreService.Action(util.Remove0xPrefix(in.GetActionHash()), false) - if err != nil { - return nil, err + cfg := &logger.Config{ + EnableMemory: true, + DisableStack: false, + DisableStorage: false, + EnableReturnData: true, } - act, err := (&action.Deserializer{}).SetEvmNetworkID(svr.coreService.EVMNetworkID()).ActionToSealedEnvelope(actInfo.Action) + _, _, traces, err := svr.coreService.TraceTransaction(ctx, in.GetActionHash(), cfg) if err != nil { - return nil, err - } - sc, ok := act.Action().(*action.Execution) - if !ok { - return nil, status.Error(codes.InvalidArgument, "the type of action is not supported") - } - tracer := logger.NewStructLogger(nil) - ctx = protocol.WithVMConfigCtx(ctx, vm.Config{ - Debug: true, - Tracer: tracer, - NoBaseFee: true, - }) - - _, _, err = svr.coreService.SimulateExecution(ctx, act.SenderAddress(), sc) - if err != nil { - return nil, err + return nil, status.Error(codes.Internal, err.Error()) } - structLogs := make([]*iotextypes.TransactionStructLog, 0) - for _, log := range tracer.StructLogs() { + for _, log := range traces.StructLogs() { var stack []string for _, s := range log.Stack { stack = append(stack, s.String()) diff --git a/api/web3server_test.go b/api/web3server_test.go index aa2da27a68..9a8852983e 100644 --- a/api/web3server_test.go +++ b/api/web3server_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/hex" "fmt" "io" @@ -13,6 +14,7 @@ import ( "testing" "time" + "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/golang/mock/gomock" "github.com/pkg/errors" "github.com/stretchr/testify/require" @@ -29,6 +31,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/test/identityset" "github.com/iotexproject/iotex-core/test/mock/mock_apicoreservice" + "github.com/iotexproject/iotex-core/testutil" ) func TestGetWeb3Reqs(t *testing.T) { @@ -534,3 +537,34 @@ func TestGetNetworkID(t *testing.T) { func TestEthAccounts(t *testing.T) { } + +func TestTraceTransaction(t *testing.T) { + require := require.New(t) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + core := mock_apicoreservice.NewMockCoreService(ctrl) + web3svr := &web3Handler{core, nil} + + ctx := context.Background() + tsf, err := action.SignedExecution(identityset.Address(29).String(), + identityset.PrivateKey(29), 1, big.NewInt(0), testutil.TestGasLimit, + big.NewInt(testutil.TestGasPriceInt64), []byte{}) + require.NoError(err) + tsfhash, err := tsf.Hash() + require.NoError(err) + receipt := &action.Receipt{Status: 1, BlockHeight: 1, ActionHash: tsfhash, GasConsumed: 100000} + structLogger := &logger.StructLogger{} + + core.EXPECT().TraceTransaction(ctx, gomock.Any(), gomock.Any()).AnyTimes().Return([]byte{0x01}, receipt, structLogger, nil) + + in := gjson.Parse(`{"params":["` + hex.EncodeToString(tsfhash[:]) + `"]}`) + ret, err := web3svr.traceTransaction(ctx, &in) + require.NoError(err) + rlt, ok := ret.(*debugTraceTransactionResult) + require.True(ok) + require.Equal("0x01", rlt.ReturnValue) + require.False(rlt.Failed) + require.Equal(uint64(100000), rlt.Gas) + require.Empty(rlt.Revert) + require.Equal(0, len(rlt.StructLogs)) +} From df09bab0bb9155058e3734fc43cc89715647cde9 Mon Sep 17 00:00:00 2001 From: millken Date: Sun, 29 Jan 2023 12:11:16 +0800 Subject: [PATCH 06/11] update tests --- api/coreservice_test.go | 31 +++++++++++++++++++++++++++++++ api/web3server_test.go | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/api/coreservice_test.go b/api/coreservice_test.go index fc25535b62..61ded830e7 100644 --- a/api/coreservice_test.go +++ b/api/coreservice_test.go @@ -7,9 +7,12 @@ package api import ( "context" + "encoding/hex" + "math/big" "strconv" "testing" + "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/golang/mock/gomock" "github.com/iotexproject/iotex-proto/golang/iotexapi" "github.com/pkg/errors" @@ -21,6 +24,7 @@ import ( "github.com/iotexproject/iotex-core/api/logfilter" "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/test/identityset" "github.com/iotexproject/iotex-core/test/mock/mock_blockindex" "github.com/iotexproject/iotex-core/testutil" ) @@ -198,3 +202,30 @@ func TestEstimateGasForAction(t *testing.T) { _, err = svr.EstimateGasForAction(context.Background(), nil) require.Contains(err.Error(), action.ErrNilProto.Error()) } + +func TestTraceTransaction(t *testing.T) { + require := require.New(t) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + svr, _, _, _, cleanCallback := setupTestCoreSerivce() + defer cleanCallback() + ctx := context.Background() + tsf, err := action.SignedExecution(identityset.Address(29).String(), + identityset.PrivateKey(29), 1, big.NewInt(0), testutil.TestGasLimit, + big.NewInt(testutil.TestGasPriceInt64), []byte{}) + require.NoError(err) + tsfhash, err := tsf.Hash() + require.NoError(err) + cfg := &logger.Config{ + EnableMemory: true, + DisableStack: false, + DisableStorage: false, + EnableReturnData: true, + } + retval, receipt, traces, err := svr.TraceTransaction(ctx, hex.EncodeToString(tsfhash[:]), cfg) + require.Equal("0x", byteToHex(retval)) + require.Equal(1, receipt.Status) + require.Equal(uint64(100000), receipt.GasConsumed) + require.Empty(receipt.ExecutionRevertMsg()) + require.Equal(0, len(traces.StructLogs())) +} diff --git a/api/web3server_test.go b/api/web3server_test.go index 9a8852983e..e5ee1e61a3 100644 --- a/api/web3server_test.go +++ b/api/web3server_test.go @@ -538,7 +538,7 @@ func TestEthAccounts(t *testing.T) { } -func TestTraceTransaction(t *testing.T) { +func TestDebugTraceTransaction(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() From b4233b97acd43ba7bc63b0cc26bf59ef03b95d33 Mon Sep 17 00:00:00 2001 From: millken Date: Sun, 29 Jan 2023 13:54:00 +0800 Subject: [PATCH 07/11] fix tests --- api/coreservice_test.go | 14 ++++++++++---- api/web3server_test.go | 4 ++-- go.mod | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/api/coreservice_test.go b/api/coreservice_test.go index fdc0b962c3..c58be66702 100644 --- a/api/coreservice_test.go +++ b/api/coreservice_test.go @@ -203,12 +203,11 @@ func TestEstimateGasForAction(t *testing.T) { require.Contains(err.Error(), action.ErrNilProto.Error()) } - func TestTraceTransaction(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) defer ctrl.Finish() - svr, _, _, _, cleanCallback := setupTestCoreSerivce() + svr, bc, _, ap, cleanCallback := setupTestCoreSerivce() defer cleanCallback() ctx := context.Background() tsf, err := action.SignedExecution(identityset.Address(29).String(), @@ -216,7 +215,12 @@ func TestTraceTransaction(t *testing.T) { big.NewInt(testutil.TestGasPriceInt64), []byte{}) require.NoError(err) tsfhash, err := tsf.Hash() + + blk1Time := testutil.TimestampNow() + require.NoError(ap.Add(ctx, tsf)) + blk, err := bc.MintNewBlock(blk1Time) require.NoError(err) + require.NoError(bc.CommitBlock(blk)) cfg := &logger.Config{ EnableMemory: true, DisableStack: false, @@ -224,11 +228,13 @@ func TestTraceTransaction(t *testing.T) { EnableReturnData: true, } retval, receipt, traces, err := svr.TraceTransaction(ctx, hex.EncodeToString(tsfhash[:]), cfg) + require.NoError(err) require.Equal("0x", byteToHex(retval)) - require.Equal(1, receipt.Status) - require.Equal(uint64(100000), receipt.GasConsumed) + require.Equal(uint64(1), receipt.Status) + require.Equal(uint64(0x2710), receipt.GasConsumed) require.Empty(receipt.ExecutionRevertMsg()) require.Equal(0, len(traces.StructLogs())) +} func TestProofAndCompareReverseActions(t *testing.T) { sliceN := func(n uint64) (value []uint64) { diff --git a/api/web3server_test.go b/api/web3server_test.go index 5577cff6a1..c085900549 100644 --- a/api/web3server_test.go +++ b/api/web3server_test.go @@ -31,8 +31,8 @@ import ( "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/test/identityset" "github.com/iotexproject/iotex-core/test/mock/mock_apicoreservice" - "github.com/iotexproject/iotex-core/testutil" mock_apitypes "github.com/iotexproject/iotex-core/test/mock/mock_apiresponder" + "github.com/iotexproject/iotex-core/testutil" ) func TestGetWeb3Reqs(t *testing.T) { @@ -1006,4 +1006,4 @@ func TestDebugTraceTransaction(t *testing.T) { require.Equal(uint64(100000), rlt.Gas) require.Empty(rlt.Revert) require.Equal(0, len(rlt.StructLogs)) -} \ No newline at end of file +} diff --git a/go.mod b/go.mod index e6ba9cb775..0702a68e66 100644 --- a/go.mod +++ b/go.mod @@ -54,8 +54,8 @@ require ( ) require ( - github.com/holiman/uint256 v1.2.0 github.com/cespare/xxhash/v2 v2.1.2 + github.com/holiman/uint256 v1.2.0 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible github.com/shirou/gopsutil/v3 v3.22.2 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.34.0 From a41cedb34d55fb0b08e8a05c22351b21414dbe19 Mon Sep 17 00:00:00 2001 From: millken Date: Tue, 14 Feb 2023 10:46:53 +0800 Subject: [PATCH 08/11] fix tests --- api/grpcserver_test.go | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/api/grpcserver_test.go b/api/grpcserver_test.go index 74d54cace5..7887b058eb 100644 --- a/api/grpcserver_test.go +++ b/api/grpcserver_test.go @@ -11,6 +11,7 @@ import ( "math/big" "testing" + "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/golang/mock/gomock" "github.com/iotexproject/go-pkgs/hash" "github.com/iotexproject/iotex-proto/golang/iotexapi" @@ -1019,18 +1020,7 @@ func TestGrpcServer_TraceTransactionStructLogs(t *testing.T) { core := mock_apicoreservice.NewMockCoreService(ctrl) grpcSvr := newGRPCHandler(core) - addr1 := identityset.Address(28).String() - priKey1 := identityset.PrivateKey(29) - ex1, err := action.SignedExecution(addr1, priKey1, uint64(1), big.NewInt(10), uint64(100000), big.NewInt(0), []byte{}) - require.NoError(err) - act := &iotexapi.ActionInfo{ - Index: 0, - ActHash: "_test", - Action: ex1.Proto(), - } - core.EXPECT().Action(gomock.Any(), gomock.Any()).Return(act, nil) - core.EXPECT().EVMNetworkID().Return(uint32(11)) - core.EXPECT().SimulateExecution(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil, nil) + core.EXPECT().TraceTransaction(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil, logger.NewStructLogger(nil), nil) resp, err := grpcSvr.TraceTransactionStructLogs(context.Background(), &iotexapi.TraceTransactionStructLogsRequest{ ActionHash: "_actionHash", }) From d893f73871f9acc560b03695bf4e738fe86ad48b Mon Sep 17 00:00:00 2001 From: millken Date: Wed, 15 Feb 2023 16:40:25 +0800 Subject: [PATCH 09/11] fix comments --- api/coreservice.go | 2 +- api/web3server.go | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/api/coreservice.go b/api/coreservice.go index 168abf56c7..644d612962 100644 --- a/api/coreservice.go +++ b/api/coreservice.go @@ -1634,7 +1634,7 @@ func (core *coreService) TraceTransaction(ctx context.Context, actHash string, c } sc, ok := act.Action().(*action.Execution) if !ok { - err = status.Error(codes.InvalidArgument, "the type of action is not supported") + err = errors.New("the type of action is not supported") return } traces = logger.NewStructLogger(nil) diff --git a/api/web3server.go b/api/web3server.go index edb1a47ebf..55d91e5da3 100644 --- a/api/web3server.go +++ b/api/web3server.go @@ -889,10 +889,6 @@ func (svr *web3Handler) traceTransaction(ctx context.Context, in *gjson.Result) if !actHash.Exists() { return nil, errInvalidFormat } - hash := util.Remove0xPrefix(actHash.String()) - if len(hash) != 64 { - return nil, errInvalidFormat - } var ( enableMemory, disableStack, disableStorage, enableReturnData bool ) @@ -908,7 +904,7 @@ func (svr *web3Handler) traceTransaction(ctx context.Context, in *gjson.Result) DisableStorage: disableStorage, EnableReturnData: enableReturnData, } - retval, receipt, traces, err := svr.coreService.TraceTransaction(ctx, hash, cfg) + retval, receipt, traces, err := svr.coreService.TraceTransaction(ctx, actHash.String(), cfg) if err != nil { return nil, err } From e4a14547fc8d4b46abdb4b0cb62bbe2f0a34cafb Mon Sep 17 00:00:00 2001 From: millken Date: Wed, 15 Feb 2023 16:43:17 +0800 Subject: [PATCH 10/11] fix comments --- api/coreservice.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/coreservice.go b/api/coreservice.go index 644d612962..f18d8eb74f 100644 --- a/api/coreservice.go +++ b/api/coreservice.go @@ -1637,7 +1637,7 @@ func (core *coreService) TraceTransaction(ctx context.Context, actHash string, c err = errors.New("the type of action is not supported") return } - traces = logger.NewStructLogger(nil) + traces = logger.NewStructLogger(config) ctx = protocol.WithVMConfigCtx(ctx, vm.Config{ Debug: true, Tracer: traces, From d133278ca7ca9c7a252400143de984597d0cc675 Mon Sep 17 00:00:00 2001 From: millken Date: Wed, 15 Feb 2023 16:45:04 +0800 Subject: [PATCH 11/11] fix comments --- api/coreservice.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/api/coreservice.go b/api/coreservice.go index f18d8eb74f..c2093432cc 100644 --- a/api/coreservice.go +++ b/api/coreservice.go @@ -1623,27 +1623,26 @@ func (core *coreService) SyncingProgress() (uint64, uint64, uint64) { } // TraceTransaction returns the trace result of transaction -func (core *coreService) TraceTransaction(ctx context.Context, actHash string, config *logger.Config) (retval []byte, receipt *action.Receipt, traces *logger.StructLogger, err error) { +func (core *coreService) TraceTransaction(ctx context.Context, actHash string, config *logger.Config) ([]byte, *action.Receipt, *logger.StructLogger, error) { actInfo, err := core.Action(util.Remove0xPrefix(actHash), false) if err != nil { - return + return nil, nil, nil, err } act, err := (&action.Deserializer{}).SetEvmNetworkID(core.EVMNetworkID()).ActionToSealedEnvelope(actInfo.Action) if err != nil { - return + return nil, nil, nil, err } sc, ok := act.Action().(*action.Execution) if !ok { - err = errors.New("the type of action is not supported") - return + return nil, nil, nil, errors.New("the type of action is not supported") } - traces = logger.NewStructLogger(config) + traces := logger.NewStructLogger(config) ctx = protocol.WithVMConfigCtx(ctx, vm.Config{ Debug: true, Tracer: traces, NoBaseFee: true, }) addr, _ := address.FromString(address.ZeroAddress) - retval, receipt, err = core.SimulateExecution(ctx, addr, sc) - return + retval, receipt, err := core.SimulateExecution(ctx, addr, sc) + return retval, receipt, traces, err }