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
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
"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
|
// NotificationEvent is a tuple of scripthash that emitted the Item as a
|
||||||
// notification and that item itself.
|
// notification and that item itself.
|
||||||
type NotificationEvent struct {
|
type NotificationEvent struct {
|
||||||
ScriptHash util.Uint160
|
ScriptHash util.Uint160 `json:"contract"`
|
||||||
Name string
|
Name string `json:"eventname"`
|
||||||
Item *stackitem.Array
|
Item *stackitem.Array `json:"state"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppExecResult represent the result of the script execution, gathering together
|
// 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)
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/internal/random"
|
"github.com/nspcc-dev/neo-go/pkg/internal/random"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/internal/testserdes"
|
"github.com/nspcc-dev/neo-go/pkg/internal/testserdes"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEncodeDecodeNotificationEvent(t *testing.T) {
|
func TestEncodeDecodeNotificationEvent(t *testing.T) {
|
||||||
|
@ -31,3 +33,92 @@ func TestEncodeDecodeAppExecResult(t *testing.T) {
|
||||||
|
|
||||||
testserdes.EncodeDecodeBinary(t, appExecResult, new(AppExecResult))
|
testserdes.EncodeDecodeBinary(t, appExecResult, new(AppExecResult))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMarshalUnmarshalJSONNotificationEvent(t *testing.T) {
|
||||||
|
t.Run("positive", func(t *testing.T) {
|
||||||
|
ne := &NotificationEvent{
|
||||||
|
ScriptHash: random.Uint160(),
|
||||||
|
Name: "my_ne",
|
||||||
|
Item: stackitem.NewArray([]stackitem.Item{
|
||||||
|
stackitem.NewBool(true),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
testserdes.MarshalUnmarshalJSON(t, ne, new(NotificationEvent))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("MarshalJSON recursive reference", func(t *testing.T) {
|
||||||
|
i := make([]stackitem.Item, 1)
|
||||||
|
recursive := stackitem.NewArray(i)
|
||||||
|
i[0] = recursive
|
||||||
|
ne := &NotificationEvent{
|
||||||
|
Item: recursive,
|
||||||
|
}
|
||||||
|
_, err := json.Marshal(ne)
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("UnmarshalJSON error", func(t *testing.T) {
|
||||||
|
errorCases := []string{
|
||||||
|
`{"contract":"0xBadHash","eventname":"my_ne","state":{"type":"Array","value":[{"type":"Boolean","value":true}]}}`,
|
||||||
|
`{"contract":"0xab2f820e2aa7cca1e081283c58a7d7943c33a2f1","eventname":"my_ne","state":{"type":"Array","value":[{"type":"BadType","value":true}]}}`,
|
||||||
|
`{"contract":"0xab2f820e2aa7cca1e081283c58a7d7943c33a2f1","eventname":"my_ne","state":{"type":"Boolean", "value":true}}`,
|
||||||
|
}
|
||||||
|
for _, errCase := range errorCases {
|
||||||
|
err := json.Unmarshal([]byte(errCase), new(NotificationEvent))
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMarshalUnmarshalJSONAppExecResult(t *testing.T) {
|
||||||
|
t.Run("positive", func(t *testing.T) {
|
||||||
|
appExecResult := &AppExecResult{
|
||||||
|
TxHash: random.Uint256(),
|
||||||
|
Trigger: 1,
|
||||||
|
VMState: vm.HaltState,
|
||||||
|
GasConsumed: 10,
|
||||||
|
Stack: []stackitem.Item{},
|
||||||
|
Events: []NotificationEvent{},
|
||||||
|
}
|
||||||
|
testserdes.MarshalUnmarshalJSON(t, appExecResult, new(AppExecResult))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("MarshalJSON recursive reference", func(t *testing.T) {
|
||||||
|
i := make([]stackitem.Item, 1)
|
||||||
|
recursive := stackitem.NewArray(i)
|
||||||
|
i[0] = recursive
|
||||||
|
errorCases := []*AppExecResult{
|
||||||
|
{
|
||||||
|
Stack: i,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, errCase := range errorCases {
|
||||||
|
_, err := json.Marshal(errCase)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("UnmarshalJSON error", func(t *testing.T) {
|
||||||
|
nilStackCases := []string{
|
||||||
|
`{"txid":"0x17145a039fca704fcdbeb46e6b210af98a1a9e5b9768e46ffc38f71c79ac2521","trigger":"Application","vmstate":"HALT","gasconsumed":"1","stack":[{"type":"WrongType","value":"1"}],"notifications":[]}`,
|
||||||
|
}
|
||||||
|
for _, str := range nilStackCases {
|
||||||
|
actual := new(AppExecResult)
|
||||||
|
err := json.Unmarshal([]byte(str), actual)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Nil(t, actual.Stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
errorCases := []string{
|
||||||
|
`{"txid":"0xBadHash","trigger":"Application","vmstate":"HALT","gasconsumed":"1","stack":[{"type":"Integer","value":"1"}],"notifications":[]}`,
|
||||||
|
`{"txid":"0x17145a039fca704fcdbeb46e6b210af98a1a9e5b9768e46ffc38f71c79ac2521","trigger":"Application","vmstate":"BadState","gasconsumed":"1","stack":[{"type":"Integer","value":"1"}],"notifications":[]}`,
|
||||||
|
`{"txid":"0x17145a039fca704fcdbeb46e6b210af98a1a9e5b9768e46ffc38f71c79ac2521","trigger":"BadTrigger","vmstate":"HALT","gasconsumed":"1","stack":[{"type":"Integer","value":"1"}],"notifications":[]}`,
|
||||||
|
}
|
||||||
|
for _, str := range errorCases {
|
||||||
|
actual := new(AppExecResult)
|
||||||
|
err := json.Unmarshal([]byte(str), actual)
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -19,10 +19,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetApplicationLog returns the contract log based on the specified txid.
|
// 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) (*state.AppExecResult, error) {
|
||||||
var (
|
var (
|
||||||
params = request.NewRawParams(hash.StringLE())
|
params = request.NewRawParams(hash.StringLE())
|
||||||
resp = &result.ApplicationLog{}
|
resp = new(state.AppExecResult)
|
||||||
)
|
)
|
||||||
if err := c.performRequest("getapplicationlog", params, resp); err != nil {
|
if err := c.performRequest("getapplicationlog", params, resp); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -25,7 +25,9 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
"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"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
"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/util"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -113,13 +115,13 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return &result.ApplicationLog{
|
return &state.AppExecResult{
|
||||||
TxHash: txHash,
|
TxHash: txHash,
|
||||||
Trigger: "Application",
|
Trigger: trigger.Application,
|
||||||
VMState: "HALT",
|
VMState: vm.HaltState,
|
||||||
GasConsumed: 1,
|
GasConsumed: 1,
|
||||||
Stack: []stackitem.Item{stackitem.NewBigInteger(big.NewInt(1))},
|
Stack: []stackitem.Item{stackitem.NewBigInteger(big.NewInt(1))},
|
||||||
Events: []result.NotificationEvent{},
|
Events: []state.NotificationEvent{},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -8,10 +8,10 @@ import (
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -141,9 +141,9 @@ readloop:
|
||||||
case response.TransactionEventID:
|
case response.TransactionEventID:
|
||||||
val = &transaction.Transaction{Network: c.opts.Network}
|
val = &transaction.Transaction{Network: c.opts.Network}
|
||||||
case response.NotificationEventID:
|
case response.NotificationEventID:
|
||||||
val = new(result.NotificationEvent)
|
val = new(state.NotificationEvent)
|
||||||
case response.ExecutionEventID:
|
case response.ExecutionEventID:
|
||||||
val = new(result.ApplicationLog)
|
val = new(state.AppExecResult)
|
||||||
case response.MissedEventID:
|
case response.MissedEventID:
|
||||||
// No value.
|
// No value.
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1,109 +0,0 @@
|
||||||
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"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 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
|
|
||||||
Trigger string
|
|
||||||
VMState string
|
|
||||||
GasConsumed int64
|
|
||||||
Stack []stackitem.Item
|
|
||||||
Events []NotificationEvent
|
|
||||||
}
|
|
||||||
|
|
||||||
//NotificationEvent response wrapper
|
|
||||||
type NotificationEvent struct {
|
|
||||||
Contract util.Uint160 `json:"contract"`
|
|
||||||
Name string `json:"eventname"`
|
|
||||||
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 {
|
|
||||||
seen := make(map[stackitem.Item]bool)
|
|
||||||
item := smartcontract.ParameterFromStackItem(event.Item, seen)
|
|
||||||
return NotificationEvent{
|
|
||||||
Contract: event.ScriptHash,
|
|
||||||
Name: event.Name,
|
|
||||||
Item: item,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewApplicationLog creates a new ApplicationLog wrapper.
|
|
||||||
func NewApplicationLog(appExecRes *state.AppExecResult) ApplicationLog {
|
|
||||||
events := make([]NotificationEvent, 0, len(appExecRes.Events))
|
|
||||||
for _, e := range appExecRes.Events {
|
|
||||||
events = append(events, StateEventToResultNotification(e))
|
|
||||||
}
|
|
||||||
return ApplicationLog{
|
|
||||||
TxHash: appExecRes.TxHash,
|
|
||||||
Trigger: appExecRes.Trigger.String(),
|
|
||||||
VMState: appExecRes.VMState.String(),
|
|
||||||
GasConsumed: appExecRes.GasConsumed,
|
|
||||||
Stack: appExecRes.Stack,
|
|
||||||
Events: events,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -498,7 +498,7 @@ func (s *Server) getApplicationLog(reqParams request.Params) (interface{}, *resp
|
||||||
return nil, response.NewRPCError("Unknown transaction", "", err)
|
return nil, response.NewRPCError("Unknown transaction", "", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.NewApplicationLog(appExecResult), nil
|
return appExecResult, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) getNEP5Balances(ps request.Params) (interface{}, *response.Error) {
|
func (s *Server) getNEP5Balances(ps request.Params) (interface{}, *response.Error) {
|
||||||
|
@ -1159,10 +1159,10 @@ chloop:
|
||||||
resp.Payload[0] = b
|
resp.Payload[0] = b
|
||||||
case execution := <-s.executionCh:
|
case execution := <-s.executionCh:
|
||||||
resp.Event = response.ExecutionEventID
|
resp.Event = response.ExecutionEventID
|
||||||
resp.Payload[0] = result.NewApplicationLog(execution)
|
resp.Payload[0] = execution
|
||||||
case notification := <-s.notificationCh:
|
case notification := <-s.notificationCh:
|
||||||
resp.Event = response.NotificationEventID
|
resp.Event = response.NotificationEventID
|
||||||
resp.Payload[0] = result.StateEventToResultNotification(*notification)
|
resp.Payload[0] = *notification
|
||||||
case tx := <-s.transactionCh:
|
case tx := <-s.transactionCh:
|
||||||
resp.Event = response.TransactionEventID
|
resp.Event = response.TransactionEventID
|
||||||
resp.Payload[0] = tx
|
resp.Payload[0] = tx
|
||||||
|
|
|
@ -26,7 +26,9 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -62,15 +64,15 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
params: `["` + deploymentTxHash + `"]`,
|
params: `["` + deploymentTxHash + `"]`,
|
||||||
result: func(e *executor) interface{} { return &result.ApplicationLog{} },
|
result: func(e *executor) interface{} { return &state.AppExecResult{} },
|
||||||
check: func(t *testing.T, e *executor, acc interface{}) {
|
check: func(t *testing.T, e *executor, acc interface{}) {
|
||||||
res, ok := acc.(*result.ApplicationLog)
|
res, ok := acc.(*state.AppExecResult)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
expectedTxHash, err := util.Uint256DecodeStringLE(deploymentTxHash)
|
expectedTxHash, err := util.Uint256DecodeStringLE(deploymentTxHash)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, expectedTxHash, res.TxHash)
|
assert.Equal(t, expectedTxHash, res.TxHash)
|
||||||
assert.Equal(t, "Application", res.Trigger)
|
assert.Equal(t, trigger.Application, res.Trigger)
|
||||||
assert.Equal(t, "HALT", res.VMState)
|
assert.Equal(t, vm.HaltState, res.VMState)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -722,10 +724,10 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) []
|
||||||
rpc := `{"jsonrpc": "2.0", "id": 1, "method": "getapplicationlog", "params": ["%s"]}`
|
rpc := `{"jsonrpc": "2.0", "id": 1, "method": "getapplicationlog", "params": ["%s"]}`
|
||||||
body := doRPCCall(fmt.Sprintf(rpc, e.chain.GetHeaderHash(1).StringLE()), httpSrv.URL, t)
|
body := doRPCCall(fmt.Sprintf(rpc, e.chain.GetHeaderHash(1).StringLE()), httpSrv.URL, t)
|
||||||
data := checkErrGetResult(t, body, false)
|
data := checkErrGetResult(t, body, false)
|
||||||
var res result.ApplicationLog
|
var res state.AppExecResult
|
||||||
require.NoError(t, json.Unmarshal(data, &res))
|
require.NoError(t, json.Unmarshal(data, &res))
|
||||||
require.Equal(t, "System", res.Trigger)
|
require.Equal(t, trigger.System, res.Trigger)
|
||||||
require.Equal(t, "HALT", res.VMState)
|
require.Equal(t, vm.HaltState, res.VMState)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("submit", func(t *testing.T) {
|
t.Run("submit", func(t *testing.T) {
|
||||||
|
|
|
@ -3,10 +3,10 @@ package server
|
||||||
import (
|
import (
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
|
||||||
"go.uber.org/atomic"
|
"go.uber.org/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -72,14 +72,14 @@ func (f *feed) Matches(r *response.Notification) bool {
|
||||||
return senderOK && signerOK
|
return senderOK && signerOK
|
||||||
case response.NotificationEventID:
|
case response.NotificationEventID:
|
||||||
filt := f.filter.(request.NotificationFilter)
|
filt := f.filter.(request.NotificationFilter)
|
||||||
notification := r.Payload[0].(result.NotificationEvent)
|
notification := r.Payload[0].(state.NotificationEvent)
|
||||||
hashOk := filt.Contract == nil || notification.Contract.Equals(*filt.Contract)
|
hashOk := filt.Contract == nil || notification.ScriptHash.Equals(*filt.Contract)
|
||||||
nameOk := filt.Name == nil || notification.Name == *filt.Name
|
nameOk := filt.Name == nil || notification.Name == *filt.Name
|
||||||
return hashOk && nameOk
|
return hashOk && nameOk
|
||||||
case response.ExecutionEventID:
|
case response.ExecutionEventID:
|
||||||
filt := f.filter.(request.ExecutionFilter)
|
filt := f.filter.(request.ExecutionFilter)
|
||||||
applog := r.Payload[0].(result.ApplicationLog)
|
applog := r.Payload[0].(*state.AppExecResult)
|
||||||
return applog.VMState == filt.State
|
return applog.VMState.String() == filt.State
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package trigger
|
package trigger
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
//go:generate stringer -type=Type -output=trigger_type_string.go
|
//go:generate stringer -type=Type -output=trigger_type_string.go
|
||||||
|
|
||||||
// Type represents trigger type used in C# reference node: https://github.com/neo-project/neo/blob/c64748ecbac3baeb8045b16af0d518398a6ced24/neo/SmartContract/TriggerType.cs#L3
|
// Type represents trigger type used in C# reference node: https://github.com/neo-project/neo/blob/c64748ecbac3baeb8045b16af0d518398a6ced24/neo/SmartContract/TriggerType.cs#L3
|
||||||
|
@ -27,3 +29,14 @@ const (
|
||||||
// All represents any trigger type.
|
// All represents any trigger type.
|
||||||
All Type = System | Verification | Application
|
All Type = System | Verification | Application
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FromString converts string to trigger Type
|
||||||
|
func FromString(str string) (Type, error) {
|
||||||
|
triggers := []Type{System, Verification, Application, All}
|
||||||
|
for _, t := range triggers {
|
||||||
|
if t.String() == str {
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, fmt.Errorf("unknown trigger type: %s", str)
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestStringer(t *testing.T) {
|
func TestStringer(t *testing.T) {
|
||||||
|
@ -38,3 +39,25 @@ func TestDecodeBynary(t *testing.T) {
|
||||||
assert.Equal(t, o, Type(b))
|
assert.Equal(t, o, Type(b))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFromString(t *testing.T) {
|
||||||
|
testCases := map[string]Type{
|
||||||
|
"System": System,
|
||||||
|
"Application": Application,
|
||||||
|
"Verification": Verification,
|
||||||
|
"All": All,
|
||||||
|
}
|
||||||
|
for str, expected := range testCases {
|
||||||
|
actual, err := FromString(str)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, expected, actual)
|
||||||
|
}
|
||||||
|
errorCases := []string{
|
||||||
|
"",
|
||||||
|
"Unknown",
|
||||||
|
}
|
||||||
|
for _, str := range errorCases {
|
||||||
|
_, err := FromString(str)
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue