From 361724a33e8f2072fb3fb63ccfa9b7e5ef4136a1 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 28 Aug 2019 19:27:06 +0300 Subject: [PATCH] pkg/core: use util.binaryReader/Writer Simplify error handling. --- pkg/core/account_state.go | 61 ++++--------- pkg/core/asset_state.go | 108 +++++++---------------- pkg/core/block.go | 40 +++++---- pkg/core/block_base.go | 72 ++++++--------- pkg/core/header_hash_list.go | 12 +-- pkg/core/spent_coin_state.go | 45 +++------- pkg/core/storage/helpers.go | 8 +- pkg/core/transaction/attribute.go | 93 +++++++++---------- pkg/core/transaction/claim.go | 12 ++- pkg/core/transaction/input.go | 20 ++--- pkg/core/transaction/invocation.go | 22 ++--- pkg/core/transaction/output.go | 25 +++--- pkg/core/transaction/publish.go | 50 +++-------- pkg/core/transaction/register.go | 49 ++++------ pkg/core/transaction/state.go | 6 +- pkg/core/transaction/state_descriptor.go | 29 ++---- pkg/core/transaction/transaction.go | 55 +++++++----- pkg/core/transaction/witness.go | 30 +++---- pkg/core/unspent_coin_state.go | 21 ++--- 19 files changed, 291 insertions(+), 467 deletions(-) diff --git a/pkg/core/account_state.go b/pkg/core/account_state.go index 01fecc7a7..44d277e76 100644 --- a/pkg/core/account_state.go +++ b/pkg/core/account_state.go @@ -2,7 +2,6 @@ package core import ( "bytes" - "encoding/binary" "fmt" "io" @@ -69,17 +68,11 @@ func NewAccountState(scriptHash util.Uint160) *AccountState { // DecodeBinary decodes AccountState from the given io.Reader. func (s *AccountState) DecodeBinary(r io.Reader) error { - if err := binary.Read(r, binary.LittleEndian, &s.Version); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &s.ScriptHash); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &s.IsFrozen); err != nil { - return err - } - - lenVotes := util.ReadVarUint(r) + br := util.BinReader{R: r} + br.ReadLE(&s.Version) + br.ReadLE(&s.ScriptHash) + br.ReadLE(&s.IsFrozen) + lenVotes := br.ReadVarUint() s.Votes = make([]*keys.PublicKey, lenVotes) for i := 0; i < int(lenVotes); i++ { s.Votes[i] = &keys.PublicKey{} @@ -89,37 +82,25 @@ func (s *AccountState) DecodeBinary(r io.Reader) error { } s.Balances = make(map[util.Uint256]util.Fixed8) - lenBalances := util.ReadVarUint(r) + lenBalances := br.ReadVarUint() for i := 0; i < int(lenBalances); i++ { key := util.Uint256{} - if err := binary.Read(r, binary.LittleEndian, &key); err != nil { - return err - } + br.ReadLE(&key) var val util.Fixed8 - if err := binary.Read(r, binary.LittleEndian, &val); err != nil { - return err - } + br.ReadLE(&val) s.Balances[key] = val } - return nil + return br.Err } // EncodeBinary encode AccountState to the given io.Writer. func (s *AccountState) EncodeBinary(w io.Writer) error { - if err := binary.Write(w, binary.LittleEndian, s.Version); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, s.ScriptHash); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, s.IsFrozen); err != nil { - return err - } - - if err := util.WriteVarUint(w, uint64(len(s.Votes))); err != nil { - return err - } + bw := util.BinWriter{W: w} + 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 { return err @@ -127,19 +108,13 @@ func (s *AccountState) EncodeBinary(w io.Writer) error { } balances := s.nonZeroBalances() - if err := util.WriteVarUint(w, uint64(len(balances))); err != nil { - return err - } + bw.WriteVarUint(uint64(len(balances))) for k, v := range balances { - if err := binary.Write(w, binary.LittleEndian, k); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, v); err != nil { - return err - } + bw.WriteLE(k) + bw.WriteLE(v) } - return nil + return bw.Err } // Returns only the non-zero balances for the account. diff --git a/pkg/core/asset_state.go b/pkg/core/asset_state.go index ee4b4407b..19f7db8c3 100644 --- a/pkg/core/asset_state.go +++ b/pkg/core/asset_state.go @@ -2,7 +2,6 @@ package core import ( "bytes" - "encoding/binary" "io" "github.com/CityOfZion/neo-go/pkg/core/storage" @@ -48,95 +47,56 @@ type AssetState struct { // DecodeBinary implements the Payload interface. func (a *AssetState) DecodeBinary(r io.Reader) error { - if err := binary.Read(r, binary.LittleEndian, &a.ID); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &a.AssetType); err != nil { - return err - } + br := util.BinReader{R: r} + br.ReadLE(&a.ID) + br.ReadLE(&a.AssetType) - var err error - a.Name, err = util.ReadVarString(r) - if err != nil { - return err - } + a.Name = br.ReadString() - if err := binary.Read(r, binary.LittleEndian, &a.Amount); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &a.Available); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &a.Precision); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &a.FeeMode); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &a.FeeAddress); err != nil { - return err - } + br.ReadLE(&a.Amount) + br.ReadLE(&a.Available) + br.ReadLE(&a.Precision) + br.ReadLE(&a.FeeMode) + br.ReadLE(&a.FeeAddress) + if br.Err != nil { + return br.Err + } a.Owner = &keys.PublicKey{} if err := a.Owner.DecodeBinary(r); err != nil { return err } - if err := binary.Read(r, binary.LittleEndian, &a.Admin); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &a.Issuer); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &a.Expiration); err != nil { - return err - } - return binary.Read(r, binary.LittleEndian, &a.IsFrozen) + br.ReadLE(&a.Admin) + br.ReadLE(&a.Issuer) + br.ReadLE(&a.Expiration) + br.ReadLE(&a.IsFrozen) + + return br.Err } // EncodeBinary implements the Payload interface. func (a *AssetState) EncodeBinary(w io.Writer) error { - if err := binary.Write(w, binary.LittleEndian, a.ID); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, a.AssetType); err != nil { - return err - } - if err := util.WriteVarUint(w, uint64(len(a.Name))); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, []byte(a.Name)); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, a.Amount); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, a.Available); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, a.Precision); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, a.FeeMode); err != nil { - return err - } + bw := util.BinWriter{W: w} + bw.WriteLE(a.ID) + bw.WriteLE(a.AssetType) + bw.WriteString(a.Name) + bw.WriteLE(a.Amount) + bw.WriteLE(a.Available) + bw.WriteLE(a.Precision) + bw.WriteLE(a.FeeMode) + bw.WriteLE(a.FeeAddress) - if err := binary.Write(w, binary.LittleEndian, a.FeeAddress); err != nil { - return err + if bw.Err != nil { + return bw.Err } - if err := a.Owner.EncodeBinary(w); err != nil { return err } - if err := binary.Write(w, binary.LittleEndian, a.Admin); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, a.Issuer); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, a.Expiration); err != nil { - return err - } - return binary.Write(w, binary.LittleEndian, a.IsFrozen) + bw.WriteLE(a.Admin) + bw.WriteLE(a.Issuer) + bw.WriteLE(a.Expiration) + bw.WriteLE(a.IsFrozen) + return bw.Err } // GetName returns the asset name based on its type. diff --git a/pkg/core/block.go b/pkg/core/block.go index 762ba6787..7744314fd 100644 --- a/pkg/core/block.go +++ b/pkg/core/block.go @@ -2,7 +2,6 @@ package core import ( "bytes" - "encoding/binary" "io" "github.com/CityOfZion/neo-go/pkg/core/transaction" @@ -79,9 +78,11 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) { return block, err } + br := util.BinReader{R: r} var padding uint8 - if err := binary.Read(r, binary.LittleEndian, &padding); err != nil { - return block, err + br.ReadLE(&padding) + if br.Err != nil { + return block, br.Err } block.Script = &transaction.Witness{} @@ -89,17 +90,15 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) { return block, err } - lenTX := util.ReadVarUint(r) + lenTX := br.ReadVarUint() block.Transactions = make([]*transaction.Transaction, lenTX) for i := 0; i < int(lenTX); i++ { var hash util.Uint256 - if err := binary.Read(r, binary.LittleEndian, &hash); err != nil { - return block, err - } + br.ReadLE(&hash) block.Transactions[i] = transaction.NewTrimmedTX(hash) } - return block, nil + return block, br.Err } // Trim returns a subset of the block data to save up space @@ -110,23 +109,22 @@ func (b *Block) Trim() ([]byte, error) { if err := b.encodeHashableFields(buf); err != nil { return nil, err } - if err := binary.Write(buf, binary.LittleEndian, uint8(1)); err != nil { - return nil, err + bw := util.BinWriter{W: buf} + bw.WriteLE(uint8(1)) + if bw.Err != nil { + return nil, bw.Err } if err := b.Script.EncodeBinary(buf); err != nil { return nil, err } - lenTX := uint64(len(b.Transactions)) - if err := util.WriteVarUint(buf, lenTX); err != nil { - return nil, err - } + bw.WriteVarUint(uint64(len(b.Transactions))) for _, tx := range b.Transactions { - if err := binary.Write(buf, binary.LittleEndian, tx.Hash()); err != nil { - return nil, err - } + bw.WriteLE(tx.Hash()) + } + if bw.Err != nil { + return nil, bw.Err } - return buf.Bytes(), nil } @@ -136,7 +134,11 @@ func (b *Block) DecodeBinary(r io.Reader) error { return err } - lentx := util.ReadVarUint(r) + br := util.BinReader{R: r} + lentx := br.ReadVarUint() + if br.Err != nil { + return br.Err + } b.Transactions = make([]*transaction.Transaction, lentx) for i := 0; i < int(lentx); i++ { b.Transactions[i] = &transaction.Transaction{} diff --git a/pkg/core/block_base.go b/pkg/core/block_base.go index 608e3e706..00fd4d277 100644 --- a/pkg/core/block_base.go +++ b/pkg/core/block_base.go @@ -2,7 +2,6 @@ package core import ( "bytes" - "encoding/binary" "fmt" "io" @@ -67,8 +66,10 @@ func (b *BlockBase) DecodeBinary(r io.Reader) error { } var padding uint8 - if err := binary.Read(r, binary.LittleEndian, &padding); err != nil { - return err + br := util.BinReader{R: r} + br.ReadLE(&padding) + if br.Err != nil { + return br.Err } if padding != 1 { return fmt.Errorf("format error: padding must equal 1 got %d", padding) @@ -83,8 +84,10 @@ func (b *BlockBase) EncodeBinary(w io.Writer) error { if err := b.encodeHashableFields(w); err != nil { return err } - if err := binary.Write(w, binary.LittleEndian, uint8(1)); err != nil { - return err + bw := util.BinWriter{W: w} + bw.WriteLE(uint8(1)) + if bw.Err != nil { + return bw.Err } return b.Script.EncodeBinary(w) } @@ -108,50 +111,31 @@ 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 { - if err := binary.Write(w, binary.LittleEndian, b.Version); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, b.PrevHash); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, b.MerkleRoot); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, b.Timestamp); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, b.Index); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, b.ConsensusData); err != nil { - return err - } - return binary.Write(w, binary.LittleEndian, b.NextConsensus) + bw := util.BinWriter{W: w} + bw.WriteLE(b.Version) + bw.WriteLE(b.PrevHash) + bw.WriteLE(b.MerkleRoot) + bw.WriteLE(b.Timestamp) + bw.WriteLE(b.Index) + bw.WriteLE(b.ConsensusData) + bw.WriteLE(b.NextConsensus) + return bw.Err } // 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 { - if err := binary.Read(r, binary.LittleEndian, &b.Version); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &b.PrevHash); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &b.MerkleRoot); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &b.Timestamp); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &b.Index); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &b.ConsensusData); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &b.NextConsensus); err != nil { - return err + br := util.BinReader{R: r} + br.ReadLE(&b.Version) + br.ReadLE(&b.PrevHash) + br.ReadLE(&b.MerkleRoot) + br.ReadLE(&b.Timestamp) + br.ReadLE(&b.Index) + br.ReadLE(&b.ConsensusData) + br.ReadLE(&b.NextConsensus) + + if br.Err != nil { + return br.Err } // Make the hash of the block here so we dont need to do this diff --git a/pkg/core/header_hash_list.go b/pkg/core/header_hash_list.go index ad97b526e..35c190afa 100644 --- a/pkg/core/header_hash_list.go +++ b/pkg/core/header_hash_list.go @@ -1,7 +1,6 @@ package core import ( - "encoding/binary" "io" "github.com/CityOfZion/neo-go/pkg/util" @@ -60,14 +59,11 @@ func (l *HeaderHashList) Slice(start, end int) []util.Uint256 { // WriteTo will write n underlying hashes to the given io.Writer // starting from start. func (l *HeaderHashList) Write(w io.Writer, start, n int) error { - if err := util.WriteVarUint(w, uint64(n)); err != nil { - return err - } + bw := util.BinWriter{W: w} + bw.WriteVarUint(uint64(n)) hashes := l.Slice(start, start+n) for _, hash := range hashes { - if err := binary.Write(w, binary.LittleEndian, hash); err != nil { - return err - } + bw.WriteLE(hash) } - return nil + return bw.Err } diff --git a/pkg/core/spent_coin_state.go b/pkg/core/spent_coin_state.go index 9e590dd49..fcfde1ae7 100644 --- a/pkg/core/spent_coin_state.go +++ b/pkg/core/spent_coin_state.go @@ -2,7 +2,6 @@ package core import ( "bytes" - "encoding/binary" "fmt" "io" @@ -68,49 +67,33 @@ func NewSpentCoinState(hash util.Uint256, height uint32) *SpentCoinState { // DecodeBinary implements the Payload interface. func (s *SpentCoinState) DecodeBinary(r io.Reader) error { - if err := binary.Read(r, binary.LittleEndian, &s.txHash); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &s.txHeight); err != nil { - return err - } + br := util.BinReader{R: r} + br.ReadLE(&s.txHash) + br.ReadLE(&s.txHeight) s.items = make(map[uint16]uint32) - lenItems := util.ReadVarUint(r) + lenItems := br.ReadVarUint() for i := 0; i < int(lenItems); i++ { var ( key uint16 value uint32 ) - if err := binary.Read(r, binary.LittleEndian, &key); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &value); err != nil { - return err - } + br.ReadLE(&key) + br.ReadLE(&value) s.items[key] = value } - return nil + return br.Err } // EncodeBinary implements the Payload interface. func (s *SpentCoinState) EncodeBinary(w io.Writer) error { - if err := binary.Write(w, binary.LittleEndian, s.txHash); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, s.txHeight); err != nil { - return err - } - if err := util.WriteVarUint(w, uint64(len(s.items))); err != nil { - return err - } + bw := util.BinWriter{W: w} + bw.WriteLE(s.txHash) + bw.WriteLE(s.txHeight) + bw.WriteVarUint(uint64(len(s.items))) for k, v := range s.items { - if err := binary.Write(w, binary.LittleEndian, k); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, v); err != nil { - return err - } + bw.WriteLE(k) + bw.WriteLE(v) } - return nil + return bw.Err } diff --git a/pkg/core/storage/helpers.go b/pkg/core/storage/helpers.go index b98c7671c..2776da38c 100644 --- a/pkg/core/storage/helpers.go +++ b/pkg/core/storage/helpers.go @@ -84,10 +84,12 @@ func HeaderHashes(s Store) ([]util.Uint256, error) { // the given byte array. func read2000Uint256Hashes(b []byte) ([]util.Uint256, error) { r := bytes.NewReader(b) - lenHashes := util.ReadVarUint(r) + br := util.BinReader{R: r} + lenHashes := br.ReadVarUint() hashes := make([]util.Uint256, lenHashes) - if err := binary.Read(r, binary.LittleEndian, hashes); err != nil { - return nil, err + br.ReadLE(hashes) + if br.Err != nil { + return nil, br.Err } return hashes, nil } diff --git a/pkg/core/transaction/attribute.go b/pkg/core/transaction/attribute.go index 783b1dcc3..34bf6443c 100644 --- a/pkg/core/transaction/attribute.go +++ b/pkg/core/transaction/attribute.go @@ -1,7 +1,6 @@ package transaction import ( - "encoding/binary" "encoding/hex" "encoding/json" "fmt" @@ -18,66 +17,58 @@ type Attribute struct { // DecodeBinary implements the Payload interface. func (attr *Attribute) DecodeBinary(r io.Reader) error { - if err := binary.Read(r, binary.LittleEndian, &attr.Usage); err != nil { - return err - } - if attr.Usage == ContractHash || - attr.Usage == Vote || - (attr.Usage >= Hash1 && attr.Usage <= Hash15) { - attr.Data = make([]byte, 32) - return binary.Read(r, binary.LittleEndian, attr.Data) - } + br := util.BinReader{R: r} + br.ReadLE(&attr.Usage) + + // very special case if attr.Usage == ECDH02 || attr.Usage == ECDH03 { attr.Data = make([]byte, 33) attr.Data[0] = byte(attr.Usage) - return binary.Read(r, binary.LittleEndian, attr.Data[1:]) + br.ReadLE(attr.Data[1:]) + return br.Err } - if attr.Usage == Script { - attr.Data = make([]byte, 20) - return binary.Read(r, binary.LittleEndian, attr.Data) + var datasize uint64 + switch attr.Usage { + case ContractHash, Vote, Hash1, Hash2, Hash3, Hash4, Hash5, + Hash6, Hash7, Hash8, Hash9, Hash10, Hash11, Hash12, Hash13, + Hash14, Hash15: + datasize = 32 + case Script: + datasize = 20 + case DescriptionURL: + datasize = 1 + case Description, Remark, Remark1, Remark2, Remark3, Remark4, + Remark5, Remark6, Remark7, Remark8, Remark9, Remark10, Remark11, + Remark12, Remark13, Remark14, Remark15: + datasize = br.ReadVarUint() + default: + return fmt.Errorf("failed decoding TX attribute usage: 0x%2x", attr.Usage) } - if attr.Usage == DescriptionURL { - attr.Data = make([]byte, 1) - return binary.Read(r, binary.LittleEndian, attr.Data) - } - if attr.Usage == Description || attr.Usage >= Remark { - lenData := util.ReadVarUint(r) - attr.Data = make([]byte, lenData) - return binary.Read(r, binary.LittleEndian, attr.Data) - } - return fmt.Errorf("failed decoding TX attribute usage: 0x%2x", attr.Usage) + attr.Data = make([]byte, datasize) + br.ReadLE(attr.Data) + return br.Err } // EncodeBinary implements the Payload interface. func (attr *Attribute) EncodeBinary(w io.Writer) error { - if err := binary.Write(w, binary.LittleEndian, &attr.Usage); err != nil { - return err + bw := util.BinWriter{W: w} + bw.WriteLE(&attr.Usage) + switch attr.Usage { + case ECDH02, ECDH03: + bw.WriteLE(attr.Data[1:]) + case DescriptionURL, Description, Remark, Remark1, Remark2, Remark3, Remark4, + Remark5, Remark6, Remark7, Remark8, Remark9, Remark10, Remark11, + Remark12, Remark13, Remark14, Remark15: + bw.WriteVarUint(uint64(len(attr.Data))) + fallthrough + case Script, ContractHash, Vote, Hash1, Hash2, Hash3, Hash4, Hash5, Hash6, + Hash7, Hash8, Hash9, Hash10, Hash11, Hash12, Hash13, Hash14, Hash15: + bw.WriteLE(attr.Data) + default: + return fmt.Errorf("failed encoding TX attribute usage: 0x%2x", attr.Usage) } - if attr.Usage == ContractHash || - attr.Usage == Vote || - (attr.Usage >= Hash1 && attr.Usage <= Hash15) { - return binary.Write(w, binary.LittleEndian, attr.Data) - } - if attr.Usage == ECDH02 || attr.Usage == ECDH03 { - attr.Data[0] = byte(attr.Usage) - return binary.Write(w, binary.LittleEndian, attr.Data[1:33]) - } - if attr.Usage == Script { - return binary.Write(w, binary.LittleEndian, attr.Data) - } - if attr.Usage == DescriptionURL { - if err := util.WriteVarUint(w, uint64(len(attr.Data))); err != nil { - return err - } - return binary.Write(w, binary.LittleEndian, attr.Data) - } - if attr.Usage == Description || attr.Usage >= Remark { - if err := util.WriteVarUint(w, uint64(len(attr.Data))); err != nil { - return err - } - return binary.Write(w, binary.LittleEndian, attr.Data) - } - return fmt.Errorf("failed encoding TX attribute usage: 0x%2x", attr.Usage) + + return bw.Err } // Size returns the size in number bytes of the Attribute diff --git a/pkg/core/transaction/claim.go b/pkg/core/transaction/claim.go index b620ae297..ecb7f0720 100644 --- a/pkg/core/transaction/claim.go +++ b/pkg/core/transaction/claim.go @@ -13,7 +13,11 @@ type ClaimTX struct { // DecodeBinary implements the Payload interface. func (tx *ClaimTX) DecodeBinary(r io.Reader) error { - lenClaims := util.ReadVarUint(r) + br := util.BinReader{R: r} + lenClaims := br.ReadVarUint() + if br.Err != nil { + return br.Err + } tx.Claims = make([]*Input, lenClaims) for i := 0; i < int(lenClaims); i++ { tx.Claims[i] = &Input{} @@ -26,8 +30,10 @@ func (tx *ClaimTX) DecodeBinary(r io.Reader) error { // EncodeBinary implements the Payload interface. func (tx *ClaimTX) EncodeBinary(w io.Writer) error { - if err := util.WriteVarUint(w, uint64(len(tx.Claims))); err != nil { - return err + bw := util.BinWriter{W: w} + 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 { diff --git a/pkg/core/transaction/input.go b/pkg/core/transaction/input.go index 23ef80c03..ab923981f 100644 --- a/pkg/core/transaction/input.go +++ b/pkg/core/transaction/input.go @@ -1,7 +1,6 @@ package transaction import ( - "encoding/binary" "io" "github.com/CityOfZion/neo-go/pkg/util" @@ -18,21 +17,18 @@ type Input struct { // DecodeBinary implements the Payload interface. func (in *Input) DecodeBinary(r io.Reader) error { - if err := binary.Read(r, binary.LittleEndian, &in.PrevHash); err != nil { - return err - } - return binary.Read(r, binary.LittleEndian, &in.PrevIndex) + br := util.BinReader{R: r} + br.ReadLE(&in.PrevHash) + br.ReadLE(&in.PrevIndex) + return br.Err } // EncodeBinary implements the Payload interface. func (in *Input) EncodeBinary(w io.Writer) error { - if err := binary.Write(w, binary.LittleEndian, in.PrevHash); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, in.PrevIndex); err != nil { - return err - } - return nil + bw := util.BinWriter{W: w} + bw.WriteLE(in.PrevHash) + bw.WriteLE(in.PrevIndex) + return bw.Err } // Size returns the size in bytes of the Input diff --git a/pkg/core/transaction/invocation.go b/pkg/core/transaction/invocation.go index 216d141fb..f07233cfe 100644 --- a/pkg/core/transaction/invocation.go +++ b/pkg/core/transaction/invocation.go @@ -1,7 +1,6 @@ package transaction import ( - "encoding/binary" "io" "github.com/CityOfZion/neo-go/pkg/util" @@ -34,21 +33,16 @@ func NewInvocationTX(script []byte) *Transaction { // DecodeBinary implements the Payload interface. func (tx *InvocationTX) DecodeBinary(r io.Reader) error { - lenScript := util.ReadVarUint(r) - tx.Script = make([]byte, lenScript) - if err := binary.Read(r, binary.LittleEndian, tx.Script); err != nil { - return err - } - return binary.Read(r, binary.LittleEndian, &tx.Gas) + br := util.BinReader{R: r} + tx.Script = br.ReadBytes() + br.ReadLE(&tx.Gas) + return br.Err } // EncodeBinary implements the Payload interface. func (tx *InvocationTX) EncodeBinary(w io.Writer) error { - if err := util.WriteVarUint(w, uint64(len(tx.Script))); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, tx.Script); err != nil { - return err - } - return binary.Write(w, binary.LittleEndian, tx.Gas) + bw := util.BinWriter{W: w} + bw.WriteBytes(tx.Script) + bw.WriteLE(tx.Gas) + return bw.Err } diff --git a/pkg/core/transaction/output.go b/pkg/core/transaction/output.go index 2898605aa..60a55b5cf 100644 --- a/pkg/core/transaction/output.go +++ b/pkg/core/transaction/output.go @@ -1,7 +1,6 @@ package transaction import ( - "encoding/binary" "encoding/json" "io" @@ -36,24 +35,20 @@ func NewOutput(assetID util.Uint256, amount util.Fixed8, scriptHash util.Uint160 // DecodeBinary implements the Payload interface. func (out *Output) DecodeBinary(r io.Reader) error { - if err := binary.Read(r, binary.LittleEndian, &out.AssetID); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &out.Amount); err != nil { - return err - } - return binary.Read(r, binary.LittleEndian, &out.ScriptHash) + br := util.BinReader{R: r} + br.ReadLE(&out.AssetID) + br.ReadLE(&out.Amount) + br.ReadLE(&out.ScriptHash) + return br.Err } // EncodeBinary implements the Payload interface. func (out *Output) EncodeBinary(w io.Writer) error { - if err := binary.Write(w, binary.LittleEndian, out.AssetID); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, out.Amount); err != nil { - return err - } - return binary.Write(w, binary.LittleEndian, out.ScriptHash) + bw := util.BinWriter{W: w} + bw.WriteLE(out.AssetID) + bw.WriteLE(out.Amount) + bw.WriteLE(out.ScriptHash) + return bw.Err } // Size returns the size in bytes of the Output diff --git a/pkg/core/transaction/publish.go b/pkg/core/transaction/publish.go index ed92409c9..f6a247b92 100644 --- a/pkg/core/transaction/publish.go +++ b/pkg/core/transaction/publish.go @@ -1,7 +1,6 @@ package transaction import ( - "encoding/binary" "io" "github.com/CityOfZion/neo-go/pkg/smartcontract" @@ -24,55 +23,30 @@ type PublishTX struct { // DecodeBinary implements the Payload interface. func (tx *PublishTX) DecodeBinary(r io.Reader) error { - var err error + br := util.BinReader{R: r} + tx.Script = br.ReadBytes() - tx.Script, err = util.ReadVarBytes(r) - if err != nil { - return err - } - - lenParams := util.ReadVarUint(r) + lenParams := br.ReadVarUint() tx.ParamList = make([]smartcontract.ParamType, lenParams) for i := 0; i < int(lenParams); i++ { var ptype uint8 - if err := binary.Read(r, binary.LittleEndian, &ptype); err != nil { - return err - } + br.ReadLE(&ptype) tx.ParamList[i] = smartcontract.ParamType(ptype) } var rtype uint8 - if err := binary.Read(r, binary.LittleEndian, &rtype); err != nil { - return err - } + br.ReadLE(&rtype) tx.ReturnType = smartcontract.ParamType(rtype) - if err := binary.Read(r, binary.LittleEndian, &tx.NeedStorage); err != nil { - return err - } + br.ReadLE(&tx.NeedStorage) - tx.Name, err = util.ReadVarString(r) - if err != nil { - return err - } - tx.CodeVersion, err = util.ReadVarString(r) - if err != nil { - return err - } - tx.Author, err = util.ReadVarString(r) - if err != nil { - return err - } - tx.Email, err = util.ReadVarString(r) - if err != nil { - return err - } - tx.Description, err = util.ReadVarString(r) - if err != nil { - return err - } + tx.Name = br.ReadString() + tx.CodeVersion = br.ReadString() + tx.Author = br.ReadString() + tx.Email = br.ReadString() + tx.Description = br.ReadString() - return nil + return br.Err } // EncodeBinary implements the Payload interface. diff --git a/pkg/core/transaction/register.go b/pkg/core/transaction/register.go index 5f2467a47..2d47fd442 100644 --- a/pkg/core/transaction/register.go +++ b/pkg/core/transaction/register.go @@ -1,7 +1,6 @@ package transaction import ( - "encoding/binary" "io" "github.com/CityOfZion/neo-go/pkg/crypto/keys" @@ -32,22 +31,15 @@ type RegisterTX struct { // DecodeBinary implements the Payload interface. func (tx *RegisterTX) DecodeBinary(r io.Reader) error { - if err := binary.Read(r, binary.LittleEndian, &tx.AssetType); err != nil { - return err - } + br := util.BinReader{R: r} + br.ReadLE(&tx.AssetType) - var err error - tx.Name, err = util.ReadVarString(r) - if err != nil { - return err - } + tx.Name = br.ReadString() - if err := binary.Read(r, binary.LittleEndian, &tx.Amount); err != nil { - return err - } - - if err := binary.Read(r, binary.LittleEndian, &tx.Precision); err != nil { - return err + br.ReadLE(&tx.Amount) + br.ReadLE(&tx.Precision) + if br.Err != nil { + return br.Err } tx.Owner = &keys.PublicKey{} @@ -55,25 +47,18 @@ func (tx *RegisterTX) DecodeBinary(r io.Reader) error { return err } - return binary.Read(r, binary.LittleEndian, &tx.Admin) + br.ReadLE(&tx.Admin) + return br.Err } // EncodeBinary implements the Payload interface. func (tx *RegisterTX) EncodeBinary(w io.Writer) error { - if err := binary.Write(w, binary.LittleEndian, tx.AssetType); err != nil { - return err - } - if err := util.WriteVarString(w, tx.Name); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, tx.Amount); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, tx.Precision); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, tx.Owner.Bytes()); err != nil { - return err - } - return binary.Write(w, binary.LittleEndian, tx.Admin) + bw := util.BinWriter{W: w} + bw.WriteLE(tx.AssetType) + bw.WriteString(tx.Name) + bw.WriteLE(tx.Amount) + bw.WriteLE(tx.Precision) + bw.WriteLE(tx.Owner.Bytes()) + bw.WriteLE(tx.Admin) + return bw.Err } diff --git a/pkg/core/transaction/state.go b/pkg/core/transaction/state.go index 3b61e7f84..6bcbf8e2a 100644 --- a/pkg/core/transaction/state.go +++ b/pkg/core/transaction/state.go @@ -13,7 +13,11 @@ type StateTX struct { // DecodeBinary implements the Payload interface. func (tx *StateTX) DecodeBinary(r io.Reader) error { - lenDesc := util.ReadVarUint(r) + br := util.BinReader{R: r} + lenDesc := br.ReadVarUint() + if br.Err != nil { + return br.Err + } for i := 0; i < int(lenDesc); i++ { tx.Descriptors[i] = &StateDescriptor{} if err := tx.Descriptors[i].DecodeBinary(r); err != nil { diff --git a/pkg/core/transaction/state_descriptor.go b/pkg/core/transaction/state_descriptor.go index b45b250a3..95f41be52 100644 --- a/pkg/core/transaction/state_descriptor.go +++ b/pkg/core/transaction/state_descriptor.go @@ -1,7 +1,6 @@ package transaction import ( - "encoding/binary" "io" "github.com/CityOfZion/neo-go/pkg/util" @@ -26,30 +25,14 @@ type StateDescriptor struct { // DecodeBinary implements the Payload interface. func (s *StateDescriptor) DecodeBinary(r io.Reader) error { - if err := binary.Read(r, binary.LittleEndian, &s.Type); err != nil { - return err - } + br := util.BinReader{R: r} + br.ReadLE(&s.Type) - keyLen := util.ReadVarUint(r) - s.Key = make([]byte, keyLen) - if err := binary.Read(r, binary.LittleEndian, s.Key); err != nil { - return err - } + s.Key = br.ReadBytes() + s.Value = br.ReadBytes() + s.Field = br.ReadString() - valLen := util.ReadVarUint(r) - s.Value = make([]byte, valLen) - if err := binary.Read(r, binary.LittleEndian, s.Value); err != nil { - return err - } - - fieldLen := util.ReadVarUint(r) - field := make([]byte, fieldLen) - if err := binary.Read(r, binary.LittleEndian, field); err != nil { - return err - } - s.Field = string(field) - - return nil + return br.Err } // EncodeBinary implements the Payload interface. diff --git a/pkg/core/transaction/transaction.go b/pkg/core/transaction/transaction.go index d95f73dd9..fb83461a2 100644 --- a/pkg/core/transaction/transaction.go +++ b/pkg/core/transaction/transaction.go @@ -2,7 +2,6 @@ package transaction import ( "bytes" - "encoding/binary" "io" "github.com/CityOfZion/neo-go/pkg/crypto/hash" @@ -79,17 +78,17 @@ func (t *Transaction) AddInput(in *Input) { // DecodeBinary implements the payload interface. func (t *Transaction) DecodeBinary(r io.Reader) error { - if err := binary.Read(r, binary.LittleEndian, &t.Type); err != nil { - return err - } - if err := binary.Read(r, binary.LittleEndian, &t.Version); err != nil { - return err + br := util.BinReader{R: r} + br.ReadLE(&t.Type) + br.ReadLE(&t.Version) + if br.Err != nil { + return br.Err } if err := t.decodeData(r); err != nil { return err } - lenAttrs := util.ReadVarUint(r) + lenAttrs := br.ReadVarUint() t.Attributes = make([]*Attribute, lenAttrs) for i := 0; i < int(lenAttrs); i++ { t.Attributes[i] = &Attribute{} @@ -100,7 +99,7 @@ func (t *Transaction) DecodeBinary(r io.Reader) error { } } - lenInputs := util.ReadVarUint(r) + lenInputs := br.ReadVarUint() t.Inputs = make([]*Input, lenInputs) for i := 0; i < int(lenInputs); i++ { t.Inputs[i] = &Input{} @@ -109,7 +108,7 @@ func (t *Transaction) DecodeBinary(r io.Reader) error { } } - lenOutputs := util.ReadVarUint(r) + lenOutputs := br.ReadVarUint() t.Outputs = make([]*Output, lenOutputs) for i := 0; i < int(lenOutputs); i++ { t.Outputs[i] = &Output{} @@ -118,7 +117,7 @@ func (t *Transaction) DecodeBinary(r io.Reader) error { } } - lenScripts := util.ReadVarUint(r) + lenScripts := br.ReadVarUint() t.Scripts = make([]*Witness, lenScripts) for i := 0; i < int(lenScripts); i++ { t.Scripts[i] = &Witness{} @@ -127,6 +126,9 @@ func (t *Transaction) DecodeBinary(r io.Reader) error { } } + if br.Err != nil { + return br.Err + } // Create the hash of the transaction at decode, so we dont need // to do it anymore. return t.createHash() @@ -172,8 +174,10 @@ func (t *Transaction) EncodeBinary(w io.Writer) error { if err := t.encodeHashableFields(w); err != nil { return err } - if err := util.WriteVarUint(w, uint64(len(t.Scripts))); err != nil { - return err + bw := util.BinWriter{W: 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 { @@ -186,11 +190,12 @@ 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 { - if err := binary.Write(w, binary.LittleEndian, t.Type); err != nil { - return err - } - if err := binary.Write(w, binary.LittleEndian, t.Version); err != nil { - return err + bw := util.BinWriter{W: w} + + bw.WriteLE(t.Type) + bw.WriteLE(t.Version) + if bw.Err != nil { + return bw.Err } // Underlying TXer. @@ -201,9 +206,9 @@ func (t *Transaction) encodeHashableFields(w io.Writer) error { } // Attributes - lenAttrs := uint64(len(t.Attributes)) - if err := util.WriteVarUint(w, lenAttrs); err != nil { - return err + bw.WriteVarUint(uint64(len(t.Attributes))) + if bw.Err != nil { + return bw.Err } for _, attr := range t.Attributes { if err := attr.EncodeBinary(w); err != nil { @@ -212,8 +217,9 @@ func (t *Transaction) encodeHashableFields(w io.Writer) error { } // Inputs - if err := util.WriteVarUint(w, uint64(len(t.Inputs))); err != nil { - return err + bw.WriteVarUint(uint64(len(t.Inputs))) + if bw.Err != nil { + return bw.Err } for _, in := range t.Inputs { if err := in.EncodeBinary(w); err != nil { @@ -222,8 +228,9 @@ func (t *Transaction) encodeHashableFields(w io.Writer) error { } // Outputs - if err := util.WriteVarUint(w, uint64(len(t.Outputs))); err != nil { - return err + bw.WriteVarUint(uint64(len(t.Outputs))) + if bw.Err != nil { + return bw.Err } for _, out := range t.Outputs { if err := out.EncodeBinary(w); err != nil { diff --git a/pkg/core/transaction/witness.go b/pkg/core/transaction/witness.go index cf10d8bb2..125fede63 100644 --- a/pkg/core/transaction/witness.go +++ b/pkg/core/transaction/witness.go @@ -1,7 +1,6 @@ package transaction import ( - "encoding/binary" "encoding/hex" "encoding/json" "io" @@ -18,28 +17,21 @@ type Witness struct { // DecodeBinary implements the payload interface. func (w *Witness) DecodeBinary(r io.Reader) error { - lenb := util.ReadVarUint(r) - w.InvocationScript = make([]byte, lenb) - if err := binary.Read(r, binary.LittleEndian, w.InvocationScript); err != nil { - return err - } - lenb = util.ReadVarUint(r) - w.VerificationScript = make([]byte, lenb) - return binary.Read(r, binary.LittleEndian, w.VerificationScript) + br := util.BinReader{R: r} + + w.InvocationScript = br.ReadBytes() + w.VerificationScript = br.ReadBytes() + return br.Err } // EncodeBinary implements the payload interface. func (w *Witness) EncodeBinary(writer io.Writer) error { - if err := util.WriteVarUint(writer, uint64(len(w.InvocationScript))); err != nil { - return err - } - if err := binary.Write(writer, binary.LittleEndian, w.InvocationScript); err != nil { - return err - } - if err := util.WriteVarUint(writer, uint64(len(w.VerificationScript))); err != nil { - return err - } - return binary.Write(writer, binary.LittleEndian, w.VerificationScript) + bw := util.BinWriter{W: writer} + + bw.WriteBytes(w.InvocationScript) + bw.WriteBytes(w.VerificationScript) + + return bw.Err } // MarshalJSON implements the json marshaller interface. diff --git a/pkg/core/unspent_coin_state.go b/pkg/core/unspent_coin_state.go index e588e0575..e8972934f 100644 --- a/pkg/core/unspent_coin_state.go +++ b/pkg/core/unspent_coin_state.go @@ -2,7 +2,6 @@ package core import ( "bytes" - "encoding/binary" "fmt" "io" @@ -68,29 +67,25 @@ func (u UnspentCoins) commit(b storage.Batch) error { // EncodeBinary encodes UnspentCoinState to the given io.Writer. func (s *UnspentCoinState) EncodeBinary(w io.Writer) error { - if err := util.WriteVarUint(w, uint64(len(s.states))); err != nil { - return err - } + bw := util.BinWriter{W: w} + bw.WriteVarUint(uint64(len(s.states))) for _, state := range s.states { - if err := binary.Write(w, binary.LittleEndian, byte(state)); err != nil { - return err - } + bw.WriteLE(byte(state)) } - return nil + return bw.Err } // DecodeBinary decodes UnspentCoinState from the given io.Reader. func (s *UnspentCoinState) DecodeBinary(r io.Reader) error { - lenStates := util.ReadVarUint(r) + br := util.BinReader{R: r} + lenStates := br.ReadVarUint() s.states = make([]CoinState, lenStates) for i := 0; i < int(lenStates); i++ { var state uint8 - if err := binary.Read(r, binary.LittleEndian, &state); err != nil { - return err - } + br.ReadLE(&state) s.states[i] = CoinState(state) } - return nil + return br.Err } // IsDoubleSpend verifies that the input transactions are not double spent.