Optimizations + some improvements (#105)

* Optimizations + some improvements

- optimized pkg/core/storage.HeaderHashes
- optimized pkg/rpc.performRequest (used json.Encoder)
- fixes for pkg/util.ReadVarUint and pkg/util.WriteVarUint
- optimized and fix fixed8 (Fixed8DecodeString / MarshalJSON) + tests
- optimized and fix uint160 (Bytes / Uint160DecodeString / Equal / MarshalJSON) + tests
- optimized and fix uint256 (Bytes / Equal / MarshalJSON) + tests
- preallocate for pkg/vm.buildStackOutput
- add go.mod / go.sum

* update version
This commit is contained in:
Evgeniy Kulikov 2018-11-26 18:56:45 +03:00 committed by Anthony De Meulemeester
parent c8d7671d26
commit 6ccb518ab0
14 changed files with 205 additions and 101 deletions

View file

@ -1 +1 @@
0.44.10 0.44.11

22
go.mod Normal file
View file

@ -0,0 +1,22 @@
module github.com/CityOfZion/neo-go
require (
github.com/anthdm/rfc6979 v0.0.0-20141003034818-6a90f24967eb
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb // indirect
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/go-redis/redis v6.10.2+incompatible
github.com/go-yaml/yaml v2.1.0+incompatible
github.com/golang/snappy v0.0.0-20170215233205-553a64147049 // indirect
github.com/onsi/gomega v1.4.2 // indirect
github.com/pkg/errors v0.8.0
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/sirupsen/logrus v1.0.5
github.com/stretchr/testify v1.2.1
github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73
github.com/urfave/cli v1.20.0
golang.org/x/crypto v0.0.0-20180316180149-374053ea96cb
golang.org/x/text v0.3.0
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
)

58
go.sum Normal file
View file

@ -0,0 +1,58 @@
github.com/anthdm/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:UTxADjhpvBfb7LpAB+uu4uzlTJ3ZJyWA5En+KsYHed8=
github.com/anthdm/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:EjSkpESoXW3cDxVZzHil2eVMoGkYxb8Q7qgfV5JOTPs=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-redis/redis v6.10.2+incompatible h1:SLbqrO/Ik1nhXA5/cbEs1P5MUBo1Qq4ihlNfGnnipPw=
github.com/go-redis/redis v6.10.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049 h1:K9KHZbXKpGydfDN0aZrsoHpLJlZsBrGMFWbgLDGnPZk=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.2 h1:3mYCb7aPxS/RU7TI1y4rkEn1oKmPRjNJLNEXgw7MH2I=
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.0.5 h1:8c8b5uO0zS4X6RPl/sd1ENwSkIc0/H2PaHxE3udaE8I=
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U=
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73 h1:I2drr5K0tykBofr74ZEGliE/Hf6fNkEbcPyFvsy7wZk=
github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
golang.org/x/crypto v0.0.0-20180316180149-374053ea96cb h1:O6ztCaemiMr99EgJdgXrr0J7N0EQN1oky/0GxML9Avk=
golang.org/x/crypto v0.0.0-20180316180149-374053ea96cb/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20180318012157-96caea41033d h1:Xmo0nLTRYewf0eXDvo12nMSuOgNQ4283hdbOHIUf7h8=
golang.org/x/tools v0.0.0-20180318012157-96caea41033d/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View file

@ -42,6 +42,13 @@ func CurrentHeaderHeight(s Store) (i uint32, h util.Uint256, err error) {
return return
} }
// uint32Slice attaches the methods of Interface to []int, sorting in increasing order.
type uint32Slice []uint32
func (p uint32Slice) Len() int { return len(p) }
func (p uint32Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p uint32Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// HeaderHashes returns a sorted list of header hashes retrieved from // HeaderHashes returns a sorted list of header hashes retrieved from
// the given underlying Store. // the given underlying Store.
func HeaderHashes(s Store) ([]util.Uint256, error) { func HeaderHashes(s Store) ([]util.Uint256, error) {
@ -56,19 +63,17 @@ func HeaderHashes(s Store) ([]util.Uint256, error) {
}) })
var ( var (
i = 0 hashes []util.Uint256
sortedKeys = make([]int, len(hashMap)) sortedKeys = make([]uint32, 0, len(hashMap))
) )
for k, _ := range hashMap { for k := range hashMap {
sortedKeys[i] = int(k) sortedKeys = append(sortedKeys, k)
i++
} }
sort.Ints(sortedKeys) sort.Sort(uint32Slice(sortedKeys))
hashes := []util.Uint256{}
for _, key := range sortedKeys { for _, key := range sortedKeys {
values := hashMap[uint32(key)] values := hashMap[key]
for _, hash := range values { for _, hash := range values {
hashes = append(hashes, hash) hashes = append(hashes, hash)
} }

View file

@ -43,7 +43,7 @@ func (w *Witness) EncodeBinary(writer io.Writer) error {
// MarshalJSON implements the json marshaller interface. // MarshalJSON implements the json marshaller interface.
func (w *Witness) MarshalJSON() ([]byte, error) { func (w *Witness) MarshalJSON() ([]byte, error) {
data := map[string]interface{}{ data := map[string]string{
"invocation": hex.EncodeToString(w.InvocationScript), "invocation": hex.EncodeToString(w.InvocationScript),
"verification": hex.EncodeToString(w.VerificationScript), "verification": hex.EncodeToString(w.VerificationScript),
} }

View file

@ -83,18 +83,21 @@ func NewClient(ctx context.Context, endpoint string, opts ClientOptions) (*Clien
} }
func (c *Client) performRequest(method string, p params, v interface{}) error { func (c *Client) performRequest(method string, p params, v interface{}) error {
r := request{ var (
JSONRPC: c.version, r = request{
Method: method, JSONRPC: c.version,
Params: p.values, Method: method,
ID: 1, Params: p.values,
} ID: 1,
}
buf = new(bytes.Buffer)
)
b, err := json.Marshal(r) if err := json.NewEncoder(buf).Encode(r); err != nil {
if err != nil {
return err return err
} }
req, err := http.NewRequest("POST", c.endpoint.String(), bytes.NewReader(b))
req, err := http.NewRequest("POST", c.endpoint.String(), buf)
if err != nil { if err != nil {
return err return err
} }

View file

@ -1,7 +1,6 @@
package util package util
import ( import (
"bytes"
"encoding/json" "encoding/json"
"errors" "errors"
"strconv" "strconv"
@ -20,7 +19,7 @@ type Fixed8 int64
// String implements the Stringer interface. // String implements the Stringer interface.
func (f Fixed8) String() string { func (f Fixed8) String() string {
buf := new(bytes.Buffer) buf := new(strings.Builder)
val := int64(f) val := int64(f)
if val < 0 { if val < 0 {
buf.WriteRune('-') buf.WriteRune('-')
@ -54,20 +53,23 @@ func NewFixed8(val int) Fixed8 {
// with precision up to 10^-8 // with precision up to 10^-8
func Fixed8DecodeString(s string) (Fixed8, error) { func Fixed8DecodeString(s string) (Fixed8, error) {
parts := strings.SplitN(s, ".", 2) parts := strings.SplitN(s, ".", 2)
ip, err := strconv.Atoi(parts[0]) ip, err := strconv.ParseInt(parts[0], 10, 64)
if err != nil { if err != nil {
return 0, errInvalidString return 0, errInvalidString
} else if len(parts) == 1 { } else if len(parts) == 1 {
return NewFixed8(ip), nil return Fixed8(ip * decimals), nil
} }
fp, err := strconv.Atoi(parts[1]) fp, err := strconv.ParseInt(parts[1], 10, 64)
if err != nil || fp >= decimals { if err != nil || fp >= decimals {
return 0, errInvalidString return 0, errInvalidString
} }
for i := len(parts[1]); i < precision; i++ { for i := len(parts[1]); i < precision; i++ {
fp *= 10 fp *= 10
} }
if ip < 0 {
return Fixed8(ip*decimals - fp), nil
}
return Fixed8(ip*decimals + fp), nil return Fixed8(ip*decimals + fp), nil
} }
@ -91,3 +93,8 @@ func (f *Fixed8) UnmarshalJSON(data []byte) error {
*f = Fixed8(decimals * fl) *f = Fixed8(decimals * fl)
return nil return nil
} }
// MarshalJSON implements the json marshaller interface.
func (f Fixed8) MarshalJSON() ([]byte, error) {
return []byte(`"` + f.String() + `"`), nil
}

View file

@ -2,6 +2,7 @@ package util
import ( import (
"encoding/json" "encoding/json"
"strconv"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -39,19 +40,25 @@ func TestFixed8DecodeString(t *testing.T) {
} }
func TestFixed8UnmarshalJSON(t *testing.T) { func TestFixed8UnmarshalJSON(t *testing.T) {
fl := float64(123.45) var testCases = []float64{
str := "123.45" 123.45,
expected, _ := Fixed8DecodeString(str) -123.45,
}
// UnmarshalJSON should decode floats for _, fl := range testCases {
var u1 Fixed8 str := strconv.FormatFloat(fl, 'g', -1, 64)
s, _ := json.Marshal(fl) expected, _ := Fixed8DecodeString(str)
assert.Nil(t, json.Unmarshal(s, &u1))
assert.Equal(t, expected, u1)
// UnmarshalJSON should decode strings // UnmarshalJSON should decode floats
var u2 Fixed8 var u1 Fixed8
s, _ = json.Marshal(str) s, _ := json.Marshal(fl)
assert.Nil(t, json.Unmarshal(s, &u2)) assert.Nil(t, json.Unmarshal(s, &u1))
assert.Equal(t, expected, u2) assert.Equal(t, expected, u1)
// UnmarshalJSON should decode strings
var u2 Fixed8
s, _ = json.Marshal(str)
assert.Nil(t, json.Unmarshal(s, &u2))
assert.Equal(t, expected, u2)
}
} }

View file

@ -19,24 +19,22 @@ import (
func ReadVarUint(r io.Reader) uint64 { func ReadVarUint(r io.Reader) uint64 {
var b uint8 var b uint8
binary.Read(r, binary.LittleEndian, &b) binary.Read(r, binary.LittleEndian, &b)
switch b {
if b == 0xfd { case 0xfd:
var v uint16 var v uint16
binary.Read(r, binary.LittleEndian, &v) binary.Read(r, binary.LittleEndian, &v)
return uint64(v) return uint64(v)
} case 0xfe:
if b == 0xfe {
var v uint32 var v uint32
binary.Read(r, binary.LittleEndian, &v) binary.Read(r, binary.LittleEndian, &v)
return uint64(v) return uint64(v)
} case 0xff:
if b == 0xff {
var v uint64 var v uint64
binary.Read(r, binary.LittleEndian, &v) binary.Read(r, binary.LittleEndian, &v)
return v return v
default:
return uint64(b)
} }
return uint64(b)
} }
// WriteVarUint writes a variable unsigned integer. // WriteVarUint writes a variable unsigned integer.
@ -45,24 +43,26 @@ func WriteVarUint(w io.Writer, val uint64) error {
return errors.New("value out of range") return errors.New("value out of range")
} }
if val < 0xfd { if val < 0xfd {
binary.Write(w, binary.LittleEndian, uint8(val)) return binary.Write(w, binary.LittleEndian, uint8(val))
return nil
} }
if val < 0xFFFF { if val < 0xFFFF {
binary.Write(w, binary.LittleEndian, byte(0xfd)) if err := binary.Write(w, binary.LittleEndian, byte(0xfd)); err != nil {
binary.Write(w, binary.LittleEndian, uint16(val)) return err
return nil }
return binary.Write(w, binary.LittleEndian, uint16(val))
} }
if val < 0xFFFFFFFF { if val < 0xFFFFFFFF {
binary.Write(w, binary.LittleEndian, byte(0xfe)) if err := binary.Write(w, binary.LittleEndian, byte(0xfe)); err != nil {
binary.Write(w, binary.LittleEndian, uint32(val)) return err
return nil }
return binary.Write(w, binary.LittleEndian, uint32(val))
} }
binary.Write(w, binary.LittleEndian, byte(0xff)) if err := binary.Write(w, binary.LittleEndian, byte(0xff)); err != nil {
binary.Write(w, binary.LittleEndian, val) return err
}
return nil return binary.Write(w, binary.LittleEndian, val)
} }
// ReadVarBytes reads a variable length byte array. // ReadVarBytes reads a variable length byte array.

View file

@ -16,7 +16,8 @@ const uint160Size = 20
type Uint160 [uint160Size]uint8 type Uint160 [uint160Size]uint8
// Uint160DecodeString attempts to decode the given string into an Uint160. // Uint160DecodeString attempts to decode the given string into an Uint160.
func Uint160DecodeString(s string) (u Uint160, err error) { func Uint160DecodeString(s string) (Uint160, error) {
var u Uint160
if len(s) != uint160Size*2 { if len(s) != uint160Size*2 {
return u, fmt.Errorf("expected string size of %d got %d", uint160Size*2, len(s)) return u, fmt.Errorf("expected string size of %d got %d", uint160Size*2, len(s))
} }
@ -51,11 +52,7 @@ func Uint160FromScript(script []byte) (u Uint160, err error) {
// Bytes returns the byte slice representation of u. // Bytes returns the byte slice representation of u.
func (u Uint160) Bytes() []byte { func (u Uint160) Bytes() []byte {
b := make([]byte, uint160Size) return u[:]
for i := 0; i < uint160Size; i++ {
b[i] = byte(u[i])
}
return b
} }
// BytesReverse return a reversed byte representation of u. // BytesReverse return a reversed byte representation of u.
@ -70,12 +67,7 @@ func (u Uint160) String() string {
// Equals returns true if both Uint256 values are the same. // Equals returns true if both Uint256 values are the same.
func (u Uint160) Equals(other Uint160) bool { func (u Uint160) Equals(other Uint160) bool {
for i := 0; i < uint160Size; i++ { return u == other
if u[i] != other[i] {
return false
}
}
return true
} }
// UnmarshalJSON implements the json unmarshaller interface. // UnmarshalJSON implements the json unmarshaller interface.
@ -93,7 +85,5 @@ func (u *Uint160) UnmarshalJSON(data []byte) (err error) {
// MarshalJSON implements the json marshaller interface. // MarshalJSON implements the json marshaller interface.
func (u Uint160) MarshalJSON() ([]byte, error) { func (u Uint160) MarshalJSON() ([]byte, error) {
return json.Marshal( return []byte(`"0x` + u.String() + `"`), nil
fmt.Sprintf("0x%s", hex.EncodeToString(ArrayReverse(u.Bytes()))),
)
} }

View file

@ -2,7 +2,6 @@ package util
import ( import (
"encoding/hex" "encoding/hex"
"encoding/json"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -10,19 +9,29 @@ import (
func TestUint160UnmarshalJSON(t *testing.T) { func TestUint160UnmarshalJSON(t *testing.T) {
str := "2d3b96ae1bcc5a585e075e3b81920210dec16302" str := "2d3b96ae1bcc5a585e075e3b81920210dec16302"
expected, _ := Uint160DecodeString(str) expected, err := Uint160DecodeString(str)
if err != nil {
t.Fatal(err)
}
// UnmarshalJSON should decode hex-strings // UnmarshalJSON should decode hex-strings
var u1 Uint160 var u1, u2 Uint160
s, _ := json.Marshal(str)
assert.Nil(t, json.Unmarshal(s, &u1)) if err = u1.UnmarshalJSON([]byte(`"` + str + `"`)); err != nil {
t.Fatal(err)
}
assert.True(t, expected.Equals(u1)) assert.True(t, expected.Equals(u1))
s, err := expected.MarshalJSON()
if err != nil {
t.Fatal(err)
}
// UnmarshalJSON should decode hex-strings prefixed by 0x // UnmarshalJSON should decode hex-strings prefixed by 0x
var u2 Uint160 if err = u2.UnmarshalJSON(s); err != nil {
s, _ = json.Marshal("0x" + str) t.Fatal(err)
assert.Nil(t, json.Unmarshal(s, &u2)) }
assert.True(t, expected.Equals(u2)) assert.True(t, expected.Equals(u1))
} }
func TestUInt160DecodeString(t *testing.T) { func TestUInt160DecodeString(t *testing.T) {

View file

@ -38,11 +38,7 @@ func Uint256DecodeBytes(b []byte) (u Uint256, err error) {
// Bytes returns a byte slice representation of u. // Bytes returns a byte slice representation of u.
func (u Uint256) Bytes() []byte { func (u Uint256) Bytes() []byte {
b := make([]byte, uint256Size) return u[:]
for i := 0; i < uint256Size; i++ {
b[i] = byte(u[i])
}
return b
} }
// BytesReverse return a reversed byte representation of u. // BytesReverse return a reversed byte representation of u.
@ -52,7 +48,7 @@ func (u Uint256) BytesReverse() []byte {
// Equals returns true if both Uint256 values are the same. // Equals returns true if both Uint256 values are the same.
func (u Uint256) Equals(other Uint256) bool { func (u Uint256) Equals(other Uint256) bool {
return u.String() == other.String() return u == other
} }
// String implements the stringer interface. // String implements the stringer interface.
@ -75,5 +71,5 @@ func (u *Uint256) UnmarshalJSON(data []byte) (err error) {
// MarshalJSON implements the json marshaller interface. // MarshalJSON implements the json marshaller interface.
func (u Uint256) MarshalJSON() ([]byte, error) { func (u Uint256) MarshalJSON() ([]byte, error) {
return json.Marshal(fmt.Sprintf("0x%s", u.String())) return []byte(`"0x` + u.String() + `"`), nil
} }

View file

@ -2,7 +2,6 @@ package util
import ( import (
"encoding/hex" "encoding/hex"
"encoding/json"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -10,19 +9,29 @@ import (
func TestUint256UnmarshalJSON(t *testing.T) { func TestUint256UnmarshalJSON(t *testing.T) {
str := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d" str := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"
expected, _ := Uint256DecodeString(str) expected, err := Uint256DecodeString(str)
if err != nil {
t.Fatal(err)
}
// UnmarshalJSON should decode hex-strings // UnmarshalJSON should decode hex-strings
var u1 Uint256 var u1, u2 Uint256
s, _ := json.Marshal(str)
assert.Nil(t, json.Unmarshal(s, &u1)) if err = u1.UnmarshalJSON([]byte(`"` + str + `"`)); err != nil {
t.Fatal(err)
}
assert.True(t, expected.Equals(u1)) assert.True(t, expected.Equals(u1))
s, err := expected.MarshalJSON()
if err != nil {
t.Fatal(err)
}
// UnmarshalJSON should decode hex-strings prefixed by 0x // UnmarshalJSON should decode hex-strings prefixed by 0x
var u2 Uint256 if err = u2.UnmarshalJSON(s); err != nil {
s, _ = json.Marshal("0x" + str) t.Fatal(err)
assert.Nil(t, json.Unmarshal(s, &u2)) }
assert.True(t, expected.Equals(u2)) assert.True(t, expected.Equals(u1))
} }
func TestUint256DecodeString(t *testing.T) { func TestUint256DecodeString(t *testing.T) {

View file

@ -10,14 +10,12 @@ type stackItem struct {
} }
func buildStackOutput(s *Stack) string { func buildStackOutput(s *Stack) string {
items := make([]stackItem, s.Len()) items := make([]stackItem, 0, s.Len())
i := 0
s.Iter(func(e *Element) { s.Iter(func(e *Element) {
items[i] = stackItem{ items = append(items, stackItem{
Value: e.value, Value: e.value,
Type: e.value.String(), Type: e.value.String(),
} })
i++
}) })
b, _ := json.MarshalIndent(items, "", " ") b, _ := json.MarshalIndent(items, "", " ")