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
}
// 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
// the given underlying Store.
func HeaderHashes(s Store) ([]util.Uint256, error) {
@ -56,19 +63,17 @@ func HeaderHashes(s Store) ([]util.Uint256, error) {
})
var (
i = 0
sortedKeys = make([]int, len(hashMap))
hashes []util.Uint256
sortedKeys = make([]uint32, 0, len(hashMap))
)
for k, _ := range hashMap {
sortedKeys[i] = int(k)
i++
for k := range hashMap {
sortedKeys = append(sortedKeys, k)
}
sort.Ints(sortedKeys)
sort.Sort(uint32Slice(sortedKeys))
hashes := []util.Uint256{}
for _, key := range sortedKeys {
values := hashMap[uint32(key)]
values := hashMap[key]
for _, hash := range values {
hashes = append(hashes, hash)
}

View file

@ -43,7 +43,7 @@ func (w *Witness) EncodeBinary(writer io.Writer) error {
// MarshalJSON implements the json marshaller interface.
func (w *Witness) MarshalJSON() ([]byte, error) {
data := map[string]interface{}{
data := map[string]string{
"invocation": hex.EncodeToString(w.InvocationScript),
"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 {
r := request{
JSONRPC: c.version,
Method: method,
Params: p.values,
ID: 1,
}
var (
r = request{
JSONRPC: c.version,
Method: method,
Params: p.values,
ID: 1,
}
buf = new(bytes.Buffer)
)
b, err := json.Marshal(r)
if err != nil {
if err := json.NewEncoder(buf).Encode(r); err != nil {
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 {
return err
}

View file

@ -1,7 +1,6 @@
package util
import (
"bytes"
"encoding/json"
"errors"
"strconv"
@ -20,7 +19,7 @@ type Fixed8 int64
// String implements the Stringer interface.
func (f Fixed8) String() string {
buf := new(bytes.Buffer)
buf := new(strings.Builder)
val := int64(f)
if val < 0 {
buf.WriteRune('-')
@ -54,20 +53,23 @@ func NewFixed8(val int) Fixed8 {
// with precision up to 10^-8
func Fixed8DecodeString(s string) (Fixed8, error) {
parts := strings.SplitN(s, ".", 2)
ip, err := strconv.Atoi(parts[0])
ip, err := strconv.ParseInt(parts[0], 10, 64)
if err != nil {
return 0, errInvalidString
} 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 {
return 0, errInvalidString
}
for i := len(parts[1]); i < precision; i++ {
fp *= 10
}
if ip < 0 {
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)
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 (
"encoding/json"
"strconv"
"testing"
"github.com/stretchr/testify/assert"
@ -39,19 +40,25 @@ func TestFixed8DecodeString(t *testing.T) {
}
func TestFixed8UnmarshalJSON(t *testing.T) {
fl := float64(123.45)
str := "123.45"
expected, _ := Fixed8DecodeString(str)
var testCases = []float64{
123.45,
-123.45,
}
// UnmarshalJSON should decode floats
var u1 Fixed8
s, _ := json.Marshal(fl)
assert.Nil(t, json.Unmarshal(s, &u1))
assert.Equal(t, expected, u1)
for _, fl := range testCases {
str := strconv.FormatFloat(fl, 'g', -1, 64)
expected, _ := Fixed8DecodeString(str)
// UnmarshalJSON should decode strings
var u2 Fixed8
s, _ = json.Marshal(str)
assert.Nil(t, json.Unmarshal(s, &u2))
assert.Equal(t, expected, u2)
// UnmarshalJSON should decode floats
var u1 Fixed8
s, _ := json.Marshal(fl)
assert.Nil(t, json.Unmarshal(s, &u1))
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 {
var b uint8
binary.Read(r, binary.LittleEndian, &b)
if b == 0xfd {
switch b {
case 0xfd:
var v uint16
binary.Read(r, binary.LittleEndian, &v)
return uint64(v)
}
if b == 0xfe {
case 0xfe:
var v uint32
binary.Read(r, binary.LittleEndian, &v)
return uint64(v)
}
if b == 0xff {
case 0xff:
var v uint64
binary.Read(r, binary.LittleEndian, &v)
return v
default:
return uint64(b)
}
return uint64(b)
}
// 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")
}
if val < 0xfd {
binary.Write(w, binary.LittleEndian, uint8(val))
return nil
return binary.Write(w, binary.LittleEndian, uint8(val))
}
if val < 0xFFFF {
binary.Write(w, binary.LittleEndian, byte(0xfd))
binary.Write(w, binary.LittleEndian, uint16(val))
return nil
if err := binary.Write(w, binary.LittleEndian, byte(0xfd)); err != nil {
return err
}
return binary.Write(w, binary.LittleEndian, uint16(val))
}
if val < 0xFFFFFFFF {
binary.Write(w, binary.LittleEndian, byte(0xfe))
binary.Write(w, binary.LittleEndian, uint32(val))
return nil
if err := binary.Write(w, binary.LittleEndian, byte(0xfe)); err != nil {
return err
}
return binary.Write(w, binary.LittleEndian, uint32(val))
}
binary.Write(w, binary.LittleEndian, byte(0xff))
binary.Write(w, binary.LittleEndian, val)
if err := binary.Write(w, binary.LittleEndian, byte(0xff)); err != nil {
return err
}
return nil
return binary.Write(w, binary.LittleEndian, val)
}
// ReadVarBytes reads a variable length byte array.

View file

@ -16,7 +16,8 @@ const uint160Size = 20
type Uint160 [uint160Size]uint8
// 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 {
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.
func (u Uint160) Bytes() []byte {
b := make([]byte, uint160Size)
for i := 0; i < uint160Size; i++ {
b[i] = byte(u[i])
}
return b
return 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.
func (u Uint160) Equals(other Uint160) bool {
for i := 0; i < uint160Size; i++ {
if u[i] != other[i] {
return false
}
}
return true
return u == other
}
// UnmarshalJSON implements the json unmarshaller interface.
@ -93,7 +85,5 @@ func (u *Uint160) UnmarshalJSON(data []byte) (err error) {
// MarshalJSON implements the json marshaller interface.
func (u Uint160) MarshalJSON() ([]byte, error) {
return json.Marshal(
fmt.Sprintf("0x%s", hex.EncodeToString(ArrayReverse(u.Bytes()))),
)
return []byte(`"0x` + u.String() + `"`), nil
}

View file

@ -2,7 +2,6 @@ package util
import (
"encoding/hex"
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
@ -10,19 +9,29 @@ import (
func TestUint160UnmarshalJSON(t *testing.T) {
str := "2d3b96ae1bcc5a585e075e3b81920210dec16302"
expected, _ := Uint160DecodeString(str)
expected, err := Uint160DecodeString(str)
if err != nil {
t.Fatal(err)
}
// UnmarshalJSON should decode hex-strings
var u1 Uint160
s, _ := json.Marshal(str)
assert.Nil(t, json.Unmarshal(s, &u1))
var u1, u2 Uint160
if err = u1.UnmarshalJSON([]byte(`"` + str + `"`)); err != nil {
t.Fatal(err)
}
assert.True(t, expected.Equals(u1))
s, err := expected.MarshalJSON()
if err != nil {
t.Fatal(err)
}
// UnmarshalJSON should decode hex-strings prefixed by 0x
var u2 Uint160
s, _ = json.Marshal("0x" + str)
assert.Nil(t, json.Unmarshal(s, &u2))
assert.True(t, expected.Equals(u2))
if err = u2.UnmarshalJSON(s); err != nil {
t.Fatal(err)
}
assert.True(t, expected.Equals(u1))
}
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.
func (u Uint256) Bytes() []byte {
b := make([]byte, uint256Size)
for i := 0; i < uint256Size; i++ {
b[i] = byte(u[i])
}
return b
return 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.
func (u Uint256) Equals(other Uint256) bool {
return u.String() == other.String()
return u == other
}
// String implements the stringer interface.
@ -75,5 +71,5 @@ func (u *Uint256) UnmarshalJSON(data []byte) (err error) {
// MarshalJSON implements the json marshaller interface.
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 (
"encoding/hex"
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
@ -10,19 +9,29 @@ import (
func TestUint256UnmarshalJSON(t *testing.T) {
str := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"
expected, _ := Uint256DecodeString(str)
expected, err := Uint256DecodeString(str)
if err != nil {
t.Fatal(err)
}
// UnmarshalJSON should decode hex-strings
var u1 Uint256
s, _ := json.Marshal(str)
assert.Nil(t, json.Unmarshal(s, &u1))
var u1, u2 Uint256
if err = u1.UnmarshalJSON([]byte(`"` + str + `"`)); err != nil {
t.Fatal(err)
}
assert.True(t, expected.Equals(u1))
s, err := expected.MarshalJSON()
if err != nil {
t.Fatal(err)
}
// UnmarshalJSON should decode hex-strings prefixed by 0x
var u2 Uint256
s, _ = json.Marshal("0x" + str)
assert.Nil(t, json.Unmarshal(s, &u2))
assert.True(t, expected.Equals(u2))
if err = u2.UnmarshalJSON(s); err != nil {
t.Fatal(err)
}
assert.True(t, expected.Equals(u1))
}
func TestUint256DecodeString(t *testing.T) {

View file

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