2020-01-13 09:27:34 +00:00
|
|
|
package result
|
2019-10-29 15:31:39 +00:00
|
|
|
|
|
|
|
import (
|
2020-07-31 12:26:28 +00:00
|
|
|
"encoding/json"
|
2020-09-22 09:03:19 +00:00
|
|
|
"errors"
|
2020-07-31 12:26:28 +00:00
|
|
|
|
2020-09-22 09:03:19 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
2020-11-26 11:17:21 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
2020-07-31 12:26:28 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
2019-10-29 15:31:39 +00:00
|
|
|
)
|
|
|
|
|
2020-01-13 09:27:34 +00:00
|
|
|
// Invoke represents code invocation result and is used by several RPC calls
|
2020-09-22 09:03:19 +00:00
|
|
|
// that invoke functions, scripts and generic bytecode. Transaction is
|
|
|
|
// represented in raw serialized format, use transaction.NewTransactionFromBytes
|
|
|
|
// or GetTransaction method to deserialize it.
|
2020-01-13 09:27:34 +00:00
|
|
|
type Invoke struct {
|
2020-10-05 13:33:20 +00:00
|
|
|
State string
|
|
|
|
GasConsumed int64
|
2020-10-14 13:46:06 +00:00
|
|
|
Script []byte
|
2020-10-05 13:33:20 +00:00
|
|
|
Stack []stackitem.Item
|
|
|
|
FaultException string
|
2020-09-22 09:03:19 +00:00
|
|
|
// Transaction represents transaction bytes. Use GetTransaction method to decode it.
|
|
|
|
Transaction []byte
|
2020-07-31 12:26:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type invokeAux struct {
|
2020-10-05 13:33:20 +00:00
|
|
|
State string `json:"state"`
|
2020-11-26 11:17:21 +00:00
|
|
|
GasConsumed util.Fixed8 `json:"gasconsumed,string"`
|
2020-10-14 13:46:06 +00:00
|
|
|
Script []byte `json:"script"`
|
2020-10-05 13:33:20 +00:00
|
|
|
Stack json.RawMessage `json:"stack"`
|
|
|
|
FaultException string `json:"exception,omitempty"`
|
2020-11-12 11:05:20 +00:00
|
|
|
Transaction []byte `json:"tx,omitempty"`
|
2020-07-31 12:26:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalJSON implements json.Marshaler.
|
|
|
|
func (r Invoke) MarshalJSON() ([]byte, error) {
|
|
|
|
var st json.RawMessage
|
|
|
|
arr := make([]json.RawMessage, len(r.Stack))
|
|
|
|
for i := range arr {
|
|
|
|
data, err := stackitem.ToJSONWithTypes(r.Stack[i])
|
|
|
|
if err != nil {
|
2020-09-07 10:33:05 +00:00
|
|
|
st = []byte(`"error: recursive reference"`)
|
2020-07-31 12:26:28 +00:00
|
|
|
break
|
|
|
|
}
|
|
|
|
arr[i] = data
|
|
|
|
}
|
|
|
|
|
|
|
|
var err error
|
|
|
|
if st == nil {
|
|
|
|
st, err = json.Marshal(arr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
2020-09-22 09:03:19 +00:00
|
|
|
|
2020-07-31 12:26:28 +00:00
|
|
|
return json.Marshal(&invokeAux{
|
2020-11-26 11:17:21 +00:00
|
|
|
GasConsumed: util.Fixed8(r.GasConsumed),
|
2020-10-05 13:33:20 +00:00
|
|
|
Script: r.Script,
|
|
|
|
State: r.State,
|
|
|
|
Stack: st,
|
|
|
|
FaultException: r.FaultException,
|
2020-11-12 11:05:20 +00:00
|
|
|
Transaction: r.Transaction,
|
2020-07-31 12:26:28 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalJSON implements json.Unmarshaler.
|
|
|
|
func (r *Invoke) UnmarshalJSON(data []byte) error {
|
|
|
|
aux := new(invokeAux)
|
|
|
|
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 {
|
|
|
|
r.Stack = st
|
|
|
|
}
|
|
|
|
}
|
2020-11-26 11:17:21 +00:00
|
|
|
r.GasConsumed = int64(aux.GasConsumed)
|
2020-07-31 12:26:28 +00:00
|
|
|
r.Script = aux.Script
|
|
|
|
r.State = aux.State
|
2020-10-05 13:33:20 +00:00
|
|
|
r.FaultException = aux.FaultException
|
2020-11-12 11:05:20 +00:00
|
|
|
r.Transaction = aux.Transaction
|
2020-07-31 12:26:28 +00:00
|
|
|
return nil
|
2019-10-29 15:31:39 +00:00
|
|
|
}
|
2020-09-22 09:03:19 +00:00
|
|
|
|
|
|
|
// GetTransaction returns decoded transaction from Invoke.Transaction bytes.
|
|
|
|
func (r *Invoke) GetTransaction(magic netmode.Magic) (*transaction.Transaction, error) {
|
|
|
|
if r.Transaction == nil {
|
|
|
|
return nil, errors.New("empty transaction")
|
|
|
|
}
|
|
|
|
return transaction.NewTransactionFromBytes(magic, r.Transaction)
|
|
|
|
}
|