Merge pull request #545 from nspcc-dev/feat/optimizeio

Remove some reflection from the io package
This commit is contained in:
Roman Khimov 2019-12-09 15:12:13 +03:00 committed by GitHub
commit 052ba1e94f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 129 additions and 117 deletions

8
go.mod
View file

@ -6,21 +6,15 @@ require (
github.com/etcd-io/bbolt v1.3.3 github.com/etcd-io/bbolt v1.3.3
github.com/go-redis/redis v6.10.2+incompatible github.com/go-redis/redis v6.10.2+incompatible
github.com/go-yaml/yaml v2.1.0+incompatible github.com/go-yaml/yaml v2.1.0+incompatible
github.com/golang/snappy v0.0.1 // indirect
github.com/mattn/go-colorable v0.1.4 // indirect
github.com/mattn/go-isatty v0.0.10 // indirect
github.com/mr-tron/base58 v1.1.2 github.com/mr-tron/base58 v1.1.2
github.com/nspcc-dev/dbft v0.0.0-20191205084618-dacb1a30c254 github.com/nspcc-dev/dbft v0.0.0-20191209120240-0d6b7568d9ae
github.com/nspcc-dev/rfc6979 v0.1.0 github.com/nspcc-dev/rfc6979 v0.1.0
github.com/onsi/ginkgo v1.10.3 // indirect
github.com/onsi/gomega v1.7.1 // indirect
github.com/pkg/errors v0.8.1 github.com/pkg/errors v0.8.1
github.com/prometheus/client_golang v1.2.1 github.com/prometheus/client_golang v1.2.1
github.com/sirupsen/logrus v1.4.2 github.com/sirupsen/logrus v1.4.2
github.com/stretchr/testify v1.4.0 github.com/stretchr/testify v1.4.0
github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73 github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73
github.com/urfave/cli v1.20.0 github.com/urfave/cli v1.20.0
github.com/yuin/gopher-lua v0.0.0-20191128022950-c6266f4fe8d7 // indirect
go.uber.org/atomic v1.4.0 go.uber.org/atomic v1.4.0
go.uber.org/zap v1.10.0 go.uber.org/zap v1.10.0
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4

3
go.sum
View file

@ -1,4 +1,5 @@
github.com/CityOfZion/neo-go v0.62.1-pre.0.20191114145240-e740fbe708f8/go.mod h1:MJCkWUBhi9pn/CrYO1Q3P687y2KeahrOPS9BD9LDGb0= github.com/CityOfZion/neo-go v0.62.1-pre.0.20191114145240-e740fbe708f8/go.mod h1:MJCkWUBhi9pn/CrYO1Q3P687y2KeahrOPS9BD9LDGb0=
github.com/CityOfZion/neo-go v0.70.1-pre.0.20191209120015-fccb0085941e/go.mod h1:0enZl0az8xA6PVkwzEOwPWVJGqlt/GO4hA4kmQ5Xzig=
github.com/Workiva/go-datastructures v1.0.50 h1:slDmfW6KCHcC7U+LP3DDBbm4fqTwZGn1beOFPfGaLvo= github.com/Workiva/go-datastructures v1.0.50 h1:slDmfW6KCHcC7U+LP3DDBbm4fqTwZGn1beOFPfGaLvo=
github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA=
github.com/abiosoft/ishell v2.0.0+incompatible h1:zpwIuEHc37EzrsIYah3cpevrIc8Oma7oZPxr03tlmmw= github.com/abiosoft/ishell v2.0.0+incompatible h1:zpwIuEHc37EzrsIYah3cpevrIc8Oma7oZPxr03tlmmw=
@ -90,6 +91,8 @@ github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjW
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nspcc-dev/dbft v0.0.0-20191205084618-dacb1a30c254 h1:A4OkQDQOSPsJF8qUmqNvFDzmIGALrvOCZrMktllDoKc= github.com/nspcc-dev/dbft v0.0.0-20191205084618-dacb1a30c254 h1:A4OkQDQOSPsJF8qUmqNvFDzmIGALrvOCZrMktllDoKc=
github.com/nspcc-dev/dbft v0.0.0-20191205084618-dacb1a30c254/go.mod h1:w1Ln2aT+dBlPhLnuZhBV+DfPEdS2CHWWLp5JTScY3bw= github.com/nspcc-dev/dbft v0.0.0-20191205084618-dacb1a30c254/go.mod h1:w1Ln2aT+dBlPhLnuZhBV+DfPEdS2CHWWLp5JTScY3bw=
github.com/nspcc-dev/dbft v0.0.0-20191209120240-0d6b7568d9ae h1:T5V1QANlNMKun0EPB3eqg2PTXG4rmLhzDyEiV63kdB0=
github.com/nspcc-dev/dbft v0.0.0-20191209120240-0d6b7568d9ae/go.mod h1:3FjXOoHmA51EGfb5GS/HOv7VdmngNRTssSeQ729dvGY=
github.com/nspcc-dev/neofs-crypto v0.2.0 h1:ftN+59WqxSWz/RCgXYOfhmltOOqU+udsNQSvN6wkFck= github.com/nspcc-dev/neofs-crypto v0.2.0 h1:ftN+59WqxSWz/RCgXYOfhmltOOqU+udsNQSvN6wkFck=
github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA= github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA=
github.com/nspcc-dev/rfc6979 v0.1.0 h1:Lwg7esRRoyK1Up/IN1vAef1EmvrBeMHeeEkek2fAJ6c= github.com/nspcc-dev/rfc6979 v0.1.0 h1:Lwg7esRRoyK1Up/IN1vAef1EmvrBeMHeeEkek2fAJ6c=

View file

@ -23,7 +23,7 @@ func (c *commit) EncodeBinary(w *io.BinWriter) {
// DecodeBinary implements io.Serializable interface. // DecodeBinary implements io.Serializable interface.
func (c *commit) DecodeBinary(r *io.BinReader) { func (c *commit) DecodeBinary(r *io.BinReader) {
r.ReadBE(&c.signature) r.ReadBytes(c.signature[:])
} }
// Signature implements payload.Commit interface. // Signature implements payload.Commit interface.

View file

@ -212,12 +212,12 @@ func (p *Payload) Verify() bool {
// DecodeBinaryUnsigned reads payload from w excluding signature. // DecodeBinaryUnsigned reads payload from w excluding signature.
func (p *Payload) DecodeBinaryUnsigned(r *io.BinReader) { func (p *Payload) DecodeBinaryUnsigned(r *io.BinReader) {
r.ReadLE(&p.version) r.ReadLE(&p.version)
r.ReadBE(p.prevHash[:]) r.ReadBytes(p.prevHash[:])
r.ReadLE(&p.height) r.ReadLE(&p.height)
r.ReadLE(&p.validatorIndex) r.ReadLE(&p.validatorIndex)
r.ReadLE(&p.timestamp) r.ReadLE(&p.timestamp)
data := r.ReadBytes() data := r.ReadVarBytes()
if r.Err != nil { if r.Err != nil {
return return
} }

View file

@ -31,7 +31,7 @@ func (p *prepareRequest) EncodeBinary(w *io.BinWriter) {
func (p *prepareRequest) DecodeBinary(r *io.BinReader) { func (p *prepareRequest) DecodeBinary(r *io.BinReader) {
r.ReadLE(&p.timestamp) r.ReadLE(&p.timestamp)
r.ReadLE(&p.nonce) r.ReadLE(&p.nonce)
r.ReadBE(p.nextConsensus[:]) r.ReadBytes(p.nextConsensus[:])
r.ReadArray(&p.transactionHashes) r.ReadArray(&p.transactionHashes)
p.minerTx.DecodeBinary(r) p.minerTx.DecodeBinary(r)
} }

View file

@ -20,7 +20,7 @@ func (p *prepareResponse) EncodeBinary(w *io.BinWriter) {
// DecodeBinary implements io.Serializable interface. // DecodeBinary implements io.Serializable interface.
func (p *prepareResponse) DecodeBinary(r *io.BinReader) { func (p *prepareResponse) DecodeBinary(r *io.BinReader) {
r.ReadBE(p.preparationHash[:]) r.ReadBytes(p.preparationHash[:])
} }
// PreparationHash implements payload.PrepareResponse interface. // PreparationHash implements payload.PrepareResponse interface.

View file

@ -54,7 +54,7 @@ func (m *recoveryMessage) DecodeBinary(r *io.BinReader) {
if l != 0 { if l != 0 {
if l == util.Uint256Size { if l == util.Uint256Size {
m.preparationHash = new(util.Uint256) m.preparationHash = new(util.Uint256)
r.ReadBE(m.preparationHash[:]) r.ReadBytes(m.preparationHash[:])
} else { } else {
r.Err = errors.New("invalid data") r.Err = errors.New("invalid data")
} }
@ -93,7 +93,7 @@ func (p *changeViewCompact) DecodeBinary(r *io.BinReader) {
r.ReadLE(&p.ValidatorIndex) r.ReadLE(&p.ValidatorIndex)
r.ReadLE(&p.OriginalViewNumber) r.ReadLE(&p.OriginalViewNumber)
r.ReadLE(&p.Timestamp) r.ReadLE(&p.Timestamp)
p.InvocationScript = r.ReadBytes() p.InvocationScript = r.ReadVarBytes()
} }
// EncodeBinary implements io.Serializable interface. // EncodeBinary implements io.Serializable interface.
@ -108,8 +108,8 @@ func (p *changeViewCompact) EncodeBinary(w *io.BinWriter) {
func (p *commitCompact) DecodeBinary(r *io.BinReader) { func (p *commitCompact) DecodeBinary(r *io.BinReader) {
r.ReadLE(&p.ViewNumber) r.ReadLE(&p.ViewNumber)
r.ReadLE(&p.ValidatorIndex) r.ReadLE(&p.ValidatorIndex)
r.ReadBE(p.Signature[:]) r.ReadBytes(p.Signature[:])
p.InvocationScript = r.ReadBytes() p.InvocationScript = r.ReadVarBytes()
} }
// EncodeBinary implements io.Serializable interface. // EncodeBinary implements io.Serializable interface.
@ -123,7 +123,7 @@ func (p *commitCompact) EncodeBinary(w *io.BinWriter) {
// DecodeBinary implements io.Serializable interface. // DecodeBinary implements io.Serializable interface.
func (p *preparationCompact) DecodeBinary(r *io.BinReader) { func (p *preparationCompact) DecodeBinary(r *io.BinReader) {
r.ReadLE(&p.ValidatorIndex) r.ReadLE(&p.ValidatorIndex)
p.InvocationScript = r.ReadBytes() p.InvocationScript = r.ReadVarBytes()
} }
// EncodeBinary implements io.Serializable interface. // EncodeBinary implements io.Serializable interface.

View file

@ -103,7 +103,7 @@ func NewAccountState(scriptHash util.Uint160) *AccountState {
// DecodeBinary decodes AccountState from the given BinReader. // DecodeBinary decodes AccountState from the given BinReader.
func (s *AccountState) DecodeBinary(br *io.BinReader) { func (s *AccountState) DecodeBinary(br *io.BinReader) {
br.ReadLE(&s.Version) br.ReadLE(&s.Version)
br.ReadLE(&s.ScriptHash) br.ReadBytes(s.ScriptHash[:])
br.ReadLE(&s.IsFrozen) br.ReadLE(&s.IsFrozen)
br.ReadArray(&s.Votes) br.ReadArray(&s.Votes)
@ -111,7 +111,7 @@ func (s *AccountState) DecodeBinary(br *io.BinReader) {
lenBalances := br.ReadVarUint() lenBalances := br.ReadVarUint()
for i := 0; i < int(lenBalances); i++ { for i := 0; i < int(lenBalances); i++ {
key := util.Uint256{} key := util.Uint256{}
br.ReadLE(&key) br.ReadBytes(key[:])
ubs := make([]UnspentBalance, 0) ubs := make([]UnspentBalance, 0)
br.ReadArray(&ubs) br.ReadArray(&ubs)
s.Balances[key] = ubs s.Balances[key] = ubs

View file

@ -52,7 +52,7 @@ type AssetState struct {
// DecodeBinary implements Serializable interface. // DecodeBinary implements Serializable interface.
func (a *AssetState) DecodeBinary(br *io.BinReader) { func (a *AssetState) DecodeBinary(br *io.BinReader) {
br.ReadLE(&a.ID) br.ReadBytes(a.ID[:])
br.ReadLE(&a.AssetType) br.ReadLE(&a.AssetType)
a.Name = br.ReadString() a.Name = br.ReadString()
@ -61,12 +61,12 @@ func (a *AssetState) DecodeBinary(br *io.BinReader) {
br.ReadLE(&a.Available) br.ReadLE(&a.Available)
br.ReadLE(&a.Precision) br.ReadLE(&a.Precision)
br.ReadLE(&a.FeeMode) br.ReadLE(&a.FeeMode)
br.ReadLE(&a.FeeAddress) br.ReadBytes(a.FeeAddress[:])
a.Owner = &keys.PublicKey{} a.Owner = &keys.PublicKey{}
a.Owner.DecodeBinary(br) a.Owner.DecodeBinary(br)
br.ReadLE(&a.Admin) br.ReadBytes(a.Admin[:])
br.ReadLE(&a.Issuer) br.ReadBytes(a.Issuer[:])
br.ReadLE(&a.Expiration) br.ReadLE(&a.Expiration)
br.ReadLE(&a.IsFrozen) br.ReadLE(&a.IsFrozen)
} }

View file

@ -73,9 +73,9 @@ func (b *BlockBase) VerificationHash() util.Uint256 {
func (b *BlockBase) DecodeBinary(br *io.BinReader) { func (b *BlockBase) DecodeBinary(br *io.BinReader) {
b.decodeHashableFields(br) b.decodeHashableFields(br)
var padding uint8 padding := []byte{0}
br.ReadLE(&padding) br.ReadBytes(padding)
if padding != 1 { if padding[0] != 1 {
br.Err = fmt.Errorf("format error: padding must equal 1 got %d", padding) br.Err = fmt.Errorf("format error: padding must equal 1 got %d", padding)
return return
} }
@ -128,12 +128,12 @@ func (b *BlockBase) encodeHashableFields(bw *io.BinWriter) {
// see Hash() for more information about the fields. // see Hash() for more information about the fields.
func (b *BlockBase) decodeHashableFields(br *io.BinReader) { func (b *BlockBase) decodeHashableFields(br *io.BinReader) {
br.ReadLE(&b.Version) br.ReadLE(&b.Version)
br.ReadLE(&b.PrevHash) br.ReadBytes(b.PrevHash[:])
br.ReadLE(&b.MerkleRoot) br.ReadBytes(b.MerkleRoot[:])
br.ReadLE(&b.Timestamp) br.ReadLE(&b.Timestamp)
br.ReadLE(&b.Index) br.ReadLE(&b.Index)
br.ReadLE(&b.ConsensusData) br.ReadLE(&b.ConsensusData)
br.ReadLE(&b.NextConsensus) br.ReadBytes(b.NextConsensus[:])
// 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
// again. // again.

View file

@ -38,7 +38,7 @@ func (a Contracts) commit(store storage.Store) error {
// DecodeBinary implements Serializable interface. // DecodeBinary implements Serializable interface.
func (cs *ContractState) DecodeBinary(br *io.BinReader) { func (cs *ContractState) DecodeBinary(br *io.BinReader) {
cs.Script = br.ReadBytes() cs.Script = br.ReadVarBytes()
br.ReadArray(&cs.ParamList) br.ReadArray(&cs.ParamList)
br.ReadLE(&cs.ReturnType) br.ReadLE(&cs.ReturnType)
br.ReadLE(&cs.Properties) br.ReadLE(&cs.Properties)

View file

@ -18,10 +18,10 @@ type Header struct {
func (h *Header) DecodeBinary(r *io.BinReader) { func (h *Header) DecodeBinary(r *io.BinReader) {
h.BlockBase.DecodeBinary(r) h.BlockBase.DecodeBinary(r)
var padding uint8 padding := []byte{0}
r.ReadLE(&padding) r.ReadBytes(padding)
if padding != 0 { if padding[0] != 0 {
r.Err = fmt.Errorf("format error: padding must equal 0 got %d", padding) r.Err = fmt.Errorf("format error: padding must equal 0 got %d", padding)
} }
} }

View file

@ -63,7 +63,7 @@ func (ne NotificationEvent) EncodeBinary(w *io.BinWriter) {
// DecodeBinary implements the Serializable interface. // DecodeBinary implements the Serializable interface.
func (ne *NotificationEvent) DecodeBinary(r *io.BinReader) { func (ne *NotificationEvent) DecodeBinary(r *io.BinReader) {
r.ReadLE(&ne.ScriptHash) r.ReadBytes(ne.ScriptHash[:])
ne.Item = vm.DecodeBinaryStackItem(r) ne.Item = vm.DecodeBinaryStackItem(r)
} }
@ -75,6 +75,6 @@ func (aer *AppExecResult) EncodeBinary(w *io.BinWriter) {
// DecodeBinary implements the Serializable interface. // DecodeBinary implements the Serializable interface.
func (aer *AppExecResult) DecodeBinary(r *io.BinReader) { func (aer *AppExecResult) DecodeBinary(r *io.BinReader) {
r.ReadLE(&aer.TxHash) r.ReadBytes(aer.TxHash[:])
r.ReadArray(&aer.Events) r.ReadArray(&aer.Events)
} }

View file

@ -75,7 +75,7 @@ func NewSpentCoinState(hash util.Uint256, height uint32) *SpentCoinState {
// DecodeBinary implements Serializable interface. // DecodeBinary implements Serializable interface.
func (s *SpentCoinState) DecodeBinary(br *io.BinReader) { func (s *SpentCoinState) DecodeBinary(br *io.BinReader) {
br.ReadLE(&s.txHash) br.ReadBytes(s.txHash[:])
br.ReadLE(&s.txHeight) br.ReadLE(&s.txHeight)
s.items = make(map[uint16]uint32) s.items = make(map[uint16]uint32)

View file

@ -59,6 +59,6 @@ func (si *StorageItem) EncodeBinary(w *io.BinWriter) {
// DecodeBinary implements Serializable interface. // DecodeBinary implements Serializable interface.
func (si *StorageItem) DecodeBinary(r *io.BinReader) { func (si *StorageItem) DecodeBinary(r *io.BinReader) {
si.Value = r.ReadBytes() si.Value = r.ReadVarBytes()
r.ReadLE(&si.IsConst) r.ReadLE(&si.IsConst)
} }

View file

@ -22,7 +22,7 @@ func (attr *Attribute) DecodeBinary(br *io.BinReader) {
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)
br.ReadLE(attr.Data[1:]) br.ReadBytes(attr.Data[1:])
return return
} }
var datasize uint64 var datasize uint64
@ -47,7 +47,7 @@ func (attr *Attribute) DecodeBinary(br *io.BinReader) {
return return
} }
attr.Data = make([]byte, datasize) attr.Data = make([]byte, datasize)
br.ReadLE(attr.Data) br.ReadBytes(attr.Data)
} }
// EncodeBinary implements Serializable interface. // EncodeBinary implements Serializable interface.

View file

@ -16,7 +16,7 @@ type Input struct {
// DecodeBinary implements Serializable interface. // DecodeBinary implements Serializable interface.
func (in *Input) DecodeBinary(br *io.BinReader) { func (in *Input) DecodeBinary(br *io.BinReader) {
br.ReadLE(&in.PrevHash) br.ReadBytes(in.PrevHash[:])
br.ReadLE(&in.PrevIndex) br.ReadLE(&in.PrevIndex)
} }

View file

@ -35,7 +35,7 @@ func NewInvocationTX(script []byte, gas util.Fixed8) *Transaction {
// DecodeBinary implements Serializable interface. // DecodeBinary implements Serializable interface.
func (tx *InvocationTX) DecodeBinary(br *io.BinReader) { func (tx *InvocationTX) DecodeBinary(br *io.BinReader) {
tx.Script = br.ReadBytes() tx.Script = br.ReadVarBytes()
if tx.Version >= 1 { if tx.Version >= 1 {
br.ReadLE(&tx.Gas) br.ReadLE(&tx.Gas)
} else { } else {

View file

@ -35,9 +35,9 @@ func NewOutput(assetID util.Uint256, amount util.Fixed8, scriptHash util.Uint160
// DecodeBinary implements Serializable interface. // DecodeBinary implements Serializable interface.
func (out *Output) DecodeBinary(br *io.BinReader) { func (out *Output) DecodeBinary(br *io.BinReader) {
br.ReadLE(&out.AssetID) br.ReadBytes(out.AssetID[:])
br.ReadLE(&out.Amount) br.ReadLE(&out.Amount)
br.ReadLE(&out.ScriptHash) br.ReadBytes(out.ScriptHash[:])
} }
// EncodeBinary implements Serializable interface. // EncodeBinary implements Serializable interface.

View file

@ -22,7 +22,7 @@ type PublishTX struct {
// DecodeBinary implements Serializable interface. // DecodeBinary implements Serializable interface.
func (tx *PublishTX) DecodeBinary(br *io.BinReader) { func (tx *PublishTX) DecodeBinary(br *io.BinReader) {
tx.Script = br.ReadBytes() tx.Script = br.ReadVarBytes()
lenParams := br.ReadVarUint() lenParams := br.ReadVarUint()
tx.ParamList = make([]smartcontract.ParamType, lenParams) tx.ParamList = make([]smartcontract.ParamType, lenParams)

View file

@ -40,7 +40,7 @@ func (tx *RegisterTX) DecodeBinary(br *io.BinReader) {
tx.Owner = &keys.PublicKey{} tx.Owner = &keys.PublicKey{}
tx.Owner.DecodeBinary(br) tx.Owner.DecodeBinary(br)
br.ReadLE(&tx.Admin) br.ReadBytes(tx.Admin[:])
} }
// EncodeBinary implements Serializable interface. // EncodeBinary implements Serializable interface.

View file

@ -25,8 +25,8 @@ type StateDescriptor struct {
func (s *StateDescriptor) DecodeBinary(r *io.BinReader) { func (s *StateDescriptor) DecodeBinary(r *io.BinReader) {
r.ReadLE(&s.Type) r.ReadLE(&s.Type)
s.Key = r.ReadBytes() s.Key = r.ReadVarBytes()
s.Value = r.ReadBytes() s.Value = r.ReadVarBytes()
s.Field = r.ReadString() s.Field = r.ReadString()
} }

View file

@ -17,8 +17,8 @@ type Witness struct {
// DecodeBinary implements Serializable interface. // DecodeBinary implements Serializable interface.
func (w *Witness) DecodeBinary(br *io.BinReader) { func (w *Witness) DecodeBinary(br *io.BinReader) {
w.InvocationScript = br.ReadBytes() w.InvocationScript = br.ReadVarBytes()
w.VerificationScript = br.ReadBytes() w.VerificationScript = br.ReadVarBytes()
} }
// EncodeBinary implements Serializable interface. // EncodeBinary implements Serializable interface.

View file

@ -181,7 +181,7 @@ func (p *PublicKey) DecodeBinary(r *io.BinReader) {
case 0x02, 0x03: case 0x02, 0x03:
// Compressed public keys // Compressed public keys
xbytes := make([]byte, 32) xbytes := make([]byte, 32)
r.ReadLE(xbytes) r.ReadBytes(xbytes)
if r.Err != nil { if r.Err != nil {
return return
} }
@ -194,8 +194,8 @@ func (p *PublicKey) DecodeBinary(r *io.BinReader) {
case 0x04: case 0x04:
xbytes := make([]byte, 32) xbytes := make([]byte, 32)
ybytes := make([]byte, 32) ybytes := make([]byte, 32)
r.ReadLE(xbytes) r.ReadBytes(xbytes)
r.ReadLE(ybytes) r.ReadBytes(ybytes)
if r.Err != nil { if r.Err != nil {
return return
} }

View file

@ -47,19 +47,14 @@ func (r *BinReader) ReadArray(t interface{}, maxSize ...int) {
panic(value.Type().String() + " is not a pointer to a slice") panic(value.Type().String() + " is not a pointer to a slice")
} }
sliceType := value.Elem().Type()
elemType := sliceType.Elem()
isPtr := elemType.Kind() == reflect.Ptr
if isPtr {
checkHasDecodeBinary(elemType)
} else {
checkHasDecodeBinary(reflect.PtrTo(elemType))
}
if r.Err != nil { if r.Err != nil {
return return
} }
sliceType := value.Elem().Type()
elemType := sliceType.Elem()
isPtr := elemType.Kind() == reflect.Ptr
ms := maxArraySize ms := maxArraySize
if len(maxSize) != 0 { if len(maxSize) != 0 {
ms = maxSize[0] ms = maxSize[0]
@ -82,27 +77,18 @@ func (r *BinReader) ReadArray(t interface{}, maxSize ...int) {
} else { } else {
elem = arr.Index(i).Addr() elem = arr.Index(i).Addr()
} }
method := elem.MethodByName("DecodeBinary")
method.Call([]reflect.Value{reflect.ValueOf(r)}) el, ok := elem.Interface().(decodable)
if !ok {
panic(elemType.String() + "is not decodable")
}
el.DecodeBinary(r)
} }
value.Elem().Set(arr) value.Elem().Set(arr)
} }
func checkHasDecodeBinary(v reflect.Type) {
method, ok := v.MethodByName("DecodeBinary")
if !ok || !isDecodeBinaryMethod(method) {
panic(v.String() + " does not have DecodeBinary(*io.BinReader)")
}
}
func isDecodeBinaryMethod(method reflect.Method) bool {
t := method.Type
return t != nil &&
t.NumIn() == 2 && t.In(1) == reflect.TypeOf((*BinReader)(nil)) &&
t.NumOut() == 0
}
// ReadBE reads from the underlying io.Reader // ReadBE reads from the underlying io.Reader
// into the interface v in big-endian format. // into the interface v in big-endian format.
func (r *BinReader) ReadBE(v interface{}) { func (r *BinReader) ReadBE(v interface{}) {
@ -141,17 +127,26 @@ func (r *BinReader) ReadVarUint() uint64 {
return uint64(b) return uint64(b)
} }
// ReadBytes reads the next set of bytes from the underlying reader. // ReadVarBytes reads the next set of bytes from the underlying reader.
// ReadVarUInt() is used to determine how large that slice is // ReadVarUInt() is used to determine how large that slice is
func (r *BinReader) ReadBytes() []byte { func (r *BinReader) ReadVarBytes() []byte {
n := r.ReadVarUint() n := r.ReadVarUint()
b := make([]byte, n) b := make([]byte, n)
r.ReadLE(b) r.ReadBytes(b)
return b return b
} }
// ReadString calls ReadBytes and casts the results as a string. // ReadBytes copies fixed-size buffer from the reader to provided slice.
func (r *BinReader) ReadBytes(buf []byte) {
if r.Err != nil {
return
}
_, r.Err = io.ReadFull(r.r, buf)
}
// ReadString calls ReadVarBytes and casts the results as a string.
func (r *BinReader) ReadString() string { func (r *BinReader) ReadString() string {
b := r.ReadBytes() b := r.ReadVarBytes()
return string(b) return string(b)
} }

View file

@ -39,33 +39,26 @@ func (w *BinWriter) WriteBE(v interface{}) {
func (w *BinWriter) WriteArray(arr interface{}) { func (w *BinWriter) WriteArray(arr interface{}) {
switch val := reflect.ValueOf(arr); val.Kind() { switch val := reflect.ValueOf(arr); val.Kind() {
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
typ := val.Type().Elem()
method, ok := typ.MethodByName("EncodeBinary")
if !ok || !isEncodeBinaryMethod(method) {
panic(typ.String() + " does not have EncodeBinary(*BinWriter)")
}
if w.Err != nil { if w.Err != nil {
return return
} }
typ := val.Type().Elem()
w.WriteVarUint(uint64(val.Len())) w.WriteVarUint(uint64(val.Len()))
for i := 0; i < val.Len(); i++ { for i := 0; i < val.Len(); i++ {
method := val.Index(i).MethodByName("EncodeBinary") el, ok := val.Index(i).Interface().(encodable)
method.Call([]reflect.Value{reflect.ValueOf(w)}) if !ok {
panic(typ.String() + "is not encodable")
}
el.EncodeBinary(w)
} }
default: default:
panic("not an array") panic("not an array")
} }
} }
func isEncodeBinaryMethod(method reflect.Method) bool {
t := method.Type
return t != nil &&
t.NumIn() == 2 && t.In(1) == reflect.TypeOf((*BinWriter)(nil)) &&
t.NumOut() == 0
}
// WriteVarUint writes a uint64 into the underlying writer using variable-length encoding. // WriteVarUint writes a uint64 into the underlying writer using variable-length encoding.
func (w *BinWriter) WriteVarUint(val uint64) { func (w *BinWriter) WriteVarUint(val uint64) {
if w.Err != nil { if w.Err != nil {

View file

@ -91,7 +91,7 @@ func TestReaderErrHandling(t *testing.T) {
assert.Equal(t, i, iorig) assert.Equal(t, i, iorig)
val := br.ReadVarUint() val := br.ReadVarUint()
assert.Equal(t, val, uint64(0)) assert.Equal(t, val, uint64(0))
b := br.ReadBytes() b := br.ReadVarBytes()
assert.Equal(t, b, []byte{}) assert.Equal(t, b, []byte{})
s := br.ReadString() s := br.ReadString()
assert.Equal(t, s, "") assert.Equal(t, s, "")
@ -267,8 +267,7 @@ func TestBinWriter_WriteArray(t *testing.T) {
require.Equal(t, w.Bytes(), []byte(nil)) require.Equal(t, w.Bytes(), []byte(nil))
w.Reset() w.Reset()
w.Err = errors.New("error") require.Panics(t, func() { w.WriteArray([]int{1}) })
require.Panics(t, func() { w.WriteArray([]int{}) })
w.Reset() w.Reset()
w.Err = errors.New("error") w.Err = errors.New("error")
@ -326,15 +325,35 @@ func TestBinReader_ReadArray(t *testing.T) {
require.NoError(t, r.Err) require.NoError(t, r.Err)
require.Equal(t, []testSerializable{}, arrVal) require.Equal(t, []testSerializable{}, arrVal)
r = NewBinReaderFromBuf([]byte{0}) r = NewBinReaderFromBuf([]byte{1})
r.Err = errors.New("error") require.Panics(t, func() { r.ReadArray(&[]int{1}) })
require.Panics(t, func() { r.ReadArray(&[]*int{}) })
r = NewBinReaderFromBuf([]byte{0}) r = NewBinReaderFromBuf([]byte{0})
r.Err = errors.New("error") r.Err = errors.New("error")
require.Panics(t, func() { r.ReadArray(&[]int{}) }) require.Panics(t, func() { r.ReadArray(1) })
}
r = NewBinReaderFromBuf([]byte{0})
r.Err = errors.New("error") func TestBinReader_ReadBytes(t *testing.T) {
require.Panics(t, func() { r.ReadArray(0) }) data := []byte{0, 1, 2, 3, 4, 5, 6, 7}
r := NewBinReaderFromBuf(data)
buf := make([]byte, 4)
r.ReadBytes(buf)
require.NoError(t, r.Err)
require.Equal(t, data[:4], buf)
r.ReadBytes([]byte{})
require.NoError(t, r.Err)
buf = make([]byte, 3)
r.ReadBytes(buf)
require.NoError(t, r.Err)
require.Equal(t, data[4:7], buf)
buf = make([]byte, 2)
r.ReadBytes(buf)
require.Error(t, r.Err)
r.ReadBytes([]byte{})
require.Error(t, r.Err)
} }

View file

@ -10,3 +10,11 @@ type Serializable interface {
DecodeBinary(*BinReader) DecodeBinary(*BinReader)
EncodeBinary(*BinWriter) EncodeBinary(*BinWriter)
} }
type decodable interface {
DecodeBinary(*BinReader)
}
type encodable interface {
EncodeBinary(*BinWriter)
}

View file

@ -150,7 +150,7 @@ func (m *Message) CommandType() CommandType {
// Decode decodes a Message from the given reader. // Decode decodes a Message from the given reader.
func (m *Message) Decode(br *io.BinReader) error { func (m *Message) Decode(br *io.BinReader) error {
br.ReadLE(&m.Magic) br.ReadLE(&m.Magic)
br.ReadLE(&m.Command) br.ReadBytes(m.Command[:])
br.ReadLE(&m.Length) br.ReadLE(&m.Length)
br.ReadLE(&m.Checksum) br.ReadLE(&m.Checksum)
if br.Err != nil { if br.Err != nil {

View file

@ -31,7 +31,7 @@ func NewAddressAndTime(e *net.TCPAddr, t time.Time) *AddressAndTime {
func (p *AddressAndTime) DecodeBinary(br *io.BinReader) { func (p *AddressAndTime) DecodeBinary(br *io.BinReader) {
br.ReadLE(&p.Timestamp) br.ReadLE(&p.Timestamp)
br.ReadLE(&p.Services) br.ReadLE(&p.Services)
br.ReadBE(&p.IP) br.ReadBytes(p.IP[:])
br.ReadBE(&p.Port) br.ReadBE(&p.Port)
} }

View file

@ -24,7 +24,7 @@ func NewGetBlocks(start []util.Uint256, stop util.Uint256) *GetBlocks {
// DecodeBinary implements Serializable interface. // DecodeBinary implements Serializable interface.
func (p *GetBlocks) DecodeBinary(br *io.BinReader) { func (p *GetBlocks) DecodeBinary(br *io.BinReader) {
br.ReadArray(&p.HashStart) br.ReadArray(&p.HashStart)
br.ReadLE(&p.HashStop) br.ReadBytes(p.HashStop[:])
} }
// EncodeBinary implements Serializable interface. // EncodeBinary implements Serializable interface.

View file

@ -21,7 +21,7 @@ func (m *MerkleBlock) DecodeBinary(br *io.BinReader) {
m.TxCount = int(br.ReadVarUint()) m.TxCount = int(br.ReadVarUint())
br.ReadArray(&m.Hashes) br.ReadArray(&m.Hashes)
m.Flags = br.ReadBytes() m.Flags = br.ReadVarBytes()
} }
// EncodeBinary implements Serializable interface. // EncodeBinary implements Serializable interface.

View file

@ -60,7 +60,7 @@ func (p *Version) DecodeBinary(br *io.BinReader) {
br.ReadLE(&p.Timestamp) br.ReadLE(&p.Timestamp)
br.ReadLE(&p.Port) br.ReadLE(&p.Port)
br.ReadLE(&p.Nonce) br.ReadLE(&p.Nonce)
p.UserAgent = br.ReadBytes() p.UserAgent = br.ReadVarBytes()
br.ReadLE(&p.StartHeight) br.ReadLE(&p.StartHeight)
br.ReadLE(&p.Relay) br.ReadLE(&p.Relay)
} }

View file

@ -27,7 +27,7 @@ func TestCreateMultiSigRedeemScript(t *testing.T) {
assert.Equal(t, opcode.PUSH3, opcode.Opcode(b)) assert.Equal(t, opcode.PUSH3, opcode.Opcode(b))
for i := 0; i < len(validators); i++ { for i := 0; i < len(validators); i++ {
bb := br.ReadBytes() bb := br.ReadVarBytes()
if br.Err != nil { if br.Err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -123,5 +123,5 @@ func (u Uint256) EncodeBinary(w *io.BinWriter) {
// DecodeBinary implements io.Serializable interface. // DecodeBinary implements io.Serializable interface.
func (u *Uint256) DecodeBinary(r *io.BinReader) { func (u *Uint256) DecodeBinary(r *io.BinReader) {
r.ReadBE(u[:]) r.ReadBytes(u[:])
} }

View file

@ -102,14 +102,14 @@ func DecodeBinaryStackItem(r *io.BinReader) StackItem {
switch stackItemType(t) { switch stackItemType(t) {
case byteArrayT: case byteArrayT:
data := r.ReadBytes() data := r.ReadVarBytes()
return NewByteArrayItem(data) return NewByteArrayItem(data)
case booleanT: case booleanT:
var b bool var b bool
r.ReadLE(&b) r.ReadLE(&b)
return NewBoolItem(b) return NewBoolItem(b)
case integerT: case integerT:
data := r.ReadBytes() data := r.ReadVarBytes()
num := new(big.Int).SetBytes(util.ArrayReverse(data)) num := new(big.Int).SetBytes(util.ArrayReverse(data))
return &BigIntegerItem{ return &BigIntegerItem{
value: num, value: num,