pkg/core: use util.binaryReader/Writer

Simplify error handling.
This commit is contained in:
Roman Khimov 2019-08-28 19:27:06 +03:00
parent 459542a978
commit 361724a33e
19 changed files with 291 additions and 467 deletions

View file

@ -2,7 +2,6 @@ package core
import ( import (
"bytes" "bytes"
"encoding/binary"
"fmt" "fmt"
"io" "io"
@ -69,17 +68,11 @@ func NewAccountState(scriptHash util.Uint160) *AccountState {
// DecodeBinary decodes AccountState from the given io.Reader. // DecodeBinary decodes AccountState from the given io.Reader.
func (s *AccountState) DecodeBinary(r io.Reader) error { func (s *AccountState) DecodeBinary(r io.Reader) error {
if err := binary.Read(r, binary.LittleEndian, &s.Version); err != nil { br := util.BinReader{R: r}
return err br.ReadLE(&s.Version)
} br.ReadLE(&s.ScriptHash)
if err := binary.Read(r, binary.LittleEndian, &s.ScriptHash); err != nil { br.ReadLE(&s.IsFrozen)
return err lenVotes := br.ReadVarUint()
}
if err := binary.Read(r, binary.LittleEndian, &s.IsFrozen); err != nil {
return err
}
lenVotes := util.ReadVarUint(r)
s.Votes = make([]*keys.PublicKey, lenVotes) s.Votes = make([]*keys.PublicKey, lenVotes)
for i := 0; i < int(lenVotes); i++ { for i := 0; i < int(lenVotes); i++ {
s.Votes[i] = &keys.PublicKey{} s.Votes[i] = &keys.PublicKey{}
@ -89,37 +82,25 @@ func (s *AccountState) DecodeBinary(r io.Reader) error {
} }
s.Balances = make(map[util.Uint256]util.Fixed8) s.Balances = make(map[util.Uint256]util.Fixed8)
lenBalances := util.ReadVarUint(r) lenBalances := br.ReadVarUint()
for i := 0; i < int(lenBalances); i++ { for i := 0; i < int(lenBalances); i++ {
key := util.Uint256{} key := util.Uint256{}
if err := binary.Read(r, binary.LittleEndian, &key); err != nil { br.ReadLE(&key)
return err
}
var val util.Fixed8 var val util.Fixed8
if err := binary.Read(r, binary.LittleEndian, &val); err != nil { br.ReadLE(&val)
return err
}
s.Balances[key] = val s.Balances[key] = val
} }
return nil return br.Err
} }
// EncodeBinary encode AccountState to the given io.Writer. // EncodeBinary encode AccountState to the given io.Writer.
func (s *AccountState) EncodeBinary(w io.Writer) error { func (s *AccountState) EncodeBinary(w io.Writer) error {
if err := binary.Write(w, binary.LittleEndian, s.Version); err != nil { bw := util.BinWriter{W: w}
return err bw.WriteLE(s.Version)
} bw.WriteLE(s.ScriptHash)
if err := binary.Write(w, binary.LittleEndian, s.ScriptHash); err != nil { bw.WriteLE(s.IsFrozen)
return err bw.WriteVarUint(uint64(len(s.Votes)))
}
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
}
for _, point := range s.Votes { for _, point := range s.Votes {
if err := point.EncodeBinary(w); err != nil { if err := point.EncodeBinary(w); err != nil {
return err return err
@ -127,19 +108,13 @@ func (s *AccountState) EncodeBinary(w io.Writer) error {
} }
balances := s.nonZeroBalances() balances := s.nonZeroBalances()
if err := util.WriteVarUint(w, uint64(len(balances))); err != nil { bw.WriteVarUint(uint64(len(balances)))
return err
}
for k, v := range balances { for k, v := range balances {
if err := binary.Write(w, binary.LittleEndian, k); err != nil { bw.WriteLE(k)
return err bw.WriteLE(v)
}
if err := binary.Write(w, binary.LittleEndian, v); err != nil {
return err
}
} }
return nil return bw.Err
} }
// Returns only the non-zero balances for the account. // Returns only the non-zero balances for the account.

View file

@ -2,7 +2,6 @@ package core
import ( import (
"bytes" "bytes"
"encoding/binary"
"io" "io"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
@ -48,95 +47,56 @@ type AssetState struct {
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (a *AssetState) DecodeBinary(r io.Reader) error { func (a *AssetState) DecodeBinary(r io.Reader) error {
if err := binary.Read(r, binary.LittleEndian, &a.ID); err != nil { br := util.BinReader{R: r}
return err br.ReadLE(&a.ID)
} br.ReadLE(&a.AssetType)
if err := binary.Read(r, binary.LittleEndian, &a.AssetType); err != nil {
return err
}
var err error a.Name = br.ReadString()
a.Name, err = util.ReadVarString(r)
if err != nil {
return err
}
if err := binary.Read(r, binary.LittleEndian, &a.Amount); err != nil { br.ReadLE(&a.Amount)
return err br.ReadLE(&a.Available)
} br.ReadLE(&a.Precision)
if err := binary.Read(r, binary.LittleEndian, &a.Available); err != nil { br.ReadLE(&a.FeeMode)
return err br.ReadLE(&a.FeeAddress)
}
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
}
if br.Err != nil {
return br.Err
}
a.Owner = &keys.PublicKey{} a.Owner = &keys.PublicKey{}
if err := a.Owner.DecodeBinary(r); err != nil { if err := a.Owner.DecodeBinary(r); err != nil {
return err return err
} }
if err := binary.Read(r, binary.LittleEndian, &a.Admin); err != nil { br.ReadLE(&a.Admin)
return err br.ReadLE(&a.Issuer)
} br.ReadLE(&a.Expiration)
if err := binary.Read(r, binary.LittleEndian, &a.Issuer); err != nil { br.ReadLE(&a.IsFrozen)
return err
} return br.Err
if err := binary.Read(r, binary.LittleEndian, &a.Expiration); err != nil {
return err
}
return binary.Read(r, binary.LittleEndian, &a.IsFrozen)
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (a *AssetState) EncodeBinary(w io.Writer) error { func (a *AssetState) EncodeBinary(w io.Writer) error {
if err := binary.Write(w, binary.LittleEndian, a.ID); err != nil { bw := util.BinWriter{W: w}
return err bw.WriteLE(a.ID)
} bw.WriteLE(a.AssetType)
if err := binary.Write(w, binary.LittleEndian, a.AssetType); err != nil { bw.WriteString(a.Name)
return err bw.WriteLE(a.Amount)
} bw.WriteLE(a.Available)
if err := util.WriteVarUint(w, uint64(len(a.Name))); err != nil { bw.WriteLE(a.Precision)
return err bw.WriteLE(a.FeeMode)
} bw.WriteLE(a.FeeAddress)
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
}
if err := binary.Write(w, binary.LittleEndian, a.FeeAddress); err != nil { if bw.Err != nil {
return err return bw.Err
} }
if err := a.Owner.EncodeBinary(w); err != nil { if err := a.Owner.EncodeBinary(w); err != nil {
return err return err
} }
if err := binary.Write(w, binary.LittleEndian, a.Admin); err != nil { bw.WriteLE(a.Admin)
return err bw.WriteLE(a.Issuer)
} bw.WriteLE(a.Expiration)
if err := binary.Write(w, binary.LittleEndian, a.Issuer); err != nil { bw.WriteLE(a.IsFrozen)
return err return bw.Err
}
if err := binary.Write(w, binary.LittleEndian, a.Expiration); err != nil {
return err
}
return binary.Write(w, binary.LittleEndian, a.IsFrozen)
} }
// GetName returns the asset name based on its type. // GetName returns the asset name based on its type.

View file

@ -2,7 +2,6 @@ package core
import ( import (
"bytes" "bytes"
"encoding/binary"
"io" "io"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
@ -79,9 +78,11 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) {
return block, err return block, err
} }
br := util.BinReader{R: r}
var padding uint8 var padding uint8
if err := binary.Read(r, binary.LittleEndian, &padding); err != nil { br.ReadLE(&padding)
return block, err if br.Err != nil {
return block, br.Err
} }
block.Script = &transaction.Witness{} block.Script = &transaction.Witness{}
@ -89,17 +90,15 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) {
return block, err return block, err
} }
lenTX := util.ReadVarUint(r) lenTX := br.ReadVarUint()
block.Transactions = make([]*transaction.Transaction, lenTX) block.Transactions = make([]*transaction.Transaction, lenTX)
for i := 0; i < int(lenTX); i++ { for i := 0; i < int(lenTX); i++ {
var hash util.Uint256 var hash util.Uint256
if err := binary.Read(r, binary.LittleEndian, &hash); err != nil { br.ReadLE(&hash)
return block, err
}
block.Transactions[i] = transaction.NewTrimmedTX(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 // 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 { if err := b.encodeHashableFields(buf); err != nil {
return nil, err return nil, err
} }
if err := binary.Write(buf, binary.LittleEndian, uint8(1)); err != nil { bw := util.BinWriter{W: buf}
return nil, err bw.WriteLE(uint8(1))
if bw.Err != nil {
return nil, bw.Err
} }
if err := b.Script.EncodeBinary(buf); err != nil { if err := b.Script.EncodeBinary(buf); err != nil {
return nil, err return nil, err
} }
lenTX := uint64(len(b.Transactions)) bw.WriteVarUint(uint64(len(b.Transactions)))
if err := util.WriteVarUint(buf, lenTX); err != nil {
return nil, err
}
for _, tx := range b.Transactions { for _, tx := range b.Transactions {
if err := binary.Write(buf, binary.LittleEndian, tx.Hash()); err != nil { bw.WriteLE(tx.Hash())
return nil, err
} }
if bw.Err != nil {
return nil, bw.Err
} }
return buf.Bytes(), nil return buf.Bytes(), nil
} }
@ -136,7 +134,11 @@ func (b *Block) DecodeBinary(r io.Reader) error {
return err 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) b.Transactions = make([]*transaction.Transaction, lentx)
for i := 0; i < int(lentx); i++ { for i := 0; i < int(lentx); i++ {
b.Transactions[i] = &transaction.Transaction{} b.Transactions[i] = &transaction.Transaction{}

View file

@ -2,7 +2,6 @@ package core
import ( import (
"bytes" "bytes"
"encoding/binary"
"fmt" "fmt"
"io" "io"
@ -67,8 +66,10 @@ func (b *BlockBase) DecodeBinary(r io.Reader) error {
} }
var padding uint8 var padding uint8
if err := binary.Read(r, binary.LittleEndian, &padding); err != nil { br := util.BinReader{R: r}
return err br.ReadLE(&padding)
if br.Err != nil {
return br.Err
} }
if padding != 1 { if padding != 1 {
return fmt.Errorf("format error: padding must equal 1 got %d", padding) 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 { if err := b.encodeHashableFields(w); err != nil {
return err return err
} }
if err := binary.Write(w, binary.LittleEndian, uint8(1)); err != nil { bw := util.BinWriter{W: w}
return err bw.WriteLE(uint8(1))
if bw.Err != nil {
return bw.Err
} }
return b.Script.EncodeBinary(w) return b.Script.EncodeBinary(w)
} }
@ -108,50 +111,31 @@ func (b *BlockBase) createHash() error {
// encodeHashableFields will only encode the fields used for hashing. // encodeHashableFields will only encode the fields used for hashing.
// see Hash() for more information about the fields. // see Hash() for more information about the fields.
func (b *BlockBase) encodeHashableFields(w io.Writer) error { func (b *BlockBase) encodeHashableFields(w io.Writer) error {
if err := binary.Write(w, binary.LittleEndian, b.Version); err != nil { bw := util.BinWriter{W: w}
return err bw.WriteLE(b.Version)
} bw.WriteLE(b.PrevHash)
if err := binary.Write(w, binary.LittleEndian, b.PrevHash); err != nil { bw.WriteLE(b.MerkleRoot)
return err bw.WriteLE(b.Timestamp)
} bw.WriteLE(b.Index)
if err := binary.Write(w, binary.LittleEndian, b.MerkleRoot); err != nil { bw.WriteLE(b.ConsensusData)
return err bw.WriteLE(b.NextConsensus)
} return bw.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)
} }
// decodeHashableFields will only decode the fields used for hashing. // decodeHashableFields will only decode the fields used for hashing.
// see Hash() for more information about the fields. // see Hash() for more information about the fields.
func (b *BlockBase) decodeHashableFields(r io.Reader) error { func (b *BlockBase) decodeHashableFields(r io.Reader) error {
if err := binary.Read(r, binary.LittleEndian, &b.Version); err != nil { br := util.BinReader{R: r}
return err br.ReadLE(&b.Version)
} br.ReadLE(&b.PrevHash)
if err := binary.Read(r, binary.LittleEndian, &b.PrevHash); err != nil { br.ReadLE(&b.MerkleRoot)
return err br.ReadLE(&b.Timestamp)
} br.ReadLE(&b.Index)
if err := binary.Read(r, binary.LittleEndian, &b.MerkleRoot); err != nil { br.ReadLE(&b.ConsensusData)
return err br.ReadLE(&b.NextConsensus)
}
if err := binary.Read(r, binary.LittleEndian, &b.Timestamp); err != nil { if br.Err != nil {
return err return br.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
} }
// Make the hash of the block here so we dont need to do this // Make the hash of the block here so we dont need to do this

View file

@ -1,7 +1,6 @@
package core package core
import ( import (
"encoding/binary"
"io" "io"
"github.com/CityOfZion/neo-go/pkg/util" "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 // WriteTo will write n underlying hashes to the given io.Writer
// starting from start. // starting from start.
func (l *HeaderHashList) Write(w io.Writer, start, n int) error { func (l *HeaderHashList) Write(w io.Writer, start, n int) error {
if err := util.WriteVarUint(w, uint64(n)); err != nil { bw := util.BinWriter{W: w}
return err bw.WriteVarUint(uint64(n))
}
hashes := l.Slice(start, start+n) hashes := l.Slice(start, start+n)
for _, hash := range hashes { for _, hash := range hashes {
if err := binary.Write(w, binary.LittleEndian, hash); err != nil { bw.WriteLE(hash)
return err
} }
} return bw.Err
return nil
} }

View file

@ -2,7 +2,6 @@ package core
import ( import (
"bytes" "bytes"
"encoding/binary"
"fmt" "fmt"
"io" "io"
@ -68,49 +67,33 @@ func NewSpentCoinState(hash util.Uint256, height uint32) *SpentCoinState {
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (s *SpentCoinState) DecodeBinary(r io.Reader) error { func (s *SpentCoinState) DecodeBinary(r io.Reader) error {
if err := binary.Read(r, binary.LittleEndian, &s.txHash); err != nil { br := util.BinReader{R: r}
return err br.ReadLE(&s.txHash)
} br.ReadLE(&s.txHeight)
if err := binary.Read(r, binary.LittleEndian, &s.txHeight); err != nil {
return err
}
s.items = make(map[uint16]uint32) s.items = make(map[uint16]uint32)
lenItems := util.ReadVarUint(r) lenItems := br.ReadVarUint()
for i := 0; i < int(lenItems); i++ { for i := 0; i < int(lenItems); i++ {
var ( var (
key uint16 key uint16
value uint32 value uint32
) )
if err := binary.Read(r, binary.LittleEndian, &key); err != nil { br.ReadLE(&key)
return err br.ReadLE(&value)
}
if err := binary.Read(r, binary.LittleEndian, &value); err != nil {
return err
}
s.items[key] = value s.items[key] = value
} }
return nil return br.Err
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (s *SpentCoinState) EncodeBinary(w io.Writer) error { func (s *SpentCoinState) EncodeBinary(w io.Writer) error {
if err := binary.Write(w, binary.LittleEndian, s.txHash); err != nil { bw := util.BinWriter{W: w}
return err bw.WriteLE(s.txHash)
} bw.WriteLE(s.txHeight)
if err := binary.Write(w, binary.LittleEndian, s.txHeight); err != nil { bw.WriteVarUint(uint64(len(s.items)))
return err
}
if err := util.WriteVarUint(w, uint64(len(s.items))); err != nil {
return err
}
for k, v := range s.items { for k, v := range s.items {
if err := binary.Write(w, binary.LittleEndian, k); err != nil { bw.WriteLE(k)
return err bw.WriteLE(v)
} }
if err := binary.Write(w, binary.LittleEndian, v); err != nil { return bw.Err
return err
}
}
return nil
} }

View file

@ -84,10 +84,12 @@ func HeaderHashes(s Store) ([]util.Uint256, error) {
// the given byte array. // the given byte array.
func read2000Uint256Hashes(b []byte) ([]util.Uint256, error) { func read2000Uint256Hashes(b []byte) ([]util.Uint256, error) {
r := bytes.NewReader(b) r := bytes.NewReader(b)
lenHashes := util.ReadVarUint(r) br := util.BinReader{R: r}
lenHashes := br.ReadVarUint()
hashes := make([]util.Uint256, lenHashes) hashes := make([]util.Uint256, lenHashes)
if err := binary.Read(r, binary.LittleEndian, hashes); err != nil { br.ReadLE(hashes)
return nil, err if br.Err != nil {
return nil, br.Err
} }
return hashes, nil return hashes, nil
} }

View file

@ -1,7 +1,6 @@
package transaction package transaction
import ( import (
"encoding/binary"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -18,68 +17,60 @@ type Attribute struct {
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (attr *Attribute) DecodeBinary(r io.Reader) error { func (attr *Attribute) DecodeBinary(r io.Reader) error {
if err := binary.Read(r, binary.LittleEndian, &attr.Usage); err != nil { br := util.BinReader{R: r}
return err br.ReadLE(&attr.Usage)
}
if attr.Usage == ContractHash || // very special case
attr.Usage == Vote ||
(attr.Usage >= Hash1 && attr.Usage <= Hash15) {
attr.Data = make([]byte, 32)
return binary.Read(r, binary.LittleEndian, attr.Data)
}
if attr.Usage == ECDH02 || attr.Usage == ECDH03 { if attr.Usage == ECDH02 || attr.Usage == ECDH03 {
attr.Data = make([]byte, 33) attr.Data = make([]byte, 33)
attr.Data[0] = byte(attr.Usage) 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)
}
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)
} }
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) 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. // EncodeBinary implements the Payload interface.
func (attr *Attribute) EncodeBinary(w io.Writer) error { func (attr *Attribute) EncodeBinary(w io.Writer) error {
if err := binary.Write(w, binary.LittleEndian, &attr.Usage); err != nil { bw := util.BinWriter{W: w}
return err bw.WriteLE(&attr.Usage)
} switch attr.Usage {
if attr.Usage == ContractHash || case ECDH02, ECDH03:
attr.Usage == Vote || bw.WriteLE(attr.Data[1:])
(attr.Usage >= Hash1 && attr.Usage <= Hash15) { case DescriptionURL, Description, Remark, Remark1, Remark2, Remark3, Remark4,
return binary.Write(w, binary.LittleEndian, attr.Data) Remark5, Remark6, Remark7, Remark8, Remark9, Remark10, Remark11,
} Remark12, Remark13, Remark14, Remark15:
if attr.Usage == ECDH02 || attr.Usage == ECDH03 { bw.WriteVarUint(uint64(len(attr.Data)))
attr.Data[0] = byte(attr.Usage) fallthrough
return binary.Write(w, binary.LittleEndian, attr.Data[1:33]) case Script, ContractHash, Vote, Hash1, Hash2, Hash3, Hash4, Hash5, Hash6,
} Hash7, Hash8, Hash9, Hash10, Hash11, Hash12, Hash13, Hash14, Hash15:
if attr.Usage == Script { bw.WriteLE(attr.Data)
return binary.Write(w, binary.LittleEndian, attr.Data) default:
}
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 fmt.Errorf("failed encoding TX attribute usage: 0x%2x", attr.Usage)
} }
return bw.Err
}
// Size returns the size in number bytes of the Attribute // Size returns the size in number bytes of the Attribute
func (attr *Attribute) Size() int { func (attr *Attribute) Size() int {
switch attr.Usage { switch attr.Usage {

View file

@ -13,7 +13,11 @@ type ClaimTX struct {
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (tx *ClaimTX) DecodeBinary(r io.Reader) error { func (tx *ClaimTX) DecodeBinary(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) tx.Claims = make([]*Input, lenClaims)
for i := 0; i < int(lenClaims); i++ { for i := 0; i < int(lenClaims); i++ {
tx.Claims[i] = &Input{} tx.Claims[i] = &Input{}
@ -26,8 +30,10 @@ func (tx *ClaimTX) DecodeBinary(r io.Reader) error {
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (tx *ClaimTX) EncodeBinary(w io.Writer) error { func (tx *ClaimTX) EncodeBinary(w io.Writer) error {
if err := util.WriteVarUint(w, uint64(len(tx.Claims))); err != nil { bw := util.BinWriter{W: w}
return err bw.WriteVarUint(uint64(len(tx.Claims)))
if bw.Err != nil {
return bw.Err
} }
for _, claim := range tx.Claims { for _, claim := range tx.Claims {
if err := claim.EncodeBinary(w); err != nil { if err := claim.EncodeBinary(w); err != nil {

View file

@ -1,7 +1,6 @@
package transaction package transaction
import ( import (
"encoding/binary"
"io" "io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
@ -18,21 +17,18 @@ type Input struct {
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (in *Input) DecodeBinary(r io.Reader) error { func (in *Input) DecodeBinary(r io.Reader) error {
if err := binary.Read(r, binary.LittleEndian, &in.PrevHash); err != nil { br := util.BinReader{R: r}
return err br.ReadLE(&in.PrevHash)
} br.ReadLE(&in.PrevIndex)
return binary.Read(r, binary.LittleEndian, &in.PrevIndex) return br.Err
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (in *Input) EncodeBinary(w io.Writer) error { func (in *Input) EncodeBinary(w io.Writer) error {
if err := binary.Write(w, binary.LittleEndian, in.PrevHash); err != nil { bw := util.BinWriter{W: w}
return err bw.WriteLE(in.PrevHash)
} bw.WriteLE(in.PrevIndex)
if err := binary.Write(w, binary.LittleEndian, in.PrevIndex); err != nil { return bw.Err
return err
}
return nil
} }
// Size returns the size in bytes of the Input // Size returns the size in bytes of the Input

View file

@ -1,7 +1,6 @@
package transaction package transaction
import ( import (
"encoding/binary"
"io" "io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
@ -34,21 +33,16 @@ func NewInvocationTX(script []byte) *Transaction {
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (tx *InvocationTX) DecodeBinary(r io.Reader) error { func (tx *InvocationTX) DecodeBinary(r io.Reader) error {
lenScript := util.ReadVarUint(r) br := util.BinReader{R: r}
tx.Script = make([]byte, lenScript) tx.Script = br.ReadBytes()
if err := binary.Read(r, binary.LittleEndian, tx.Script); err != nil { br.ReadLE(&tx.Gas)
return err return br.Err
}
return binary.Read(r, binary.LittleEndian, &tx.Gas)
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (tx *InvocationTX) EncodeBinary(w io.Writer) error { func (tx *InvocationTX) EncodeBinary(w io.Writer) error {
if err := util.WriteVarUint(w, uint64(len(tx.Script))); err != nil { bw := util.BinWriter{W: w}
return err bw.WriteBytes(tx.Script)
} bw.WriteLE(tx.Gas)
if err := binary.Write(w, binary.LittleEndian, tx.Script); err != nil { return bw.Err
return err
}
return binary.Write(w, binary.LittleEndian, tx.Gas)
} }

View file

@ -1,7 +1,6 @@
package transaction package transaction
import ( import (
"encoding/binary"
"encoding/json" "encoding/json"
"io" "io"
@ -36,24 +35,20 @@ func NewOutput(assetID util.Uint256, amount util.Fixed8, scriptHash util.Uint160
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (out *Output) DecodeBinary(r io.Reader) error { func (out *Output) DecodeBinary(r io.Reader) error {
if err := binary.Read(r, binary.LittleEndian, &out.AssetID); err != nil { br := util.BinReader{R: r}
return err br.ReadLE(&out.AssetID)
} br.ReadLE(&out.Amount)
if err := binary.Read(r, binary.LittleEndian, &out.Amount); err != nil { br.ReadLE(&out.ScriptHash)
return err return br.Err
}
return binary.Read(r, binary.LittleEndian, &out.ScriptHash)
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (out *Output) EncodeBinary(w io.Writer) error { func (out *Output) EncodeBinary(w io.Writer) error {
if err := binary.Write(w, binary.LittleEndian, out.AssetID); err != nil { bw := util.BinWriter{W: w}
return err bw.WriteLE(out.AssetID)
} bw.WriteLE(out.Amount)
if err := binary.Write(w, binary.LittleEndian, out.Amount); err != nil { bw.WriteLE(out.ScriptHash)
return err return bw.Err
}
return binary.Write(w, binary.LittleEndian, out.ScriptHash)
} }
// Size returns the size in bytes of the Output // Size returns the size in bytes of the Output

View file

@ -1,7 +1,6 @@
package transaction package transaction
import ( import (
"encoding/binary"
"io" "io"
"github.com/CityOfZion/neo-go/pkg/smartcontract" "github.com/CityOfZion/neo-go/pkg/smartcontract"
@ -24,55 +23,30 @@ type PublishTX struct {
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (tx *PublishTX) DecodeBinary(r io.Reader) error { func (tx *PublishTX) DecodeBinary(r io.Reader) error {
var err error br := util.BinReader{R: r}
tx.Script = br.ReadBytes()
tx.Script, err = util.ReadVarBytes(r) lenParams := br.ReadVarUint()
if err != nil {
return err
}
lenParams := util.ReadVarUint(r)
tx.ParamList = make([]smartcontract.ParamType, lenParams) tx.ParamList = make([]smartcontract.ParamType, lenParams)
for i := 0; i < int(lenParams); i++ { for i := 0; i < int(lenParams); i++ {
var ptype uint8 var ptype uint8
if err := binary.Read(r, binary.LittleEndian, &ptype); err != nil { br.ReadLE(&ptype)
return err
}
tx.ParamList[i] = smartcontract.ParamType(ptype) tx.ParamList[i] = smartcontract.ParamType(ptype)
} }
var rtype uint8 var rtype uint8
if err := binary.Read(r, binary.LittleEndian, &rtype); err != nil { br.ReadLE(&rtype)
return err
}
tx.ReturnType = smartcontract.ParamType(rtype) tx.ReturnType = smartcontract.ParamType(rtype)
if err := binary.Read(r, binary.LittleEndian, &tx.NeedStorage); err != nil { br.ReadLE(&tx.NeedStorage)
return err
}
tx.Name, err = util.ReadVarString(r) tx.Name = br.ReadString()
if err != nil { tx.CodeVersion = br.ReadString()
return err tx.Author = br.ReadString()
} tx.Email = br.ReadString()
tx.CodeVersion, err = util.ReadVarString(r) tx.Description = br.ReadString()
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
}
return nil return br.Err
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.

View file

@ -1,7 +1,6 @@
package transaction package transaction
import ( import (
"encoding/binary"
"io" "io"
"github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/crypto/keys"
@ -32,22 +31,15 @@ type RegisterTX struct {
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (tx *RegisterTX) DecodeBinary(r io.Reader) error { func (tx *RegisterTX) DecodeBinary(r io.Reader) error {
if err := binary.Read(r, binary.LittleEndian, &tx.AssetType); err != nil { br := util.BinReader{R: r}
return err br.ReadLE(&tx.AssetType)
}
var err error tx.Name = br.ReadString()
tx.Name, err = util.ReadVarString(r)
if err != nil {
return err
}
if err := binary.Read(r, binary.LittleEndian, &tx.Amount); err != nil { br.ReadLE(&tx.Amount)
return err br.ReadLE(&tx.Precision)
} if br.Err != nil {
return br.Err
if err := binary.Read(r, binary.LittleEndian, &tx.Precision); err != nil {
return err
} }
tx.Owner = &keys.PublicKey{} tx.Owner = &keys.PublicKey{}
@ -55,25 +47,18 @@ func (tx *RegisterTX) DecodeBinary(r io.Reader) error {
return err return err
} }
return binary.Read(r, binary.LittleEndian, &tx.Admin) br.ReadLE(&tx.Admin)
return br.Err
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (tx *RegisterTX) EncodeBinary(w io.Writer) error { func (tx *RegisterTX) EncodeBinary(w io.Writer) error {
if err := binary.Write(w, binary.LittleEndian, tx.AssetType); err != nil { bw := util.BinWriter{W: w}
return err bw.WriteLE(tx.AssetType)
} bw.WriteString(tx.Name)
if err := util.WriteVarString(w, tx.Name); err != nil { bw.WriteLE(tx.Amount)
return err bw.WriteLE(tx.Precision)
} bw.WriteLE(tx.Owner.Bytes())
if err := binary.Write(w, binary.LittleEndian, tx.Amount); err != nil { bw.WriteLE(tx.Admin)
return err return bw.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)
} }

View file

@ -13,7 +13,11 @@ type StateTX struct {
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (tx *StateTX) DecodeBinary(r io.Reader) error { func (tx *StateTX) DecodeBinary(r io.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++ { for i := 0; i < int(lenDesc); i++ {
tx.Descriptors[i] = &StateDescriptor{} tx.Descriptors[i] = &StateDescriptor{}
if err := tx.Descriptors[i].DecodeBinary(r); err != nil { if err := tx.Descriptors[i].DecodeBinary(r); err != nil {

View file

@ -1,7 +1,6 @@
package transaction package transaction
import ( import (
"encoding/binary"
"io" "io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
@ -26,30 +25,14 @@ type StateDescriptor struct {
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
func (s *StateDescriptor) DecodeBinary(r io.Reader) error { func (s *StateDescriptor) DecodeBinary(r io.Reader) error {
if err := binary.Read(r, binary.LittleEndian, &s.Type); err != nil { br := util.BinReader{R: r}
return err br.ReadLE(&s.Type)
}
keyLen := util.ReadVarUint(r) s.Key = br.ReadBytes()
s.Key = make([]byte, keyLen) s.Value = br.ReadBytes()
if err := binary.Read(r, binary.LittleEndian, s.Key); err != nil { s.Field = br.ReadString()
return err
}
valLen := util.ReadVarUint(r) return br.Err
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
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.

View file

@ -2,7 +2,6 @@ package transaction
import ( import (
"bytes" "bytes"
"encoding/binary"
"io" "io"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
@ -79,17 +78,17 @@ func (t *Transaction) AddInput(in *Input) {
// DecodeBinary implements the payload interface. // DecodeBinary implements the payload interface.
func (t *Transaction) DecodeBinary(r io.Reader) error { func (t *Transaction) DecodeBinary(r io.Reader) error {
if err := binary.Read(r, binary.LittleEndian, &t.Type); err != nil { br := util.BinReader{R: r}
return err br.ReadLE(&t.Type)
} br.ReadLE(&t.Version)
if err := binary.Read(r, binary.LittleEndian, &t.Version); err != nil { if br.Err != nil {
return err return br.Err
} }
if err := t.decodeData(r); err != nil { if err := t.decodeData(r); err != nil {
return err return err
} }
lenAttrs := util.ReadVarUint(r) lenAttrs := br.ReadVarUint()
t.Attributes = make([]*Attribute, lenAttrs) t.Attributes = make([]*Attribute, lenAttrs)
for i := 0; i < int(lenAttrs); i++ { for i := 0; i < int(lenAttrs); i++ {
t.Attributes[i] = &Attribute{} t.Attributes[i] = &Attribute{}
@ -100,7 +99,7 @@ func (t *Transaction) DecodeBinary(r io.Reader) error {
} }
} }
lenInputs := util.ReadVarUint(r) lenInputs := br.ReadVarUint()
t.Inputs = make([]*Input, lenInputs) t.Inputs = make([]*Input, lenInputs)
for i := 0; i < int(lenInputs); i++ { for i := 0; i < int(lenInputs); i++ {
t.Inputs[i] = &Input{} t.Inputs[i] = &Input{}
@ -109,7 +108,7 @@ func (t *Transaction) DecodeBinary(r io.Reader) error {
} }
} }
lenOutputs := util.ReadVarUint(r) lenOutputs := br.ReadVarUint()
t.Outputs = make([]*Output, lenOutputs) t.Outputs = make([]*Output, lenOutputs)
for i := 0; i < int(lenOutputs); i++ { for i := 0; i < int(lenOutputs); i++ {
t.Outputs[i] = &Output{} t.Outputs[i] = &Output{}
@ -118,7 +117,7 @@ func (t *Transaction) DecodeBinary(r io.Reader) error {
} }
} }
lenScripts := util.ReadVarUint(r) lenScripts := br.ReadVarUint()
t.Scripts = make([]*Witness, lenScripts) t.Scripts = make([]*Witness, lenScripts)
for i := 0; i < int(lenScripts); i++ { for i := 0; i < int(lenScripts); i++ {
t.Scripts[i] = &Witness{} t.Scripts[i] = &Witness{}
@ -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 // Create the hash of the transaction at decode, so we dont need
// to do it anymore. // to do it anymore.
return t.createHash() return t.createHash()
@ -172,8 +174,10 @@ func (t *Transaction) EncodeBinary(w io.Writer) error {
if err := t.encodeHashableFields(w); err != nil { if err := t.encodeHashableFields(w); err != nil {
return err return err
} }
if err := util.WriteVarUint(w, uint64(len(t.Scripts))); err != nil { bw := util.BinWriter{W: w}
return err bw.WriteVarUint(uint64(len(t.Scripts)))
if bw.Err != nil {
return bw.Err
} }
for _, s := range t.Scripts { for _, s := range t.Scripts {
if err := s.EncodeBinary(w); err != nil { 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 // encodeHashableFields will only encode the fields that are not used for
// signing the transaction, which are all fields except the scripts. // signing the transaction, which are all fields except the scripts.
func (t *Transaction) encodeHashableFields(w io.Writer) error { func (t *Transaction) encodeHashableFields(w io.Writer) error {
if err := binary.Write(w, binary.LittleEndian, t.Type); err != nil { bw := util.BinWriter{W: w}
return err
} bw.WriteLE(t.Type)
if err := binary.Write(w, binary.LittleEndian, t.Version); err != nil { bw.WriteLE(t.Version)
return err if bw.Err != nil {
return bw.Err
} }
// Underlying TXer. // Underlying TXer.
@ -201,9 +206,9 @@ func (t *Transaction) encodeHashableFields(w io.Writer) error {
} }
// Attributes // Attributes
lenAttrs := uint64(len(t.Attributes)) bw.WriteVarUint(uint64(len(t.Attributes)))
if err := util.WriteVarUint(w, lenAttrs); err != nil { if bw.Err != nil {
return err return bw.Err
} }
for _, attr := range t.Attributes { for _, attr := range t.Attributes {
if err := attr.EncodeBinary(w); err != nil { if err := attr.EncodeBinary(w); err != nil {
@ -212,8 +217,9 @@ func (t *Transaction) encodeHashableFields(w io.Writer) error {
} }
// Inputs // Inputs
if err := util.WriteVarUint(w, uint64(len(t.Inputs))); err != nil { bw.WriteVarUint(uint64(len(t.Inputs)))
return err if bw.Err != nil {
return bw.Err
} }
for _, in := range t.Inputs { for _, in := range t.Inputs {
if err := in.EncodeBinary(w); err != nil { if err := in.EncodeBinary(w); err != nil {
@ -222,8 +228,9 @@ func (t *Transaction) encodeHashableFields(w io.Writer) error {
} }
// Outputs // Outputs
if err := util.WriteVarUint(w, uint64(len(t.Outputs))); err != nil { bw.WriteVarUint(uint64(len(t.Outputs)))
return err if bw.Err != nil {
return bw.Err
} }
for _, out := range t.Outputs { for _, out := range t.Outputs {
if err := out.EncodeBinary(w); err != nil { if err := out.EncodeBinary(w); err != nil {

View file

@ -1,7 +1,6 @@
package transaction package transaction
import ( import (
"encoding/binary"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"io" "io"
@ -18,28 +17,21 @@ type Witness struct {
// DecodeBinary implements the payload interface. // DecodeBinary implements the payload interface.
func (w *Witness) DecodeBinary(r io.Reader) error { func (w *Witness) DecodeBinary(r io.Reader) error {
lenb := util.ReadVarUint(r) br := util.BinReader{R: r}
w.InvocationScript = make([]byte, lenb)
if err := binary.Read(r, binary.LittleEndian, w.InvocationScript); err != nil { w.InvocationScript = br.ReadBytes()
return err w.VerificationScript = br.ReadBytes()
} return br.Err
lenb = util.ReadVarUint(r)
w.VerificationScript = make([]byte, lenb)
return binary.Read(r, binary.LittleEndian, w.VerificationScript)
} }
// EncodeBinary implements the payload interface. // EncodeBinary implements the payload interface.
func (w *Witness) EncodeBinary(writer io.Writer) error { func (w *Witness) EncodeBinary(writer io.Writer) error {
if err := util.WriteVarUint(writer, uint64(len(w.InvocationScript))); err != nil { bw := util.BinWriter{W: writer}
return err
} bw.WriteBytes(w.InvocationScript)
if err := binary.Write(writer, binary.LittleEndian, w.InvocationScript); err != nil { bw.WriteBytes(w.VerificationScript)
return err
} return bw.Err
if err := util.WriteVarUint(writer, uint64(len(w.VerificationScript))); err != nil {
return err
}
return binary.Write(writer, binary.LittleEndian, w.VerificationScript)
} }
// MarshalJSON implements the json marshaller interface. // MarshalJSON implements the json marshaller interface.

View file

@ -2,7 +2,6 @@ package core
import ( import (
"bytes" "bytes"
"encoding/binary"
"fmt" "fmt"
"io" "io"
@ -68,29 +67,25 @@ func (u UnspentCoins) commit(b storage.Batch) error {
// EncodeBinary encodes UnspentCoinState to the given io.Writer. // EncodeBinary encodes UnspentCoinState to the given io.Writer.
func (s *UnspentCoinState) EncodeBinary(w io.Writer) error { func (s *UnspentCoinState) EncodeBinary(w io.Writer) error {
if err := util.WriteVarUint(w, uint64(len(s.states))); err != nil { bw := util.BinWriter{W: w}
return err bw.WriteVarUint(uint64(len(s.states)))
}
for _, state := range s.states { for _, state := range s.states {
if err := binary.Write(w, binary.LittleEndian, byte(state)); err != nil { bw.WriteLE(byte(state))
return err
} }
} return bw.Err
return nil
} }
// DecodeBinary decodes UnspentCoinState from the given io.Reader. // DecodeBinary decodes UnspentCoinState from the given io.Reader.
func (s *UnspentCoinState) DecodeBinary(r io.Reader) error { 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) s.states = make([]CoinState, lenStates)
for i := 0; i < int(lenStates); i++ { for i := 0; i < int(lenStates); i++ {
var state uint8 var state uint8
if err := binary.Read(r, binary.LittleEndian, &state); err != nil { br.ReadLE(&state)
return err
}
s.states[i] = CoinState(state) s.states[i] = CoinState(state)
} }
return nil return br.Err
} }
// IsDoubleSpend verifies that the input transactions are not double spent. // IsDoubleSpend verifies that the input transactions are not double spent.