Merge pull request #1013 from nspcc-dev/neo3/vm/stackitem_refactoring

vm: move StackItem to a separate package
This commit is contained in:
Roman Khimov 2020-06-08 15:30:44 +03:00 committed by GitHub
commit 795523f5cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 2575 additions and 2466 deletions

View file

@ -0,0 +1,72 @@
package smartcontract
import (
"fmt"
"math/big"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
)
// ParameterFromStackItem converts stackitem.Item to Parameter
func ParameterFromStackItem(i stackitem.Item, seen map[stackitem.Item]bool) Parameter {
switch t := i.(type) {
case stackitem.Null, *stackitem.Pointer:
return NewParameter(AnyType)
case *stackitem.BigInteger:
return Parameter{
Type: IntegerType,
Value: i.Value().(*big.Int).Int64(),
}
case *stackitem.Bool:
return Parameter{
Type: BoolType,
Value: i.Value().(bool),
}
case *stackitem.ByteArray:
return Parameter{
Type: ByteArrayType,
Value: i.Value().([]byte),
}
case *stackitem.Interop:
return Parameter{
Type: InteropInterfaceType,
Value: nil,
}
case *stackitem.Buffer:
return Parameter{
Type: ByteArrayType,
Value: i.Value().([]byte),
}
case *stackitem.Struct, *stackitem.Array:
var value []Parameter
if !seen[i] {
seen[i] = true
for _, stackItem := range i.Value().([]stackitem.Item) {
parameter := ParameterFromStackItem(stackItem, seen)
value = append(value, parameter)
}
}
return Parameter{
Type: ArrayType,
Value: value,
}
case *stackitem.Map:
value := make([]ParameterPair, 0)
if !seen[i] {
seen[i] = true
for _, element := range i.Value().([]stackitem.MapElement) {
value = append(value, ParameterPair{
Key: ParameterFromStackItem(element.Key, seen),
Value: ParameterFromStackItem(element.Value, seen),
})
}
}
return Parameter{
Type: MapType,
Value: value,
}
default:
panic(fmt.Sprintf("unknown stack item type: %v", t))
}
}

View file

@ -0,0 +1,79 @@
package smartcontract
import (
"math/big"
"testing"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/stretchr/testify/assert"
)
var toContractParameterTestCases = []struct {
input stackitem.Item
result Parameter
}{
{
input: stackitem.NewStruct([]stackitem.Item{
stackitem.NewBigInteger(big.NewInt(1)),
stackitem.NewBool(true),
}),
result: Parameter{Type: ArrayType, Value: []Parameter{
{Type: IntegerType, Value: int64(1)},
{Type: BoolType, Value: true},
}},
},
{
input: stackitem.NewBool(false),
result: Parameter{Type: BoolType, Value: false},
},
{
input: stackitem.NewByteArray([]byte{0x01, 0x02, 0x03}),
result: Parameter{Type: ByteArrayType, Value: []byte{0x01, 0x02, 0x03}},
},
{
input: stackitem.NewBuffer([]byte{0x01, 0x02, 0x03}),
result: Parameter{Type: ByteArrayType, Value: []byte{0x01, 0x02, 0x03}},
},
{
input: stackitem.NewArray([]stackitem.Item{stackitem.NewBigInteger(big.NewInt(2)), stackitem.NewBool(true)}),
result: Parameter{Type: ArrayType, Value: []Parameter{
{Type: IntegerType, Value: int64(2)},
{Type: BoolType, Value: true},
}},
},
{
input: stackitem.NewInterop(nil),
result: Parameter{Type: InteropInterfaceType, Value: nil},
},
{
input: stackitem.NewMapWithValue([]stackitem.MapElement{
{Key: stackitem.NewBigInteger(big.NewInt(1)), Value: stackitem.NewBool(true)},
{Key: stackitem.NewByteArray([]byte("qwerty")), Value: stackitem.NewBigInteger(big.NewInt(3))},
{Key: stackitem.NewBool(true), Value: stackitem.NewBool(false)},
}),
result: Parameter{
Type: MapType,
Value: []ParameterPair{
{
Key: Parameter{Type: IntegerType, Value: int64(1)},
Value: Parameter{Type: BoolType, Value: true},
}, {
Key: Parameter{Type: ByteArrayType, Value: []byte("qwerty")},
Value: Parameter{Type: IntegerType, Value: int64(3)},
}, {
Key: Parameter{Type: BoolType, Value: true},
Value: Parameter{Type: BoolType, Value: false},
},
},
},
},
}
func TestToContractParameter(t *testing.T) {
for _, tc := range toContractParameterTestCases {
seen := make(map[stackitem.Item]bool)
res := ParameterFromStackItem(tc.input, seen)
assert.Equal(t, res, tc.result)
}
}