rpc: use state.AppExecResult for ApplicationLog marshalling
Closes #1371
This commit is contained in:
parent
34df5d5949
commit
acacac1b24
11 changed files with 276 additions and 136 deletions
|
@ -1,7 +1,9 @@
|
|||
package state
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||
|
@ -13,9 +15,9 @@ import (
|
|||
// NotificationEvent is a tuple of scripthash that emitted the Item as a
|
||||
// notification and that item itself.
|
||||
type NotificationEvent struct {
|
||||
ScriptHash util.Uint160
|
||||
Name string
|
||||
Item *stackitem.Array
|
||||
ScriptHash util.Uint160 `json:"contract"`
|
||||
Name string `json:"eventname"`
|
||||
Item *stackitem.Array `json:"state"`
|
||||
}
|
||||
|
||||
// AppExecResult represent the result of the script execution, gathering together
|
||||
|
@ -79,3 +81,119 @@ func (aer *AppExecResult) DecodeBinary(r *io.BinReader) {
|
|||
}
|
||||
r.ReadArray(&aer.Events)
|
||||
}
|
||||
|
||||
// notificationEventAux is an auxiliary struct for NotificationEvent JSON marshalling.
|
||||
type notificationEventAux struct {
|
||||
ScriptHash util.Uint160 `json:"contract"`
|
||||
Name string `json:"eventname"`
|
||||
Item json.RawMessage `json:"state"`
|
||||
}
|
||||
|
||||
// MarshalJSON implements implements json.Marshaler interface.
|
||||
func (ne *NotificationEvent) MarshalJSON() ([]byte, error) {
|
||||
item, err := stackitem.ToJSONWithTypes(ne.Item)
|
||||
if err != nil {
|
||||
item = []byte(`"error: recursive reference"`)
|
||||
}
|
||||
return json.Marshal(¬ificationEventAux{
|
||||
ScriptHash: ne.ScriptHash,
|
||||
Name: ne.Name,
|
||||
Item: item,
|
||||
})
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler interface.
|
||||
func (ne *NotificationEvent) UnmarshalJSON(data []byte) error {
|
||||
aux := new(notificationEventAux)
|
||||
if err := json.Unmarshal(data, aux); err != nil {
|
||||
return err
|
||||
}
|
||||
item, err := stackitem.FromJSONWithTypes(aux.Item)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if t := item.Type(); t != stackitem.ArrayT {
|
||||
return fmt.Errorf("failed to convert notification event state of type %s to array", t.String())
|
||||
}
|
||||
ne.Item = item.(*stackitem.Array)
|
||||
ne.Name = aux.Name
|
||||
ne.ScriptHash = aux.ScriptHash
|
||||
return nil
|
||||
}
|
||||
|
||||
// appExecResultAux is an auxiliary struct for JSON marshalling
|
||||
type appExecResultAux 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 implements json.Marshaler interface.
|
||||
func (aer *AppExecResult) MarshalJSON() ([]byte, error) {
|
||||
var st json.RawMessage
|
||||
arr := make([]json.RawMessage, len(aer.Stack))
|
||||
for i := range arr {
|
||||
data, err := stackitem.ToJSONWithTypes(aer.Stack[i])
|
||||
if err != nil {
|
||||
st = []byte(`"error: recursive reference"`)
|
||||
break
|
||||
}
|
||||
arr[i] = data
|
||||
}
|
||||
|
||||
var err error
|
||||
if st == nil {
|
||||
st, err = json.Marshal(arr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return json.Marshal(&appExecResultAux{
|
||||
TxHash: aer.TxHash,
|
||||
Trigger: aer.Trigger.String(),
|
||||
VMState: aer.VMState.String(),
|
||||
GasConsumed: aer.GasConsumed,
|
||||
Stack: st,
|
||||
Events: aer.Events,
|
||||
})
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements implements json.Unmarshaler interface.
|
||||
func (aer *AppExecResult) UnmarshalJSON(data []byte) error {
|
||||
aux := new(appExecResultAux)
|
||||
if err := json.Unmarshal(data, aux); err != nil {
|
||||
return err
|
||||
}
|
||||
var arr []json.RawMessage
|
||||
if err := json.Unmarshal(aux.Stack, &arr); err == nil {
|
||||
st := make([]stackitem.Item, len(arr))
|
||||
for i := range arr {
|
||||
st[i], err = stackitem.FromJSONWithTypes(arr[i])
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
aer.Stack = st
|
||||
}
|
||||
}
|
||||
|
||||
trigger, err := trigger.FromString(aux.Trigger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
aer.Trigger = trigger
|
||||
aer.TxHash = aux.TxHash
|
||||
state, err := vm.StateFromString(aux.VMState)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
aer.VMState = state
|
||||
aer.Events = aux.Events
|
||||
aer.GasConsumed = aux.GasConsumed
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue