mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-23 03:41:34 +00:00
Parse stack params (#119)
* small fixes * gofmt * bytearray parsing * tests * removed unnecessary files * added more types for bytearray * iter * made TryParseArray parameter variadic * fixes after review * fix after review * misprints * updated array reverse * imports/fmt * naming
This commit is contained in:
parent
7c1147f04f
commit
a058598ecc
5 changed files with 210 additions and 4 deletions
1
go.mod
1
go.mod
|
@ -19,4 +19,5 @@ require (
|
|||
golang.org/x/tools v0.0.0-20180318012157-96caea41033d
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
|
||||
gopkg.in/h2non/gock.v1 v1.0.12 // indirect
|
||||
)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
|
@ -97,7 +98,7 @@ func (t *StackParamType) UnmarshalJSON(data []byte) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// StackParam respresent a stack parameter.
|
||||
// StackParam represent a stack parameter.
|
||||
type StackParam struct {
|
||||
Type StackParamType `json:"type"`
|
||||
Value interface{} `json:"value"`
|
||||
|
@ -172,3 +173,89 @@ func (p *StackParam) UnmarshalJSON(data []byte) (err error) {
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
type StackParams []StackParam
|
||||
|
||||
func (p StackParams) TryParseArray(vals ...interface{}) error {
|
||||
var (
|
||||
err error
|
||||
i int
|
||||
par StackParam
|
||||
)
|
||||
if len(p) != len(vals) {
|
||||
return errors.New("receiver array doesn't fit the StackParams length")
|
||||
}
|
||||
for i, par = range p {
|
||||
if err = par.TryParse(vals[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p StackParam) TryParse(dest interface{}) error {
|
||||
var (
|
||||
err error
|
||||
ok bool
|
||||
data []byte
|
||||
)
|
||||
switch p.Type {
|
||||
case ByteArray:
|
||||
if data, ok = p.Value.([]byte); !ok {
|
||||
return errors.Errorf("failed to cast %s to []byte", p.Value)
|
||||
}
|
||||
switch dest := dest.(type) {
|
||||
case *util.Uint160:
|
||||
if *dest, err = util.Uint160DecodeBytes(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
case *[]byte:
|
||||
*dest = data
|
||||
return nil
|
||||
case *util.Uint256:
|
||||
if *dest, err = util.Uint256DecodeBytes(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
case *int64, *int32, *int16, *int8, *int, *uint64, *uint32, *uint16, *uint8, *uint:
|
||||
i := bytesToUint64(data)
|
||||
switch dest := dest.(type) {
|
||||
case *int64:
|
||||
*dest = int64(i)
|
||||
case *int32:
|
||||
*dest = int32(i)
|
||||
case *int16:
|
||||
*dest = int16(i)
|
||||
case *int8:
|
||||
*dest = int8(i)
|
||||
case *int:
|
||||
*dest = int(i)
|
||||
case *uint64:
|
||||
*dest = i
|
||||
case *uint32:
|
||||
*dest = uint32(i)
|
||||
case *uint16:
|
||||
*dest = uint16(i)
|
||||
case *uint8:
|
||||
*dest = uint8(i)
|
||||
case *uint:
|
||||
*dest = uint(i)
|
||||
}
|
||||
case *string:
|
||||
*dest = string(data)
|
||||
return nil
|
||||
default:
|
||||
return errors.Errorf("cannot cast stackparam of type %s to type %s", p.Type, dest)
|
||||
}
|
||||
default:
|
||||
return errors.New("cannot define stackparam type")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func bytesToUint64(b []byte) uint64 {
|
||||
data := make([]byte, 8)
|
||||
copy(data[8-len(b):], util.ArrayReverse(b))
|
||||
return binary.BigEndian.Uint64(data)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
@ -103,3 +104,120 @@ func TestStackParam_UnmarshalJSON(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
hash160 = "0bcd2978634d961c24f5aea0802297ff128724d6"
|
||||
hash256 = "7fe610b7c8259ae949accacb091a1bc53219c51a1cb8752fbc6457674c13ec0b"
|
||||
testString = "myteststring"
|
||||
)
|
||||
|
||||
func TestStackParam_TryParse(t *testing.T) {
|
||||
// ByteArray to util.Uint160 conversion
|
||||
data, err := hex.DecodeString(hash160)
|
||||
var (
|
||||
outputUint160, expectedUint160 util.Uint160
|
||||
input = StackParam{
|
||||
Type: ByteArray,
|
||||
Value: data,
|
||||
}
|
||||
)
|
||||
expectedUint160, err = util.Uint160DecodeString(hash160)
|
||||
if err = input.TryParse(&outputUint160); err != nil {
|
||||
t.Errorf("failed to parse stackparam to Uint160: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(outputUint160, expectedUint160) {
|
||||
t.Errorf("got (%v), expected (%v)", outputUint160, expectedUint160)
|
||||
}
|
||||
|
||||
// ByteArray to util.Uint256 conversion
|
||||
data, err = hex.DecodeString(hash256)
|
||||
var (
|
||||
outputUint256, expectedUint256 util.Uint256
|
||||
uint256input = StackParam{
|
||||
Type: ByteArray,
|
||||
Value: data,
|
||||
}
|
||||
)
|
||||
expectedUint256, err = util.Uint256DecodeString(hash256)
|
||||
if err = uint256input.TryParse(&outputUint256); err != nil {
|
||||
t.Errorf("failed to parse stackparam to []byte: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(outputUint256, expectedUint256) {
|
||||
t.Errorf("got (%v), expected (%v)", outputUint256, expectedUint256)
|
||||
}
|
||||
|
||||
// ByteArray to []byte conversion
|
||||
var (
|
||||
outputBytes []byte
|
||||
expectedBytes = expectedUint160.Bytes()
|
||||
)
|
||||
if err = input.TryParse(&outputBytes); err != nil {
|
||||
t.Errorf("failed to parse stackparam to []byte: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(outputBytes, expectedBytes) {
|
||||
t.Errorf("got (%v), expected (%v)", outputBytes, expectedBytes)
|
||||
}
|
||||
|
||||
// ByteArray to int64 conversion
|
||||
data, err = hex.DecodeString("637829cd0b")
|
||||
var (
|
||||
outputInt, expectedInt int64
|
||||
intinput = StackParam{
|
||||
Type: ByteArray,
|
||||
Value: data,
|
||||
}
|
||||
)
|
||||
expectedInt = 50686687331
|
||||
if err = intinput.TryParse(&outputInt); err != nil {
|
||||
t.Errorf("failed to parse stackparam to []byte: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(outputInt, expectedInt) {
|
||||
t.Errorf("got (%v), expected (%v)", outputInt, expectedInt)
|
||||
}
|
||||
|
||||
// ByteArray to string conversion
|
||||
data = []byte(testString)
|
||||
var (
|
||||
outputStr, expectedStr string
|
||||
strinput = StackParam{
|
||||
Type: ByteArray,
|
||||
Value: data,
|
||||
}
|
||||
)
|
||||
expectedStr = testString
|
||||
if err = strinput.TryParse(&outputStr); err != nil {
|
||||
t.Errorf("failed to parse stackparam to []byte: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(outputStr, expectedStr) {
|
||||
t.Errorf("got (%v), expected (%v)", outputStr, expectedStr)
|
||||
}
|
||||
|
||||
// StackParams to []util.Uint160
|
||||
data, err = hex.DecodeString(hash160)
|
||||
expUint160, err := util.Uint160DecodeString(hash160)
|
||||
var (
|
||||
params = StackParams{
|
||||
StackParam{
|
||||
Type: ByteArray,
|
||||
Value: data,
|
||||
},
|
||||
StackParam{
|
||||
Type: ByteArray,
|
||||
Value: data,
|
||||
},
|
||||
}
|
||||
expectedArray = []util.Uint160{
|
||||
expUint160,
|
||||
expUint160,
|
||||
}
|
||||
out1, out2 = &util.Uint160{}, &util.Uint160{}
|
||||
)
|
||||
if err = params.TryParseArray(out1, out2); err != nil {
|
||||
t.Errorf("failed to parse stackparam to []byte: %v", err)
|
||||
}
|
||||
outArray := []util.Uint160{*out1, *out2}
|
||||
if !reflect.DeepEqual(outArray, expectedArray) {
|
||||
t.Errorf("got (%v), expected (%v)", outArray, expectedArray)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ func ArrayReverse(b []byte) []byte {
|
|||
return b
|
||||
}
|
||||
dest := make([]byte, len(b))
|
||||
for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
|
||||
for i, j := 0, len(b)-1; i <= j; i, j = i+1, j-1 {
|
||||
dest[i], dest[j] = b[j], b[i]
|
||||
}
|
||||
return dest
|
||||
|
|
|
@ -6,9 +6,9 @@ import (
|
|||
)
|
||||
|
||||
func TestArrayReverse(t *testing.T) {
|
||||
arr := []byte{0x01, 0x02, 0x03, 0x04}
|
||||
arr := []byte{0x01, 0x02, 0x03, 0x04, 0x05}
|
||||
have := ArrayReverse(arr)
|
||||
want := []byte{0x04, 0x03, 0x02, 0x01}
|
||||
want := []byte{0x05, 0x04, 0x03, 0x02, 0x01}
|
||||
if bytes.Compare(have, want) != 0 {
|
||||
t.Fatalf("expected %v got %v", want, have)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue