diff --git a/pkg/rpc/client/rpc.go b/pkg/rpc/client/rpc.go index a91e21d08..54f483495 100644 --- a/pkg/rpc/client/rpc.go +++ b/pkg/rpc/client/rpc.go @@ -18,6 +18,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/rpc/response/result" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/wallet" ) @@ -25,11 +26,14 @@ import ( var errNetworkNotInitialized = errors.New("RPC client network is not initialized") // GetApplicationLog returns the contract log based on the specified txid. -func (c *Client) GetApplicationLog(hash util.Uint256) (*result.ApplicationLog, error) { +func (c *Client) GetApplicationLog(hash util.Uint256, trig *trigger.Type) (*result.ApplicationLog, error) { var ( params = request.NewRawParams(hash.StringLE()) resp = new(result.ApplicationLog) ) + if trig != nil { + params.Values = append(params.Values, trig.String()) + } if err := c.performRequest("getapplicationlog", params, resp); err != nil { return nil, err } diff --git a/pkg/rpc/client/rpc_test.go b/pkg/rpc/client/rpc_test.go index 5de689e28..54b31f050 100644 --- a/pkg/rpc/client/rpc_test.go +++ b/pkg/rpc/client/rpc_test.go @@ -108,7 +108,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ { name: "positive", invoke: func(c *Client) (interface{}, error) { - return c.GetApplicationLog(util.Uint256{}) + return c.GetApplicationLog(util.Uint256{}, nil) }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"txid":"0x17145a039fca704fcdbeb46e6b210af98a1a9e5b9768e46ffc38f71c79ac2521","executions":[{"trigger":"Application","vmstate":"HALT","gasconsumed":"1","stack":[{"type":"Integer","value":"1"}],"notifications":[]}]}}`, result: func(c *Client) interface{} { @@ -973,7 +973,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ { name: "getapplicationlog_invalid_params_error", invoke: func(c *Client) (interface{}, error) { - return c.GetApplicationLog(util.Uint256{}) + return c.GetApplicationLog(util.Uint256{}, nil) }, }, { @@ -1148,7 +1148,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ { name: "getapplicationlog_unmarshalling_error", invoke: func(c *Client) (interface{}, error) { - return c.GetApplicationLog(util.Uint256{}) + return c.GetApplicationLog(util.Uint256{}, nil) }, }, { diff --git a/pkg/rpc/response/result/application_log.go b/pkg/rpc/response/result/application_log.go index b318dd7aa..98920e720 100644 --- a/pkg/rpc/response/result/application_log.go +++ b/pkg/rpc/response/result/application_log.go @@ -12,8 +12,9 @@ import ( // ApplicationLog represent the results of the script executions for block or transaction. type ApplicationLog struct { - Container util.Uint256 - Executions []state.Execution + Container util.Uint256 + IsTransaction bool + Executions []state.Execution } // applicationLogAux is an auxiliary struct for ApplicationLog JSON marshalling. @@ -28,7 +29,7 @@ func (l ApplicationLog) MarshalJSON() ([]byte, error) { result := &applicationLogAux{ Executions: make([]json.RawMessage, len(l.Executions)), } - if l.Executions[0].Trigger == trigger.Application { + if l.IsTransaction { result.TxHash = &l.Container } else { result.BlockHash = &l.Container @@ -67,13 +68,17 @@ func (l *ApplicationLog) UnmarshalJSON(data []byte) error { return nil } -// NewApplicationLog creates ApplicationLog from a set of several application execution results. -func NewApplicationLog(hash util.Uint256, aers []state.AppExecResult) ApplicationLog { +// NewApplicationLog creates ApplicationLog from a set of several application execution results +// including only the results with the specified trigger. +func NewApplicationLog(hash util.Uint256, aers []state.AppExecResult, trig trigger.Type) ApplicationLog { result := ApplicationLog{ - Container: hash, + Container: hash, + IsTransaction: aers[0].Trigger == trigger.Application, } for _, aer := range aers { - result.Executions = append(result.Executions, aer.Execution) + if aer.Trigger&trig != 0 { + result.Executions = append(result.Executions, aer.Execution) + } } return result } diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go index 59bd5b16d..ce5937069 100644 --- a/pkg/rpc/server/server.go +++ b/pkg/rpc/server/server.go @@ -527,11 +527,19 @@ func (s *Server) getApplicationLog(reqParams request.Params) (interface{}, *resp return nil, response.ErrInvalidParams } + trig := trigger.All + if len(reqParams) > 1 { + trig, err = trigger.FromString(reqParams.ValueWithType(1, request.StringT).String()) + if err != nil { + return nil, response.ErrInvalidParams + } + } + appExecResults, err := s.chain.GetAppExecResults(hash, trigger.All) if err != nil { return nil, response.NewRPCError("Unknown transaction or block", "", err) } - return result.NewApplicationLog(hash, appExecResults), nil + return result.NewApplicationLog(hash, appExecResults, trig), nil } func (s *Server) getNEP5Balances(ps request.Params) (interface{}, *response.Error) { diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index 35882c4bd..5694c9121 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -58,6 +58,7 @@ type rpcTestCase struct { const testContractHash = "b0fda4dd46b8e5d207e86e774a4a133c6db69ee7" const deploymentTxHash = "59f7b22b90e26f883a56b916c1580e3ee4f13caded686353cd77577e6194c173" +const genesisBlockHash = "a496577895eb8c227bb866dc44f99f21c0cf06417ca8f2a877cc5d761a50dac0" const verifyContractHash = "c1213693b22cb0454a436d6e0bd76b8c0a3bfdf7" const verifyContractAVM = "570300412d51083021700c14aa8acf859d4fe402b34e673f2156821796a488ebdb30716813cedb2869db289740" @@ -80,6 +81,43 @@ var rpcTestCases = map[string][]rpcTestCase{ assert.Equal(t, vm.HaltState, res.Executions[0].VMState) }, }, + { + name: "positive, genesis block", + params: `["` + genesisBlockHash + `"]`, + result: func(e *executor) interface{} { return &result.ApplicationLog{} }, + check: func(t *testing.T, e *executor, acc interface{}) { + res, ok := acc.(*result.ApplicationLog) + require.True(t, ok) + assert.Equal(t, genesisBlockHash, res.Container.StringLE()) + assert.Equal(t, 1, len(res.Executions)) + assert.Equal(t, trigger.PostPersist, res.Executions[0].Trigger) // no onPersist for genesis block + assert.Equal(t, vm.HaltState, res.Executions[0].VMState) + }, + }, + { + name: "positive, genesis block, postPersist", + params: `["` + genesisBlockHash + `", "PostPersist"]`, + result: func(e *executor) interface{} { return &result.ApplicationLog{} }, + check: func(t *testing.T, e *executor, acc interface{}) { + res, ok := acc.(*result.ApplicationLog) + require.True(t, ok) + assert.Equal(t, genesisBlockHash, res.Container.StringLE()) + assert.Equal(t, 1, len(res.Executions)) + assert.Equal(t, trigger.PostPersist, res.Executions[0].Trigger) // no onPersist for genesis block + assert.Equal(t, vm.HaltState, res.Executions[0].VMState) + }, + }, + { + name: "positive, genesis block, onPersist", + params: `["` + genesisBlockHash + `", "OnPersist"]`, + result: func(e *executor) interface{} { return &result.ApplicationLog{} }, + check: func(t *testing.T, e *executor, acc interface{}) { + res, ok := acc.(*result.ApplicationLog) + require.True(t, ok) + assert.Equal(t, genesisBlockHash, res.Container.StringLE()) + assert.Equal(t, 0, len(res.Executions)) // no onPersist for genesis block + }, + }, { name: "no params", params: `[]`,