io: move BinReader/BinWriter there, redo Serializable with it

The logic here is that we'll have all binary encoding/decoding done via our io
package, which simplifies error handling. This functionality doesn't belong to
util, so it's moved.

This also expands BufBinWriter with Reset() method to fit the needs of core
package.
This commit is contained in:
Roman Khimov 2019-09-16 12:18:13 +03:00
parent f01354b5bd
commit 5bf00db2c9
68 changed files with 446 additions and 501 deletions

View file

@ -1,12 +1,11 @@
package core package core
import ( import (
"bytes"
"fmt" "fmt"
"io"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -21,7 +20,7 @@ func (a Accounts) getAndUpdate(s storage.Store, hash util.Uint160) (*AccountStat
account := &AccountState{} account := &AccountState{}
key := storage.AppendPrefix(storage.STAccount, hash.Bytes()) key := storage.AppendPrefix(storage.STAccount, hash.Bytes())
if b, err := s.Get(key); err == nil { if b, err := s.Get(key); err == nil {
if err := account.DecodeBinary(bytes.NewReader(b)); err != nil { if err := account.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil {
return nil, fmt.Errorf("failed to decode (AccountState): %s", err) return nil, fmt.Errorf("failed to decode (AccountState): %s", err)
} }
} else { } else {
@ -34,9 +33,9 @@ func (a Accounts) getAndUpdate(s storage.Store, hash util.Uint160) (*AccountStat
// commit writes all account states to the given Batch. // commit writes all account states to the given Batch.
func (a Accounts) commit(b storage.Batch) error { func (a Accounts) commit(b storage.Batch) error {
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
for hash, state := range a { for hash, state := range a {
if err := state.EncodeBinary(buf); err != nil { if err := state.EncodeBinary(buf.BinWriter); err != nil {
return err return err
} }
key := storage.AppendPrefix(storage.STAccount, hash.Bytes()) key := storage.AppendPrefix(storage.STAccount, hash.Bytes())
@ -66,9 +65,8 @@ func NewAccountState(scriptHash util.Uint160) *AccountState {
} }
} }
// DecodeBinary decodes AccountState from the given io.Reader. // DecodeBinary decodes AccountState from the given BinReader.
func (s *AccountState) DecodeBinary(r io.Reader) error { func (s *AccountState) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
br.ReadLE(&s.Version) br.ReadLE(&s.Version)
br.ReadLE(&s.ScriptHash) br.ReadLE(&s.ScriptHash)
br.ReadLE(&s.IsFrozen) br.ReadLE(&s.IsFrozen)
@ -76,7 +74,7 @@ func (s *AccountState) DecodeBinary(r io.Reader) error {
s.Votes = make([]*keys.PublicKey, lenVotes) s.Votes = make([]*keys.PublicKey, lenVotes)
for i := 0; i < int(lenVotes); i++ { for i := 0; i < int(lenVotes); i++ {
s.Votes[i] = &keys.PublicKey{} s.Votes[i] = &keys.PublicKey{}
if err := s.Votes[i].DecodeBinary(r); err != nil { if err := s.Votes[i].DecodeBinary(br); err != nil {
return err return err
} }
} }
@ -94,15 +92,14 @@ func (s *AccountState) DecodeBinary(r io.Reader) error {
return br.Err return br.Err
} }
// EncodeBinary encode AccountState to the given io.Writer. // EncodeBinary encodes AccountState to the given BinWriter.
func (s *AccountState) EncodeBinary(w io.Writer) error { func (s *AccountState) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteLE(s.Version) bw.WriteLE(s.Version)
bw.WriteLE(s.ScriptHash) bw.WriteLE(s.ScriptHash)
bw.WriteLE(s.IsFrozen) bw.WriteLE(s.IsFrozen)
bw.WriteVarUint(uint64(len(s.Votes))) bw.WriteVarUint(uint64(len(s.Votes)))
for _, point := range s.Votes { for _, point := range s.Votes {
if err := point.EncodeBinary(w); err != nil { if err := point.EncodeBinary(bw); err != nil {
return err return err
} }
} }

View file

@ -1,10 +1,10 @@
package core package core
import ( import (
"bytes"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -30,13 +30,13 @@ func TestDecodeEncodeAccountState(t *testing.T) {
Balances: balances, Balances: balances,
} }
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
if err := a.EncodeBinary(buf); err != nil { if err := a.EncodeBinary(buf.BinWriter); err != nil {
t.Fatal(err) t.Fatal(err)
} }
aDecode := &AccountState{} aDecode := &AccountState{}
if err := aDecode.DecodeBinary(buf); err != nil { if err := aDecode.DecodeBinary(io.NewBinReaderFromBuf(buf.Bytes())); err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -1,12 +1,10 @@
package core package core
import ( import (
"bytes"
"io"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"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/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -16,9 +14,9 @@ const feeMode = 0x0
type Assets map[util.Uint256]*AssetState type Assets map[util.Uint256]*AssetState
func (a Assets) commit(b storage.Batch) error { func (a Assets) commit(b storage.Batch) error {
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
for hash, state := range a { for hash, state := range a {
if err := state.EncodeBinary(buf); err != nil { if err := state.EncodeBinary(buf.BinWriter); err != nil {
return err return err
} }
key := storage.AppendPrefix(storage.STAsset, hash.Bytes()) key := storage.AppendPrefix(storage.STAsset, hash.Bytes())
@ -46,8 +44,7 @@ type AssetState struct {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (a *AssetState) DecodeBinary(r io.Reader) error { func (a *AssetState) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
br.ReadLE(&a.ID) br.ReadLE(&a.ID)
br.ReadLE(&a.AssetType) br.ReadLE(&a.AssetType)
@ -63,7 +60,7 @@ func (a *AssetState) DecodeBinary(r io.Reader) error {
return br.Err return br.Err
} }
a.Owner = &keys.PublicKey{} a.Owner = &keys.PublicKey{}
if err := a.Owner.DecodeBinary(r); err != nil { if err := a.Owner.DecodeBinary(br); err != nil {
return err return err
} }
br.ReadLE(&a.Admin) br.ReadLE(&a.Admin)
@ -75,8 +72,7 @@ func (a *AssetState) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (a *AssetState) EncodeBinary(w io.Writer) error { func (a *AssetState) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteLE(a.ID) bw.WriteLE(a.ID)
bw.WriteLE(a.AssetType) bw.WriteLE(a.AssetType)
bw.WriteString(a.Name) bw.WriteString(a.Name)
@ -89,7 +85,7 @@ func (a *AssetState) EncodeBinary(w io.Writer) error {
if bw.Err != nil { if bw.Err != nil {
return bw.Err return bw.Err
} }
if err := a.Owner.EncodeBinary(w); err != nil { if err := a.Owner.EncodeBinary(bw); err != nil {
return err return err
} }
bw.WriteLE(a.Admin) bw.WriteLE(a.Admin)

View file

@ -1,11 +1,11 @@
package core package core
import ( import (
"bytes"
"testing" "testing"
"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/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -26,9 +26,9 @@ func TestEncodeDecodeAssetState(t *testing.T) {
IsFrozen: false, IsFrozen: false,
} }
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
assert.Nil(t, asset.EncodeBinary(buf)) assert.Nil(t, asset.EncodeBinary(buf.BinWriter))
assetDecode := &AssetState{} assetDecode := &AssetState{}
assert.Nil(t, assetDecode.DecodeBinary(buf)) assert.Nil(t, assetDecode.DecodeBinary(io.NewBinReaderFromBuf(buf.Bytes())))
assert.Equal(t, asset, assetDecode) assert.Equal(t, asset, assetDecode)
} }

View file

@ -1,11 +1,9 @@
package core package core
import ( import (
"bytes"
"io"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@ -73,12 +71,11 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) {
Trimmed: true, Trimmed: true,
} }
r := bytes.NewReader(b) br := io.NewBinReaderFromBuf(b)
if err := block.decodeHashableFields(r); err != nil { if err := block.decodeHashableFields(br); err != nil {
return block, err return block, err
} }
br := util.NewBinReaderFromIO(r)
var padding uint8 var padding uint8
br.ReadLE(&padding) br.ReadLE(&padding)
if br.Err != nil { if br.Err != nil {
@ -86,7 +83,7 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) {
} }
block.Script = &transaction.Witness{} block.Script = &transaction.Witness{}
if err := block.Script.DecodeBinary(r); err != nil { if err := block.Script.DecodeBinary(br); err != nil {
return block, err return block, err
} }
@ -105,36 +102,34 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) {
// in storage. // in storage.
// Notice that only the hashes of the transactions are stored. // Notice that only the hashes of the transactions are stored.
func (b *Block) Trim() ([]byte, error) { func (b *Block) Trim() ([]byte, error) {
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
if err := b.encodeHashableFields(buf); err != nil { if err := b.encodeHashableFields(buf.BinWriter); err != nil {
return nil, err return nil, err
} }
bw := util.NewBinWriterFromIO(buf) buf.WriteLE(uint8(1))
bw.WriteLE(uint8(1)) if buf.Err != nil {
if bw.Err != nil { return nil, buf.Err
return nil, bw.Err
} }
if err := b.Script.EncodeBinary(buf); err != nil { if err := b.Script.EncodeBinary(buf.BinWriter); err != nil {
return nil, err return nil, err
} }
bw.WriteVarUint(uint64(len(b.Transactions))) buf.WriteVarUint(uint64(len(b.Transactions)))
for _, tx := range b.Transactions { for _, tx := range b.Transactions {
bw.WriteLE(tx.Hash()) buf.WriteLE(tx.Hash())
} }
if bw.Err != nil { if buf.Err != nil {
return nil, bw.Err return nil, buf.Err
} }
return buf.Bytes(), nil return buf.Bytes(), nil
} }
// DecodeBinary decodes the block from the given reader. // DecodeBinary decodes the block from the given reader.
func (b *Block) DecodeBinary(r io.Reader) error { func (b *Block) DecodeBinary(br *io.BinReader) error {
if err := b.BlockBase.DecodeBinary(r); err != nil { if err := b.BlockBase.DecodeBinary(br); err != nil {
return err return err
} }
br := util.NewBinReaderFromIO(r)
lentx := br.ReadVarUint() lentx := br.ReadVarUint()
if br.Err != nil { if br.Err != nil {
return br.Err return br.Err
@ -142,7 +137,7 @@ func (b *Block) DecodeBinary(r io.Reader) error {
b.Transactions = make([]*transaction.Transaction, lentx) b.Transactions = make([]*transaction.Transaction, lentx)
for i := 0; i < int(lentx); i++ { for i := 0; i < int(lentx); i++ {
b.Transactions[i] = &transaction.Transaction{} b.Transactions[i] = &transaction.Transaction{}
if err := b.Transactions[i].DecodeBinary(r); err != nil { if err := b.Transactions[i].DecodeBinary(br); err != nil {
return err return err
} }
} }
@ -151,18 +146,17 @@ func (b *Block) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary encodes the block to the given writer. // EncodeBinary encodes the block to the given writer.
func (b *Block) EncodeBinary(w io.Writer) error { func (b *Block) EncodeBinary(bw *io.BinWriter) error {
err := b.BlockBase.EncodeBinary(w) err := b.BlockBase.EncodeBinary(bw)
if err != nil { if err != nil {
return err return err
} }
bw := util.NewBinWriterFromIO(w)
bw.WriteVarUint(uint64(len(b.Transactions))) bw.WriteVarUint(uint64(len(b.Transactions)))
if bw.Err != nil { if bw.Err != nil {
return err return err
} }
for _, tx := range b.Transactions { for _, tx := range b.Transactions {
err := tx.EncodeBinary(w) err := tx.EncodeBinary(bw)
if err != nil { if err != nil {
return err return err
} }

View file

@ -1,12 +1,11 @@
package core package core
import ( import (
"bytes"
"fmt" "fmt"
"io"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -60,13 +59,12 @@ func (b *BlockBase) Hash() util.Uint256 {
} }
// DecodeBinary implements the payload interface. // DecodeBinary implements the payload interface.
func (b *BlockBase) DecodeBinary(r io.Reader) error { func (b *BlockBase) DecodeBinary(br *io.BinReader) error {
if err := b.decodeHashableFields(r); err != nil { if err := b.decodeHashableFields(br); err != nil {
return err return err
} }
var padding uint8 var padding uint8
br := util.NewBinReaderFromIO(r)
br.ReadLE(&padding) br.ReadLE(&padding)
if br.Err != nil { if br.Err != nil {
return br.Err return br.Err
@ -76,20 +74,19 @@ func (b *BlockBase) DecodeBinary(r io.Reader) error {
} }
b.Script = &transaction.Witness{} b.Script = &transaction.Witness{}
return b.Script.DecodeBinary(r) return b.Script.DecodeBinary(br)
} }
// EncodeBinary implements the Payload interface // EncodeBinary implements the Payload interface
func (b *BlockBase) EncodeBinary(w io.Writer) error { func (b *BlockBase) EncodeBinary(bw *io.BinWriter) error {
if err := b.encodeHashableFields(w); err != nil { if err := b.encodeHashableFields(bw); err != nil {
return err return err
} }
bw := util.NewBinWriterFromIO(w)
bw.WriteLE(uint8(1)) bw.WriteLE(uint8(1))
if bw.Err != nil { if bw.Err != nil {
return bw.Err return bw.Err
} }
return b.Script.EncodeBinary(w) return b.Script.EncodeBinary(bw)
} }
// createHash creates the hash of the block. // createHash creates the hash of the block.
@ -99,8 +96,8 @@ func (b *BlockBase) EncodeBinary(w io.Writer) error {
// Since MerkleRoot already contains the hash value of all transactions, // Since MerkleRoot already contains the hash value of all transactions,
// the modification of transaction will influence the hash value of the block. // the modification of transaction will influence the hash value of the block.
func (b *BlockBase) createHash() error { func (b *BlockBase) createHash() error {
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
if err := b.encodeHashableFields(buf); err != nil { if err := b.encodeHashableFields(buf.BinWriter); err != nil {
return err return err
} }
b.hash = hash.DoubleSha256(buf.Bytes()) b.hash = hash.DoubleSha256(buf.Bytes())
@ -110,8 +107,7 @@ func (b *BlockBase) createHash() error {
// encodeHashableFields will only encode the fields used for hashing. // encodeHashableFields will only encode the fields used for hashing.
// see Hash() for more information about the fields. // see Hash() for more information about the fields.
func (b *BlockBase) encodeHashableFields(w io.Writer) error { func (b *BlockBase) encodeHashableFields(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteLE(b.Version) bw.WriteLE(b.Version)
bw.WriteLE(b.PrevHash) bw.WriteLE(b.PrevHash)
bw.WriteLE(b.MerkleRoot) bw.WriteLE(b.MerkleRoot)
@ -124,8 +120,7 @@ func (b *BlockBase) encodeHashableFields(w io.Writer) error {
// decodeHashableFields will only decode the fields used for hashing. // decodeHashableFields will only decode the fields used for hashing.
// see Hash() for more information about the fields. // see Hash() for more information about the fields.
func (b *BlockBase) decodeHashableFields(r io.Reader) error { func (b *BlockBase) decodeHashableFields(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
br.ReadLE(&b.Version) br.ReadLE(&b.Version)
br.ReadLE(&b.PrevHash) br.ReadLE(&b.PrevHash)
br.ReadLE(&b.MerkleRoot) br.ReadLE(&b.MerkleRoot)

View file

@ -1,12 +1,12 @@
package core package core
import ( import (
"bytes"
"encoding/hex" "encoding/hex"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -24,7 +24,7 @@ func TestDecodeBlock1(t *testing.T) {
} }
block := &Block{} block := &Block{}
if err := block.DecodeBinary(bytes.NewReader(b)); err != nil { if err := block.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -109,7 +109,7 @@ func TestBinBlockDecodeEncode(t *testing.T) {
b := Block{} b := Block{}
r := bytes.NewReader(rawtxBytes) r := io.NewBinReaderFromBuf(rawtxBytes)
err := b.DecodeBinary(r) err := b.DecodeBinary(r)
assert.Nil(t, err) assert.Nil(t, err)
expected := map[string]bool{ // 18 trans expected := map[string]bool{ // 18 trans
@ -165,9 +165,9 @@ func TestBinBlockDecodeEncode(t *testing.T) {
} }
assert.Equal(t, true, val) assert.Equal(t, true, val)
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
err = b.EncodeBinary(buf) err = b.EncodeBinary(buf.BinWriter)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes())) assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
@ -185,7 +185,7 @@ func TestBlockSizeCalculation(t *testing.T) {
b := Block{} b := Block{}
r := bytes.NewReader(rawBlockBytes) r := io.NewBinReaderFromBuf(rawBlockBytes)
err := b.DecodeBinary(r) err := b.DecodeBinary(r)
assert.Nil(t, err) assert.Nil(t, err)
@ -250,11 +250,12 @@ func TestBlockSizeCalculation(t *testing.T) {
assert.Equal(t, "552102486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a7021024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d2102aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e2103b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c2103b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a2102ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba5542102df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e89509357ae", hex.EncodeToString(b.Script.VerificationScript)) assert.Equal(t, "552102486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a7021024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d2102aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e2103b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c2103b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a2102ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba5542102df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e89509357ae", hex.EncodeToString(b.Script.VerificationScript))
assert.Equal(t, "0006d3ff96e269f599eb1b5c5a527c218439e498dcc65b63794591bbcdc0516b", b.Hash().ReverseString()) assert.Equal(t, "0006d3ff96e269f599eb1b5c5a527c218439e498dcc65b63794591bbcdc0516b", b.Hash().ReverseString())
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
err = b.EncodeBinary(buf) err = b.EncodeBinary(buf.BinWriter)
assert.Nil(t, err) assert.Nil(t, err)
benc := buf.Bytes()
// test size of the block // test size of the block
assert.Equal(t, 7360, buf.Len()) assert.Equal(t, 7360, len(benc))
assert.Equal(t, rawBlock, hex.EncodeToString(buf.Bytes())) assert.Equal(t, rawBlock, hex.EncodeToString(benc))
} }

View file

@ -1,9 +1,7 @@
package core package core
import ( import (
"bytes"
"context" "context"
"encoding/binary"
"fmt" "fmt"
"math" "math"
"sync/atomic" "sync/atomic"
@ -12,6 +10,7 @@ import (
"github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/config"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"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/util" "github.com/CityOfZion/neo-go/pkg/util"
"github.com/pkg/errors" "github.com/pkg/errors"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@ -243,9 +242,9 @@ func (bc *Blockchain) AddHeaders(headers ...*Header) (err error) {
func (bc *Blockchain) processHeader(h *Header, batch storage.Batch, headerList *HeaderHashList) error { func (bc *Blockchain) processHeader(h *Header, batch storage.Batch, headerList *HeaderHashList) error {
headerList.Add(h.Hash()) headerList.Add(h.Hash())
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
for int(h.Index)-headerBatchCount >= int(bc.storedHeaderCount) { for int(h.Index)-headerBatchCount >= int(bc.storedHeaderCount) {
if err := headerList.Write(buf, int(bc.storedHeaderCount), headerBatchCount); err != nil { if err := headerList.Write(buf.BinWriter, int(bc.storedHeaderCount), headerBatchCount); err != nil {
return err return err
} }
key := storage.AppendPrefixInt(storage.IXHeaderHashList, int(bc.storedHeaderCount)) key := storage.AppendPrefixInt(storage.IXHeaderHashList, int(bc.storedHeaderCount))
@ -255,7 +254,7 @@ func (bc *Blockchain) processHeader(h *Header, batch storage.Batch, headerList *
} }
buf.Reset() buf.Reset()
if err := h.EncodeBinary(buf); err != nil { if err := h.EncodeBinary(buf.BinWriter); err != nil {
return err return err
} }
@ -467,11 +466,12 @@ func (bc *Blockchain) GetTransaction(hash util.Uint256) (*transaction.Transactio
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }
r := bytes.NewReader(b) r := io.NewBinReaderFromBuf(b)
var height uint32 var height uint32
if err := binary.Read(r, binary.LittleEndian, &height); err != nil { r.ReadLE(&height)
return nil, 0, err if r.Err != nil {
return nil, 0, r.Err
} }
tx := &transaction.Transaction{} tx := &transaction.Transaction{}
@ -578,7 +578,7 @@ func (bc *Blockchain) GetAssetState(assetID util.Uint256) *AssetState {
var as *AssetState var as *AssetState
bc.Store.Seek(storage.STAsset.Bytes(), func(k, v []byte) { bc.Store.Seek(storage.STAsset.Bytes(), func(k, v []byte) {
var a AssetState var a AssetState
if err := a.DecodeBinary(bytes.NewReader(v)); err == nil && a.ID == assetID { if err := a.DecodeBinary(io.NewBinReaderFromBuf(v)); err == nil && a.ID == assetID {
as = &a as = &a
} }
}) })
@ -591,7 +591,7 @@ func (bc *Blockchain) GetAccountState(scriptHash util.Uint160) *AccountState {
var as *AccountState var as *AccountState
bc.Store.Seek(storage.STAccount.Bytes(), func(k, v []byte) { bc.Store.Seek(storage.STAccount.Bytes(), func(k, v []byte) {
var a AccountState var a AccountState
if err := a.DecodeBinary(bytes.NewReader(v)); err == nil && a.ScriptHash == scriptHash { if err := a.DecodeBinary(io.NewBinReaderFromBuf(v)); err == nil && a.ScriptHash == scriptHash {
as = &a as = &a
} }
}) })
@ -921,9 +921,10 @@ func (bc *Blockchain) VerifyWitnesses(t *transaction.Transaction) error {
} }
func hashAndIndexToBytes(h util.Uint256, index uint32) []byte { func hashAndIndexToBytes(h util.Uint256, index uint32) []byte {
buf := make([]byte, 4) buf := io.NewBufBinWriter()
binary.LittleEndian.PutUint32(buf, index) buf.WriteLE(h.BytesReverse())
return append(h.BytesReverse(), buf...) buf.WriteLE(index)
return buf.Bytes()
} }
func (bc *Blockchain) secondsPerBlock() int { func (bc *Blockchain) secondsPerBlock() int {

View file

@ -1,9 +1,9 @@
package core package core
import ( import (
"encoding/binary"
"fmt" "fmt"
"io"
"github.com/CityOfZion/neo-go/pkg/io"
) )
// Header holds the head info of a block. // Header holds the head info of a block.
@ -15,14 +15,15 @@ type Header struct {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (h *Header) DecodeBinary(r io.Reader) error { func (h *Header) DecodeBinary(r *io.BinReader) error {
if err := h.BlockBase.DecodeBinary(r); err != nil { if err := h.BlockBase.DecodeBinary(r); err != nil {
return err return err
} }
var padding uint8 var padding uint8
if err := binary.Read(r, binary.LittleEndian, &padding); err != nil { r.ReadLE(&padding)
return err if r.Err != nil {
return r.Err
} }
if padding != 0 { if padding != 0 {
@ -33,9 +34,8 @@ func (h *Header) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (h *Header) EncodeBinary(w io.Writer) error { func (h *Header) EncodeBinary(w *io.BinWriter) error {
if err := h.BlockBase.EncodeBinary(w); err != nil { h.BlockBase.EncodeBinary(w)
return err w.WriteLE(uint8(0))
} return w.Err
return binary.Write(w, binary.LittleEndian, uint8(0))
} }

View file

@ -1,8 +1,7 @@
package core package core
import ( import (
"io" "github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -56,10 +55,9 @@ func (l *HeaderHashList) Slice(start, end int) []util.Uint256 {
return l.hashes[start:end] return l.hashes[start:end]
} }
// WriteTo will write n underlying hashes to the given io.Writer // WriteTo will write n underlying hashes to the given BinWriter
// starting from start. // starting from start.
func (l *HeaderHashList) Write(w io.Writer, start, n int) error { func (l *HeaderHashList) Write(bw *io.BinWriter, start, n int) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteVarUint(uint64(n)) bw.WriteVarUint(uint64(n))
hashes := l.Slice(start, start+n) hashes := l.Slice(start, start+n)
for _, hash := range hashes { for _, hash := range hashes {

View file

@ -1,12 +1,12 @@
package core package core
import ( import (
"bytes"
"testing" "testing"
"time" "time"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -26,13 +26,13 @@ func TestHeaderEncodeDecode(t *testing.T) {
}, },
}} }}
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
if err := header.EncodeBinary(buf); err != nil { if err := header.EncodeBinary(buf.BinWriter); err != nil {
t.Fatal(err) t.Fatal(err)
} }
headerDecode := &Header{} headerDecode := &Header{}
if err := headerDecode.DecodeBinary(buf); err != nil { if err := headerDecode.DecodeBinary(io.NewBinReaderFromBuf(buf.Bytes())); err != nil {
t.Fatal(err) t.Fatal(err)
} }
assert.Equal(t, header.Version, headerDecode.Version, "expected both versions to be equal") assert.Equal(t, header.Version, headerDecode.Version, "expected both versions to be equal")

View file

@ -1,7 +1,6 @@
package core package core
import ( import (
"bytes"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -11,6 +10,7 @@ import (
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -63,7 +63,7 @@ func getDecodedBlock(t *testing.T, i int) *Block {
} }
block := &Block{} block := &Block{}
if err := block.DecodeBinary(bytes.NewReader(b)); err != nil { if err := block.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -1,11 +1,10 @@
package core package core
import ( import (
"bytes"
"fmt" "fmt"
"io"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -21,7 +20,7 @@ func (s SpentCoins) getAndUpdate(store storage.Store, hash util.Uint256) (*Spent
spent := &SpentCoinState{} spent := &SpentCoinState{}
key := storage.AppendPrefix(storage.STSpentCoin, hash.BytesReverse()) key := storage.AppendPrefix(storage.STSpentCoin, hash.BytesReverse())
if b, err := store.Get(key); err == nil { if b, err := store.Get(key); err == nil {
if err := spent.DecodeBinary(bytes.NewReader(b)); err != nil { if err := spent.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil {
return nil, fmt.Errorf("failed to decode (UnspentCoinState): %s", err) return nil, fmt.Errorf("failed to decode (UnspentCoinState): %s", err)
} }
} else { } else {
@ -35,9 +34,9 @@ func (s SpentCoins) getAndUpdate(store storage.Store, hash util.Uint256) (*Spent
} }
func (s SpentCoins) commit(b storage.Batch) error { func (s SpentCoins) commit(b storage.Batch) error {
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
for hash, state := range s { for hash, state := range s {
if err := state.EncodeBinary(buf); err != nil { if err := state.EncodeBinary(buf.BinWriter); err != nil {
return err return err
} }
key := storage.AppendPrefix(storage.STSpentCoin, hash.BytesReverse()) key := storage.AppendPrefix(storage.STSpentCoin, hash.BytesReverse())
@ -66,8 +65,7 @@ func NewSpentCoinState(hash util.Uint256, height uint32) *SpentCoinState {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (s *SpentCoinState) DecodeBinary(r io.Reader) error { func (s *SpentCoinState) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
br.ReadLE(&s.txHash) br.ReadLE(&s.txHash)
br.ReadLE(&s.txHeight) br.ReadLE(&s.txHeight)
@ -86,8 +84,7 @@ func (s *SpentCoinState) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (s *SpentCoinState) EncodeBinary(w io.Writer) error { func (s *SpentCoinState) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteLE(s.txHash) bw.WriteLE(s.txHash)
bw.WriteLE(s.txHeight) bw.WriteLE(s.txHeight)
bw.WriteVarUint(uint64(len(s.items))) bw.WriteVarUint(uint64(len(s.items)))

View file

@ -1,10 +1,10 @@
package core package core
import ( import (
"bytes"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -20,10 +20,10 @@ func TestEncodeDecodeSpentCoinState(t *testing.T) {
}, },
} }
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
assert.Nil(t, spent.EncodeBinary(buf)) assert.Nil(t, spent.EncodeBinary(buf.BinWriter))
spentDecode := new(SpentCoinState) spentDecode := new(SpentCoinState)
assert.Nil(t, spentDecode.DecodeBinary(buf)) assert.Nil(t, spentDecode.DecodeBinary(io.NewBinReaderFromBuf(buf.Bytes())))
assert.Equal(t, spent, spentDecode) assert.Equal(t, spent, spentDecode)
} }

View file

@ -5,6 +5,7 @@ import (
"encoding/binary" "encoding/binary"
"sort" "sort"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -84,7 +85,7 @@ func HeaderHashes(s Store) ([]util.Uint256, error) {
// the given byte array. // the given byte array.
func read2000Uint256Hashes(b []byte) ([]util.Uint256, error) { func read2000Uint256Hashes(b []byte) ([]util.Uint256, error) {
r := bytes.NewReader(b) r := bytes.NewReader(b)
br := util.NewBinReaderFromIO(r) br := io.NewBinReaderFromIO(r)
lenHashes := br.ReadVarUint() lenHashes := br.ReadVarUint()
hashes := make([]util.Uint256, lenHashes) hashes := make([]util.Uint256, lenHashes)
br.ReadLE(hashes) br.ReadLE(hashes)

View file

@ -4,8 +4,8 @@ import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -16,8 +16,7 @@ type Attribute struct {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (attr *Attribute) DecodeBinary(r io.Reader) error { func (attr *Attribute) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
br.ReadLE(&attr.Usage) br.ReadLE(&attr.Usage)
// very special case // very special case
@ -53,8 +52,7 @@ func (attr *Attribute) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (attr *Attribute) EncodeBinary(w io.Writer) error { func (attr *Attribute) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteLE(&attr.Usage) bw.WriteLE(&attr.Usage)
switch attr.Usage { switch attr.Usage {
case ECDH02, ECDH03: case ECDH02, ECDH03:

View file

@ -1,8 +1,7 @@
package transaction package transaction
import ( import (
"io" "github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -12,8 +11,7 @@ type ClaimTX struct {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (tx *ClaimTX) DecodeBinary(r io.Reader) error { func (tx *ClaimTX) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
lenClaims := br.ReadVarUint() lenClaims := br.ReadVarUint()
if br.Err != nil { if br.Err != nil {
return br.Err return br.Err
@ -21,7 +19,7 @@ func (tx *ClaimTX) DecodeBinary(r io.Reader) error {
tx.Claims = make([]*Input, lenClaims) tx.Claims = make([]*Input, lenClaims)
for i := 0; i < int(lenClaims); i++ { for i := 0; i < int(lenClaims); i++ {
tx.Claims[i] = &Input{} tx.Claims[i] = &Input{}
if err := tx.Claims[i].DecodeBinary(r); err != nil { if err := tx.Claims[i].DecodeBinary(br); err != nil {
return err return err
} }
} }
@ -29,14 +27,13 @@ func (tx *ClaimTX) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (tx *ClaimTX) EncodeBinary(w io.Writer) error { func (tx *ClaimTX) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteVarUint(uint64(len(tx.Claims))) bw.WriteVarUint(uint64(len(tx.Claims)))
if bw.Err != nil { if bw.Err != nil {
return bw.Err return bw.Err
} }
for _, claim := range tx.Claims { for _, claim := range tx.Claims {
if err := claim.EncodeBinary(w); err != nil { if err := claim.EncodeBinary(bw); err != nil {
return err return err
} }
} }

View file

@ -1,7 +1,7 @@
package transaction package transaction
import ( import (
"io" "github.com/CityOfZion/neo-go/pkg/io"
) )
// ContractTX represents a contract transaction. // ContractTX represents a contract transaction.
@ -16,12 +16,12 @@ func NewContractTX() *Transaction {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (tx *ContractTX) DecodeBinary(r io.Reader) error { func (tx *ContractTX) DecodeBinary(r *io.BinReader) error {
return nil return nil
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (tx *ContractTX) EncodeBinary(w io.Writer) error { func (tx *ContractTX) EncodeBinary(w *io.BinWriter) error {
return nil return nil
} }

View file

@ -1,10 +1,10 @@
package transaction package transaction
import ( import (
"bytes"
"encoding/hex" "encoding/hex"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -29,9 +29,9 @@ func TestEncodeDecodeContract(t *testing.T) {
assert.Equal(t, "bdf6cc3b9af12a7565bda80933a75ee8cef1bc771d0d58effc08e4c8b436da79", tx.Hash().ReverseString()) assert.Equal(t, "bdf6cc3b9af12a7565bda80933a75ee8cef1bc771d0d58effc08e4c8b436da79", tx.Hash().ReverseString())
// Encode // Encode
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
err := tx.EncodeBinary(buf) err := tx.EncodeBinary(buf.BinWriter)
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes())) assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
} }

View file

@ -1,9 +1,8 @@
package transaction package transaction
import ( import (
"io"
"github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/io"
) )
// EnrollmentTX transaction represents an enrollment form, which indicates // EnrollmentTX transaction represents an enrollment form, which indicates
@ -17,13 +16,13 @@ type EnrollmentTX struct {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (tx *EnrollmentTX) DecodeBinary(r io.Reader) error { func (tx *EnrollmentTX) DecodeBinary(r *io.BinReader) error {
tx.PublicKey = &keys.PublicKey{} tx.PublicKey = &keys.PublicKey{}
return tx.PublicKey.DecodeBinary(r) return tx.PublicKey.DecodeBinary(r)
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (tx *EnrollmentTX) EncodeBinary(w io.Writer) error { func (tx *EnrollmentTX) EncodeBinary(w *io.BinWriter) error {
return tx.PublicKey.EncodeBinary(w) return tx.PublicKey.EncodeBinary(w)
} }

View file

@ -1,10 +1,10 @@
package transaction package transaction
import ( import (
"bytes"
"encoding/hex" "encoding/hex"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -16,8 +16,8 @@ func TestEncodeDecodeEnrollment(t *testing.T) {
assert.IsType(t, tx.Data, &EnrollmentTX{}) assert.IsType(t, tx.Data, &EnrollmentTX{})
assert.Equal(t, 0, int(tx.Version)) assert.Equal(t, 0, int(tx.Version))
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
err := tx.EncodeBinary(buf) err := tx.EncodeBinary(buf.BinWriter)
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes())) assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))

View file

@ -1,10 +1,10 @@
package transaction package transaction
import ( import (
"bytes"
"encoding/hex" "encoding/hex"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -21,7 +21,7 @@ func decodeTransaction(rawTX string, t *testing.T) *Transaction {
b, err1 := hex.DecodeString(rawTX) b, err1 := hex.DecodeString(rawTX)
assert.Nil(t, err1) assert.Nil(t, err1)
tx := &Transaction{} tx := &Transaction{}
err2 := tx.DecodeBinary(bytes.NewReader(b)) err2 := tx.DecodeBinary(io.NewBinReaderFromBuf(b))
assert.Nil(t, err2) assert.Nil(t, err2)
return tx return tx
} }

View file

@ -1,8 +1,7 @@
package transaction package transaction
import ( import (
"io" "github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -16,16 +15,14 @@ type Input struct {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (in *Input) DecodeBinary(r io.Reader) error { func (in *Input) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
br.ReadLE(&in.PrevHash) br.ReadLE(&in.PrevHash)
br.ReadLE(&in.PrevIndex) br.ReadLE(&in.PrevIndex)
return br.Err return br.Err
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (in *Input) EncodeBinary(w io.Writer) error { func (in *Input) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteLE(in.PrevHash) bw.WriteLE(in.PrevHash)
bw.WriteLE(in.PrevIndex) bw.WriteLE(in.PrevIndex)
return bw.Err return bw.Err

View file

@ -1,8 +1,7 @@
package transaction package transaction
import ( import (
"io" "github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -33,8 +32,7 @@ func NewInvocationTX(script []byte) *Transaction {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (tx *InvocationTX) DecodeBinary(r io.Reader) error { func (tx *InvocationTX) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
tx.Script = br.ReadBytes() tx.Script = br.ReadBytes()
if tx.Version >= 1 { if tx.Version >= 1 {
br.ReadLE(&tx.Gas) br.ReadLE(&tx.Gas)
@ -45,8 +43,7 @@ func (tx *InvocationTX) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (tx *InvocationTX) EncodeBinary(w io.Writer) error { func (tx *InvocationTX) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteBytes(tx.Script) bw.WriteBytes(tx.Script)
if tx.Version >= 1 { if tx.Version >= 1 {
bw.WriteLE(tx.Gas) bw.WriteLE(tx.Gas)

View file

@ -1,7 +1,7 @@
package transaction package transaction
import ( import (
"io" "github.com/CityOfZion/neo-go/pkg/io"
) )
// IssueTX represents a issue transaction. // IssueTX represents a issue transaction.
@ -9,12 +9,12 @@ import (
type IssueTX struct{} type IssueTX struct{}
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (tx *IssueTX) DecodeBinary(r io.Reader) error { func (tx *IssueTX) DecodeBinary(r *io.BinReader) error {
return nil return nil
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (tx *IssueTX) EncodeBinary(w io.Writer) error { func (tx *IssueTX) EncodeBinary(w *io.BinWriter) error {
return nil return nil
} }

View file

@ -1,8 +1,7 @@
package transaction package transaction
import ( import (
"encoding/binary" "github.com/CityOfZion/neo-go/pkg/io"
"io"
) )
// MinerTX represents a miner transaction. // MinerTX represents a miner transaction.
@ -12,13 +11,15 @@ type MinerTX struct {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (tx *MinerTX) DecodeBinary(r io.Reader) error { func (tx *MinerTX) DecodeBinary(r *io.BinReader) error {
return binary.Read(r, binary.LittleEndian, &tx.Nonce) r.ReadLE(&tx.Nonce)
return r.Err
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (tx *MinerTX) EncodeBinary(w io.Writer) error { func (tx *MinerTX) EncodeBinary(w *io.BinWriter) error {
return binary.Write(w, binary.LittleEndian, tx.Nonce) w.WriteLE(tx.Nonce)
return w.Err
} }
// Size returns serialized binary size for this transaction. // Size returns serialized binary size for this transaction.

View file

@ -1,10 +1,10 @@
package transaction package transaction
import ( import (
"bytes"
"encoding/hex" "encoding/hex"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -21,9 +21,9 @@ func TestEncodeDecodeMiner(t *testing.T) {
assert.Equal(t, "a1f219dc6be4c35eca172e65e02d4591045220221b1543f1a4b67b9e9442c264", tx.Hash().ReverseString()) assert.Equal(t, "a1f219dc6be4c35eca172e65e02d4591045220221b1543f1a4b67b9e9442c264", tx.Hash().ReverseString())
// Encode // Encode
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
err := tx.EncodeBinary(buf) err := tx.EncodeBinary(buf.BinWriter)
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes())) assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))

View file

@ -2,9 +2,9 @@ package transaction
import ( import (
"encoding/json" "encoding/json"
"io"
"github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -34,8 +34,7 @@ func NewOutput(assetID util.Uint256, amount util.Fixed8, scriptHash util.Uint160
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (out *Output) DecodeBinary(r io.Reader) error { func (out *Output) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
br.ReadLE(&out.AssetID) br.ReadLE(&out.AssetID)
br.ReadLE(&out.Amount) br.ReadLE(&out.Amount)
br.ReadLE(&out.ScriptHash) br.ReadLE(&out.ScriptHash)
@ -43,8 +42,7 @@ func (out *Output) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (out *Output) EncodeBinary(w io.Writer) error { func (out *Output) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteLE(out.AssetID) bw.WriteLE(out.AssetID)
bw.WriteLE(out.Amount) bw.WriteLE(out.Amount)
bw.WriteLE(out.ScriptHash) bw.WriteLE(out.ScriptHash)

View file

@ -1,8 +1,7 @@
package transaction package transaction
import ( import (
"io" "github.com/CityOfZion/neo-go/pkg/io"
"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"
) )
@ -23,8 +22,7 @@ type PublishTX struct {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (tx *PublishTX) DecodeBinary(r io.Reader) error { func (tx *PublishTX) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
tx.Script = br.ReadBytes() tx.Script = br.ReadBytes()
lenParams := br.ReadVarUint() lenParams := br.ReadVarUint()
@ -55,8 +53,7 @@ func (tx *PublishTX) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (tx *PublishTX) EncodeBinary(w io.Writer) error { func (tx *PublishTX) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteBytes(tx.Script) bw.WriteBytes(tx.Script)
bw.WriteVarUint(uint64(len(tx.ParamList))) bw.WriteVarUint(uint64(len(tx.ParamList)))
for _, param := range tx.ParamList { for _, param := range tx.ParamList {

View file

@ -1,9 +1,8 @@
package transaction package transaction
import ( import (
"io"
"github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -30,8 +29,7 @@ type RegisterTX struct {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (tx *RegisterTX) DecodeBinary(r io.Reader) error { func (tx *RegisterTX) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
br.ReadLE(&tx.AssetType) br.ReadLE(&tx.AssetType)
tx.Name = br.ReadString() tx.Name = br.ReadString()
@ -43,7 +41,7 @@ func (tx *RegisterTX) DecodeBinary(r io.Reader) error {
} }
tx.Owner = &keys.PublicKey{} tx.Owner = &keys.PublicKey{}
if err := tx.Owner.DecodeBinary(r); err != nil { if err := tx.Owner.DecodeBinary(br); err != nil {
return err return err
} }
@ -52,8 +50,7 @@ func (tx *RegisterTX) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (tx *RegisterTX) EncodeBinary(w io.Writer) error { func (tx *RegisterTX) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteLE(tx.AssetType) bw.WriteLE(tx.AssetType)
bw.WriteString(tx.Name) bw.WriteString(tx.Name)
bw.WriteLE(tx.Amount) bw.WriteLE(tx.Amount)

View file

@ -1,12 +1,12 @@
package transaction package transaction
import ( import (
"bytes"
"encoding/hex" "encoding/hex"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -26,11 +26,12 @@ func TestRegisterTX(t *testing.T) {
}, },
} }
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
assert.Nil(t, tx.EncodeBinary(buf)) assert.Nil(t, tx.EncodeBinary(buf.BinWriter))
b := buf.Bytes()
txDecode := &Transaction{} txDecode := &Transaction{}
assert.Nil(t, txDecode.DecodeBinary(buf)) assert.Nil(t, txDecode.DecodeBinary(io.NewBinReaderFromBuf(b)))
txData := tx.Data.(*RegisterTX) txData := tx.Data.(*RegisterTX)
txDecodeData := txDecode.Data.(*RegisterTX) txDecodeData := txDecode.Data.(*RegisterTX)
assert.Equal(t, txData, txDecodeData) assert.Equal(t, txData, txDecodeData)
@ -45,7 +46,7 @@ func TestDecodeRegisterTXFromRawString(t *testing.T) {
} }
tx := &Transaction{} tx := &Transaction{}
assert.Nil(t, tx.DecodeBinary(bytes.NewReader(b))) assert.Nil(t, tx.DecodeBinary(io.NewBinReaderFromBuf(b)))
assert.Equal(t, RegisterType, tx.Type) assert.Equal(t, RegisterType, tx.Type)
txData := tx.Data.(*RegisterTX) txData := tx.Data.(*RegisterTX)
assert.Equal(t, GoverningToken, txData.AssetType) assert.Equal(t, GoverningToken, txData.AssetType)
@ -56,10 +57,11 @@ func TestDecodeRegisterTXFromRawString(t *testing.T) {
assert.Equal(t, "Abf2qMs1pzQb8kYk9RuxtUb9jtRKJVuBJt", crypto.AddressFromUint160(txData.Admin)) assert.Equal(t, "Abf2qMs1pzQb8kYk9RuxtUb9jtRKJVuBJt", crypto.AddressFromUint160(txData.Admin))
assert.Equal(t, "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", tx.Hash().ReverseString()) assert.Equal(t, "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", tx.Hash().ReverseString())
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
assert.Nil(t, tx.EncodeBinary(buf)) assert.Nil(t, tx.EncodeBinary(buf.BinWriter))
benc := buf.Bytes()
txDecode := &Transaction{} txDecode := &Transaction{}
assert.Nil(t, txDecode.DecodeBinary(buf)) assert.Nil(t, txDecode.DecodeBinary(io.NewBinReaderFromBuf(benc)))
assert.Equal(t, tx, txDecode) assert.Equal(t, tx, txDecode)
} }

View file

@ -1,8 +1,7 @@
package transaction package transaction
import ( import (
"io" "github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -12,36 +11,29 @@ type StateTX struct {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (tx *StateTX) DecodeBinary(r io.Reader) error { func (tx *StateTX) DecodeBinary(r *io.BinReader) error {
br := util.NewBinReaderFromIO(r) lenDesc := r.ReadVarUint()
lenDesc := br.ReadVarUint()
if br.Err != nil {
return br.Err
}
tx.Descriptors = make([]*StateDescriptor, lenDesc) tx.Descriptors = make([]*StateDescriptor, lenDesc)
for i := 0; i < int(lenDesc); i++ { for i := 0; i < int(lenDesc); i++ {
tx.Descriptors[i] = &StateDescriptor{} tx.Descriptors[i] = &StateDescriptor{}
if err := tx.Descriptors[i].DecodeBinary(r); err != nil { err := tx.Descriptors[i].DecodeBinary(r)
if err != nil {
return err return err
} }
} }
return nil return r.Err
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (tx *StateTX) EncodeBinary(w io.Writer) error { func (tx *StateTX) EncodeBinary(w *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w) w.WriteVarUint(uint64(len(tx.Descriptors)))
bw.WriteVarUint(uint64(len(tx.Descriptors)))
if bw.Err != nil {
return bw.Err
}
for _, desc := range tx.Descriptors { for _, desc := range tx.Descriptors {
err := desc.EncodeBinary(w) err := desc.EncodeBinary(w)
if err != nil { if err != nil {
return err return err
} }
} }
return nil return w.Err
} }
// Size returns serialized binary size for this transaction. // Size returns serialized binary size for this transaction.

View file

@ -1,8 +1,7 @@
package transaction package transaction
import ( import (
"io" "github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -24,25 +23,23 @@ type StateDescriptor struct {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (s *StateDescriptor) DecodeBinary(r io.Reader) error { func (s *StateDescriptor) DecodeBinary(r *io.BinReader) error {
br := util.NewBinReaderFromIO(r) r.ReadLE(&s.Type)
br.ReadLE(&s.Type)
s.Key = br.ReadBytes() s.Key = r.ReadBytes()
s.Value = br.ReadBytes() s.Value = r.ReadBytes()
s.Field = br.ReadString() s.Field = r.ReadString()
return br.Err return r.Err
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (s *StateDescriptor) EncodeBinary(w io.Writer) error { func (s *StateDescriptor) EncodeBinary(w *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w) w.WriteLE(s.Type)
bw.WriteLE(s.Type) w.WriteBytes(s.Key)
bw.WriteBytes(s.Key) w.WriteBytes(s.Value)
bw.WriteBytes(s.Value) w.WriteString(s.Field)
bw.WriteString(s.Field) return w.Err
return bw.Err
} }
// Size returns serialized binary size for state descriptor. // Size returns serialized binary size for state descriptor.

View file

@ -1,10 +1,10 @@
package transaction package transaction
import ( import (
"bytes"
"encoding/hex" "encoding/hex"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -30,10 +30,9 @@ func TestEncodeDecodeState(t *testing.T) {
assert.Equal(t, Validator, descriptor.Type) assert.Equal(t, Validator, descriptor.Type)
// Encode // Encode
buf := io.NewBufBinWriter()
buf := new(bytes.Buffer) err := tx.EncodeBinary(buf.BinWriter)
err := tx.EncodeBinary(buf)
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes())) assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))

View file

@ -1,10 +1,8 @@
package transaction package transaction
import ( import (
"bytes"
"io"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@ -77,14 +75,13 @@ func (t *Transaction) AddInput(in *Input) {
} }
// DecodeBinary implements the payload interface. // DecodeBinary implements the payload interface.
func (t *Transaction) DecodeBinary(r io.Reader) error { func (t *Transaction) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
br.ReadLE(&t.Type) br.ReadLE(&t.Type)
br.ReadLE(&t.Version) br.ReadLE(&t.Version)
if br.Err != nil { if br.Err != nil {
return br.Err return br.Err
} }
if err := t.decodeData(r); err != nil { if err := t.decodeData(br); err != nil {
return err return err
} }
@ -92,7 +89,7 @@ func (t *Transaction) DecodeBinary(r io.Reader) error {
t.Attributes = make([]*Attribute, lenAttrs) t.Attributes = make([]*Attribute, lenAttrs)
for i := 0; i < int(lenAttrs); i++ { for i := 0; i < int(lenAttrs); i++ {
t.Attributes[i] = &Attribute{} t.Attributes[i] = &Attribute{}
if err := t.Attributes[i].DecodeBinary(r); err != nil { if err := t.Attributes[i].DecodeBinary(br); err != nil {
log.Warnf("failed to decode TX %s", t.hash) log.Warnf("failed to decode TX %s", t.hash)
return err return err
} }
@ -102,7 +99,7 @@ func (t *Transaction) DecodeBinary(r io.Reader) error {
t.Inputs = make([]*Input, lenInputs) t.Inputs = make([]*Input, lenInputs)
for i := 0; i < int(lenInputs); i++ { for i := 0; i < int(lenInputs); i++ {
t.Inputs[i] = &Input{} t.Inputs[i] = &Input{}
if err := t.Inputs[i].DecodeBinary(r); err != nil { if err := t.Inputs[i].DecodeBinary(br); err != nil {
return err return err
} }
} }
@ -111,7 +108,7 @@ func (t *Transaction) DecodeBinary(r io.Reader) error {
t.Outputs = make([]*Output, lenOutputs) t.Outputs = make([]*Output, lenOutputs)
for i := 0; i < int(lenOutputs); i++ { for i := 0; i < int(lenOutputs); i++ {
t.Outputs[i] = &Output{} t.Outputs[i] = &Output{}
if err := t.Outputs[i].DecodeBinary(r); err != nil { if err := t.Outputs[i].DecodeBinary(br); err != nil {
return err return err
} }
} }
@ -120,7 +117,7 @@ func (t *Transaction) DecodeBinary(r io.Reader) error {
t.Scripts = make([]*Witness, lenScripts) t.Scripts = make([]*Witness, lenScripts)
for i := 0; i < int(lenScripts); i++ { for i := 0; i < int(lenScripts); i++ {
t.Scripts[i] = &Witness{} t.Scripts[i] = &Witness{}
if err := t.Scripts[i].DecodeBinary(r); err != nil { if err := t.Scripts[i].DecodeBinary(br); err != nil {
return err return err
} }
} }
@ -133,7 +130,7 @@ func (t *Transaction) DecodeBinary(r io.Reader) error {
return t.createHash() return t.createHash()
} }
func (t *Transaction) decodeData(r io.Reader) error { func (t *Transaction) decodeData(r *io.BinReader) error {
switch t.Type { switch t.Type {
case InvocationType: case InvocationType:
t.Data = &InvocationTX{Version: t.Version} t.Data = &InvocationTX{Version: t.Version}
@ -169,17 +166,16 @@ func (t *Transaction) decodeData(r io.Reader) error {
} }
// EncodeBinary implements the payload interface. // EncodeBinary implements the payload interface.
func (t *Transaction) EncodeBinary(w io.Writer) error { func (t *Transaction) EncodeBinary(bw *io.BinWriter) error {
if err := t.encodeHashableFields(w); err != nil { if err := t.encodeHashableFields(bw); err != nil {
return err return err
} }
bw := util.NewBinWriterFromIO(w)
bw.WriteVarUint(uint64(len(t.Scripts))) bw.WriteVarUint(uint64(len(t.Scripts)))
if bw.Err != nil { if bw.Err != nil {
return bw.Err return bw.Err
} }
for _, s := range t.Scripts { for _, s := range t.Scripts {
if err := s.EncodeBinary(w); err != nil { if err := s.EncodeBinary(bw); err != nil {
return err return err
} }
} }
@ -188,9 +184,7 @@ func (t *Transaction) EncodeBinary(w io.Writer) error {
// encodeHashableFields will only encode the fields that are not used for // encodeHashableFields will only encode the fields that are not used for
// signing the transaction, which are all fields except the scripts. // signing the transaction, which are all fields except the scripts.
func (t *Transaction) encodeHashableFields(w io.Writer) error { func (t *Transaction) encodeHashableFields(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteLE(t.Type) bw.WriteLE(t.Type)
bw.WriteLE(t.Version) bw.WriteLE(t.Version)
if bw.Err != nil { if bw.Err != nil {
@ -199,7 +193,7 @@ func (t *Transaction) encodeHashableFields(w io.Writer) error {
// Underlying TXer. // Underlying TXer.
if t.Data != nil { if t.Data != nil {
if err := t.Data.EncodeBinary(w); err != nil { if err := t.Data.EncodeBinary(bw); err != nil {
return err return err
} }
} }
@ -210,7 +204,7 @@ func (t *Transaction) encodeHashableFields(w io.Writer) error {
return bw.Err return bw.Err
} }
for _, attr := range t.Attributes { for _, attr := range t.Attributes {
if err := attr.EncodeBinary(w); err != nil { if err := attr.EncodeBinary(bw); err != nil {
return err return err
} }
} }
@ -221,7 +215,7 @@ func (t *Transaction) encodeHashableFields(w io.Writer) error {
return bw.Err return bw.Err
} }
for _, in := range t.Inputs { for _, in := range t.Inputs {
if err := in.EncodeBinary(w); err != nil { if err := in.EncodeBinary(bw); err != nil {
return err return err
} }
} }
@ -232,7 +226,7 @@ func (t *Transaction) encodeHashableFields(w io.Writer) error {
return bw.Err return bw.Err
} }
for _, out := range t.Outputs { for _, out := range t.Outputs {
if err := out.EncodeBinary(w); err != nil { if err := out.EncodeBinary(bw); err != nil {
return err return err
} }
} }
@ -241,8 +235,8 @@ func (t *Transaction) encodeHashableFields(w io.Writer) error {
// createHash creates the hash of the transaction. // createHash creates the hash of the transaction.
func (t *Transaction) createHash() error { func (t *Transaction) createHash() error {
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
if err := t.encodeHashableFields(buf); err != nil { if err := t.encodeHashableFields(buf.BinWriter); err != nil {
return err return err
} }
@ -281,8 +275,8 @@ func (t *Transaction) Size() int {
// Bytes convert the transaction to []byte // Bytes convert the transaction to []byte
func (t *Transaction) Bytes() []byte { func (t *Transaction) Bytes() []byte {
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
if err := t.EncodeBinary(buf); err != nil { if err := t.EncodeBinary(buf.BinWriter); err != nil {
return nil return nil
} }
return buf.Bytes() return buf.Bytes()

View file

@ -1,11 +1,11 @@
package transaction package transaction
import ( import (
"bytes"
"encoding/hex" "encoding/hex"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/io"
"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/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -27,15 +27,14 @@ func TestWitnessEncodeDecode(t *testing.T) {
VerificationScript: verif, VerificationScript: verif,
} }
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
if err := wit.EncodeBinary(buf); err != nil { err = wit.EncodeBinary(buf.BinWriter)
t.Fatal(err) assert.Nil(t, err)
}
benc := buf.Bytes()
witDecode := &Witness{} witDecode := &Witness{}
if err := witDecode.DecodeBinary(buf); err != nil { err = witDecode.DecodeBinary(io.NewBinReaderFromBuf(benc))
t.Fatal(err) assert.Nil(t, err)
}
t.Log(len(witDecode.VerificationScript)) t.Log(len(witDecode.VerificationScript))
t.Log(len(witDecode.InvocationScript)) t.Log(len(witDecode.InvocationScript))
@ -61,10 +60,9 @@ func TestDecodeEncodeClaimTX(t *testing.T) {
assert.Equal(t, invoc, hex.EncodeToString(tx.Scripts[0].InvocationScript)) assert.Equal(t, invoc, hex.EncodeToString(tx.Scripts[0].InvocationScript))
assert.Equal(t, verif, hex.EncodeToString(tx.Scripts[0].VerificationScript)) assert.Equal(t, verif, hex.EncodeToString(tx.Scripts[0].VerificationScript))
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
if err := tx.EncodeBinary(buf); err != nil { err := tx.EncodeBinary(buf.BinWriter)
t.Fatal(err) assert.Nil(t, err)
}
assert.Equal(t, rawClaimTX, hex.EncodeToString(buf.Bytes())) assert.Equal(t, rawClaimTX, hex.EncodeToString(buf.Bytes()))
hash := "2c6a45547b3898318e400e541628990a07acb00f3b9a15a8e966ae49525304da" hash := "2c6a45547b3898318e400e541628990a07acb00f3b9a15a8e966ae49525304da"
@ -90,10 +88,10 @@ func TestDecodeEncodeInvocationTX(t *testing.T) {
assert.Equal(t, invoc, hex.EncodeToString(tx.Scripts[0].InvocationScript)) assert.Equal(t, invoc, hex.EncodeToString(tx.Scripts[0].InvocationScript))
assert.Equal(t, verif, hex.EncodeToString(tx.Scripts[0].VerificationScript)) assert.Equal(t, verif, hex.EncodeToString(tx.Scripts[0].VerificationScript))
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
if err := tx.EncodeBinary(buf); err != nil { err := tx.EncodeBinary(buf.BinWriter)
t.Fatal(err) assert.Nil(t, err)
}
assert.Equal(t, rawInvocationTX, hex.EncodeToString(buf.Bytes())) assert.Equal(t, rawInvocationTX, hex.EncodeToString(buf.Bytes()))
} }
@ -145,8 +143,8 @@ func TestDecodePublishTX(t *testing.T) {
assert.Equal(t, expectedTX.Type, actualTX.Type) assert.Equal(t, expectedTX.Type, actualTX.Type)
assert.Equal(t, expectedTX.Version, actualTX.Version) assert.Equal(t, expectedTX.Version, actualTX.Version)
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
err := actualTX.EncodeBinary(buf) err := actualTX.EncodeBinary(buf.BinWriter)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, rawPublishTX, hex.EncodeToString(buf.Bytes())) assert.Equal(t, rawPublishTX, hex.EncodeToString(buf.Bytes()))
} }

View file

@ -1,11 +1,11 @@
package transaction package transaction
import "io" import "github.com/CityOfZion/neo-go/pkg/io"
// TXer is interface that can act as the underlying data of // TXer is interface that can act as the underlying data of
// a transaction. // a transaction.
type TXer interface { type TXer interface {
DecodeBinary(io.Reader) error DecodeBinary(*io.BinReader) error
EncodeBinary(io.Writer) error EncodeBinary(*io.BinWriter) error
Size() int Size() int
} }

View file

@ -3,9 +3,9 @@ package transaction
import ( import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"io"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -16,18 +16,14 @@ type Witness struct {
} }
// DecodeBinary implements the payload interface. // DecodeBinary implements the payload interface.
func (w *Witness) DecodeBinary(r io.Reader) error { func (w *Witness) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
w.InvocationScript = br.ReadBytes() w.InvocationScript = br.ReadBytes()
w.VerificationScript = br.ReadBytes() w.VerificationScript = br.ReadBytes()
return br.Err return br.Err
} }
// EncodeBinary implements the payload interface. // EncodeBinary implements the payload interface.
func (w *Witness) EncodeBinary(writer io.Writer) error { func (w *Witness) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(writer)
bw.WriteBytes(w.InvocationScript) bw.WriteBytes(w.InvocationScript)
bw.WriteBytes(w.VerificationScript) bw.WriteBytes(w.VerificationScript)

View file

@ -1,12 +1,11 @@
package core package core
import ( import (
"bytes"
"fmt" "fmt"
"io"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"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/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -22,7 +21,7 @@ func (u UnspentCoins) getAndUpdate(s storage.Store, hash util.Uint256) (*Unspent
unspent := &UnspentCoinState{} unspent := &UnspentCoinState{}
key := storage.AppendPrefix(storage.STCoin, hash.BytesReverse()) key := storage.AppendPrefix(storage.STCoin, hash.BytesReverse())
if b, err := s.Get(key); err == nil { if b, err := s.Get(key); err == nil {
if err := unspent.DecodeBinary(bytes.NewReader(b)); err != nil { if err := unspent.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil {
return nil, fmt.Errorf("failed to decode (UnspentCoinState): %s", err) return nil, fmt.Errorf("failed to decode (UnspentCoinState): %s", err)
} }
} else { } else {
@ -53,9 +52,9 @@ func NewUnspentCoinState(n int) *UnspentCoinState {
// commit writes all unspent coin states to the given Batch. // commit writes all unspent coin states to the given Batch.
func (u UnspentCoins) commit(b storage.Batch) error { func (u UnspentCoins) commit(b storage.Batch) error {
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
for hash, state := range u { for hash, state := range u {
if err := state.EncodeBinary(buf); err != nil { if err := state.EncodeBinary(buf.BinWriter); err != nil {
return err return err
} }
key := storage.AppendPrefix(storage.STCoin, hash.BytesReverse()) key := storage.AppendPrefix(storage.STCoin, hash.BytesReverse())
@ -65,9 +64,8 @@ func (u UnspentCoins) commit(b storage.Batch) error {
return nil return nil
} }
// EncodeBinary encodes UnspentCoinState to the given io.Writer. // EncodeBinary encodes UnspentCoinState to the given BinWriter.
func (s *UnspentCoinState) EncodeBinary(w io.Writer) error { func (s *UnspentCoinState) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteVarUint(uint64(len(s.states))) bw.WriteVarUint(uint64(len(s.states)))
for _, state := range s.states { for _, state := range s.states {
bw.WriteLE(byte(state)) bw.WriteLE(byte(state))
@ -75,9 +73,8 @@ func (s *UnspentCoinState) EncodeBinary(w io.Writer) error {
return bw.Err return bw.Err
} }
// DecodeBinary decodes UnspentCoinState from the given io.Reader. // DecodeBinary decodes UnspentCoinState from the given BinReader.
func (s *UnspentCoinState) DecodeBinary(r io.Reader) error { func (s *UnspentCoinState) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
lenStates := br.ReadVarUint() lenStates := br.ReadVarUint()
s.states = make([]CoinState, lenStates) s.states = make([]CoinState, lenStates)
for i := 0; i < int(lenStates); i++ { for i := 0; i < int(lenStates); i++ {
@ -98,7 +95,7 @@ func IsDoubleSpend(s storage.Store, tx *transaction.Transaction) bool {
unspent := &UnspentCoinState{} unspent := &UnspentCoinState{}
key := storage.AppendPrefix(storage.STCoin, prevHash.BytesReverse()) key := storage.AppendPrefix(storage.STCoin, prevHash.BytesReverse())
if b, err := s.Get(key); err == nil { if b, err := s.Get(key); err == nil {
if err := unspent.DecodeBinary(bytes.NewReader(b)); err != nil { if err := unspent.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil {
return false return false
} }
if unspent == nil { if unspent == nil {

View file

@ -1,10 +1,10 @@
package core package core
import ( import (
"bytes"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -19,10 +19,10 @@ func TestDecodeEncodeUnspentCoinState(t *testing.T) {
}, },
} }
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
assert.Nil(t, unspent.EncodeBinary(buf)) assert.Nil(t, unspent.EncodeBinary(buf.BinWriter))
unspentDecode := &UnspentCoinState{} unspentDecode := &UnspentCoinState{}
assert.Nil(t, unspentDecode.DecodeBinary(buf)) assert.Nil(t, unspentDecode.DecodeBinary(io.NewBinReaderFromBuf(buf.Bytes())))
} }
func TestCommitUnspentCoins(t *testing.T) { func TestCommitUnspentCoins(t *testing.T) {

View file

@ -1,8 +1,6 @@
package core package core
import ( import (
"bytes"
"encoding/binary"
"time" "time"
"github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/config"
@ -10,6 +8,7 @@ import (
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/io"
"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"
@ -181,11 +180,9 @@ func headerSliceReverse(dest []*Header) {
// storeAsCurrentBlock stores the given block witch prefix // storeAsCurrentBlock stores the given block witch prefix
// SYSCurrentBlock. // SYSCurrentBlock.
func storeAsCurrentBlock(batch storage.Batch, block *Block) { func storeAsCurrentBlock(batch storage.Batch, block *Block) {
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
buf.Write(block.Hash().BytesReverse()) buf.WriteLE(block.Hash().BytesReverse())
b := make([]byte, 4) buf.WriteLE(block.Index)
binary.LittleEndian.PutUint32(b, block.Index)
buf.Write(b)
batch.Put(storage.SYSCurrentBlock.Bytes(), buf.Bytes()) batch.Put(storage.SYSCurrentBlock.Bytes(), buf.Bytes())
} }
@ -193,17 +190,18 @@ func storeAsCurrentBlock(batch storage.Batch, block *Block) {
func storeAsBlock(batch storage.Batch, block *Block, sysFee uint32) error { func storeAsBlock(batch storage.Batch, block *Block, sysFee uint32) error {
var ( var (
key = storage.AppendPrefix(storage.DataBlock, block.Hash().BytesReverse()) key = storage.AppendPrefix(storage.DataBlock, block.Hash().BytesReverse())
buf = new(bytes.Buffer) buf = io.NewBufBinWriter()
) )
// sysFee needs to be handled somehow
b := make([]byte, 4) // buf.WriteLE(sysFee)
binary.LittleEndian.PutUint32(b, sysFee)
b, err := block.Trim() b, err := block.Trim()
if err != nil { if err != nil {
return err return err
} }
buf.Write(b) buf.WriteLE(b)
if buf.Err != nil {
return buf.Err
}
batch.Put(key, buf.Bytes()) batch.Put(key, buf.Bytes())
return nil return nil
} }
@ -211,15 +209,13 @@ func storeAsBlock(batch storage.Batch, block *Block, sysFee uint32) error {
// storeAsTransaction stores the given TX as DataTransaction. // storeAsTransaction stores the given TX as DataTransaction.
func storeAsTransaction(batch storage.Batch, tx *transaction.Transaction, index uint32) error { func storeAsTransaction(batch storage.Batch, tx *transaction.Transaction, index uint32) error {
key := storage.AppendPrefix(storage.DataTransaction, tx.Hash().BytesReverse()) key := storage.AppendPrefix(storage.DataTransaction, tx.Hash().BytesReverse())
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
if err := tx.EncodeBinary(buf); err != nil { buf.WriteLE(index)
if err := tx.EncodeBinary(buf.BinWriter); err != nil {
return err return err
} }
dest := make([]byte, buf.Len()+4) batch.Put(key, buf.Bytes())
binary.LittleEndian.PutUint32(dest[:4], index)
copy(dest[4:], buf.Bytes())
batch.Put(key, dest)
return nil return nil
} }

View file

@ -5,14 +5,13 @@ import (
"crypto/ecdsa" "crypto/ecdsa"
"crypto/elliptic" "crypto/elliptic"
"crypto/x509" "crypto/x509"
"encoding/binary"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"io"
"math/big" "math/big"
"github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -51,7 +50,7 @@ func NewPublicKeyFromString(s string) (*PublicKey, error) {
} }
pubKey := new(PublicKey) pubKey := new(PublicKey)
if err := pubKey.DecodeBinary(bytes.NewReader(b)); err != nil { if err := pubKey.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil {
return nil, err return nil, err
} }
@ -122,20 +121,19 @@ func decodeCompressedY(x *big.Int, ylsb uint) (*big.Int, error) {
// DecodeBytes decodes a PublicKey from the given slice of bytes. // DecodeBytes decodes a PublicKey from the given slice of bytes.
func (p *PublicKey) DecodeBytes(data []byte) error { func (p *PublicKey) DecodeBytes(data []byte) error {
var datab []byte b := io.NewBinReaderFromBuf(data)
copy(datab, data)
b := bytes.NewBuffer(datab)
return p.DecodeBinary(b) return p.DecodeBinary(b)
} }
// DecodeBinary decodes a PublicKey from the given io.Reader. // DecodeBinary decodes a PublicKey from the given BinReader.
func (p *PublicKey) DecodeBinary(r io.Reader) error { func (p *PublicKey) DecodeBinary(r *io.BinReader) error {
var prefix uint8 var prefix uint8
var x, y *big.Int var x, y *big.Int
var err error var err error
if err = binary.Read(r, binary.LittleEndian, &prefix); err != nil { r.ReadLE(&prefix)
return err if r.Err != nil {
return r.Err
} }
// Infinity // Infinity
@ -146,8 +144,9 @@ func (p *PublicKey) DecodeBinary(r io.Reader) error {
case 0x02, 0x03: case 0x02, 0x03:
// Compressed public keys // Compressed public keys
xbytes := make([]byte, 32) xbytes := make([]byte, 32)
if _, err := io.ReadFull(r, xbytes); err != nil { r.ReadLE(xbytes)
return err if r.Err != nil {
return r.Err
} }
x = new(big.Int).SetBytes(xbytes) x = new(big.Int).SetBytes(xbytes)
ylsb := uint(prefix & 0x1) ylsb := uint(prefix & 0x1)
@ -158,11 +157,10 @@ func (p *PublicKey) DecodeBinary(r io.Reader) error {
case 0x04: case 0x04:
xbytes := make([]byte, 32) xbytes := make([]byte, 32)
ybytes := make([]byte, 32) ybytes := make([]byte, 32)
if _, err = io.ReadFull(r, xbytes); err != nil { r.ReadLE(xbytes)
return err r.ReadLE(ybytes)
} if r.Err != nil {
if _, err = io.ReadFull(r, ybytes); err != nil { return r.Err
return err
} }
x = new(big.Int).SetBytes(xbytes) x = new(big.Int).SetBytes(xbytes)
y = new(big.Int).SetBytes(ybytes) y = new(big.Int).SetBytes(ybytes)
@ -182,9 +180,10 @@ func (p *PublicKey) DecodeBinary(r io.Reader) error {
return nil return nil
} }
// EncodeBinary encodes a PublicKey to the given io.Writer. // EncodeBinary encodes a PublicKey to the given BinWriter.
func (p *PublicKey) EncodeBinary(w io.Writer) error { func (p *PublicKey) EncodeBinary(w *io.BinWriter) error {
return binary.Write(w, binary.LittleEndian, p.Bytes()) w.WriteLE(p.Bytes())
return w.Err
} }
// Signature returns a NEO-specific hash of the key. // Signature returns a NEO-specific hash of the key.

View file

@ -1,21 +1,23 @@
package keys package keys
import ( import (
"bytes"
"encoding/hex" "encoding/hex"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestEncodeDecodeInfinity(t *testing.T) { func TestEncodeDecodeInfinity(t *testing.T) {
key := &PublicKey{} key := &PublicKey{}
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
assert.Nil(t, key.EncodeBinary(buf)) assert.Nil(t, key.EncodeBinary(buf.BinWriter))
assert.Equal(t, 1, buf.Len()) assert.Nil(t, buf.Err)
b := buf.Bytes()
assert.Equal(t, 1, len(b))
keyDecode := &PublicKey{} keyDecode := &PublicKey{}
assert.Nil(t, keyDecode.DecodeBinary(buf)) assert.Nil(t, keyDecode.DecodeBytes(b))
assert.Equal(t, []byte{0x00}, keyDecode.Bytes()) assert.Equal(t, []byte{0x00}, keyDecode.Bytes())
} }
@ -24,11 +26,13 @@ func TestEncodeDecodePublicKey(t *testing.T) {
k, err := NewPrivateKey() k, err := NewPrivateKey()
assert.Nil(t, err) assert.Nil(t, err)
p := k.PublicKey() p := k.PublicKey()
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
assert.Nil(t, p.EncodeBinary(buf)) assert.Nil(t, p.EncodeBinary(buf.BinWriter))
assert.Nil(t, buf.Err)
b := buf.Bytes()
pDecode := &PublicKey{} pDecode := &PublicKey{}
assert.Nil(t, pDecode.DecodeBinary(buf)) assert.Nil(t, pDecode.DecodeBytes(b))
assert.Equal(t, p.X, pDecode.X) assert.Equal(t, p.X, pDecode.X)
} }
} }

View file

@ -1,4 +1,4 @@
package util package io
import ( import (
"bytes" "bytes"
@ -27,3 +27,13 @@ func (bw *BufBinWriter) Bytes() []byte {
bw.Err = errors.New("buffer already drained") bw.Err = errors.New("buffer already drained")
return bw.buf.Bytes() return bw.buf.Bytes()
} }
// Reset resets the state of the buffer, making it usable again. It can
// make buffer usage somewhat more efficient, because you don't need to
// create it again, but beware that the buffer is gonna be the same as the one
// returned by Bytes(), so if you need that data after Reset() you have to copy
// it yourself.
func (bw *BufBinWriter) Reset() {
bw.Err = nil
bw.buf.Reset()
}

View file

@ -1,4 +1,4 @@
package util package io
import ( import (
"bytes" "bytes"

View file

@ -1,4 +1,4 @@
package util package io
import ( import (
"encoding/binary" "encoding/binary"

View file

@ -1,4 +1,4 @@
package util package io
import ( import (
"errors" "errors"
@ -101,6 +101,18 @@ func TestBufBinWriterErr(t *testing.T) {
assert.Nil(t, res) assert.Nil(t, res)
} }
func TestBufBinWriterReset(t *testing.T) {
bw := NewBufBinWriter()
for i := 0; i < 3; i++ {
bw.WriteLE(uint32(i))
assert.Nil(t, bw.Err)
_ = bw.Bytes()
assert.NotNil(t, bw.Err)
bw.Reset()
assert.Nil(t, bw.Err)
}
}
func TestWriteString(t *testing.T) { func TestWriteString(t *testing.T) {
var ( var (
str string = "teststring" str string = "teststring"

View file

@ -1,10 +1,8 @@
package io package io
import "io"
// Serializable defines the binary encoding/decoding interface. // Serializable defines the binary encoding/decoding interface.
type Serializable interface { type Serializable interface {
Size() int Size() int
DecodeBinary(io.Reader) error DecodeBinary(*BinReader) error
EncodeBinary(io.Writer) error EncodeBinary(*BinWriter) error
} }

View file

@ -1,18 +1,15 @@
package network package network
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt"
"io"
"github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/config"
"github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/network/payload" "github.com/CityOfZion/neo-go/pkg/network/payload"
"github.com/CityOfZion/neo-go/pkg/util"
) )
const ( const (
@ -80,12 +77,13 @@ func NewMessage(magic config.NetMode, cmd CommandType, p payload.Payload) *Messa
) )
if p != nil { if p != nil {
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
if err := p.EncodeBinary(buf); err != nil { if err := p.EncodeBinary(buf.BinWriter); err != nil {
panic(err) panic(err)
} }
size = uint32(buf.Len()) b := buf.Bytes()
checksum = hash.Checksum(buf.Bytes()) size = uint32(len(b))
checksum = hash.Checksum(b)
} else { } else {
checksum = hash.Checksum([]byte{}) checksum = hash.Checksum([]byte{})
} }
@ -147,8 +145,7 @@ func (m *Message) CommandType() CommandType {
} }
// Decode a Message from the given reader. // Decode a Message from the given reader.
func (m *Message) Decode(r io.Reader) error { func (m *Message) Decode(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
br.ReadLE(&m.Magic) br.ReadLE(&m.Magic)
br.ReadLE(&m.Command) br.ReadLE(&m.Command)
br.ReadLE(&m.Length) br.ReadLE(&m.Length)
@ -160,67 +157,63 @@ func (m *Message) Decode(r io.Reader) error {
if m.Length == 0 { if m.Length == 0 {
return nil return nil
} }
return m.decodePayload(r) return m.decodePayload(br)
} }
func (m *Message) decodePayload(r io.Reader) error { func (m *Message) decodePayload(br *io.BinReader) error {
buf := new(bytes.Buffer) buf := make([]byte, m.Length)
n, err := io.CopyN(buf, r, int64(m.Length)) br.ReadLE(buf)
if err != nil { if br.Err != nil {
return err return br.Err
} }
if uint32(n) != m.Length {
return fmt.Errorf("expected to have read exactly %d bytes got %d", m.Length, n)
}
// Compare the checksum of the payload. // Compare the checksum of the payload.
if !compareChecksum(m.Checksum, buf.Bytes()) { if !compareChecksum(m.Checksum, buf) {
return errChecksumMismatch return errChecksumMismatch
} }
r := io.NewBinReaderFromBuf(buf)
var p payload.Payload var p payload.Payload
switch m.CommandType() { switch m.CommandType() {
case CMDVersion: case CMDVersion:
p = &payload.Version{} p = &payload.Version{}
if err := p.DecodeBinary(buf); err != nil { if err := p.DecodeBinary(r); err != nil {
return err return err
} }
case CMDInv, CMDGetData: case CMDInv, CMDGetData:
p = &payload.Inventory{} p = &payload.Inventory{}
if err := p.DecodeBinary(buf); err != nil { if err := p.DecodeBinary(r); err != nil {
return err return err
} }
case CMDAddr: case CMDAddr:
p = &payload.AddressList{} p = &payload.AddressList{}
if err := p.DecodeBinary(buf); err != nil { if err := p.DecodeBinary(r); err != nil {
return err return err
} }
case CMDBlock: case CMDBlock:
p = &core.Block{} p = &core.Block{}
if err := p.DecodeBinary(buf); err != nil { if err := p.DecodeBinary(r); err != nil {
return err return err
} }
case CMDGetBlocks: case CMDGetBlocks:
fallthrough fallthrough
case CMDGetHeaders: case CMDGetHeaders:
p = &payload.GetBlocks{} p = &payload.GetBlocks{}
if err := p.DecodeBinary(buf); err != nil { if err := p.DecodeBinary(r); err != nil {
return err return err
} }
case CMDHeaders: case CMDHeaders:
p = &payload.Headers{} p = &payload.Headers{}
if err := p.DecodeBinary(buf); err != nil { if err := p.DecodeBinary(r); err != nil {
return err return err
} }
case CMDTX: case CMDTX:
p = &transaction.Transaction{} p = &transaction.Transaction{}
if err := p.DecodeBinary(buf); err != nil { if err := p.DecodeBinary(r); err != nil {
return err return err
} }
case CMDMerkleBlock: case CMDMerkleBlock:
p = &payload.MerkleBlock{} p = &payload.MerkleBlock{}
if err := p.DecodeBinary(buf); err != nil { if err := p.DecodeBinary(r); err != nil {
return err return err
} }
} }
@ -230,9 +223,8 @@ func (m *Message) decodePayload(r io.Reader) error {
return nil return nil
} }
// Encode a Message to any given io.Writer. // Encode a Message to any given BinWriter.
func (m *Message) Encode(w io.Writer) error { func (m *Message) Encode(br *io.BinWriter) error {
br := util.NewBinWriterFromIO(w)
br.WriteLE(m.Magic) br.WriteLE(m.Magic)
br.WriteLE(m.Command) br.WriteLE(m.Command)
br.WriteLE(m.Length) br.WriteLE(m.Length)
@ -241,7 +233,7 @@ func (m *Message) Encode(w io.Writer) error {
return br.Err return br.Err
} }
if m.Payload != nil { if m.Payload != nil {
return m.Payload.EncodeBinary(w) return m.Payload.EncodeBinary(br)
} }
return nil return nil
} }

View file

@ -1,12 +1,11 @@
package payload package payload
import ( import (
"io"
"net" "net"
"strconv" "strconv"
"time" "time"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/io"
) )
// AddressAndTime payload. // AddressAndTime payload.
@ -29,8 +28,7 @@ func NewAddressAndTime(e *net.TCPAddr, t time.Time) *AddressAndTime {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (p *AddressAndTime) DecodeBinary(r io.Reader) error { func (p *AddressAndTime) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
br.ReadLE(&p.Timestamp) br.ReadLE(&p.Timestamp)
br.ReadLE(&p.Services) br.ReadLE(&p.Services)
br.ReadBE(&p.IP) br.ReadBE(&p.IP)
@ -39,8 +37,7 @@ func (p *AddressAndTime) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (p *AddressAndTime) EncodeBinary(w io.Writer) error { func (p *AddressAndTime) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteLE(p.Timestamp) bw.WriteLE(p.Timestamp)
bw.WriteLE(p.Services) bw.WriteLE(p.Services)
bw.WriteBE(p.IP) bw.WriteBE(p.IP)
@ -71,8 +68,7 @@ func NewAddressList(n int) *AddressList {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (p *AddressList) DecodeBinary(r io.Reader) error { func (p *AddressList) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
listLen := br.ReadVarUint() listLen := br.ReadVarUint()
if br.Err != nil { if br.Err != nil {
return br.Err return br.Err
@ -81,7 +77,7 @@ func (p *AddressList) DecodeBinary(r io.Reader) error {
p.Addrs = make([]*AddressAndTime, listLen) p.Addrs = make([]*AddressAndTime, listLen)
for i := 0; i < int(listLen); i++ { for i := 0; i < int(listLen); i++ {
p.Addrs[i] = &AddressAndTime{} p.Addrs[i] = &AddressAndTime{}
if err := p.Addrs[i].DecodeBinary(r); err != nil { if err := p.Addrs[i].DecodeBinary(br); err != nil {
return err return err
} }
} }
@ -89,14 +85,13 @@ func (p *AddressList) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (p *AddressList) EncodeBinary(w io.Writer) error { func (p *AddressList) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteVarUint(uint64(len(p.Addrs))) bw.WriteVarUint(uint64(len(p.Addrs)))
if bw.Err != nil { if bw.Err != nil {
return bw.Err return bw.Err
} }
for _, addr := range p.Addrs { for _, addr := range p.Addrs {
if err := addr.EncodeBinary(w); err != nil { if err := addr.EncodeBinary(bw); err != nil {
return err return err
} }
} }

View file

@ -1,12 +1,12 @@
package payload package payload
import ( import (
"bytes"
"fmt" "fmt"
"net" "net"
"testing" "testing"
"time" "time"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -15,7 +15,7 @@ func TestEncodeDecodeAddress(t *testing.T) {
e, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:2000") e, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:2000")
ts = time.Now() ts = time.Now()
addr = NewAddressAndTime(e, ts) addr = NewAddressAndTime(e, ts)
buf = new(bytes.Buffer) buf = io.NewBufBinWriter()
) )
assert.Equal(t, ts.UTC().Unix(), int64(addr.Timestamp)) assert.Equal(t, ts.UTC().Unix(), int64(addr.Timestamp))
@ -23,11 +23,13 @@ func TestEncodeDecodeAddress(t *testing.T) {
copy(aatip, addr.IP[:]) copy(aatip, addr.IP[:])
assert.Equal(t, e.IP, aatip) assert.Equal(t, e.IP, aatip)
assert.Equal(t, e.Port, int(addr.Port)) assert.Equal(t, e.Port, int(addr.Port))
err := addr.EncodeBinary(buf) err := addr.EncodeBinary(buf.BinWriter)
assert.Nil(t, err) assert.Nil(t, err)
b := buf.Bytes()
r := io.NewBinReaderFromBuf(b)
addrDecode := &AddressAndTime{} addrDecode := &AddressAndTime{}
err = addrDecode.DecodeBinary(buf) err = addrDecode.DecodeBinary(r)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, addr, addrDecode) assert.Equal(t, addr, addrDecode)
@ -41,12 +43,14 @@ func TestEncodeDecodeAddressList(t *testing.T) {
addrList.Addrs[i] = NewAddressAndTime(e, time.Now()) addrList.Addrs[i] = NewAddressAndTime(e, time.Now())
} }
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
err := addrList.EncodeBinary(buf) err := addrList.EncodeBinary(buf.BinWriter)
assert.Nil(t, err) assert.Nil(t, err)
b := buf.Bytes()
r := io.NewBinReaderFromBuf(b)
addrListDecode := &AddressList{} addrListDecode := &AddressList{}
err = addrListDecode.DecodeBinary(buf) err = addrListDecode.DecodeBinary(r)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, addrList, addrListDecode) assert.Equal(t, addrList, addrListDecode)

View file

@ -1,8 +1,7 @@
package payload package payload
import ( import (
"io" "github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -23,8 +22,7 @@ func NewGetBlocks(start []util.Uint256, stop util.Uint256) *GetBlocks {
} }
// DecodeBinary implements the payload interface. // DecodeBinary implements the payload interface.
func (p *GetBlocks) DecodeBinary(r io.Reader) error { func (p *GetBlocks) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
lenStart := br.ReadVarUint() lenStart := br.ReadVarUint()
p.HashStart = make([]util.Uint256, lenStart) p.HashStart = make([]util.Uint256, lenStart)
@ -34,8 +32,7 @@ func (p *GetBlocks) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the payload interface. // EncodeBinary implements the payload interface.
func (p *GetBlocks) EncodeBinary(w io.Writer) error { func (p *GetBlocks) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteVarUint(uint64(len(p.HashStart))) bw.WriteVarUint(uint64(len(p.HashStart)))
bw.WriteLE(p.HashStart) bw.WriteLE(p.HashStart)
bw.WriteLE(p.HashStop) bw.WriteLE(p.HashStop)

View file

@ -1,10 +1,10 @@
package payload package payload
import ( import (
"bytes"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -18,12 +18,14 @@ func TestGetBlockEncodeDecode(t *testing.T) {
} }
p := NewGetBlocks(start, util.Uint256{}) p := NewGetBlocks(start, util.Uint256{})
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
err := p.EncodeBinary(buf) err := p.EncodeBinary(buf.BinWriter)
assert.Nil(t, err) assert.Nil(t, err)
b := buf.Bytes()
r := io.NewBinReaderFromBuf(b)
pDecode := &GetBlocks{} pDecode := &GetBlocks{}
err = pDecode.DecodeBinary(buf) err = pDecode.DecodeBinary(r)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, p, pDecode) assert.Equal(t, p, pDecode)
} }
@ -39,12 +41,14 @@ func TestGetBlockEncodeDecodeWithHashStop(t *testing.T) {
stop = hash.Sha256([]byte("e")) stop = hash.Sha256([]byte("e"))
) )
p := NewGetBlocks(start, stop) p := NewGetBlocks(start, stop)
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
err := p.EncodeBinary(buf) err := p.EncodeBinary(buf.BinWriter)
assert.Nil(t, err) assert.Nil(t, err)
b := buf.Bytes()
r := io.NewBinReaderFromBuf(b)
pDecode := &GetBlocks{} pDecode := &GetBlocks{}
err = pDecode.DecodeBinary(buf) err = pDecode.DecodeBinary(r)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, p, pDecode) assert.Equal(t, p, pDecode)
} }

View file

@ -1,10 +1,8 @@
package payload package payload
import ( import (
"io"
"github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/io"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@ -19,8 +17,7 @@ const (
) )
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (p *Headers) DecodeBinary(r io.Reader) error { func (p *Headers) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
lenHeaders := br.ReadVarUint() lenHeaders := br.ReadVarUint()
if br.Err != nil { if br.Err != nil {
return br.Err return br.Err
@ -35,7 +32,7 @@ func (p *Headers) DecodeBinary(r io.Reader) error {
for i := 0; i < int(lenHeaders); i++ { for i := 0; i < int(lenHeaders); i++ {
header := &core.Header{} header := &core.Header{}
if err := header.DecodeBinary(r); err != nil { if err := header.DecodeBinary(br); err != nil {
return err return err
} }
p.Hdrs[i] = header p.Hdrs[i] = header
@ -45,15 +42,14 @@ func (p *Headers) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (p *Headers) EncodeBinary(w io.Writer) error { func (p *Headers) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteVarUint(uint64(len(p.Hdrs))) bw.WriteVarUint(uint64(len(p.Hdrs)))
if bw.Err != nil { if bw.Err != nil {
return bw.Err return bw.Err
} }
for _, header := range p.Hdrs { for _, header := range p.Hdrs {
if err := header.EncodeBinary(w); err != nil { if err := header.EncodeBinary(bw); err != nil {
return err return err
} }
} }

View file

@ -1,12 +1,12 @@
package payload package payload
import ( import (
"bytes"
"encoding/hex" "encoding/hex"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core"
"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/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -41,12 +41,14 @@ func TestHeadersEncodeDecode(t *testing.T) {
}}, }},
}} }}
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
err := headers.EncodeBinary(buf) err := headers.EncodeBinary(buf.BinWriter)
assert.Nil(t, err) assert.Nil(t, err)
b := buf.Bytes()
r := io.NewBinReaderFromBuf(b)
headersDecode := &Headers{} headersDecode := &Headers{}
err = headersDecode.DecodeBinary(buf) err = headersDecode.DecodeBinary(r)
assert.Nil(t, err) assert.Nil(t, err)
for i := 0; i < len(headers.Hdrs); i++ { for i := 0; i < len(headers.Hdrs); i++ {
@ -63,7 +65,7 @@ func TestBinEncodeDecode(t *testing.T) {
rawBlockBytes, _ := hex.DecodeString(rawBlockHeaders) rawBlockBytes, _ := hex.DecodeString(rawBlockHeaders)
r := bytes.NewReader(rawBlockBytes) r := io.NewBinReaderFromBuf(rawBlockBytes)
err := headerMsg.DecodeBinary(r) err := headerMsg.DecodeBinary(r)
assert.Nil(t, err) assert.Nil(t, err)
@ -74,9 +76,9 @@ func TestBinEncodeDecode(t *testing.T) {
assert.Equal(t, "f3c4ec44c07eccbda974f1ee34bc6654ab6d3f22cd89c2e5c593a16d6cc7e6e8", hash.ReverseString()) assert.Equal(t, "f3c4ec44c07eccbda974f1ee34bc6654ab6d3f22cd89c2e5c593a16d6cc7e6e8", hash.ReverseString())
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
err = headerMsg.EncodeBinary(buf) err = headerMsg.EncodeBinary(buf.BinWriter)
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
assert.Equal(t, hex.EncodeToString(rawBlockBytes), hex.EncodeToString(buf.Bytes())) assert.Equal(t, hex.EncodeToString(rawBlockBytes), hex.EncodeToString(buf.Bytes()))
} }

View file

@ -1,8 +1,7 @@
package payload package payload
import ( import (
"io" "github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -56,8 +55,7 @@ func NewInventory(typ InventoryType, hashes []util.Uint256) *Inventory {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (p *Inventory) DecodeBinary(r io.Reader) error { func (p *Inventory) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
br.ReadLE(&p.Type) br.ReadLE(&p.Type)
listLen := br.ReadVarUint() listLen := br.ReadVarUint()
@ -70,8 +68,7 @@ func (p *Inventory) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (p *Inventory) EncodeBinary(w io.Writer) error { func (p *Inventory) EncodeBinary(bw *io.BinWriter) error {
bw := util.NewBinWriterFromIO(w)
bw.WriteLE(p.Type) bw.WriteLE(p.Type)
listLen := len(p.Hashes) listLen := len(p.Hashes)

View file

@ -1,10 +1,10 @@
package payload package payload
import ( import (
"bytes"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/io"
. "github.com/CityOfZion/neo-go/pkg/util" . "github.com/CityOfZion/neo-go/pkg/util"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -16,12 +16,14 @@ func TestInventoryEncodeDecode(t *testing.T) {
} }
inv := NewInventory(BlockType, hashes) inv := NewInventory(BlockType, hashes)
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
err := inv.EncodeBinary(buf) err := inv.EncodeBinary(buf.BinWriter)
assert.Nil(t, err) assert.Nil(t, err)
b := buf.Bytes()
r := io.NewBinReaderFromBuf(b)
invDecode := &Inventory{} invDecode := &Inventory{}
err = invDecode.DecodeBinary(buf) err = invDecode.DecodeBinary(r)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, inv, invDecode) assert.Equal(t, inv, invDecode)
} }
@ -29,8 +31,8 @@ func TestInventoryEncodeDecode(t *testing.T) {
func TestEmptyInv(t *testing.T) { func TestEmptyInv(t *testing.T) {
msgInv := NewInventory(TXType, []Uint256{}) msgInv := NewInventory(TXType, []Uint256{})
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
err := msgInv.EncodeBinary(buf) err := msgInv.EncodeBinary(buf.BinWriter)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, []byte{byte(TXType), 0}, buf.Bytes()) assert.Equal(t, []byte{byte(TXType), 0}, buf.Bytes())
assert.Equal(t, 0, len(msgInv.Hashes)) assert.Equal(t, 0, len(msgInv.Hashes))

View file

@ -1,9 +1,8 @@
package payload package payload
import ( import (
"io"
"github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -16,12 +15,11 @@ type MerkleBlock struct {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (m *MerkleBlock) DecodeBinary(r io.Reader) error { func (m *MerkleBlock) DecodeBinary(br *io.BinReader) error {
m.BlockBase = &core.BlockBase{} m.BlockBase = &core.BlockBase{}
if err := m.BlockBase.DecodeBinary(r); err != nil { if err := m.BlockBase.DecodeBinary(br); err != nil {
return err return err
} }
br := util.NewBinReaderFromIO(r)
m.TxCount = int(br.ReadVarUint()) m.TxCount = int(br.ReadVarUint())
n := br.ReadVarUint() n := br.ReadVarUint()
@ -34,6 +32,6 @@ func (m *MerkleBlock) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (m *MerkleBlock) EncodeBinary(w io.Writer) error { func (m *MerkleBlock) EncodeBinary(bw *io.BinWriter) error {
return nil return nil
} }

View file

@ -1,11 +1,11 @@
package payload package payload
import "io" import "github.com/CityOfZion/neo-go/pkg/io"
// Payload is anything that can be binary encoded/decoded. // Payload is anything that can be binary encoded/decoded.
type Payload interface { type Payload interface {
EncodeBinary(io.Writer) error EncodeBinary(*io.BinWriter) error
DecodeBinary(io.Reader) error DecodeBinary(*io.BinReader) error
} }
// NullPayload is a dummy payload with no fields. // NullPayload is a dummy payload with no fields.

View file

@ -1,9 +1,9 @@
package payload package payload
import ( import (
"io"
"time" "time"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -55,8 +55,7 @@ func NewVersion(id uint32, p uint16, ua string, h uint32, r bool) *Version {
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (p *Version) DecodeBinary(r io.Reader) error { func (p *Version) DecodeBinary(br *io.BinReader) error {
br := util.NewBinReaderFromIO(r)
br.ReadLE(&p.Version) br.ReadLE(&p.Version)
br.ReadLE(&p.Services) br.ReadLE(&p.Services)
br.ReadLE(&p.Timestamp) br.ReadLE(&p.Timestamp)
@ -69,8 +68,7 @@ func (p *Version) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (p *Version) EncodeBinary(w io.Writer) error { func (p *Version) EncodeBinary(br *io.BinWriter) error {
br := util.NewBinWriterFromIO(w)
br.WriteLE(p.Version) br.WriteLE(p.Version)
br.WriteLE(p.Services) br.WriteLE(p.Services)
br.WriteLE(p.Timestamp) br.WriteLE(p.Timestamp)

View file

@ -1,9 +1,9 @@
package payload package payload
import ( import (
"bytes"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -16,13 +16,15 @@ func TestVersionEncodeDecode(t *testing.T) {
version := NewVersion(id, port, useragent, height, relay) version := NewVersion(id, port, useragent, height, relay)
buf := new(bytes.Buffer) buf := io.NewBufBinWriter()
err := version.EncodeBinary(buf) err := version.EncodeBinary(buf.BinWriter)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, int(version.Size()), buf.Len()) b := buf.Bytes()
assert.Equal(t, int(version.Size()), len(b))
r := io.NewBinReaderFromBuf(b)
versionDecoded := &Version{} versionDecoded := &Version{}
err = versionDecoded.DecodeBinary(buf) err = versionDecoded.DecodeBinary(r)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, versionDecoded.Nonce, id) assert.Equal(t, versionDecoded.Nonce, id)
assert.Equal(t, versionDecoded.Port, port) assert.Equal(t, versionDecoded.Port, port)

View file

@ -6,6 +6,7 @@ import (
"net" "net"
"sync" "sync"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/network/payload" "github.com/CityOfZion/neo-go/pkg/network/payload"
) )
@ -68,7 +69,8 @@ func (p *TCPPeer) writeMsg(msg *Message) error {
case err := <-p.done: case err := <-p.done:
return err return err
default: default:
return msg.Encode(p.conn) w := io.NewBinWriterFromIO(p.conn)
return msg.Encode(w)
} }
} }

View file

@ -5,6 +5,7 @@ import (
"regexp" "regexp"
"time" "time"
"github.com/CityOfZion/neo-go/pkg/io"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@ -77,9 +78,10 @@ func (t *TCPTransport) handleConn(conn net.Conn) {
t.server.register <- p t.server.register <- p
r := io.NewBinReaderFromIO(p.conn)
for { for {
msg := &Message{} msg := &Message{}
if err = msg.Decode(p.conn); err != nil { if err = msg.Decode(r); err != nil {
break break
} }
if err = t.server.handleMessage(p, msg); err != nil { if err = t.server.handleMessage(p, msg); err != nil {

View file

@ -1,10 +1,10 @@
package rpc package rpc
import ( import (
"bytes"
"encoding/hex" "encoding/hex"
"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/smartcontract" "github.com/CityOfZion/neo-go/pkg/smartcontract"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -113,7 +113,7 @@ func (c *Client) sendRawTransaction(rawTX string) (*response, error) {
func (c *Client) SendToAddress(asset util.Uint256, address string, amount util.Fixed8) (*SendToAddressResponse, error) { func (c *Client) SendToAddress(asset util.Uint256, address string, amount util.Fixed8) (*SendToAddressResponse, error) {
var ( var (
err error err error
buf = &bytes.Buffer{} buf = io.NewBufBinWriter()
rawTx *transaction.Transaction rawTx *transaction.Transaction
rawTxStr string rawTxStr string
txParams = ContractTxParams{ txParams = ContractTxParams{
@ -130,7 +130,7 @@ func (c *Client) SendToAddress(asset util.Uint256, address string, amount util.F
if rawTx, err = CreateRawContractTransaction(txParams); err != nil { if rawTx, err = CreateRawContractTransaction(txParams); err != nil {
return nil, errors.Wrap(err, "failed to create raw transaction for `sendtoaddress`") return nil, errors.Wrap(err, "failed to create raw transaction for `sendtoaddress`")
} }
if err = rawTx.EncodeBinary(buf); err != nil { if err = rawTx.EncodeBinary(buf.BinWriter); err != nil {
return nil, errors.Wrap(err, "failed to encode raw transaction to binary for `sendtoaddress`") return nil, errors.Wrap(err, "failed to encode raw transaction to binary for `sendtoaddress`")
} }
rawTxStr = hex.EncodeToString(buf.Bytes()) rawTxStr = hex.EncodeToString(buf.Bytes())

View file

@ -1,7 +1,6 @@
package rpc package rpc
import ( import (
"bytes"
"context" "context"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
@ -11,6 +10,7 @@ import (
"github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto"
"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/result" "github.com/CityOfZion/neo-go/pkg/rpc/result"
"github.com/CityOfZion/neo-go/pkg/rpc/wrappers" "github.com/CityOfZion/neo-go/pkg/rpc/wrappers"
@ -294,7 +294,7 @@ func (s *Server) sendrawtransaction(reqParams Params) (interface{}, error) {
} else if byteTx, err := hex.DecodeString(param.StringVal); err != nil { } else if byteTx, err := hex.DecodeString(param.StringVal); err != nil {
resultsErr = errInvalidParams resultsErr = errInvalidParams
} else { } else {
r := bytes.NewReader(byteTx) r := io.NewBinReaderFromBuf(byteTx)
tx := &transaction.Transaction{} tx := &transaction.Transaction{}
err = tx.DecodeBinary(r) err = tx.DecodeBinary(r)
if err != nil { if err != nil {

View file

@ -1,11 +1,10 @@
package rpc package rpc
import ( import (
"bytes"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
errs "github.com/pkg/errors" errs "github.com/pkg/errors"
) )
@ -71,10 +70,10 @@ func GetInvocationScript(tx *transaction.Transaction, wif keys.WIF) ([]byte, err
) )
var ( var (
err error err error
buf = new(bytes.Buffer) buf = io.NewBufBinWriter()
signature []byte signature []byte
) )
if err = tx.EncodeBinary(buf); err != nil { if err = tx.EncodeBinary(buf.BinWriter); err != nil {
return nil, errs.Wrap(err, "Failed to encode transaction to binary") return nil, errs.Wrap(err, "Failed to encode transaction to binary")
} }
data := buf.Bytes() data := buf.Bytes()

View file

@ -4,7 +4,7 @@ import (
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/vm" "github.com/CityOfZion/neo-go/pkg/vm"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -21,7 +21,7 @@ func TestCreateMultiSigRedeemScript(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
br := util.NewBinReaderFromBuf(out) br := io.NewBinReaderFromBuf(out)
var b uint8 var b uint8
br.ReadLE(&b) br.ReadLE(&b)
assert.Equal(t, vm.PUSH3, vm.Instruction(b)) assert.Equal(t, vm.PUSH3, vm.Instruction(b))

View file

@ -2,9 +2,9 @@ package util
import ( import (
"fmt" "fmt"
"io"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -12,11 +12,11 @@ import (
type smthSerializable struct { type smthSerializable struct {
} }
func (*smthSerializable) DecodeBinary(io.Reader) error { func (*smthSerializable) DecodeBinary(*io.BinReader) error {
return nil return nil
} }
func (*smthSerializable) EncodeBinary(io.Writer) error { func (*smthSerializable) EncodeBinary(*io.BinWriter) error {
return nil return nil
} }