diff --git a/pkg/core/account_state.go b/pkg/core/account_state.go index 7325b1b4d..d5c1f6bbb 100644 --- a/pkg/core/account_state.go +++ b/pkg/core/account_state.go @@ -1,12 +1,11 @@ package core import ( - "bytes" "fmt" - "io" "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/crypto/keys" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -21,7 +20,7 @@ func (a Accounts) getAndUpdate(s storage.Store, hash util.Uint160) (*AccountStat account := &AccountState{} key := storage.AppendPrefix(storage.STAccount, hash.Bytes()) 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) } } 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. func (a Accounts) commit(b storage.Batch) error { - buf := new(bytes.Buffer) + buf := io.NewBufBinWriter() for hash, state := range a { - if err := state.EncodeBinary(buf); err != nil { + if err := state.EncodeBinary(buf.BinWriter); err != nil { return err } 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. -func (s *AccountState) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +// DecodeBinary decodes AccountState from the given BinReader. +func (s *AccountState) DecodeBinary(br *io.BinReader) error { br.ReadLE(&s.Version) br.ReadLE(&s.ScriptHash) br.ReadLE(&s.IsFrozen) @@ -76,7 +74,7 @@ func (s *AccountState) DecodeBinary(r io.Reader) error { s.Votes = make([]*keys.PublicKey, lenVotes) for i := 0; i < int(lenVotes); i++ { 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 } } @@ -94,15 +92,14 @@ func (s *AccountState) DecodeBinary(r io.Reader) error { return br.Err } -// EncodeBinary encode AccountState to the given io.Writer. -func (s *AccountState) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +// EncodeBinary encodes AccountState to the given BinWriter. +func (s *AccountState) EncodeBinary(bw *io.BinWriter) error { bw.WriteLE(s.Version) bw.WriteLE(s.ScriptHash) bw.WriteLE(s.IsFrozen) bw.WriteVarUint(uint64(len(s.Votes))) for _, point := range s.Votes { - if err := point.EncodeBinary(w); err != nil { + if err := point.EncodeBinary(bw); err != nil { return err } } diff --git a/pkg/core/account_state_test.go b/pkg/core/account_state_test.go index 82009be0d..a6b0a8645 100644 --- a/pkg/core/account_state_test.go +++ b/pkg/core/account_state_test.go @@ -1,10 +1,10 @@ package core import ( - "bytes" "testing" "github.com/CityOfZion/neo-go/pkg/crypto/keys" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" "github.com/stretchr/testify/assert" ) @@ -30,13 +30,13 @@ func TestDecodeEncodeAccountState(t *testing.T) { Balances: balances, } - buf := new(bytes.Buffer) - if err := a.EncodeBinary(buf); err != nil { + buf := io.NewBufBinWriter() + if err := a.EncodeBinary(buf.BinWriter); err != nil { t.Fatal(err) } aDecode := &AccountState{} - if err := aDecode.DecodeBinary(buf); err != nil { + if err := aDecode.DecodeBinary(io.NewBinReaderFromBuf(buf.Bytes())); err != nil { t.Fatal(err) } diff --git a/pkg/core/asset_state.go b/pkg/core/asset_state.go index 02707eee9..712be5bcc 100644 --- a/pkg/core/asset_state.go +++ b/pkg/core/asset_state.go @@ -1,12 +1,10 @@ package core import ( - "bytes" - "io" - "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/crypto/keys" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -16,9 +14,9 @@ const feeMode = 0x0 type Assets map[util.Uint256]*AssetState func (a Assets) commit(b storage.Batch) error { - buf := new(bytes.Buffer) + buf := io.NewBufBinWriter() for hash, state := range a { - if err := state.EncodeBinary(buf); err != nil { + if err := state.EncodeBinary(buf.BinWriter); err != nil { return err } key := storage.AppendPrefix(storage.STAsset, hash.Bytes()) @@ -46,8 +44,7 @@ type AssetState struct { } // DecodeBinary implements the Payload interface. -func (a *AssetState) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (a *AssetState) DecodeBinary(br *io.BinReader) error { br.ReadLE(&a.ID) br.ReadLE(&a.AssetType) @@ -63,7 +60,7 @@ func (a *AssetState) DecodeBinary(r io.Reader) error { return br.Err } a.Owner = &keys.PublicKey{} - if err := a.Owner.DecodeBinary(r); err != nil { + if err := a.Owner.DecodeBinary(br); err != nil { return err } br.ReadLE(&a.Admin) @@ -75,8 +72,7 @@ func (a *AssetState) DecodeBinary(r io.Reader) error { } // EncodeBinary implements the Payload interface. -func (a *AssetState) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +func (a *AssetState) EncodeBinary(bw *io.BinWriter) error { bw.WriteLE(a.ID) bw.WriteLE(a.AssetType) bw.WriteString(a.Name) @@ -89,7 +85,7 @@ func (a *AssetState) EncodeBinary(w io.Writer) error { if bw.Err != nil { return bw.Err } - if err := a.Owner.EncodeBinary(w); err != nil { + if err := a.Owner.EncodeBinary(bw); err != nil { return err } bw.WriteLE(a.Admin) diff --git a/pkg/core/asset_state_test.go b/pkg/core/asset_state_test.go index 952c81fc4..cbebd3db2 100644 --- a/pkg/core/asset_state_test.go +++ b/pkg/core/asset_state_test.go @@ -1,11 +1,11 @@ package core import ( - "bytes" "testing" "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/crypto/keys" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" "github.com/stretchr/testify/assert" ) @@ -26,9 +26,9 @@ func TestEncodeDecodeAssetState(t *testing.T) { IsFrozen: false, } - buf := new(bytes.Buffer) - assert.Nil(t, asset.EncodeBinary(buf)) + buf := io.NewBufBinWriter() + assert.Nil(t, asset.EncodeBinary(buf.BinWriter)) assetDecode := &AssetState{} - assert.Nil(t, assetDecode.DecodeBinary(buf)) + assert.Nil(t, assetDecode.DecodeBinary(io.NewBinReaderFromBuf(buf.Bytes()))) assert.Equal(t, asset, assetDecode) } diff --git a/pkg/core/block.go b/pkg/core/block.go index e17483e4d..19d8cedd7 100644 --- a/pkg/core/block.go +++ b/pkg/core/block.go @@ -1,11 +1,9 @@ package core import ( - "bytes" - "io" - "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/crypto" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" log "github.com/sirupsen/logrus" ) @@ -73,12 +71,11 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) { Trimmed: true, } - r := bytes.NewReader(b) - if err := block.decodeHashableFields(r); err != nil { + br := io.NewBinReaderFromBuf(b) + if err := block.decodeHashableFields(br); err != nil { return block, err } - br := util.NewBinReaderFromIO(r) var padding uint8 br.ReadLE(&padding) if br.Err != nil { @@ -86,7 +83,7 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) { } block.Script = &transaction.Witness{} - if err := block.Script.DecodeBinary(r); err != nil { + if err := block.Script.DecodeBinary(br); err != nil { return block, err } @@ -105,36 +102,34 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) { // in storage. // Notice that only the hashes of the transactions are stored. func (b *Block) Trim() ([]byte, error) { - buf := new(bytes.Buffer) - if err := b.encodeHashableFields(buf); err != nil { + buf := io.NewBufBinWriter() + if err := b.encodeHashableFields(buf.BinWriter); err != nil { return nil, err } - bw := util.NewBinWriterFromIO(buf) - bw.WriteLE(uint8(1)) - if bw.Err != nil { - return nil, bw.Err + buf.WriteLE(uint8(1)) + if buf.Err != nil { + return nil, buf.Err } - if err := b.Script.EncodeBinary(buf); err != nil { + if err := b.Script.EncodeBinary(buf.BinWriter); err != nil { return nil, err } - bw.WriteVarUint(uint64(len(b.Transactions))) + buf.WriteVarUint(uint64(len(b.Transactions))) for _, tx := range b.Transactions { - bw.WriteLE(tx.Hash()) + buf.WriteLE(tx.Hash()) } - if bw.Err != nil { - return nil, bw.Err + if buf.Err != nil { + return nil, buf.Err } return buf.Bytes(), nil } // DecodeBinary decodes the block from the given reader. -func (b *Block) DecodeBinary(r io.Reader) error { - if err := b.BlockBase.DecodeBinary(r); err != nil { +func (b *Block) DecodeBinary(br *io.BinReader) error { + if err := b.BlockBase.DecodeBinary(br); err != nil { return err } - br := util.NewBinReaderFromIO(r) lentx := br.ReadVarUint() if br.Err != nil { return br.Err @@ -142,7 +137,7 @@ func (b *Block) DecodeBinary(r io.Reader) error { b.Transactions = make([]*transaction.Transaction, lentx) for i := 0; i < int(lentx); i++ { 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 } } @@ -151,18 +146,17 @@ func (b *Block) DecodeBinary(r io.Reader) error { } // EncodeBinary encodes the block to the given writer. -func (b *Block) EncodeBinary(w io.Writer) error { - err := b.BlockBase.EncodeBinary(w) +func (b *Block) EncodeBinary(bw *io.BinWriter) error { + err := b.BlockBase.EncodeBinary(bw) if err != nil { return err } - bw := util.NewBinWriterFromIO(w) bw.WriteVarUint(uint64(len(b.Transactions))) if bw.Err != nil { return err } for _, tx := range b.Transactions { - err := tx.EncodeBinary(w) + err := tx.EncodeBinary(bw) if err != nil { return err } diff --git a/pkg/core/block_base.go b/pkg/core/block_base.go index 75f769340..4e063db0e 100644 --- a/pkg/core/block_base.go +++ b/pkg/core/block_base.go @@ -1,12 +1,11 @@ package core import ( - "bytes" "fmt" - "io" "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/crypto/hash" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -60,13 +59,12 @@ func (b *BlockBase) Hash() util.Uint256 { } // DecodeBinary implements the payload interface. -func (b *BlockBase) DecodeBinary(r io.Reader) error { - if err := b.decodeHashableFields(r); err != nil { +func (b *BlockBase) DecodeBinary(br *io.BinReader) error { + if err := b.decodeHashableFields(br); err != nil { return err } var padding uint8 - br := util.NewBinReaderFromIO(r) br.ReadLE(&padding) if br.Err != nil { return br.Err @@ -76,20 +74,19 @@ func (b *BlockBase) DecodeBinary(r io.Reader) error { } b.Script = &transaction.Witness{} - return b.Script.DecodeBinary(r) + return b.Script.DecodeBinary(br) } // EncodeBinary implements the Payload interface -func (b *BlockBase) EncodeBinary(w io.Writer) error { - if err := b.encodeHashableFields(w); err != nil { +func (b *BlockBase) EncodeBinary(bw *io.BinWriter) error { + if err := b.encodeHashableFields(bw); err != nil { return err } - bw := util.NewBinWriterFromIO(w) bw.WriteLE(uint8(1)) if bw.Err != nil { return bw.Err } - return b.Script.EncodeBinary(w) + return b.Script.EncodeBinary(bw) } // 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, // the modification of transaction will influence the hash value of the block. func (b *BlockBase) createHash() error { - buf := new(bytes.Buffer) - if err := b.encodeHashableFields(buf); err != nil { + buf := io.NewBufBinWriter() + if err := b.encodeHashableFields(buf.BinWriter); err != nil { return err } b.hash = hash.DoubleSha256(buf.Bytes()) @@ -110,8 +107,7 @@ func (b *BlockBase) createHash() error { // encodeHashableFields will only encode the fields used for hashing. // see Hash() for more information about the fields. -func (b *BlockBase) encodeHashableFields(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +func (b *BlockBase) encodeHashableFields(bw *io.BinWriter) error { bw.WriteLE(b.Version) bw.WriteLE(b.PrevHash) 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. // see Hash() for more information about the fields. -func (b *BlockBase) decodeHashableFields(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (b *BlockBase) decodeHashableFields(br *io.BinReader) error { br.ReadLE(&b.Version) br.ReadLE(&b.PrevHash) br.ReadLE(&b.MerkleRoot) diff --git a/pkg/core/block_test.go b/pkg/core/block_test.go index 3191e959d..ffa159e40 100644 --- a/pkg/core/block_test.go +++ b/pkg/core/block_test.go @@ -1,12 +1,12 @@ package core import ( - "bytes" "encoding/hex" "testing" "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/crypto" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/stretchr/testify/assert" ) @@ -24,7 +24,7 @@ func TestDecodeBlock1(t *testing.T) { } block := &Block{} - if err := block.DecodeBinary(bytes.NewReader(b)); err != nil { + if err := block.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil { t.Fatal(err) } @@ -109,7 +109,7 @@ func TestBinBlockDecodeEncode(t *testing.T) { b := Block{} - r := bytes.NewReader(rawtxBytes) + r := io.NewBinReaderFromBuf(rawtxBytes) err := b.DecodeBinary(r) assert.Nil(t, err) expected := map[string]bool{ // 18 trans @@ -165,9 +165,9 @@ func TestBinBlockDecodeEncode(t *testing.T) { } 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.Equal(t, rawtx, hex.EncodeToString(buf.Bytes())) @@ -185,7 +185,7 @@ func TestBlockSizeCalculation(t *testing.T) { b := Block{} - r := bytes.NewReader(rawBlockBytes) + r := io.NewBinReaderFromBuf(rawBlockBytes) err := b.DecodeBinary(r) 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, "0006d3ff96e269f599eb1b5c5a527c218439e498dcc65b63794591bbcdc0516b", b.Hash().ReverseString()) - buf := new(bytes.Buffer) + buf := io.NewBufBinWriter() - err = b.EncodeBinary(buf) + err = b.EncodeBinary(buf.BinWriter) assert.Nil(t, err) + benc := buf.Bytes() // test size of the block - assert.Equal(t, 7360, buf.Len()) - assert.Equal(t, rawBlock, hex.EncodeToString(buf.Bytes())) + assert.Equal(t, 7360, len(benc)) + assert.Equal(t, rawBlock, hex.EncodeToString(benc)) } diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index f751fe2e8..a31b0b037 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -1,9 +1,7 @@ package core import ( - "bytes" "context" - "encoding/binary" "fmt" "math" "sync/atomic" @@ -12,6 +10,7 @@ import ( "github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/transaction" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" "github.com/pkg/errors" 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 { headerList.Add(h.Hash()) - buf := new(bytes.Buffer) + buf := io.NewBufBinWriter() 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 } key := storage.AppendPrefixInt(storage.IXHeaderHashList, int(bc.storedHeaderCount)) @@ -255,7 +254,7 @@ func (bc *Blockchain) processHeader(h *Header, batch storage.Batch, headerList * } buf.Reset() - if err := h.EncodeBinary(buf); err != nil { + if err := h.EncodeBinary(buf.BinWriter); err != nil { return err } @@ -467,11 +466,12 @@ func (bc *Blockchain) GetTransaction(hash util.Uint256) (*transaction.Transactio if err != nil { return nil, 0, err } - r := bytes.NewReader(b) + r := io.NewBinReaderFromBuf(b) var height uint32 - if err := binary.Read(r, binary.LittleEndian, &height); err != nil { - return nil, 0, err + r.ReadLE(&height) + if r.Err != nil { + return nil, 0, r.Err } tx := &transaction.Transaction{} @@ -578,7 +578,7 @@ func (bc *Blockchain) GetAssetState(assetID util.Uint256) *AssetState { var as *AssetState bc.Store.Seek(storage.STAsset.Bytes(), func(k, v []byte) { 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 } }) @@ -591,7 +591,7 @@ func (bc *Blockchain) GetAccountState(scriptHash util.Uint160) *AccountState { var as *AccountState bc.Store.Seek(storage.STAccount.Bytes(), func(k, v []byte) { 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 } }) @@ -921,9 +921,10 @@ func (bc *Blockchain) VerifyWitnesses(t *transaction.Transaction) error { } func hashAndIndexToBytes(h util.Uint256, index uint32) []byte { - buf := make([]byte, 4) - binary.LittleEndian.PutUint32(buf, index) - return append(h.BytesReverse(), buf...) + buf := io.NewBufBinWriter() + buf.WriteLE(h.BytesReverse()) + buf.WriteLE(index) + return buf.Bytes() } func (bc *Blockchain) secondsPerBlock() int { diff --git a/pkg/core/header.go b/pkg/core/header.go index 79b0e56ed..659270cc5 100644 --- a/pkg/core/header.go +++ b/pkg/core/header.go @@ -1,9 +1,9 @@ package core import ( - "encoding/binary" "fmt" - "io" + + "github.com/CityOfZion/neo-go/pkg/io" ) // Header holds the head info of a block. @@ -15,14 +15,15 @@ type Header struct { } // 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 { return err } var padding uint8 - if err := binary.Read(r, binary.LittleEndian, &padding); err != nil { - return err + r.ReadLE(&padding) + if r.Err != nil { + return r.Err } if padding != 0 { @@ -33,9 +34,8 @@ func (h *Header) DecodeBinary(r io.Reader) error { } // EncodeBinary implements the Payload interface. -func (h *Header) EncodeBinary(w io.Writer) error { - if err := h.BlockBase.EncodeBinary(w); err != nil { - return err - } - return binary.Write(w, binary.LittleEndian, uint8(0)) +func (h *Header) EncodeBinary(w *io.BinWriter) error { + h.BlockBase.EncodeBinary(w) + w.WriteLE(uint8(0)) + return w.Err } diff --git a/pkg/core/header_hash_list.go b/pkg/core/header_hash_list.go index d54723aba..9f6ffbdf2 100644 --- a/pkg/core/header_hash_list.go +++ b/pkg/core/header_hash_list.go @@ -1,8 +1,7 @@ package core import ( - "io" - + "github.com/CityOfZion/neo-go/pkg/io" "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] } -// WriteTo will write n underlying hashes to the given io.Writer +// WriteTo will write n underlying hashes to the given BinWriter // starting from start. -func (l *HeaderHashList) Write(w io.Writer, start, n int) error { - bw := util.NewBinWriterFromIO(w) +func (l *HeaderHashList) Write(bw *io.BinWriter, start, n int) error { bw.WriteVarUint(uint64(n)) hashes := l.Slice(start, start+n) for _, hash := range hashes { diff --git a/pkg/core/header_test.go b/pkg/core/header_test.go index dcd83d7c0..8b7bcf19f 100644 --- a/pkg/core/header_test.go +++ b/pkg/core/header_test.go @@ -1,12 +1,12 @@ package core import ( - "bytes" "testing" "time" "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/crypto/hash" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" "github.com/stretchr/testify/assert" ) @@ -26,13 +26,13 @@ func TestHeaderEncodeDecode(t *testing.T) { }, }} - buf := new(bytes.Buffer) - if err := header.EncodeBinary(buf); err != nil { + buf := io.NewBufBinWriter() + if err := header.EncodeBinary(buf.BinWriter); err != nil { t.Fatal(err) } headerDecode := &Header{} - if err := headerDecode.DecodeBinary(buf); err != nil { + if err := headerDecode.DecodeBinary(io.NewBinReaderFromBuf(buf.Bytes())); err != nil { t.Fatal(err) } assert.Equal(t, header.Version, headerDecode.Version, "expected both versions to be equal") diff --git a/pkg/core/helper_test.go b/pkg/core/helper_test.go index 27317f64a..1ab25d3e9 100644 --- a/pkg/core/helper_test.go +++ b/pkg/core/helper_test.go @@ -1,7 +1,6 @@ package core import ( - "bytes" "encoding/hex" "encoding/json" "fmt" @@ -11,6 +10,7 @@ import ( "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/crypto/hash" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -63,7 +63,7 @@ func getDecodedBlock(t *testing.T, i int) *Block { } block := &Block{} - if err := block.DecodeBinary(bytes.NewReader(b)); err != nil { + if err := block.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil { t.Fatal(err) } diff --git a/pkg/core/spent_coin_state.go b/pkg/core/spent_coin_state.go index 594fd3756..21db15fb9 100644 --- a/pkg/core/spent_coin_state.go +++ b/pkg/core/spent_coin_state.go @@ -1,11 +1,10 @@ package core import ( - "bytes" "fmt" - "io" "github.com/CityOfZion/neo-go/pkg/core/storage" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -21,7 +20,7 @@ func (s SpentCoins) getAndUpdate(store storage.Store, hash util.Uint256) (*Spent spent := &SpentCoinState{} key := storage.AppendPrefix(storage.STSpentCoin, hash.BytesReverse()) 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) } } else { @@ -35,9 +34,9 @@ func (s SpentCoins) getAndUpdate(store storage.Store, hash util.Uint256) (*Spent } func (s SpentCoins) commit(b storage.Batch) error { - buf := new(bytes.Buffer) + buf := io.NewBufBinWriter() for hash, state := range s { - if err := state.EncodeBinary(buf); err != nil { + if err := state.EncodeBinary(buf.BinWriter); err != nil { return err } key := storage.AppendPrefix(storage.STSpentCoin, hash.BytesReverse()) @@ -66,8 +65,7 @@ func NewSpentCoinState(hash util.Uint256, height uint32) *SpentCoinState { } // DecodeBinary implements the Payload interface. -func (s *SpentCoinState) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (s *SpentCoinState) DecodeBinary(br *io.BinReader) error { br.ReadLE(&s.txHash) br.ReadLE(&s.txHeight) @@ -86,8 +84,7 @@ func (s *SpentCoinState) DecodeBinary(r io.Reader) error { } // EncodeBinary implements the Payload interface. -func (s *SpentCoinState) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +func (s *SpentCoinState) EncodeBinary(bw *io.BinWriter) error { bw.WriteLE(s.txHash) bw.WriteLE(s.txHeight) bw.WriteVarUint(uint64(len(s.items))) diff --git a/pkg/core/spent_coin_state_test.go b/pkg/core/spent_coin_state_test.go index 8a2b03981..dde497e3d 100644 --- a/pkg/core/spent_coin_state_test.go +++ b/pkg/core/spent_coin_state_test.go @@ -1,10 +1,10 @@ package core import ( - "bytes" "testing" "github.com/CityOfZion/neo-go/pkg/core/storage" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" "github.com/stretchr/testify/assert" ) @@ -20,10 +20,10 @@ func TestEncodeDecodeSpentCoinState(t *testing.T) { }, } - buf := new(bytes.Buffer) - assert.Nil(t, spent.EncodeBinary(buf)) + buf := io.NewBufBinWriter() + assert.Nil(t, spent.EncodeBinary(buf.BinWriter)) spentDecode := new(SpentCoinState) - assert.Nil(t, spentDecode.DecodeBinary(buf)) + assert.Nil(t, spentDecode.DecodeBinary(io.NewBinReaderFromBuf(buf.Bytes()))) assert.Equal(t, spent, spentDecode) } diff --git a/pkg/core/storage/helpers.go b/pkg/core/storage/helpers.go index ca3c1a7c2..8916a5615 100644 --- a/pkg/core/storage/helpers.go +++ b/pkg/core/storage/helpers.go @@ -5,6 +5,7 @@ import ( "encoding/binary" "sort" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -84,7 +85,7 @@ func HeaderHashes(s Store) ([]util.Uint256, error) { // the given byte array. func read2000Uint256Hashes(b []byte) ([]util.Uint256, error) { r := bytes.NewReader(b) - br := util.NewBinReaderFromIO(r) + br := io.NewBinReaderFromIO(r) lenHashes := br.ReadVarUint() hashes := make([]util.Uint256, lenHashes) br.ReadLE(hashes) diff --git a/pkg/core/transaction/attribute.go b/pkg/core/transaction/attribute.go index c5df619f3..b4e07aee4 100644 --- a/pkg/core/transaction/attribute.go +++ b/pkg/core/transaction/attribute.go @@ -4,8 +4,8 @@ import ( "encoding/hex" "encoding/json" "fmt" - "io" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -16,8 +16,7 @@ type Attribute struct { } // DecodeBinary implements the Payload interface. -func (attr *Attribute) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (attr *Attribute) DecodeBinary(br *io.BinReader) error { br.ReadLE(&attr.Usage) // very special case @@ -53,8 +52,7 @@ func (attr *Attribute) DecodeBinary(r io.Reader) error { } // EncodeBinary implements the Payload interface. -func (attr *Attribute) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +func (attr *Attribute) EncodeBinary(bw *io.BinWriter) error { bw.WriteLE(&attr.Usage) switch attr.Usage { case ECDH02, ECDH03: diff --git a/pkg/core/transaction/claim.go b/pkg/core/transaction/claim.go index f5c7c8e8d..bb864548c 100644 --- a/pkg/core/transaction/claim.go +++ b/pkg/core/transaction/claim.go @@ -1,8 +1,7 @@ package transaction import ( - "io" - + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -12,8 +11,7 @@ type ClaimTX struct { } // DecodeBinary implements the Payload interface. -func (tx *ClaimTX) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (tx *ClaimTX) DecodeBinary(br *io.BinReader) error { lenClaims := br.ReadVarUint() if br.Err != nil { return br.Err @@ -21,7 +19,7 @@ func (tx *ClaimTX) DecodeBinary(r io.Reader) error { tx.Claims = make([]*Input, lenClaims) for i := 0; i < int(lenClaims); i++ { tx.Claims[i] = &Input{} - if err := tx.Claims[i].DecodeBinary(r); err != nil { + if err := tx.Claims[i].DecodeBinary(br); err != nil { return err } } @@ -29,14 +27,13 @@ func (tx *ClaimTX) DecodeBinary(r io.Reader) error { } // EncodeBinary implements the Payload interface. -func (tx *ClaimTX) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +func (tx *ClaimTX) EncodeBinary(bw *io.BinWriter) error { bw.WriteVarUint(uint64(len(tx.Claims))) if bw.Err != nil { return bw.Err } for _, claim := range tx.Claims { - if err := claim.EncodeBinary(w); err != nil { + if err := claim.EncodeBinary(bw); err != nil { return err } } diff --git a/pkg/core/transaction/contract.go b/pkg/core/transaction/contract.go index e36a1ded4..c7d91fa12 100644 --- a/pkg/core/transaction/contract.go +++ b/pkg/core/transaction/contract.go @@ -1,7 +1,7 @@ package transaction import ( - "io" + "github.com/CityOfZion/neo-go/pkg/io" ) // ContractTX represents a contract transaction. @@ -16,12 +16,12 @@ func NewContractTX() *Transaction { } // DecodeBinary implements the Payload interface. -func (tx *ContractTX) DecodeBinary(r io.Reader) error { +func (tx *ContractTX) DecodeBinary(r *io.BinReader) error { return nil } // EncodeBinary implements the Payload interface. -func (tx *ContractTX) EncodeBinary(w io.Writer) error { +func (tx *ContractTX) EncodeBinary(w *io.BinWriter) error { return nil } diff --git a/pkg/core/transaction/contract_test.go b/pkg/core/transaction/contract_test.go index cd3e512b9..43e7d19b2 100644 --- a/pkg/core/transaction/contract_test.go +++ b/pkg/core/transaction/contract_test.go @@ -1,10 +1,10 @@ package transaction import ( - "bytes" "encoding/hex" "testing" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/stretchr/testify/assert" ) @@ -29,9 +29,9 @@ func TestEncodeDecodeContract(t *testing.T) { assert.Equal(t, "bdf6cc3b9af12a7565bda80933a75ee8cef1bc771d0d58effc08e4c8b436da79", tx.Hash().ReverseString()) // 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, rawtx, hex.EncodeToString(buf.Bytes())) } diff --git a/pkg/core/transaction/enrollment.go b/pkg/core/transaction/enrollment.go index 752f6b9ee..9ef1b4f68 100644 --- a/pkg/core/transaction/enrollment.go +++ b/pkg/core/transaction/enrollment.go @@ -1,9 +1,8 @@ package transaction import ( - "io" - "github.com/CityOfZion/neo-go/pkg/crypto/keys" + "github.com/CityOfZion/neo-go/pkg/io" ) // EnrollmentTX transaction represents an enrollment form, which indicates @@ -17,13 +16,13 @@ type EnrollmentTX struct { } // 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{} return tx.PublicKey.DecodeBinary(r) } // 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) } diff --git a/pkg/core/transaction/enrollment_test.go b/pkg/core/transaction/enrollment_test.go index efec21d71..fa669fc0e 100644 --- a/pkg/core/transaction/enrollment_test.go +++ b/pkg/core/transaction/enrollment_test.go @@ -1,10 +1,10 @@ package transaction import ( - "bytes" "encoding/hex" "testing" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/stretchr/testify/assert" ) @@ -16,8 +16,8 @@ func TestEncodeDecodeEnrollment(t *testing.T) { assert.IsType(t, tx.Data, &EnrollmentTX{}) assert.Equal(t, 0, int(tx.Version)) - buf := new(bytes.Buffer) - err := tx.EncodeBinary(buf) + buf := io.NewBufBinWriter() + err := tx.EncodeBinary(buf.BinWriter) assert.Equal(t, nil, err) assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes())) diff --git a/pkg/core/transaction/helper_test.go b/pkg/core/transaction/helper_test.go index d727ca73d..2cc7cc121 100644 --- a/pkg/core/transaction/helper_test.go +++ b/pkg/core/transaction/helper_test.go @@ -1,10 +1,10 @@ package transaction import ( - "bytes" "encoding/hex" "testing" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/stretchr/testify/assert" ) @@ -21,7 +21,7 @@ func decodeTransaction(rawTX string, t *testing.T) *Transaction { b, err1 := hex.DecodeString(rawTX) assert.Nil(t, err1) tx := &Transaction{} - err2 := tx.DecodeBinary(bytes.NewReader(b)) + err2 := tx.DecodeBinary(io.NewBinReaderFromBuf(b)) assert.Nil(t, err2) return tx } diff --git a/pkg/core/transaction/input.go b/pkg/core/transaction/input.go index f2bd3e4df..cce3db6c3 100644 --- a/pkg/core/transaction/input.go +++ b/pkg/core/transaction/input.go @@ -1,8 +1,7 @@ package transaction import ( - "io" - + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -16,16 +15,14 @@ type Input struct { } // DecodeBinary implements the Payload interface. -func (in *Input) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (in *Input) DecodeBinary(br *io.BinReader) error { br.ReadLE(&in.PrevHash) br.ReadLE(&in.PrevIndex) return br.Err } // EncodeBinary implements the Payload interface. -func (in *Input) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +func (in *Input) EncodeBinary(bw *io.BinWriter) error { bw.WriteLE(in.PrevHash) bw.WriteLE(in.PrevIndex) return bw.Err diff --git a/pkg/core/transaction/invocation.go b/pkg/core/transaction/invocation.go index 36df0a948..52a105bcb 100644 --- a/pkg/core/transaction/invocation.go +++ b/pkg/core/transaction/invocation.go @@ -1,8 +1,7 @@ package transaction import ( - "io" - + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -33,8 +32,7 @@ func NewInvocationTX(script []byte) *Transaction { } // DecodeBinary implements the Payload interface. -func (tx *InvocationTX) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (tx *InvocationTX) DecodeBinary(br *io.BinReader) error { tx.Script = br.ReadBytes() if tx.Version >= 1 { br.ReadLE(&tx.Gas) @@ -45,8 +43,7 @@ func (tx *InvocationTX) DecodeBinary(r io.Reader) error { } // EncodeBinary implements the Payload interface. -func (tx *InvocationTX) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +func (tx *InvocationTX) EncodeBinary(bw *io.BinWriter) error { bw.WriteBytes(tx.Script) if tx.Version >= 1 { bw.WriteLE(tx.Gas) diff --git a/pkg/core/transaction/issue.go b/pkg/core/transaction/issue.go index 1a82d2df6..7555d267b 100644 --- a/pkg/core/transaction/issue.go +++ b/pkg/core/transaction/issue.go @@ -1,7 +1,7 @@ package transaction import ( - "io" + "github.com/CityOfZion/neo-go/pkg/io" ) // IssueTX represents a issue transaction. @@ -9,12 +9,12 @@ import ( type IssueTX struct{} // DecodeBinary implements the Payload interface. -func (tx *IssueTX) DecodeBinary(r io.Reader) error { +func (tx *IssueTX) DecodeBinary(r *io.BinReader) error { return nil } // EncodeBinary implements the Payload interface. -func (tx *IssueTX) EncodeBinary(w io.Writer) error { +func (tx *IssueTX) EncodeBinary(w *io.BinWriter) error { return nil } diff --git a/pkg/core/transaction/miner.go b/pkg/core/transaction/miner.go index 3f99ad125..b64fbee9b 100644 --- a/pkg/core/transaction/miner.go +++ b/pkg/core/transaction/miner.go @@ -1,8 +1,7 @@ package transaction import ( - "encoding/binary" - "io" + "github.com/CityOfZion/neo-go/pkg/io" ) // MinerTX represents a miner transaction. @@ -12,13 +11,15 @@ type MinerTX struct { } // DecodeBinary implements the Payload interface. -func (tx *MinerTX) DecodeBinary(r io.Reader) error { - return binary.Read(r, binary.LittleEndian, &tx.Nonce) +func (tx *MinerTX) DecodeBinary(r *io.BinReader) error { + r.ReadLE(&tx.Nonce) + return r.Err } // EncodeBinary implements the Payload interface. -func (tx *MinerTX) EncodeBinary(w io.Writer) error { - return binary.Write(w, binary.LittleEndian, tx.Nonce) +func (tx *MinerTX) EncodeBinary(w *io.BinWriter) error { + w.WriteLE(tx.Nonce) + return w.Err } // Size returns serialized binary size for this transaction. diff --git a/pkg/core/transaction/miner_test.go b/pkg/core/transaction/miner_test.go index b26096ba5..c5c7a77ee 100644 --- a/pkg/core/transaction/miner_test.go +++ b/pkg/core/transaction/miner_test.go @@ -1,10 +1,10 @@ package transaction import ( - "bytes" "encoding/hex" "testing" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/stretchr/testify/assert" ) @@ -21,9 +21,9 @@ func TestEncodeDecodeMiner(t *testing.T) { assert.Equal(t, "a1f219dc6be4c35eca172e65e02d4591045220221b1543f1a4b67b9e9442c264", tx.Hash().ReverseString()) // 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, rawtx, hex.EncodeToString(buf.Bytes())) diff --git a/pkg/core/transaction/output.go b/pkg/core/transaction/output.go index 1afa21e5a..887bcb18f 100644 --- a/pkg/core/transaction/output.go +++ b/pkg/core/transaction/output.go @@ -2,9 +2,9 @@ package transaction import ( "encoding/json" - "io" "github.com/CityOfZion/neo-go/pkg/crypto" + "github.com/CityOfZion/neo-go/pkg/io" "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. -func (out *Output) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (out *Output) DecodeBinary(br *io.BinReader) error { br.ReadLE(&out.AssetID) br.ReadLE(&out.Amount) br.ReadLE(&out.ScriptHash) @@ -43,8 +42,7 @@ func (out *Output) DecodeBinary(r io.Reader) error { } // EncodeBinary implements the Payload interface. -func (out *Output) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +func (out *Output) EncodeBinary(bw *io.BinWriter) error { bw.WriteLE(out.AssetID) bw.WriteLE(out.Amount) bw.WriteLE(out.ScriptHash) diff --git a/pkg/core/transaction/publish.go b/pkg/core/transaction/publish.go index 4d20de820..c5149bc97 100644 --- a/pkg/core/transaction/publish.go +++ b/pkg/core/transaction/publish.go @@ -1,8 +1,7 @@ package transaction import ( - "io" - + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/smartcontract" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -23,8 +22,7 @@ type PublishTX struct { } // DecodeBinary implements the Payload interface. -func (tx *PublishTX) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (tx *PublishTX) DecodeBinary(br *io.BinReader) error { tx.Script = br.ReadBytes() lenParams := br.ReadVarUint() @@ -55,8 +53,7 @@ func (tx *PublishTX) DecodeBinary(r io.Reader) error { } // EncodeBinary implements the Payload interface. -func (tx *PublishTX) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +func (tx *PublishTX) EncodeBinary(bw *io.BinWriter) error { bw.WriteBytes(tx.Script) bw.WriteVarUint(uint64(len(tx.ParamList))) for _, param := range tx.ParamList { diff --git a/pkg/core/transaction/register.go b/pkg/core/transaction/register.go index 41ed9ca75..711cb7465 100644 --- a/pkg/core/transaction/register.go +++ b/pkg/core/transaction/register.go @@ -1,9 +1,8 @@ package transaction import ( - "io" - "github.com/CityOfZion/neo-go/pkg/crypto/keys" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -30,8 +29,7 @@ type RegisterTX struct { } // DecodeBinary implements the Payload interface. -func (tx *RegisterTX) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (tx *RegisterTX) DecodeBinary(br *io.BinReader) error { br.ReadLE(&tx.AssetType) tx.Name = br.ReadString() @@ -43,7 +41,7 @@ func (tx *RegisterTX) DecodeBinary(r io.Reader) error { } tx.Owner = &keys.PublicKey{} - if err := tx.Owner.DecodeBinary(r); err != nil { + if err := tx.Owner.DecodeBinary(br); err != nil { return err } @@ -52,8 +50,7 @@ func (tx *RegisterTX) DecodeBinary(r io.Reader) error { } // EncodeBinary implements the Payload interface. -func (tx *RegisterTX) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +func (tx *RegisterTX) EncodeBinary(bw *io.BinWriter) error { bw.WriteLE(tx.AssetType) bw.WriteString(tx.Name) bw.WriteLE(tx.Amount) diff --git a/pkg/core/transaction/register_test.go b/pkg/core/transaction/register_test.go index 710979e3e..c8a9419d7 100644 --- a/pkg/core/transaction/register_test.go +++ b/pkg/core/transaction/register_test.go @@ -1,12 +1,12 @@ package transaction import ( - "bytes" "encoding/hex" "testing" "github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto/keys" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" "github.com/stretchr/testify/assert" ) @@ -26,11 +26,12 @@ func TestRegisterTX(t *testing.T) { }, } - buf := new(bytes.Buffer) - assert.Nil(t, tx.EncodeBinary(buf)) + buf := io.NewBufBinWriter() + assert.Nil(t, tx.EncodeBinary(buf.BinWriter)) + b := buf.Bytes() txDecode := &Transaction{} - assert.Nil(t, txDecode.DecodeBinary(buf)) + assert.Nil(t, txDecode.DecodeBinary(io.NewBinReaderFromBuf(b))) txData := tx.Data.(*RegisterTX) txDecodeData := txDecode.Data.(*RegisterTX) assert.Equal(t, txData, txDecodeData) @@ -45,7 +46,7 @@ func TestDecodeRegisterTXFromRawString(t *testing.T) { } tx := &Transaction{} - assert.Nil(t, tx.DecodeBinary(bytes.NewReader(b))) + assert.Nil(t, tx.DecodeBinary(io.NewBinReaderFromBuf(b))) assert.Equal(t, RegisterType, tx.Type) txData := tx.Data.(*RegisterTX) 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, "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", tx.Hash().ReverseString()) - buf := new(bytes.Buffer) - assert.Nil(t, tx.EncodeBinary(buf)) + buf := io.NewBufBinWriter() + assert.Nil(t, tx.EncodeBinary(buf.BinWriter)) + benc := buf.Bytes() txDecode := &Transaction{} - assert.Nil(t, txDecode.DecodeBinary(buf)) + assert.Nil(t, txDecode.DecodeBinary(io.NewBinReaderFromBuf(benc))) assert.Equal(t, tx, txDecode) } diff --git a/pkg/core/transaction/state.go b/pkg/core/transaction/state.go index 79127d14d..490c8f6a2 100644 --- a/pkg/core/transaction/state.go +++ b/pkg/core/transaction/state.go @@ -1,8 +1,7 @@ package transaction import ( - "io" - + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -12,36 +11,29 @@ type StateTX struct { } // DecodeBinary implements the Payload interface. -func (tx *StateTX) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) - lenDesc := br.ReadVarUint() - if br.Err != nil { - return br.Err - } +func (tx *StateTX) DecodeBinary(r *io.BinReader) error { + lenDesc := r.ReadVarUint() tx.Descriptors = make([]*StateDescriptor, lenDesc) for i := 0; i < int(lenDesc); i++ { 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 nil + return r.Err } // EncodeBinary implements the Payload interface. -func (tx *StateTX) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) - bw.WriteVarUint(uint64(len(tx.Descriptors))) - if bw.Err != nil { - return bw.Err - } +func (tx *StateTX) EncodeBinary(w *io.BinWriter) error { + w.WriteVarUint(uint64(len(tx.Descriptors))) for _, desc := range tx.Descriptors { err := desc.EncodeBinary(w) if err != nil { return err } } - return nil + return w.Err } // Size returns serialized binary size for this transaction. diff --git a/pkg/core/transaction/state_descriptor.go b/pkg/core/transaction/state_descriptor.go index 2ad49c494..c7e82822e 100644 --- a/pkg/core/transaction/state_descriptor.go +++ b/pkg/core/transaction/state_descriptor.go @@ -1,8 +1,7 @@ package transaction import ( - "io" - + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -24,25 +23,23 @@ type StateDescriptor struct { } // DecodeBinary implements the Payload interface. -func (s *StateDescriptor) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) - br.ReadLE(&s.Type) +func (s *StateDescriptor) DecodeBinary(r *io.BinReader) error { + r.ReadLE(&s.Type) - s.Key = br.ReadBytes() - s.Value = br.ReadBytes() - s.Field = br.ReadString() + s.Key = r.ReadBytes() + s.Value = r.ReadBytes() + s.Field = r.ReadString() - return br.Err + return r.Err } // EncodeBinary implements the Payload interface. -func (s *StateDescriptor) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) - bw.WriteLE(s.Type) - bw.WriteBytes(s.Key) - bw.WriteBytes(s.Value) - bw.WriteString(s.Field) - return bw.Err +func (s *StateDescriptor) EncodeBinary(w *io.BinWriter) error { + w.WriteLE(s.Type) + w.WriteBytes(s.Key) + w.WriteBytes(s.Value) + w.WriteString(s.Field) + return w.Err } // Size returns serialized binary size for state descriptor. diff --git a/pkg/core/transaction/state_test.go b/pkg/core/transaction/state_test.go index 65052058c..eb425b42e 100644 --- a/pkg/core/transaction/state_test.go +++ b/pkg/core/transaction/state_test.go @@ -1,10 +1,10 @@ package transaction import ( - "bytes" "encoding/hex" "testing" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/stretchr/testify/assert" ) @@ -30,10 +30,9 @@ func TestEncodeDecodeState(t *testing.T) { assert.Equal(t, Validator, descriptor.Type) // Encode + buf := io.NewBufBinWriter() - buf := new(bytes.Buffer) - - err := tx.EncodeBinary(buf) + err := tx.EncodeBinary(buf.BinWriter) assert.Equal(t, nil, err) assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes())) diff --git a/pkg/core/transaction/transaction.go b/pkg/core/transaction/transaction.go index 8dedd17c1..3bf651317 100644 --- a/pkg/core/transaction/transaction.go +++ b/pkg/core/transaction/transaction.go @@ -1,10 +1,8 @@ package transaction import ( - "bytes" - "io" - "github.com/CityOfZion/neo-go/pkg/crypto/hash" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" log "github.com/sirupsen/logrus" ) @@ -77,14 +75,13 @@ func (t *Transaction) AddInput(in *Input) { } // DecodeBinary implements the payload interface. -func (t *Transaction) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (t *Transaction) DecodeBinary(br *io.BinReader) error { br.ReadLE(&t.Type) br.ReadLE(&t.Version) if br.Err != nil { return br.Err } - if err := t.decodeData(r); err != nil { + if err := t.decodeData(br); err != nil { return err } @@ -92,7 +89,7 @@ func (t *Transaction) DecodeBinary(r io.Reader) error { t.Attributes = make([]*Attribute, lenAttrs) for i := 0; i < int(lenAttrs); i++ { 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) return err } @@ -102,7 +99,7 @@ func (t *Transaction) DecodeBinary(r io.Reader) error { t.Inputs = make([]*Input, lenInputs) for i := 0; i < int(lenInputs); i++ { t.Inputs[i] = &Input{} - if err := t.Inputs[i].DecodeBinary(r); err != nil { + if err := t.Inputs[i].DecodeBinary(br); err != nil { return err } } @@ -111,7 +108,7 @@ func (t *Transaction) DecodeBinary(r io.Reader) error { t.Outputs = make([]*Output, lenOutputs) for i := 0; i < int(lenOutputs); i++ { t.Outputs[i] = &Output{} - if err := t.Outputs[i].DecodeBinary(r); err != nil { + if err := t.Outputs[i].DecodeBinary(br); err != nil { return err } } @@ -120,7 +117,7 @@ func (t *Transaction) DecodeBinary(r io.Reader) error { t.Scripts = make([]*Witness, lenScripts) for i := 0; i < int(lenScripts); i++ { t.Scripts[i] = &Witness{} - if err := t.Scripts[i].DecodeBinary(r); err != nil { + if err := t.Scripts[i].DecodeBinary(br); err != nil { return err } } @@ -133,7 +130,7 @@ func (t *Transaction) DecodeBinary(r io.Reader) error { return t.createHash() } -func (t *Transaction) decodeData(r io.Reader) error { +func (t *Transaction) decodeData(r *io.BinReader) error { switch t.Type { case InvocationType: t.Data = &InvocationTX{Version: t.Version} @@ -169,17 +166,16 @@ func (t *Transaction) decodeData(r io.Reader) error { } // EncodeBinary implements the payload interface. -func (t *Transaction) EncodeBinary(w io.Writer) error { - if err := t.encodeHashableFields(w); err != nil { +func (t *Transaction) EncodeBinary(bw *io.BinWriter) error { + if err := t.encodeHashableFields(bw); err != nil { return err } - bw := util.NewBinWriterFromIO(w) bw.WriteVarUint(uint64(len(t.Scripts))) if bw.Err != nil { return bw.Err } for _, s := range t.Scripts { - if err := s.EncodeBinary(w); err != nil { + if err := s.EncodeBinary(bw); err != nil { 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 // signing the transaction, which are all fields except the scripts. -func (t *Transaction) encodeHashableFields(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) - +func (t *Transaction) encodeHashableFields(bw *io.BinWriter) error { bw.WriteLE(t.Type) bw.WriteLE(t.Version) if bw.Err != nil { @@ -199,7 +193,7 @@ func (t *Transaction) encodeHashableFields(w io.Writer) error { // Underlying TXer. if t.Data != nil { - if err := t.Data.EncodeBinary(w); err != nil { + if err := t.Data.EncodeBinary(bw); err != nil { return err } } @@ -210,7 +204,7 @@ func (t *Transaction) encodeHashableFields(w io.Writer) error { return bw.Err } for _, attr := range t.Attributes { - if err := attr.EncodeBinary(w); err != nil { + if err := attr.EncodeBinary(bw); err != nil { return err } } @@ -221,7 +215,7 @@ func (t *Transaction) encodeHashableFields(w io.Writer) error { return bw.Err } for _, in := range t.Inputs { - if err := in.EncodeBinary(w); err != nil { + if err := in.EncodeBinary(bw); err != nil { return err } } @@ -232,7 +226,7 @@ func (t *Transaction) encodeHashableFields(w io.Writer) error { return bw.Err } for _, out := range t.Outputs { - if err := out.EncodeBinary(w); err != nil { + if err := out.EncodeBinary(bw); err != nil { return err } } @@ -241,8 +235,8 @@ func (t *Transaction) encodeHashableFields(w io.Writer) error { // createHash creates the hash of the transaction. func (t *Transaction) createHash() error { - buf := new(bytes.Buffer) - if err := t.encodeHashableFields(buf); err != nil { + buf := io.NewBufBinWriter() + if err := t.encodeHashableFields(buf.BinWriter); err != nil { return err } @@ -281,8 +275,8 @@ func (t *Transaction) Size() int { // Bytes convert the transaction to []byte func (t *Transaction) Bytes() []byte { - buf := new(bytes.Buffer) - if err := t.EncodeBinary(buf); err != nil { + buf := io.NewBufBinWriter() + if err := t.EncodeBinary(buf.BinWriter); err != nil { return nil } return buf.Bytes() diff --git a/pkg/core/transaction/transaction_test.go b/pkg/core/transaction/transaction_test.go index 3bfeb94da..a5387bb5f 100644 --- a/pkg/core/transaction/transaction_test.go +++ b/pkg/core/transaction/transaction_test.go @@ -1,11 +1,11 @@ package transaction import ( - "bytes" "encoding/hex" "testing" "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/util" "github.com/stretchr/testify/assert" @@ -27,15 +27,14 @@ func TestWitnessEncodeDecode(t *testing.T) { VerificationScript: verif, } - buf := new(bytes.Buffer) - if err := wit.EncodeBinary(buf); err != nil { - t.Fatal(err) - } + buf := io.NewBufBinWriter() + err = wit.EncodeBinary(buf.BinWriter) + assert.Nil(t, err) + benc := buf.Bytes() witDecode := &Witness{} - if err := witDecode.DecodeBinary(buf); err != nil { - t.Fatal(err) - } + err = witDecode.DecodeBinary(io.NewBinReaderFromBuf(benc)) + assert.Nil(t, err) t.Log(len(witDecode.VerificationScript)) 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, verif, hex.EncodeToString(tx.Scripts[0].VerificationScript)) - buf := new(bytes.Buffer) - if err := tx.EncodeBinary(buf); err != nil { - t.Fatal(err) - } + buf := io.NewBufBinWriter() + err := tx.EncodeBinary(buf.BinWriter) + assert.Nil(t, err) assert.Equal(t, rawClaimTX, hex.EncodeToString(buf.Bytes())) hash := "2c6a45547b3898318e400e541628990a07acb00f3b9a15a8e966ae49525304da" @@ -90,10 +88,10 @@ func TestDecodeEncodeInvocationTX(t *testing.T) { assert.Equal(t, invoc, hex.EncodeToString(tx.Scripts[0].InvocationScript)) assert.Equal(t, verif, hex.EncodeToString(tx.Scripts[0].VerificationScript)) - buf := new(bytes.Buffer) - if err := tx.EncodeBinary(buf); err != nil { - t.Fatal(err) - } + buf := io.NewBufBinWriter() + err := tx.EncodeBinary(buf.BinWriter) + assert.Nil(t, err) + 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.Version, actualTX.Version) - buf := new(bytes.Buffer) - err := actualTX.EncodeBinary(buf) + buf := io.NewBufBinWriter() + err := actualTX.EncodeBinary(buf.BinWriter) assert.Nil(t, err) assert.Equal(t, rawPublishTX, hex.EncodeToString(buf.Bytes())) } diff --git a/pkg/core/transaction/txer.go b/pkg/core/transaction/txer.go index e87187bfd..c26c6364c 100644 --- a/pkg/core/transaction/txer.go +++ b/pkg/core/transaction/txer.go @@ -1,11 +1,11 @@ package transaction -import "io" +import "github.com/CityOfZion/neo-go/pkg/io" // TXer is interface that can act as the underlying data of // a transaction. type TXer interface { - DecodeBinary(io.Reader) error - EncodeBinary(io.Writer) error + DecodeBinary(*io.BinReader) error + EncodeBinary(*io.BinWriter) error Size() int } diff --git a/pkg/core/transaction/witness.go b/pkg/core/transaction/witness.go index d3a07e44d..20c1d8d91 100644 --- a/pkg/core/transaction/witness.go +++ b/pkg/core/transaction/witness.go @@ -3,9 +3,9 @@ package transaction import ( "encoding/hex" "encoding/json" - "io" "github.com/CityOfZion/neo-go/pkg/crypto/hash" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -16,18 +16,14 @@ type Witness struct { } // DecodeBinary implements the payload interface. -func (w *Witness) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) - +func (w *Witness) DecodeBinary(br *io.BinReader) error { w.InvocationScript = br.ReadBytes() w.VerificationScript = br.ReadBytes() return br.Err } // EncodeBinary implements the payload interface. -func (w *Witness) EncodeBinary(writer io.Writer) error { - bw := util.NewBinWriterFromIO(writer) - +func (w *Witness) EncodeBinary(bw *io.BinWriter) error { bw.WriteBytes(w.InvocationScript) bw.WriteBytes(w.VerificationScript) diff --git a/pkg/core/unspent_coin_state.go b/pkg/core/unspent_coin_state.go index 1954a750c..504dc68dd 100644 --- a/pkg/core/unspent_coin_state.go +++ b/pkg/core/unspent_coin_state.go @@ -1,12 +1,11 @@ package core import ( - "bytes" "fmt" - "io" "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/transaction" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -22,7 +21,7 @@ func (u UnspentCoins) getAndUpdate(s storage.Store, hash util.Uint256) (*Unspent unspent := &UnspentCoinState{} key := storage.AppendPrefix(storage.STCoin, hash.BytesReverse()) 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) } } else { @@ -53,9 +52,9 @@ func NewUnspentCoinState(n int) *UnspentCoinState { // commit writes all unspent coin states to the given Batch. func (u UnspentCoins) commit(b storage.Batch) error { - buf := new(bytes.Buffer) + buf := io.NewBufBinWriter() for hash, state := range u { - if err := state.EncodeBinary(buf); err != nil { + if err := state.EncodeBinary(buf.BinWriter); err != nil { return err } key := storage.AppendPrefix(storage.STCoin, hash.BytesReverse()) @@ -65,9 +64,8 @@ func (u UnspentCoins) commit(b storage.Batch) error { return nil } -// EncodeBinary encodes UnspentCoinState to the given io.Writer. -func (s *UnspentCoinState) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +// EncodeBinary encodes UnspentCoinState to the given BinWriter. +func (s *UnspentCoinState) EncodeBinary(bw *io.BinWriter) error { bw.WriteVarUint(uint64(len(s.states))) for _, state := range s.states { bw.WriteLE(byte(state)) @@ -75,9 +73,8 @@ func (s *UnspentCoinState) EncodeBinary(w io.Writer) error { return bw.Err } -// DecodeBinary decodes UnspentCoinState from the given io.Reader. -func (s *UnspentCoinState) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +// DecodeBinary decodes UnspentCoinState from the given BinReader. +func (s *UnspentCoinState) DecodeBinary(br *io.BinReader) error { lenStates := br.ReadVarUint() s.states = make([]CoinState, lenStates) for i := 0; i < int(lenStates); i++ { @@ -98,7 +95,7 @@ func IsDoubleSpend(s storage.Store, tx *transaction.Transaction) bool { unspent := &UnspentCoinState{} key := storage.AppendPrefix(storage.STCoin, prevHash.BytesReverse()) 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 } if unspent == nil { diff --git a/pkg/core/unspent_coint_state_test.go b/pkg/core/unspent_coint_state_test.go index 3338f6b8a..8fb649f19 100644 --- a/pkg/core/unspent_coint_state_test.go +++ b/pkg/core/unspent_coint_state_test.go @@ -1,10 +1,10 @@ package core import ( - "bytes" "testing" "github.com/CityOfZion/neo-go/pkg/core/storage" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/stretchr/testify/assert" ) @@ -19,10 +19,10 @@ func TestDecodeEncodeUnspentCoinState(t *testing.T) { }, } - buf := new(bytes.Buffer) - assert.Nil(t, unspent.EncodeBinary(buf)) + buf := io.NewBufBinWriter() + assert.Nil(t, unspent.EncodeBinary(buf.BinWriter)) unspentDecode := &UnspentCoinState{} - assert.Nil(t, unspentDecode.DecodeBinary(buf)) + assert.Nil(t, unspentDecode.DecodeBinary(io.NewBinReaderFromBuf(buf.Bytes()))) } func TestCommitUnspentCoins(t *testing.T) { diff --git a/pkg/core/util.go b/pkg/core/util.go index de359a38f..b092a2da4 100644 --- a/pkg/core/util.go +++ b/pkg/core/util.go @@ -1,8 +1,6 @@ package core import ( - "bytes" - "encoding/binary" "time" "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/crypto/hash" "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/util" "github.com/CityOfZion/neo-go/pkg/vm" @@ -181,11 +180,9 @@ func headerSliceReverse(dest []*Header) { // storeAsCurrentBlock stores the given block witch prefix // SYSCurrentBlock. func storeAsCurrentBlock(batch storage.Batch, block *Block) { - buf := new(bytes.Buffer) - buf.Write(block.Hash().BytesReverse()) - b := make([]byte, 4) - binary.LittleEndian.PutUint32(b, block.Index) - buf.Write(b) + buf := io.NewBufBinWriter() + buf.WriteLE(block.Hash().BytesReverse()) + buf.WriteLE(block.Index) 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 { var ( key = storage.AppendPrefix(storage.DataBlock, block.Hash().BytesReverse()) - buf = new(bytes.Buffer) + buf = io.NewBufBinWriter() ) - - b := make([]byte, 4) - binary.LittleEndian.PutUint32(b, sysFee) - + // sysFee needs to be handled somehow + // buf.WriteLE(sysFee) b, err := block.Trim() if err != nil { return err } - buf.Write(b) + buf.WriteLE(b) + if buf.Err != nil { + return buf.Err + } batch.Put(key, buf.Bytes()) return nil } @@ -211,15 +209,13 @@ func storeAsBlock(batch storage.Batch, block *Block, sysFee uint32) error { // storeAsTransaction stores the given TX as DataTransaction. func storeAsTransaction(batch storage.Batch, tx *transaction.Transaction, index uint32) error { key := storage.AppendPrefix(storage.DataTransaction, tx.Hash().BytesReverse()) - buf := new(bytes.Buffer) - if err := tx.EncodeBinary(buf); err != nil { + buf := io.NewBufBinWriter() + buf.WriteLE(index) + if err := tx.EncodeBinary(buf.BinWriter); err != nil { return err } - dest := make([]byte, buf.Len()+4) - binary.LittleEndian.PutUint32(dest[:4], index) - copy(dest[4:], buf.Bytes()) - batch.Put(key, dest) + batch.Put(key, buf.Bytes()) return nil } diff --git a/pkg/crypto/keys/publickey.go b/pkg/crypto/keys/publickey.go index a03734688..2a30c2626 100644 --- a/pkg/crypto/keys/publickey.go +++ b/pkg/crypto/keys/publickey.go @@ -5,14 +5,13 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/x509" - "encoding/binary" "encoding/hex" "fmt" - "io" "math/big" "github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto/hash" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/pkg/errors" ) @@ -51,7 +50,7 @@ func NewPublicKeyFromString(s string) (*PublicKey, error) { } pubKey := new(PublicKey) - if err := pubKey.DecodeBinary(bytes.NewReader(b)); err != nil { + if err := pubKey.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil { 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. func (p *PublicKey) DecodeBytes(data []byte) error { - var datab []byte - copy(datab, data) - b := bytes.NewBuffer(datab) + b := io.NewBinReaderFromBuf(data) return p.DecodeBinary(b) } -// DecodeBinary decodes a PublicKey from the given io.Reader. -func (p *PublicKey) DecodeBinary(r io.Reader) error { +// DecodeBinary decodes a PublicKey from the given BinReader. +func (p *PublicKey) DecodeBinary(r *io.BinReader) error { var prefix uint8 var x, y *big.Int var err error - if err = binary.Read(r, binary.LittleEndian, &prefix); err != nil { - return err + r.ReadLE(&prefix) + if r.Err != nil { + return r.Err } // Infinity @@ -146,8 +144,9 @@ func (p *PublicKey) DecodeBinary(r io.Reader) error { case 0x02, 0x03: // Compressed public keys xbytes := make([]byte, 32) - if _, err := io.ReadFull(r, xbytes); err != nil { - return err + r.ReadLE(xbytes) + if r.Err != nil { + return r.Err } x = new(big.Int).SetBytes(xbytes) ylsb := uint(prefix & 0x1) @@ -158,11 +157,10 @@ func (p *PublicKey) DecodeBinary(r io.Reader) error { case 0x04: xbytes := make([]byte, 32) ybytes := make([]byte, 32) - if _, err = io.ReadFull(r, xbytes); err != nil { - return err - } - if _, err = io.ReadFull(r, ybytes); err != nil { - return err + r.ReadLE(xbytes) + r.ReadLE(ybytes) + if r.Err != nil { + return r.Err } x = new(big.Int).SetBytes(xbytes) y = new(big.Int).SetBytes(ybytes) @@ -182,9 +180,10 @@ func (p *PublicKey) DecodeBinary(r io.Reader) error { return nil } -// EncodeBinary encodes a PublicKey to the given io.Writer. -func (p *PublicKey) EncodeBinary(w io.Writer) error { - return binary.Write(w, binary.LittleEndian, p.Bytes()) +// EncodeBinary encodes a PublicKey to the given BinWriter. +func (p *PublicKey) EncodeBinary(w *io.BinWriter) error { + w.WriteLE(p.Bytes()) + return w.Err } // Signature returns a NEO-specific hash of the key. diff --git a/pkg/crypto/keys/publickey_test.go b/pkg/crypto/keys/publickey_test.go index 34c0b334d..71e73f5ef 100644 --- a/pkg/crypto/keys/publickey_test.go +++ b/pkg/crypto/keys/publickey_test.go @@ -1,21 +1,23 @@ package keys import ( - "bytes" "encoding/hex" "testing" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/stretchr/testify/assert" ) func TestEncodeDecodeInfinity(t *testing.T) { key := &PublicKey{} - buf := new(bytes.Buffer) - assert.Nil(t, key.EncodeBinary(buf)) - assert.Equal(t, 1, buf.Len()) + buf := io.NewBufBinWriter() + assert.Nil(t, key.EncodeBinary(buf.BinWriter)) + assert.Nil(t, buf.Err) + b := buf.Bytes() + assert.Equal(t, 1, len(b)) keyDecode := &PublicKey{} - assert.Nil(t, keyDecode.DecodeBinary(buf)) + assert.Nil(t, keyDecode.DecodeBytes(b)) assert.Equal(t, []byte{0x00}, keyDecode.Bytes()) } @@ -24,11 +26,13 @@ func TestEncodeDecodePublicKey(t *testing.T) { k, err := NewPrivateKey() assert.Nil(t, err) p := k.PublicKey() - buf := new(bytes.Buffer) - assert.Nil(t, p.EncodeBinary(buf)) + buf := io.NewBufBinWriter() + assert.Nil(t, p.EncodeBinary(buf.BinWriter)) + assert.Nil(t, buf.Err) + b := buf.Bytes() pDecode := &PublicKey{} - assert.Nil(t, pDecode.DecodeBinary(buf)) + assert.Nil(t, pDecode.DecodeBytes(b)) assert.Equal(t, p.X, pDecode.X) } } diff --git a/pkg/util/binaryBufWriter.go b/pkg/io/binaryBufWriter.go similarity index 62% rename from pkg/util/binaryBufWriter.go rename to pkg/io/binaryBufWriter.go index 0a2ba4cfc..31ba262ac 100644 --- a/pkg/util/binaryBufWriter.go +++ b/pkg/io/binaryBufWriter.go @@ -1,4 +1,4 @@ -package util +package io import ( "bytes" @@ -27,3 +27,13 @@ func (bw *BufBinWriter) Bytes() []byte { bw.Err = errors.New("buffer already drained") 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() +} diff --git a/pkg/util/binaryReader.go b/pkg/io/binaryReader.go similarity index 99% rename from pkg/util/binaryReader.go rename to pkg/io/binaryReader.go index 47694891a..27845b21d 100644 --- a/pkg/util/binaryReader.go +++ b/pkg/io/binaryReader.go @@ -1,4 +1,4 @@ -package util +package io import ( "bytes" diff --git a/pkg/util/binaryWriter.go b/pkg/io/binaryWriter.go similarity index 99% rename from pkg/util/binaryWriter.go rename to pkg/io/binaryWriter.go index a867c94eb..b85cda48b 100644 --- a/pkg/util/binaryWriter.go +++ b/pkg/io/binaryWriter.go @@ -1,4 +1,4 @@ -package util +package io import ( "encoding/binary" diff --git a/pkg/util/binaryrw_test.go b/pkg/io/binaryrw_test.go similarity index 94% rename from pkg/util/binaryrw_test.go rename to pkg/io/binaryrw_test.go index 466504057..dc69a92c4 100644 --- a/pkg/util/binaryrw_test.go +++ b/pkg/io/binaryrw_test.go @@ -1,4 +1,4 @@ -package util +package io import ( "errors" @@ -101,6 +101,18 @@ func TestBufBinWriterErr(t *testing.T) { 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) { var ( str string = "teststring" diff --git a/pkg/io/serializable.go b/pkg/io/serializable.go index 359c8513e..0f49c61d8 100644 --- a/pkg/io/serializable.go +++ b/pkg/io/serializable.go @@ -1,10 +1,8 @@ package io -import "io" - // Serializable defines the binary encoding/decoding interface. type Serializable interface { Size() int - DecodeBinary(io.Reader) error - EncodeBinary(io.Writer) error + DecodeBinary(*BinReader) error + EncodeBinary(*BinWriter) error } diff --git a/pkg/network/message.go b/pkg/network/message.go index 01b1a0947..69fe8b2d8 100644 --- a/pkg/network/message.go +++ b/pkg/network/message.go @@ -1,18 +1,15 @@ package network import ( - "bytes" "encoding/binary" "errors" - "fmt" - "io" "github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core/transaction" "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/util" ) const ( @@ -80,12 +77,13 @@ func NewMessage(magic config.NetMode, cmd CommandType, p payload.Payload) *Messa ) if p != nil { - buf := new(bytes.Buffer) - if err := p.EncodeBinary(buf); err != nil { + buf := io.NewBufBinWriter() + if err := p.EncodeBinary(buf.BinWriter); err != nil { panic(err) } - size = uint32(buf.Len()) - checksum = hash.Checksum(buf.Bytes()) + b := buf.Bytes() + size = uint32(len(b)) + checksum = hash.Checksum(b) } else { checksum = hash.Checksum([]byte{}) } @@ -147,8 +145,7 @@ func (m *Message) CommandType() CommandType { } // Decode a Message from the given reader. -func (m *Message) Decode(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (m *Message) Decode(br *io.BinReader) error { br.ReadLE(&m.Magic) br.ReadLE(&m.Command) br.ReadLE(&m.Length) @@ -160,67 +157,63 @@ func (m *Message) Decode(r io.Reader) error { if m.Length == 0 { return nil } - return m.decodePayload(r) + return m.decodePayload(br) } -func (m *Message) decodePayload(r io.Reader) error { - buf := new(bytes.Buffer) - n, err := io.CopyN(buf, r, int64(m.Length)) - if err != nil { - return err +func (m *Message) decodePayload(br *io.BinReader) error { + buf := make([]byte, m.Length) + br.ReadLE(buf) + if br.Err != nil { + 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. - if !compareChecksum(m.Checksum, buf.Bytes()) { + if !compareChecksum(m.Checksum, buf) { return errChecksumMismatch } + r := io.NewBinReaderFromBuf(buf) var p payload.Payload switch m.CommandType() { case CMDVersion: p = &payload.Version{} - if err := p.DecodeBinary(buf); err != nil { + if err := p.DecodeBinary(r); err != nil { return err } case CMDInv, CMDGetData: p = &payload.Inventory{} - if err := p.DecodeBinary(buf); err != nil { + if err := p.DecodeBinary(r); err != nil { return err } case CMDAddr: p = &payload.AddressList{} - if err := p.DecodeBinary(buf); err != nil { + if err := p.DecodeBinary(r); err != nil { return err } case CMDBlock: p = &core.Block{} - if err := p.DecodeBinary(buf); err != nil { + if err := p.DecodeBinary(r); err != nil { return err } case CMDGetBlocks: fallthrough case CMDGetHeaders: p = &payload.GetBlocks{} - if err := p.DecodeBinary(buf); err != nil { + if err := p.DecodeBinary(r); err != nil { return err } case CMDHeaders: p = &payload.Headers{} - if err := p.DecodeBinary(buf); err != nil { + if err := p.DecodeBinary(r); err != nil { return err } case CMDTX: p = &transaction.Transaction{} - if err := p.DecodeBinary(buf); err != nil { + if err := p.DecodeBinary(r); err != nil { return err } case CMDMerkleBlock: p = &payload.MerkleBlock{} - if err := p.DecodeBinary(buf); err != nil { + if err := p.DecodeBinary(r); err != nil { return err } } @@ -230,9 +223,8 @@ func (m *Message) decodePayload(r io.Reader) error { return nil } -// Encode a Message to any given io.Writer. -func (m *Message) Encode(w io.Writer) error { - br := util.NewBinWriterFromIO(w) +// Encode a Message to any given BinWriter. +func (m *Message) Encode(br *io.BinWriter) error { br.WriteLE(m.Magic) br.WriteLE(m.Command) br.WriteLE(m.Length) @@ -241,7 +233,7 @@ func (m *Message) Encode(w io.Writer) error { return br.Err } if m.Payload != nil { - return m.Payload.EncodeBinary(w) + return m.Payload.EncodeBinary(br) } return nil } diff --git a/pkg/network/payload/address.go b/pkg/network/payload/address.go index d0b1765cd..e562f0b21 100644 --- a/pkg/network/payload/address.go +++ b/pkg/network/payload/address.go @@ -1,12 +1,11 @@ package payload import ( - "io" "net" "strconv" "time" - "github.com/CityOfZion/neo-go/pkg/util" + "github.com/CityOfZion/neo-go/pkg/io" ) // AddressAndTime payload. @@ -29,8 +28,7 @@ func NewAddressAndTime(e *net.TCPAddr, t time.Time) *AddressAndTime { } // DecodeBinary implements the Payload interface. -func (p *AddressAndTime) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (p *AddressAndTime) DecodeBinary(br *io.BinReader) error { br.ReadLE(&p.Timestamp) br.ReadLE(&p.Services) br.ReadBE(&p.IP) @@ -39,8 +37,7 @@ func (p *AddressAndTime) DecodeBinary(r io.Reader) error { } // EncodeBinary implements the Payload interface. -func (p *AddressAndTime) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +func (p *AddressAndTime) EncodeBinary(bw *io.BinWriter) error { bw.WriteLE(p.Timestamp) bw.WriteLE(p.Services) bw.WriteBE(p.IP) @@ -71,8 +68,7 @@ func NewAddressList(n int) *AddressList { } // DecodeBinary implements the Payload interface. -func (p *AddressList) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (p *AddressList) DecodeBinary(br *io.BinReader) error { listLen := br.ReadVarUint() if br.Err != nil { return br.Err @@ -81,7 +77,7 @@ func (p *AddressList) DecodeBinary(r io.Reader) error { p.Addrs = make([]*AddressAndTime, listLen) for i := 0; i < int(listLen); i++ { p.Addrs[i] = &AddressAndTime{} - if err := p.Addrs[i].DecodeBinary(r); err != nil { + if err := p.Addrs[i].DecodeBinary(br); err != nil { return err } } @@ -89,14 +85,13 @@ func (p *AddressList) DecodeBinary(r io.Reader) error { } // EncodeBinary implements the Payload interface. -func (p *AddressList) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +func (p *AddressList) EncodeBinary(bw *io.BinWriter) error { bw.WriteVarUint(uint64(len(p.Addrs))) if bw.Err != nil { return bw.Err } for _, addr := range p.Addrs { - if err := addr.EncodeBinary(w); err != nil { + if err := addr.EncodeBinary(bw); err != nil { return err } } diff --git a/pkg/network/payload/address_test.go b/pkg/network/payload/address_test.go index afece415a..dbe5db885 100644 --- a/pkg/network/payload/address_test.go +++ b/pkg/network/payload/address_test.go @@ -1,12 +1,12 @@ package payload import ( - "bytes" "fmt" "net" "testing" "time" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/stretchr/testify/assert" ) @@ -15,7 +15,7 @@ func TestEncodeDecodeAddress(t *testing.T) { e, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:2000") ts = time.Now() addr = NewAddressAndTime(e, ts) - buf = new(bytes.Buffer) + buf = io.NewBufBinWriter() ) assert.Equal(t, ts.UTC().Unix(), int64(addr.Timestamp)) @@ -23,11 +23,13 @@ func TestEncodeDecodeAddress(t *testing.T) { copy(aatip, addr.IP[:]) assert.Equal(t, e.IP, aatip) assert.Equal(t, e.Port, int(addr.Port)) - err := addr.EncodeBinary(buf) + err := addr.EncodeBinary(buf.BinWriter) assert.Nil(t, err) + b := buf.Bytes() + r := io.NewBinReaderFromBuf(b) addrDecode := &AddressAndTime{} - err = addrDecode.DecodeBinary(buf) + err = addrDecode.DecodeBinary(r) assert.Nil(t, err) assert.Equal(t, addr, addrDecode) @@ -41,12 +43,14 @@ func TestEncodeDecodeAddressList(t *testing.T) { addrList.Addrs[i] = NewAddressAndTime(e, time.Now()) } - buf := new(bytes.Buffer) - err := addrList.EncodeBinary(buf) + buf := io.NewBufBinWriter() + err := addrList.EncodeBinary(buf.BinWriter) assert.Nil(t, err) + b := buf.Bytes() + r := io.NewBinReaderFromBuf(b) addrListDecode := &AddressList{} - err = addrListDecode.DecodeBinary(buf) + err = addrListDecode.DecodeBinary(r) assert.Nil(t, err) assert.Equal(t, addrList, addrListDecode) diff --git a/pkg/network/payload/getblocks.go b/pkg/network/payload/getblocks.go index 1246a9348..f1e3e1fc1 100644 --- a/pkg/network/payload/getblocks.go +++ b/pkg/network/payload/getblocks.go @@ -1,8 +1,7 @@ package payload import ( - "io" - + "github.com/CityOfZion/neo-go/pkg/io" "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. -func (p *GetBlocks) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (p *GetBlocks) DecodeBinary(br *io.BinReader) error { lenStart := br.ReadVarUint() p.HashStart = make([]util.Uint256, lenStart) @@ -34,8 +32,7 @@ func (p *GetBlocks) DecodeBinary(r io.Reader) error { } // EncodeBinary implements the payload interface. -func (p *GetBlocks) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +func (p *GetBlocks) EncodeBinary(bw *io.BinWriter) error { bw.WriteVarUint(uint64(len(p.HashStart))) bw.WriteLE(p.HashStart) bw.WriteLE(p.HashStop) diff --git a/pkg/network/payload/getblocks_test.go b/pkg/network/payload/getblocks_test.go index e0745a3fb..5844c9bbd 100644 --- a/pkg/network/payload/getblocks_test.go +++ b/pkg/network/payload/getblocks_test.go @@ -1,10 +1,10 @@ package payload import ( - "bytes" "testing" "github.com/CityOfZion/neo-go/pkg/crypto/hash" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" "github.com/stretchr/testify/assert" ) @@ -18,12 +18,14 @@ func TestGetBlockEncodeDecode(t *testing.T) { } p := NewGetBlocks(start, util.Uint256{}) - buf := new(bytes.Buffer) - err := p.EncodeBinary(buf) + buf := io.NewBufBinWriter() + err := p.EncodeBinary(buf.BinWriter) assert.Nil(t, err) + b := buf.Bytes() + r := io.NewBinReaderFromBuf(b) pDecode := &GetBlocks{} - err = pDecode.DecodeBinary(buf) + err = pDecode.DecodeBinary(r) assert.Nil(t, err) assert.Equal(t, p, pDecode) } @@ -39,12 +41,14 @@ func TestGetBlockEncodeDecodeWithHashStop(t *testing.T) { stop = hash.Sha256([]byte("e")) ) p := NewGetBlocks(start, stop) - buf := new(bytes.Buffer) - err := p.EncodeBinary(buf) + buf := io.NewBufBinWriter() + err := p.EncodeBinary(buf.BinWriter) assert.Nil(t, err) + b := buf.Bytes() + r := io.NewBinReaderFromBuf(b) pDecode := &GetBlocks{} - err = pDecode.DecodeBinary(buf) + err = pDecode.DecodeBinary(r) assert.Nil(t, err) assert.Equal(t, p, pDecode) } diff --git a/pkg/network/payload/headers.go b/pkg/network/payload/headers.go index 1e3904d1b..66771fb5e 100644 --- a/pkg/network/payload/headers.go +++ b/pkg/network/payload/headers.go @@ -1,10 +1,8 @@ package payload import ( - "io" - "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" ) @@ -19,8 +17,7 @@ const ( ) // DecodeBinary implements the Payload interface. -func (p *Headers) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (p *Headers) DecodeBinary(br *io.BinReader) error { lenHeaders := br.ReadVarUint() if br.Err != nil { return br.Err @@ -35,7 +32,7 @@ func (p *Headers) DecodeBinary(r io.Reader) error { for i := 0; i < int(lenHeaders); i++ { header := &core.Header{} - if err := header.DecodeBinary(r); err != nil { + if err := header.DecodeBinary(br); err != nil { return err } p.Hdrs[i] = header @@ -45,15 +42,14 @@ func (p *Headers) DecodeBinary(r io.Reader) error { } // EncodeBinary implements the Payload interface. -func (p *Headers) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +func (p *Headers) EncodeBinary(bw *io.BinWriter) error { bw.WriteVarUint(uint64(len(p.Hdrs))) if bw.Err != nil { return bw.Err } for _, header := range p.Hdrs { - if err := header.EncodeBinary(w); err != nil { + if err := header.EncodeBinary(bw); err != nil { return err } } diff --git a/pkg/network/payload/headers_test.go b/pkg/network/payload/headers_test.go index 7b762d4b8..2ee849f27 100644 --- a/pkg/network/payload/headers_test.go +++ b/pkg/network/payload/headers_test.go @@ -1,12 +1,12 @@ package payload import ( - "bytes" "encoding/hex" "testing" "github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core/transaction" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/stretchr/testify/assert" ) @@ -41,12 +41,14 @@ func TestHeadersEncodeDecode(t *testing.T) { }}, }} - buf := new(bytes.Buffer) - err := headers.EncodeBinary(buf) + buf := io.NewBufBinWriter() + err := headers.EncodeBinary(buf.BinWriter) assert.Nil(t, err) + b := buf.Bytes() + r := io.NewBinReaderFromBuf(b) headersDecode := &Headers{} - err = headersDecode.DecodeBinary(buf) + err = headersDecode.DecodeBinary(r) assert.Nil(t, err) for i := 0; i < len(headers.Hdrs); i++ { @@ -63,7 +65,7 @@ func TestBinEncodeDecode(t *testing.T) { rawBlockBytes, _ := hex.DecodeString(rawBlockHeaders) - r := bytes.NewReader(rawBlockBytes) + r := io.NewBinReaderFromBuf(rawBlockBytes) err := headerMsg.DecodeBinary(r) assert.Nil(t, err) @@ -74,9 +76,9 @@ func TestBinEncodeDecode(t *testing.T) { 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, hex.EncodeToString(rawBlockBytes), hex.EncodeToString(buf.Bytes())) } diff --git a/pkg/network/payload/inventory.go b/pkg/network/payload/inventory.go index cdfd783fe..ade25c9c8 100644 --- a/pkg/network/payload/inventory.go +++ b/pkg/network/payload/inventory.go @@ -1,8 +1,7 @@ package payload import ( - "io" - + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -56,8 +55,7 @@ func NewInventory(typ InventoryType, hashes []util.Uint256) *Inventory { } // DecodeBinary implements the Payload interface. -func (p *Inventory) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (p *Inventory) DecodeBinary(br *io.BinReader) error { br.ReadLE(&p.Type) listLen := br.ReadVarUint() @@ -70,8 +68,7 @@ func (p *Inventory) DecodeBinary(r io.Reader) error { } // EncodeBinary implements the Payload interface. -func (p *Inventory) EncodeBinary(w io.Writer) error { - bw := util.NewBinWriterFromIO(w) +func (p *Inventory) EncodeBinary(bw *io.BinWriter) error { bw.WriteLE(p.Type) listLen := len(p.Hashes) diff --git a/pkg/network/payload/inventory_test.go b/pkg/network/payload/inventory_test.go index f9fffcc79..acbe7c7c2 100644 --- a/pkg/network/payload/inventory_test.go +++ b/pkg/network/payload/inventory_test.go @@ -1,10 +1,10 @@ package payload import ( - "bytes" "testing" "github.com/CityOfZion/neo-go/pkg/crypto/hash" + "github.com/CityOfZion/neo-go/pkg/io" . "github.com/CityOfZion/neo-go/pkg/util" "github.com/stretchr/testify/assert" ) @@ -16,12 +16,14 @@ func TestInventoryEncodeDecode(t *testing.T) { } inv := NewInventory(BlockType, hashes) - buf := new(bytes.Buffer) - err := inv.EncodeBinary(buf) + buf := io.NewBufBinWriter() + err := inv.EncodeBinary(buf.BinWriter) assert.Nil(t, err) + b := buf.Bytes() + r := io.NewBinReaderFromBuf(b) invDecode := &Inventory{} - err = invDecode.DecodeBinary(buf) + err = invDecode.DecodeBinary(r) assert.Nil(t, err) assert.Equal(t, inv, invDecode) } @@ -29,8 +31,8 @@ func TestInventoryEncodeDecode(t *testing.T) { func TestEmptyInv(t *testing.T) { msgInv := NewInventory(TXType, []Uint256{}) - buf := new(bytes.Buffer) - err := msgInv.EncodeBinary(buf) + buf := io.NewBufBinWriter() + err := msgInv.EncodeBinary(buf.BinWriter) assert.Nil(t, err) assert.Equal(t, []byte{byte(TXType), 0}, buf.Bytes()) assert.Equal(t, 0, len(msgInv.Hashes)) diff --git a/pkg/network/payload/merkleblock.go b/pkg/network/payload/merkleblock.go index 2396bec85..2c9cf979c 100644 --- a/pkg/network/payload/merkleblock.go +++ b/pkg/network/payload/merkleblock.go @@ -1,9 +1,8 @@ package payload import ( - "io" - "github.com/CityOfZion/neo-go/pkg/core" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -16,12 +15,11 @@ type MerkleBlock struct { } // 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{} - if err := m.BlockBase.DecodeBinary(r); err != nil { + if err := m.BlockBase.DecodeBinary(br); err != nil { return err } - br := util.NewBinReaderFromIO(r) m.TxCount = int(br.ReadVarUint()) n := br.ReadVarUint() @@ -34,6 +32,6 @@ func (m *MerkleBlock) DecodeBinary(r io.Reader) error { } // EncodeBinary implements the Payload interface. -func (m *MerkleBlock) EncodeBinary(w io.Writer) error { +func (m *MerkleBlock) EncodeBinary(bw *io.BinWriter) error { return nil } diff --git a/pkg/network/payload/payload.go b/pkg/network/payload/payload.go index e23f9955a..870b9972a 100644 --- a/pkg/network/payload/payload.go +++ b/pkg/network/payload/payload.go @@ -1,11 +1,11 @@ package payload -import "io" +import "github.com/CityOfZion/neo-go/pkg/io" // Payload is anything that can be binary encoded/decoded. type Payload interface { - EncodeBinary(io.Writer) error - DecodeBinary(io.Reader) error + EncodeBinary(*io.BinWriter) error + DecodeBinary(*io.BinReader) error } // NullPayload is a dummy payload with no fields. diff --git a/pkg/network/payload/version.go b/pkg/network/payload/version.go index 3402ed1cd..b9d347d45 100644 --- a/pkg/network/payload/version.go +++ b/pkg/network/payload/version.go @@ -1,9 +1,9 @@ package payload import ( - "io" "time" + "github.com/CityOfZion/neo-go/pkg/io" "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. -func (p *Version) DecodeBinary(r io.Reader) error { - br := util.NewBinReaderFromIO(r) +func (p *Version) DecodeBinary(br *io.BinReader) error { br.ReadLE(&p.Version) br.ReadLE(&p.Services) br.ReadLE(&p.Timestamp) @@ -69,8 +68,7 @@ func (p *Version) DecodeBinary(r io.Reader) error { } // EncodeBinary implements the Payload interface. -func (p *Version) EncodeBinary(w io.Writer) error { - br := util.NewBinWriterFromIO(w) +func (p *Version) EncodeBinary(br *io.BinWriter) error { br.WriteLE(p.Version) br.WriteLE(p.Services) br.WriteLE(p.Timestamp) diff --git a/pkg/network/payload/version_test.go b/pkg/network/payload/version_test.go index ca4ed156d..559fe94ed 100644 --- a/pkg/network/payload/version_test.go +++ b/pkg/network/payload/version_test.go @@ -1,9 +1,9 @@ package payload import ( - "bytes" "testing" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/stretchr/testify/assert" ) @@ -16,13 +16,15 @@ func TestVersionEncodeDecode(t *testing.T) { version := NewVersion(id, port, useragent, height, relay) - buf := new(bytes.Buffer) - err := version.EncodeBinary(buf) + buf := io.NewBufBinWriter() + err := version.EncodeBinary(buf.BinWriter) 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{} - err = versionDecoded.DecodeBinary(buf) + err = versionDecoded.DecodeBinary(r) assert.Nil(t, err) assert.Equal(t, versionDecoded.Nonce, id) assert.Equal(t, versionDecoded.Port, port) diff --git a/pkg/network/tcp_peer.go b/pkg/network/tcp_peer.go index 10dac0a82..a9a5b5a27 100644 --- a/pkg/network/tcp_peer.go +++ b/pkg/network/tcp_peer.go @@ -6,6 +6,7 @@ import ( "net" "sync" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/network/payload" ) @@ -68,7 +69,8 @@ func (p *TCPPeer) writeMsg(msg *Message) error { case err := <-p.done: return err default: - return msg.Encode(p.conn) + w := io.NewBinWriterFromIO(p.conn) + return msg.Encode(w) } } diff --git a/pkg/network/tcp_transport.go b/pkg/network/tcp_transport.go index 8f61b7607..b99c060dd 100644 --- a/pkg/network/tcp_transport.go +++ b/pkg/network/tcp_transport.go @@ -5,6 +5,7 @@ import ( "regexp" "time" + "github.com/CityOfZion/neo-go/pkg/io" log "github.com/sirupsen/logrus" ) @@ -77,9 +78,10 @@ func (t *TCPTransport) handleConn(conn net.Conn) { t.server.register <- p + r := io.NewBinReaderFromIO(p.conn) for { msg := &Message{} - if err = msg.Decode(p.conn); err != nil { + if err = msg.Decode(r); err != nil { break } if err = t.server.handleMessage(p, msg); err != nil { diff --git a/pkg/rpc/rpc.go b/pkg/rpc/rpc.go index 73d62c421..09684d114 100644 --- a/pkg/rpc/rpc.go +++ b/pkg/rpc/rpc.go @@ -1,10 +1,10 @@ package rpc import ( - "bytes" "encoding/hex" "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/util" "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) { var ( err error - buf = &bytes.Buffer{} + buf = io.NewBufBinWriter() rawTx *transaction.Transaction rawTxStr string 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 { 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`") } rawTxStr = hex.EncodeToString(buf.Bytes()) diff --git a/pkg/rpc/server.go b/pkg/rpc/server.go index f8fcb836b..db73d2ae1 100644 --- a/pkg/rpc/server.go +++ b/pkg/rpc/server.go @@ -1,7 +1,6 @@ package rpc import ( - "bytes" "context" "encoding/hex" "fmt" @@ -11,6 +10,7 @@ import ( "github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core/transaction" "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/rpc/result" "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 { resultsErr = errInvalidParams } else { - r := bytes.NewReader(byteTx) + r := io.NewBinReaderFromBuf(byteTx) tx := &transaction.Transaction{} err = tx.DecodeBinary(r) if err != nil { diff --git a/pkg/rpc/txBuilder.go b/pkg/rpc/txBuilder.go index 3109c1424..d68f3b12a 100644 --- a/pkg/rpc/txBuilder.go +++ b/pkg/rpc/txBuilder.go @@ -1,11 +1,10 @@ package rpc import ( - "bytes" - "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto/keys" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" errs "github.com/pkg/errors" ) @@ -71,10 +70,10 @@ func GetInvocationScript(tx *transaction.Transaction, wif keys.WIF) ([]byte, err ) var ( err error - buf = new(bytes.Buffer) + buf = io.NewBufBinWriter() 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") } data := buf.Bytes() diff --git a/pkg/smartcontract/contract_test.go b/pkg/smartcontract/contract_test.go index d42e41811..1cca3d229 100644 --- a/pkg/smartcontract/contract_test.go +++ b/pkg/smartcontract/contract_test.go @@ -4,7 +4,7 @@ import ( "testing" "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/stretchr/testify/assert" ) @@ -21,7 +21,7 @@ func TestCreateMultiSigRedeemScript(t *testing.T) { t.Fatal(err) } - br := util.NewBinReaderFromBuf(out) + br := io.NewBinReaderFromBuf(out) var b uint8 br.ReadLE(&b) assert.Equal(t, vm.PUSH3, vm.Instruction(b)) diff --git a/pkg/util/size_test.go b/pkg/util/size_test.go index 9d1217424..d77ceaebc 100644 --- a/pkg/util/size_test.go +++ b/pkg/util/size_test.go @@ -2,9 +2,9 @@ package util import ( "fmt" - "io" "testing" + "github.com/CityOfZion/neo-go/pkg/io" "github.com/stretchr/testify/assert" ) @@ -12,11 +12,11 @@ import ( type smthSerializable struct { } -func (*smthSerializable) DecodeBinary(io.Reader) error { +func (*smthSerializable) DecodeBinary(*io.BinReader) error { return nil } -func (*smthSerializable) EncodeBinary(io.Writer) error { +func (*smthSerializable) EncodeBinary(*io.BinWriter) error { return nil }