Merge pull request #705 from nspcc-dev/rpc-drop-dup-invoke-types
Drop duplicating Invoke* types and vm.stackItem
This commit is contained in:
commit
f9a1535c75
14 changed files with 74 additions and 112 deletions
|
@ -16,7 +16,7 @@ import (
|
||||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||||
"github.com/CityOfZion/neo-go/pkg/rpc/client"
|
"github.com/CityOfZion/neo-go/pkg/rpc/client"
|
||||||
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
||||||
"github.com/CityOfZion/neo-go/pkg/rpc/response"
|
"github.com/CityOfZion/neo-go/pkg/rpc/response/result"
|
||||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||||
|
@ -364,7 +364,7 @@ func invokeInternal(ctx *cli.Context, withMethod bool, signAndPush bool) error {
|
||||||
operation string
|
operation string
|
||||||
params = make([]smartcontract.Parameter, 0)
|
params = make([]smartcontract.Parameter, 0)
|
||||||
paramsStart = 1
|
paramsStart = 1
|
||||||
resp *response.InvokeResult
|
resp *result.Invoke
|
||||||
wif *keys.WIF
|
wif *keys.WIF
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||||
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
||||||
"github.com/CityOfZion/neo-go/pkg/rpc/response"
|
|
||||||
"github.com/CityOfZion/neo-go/pkg/rpc/response/result"
|
"github.com/CityOfZion/neo-go/pkg/rpc/response/result"
|
||||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
|
@ -68,10 +67,10 @@ func (c *Client) GetUnspents(address string) (*result.Unspents, error) {
|
||||||
|
|
||||||
// InvokeScript returns the result of the given script after running it true the VM.
|
// InvokeScript returns the result of the given script after running it true the VM.
|
||||||
// NOTE: This is a test invoke and will not affect the blockchain.
|
// NOTE: This is a test invoke and will not affect the blockchain.
|
||||||
func (c *Client) InvokeScript(script string) (*response.InvokeResult, error) {
|
func (c *Client) InvokeScript(script string) (*result.Invoke, error) {
|
||||||
var (
|
var (
|
||||||
params = request.NewRawParams(script)
|
params = request.NewRawParams(script)
|
||||||
resp = &response.InvokeResult{}
|
resp = &result.Invoke{}
|
||||||
)
|
)
|
||||||
if err := c.performRequest("invokescript", params, resp); err != nil {
|
if err := c.performRequest("invokescript", params, resp); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -82,10 +81,10 @@ func (c *Client) InvokeScript(script string) (*response.InvokeResult, error) {
|
||||||
// InvokeFunction returns the results after calling the smart contract scripthash
|
// InvokeFunction returns the results after calling the smart contract scripthash
|
||||||
// with the given operation and parameters.
|
// with the given operation and parameters.
|
||||||
// NOTE: this is test invoke and will not affect the blockchain.
|
// NOTE: this is test invoke and will not affect the blockchain.
|
||||||
func (c *Client) InvokeFunction(script, operation string, params []smartcontract.Parameter) (*response.InvokeResult, error) {
|
func (c *Client) InvokeFunction(script, operation string, params []smartcontract.Parameter) (*result.Invoke, error) {
|
||||||
var (
|
var (
|
||||||
p = request.NewRawParams(script, operation, params)
|
p = request.NewRawParams(script, operation, params)
|
||||||
resp = &response.InvokeResult{}
|
resp = &result.Invoke{}
|
||||||
)
|
)
|
||||||
if err := c.performRequest("invokefunction", p, resp); err != nil {
|
if err := c.performRequest("invokefunction", p, resp); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -95,10 +94,10 @@ func (c *Client) InvokeFunction(script, operation string, params []smartcontract
|
||||||
|
|
||||||
// Invoke returns the results after calling the smart contract scripthash
|
// Invoke returns the results after calling the smart contract scripthash
|
||||||
// with the given parameters.
|
// with the given parameters.
|
||||||
func (c *Client) Invoke(script string, params []smartcontract.Parameter) (*response.InvokeResult, error) {
|
func (c *Client) Invoke(script string, params []smartcontract.Parameter) (*result.Invoke, error) {
|
||||||
var (
|
var (
|
||||||
p = request.NewRawParams(script, params)
|
p = request.NewRawParams(script, params)
|
||||||
resp = &response.InvokeResult{}
|
resp = &result.Invoke{}
|
||||||
)
|
)
|
||||||
if err := c.performRequest("invoke", p, resp); err != nil {
|
if err := c.performRequest("invoke", p, resp); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/CityOfZion/neo-go/pkg/core/state"
|
"github.com/CityOfZion/neo-go/pkg/core/state"
|
||||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ApplicationLog wrapper used for the representation of the
|
// ApplicationLog wrapper used for the representation of the
|
||||||
|
@ -35,7 +36,8 @@ type NotificationEvent struct {
|
||||||
func NewApplicationLog(appExecRes *state.AppExecResult, scriptHash util.Uint160) ApplicationLog {
|
func NewApplicationLog(appExecRes *state.AppExecResult, scriptHash util.Uint160) ApplicationLog {
|
||||||
events := make([]NotificationEvent, 0, len(appExecRes.Events))
|
events := make([]NotificationEvent, 0, len(appExecRes.Events))
|
||||||
for _, e := range appExecRes.Events {
|
for _, e := range appExecRes.Events {
|
||||||
item := e.Item.ToContractParameter()
|
seen := make(map[vm.StackItem]bool)
|
||||||
|
item := e.Item.ToContractParameter(seen)
|
||||||
events = append(events, NotificationEvent{
|
events = append(events, NotificationEvent{
|
||||||
Contract: e.ScriptHash,
|
Contract: e.ScriptHash,
|
||||||
Item: item,
|
Item: item,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package result
|
package result
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Invoke represents code invocation result and is used by several RPC calls
|
// Invoke represents code invocation result and is used by several RPC calls
|
||||||
|
@ -10,5 +10,5 @@ type Invoke struct {
|
||||||
State string `json:"state"`
|
State string `json:"state"`
|
||||||
GasConsumed string `json:"gas_consumed"`
|
GasConsumed string `json:"gas_consumed"`
|
||||||
Script string `json:"script"`
|
Script string `json:"script"`
|
||||||
Stack *vm.Stack
|
Stack []smartcontract.Parameter
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,19 +4,8 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/CityOfZion/neo-go/pkg/rpc/response/result"
|
"github.com/CityOfZion/neo-go/pkg/rpc/response/result"
|
||||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
|
||||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// InvokeResult represents the outcome of a script that is
|
|
||||||
// executed by the NEO VM.
|
|
||||||
type InvokeResult struct {
|
|
||||||
State vm.State `json:"state"`
|
|
||||||
GasConsumed string `json:"gas_consumed"`
|
|
||||||
Script string `json:"script"`
|
|
||||||
Stack []smartcontract.Parameter
|
|
||||||
}
|
|
||||||
|
|
||||||
// Header is a generic JSON-RPC 2.0 response header (ID and JSON-RPC version).
|
// Header is a generic JSON-RPC 2.0 response header (ID and JSON-RPC version).
|
||||||
type Header struct {
|
type Header struct {
|
||||||
ID json.RawMessage `json:"id"`
|
ID json.RawMessage `json:"id"`
|
||||||
|
|
|
@ -624,7 +624,7 @@ func (s *Server) runScriptInVM(script []byte) *result.Invoke {
|
||||||
State: vm.State(),
|
State: vm.State(),
|
||||||
GasConsumed: vm.GasConsumed().String(),
|
GasConsumed: vm.GasConsumed().String(),
|
||||||
Script: hex.EncodeToString(script),
|
Script: hex.EncodeToString(script),
|
||||||
Stack: vm.Estack(),
|
Stack: vm.Estack().ToContractParameters(),
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,21 +12,11 @@ import (
|
||||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||||
"github.com/CityOfZion/neo-go/pkg/io"
|
"github.com/CityOfZion/neo-go/pkg/io"
|
||||||
"github.com/CityOfZion/neo-go/pkg/network"
|
"github.com/CityOfZion/neo-go/pkg/network"
|
||||||
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/zap/zaptest"
|
"go.uber.org/zap/zaptest"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InvokeFunctionResult struct for testing.
|
|
||||||
type InvokeFunctionResult struct {
|
|
||||||
Script string `json:"script"`
|
|
||||||
State string `json:"state"`
|
|
||||||
GasConsumed string `json:"gas_consumed"`
|
|
||||||
Stack []request.FuncParam `json:"stack"`
|
|
||||||
TX string `json:"tx,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func initServerWithInMemoryChain(t *testing.T) (*core.Blockchain, http.HandlerFunc) {
|
func initServerWithInMemoryChain(t *testing.T) (*core.Blockchain, http.HandlerFunc) {
|
||||||
var nBlocks uint32
|
var nBlocks uint32
|
||||||
|
|
||||||
|
|
|
@ -474,9 +474,9 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
params: `["50befd26fdf6e4d957c11e078b24ebce6291456f", [{"type": "String", "value": "qwerty"}]]`,
|
params: `["50befd26fdf6e4d957c11e078b24ebce6291456f", [{"type": "String", "value": "qwerty"}]]`,
|
||||||
result: func(e *executor) interface{} { return &InvokeFunctionResult{} },
|
result: func(e *executor) interface{} { return &result.Invoke{} },
|
||||||
check: func(t *testing.T, e *executor, inv interface{}) {
|
check: func(t *testing.T, e *executor, inv interface{}) {
|
||||||
res, ok := inv.(*InvokeFunctionResult)
|
res, ok := inv.(*result.Invoke)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
assert.Equal(t, "06717765727479676f459162ceeb248b071ec157d9e4f6fd26fdbe50", res.Script)
|
assert.Equal(t, "06717765727479676f459162ceeb248b071ec157d9e4f6fd26fdbe50", res.Script)
|
||||||
assert.NotEqual(t, "", res.State)
|
assert.NotEqual(t, "", res.State)
|
||||||
|
@ -513,9 +513,9 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
params: `["50befd26fdf6e4d957c11e078b24ebce6291456f", "test", []]`,
|
params: `["50befd26fdf6e4d957c11e078b24ebce6291456f", "test", []]`,
|
||||||
result: func(e *executor) interface{} { return &InvokeFunctionResult{} },
|
result: func(e *executor) interface{} { return &result.Invoke{} },
|
||||||
check: func(t *testing.T, e *executor, inv interface{}) {
|
check: func(t *testing.T, e *executor, inv interface{}) {
|
||||||
res, ok := inv.(*InvokeFunctionResult)
|
res, ok := inv.(*result.Invoke)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
assert.NotEqual(t, "", res.Script)
|
assert.NotEqual(t, "", res.Script)
|
||||||
assert.NotEqual(t, "", res.State)
|
assert.NotEqual(t, "", res.State)
|
||||||
|
@ -547,9 +547,9 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
params: `["51c56b0d48656c6c6f2c20776f726c6421680f4e656f2e52756e74696d652e4c6f67616c7566"]`,
|
params: `["51c56b0d48656c6c6f2c20776f726c6421680f4e656f2e52756e74696d652e4c6f67616c7566"]`,
|
||||||
result: func(e *executor) interface{} { return &InvokeFunctionResult{} },
|
result: func(e *executor) interface{} { return &result.Invoke{} },
|
||||||
check: func(t *testing.T, e *executor, inv interface{}) {
|
check: func(t *testing.T, e *executor, inv interface{}) {
|
||||||
res, ok := inv.(*InvokeFunctionResult)
|
res, ok := inv.(*result.Invoke)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
assert.NotEqual(t, "", res.Script)
|
assert.NotEqual(t, "", res.Script)
|
||||||
assert.NotEqual(t, "", res.State)
|
assert.NotEqual(t, "", res.State)
|
||||||
|
|
|
@ -171,8 +171,11 @@ func (c *Context) Dup() StackItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToContractParameter implements StackItem interface.
|
// ToContractParameter implements StackItem interface.
|
||||||
func (c *Context) ToContractParameter() smartcontract.Parameter {
|
func (c *Context) ToContractParameter(map[StackItem]bool) smartcontract.Parameter {
|
||||||
panic("Not implemented")
|
return smartcontract.Parameter{
|
||||||
|
Type: smartcontract.StringType,
|
||||||
|
Value: c.String(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) atBreakPoint() bool {
|
func (c *Context) atBreakPoint() bool {
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
package vm
|
|
||||||
|
|
||||||
import "encoding/json"
|
|
||||||
|
|
||||||
// StackOutput holds information about the stack, used for pretty printing
|
|
||||||
// the stack.
|
|
||||||
type stackItem struct {
|
|
||||||
Value interface{} `json:"value"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func appendToItems(items *[]stackItem, val StackItem, seen map[StackItem]bool) {
|
|
||||||
if arr, ok := val.Value().([]StackItem); ok {
|
|
||||||
if seen[val] {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
seen[val] = true
|
|
||||||
intItems := make([]stackItem, 0, len(arr))
|
|
||||||
for _, v := range arr {
|
|
||||||
appendToItems(&intItems, v, seen)
|
|
||||||
}
|
|
||||||
*items = append(*items, stackItem{
|
|
||||||
Value: intItems,
|
|
||||||
Type: val.String(),
|
|
||||||
})
|
|
||||||
|
|
||||||
} else {
|
|
||||||
*items = append(*items, stackItem{
|
|
||||||
Value: val,
|
|
||||||
Type: val.String(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func stackToArray(s *Stack) []stackItem {
|
|
||||||
items := make([]stackItem, 0, s.Len())
|
|
||||||
seen := make(map[StackItem]bool)
|
|
||||||
s.IterBack(func(e *Element) {
|
|
||||||
appendToItems(&items, e.value, seen)
|
|
||||||
})
|
|
||||||
return items
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildStackOutput(s *Stack) string {
|
|
||||||
b, _ := json.MarshalIndent(stackToArray(s), "", " ")
|
|
||||||
return string(b)
|
|
||||||
}
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||||
"github.com/CityOfZion/neo-go/pkg/vm/emit"
|
"github.com/CityOfZion/neo-go/pkg/vm/emit"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -469,7 +470,18 @@ func (s *Stack) popSigElements() ([][]byte, error) {
|
||||||
return elems, nil
|
return elems, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToContractParameters converts Stack to slice of smartcontract.Parameter.
|
||||||
|
func (s *Stack) ToContractParameters() []smartcontract.Parameter {
|
||||||
|
items := make([]smartcontract.Parameter, 0, s.Len())
|
||||||
|
s.IterBack(func(e *Element) {
|
||||||
|
// Each item is independent.
|
||||||
|
seen := make(map[StackItem]bool)
|
||||||
|
items = append(items, e.value.ToContractParameter(seen))
|
||||||
|
})
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalJSON implements JSON marshalling interface.
|
// MarshalJSON implements JSON marshalling interface.
|
||||||
func (s *Stack) MarshalJSON() ([]byte, error) {
|
func (s *Stack) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(stackToArray(s))
|
return json.Marshal(s.ToContractParameters())
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ type StackItem interface {
|
||||||
// Dup duplicates current StackItem.
|
// Dup duplicates current StackItem.
|
||||||
Dup() StackItem
|
Dup() StackItem
|
||||||
// ToContractParameter converts StackItem to smartcontract.Parameter
|
// ToContractParameter converts StackItem to smartcontract.Parameter
|
||||||
ToContractParameter() smartcontract.Parameter
|
ToContractParameter(map[StackItem]bool) smartcontract.Parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeStackItem(v interface{}) StackItem {
|
func makeStackItem(v interface{}) StackItem {
|
||||||
|
@ -119,12 +119,16 @@ func (i *StructItem) Dup() StackItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToContractParameter implements StackItem interface.
|
// ToContractParameter implements StackItem interface.
|
||||||
func (i *StructItem) ToContractParameter() smartcontract.Parameter {
|
func (i *StructItem) ToContractParameter(seen map[StackItem]bool) smartcontract.Parameter {
|
||||||
var value []smartcontract.Parameter
|
var value []smartcontract.Parameter
|
||||||
|
|
||||||
|
if !seen[i] {
|
||||||
|
seen[i] = true
|
||||||
for _, stackItem := range i.value {
|
for _, stackItem := range i.value {
|
||||||
parameter := stackItem.ToContractParameter()
|
parameter := stackItem.ToContractParameter(seen)
|
||||||
value = append(value, parameter)
|
value = append(value, parameter)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return smartcontract.Parameter{
|
return smartcontract.Parameter{
|
||||||
Type: smartcontract.ArrayType,
|
Type: smartcontract.ArrayType,
|
||||||
Value: value,
|
Value: value,
|
||||||
|
@ -179,7 +183,7 @@ func (i *BigIntegerItem) Dup() StackItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToContractParameter implements StackItem interface.
|
// ToContractParameter implements StackItem interface.
|
||||||
func (i *BigIntegerItem) ToContractParameter() smartcontract.Parameter {
|
func (i *BigIntegerItem) ToContractParameter(map[StackItem]bool) smartcontract.Parameter {
|
||||||
return smartcontract.Parameter{
|
return smartcontract.Parameter{
|
||||||
Type: smartcontract.IntegerType,
|
Type: smartcontract.IntegerType,
|
||||||
Value: i.value.Int64(),
|
Value: i.value.Int64(),
|
||||||
|
@ -223,7 +227,7 @@ func (i *BoolItem) Dup() StackItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToContractParameter implements StackItem interface.
|
// ToContractParameter implements StackItem interface.
|
||||||
func (i *BoolItem) ToContractParameter() smartcontract.Parameter {
|
func (i *BoolItem) ToContractParameter(map[StackItem]bool) smartcontract.Parameter {
|
||||||
return smartcontract.Parameter{
|
return smartcontract.Parameter{
|
||||||
Type: smartcontract.BoolType,
|
Type: smartcontract.BoolType,
|
||||||
Value: i.value,
|
Value: i.value,
|
||||||
|
@ -264,7 +268,7 @@ func (i *ByteArrayItem) Dup() StackItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToContractParameter implements StackItem interface.
|
// ToContractParameter implements StackItem interface.
|
||||||
func (i *ByteArrayItem) ToContractParameter() smartcontract.Parameter {
|
func (i *ByteArrayItem) ToContractParameter(map[StackItem]bool) smartcontract.Parameter {
|
||||||
return smartcontract.Parameter{
|
return smartcontract.Parameter{
|
||||||
Type: smartcontract.ByteArrayType,
|
Type: smartcontract.ByteArrayType,
|
||||||
Value: i.value,
|
Value: i.value,
|
||||||
|
@ -304,12 +308,16 @@ func (i *ArrayItem) Dup() StackItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToContractParameter implements StackItem interface.
|
// ToContractParameter implements StackItem interface.
|
||||||
func (i *ArrayItem) ToContractParameter() smartcontract.Parameter {
|
func (i *ArrayItem) ToContractParameter(seen map[StackItem]bool) smartcontract.Parameter {
|
||||||
var value []smartcontract.Parameter
|
var value []smartcontract.Parameter
|
||||||
|
|
||||||
|
if !seen[i] {
|
||||||
|
seen[i] = true
|
||||||
for _, stackItem := range i.value {
|
for _, stackItem := range i.value {
|
||||||
parameter := stackItem.ToContractParameter()
|
parameter := stackItem.ToContractParameter(seen)
|
||||||
value = append(value, parameter)
|
value = append(value, parameter)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return smartcontract.Parameter{
|
return smartcontract.Parameter{
|
||||||
Type: smartcontract.ArrayType,
|
Type: smartcontract.ArrayType,
|
||||||
Value: value,
|
Value: value,
|
||||||
|
@ -350,16 +358,19 @@ func (i *MapItem) Dup() StackItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToContractParameter implements StackItem interface.
|
// ToContractParameter implements StackItem interface.
|
||||||
func (i *MapItem) ToContractParameter() smartcontract.Parameter {
|
func (i *MapItem) ToContractParameter(seen map[StackItem]bool) smartcontract.Parameter {
|
||||||
value := make(map[smartcontract.Parameter]smartcontract.Parameter)
|
value := make(map[smartcontract.Parameter]smartcontract.Parameter)
|
||||||
|
if !seen[i] {
|
||||||
|
seen[i] = true
|
||||||
for key, val := range i.value {
|
for key, val := range i.value {
|
||||||
pValue := val.ToContractParameter()
|
pValue := val.ToContractParameter(seen)
|
||||||
pKey := fromMapKey(key).ToContractParameter()
|
pKey := fromMapKey(key).ToContractParameter(seen)
|
||||||
if pKey.Type == smartcontract.ByteArrayType {
|
if pKey.Type == smartcontract.ByteArrayType {
|
||||||
pKey.Value = string(pKey.Value.([]byte))
|
pKey.Value = string(pKey.Value.([]byte))
|
||||||
}
|
}
|
||||||
value[pKey] = pValue
|
value[pKey] = pValue
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return smartcontract.Parameter{
|
return smartcontract.Parameter{
|
||||||
Type: smartcontract.MapType,
|
Type: smartcontract.MapType,
|
||||||
Value: value,
|
Value: value,
|
||||||
|
@ -428,7 +439,7 @@ func (i *InteropItem) Dup() StackItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToContractParameter implements StackItem interface.
|
// ToContractParameter implements StackItem interface.
|
||||||
func (i *InteropItem) ToContractParameter() smartcontract.Parameter {
|
func (i *InteropItem) ToContractParameter(map[StackItem]bool) smartcontract.Parameter {
|
||||||
return smartcontract.Parameter{
|
return smartcontract.Parameter{
|
||||||
Type: smartcontract.InteropInterfaceType,
|
Type: smartcontract.InteropInterfaceType,
|
||||||
Value: nil,
|
Value: nil,
|
||||||
|
|
|
@ -60,7 +60,8 @@ var toContractParameterTestCases = []struct {
|
||||||
|
|
||||||
func TestToContractParameter(t *testing.T) {
|
func TestToContractParameter(t *testing.T) {
|
||||||
for _, tc := range toContractParameterTestCases {
|
for _, tc := range toContractParameterTestCases {
|
||||||
res := tc.input.ToContractParameter()
|
seen := make(map[StackItem]bool)
|
||||||
|
res := tc.input.ToContractParameter(seen)
|
||||||
assert.Equal(t, res, tc.result)
|
assert.Equal(t, res, tc.result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package vm
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
@ -301,7 +302,8 @@ func (v *VM) Stack(n string) string {
|
||||||
if n == "estack" {
|
if n == "estack" {
|
||||||
s = v.estack
|
s = v.estack
|
||||||
}
|
}
|
||||||
return buildStackOutput(s)
|
b, _ := json.MarshalIndent(s.ToContractParameters(), "", " ")
|
||||||
|
return string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// State returns string representation of the state for the VM.
|
// State returns string representation of the state for the VM.
|
||||||
|
|
Loading…
Reference in a new issue