From 0834661cac07bb83a197dddaa77004d21225d3a9 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 13 Aug 2020 13:16:48 +0300 Subject: [PATCH] rpc: marshal `getapplicationlog` stack as []stackitem.Item Following https://github.com/neo-project/neo-modules/issues/318 --- pkg/rpc/client/rpc_test.go | 4 +- pkg/rpc/response/result/application_log.go | 74 ++++++++++++++++++---- 2 files changed, 64 insertions(+), 14 deletions(-) diff --git a/pkg/rpc/client/rpc_test.go b/pkg/rpc/client/rpc_test.go index ca1265277..da1667e2d 100644 --- a/pkg/rpc/client/rpc_test.go +++ b/pkg/rpc/client/rpc_test.go @@ -107,7 +107,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ invoke: func(c *Client) (interface{}, error) { return c.GetApplicationLog(util.Uint256{}) }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"txid":"0x17145a039fca704fcdbeb46e6b210af98a1a9e5b9768e46ffc38f71c79ac2521","trigger":"Application","vmstate":"HALT","gasconsumed":"1","stack":[{"type":"Integer","value":1}],"notifications":[]}}`, + serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"txid":"0x17145a039fca704fcdbeb46e6b210af98a1a9e5b9768e46ffc38f71c79ac2521","trigger":"Application","vmstate":"HALT","gasconsumed":"1","stack":[{"type":"Integer","value":"1"}],"notifications":[]}}`, result: func(c *Client) interface{} { txHash, err := util.Uint256DecodeStringLE("17145a039fca704fcdbeb46e6b210af98a1a9e5b9768e46ffc38f71c79ac2521") if err != nil { @@ -118,7 +118,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ Trigger: "Application", VMState: "HALT", GasConsumed: 1, - Stack: []smartcontract.Parameter{{Type: smartcontract.IntegerType, Value: int64(1)}}, + Stack: []stackitem.Item{stackitem.NewBigInteger(big.NewInt(1))}, Events: []result.NotificationEvent{}, } }, diff --git a/pkg/rpc/response/result/application_log.go b/pkg/rpc/response/result/application_log.go index 9ecae405f..455f1d431 100644 --- a/pkg/rpc/response/result/application_log.go +++ b/pkg/rpc/response/result/application_log.go @@ -1,6 +1,8 @@ package result import ( + "encoding/json" + "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/util" @@ -10,12 +12,12 @@ import ( // ApplicationLog wrapper used for the representation of the // state.AppExecResult based on the specific tx on the RPC Server. type ApplicationLog struct { - TxHash util.Uint256 `json:"txid"` - Trigger string `json:"trigger"` - VMState string `json:"vmstate"` - GasConsumed int64 `json:"gasconsumed,string"` - Stack []smartcontract.Parameter `json:"stack"` - Events []NotificationEvent `json:"notifications"` + TxHash util.Uint256 + Trigger string + VMState string + GasConsumed int64 + Stack []stackitem.Item + Events []NotificationEvent } //NotificationEvent response wrapper @@ -25,6 +27,59 @@ type NotificationEvent struct { Item smartcontract.Parameter `json:"state"` } +type applicationLogAux struct { + TxHash util.Uint256 `json:"txid"` + Trigger string `json:"trigger"` + VMState string `json:"vmstate"` + GasConsumed int64 `json:"gasconsumed,string"` + Stack []json.RawMessage `json:"stack"` + Events []NotificationEvent `json:"notifications"` +} + +// MarshalJSON implements json.Marshaler. +func (l ApplicationLog) MarshalJSON() ([]byte, error) { + arr := make([]json.RawMessage, len(l.Stack)) + for i := range arr { + data, err := stackitem.ToJSONWithTypes(l.Stack[i]) + if err != nil { + return nil, err + } + arr[i] = data + } + return json.Marshal(&applicationLogAux{ + TxHash: l.TxHash, + Trigger: l.Trigger, + VMState: l.VMState, + GasConsumed: l.GasConsumed, + Stack: arr, + Events: l.Events, + }) +} + +// UnmarshalJSON implements json.Unmarshaler. +func (l *ApplicationLog) UnmarshalJSON(data []byte) error { + aux := new(applicationLogAux) + if err := json.Unmarshal(data, aux); err != nil { + return err + } + st := make([]stackitem.Item, len(aux.Stack)) + var err error + for i := range st { + st[i], err = stackitem.FromJSONWithTypes(aux.Stack[i]) + if err != nil { + return err + } + } + l.Stack = st + l.Trigger = aux.Trigger + l.TxHash = aux.TxHash + l.VMState = aux.VMState + l.Events = aux.Events + l.GasConsumed = aux.GasConsumed + + return nil +} + // StateEventToResultNotification converts state.NotificationEvent to // result.NotificationEvent. func StateEventToResultNotification(event state.NotificationEvent) NotificationEvent { @@ -43,17 +98,12 @@ func NewApplicationLog(appExecRes *state.AppExecResult) ApplicationLog { for _, e := range appExecRes.Events { events = append(events, StateEventToResultNotification(e)) } - st := make([]smartcontract.Parameter, len(appExecRes.Stack)) - seen := make(map[stackitem.Item]bool) - for i := range appExecRes.Stack { - st[i] = smartcontract.ParameterFromStackItem(appExecRes.Stack[i], seen) - } return ApplicationLog{ TxHash: appExecRes.TxHash, Trigger: appExecRes.Trigger.String(), VMState: appExecRes.VMState.String(), GasConsumed: appExecRes.GasConsumed, - Stack: st, + Stack: appExecRes.Stack, Events: events, } }