io: redo Serializable to return errors in BinReader/BinWriter

Further simplifies error handling.
This commit is contained in:
Roman Khimov 2019-09-16 19:31:49 +03:00
parent 0bb8950f89
commit d1a4e43c48
59 changed files with 418 additions and 605 deletions

View file

@ -20,8 +20,10 @@ func (a Accounts) getAndUpdate(s storage.Store, hash util.Uint160) (*AccountStat
account := &AccountState{}
key := storage.AppendPrefix(storage.STAccount, hash.Bytes())
if b, err := s.Get(key); err == nil {
if err := account.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil {
return nil, fmt.Errorf("failed to decode (AccountState): %s", err)
r := io.NewBinReaderFromBuf(b)
account.DecodeBinary(r)
if r.Err != nil {
return nil, fmt.Errorf("failed to decode (AccountState): %s", r.Err)
}
} else {
account = NewAccountState(hash)
@ -35,8 +37,9 @@ func (a Accounts) getAndUpdate(s storage.Store, hash util.Uint160) (*AccountStat
func (a Accounts) commit(b storage.Batch) error {
buf := io.NewBufBinWriter()
for hash, state := range a {
if err := state.EncodeBinary(buf.BinWriter); err != nil {
return err
state.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return buf.Err
}
key := storage.AppendPrefix(storage.STAccount, hash.Bytes())
b.Put(key, buf.Bytes())
@ -66,7 +69,7 @@ func NewAccountState(scriptHash util.Uint160) *AccountState {
}
// DecodeBinary decodes AccountState from the given BinReader.
func (s *AccountState) DecodeBinary(br *io.BinReader) error {
func (s *AccountState) DecodeBinary(br *io.BinReader) {
br.ReadLE(&s.Version)
br.ReadLE(&s.ScriptHash)
br.ReadLE(&s.IsFrozen)
@ -74,9 +77,7 @@ func (s *AccountState) DecodeBinary(br *io.BinReader) error {
s.Votes = make([]*keys.PublicKey, lenVotes)
for i := 0; i < int(lenVotes); i++ {
s.Votes[i] = &keys.PublicKey{}
if err := s.Votes[i].DecodeBinary(br); err != nil {
return err
}
s.Votes[i].DecodeBinary(br)
}
s.Balances = make(map[util.Uint256]util.Fixed8)
@ -88,20 +89,16 @@ func (s *AccountState) DecodeBinary(br *io.BinReader) error {
br.ReadLE(&val)
s.Balances[key] = val
}
return br.Err
}
// EncodeBinary encodes AccountState to the given BinWriter.
func (s *AccountState) EncodeBinary(bw *io.BinWriter) error {
func (s *AccountState) EncodeBinary(bw *io.BinWriter) {
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(bw); err != nil {
return err
}
point.EncodeBinary(bw)
}
balances := s.nonZeroBalances()
@ -110,8 +107,6 @@ func (s *AccountState) EncodeBinary(bw *io.BinWriter) error {
bw.WriteLE(k)
bw.WriteLE(v)
}
return bw.Err
}
// Returns only the non-zero balances for the account.

View file

@ -31,14 +31,13 @@ func TestDecodeEncodeAccountState(t *testing.T) {
}
buf := io.NewBufBinWriter()
if err := a.EncodeBinary(buf.BinWriter); err != nil {
t.Fatal(err)
}
a.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
aDecode := &AccountState{}
if err := aDecode.DecodeBinary(io.NewBinReaderFromBuf(buf.Bytes())); err != nil {
t.Fatal(err)
}
r := io.NewBinReaderFromBuf(buf.Bytes())
aDecode.DecodeBinary(r)
assert.Nil(t, r.Err)
assert.Equal(t, a.Version, aDecode.Version)
assert.Equal(t, a.ScriptHash, aDecode.ScriptHash)

View file

@ -16,8 +16,9 @@ type Assets map[util.Uint256]*AssetState
func (a Assets) commit(b storage.Batch) error {
buf := io.NewBufBinWriter()
for hash, state := range a {
if err := state.EncodeBinary(buf.BinWriter); err != nil {
return err
state.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return buf.Err
}
key := storage.AppendPrefix(storage.STAsset, hash.Bytes())
b.Put(key, buf.Bytes())
@ -43,8 +44,8 @@ type AssetState struct {
IsFrozen bool
}
// DecodeBinary implements the Payload interface.
func (a *AssetState) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (a *AssetState) DecodeBinary(br *io.BinReader) {
br.ReadLE(&a.ID)
br.ReadLE(&a.AssetType)
@ -56,23 +57,16 @@ func (a *AssetState) DecodeBinary(br *io.BinReader) error {
br.ReadLE(&a.FeeMode)
br.ReadLE(&a.FeeAddress)
if br.Err != nil {
return br.Err
}
a.Owner = &keys.PublicKey{}
if err := a.Owner.DecodeBinary(br); err != nil {
return err
}
a.Owner.DecodeBinary(br)
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(bw *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (a *AssetState) EncodeBinary(bw *io.BinWriter) {
bw.WriteLE(a.ID)
bw.WriteLE(a.AssetType)
bw.WriteString(a.Name)
@ -82,17 +76,12 @@ func (a *AssetState) EncodeBinary(bw *io.BinWriter) error {
bw.WriteLE(a.FeeMode)
bw.WriteLE(a.FeeAddress)
if bw.Err != nil {
return bw.Err
}
if err := a.Owner.EncodeBinary(bw); err != nil {
return err
}
a.Owner.EncodeBinary(bw)
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.

View file

@ -27,8 +27,11 @@ func TestEncodeDecodeAssetState(t *testing.T) {
}
buf := io.NewBufBinWriter()
assert.Nil(t, asset.EncodeBinary(buf.BinWriter))
asset.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
assetDecode := &AssetState{}
assert.Nil(t, assetDecode.DecodeBinary(io.NewBinReaderFromBuf(buf.Bytes())))
r := io.NewBinReaderFromBuf(buf.Bytes())
assetDecode.DecodeBinary(r)
assert.Nil(t, r.Err)
assert.Equal(t, asset, assetDecode)
}

View file

@ -72,20 +72,13 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) {
}
br := io.NewBinReaderFromBuf(b)
if err := block.decodeHashableFields(br); err != nil {
return block, err
}
block.decodeHashableFields(br)
var padding uint8
br.ReadLE(&padding)
if br.Err != nil {
return block, br.Err
}
block.Script = &transaction.Witness{}
if err := block.Script.DecodeBinary(br); err != nil {
return block, err
}
block.Script.DecodeBinary(br)
lenTX := br.ReadVarUint()
block.Transactions = make([]*transaction.Transaction, lenTX)
@ -103,16 +96,9 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) {
// Notice that only the hashes of the transactions are stored.
func (b *Block) Trim() ([]byte, error) {
buf := io.NewBufBinWriter()
if err := b.encodeHashableFields(buf.BinWriter); err != nil {
return nil, err
}
b.encodeHashableFields(buf.BinWriter)
buf.WriteLE(uint8(1))
if buf.Err != nil {
return nil, buf.Err
}
if err := b.Script.EncodeBinary(buf.BinWriter); err != nil {
return nil, err
}
b.Script.EncodeBinary(buf.BinWriter)
buf.WriteVarUint(uint64(len(b.Transactions)))
for _, tx := range b.Transactions {
@ -124,42 +110,25 @@ func (b *Block) Trim() ([]byte, error) {
return buf.Bytes(), nil
}
// DecodeBinary decodes the block from the given reader.
func (b *Block) DecodeBinary(br *io.BinReader) error {
if err := b.BlockBase.DecodeBinary(br); err != nil {
return err
}
// DecodeBinary decodes the block from the given BinReader, implementing
// Serializable interface.
func (b *Block) DecodeBinary(br *io.BinReader) {
b.BlockBase.DecodeBinary(br)
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{}
if err := b.Transactions[i].DecodeBinary(br); err != nil {
return err
}
b.Transactions[i].DecodeBinary(br)
}
return nil
}
// EncodeBinary encodes the block to the given writer.
func (b *Block) EncodeBinary(bw *io.BinWriter) error {
err := b.BlockBase.EncodeBinary(bw)
if err != nil {
return err
}
// EncodeBinary encodes the block to the given BinWriter, implementing
// Serializable interface.
func (b *Block) EncodeBinary(bw *io.BinWriter) {
b.BlockBase.EncodeBinary(bw)
bw.WriteVarUint(uint64(len(b.Transactions)))
if bw.Err != nil {
return err
}
for _, tx := range b.Transactions {
err := tx.EncodeBinary(bw)
if err != nil {
return err
}
tx.EncodeBinary(bw)
}
return nil
}

View file

@ -58,35 +58,26 @@ func (b *BlockBase) Hash() util.Uint256 {
return b.hash
}
// DecodeBinary implements the payload interface.
func (b *BlockBase) DecodeBinary(br *io.BinReader) error {
if err := b.decodeHashableFields(br); err != nil {
return err
}
// DecodeBinary implements Serializable interface.
func (b *BlockBase) DecodeBinary(br *io.BinReader) {
b.decodeHashableFields(br)
var padding uint8
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)
br.Err = fmt.Errorf("format error: padding must equal 1 got %d", padding)
return
}
b.Script = &transaction.Witness{}
return b.Script.DecodeBinary(br)
b.Script.DecodeBinary(br)
}
// EncodeBinary implements the Payload interface
func (b *BlockBase) EncodeBinary(bw *io.BinWriter) error {
if err := b.encodeHashableFields(bw); err != nil {
return err
}
// EncodeBinary implements Serializable interface
func (b *BlockBase) EncodeBinary(bw *io.BinWriter) {
b.encodeHashableFields(bw)
bw.WriteLE(uint8(1))
if bw.Err != nil {
return bw.Err
}
return b.Script.EncodeBinary(bw)
b.Script.EncodeBinary(bw)
}
// createHash creates the hash of the block.
@ -97,8 +88,9 @@ func (b *BlockBase) EncodeBinary(bw *io.BinWriter) error {
// the modification of transaction will influence the hash value of the block.
func (b *BlockBase) createHash() error {
buf := io.NewBufBinWriter()
if err := b.encodeHashableFields(buf.BinWriter); err != nil {
return err
b.encodeHashableFields(buf.BinWriter)
if buf.Err != nil {
return buf.Err
}
b.hash = hash.DoubleSha256(buf.Bytes())
@ -107,7 +99,7 @@ func (b *BlockBase) createHash() error {
// encodeHashableFields will only encode the fields used for hashing.
// see Hash() for more information about the fields.
func (b *BlockBase) encodeHashableFields(bw *io.BinWriter) error {
func (b *BlockBase) encodeHashableFields(bw *io.BinWriter) {
bw.WriteLE(b.Version)
bw.WriteLE(b.PrevHash)
bw.WriteLE(b.MerkleRoot)
@ -115,12 +107,11 @@ func (b *BlockBase) encodeHashableFields(bw *io.BinWriter) error {
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(br *io.BinReader) error {
func (b *BlockBase) decodeHashableFields(br *io.BinReader) {
br.ReadLE(&b.Version)
br.ReadLE(&b.PrevHash)
br.ReadLE(&b.MerkleRoot)
@ -129,11 +120,9 @@ func (b *BlockBase) decodeHashableFields(br *io.BinReader) error {
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
// again.
return b.createHash()
if br.Err == nil {
br.Err = b.createHash()
}
}

View file

@ -24,9 +24,9 @@ func TestDecodeBlock1(t *testing.T) {
}
block := &Block{}
if err := block.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil {
t.Fatal(err)
}
r := io.NewBinReaderFromBuf(b)
block.DecodeBinary(r)
assert.Nil(t, r.Err)
assert.Equal(t, uint32(data["index"].(float64)), block.Index)
assert.Equal(t, uint32(data["version"].(float64)), block.Version)
@ -110,8 +110,8 @@ func TestBinBlockDecodeEncode(t *testing.T) {
b := Block{}
r := io.NewBinReaderFromBuf(rawtxBytes)
err := b.DecodeBinary(r)
assert.Nil(t, err)
b.DecodeBinary(r)
assert.Nil(t, r.Err)
expected := map[string]bool{ // 18 trans
"009f61f481f47eb7478e887871e4e744669d461b13d68e04250035260171d706": false,
@ -167,8 +167,8 @@ func TestBinBlockDecodeEncode(t *testing.T) {
buf := io.NewBufBinWriter()
err = b.EncodeBinary(buf.BinWriter)
assert.Nil(t, err)
b.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
}
@ -186,8 +186,8 @@ func TestBlockSizeCalculation(t *testing.T) {
b := Block{}
r := io.NewBinReaderFromBuf(rawBlockBytes)
err := b.DecodeBinary(r)
assert.Nil(t, err)
b.DecodeBinary(r)
assert.Nil(t, r.Err)
expected := []struct {
ID string
@ -252,8 +252,8 @@ func TestBlockSizeCalculation(t *testing.T) {
buf := io.NewBufBinWriter()
err = b.EncodeBinary(buf.BinWriter)
assert.Nil(t, err)
b.EncodeBinary(buf.BinWriter)
assert.Nil(t, r.Err)
benc := buf.Bytes()
// test size of the block
assert.Equal(t, 7360, len(benc))

View file

@ -254,8 +254,9 @@ func (bc *Blockchain) processHeader(h *Header, batch storage.Batch, headerList *
}
buf.Reset()
if err := h.EncodeBinary(buf.BinWriter); err != nil {
return err
h.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return buf.Err
}
key := storage.AppendPrefix(storage.DataBlock, h.Hash().BytesReverse())
@ -470,14 +471,13 @@ func (bc *Blockchain) GetTransaction(hash util.Uint256) (*transaction.Transactio
var height uint32
r.ReadLE(&height)
tx := &transaction.Transaction{}
tx.DecodeBinary(r)
if r.Err != nil {
return nil, 0, r.Err
}
tx := &transaction.Transaction{}
if err := tx.DecodeBinary(r); err != nil {
return nil, 0, err
}
return tx, height, nil
}
@ -578,7 +578,9 @@ func (bc *Blockchain) GetAssetState(assetID util.Uint256) *AssetState {
var as *AssetState
bc.Store.Seek(storage.STAsset.Bytes(), func(k, v []byte) {
var a AssetState
if err := a.DecodeBinary(io.NewBinReaderFromBuf(v)); err == nil && a.ID == assetID {
r := io.NewBinReaderFromBuf(v)
a.DecodeBinary(r)
if r.Err == nil && a.ID == assetID {
as = &a
}
})
@ -591,7 +593,9 @@ func (bc *Blockchain) GetAccountState(scriptHash util.Uint160) *AccountState {
var as *AccountState
bc.Store.Seek(storage.STAccount.Bytes(), func(k, v []byte) {
var a AccountState
if err := a.DecodeBinary(io.NewBinReaderFromBuf(v)); err == nil && a.ScriptHash == scriptHash {
r := io.NewBinReaderFromBuf(v)
a.DecodeBinary(r)
if r.Err == nil && a.ScriptHash == scriptHash {
as = &a
}
})

View file

@ -14,28 +14,20 @@ type Header struct {
_ uint8
}
// DecodeBinary implements the Payload interface.
func (h *Header) DecodeBinary(r *io.BinReader) error {
if err := h.BlockBase.DecodeBinary(r); err != nil {
return err
}
// DecodeBinary implements Serializable interface.
func (h *Header) DecodeBinary(r *io.BinReader) {
h.BlockBase.DecodeBinary(r)
var padding uint8
r.ReadLE(&padding)
if r.Err != nil {
return r.Err
}
if padding != 0 {
return fmt.Errorf("format error: padding must equal 0 got %d", padding)
r.Err = fmt.Errorf("format error: padding must equal 0 got %d", padding)
}
return nil
}
// EncodeBinary implements the Payload interface.
func (h *Header) EncodeBinary(w *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (h *Header) EncodeBinary(w *io.BinWriter) {
h.BlockBase.EncodeBinary(w)
w.WriteLE(uint8(0))
return w.Err
}

View file

@ -27,14 +27,13 @@ func TestHeaderEncodeDecode(t *testing.T) {
}}
buf := io.NewBufBinWriter()
if err := header.EncodeBinary(buf.BinWriter); err != nil {
t.Fatal(err)
}
header.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
headerDecode := &Header{}
if err := headerDecode.DecodeBinary(io.NewBinReaderFromBuf(buf.Bytes())); err != nil {
t.Fatal(err)
}
r := io.NewBinReaderFromBuf(buf.Bytes())
headerDecode.DecodeBinary(r)
assert.Nil(t, r.Err)
assert.Equal(t, header.Version, headerDecode.Version, "expected both versions to be equal")
assert.Equal(t, header.PrevHash, headerDecode.PrevHash, "expected both prev hashes to be equal")
assert.Equal(t, header.MerkleRoot, headerDecode.MerkleRoot, "expected both merkle roots to be equal")

View file

@ -63,8 +63,10 @@ func getDecodedBlock(t *testing.T, i int) *Block {
}
block := &Block{}
if err := block.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil {
t.Fatal(err)
r := io.NewBinReaderFromBuf(b)
block.DecodeBinary(r)
if r.Err != nil {
t.Fatal(r.Err)
}
return block

View file

@ -20,8 +20,10 @@ func (s SpentCoins) getAndUpdate(store storage.Store, hash util.Uint256) (*Spent
spent := &SpentCoinState{}
key := storage.AppendPrefix(storage.STSpentCoin, hash.BytesReverse())
if b, err := store.Get(key); err == nil {
if err := spent.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil {
return nil, fmt.Errorf("failed to decode (UnspentCoinState): %s", err)
r := io.NewBinReaderFromBuf(b)
spent.DecodeBinary(r)
if r.Err != nil {
return nil, fmt.Errorf("failed to decode (UnspentCoinState): %s", r.Err)
}
} else {
spent = &SpentCoinState{
@ -36,8 +38,9 @@ func (s SpentCoins) getAndUpdate(store storage.Store, hash util.Uint256) (*Spent
func (s SpentCoins) commit(b storage.Batch) error {
buf := io.NewBufBinWriter()
for hash, state := range s {
if err := state.EncodeBinary(buf.BinWriter); err != nil {
return err
state.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return buf.Err
}
key := storage.AppendPrefix(storage.STSpentCoin, hash.BytesReverse())
b.Put(key, buf.Bytes())
@ -64,8 +67,8 @@ func NewSpentCoinState(hash util.Uint256, height uint32) *SpentCoinState {
}
}
// DecodeBinary implements the Payload interface.
func (s *SpentCoinState) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (s *SpentCoinState) DecodeBinary(br *io.BinReader) {
br.ReadLE(&s.txHash)
br.ReadLE(&s.txHeight)
@ -80,11 +83,10 @@ func (s *SpentCoinState) DecodeBinary(br *io.BinReader) error {
br.ReadLE(&value)
s.items[key] = value
}
return br.Err
}
// EncodeBinary implements the Payload interface.
func (s *SpentCoinState) EncodeBinary(bw *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (s *SpentCoinState) EncodeBinary(bw *io.BinWriter) {
bw.WriteLE(s.txHash)
bw.WriteLE(s.txHeight)
bw.WriteVarUint(uint64(len(s.items)))
@ -92,5 +94,4 @@ func (s *SpentCoinState) EncodeBinary(bw *io.BinWriter) error {
bw.WriteLE(k)
bw.WriteLE(v)
}
return bw.Err
}

View file

@ -21,9 +21,12 @@ func TestEncodeDecodeSpentCoinState(t *testing.T) {
}
buf := io.NewBufBinWriter()
assert.Nil(t, spent.EncodeBinary(buf.BinWriter))
spent.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
spentDecode := new(SpentCoinState)
assert.Nil(t, spentDecode.DecodeBinary(io.NewBinReaderFromBuf(buf.Bytes())))
r := io.NewBinReaderFromBuf(buf.Bytes())
spentDecode.DecodeBinary(r)
assert.Nil(t, r.Err)
assert.Equal(t, spent, spentDecode)
}

View file

@ -14,8 +14,8 @@ type Attribute struct {
Data []byte
}
// DecodeBinary implements the Payload interface.
func (attr *Attribute) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (attr *Attribute) DecodeBinary(br *io.BinReader) {
br.ReadLE(&attr.Usage)
// very special case
@ -23,7 +23,7 @@ func (attr *Attribute) DecodeBinary(br *io.BinReader) error {
attr.Data = make([]byte, 33)
attr.Data[0] = byte(attr.Usage)
br.ReadLE(attr.Data[1:])
return br.Err
return
}
var datasize uint64
switch attr.Usage {
@ -43,15 +43,15 @@ func (attr *Attribute) DecodeBinary(br *io.BinReader) error {
Remark12, Remark13, Remark14, Remark15:
datasize = br.ReadVarUint()
default:
return fmt.Errorf("failed decoding TX attribute usage: 0x%2x", int(attr.Usage))
br.Err = fmt.Errorf("failed decoding TX attribute usage: 0x%2x", int(attr.Usage))
return
}
attr.Data = make([]byte, datasize)
br.ReadLE(attr.Data)
return br.Err
}
// EncodeBinary implements the Payload interface.
func (attr *Attribute) EncodeBinary(bw *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (attr *Attribute) EncodeBinary(bw *io.BinWriter) {
bw.WriteLE(&attr.Usage)
switch attr.Usage {
case ECDH02, ECDH03:
@ -68,10 +68,8 @@ func (attr *Attribute) EncodeBinary(bw *io.BinWriter) error {
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)
bw.Err = fmt.Errorf("failed encoding TX attribute usage: 0x%2x", attr.Usage)
}
return bw.Err
}
// MarshalJSON implements the json Marschaller interface

View file

@ -9,32 +9,20 @@ type ClaimTX struct {
Claims []*Input
}
// DecodeBinary implements the Payload interface.
func (tx *ClaimTX) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (tx *ClaimTX) DecodeBinary(br *io.BinReader) {
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{}
if err := tx.Claims[i].DecodeBinary(br); err != nil {
return err
}
tx.Claims[i].DecodeBinary(br)
}
return nil
}
// EncodeBinary implements the Payload interface.
func (tx *ClaimTX) EncodeBinary(bw *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (tx *ClaimTX) EncodeBinary(bw *io.BinWriter) {
bw.WriteVarUint(uint64(len(tx.Claims)))
if bw.Err != nil {
return bw.Err
}
for _, claim := range tx.Claims {
if err := claim.EncodeBinary(bw); err != nil {
return err
}
claim.EncodeBinary(bw)
}
return nil
}

View file

@ -15,12 +15,10 @@ func NewContractTX() *Transaction {
}
}
// DecodeBinary implements the Payload interface.
func (tx *ContractTX) DecodeBinary(r *io.BinReader) error {
return nil
// DecodeBinary implements Serializable interface.
func (tx *ContractTX) DecodeBinary(r *io.BinReader) {
}
// EncodeBinary implements the Payload interface.
func (tx *ContractTX) EncodeBinary(w *io.BinWriter) error {
return nil
// EncodeBinary implements Serializable interface.
func (tx *ContractTX) EncodeBinary(w *io.BinWriter) {
}

View file

@ -31,7 +31,7 @@ func TestEncodeDecodeContract(t *testing.T) {
// Encode
buf := io.NewBufBinWriter()
err := tx.EncodeBinary(buf.BinWriter)
assert.Equal(t, nil, err)
tx.EncodeBinary(buf.BinWriter)
assert.Equal(t, nil, buf.Err)
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
}

View file

@ -15,13 +15,13 @@ type EnrollmentTX struct {
PublicKey *keys.PublicKey
}
// DecodeBinary implements the Payload interface.
func (tx *EnrollmentTX) DecodeBinary(r *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (tx *EnrollmentTX) DecodeBinary(r *io.BinReader) {
tx.PublicKey = &keys.PublicKey{}
return tx.PublicKey.DecodeBinary(r)
tx.PublicKey.DecodeBinary(r)
}
// EncodeBinary implements the Payload interface.
func (tx *EnrollmentTX) EncodeBinary(w *io.BinWriter) error {
return tx.PublicKey.EncodeBinary(w)
// EncodeBinary implements Serializable interface.
func (tx *EnrollmentTX) EncodeBinary(w *io.BinWriter) {
tx.PublicKey.EncodeBinary(w)
}

View file

@ -17,8 +17,8 @@ func TestEncodeDecodeEnrollment(t *testing.T) {
assert.Equal(t, 0, int(tx.Version))
buf := io.NewBufBinWriter()
err := tx.EncodeBinary(buf.BinWriter)
tx.EncodeBinary(buf.BinWriter)
assert.Equal(t, nil, err)
assert.Equal(t, nil, buf.Err)
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
}

View file

@ -21,7 +21,8 @@ func decodeTransaction(rawTX string, t *testing.T) *Transaction {
b, err1 := hex.DecodeString(rawTX)
assert.Nil(t, err1)
tx := &Transaction{}
err2 := tx.DecodeBinary(io.NewBinReaderFromBuf(b))
assert.Nil(t, err2)
r := io.NewBinReaderFromBuf(b)
tx.DecodeBinary(r)
assert.Nil(t, r.Err)
return tx
}

View file

@ -14,16 +14,14 @@ type Input struct {
PrevIndex uint16 `json:"vout"`
}
// DecodeBinary implements the Payload interface.
func (in *Input) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (in *Input) DecodeBinary(br *io.BinReader) {
br.ReadLE(&in.PrevHash)
br.ReadLE(&in.PrevIndex)
return br.Err
}
// EncodeBinary implements the Payload interface.
func (in *Input) EncodeBinary(bw *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (in *Input) EncodeBinary(bw *io.BinWriter) {
bw.WriteLE(in.PrevHash)
bw.WriteLE(in.PrevIndex)
return bw.Err
}

View file

@ -31,22 +31,20 @@ func NewInvocationTX(script []byte) *Transaction {
}
}
// DecodeBinary implements the Payload interface.
func (tx *InvocationTX) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (tx *InvocationTX) DecodeBinary(br *io.BinReader) {
tx.Script = br.ReadBytes()
if tx.Version >= 1 {
br.ReadLE(&tx.Gas)
} else {
tx.Gas = util.Fixed8FromInt64(0)
}
return br.Err
}
// EncodeBinary implements the Payload interface.
func (tx *InvocationTX) EncodeBinary(bw *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (tx *InvocationTX) EncodeBinary(bw *io.BinWriter) {
bw.WriteBytes(tx.Script)
if tx.Version >= 1 {
bw.WriteLE(tx.Gas)
}
return bw.Err
}

View file

@ -8,12 +8,10 @@ import (
// This TX has not special attributes.
type IssueTX struct{}
// DecodeBinary implements the Payload interface.
func (tx *IssueTX) DecodeBinary(r *io.BinReader) error {
return nil
// DecodeBinary implements Serializable interface.
func (tx *IssueTX) DecodeBinary(r *io.BinReader) {
}
// EncodeBinary implements the Payload interface.
func (tx *IssueTX) EncodeBinary(w *io.BinWriter) error {
return nil
// EncodeBinary implements Serializable interface.
func (tx *IssueTX) EncodeBinary(w *io.BinWriter) {
}

View file

@ -10,14 +10,12 @@ type MinerTX struct {
Nonce uint32
}
// DecodeBinary implements the Payload interface.
func (tx *MinerTX) DecodeBinary(r *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (tx *MinerTX) DecodeBinary(r *io.BinReader) {
r.ReadLE(&tx.Nonce)
return r.Err
}
// EncodeBinary implements the Payload interface.
func (tx *MinerTX) EncodeBinary(w *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (tx *MinerTX) EncodeBinary(w *io.BinWriter) {
w.WriteLE(tx.Nonce)
return w.Err
}

View file

@ -23,8 +23,8 @@ func TestEncodeDecodeMiner(t *testing.T) {
// Encode
buf := io.NewBufBinWriter()
err := tx.EncodeBinary(buf.BinWriter)
assert.Equal(t, nil, err)
tx.EncodeBinary(buf.BinWriter)
assert.Equal(t, nil, buf.Err)
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
}

View file

@ -33,20 +33,18 @@ func NewOutput(assetID util.Uint256, amount util.Fixed8, scriptHash util.Uint160
}
}
// DecodeBinary implements the Payload interface.
func (out *Output) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (out *Output) DecodeBinary(br *io.BinReader) {
br.ReadLE(&out.AssetID)
br.ReadLE(&out.Amount)
br.ReadLE(&out.ScriptHash)
return br.Err
}
// EncodeBinary implements the Payload interface.
func (out *Output) EncodeBinary(bw *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (out *Output) EncodeBinary(bw *io.BinWriter) {
bw.WriteLE(out.AssetID)
bw.WriteLE(out.Amount)
bw.WriteLE(out.ScriptHash)
return bw.Err
}
// MarshalJSON implements the Marshaler interface

View file

@ -20,8 +20,8 @@ type PublishTX struct {
Version uint8 // Version of the parent struct Transaction. Used in reading NeedStorage flag.
}
// DecodeBinary implements the Payload interface.
func (tx *PublishTX) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (tx *PublishTX) DecodeBinary(br *io.BinReader) {
tx.Script = br.ReadBytes()
lenParams := br.ReadVarUint()
@ -47,12 +47,10 @@ func (tx *PublishTX) DecodeBinary(br *io.BinReader) error {
tx.Author = br.ReadString()
tx.Email = br.ReadString()
tx.Description = br.ReadString()
return br.Err
}
// EncodeBinary implements the Payload interface.
func (tx *PublishTX) EncodeBinary(bw *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (tx *PublishTX) EncodeBinary(bw *io.BinWriter) {
bw.WriteBytes(tx.Script)
bw.WriteVarUint(uint64(len(tx.ParamList)))
for _, param := range tx.ParamList {
@ -67,5 +65,4 @@ func (tx *PublishTX) EncodeBinary(bw *io.BinWriter) error {
bw.WriteString(tx.Author)
bw.WriteString(tx.Email)
bw.WriteString(tx.Description)
return bw.Err
}

View file

@ -28,34 +28,27 @@ type RegisterTX struct {
Admin util.Uint160
}
// DecodeBinary implements the Payload interface.
func (tx *RegisterTX) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (tx *RegisterTX) DecodeBinary(br *io.BinReader) {
br.ReadLE(&tx.AssetType)
tx.Name = br.ReadString()
br.ReadLE(&tx.Amount)
br.ReadLE(&tx.Precision)
if br.Err != nil {
return br.Err
}
tx.Owner = &keys.PublicKey{}
if err := tx.Owner.DecodeBinary(br); err != nil {
return err
}
tx.Owner.DecodeBinary(br)
br.ReadLE(&tx.Admin)
return br.Err
}
// EncodeBinary implements the Payload interface.
func (tx *RegisterTX) EncodeBinary(bw *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (tx *RegisterTX) EncodeBinary(bw *io.BinWriter) {
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
}

View file

@ -27,11 +27,14 @@ func TestRegisterTX(t *testing.T) {
}
buf := io.NewBufBinWriter()
assert.Nil(t, tx.EncodeBinary(buf.BinWriter))
tx.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
b := buf.Bytes()
txDecode := &Transaction{}
assert.Nil(t, txDecode.DecodeBinary(io.NewBinReaderFromBuf(b)))
r := io.NewBinReaderFromBuf(b)
txDecode.DecodeBinary(r)
assert.Nil(t, r.Err)
txData := tx.Data.(*RegisterTX)
txDecodeData := txDecode.Data.(*RegisterTX)
assert.Equal(t, txData, txDecodeData)
@ -46,7 +49,9 @@ func TestDecodeRegisterTXFromRawString(t *testing.T) {
}
tx := &Transaction{}
assert.Nil(t, tx.DecodeBinary(io.NewBinReaderFromBuf(b)))
r := io.NewBinReaderFromBuf(b)
tx.DecodeBinary(r)
assert.Nil(t, r.Err)
assert.Equal(t, RegisterType, tx.Type)
txData := tx.Data.(*RegisterTX)
assert.Equal(t, GoverningToken, txData.AssetType)
@ -58,10 +63,13 @@ func TestDecodeRegisterTXFromRawString(t *testing.T) {
assert.Equal(t, "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", tx.Hash().ReverseString())
buf := io.NewBufBinWriter()
assert.Nil(t, tx.EncodeBinary(buf.BinWriter))
tx.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
benc := buf.Bytes()
txDecode := &Transaction{}
assert.Nil(t, txDecode.DecodeBinary(io.NewBinReaderFromBuf(benc)))
encreader := io.NewBinReaderFromBuf(benc)
txDecode.DecodeBinary(encreader)
assert.Nil(t, encreader.Err)
assert.Equal(t, tx, txDecode)
}

View file

@ -9,28 +9,20 @@ type StateTX struct {
Descriptors []*StateDescriptor
}
// DecodeBinary implements the Payload interface.
func (tx *StateTX) DecodeBinary(r *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (tx *StateTX) DecodeBinary(r *io.BinReader) {
lenDesc := r.ReadVarUint()
tx.Descriptors = make([]*StateDescriptor, lenDesc)
for i := 0; i < int(lenDesc); i++ {
tx.Descriptors[i] = &StateDescriptor{}
err := tx.Descriptors[i].DecodeBinary(r)
if err != nil {
return err
}
tx.Descriptors[i].DecodeBinary(r)
}
return r.Err
}
// EncodeBinary implements the Payload interface.
func (tx *StateTX) EncodeBinary(w *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (tx *StateTX) EncodeBinary(w *io.BinWriter) {
w.WriteVarUint(uint64(len(tx.Descriptors)))
for _, desc := range tx.Descriptors {
err := desc.EncodeBinary(w)
if err != nil {
return err
}
desc.EncodeBinary(w)
}
return w.Err
}

View file

@ -21,22 +21,19 @@ type StateDescriptor struct {
Field string
}
// DecodeBinary implements the Payload interface.
func (s *StateDescriptor) DecodeBinary(r *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (s *StateDescriptor) DecodeBinary(r *io.BinReader) {
r.ReadLE(&s.Type)
s.Key = r.ReadBytes()
s.Value = r.ReadBytes()
s.Field = r.ReadString()
return r.Err
}
// EncodeBinary implements the Payload interface.
func (s *StateDescriptor) EncodeBinary(w *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (s *StateDescriptor) EncodeBinary(w *io.BinWriter) {
w.WriteLE(s.Type)
w.WriteBytes(s.Key)
w.WriteBytes(s.Value)
w.WriteString(s.Field)
return w.Err
}

View file

@ -31,9 +31,8 @@ func TestEncodeDecodeState(t *testing.T) {
// Encode
buf := io.NewBufBinWriter()
tx.EncodeBinary(buf.BinWriter)
err := tx.EncodeBinary(buf.BinWriter)
assert.Equal(t, nil, err)
assert.Equal(t, nil, buf.Err)
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
}

View file

@ -74,170 +74,126 @@ func (t *Transaction) AddInput(in *Input) {
t.Inputs = append(t.Inputs, in)
}
// DecodeBinary implements the payload interface.
func (t *Transaction) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (t *Transaction) DecodeBinary(br *io.BinReader) {
br.ReadLE(&t.Type)
br.ReadLE(&t.Version)
if br.Err != nil {
return br.Err
}
if err := t.decodeData(br); err != nil {
return err
}
t.decodeData(br)
lenAttrs := br.ReadVarUint()
t.Attributes = make([]*Attribute, lenAttrs)
for i := 0; i < int(lenAttrs); i++ {
t.Attributes[i] = &Attribute{}
if err := t.Attributes[i].DecodeBinary(br); err != nil {
log.Warnf("failed to decode TX %s", t.hash)
return err
}
t.Attributes[i].DecodeBinary(br)
}
lenInputs := br.ReadVarUint()
t.Inputs = make([]*Input, lenInputs)
for i := 0; i < int(lenInputs); i++ {
t.Inputs[i] = &Input{}
if err := t.Inputs[i].DecodeBinary(br); err != nil {
return err
}
t.Inputs[i].DecodeBinary(br)
}
lenOutputs := br.ReadVarUint()
t.Outputs = make([]*Output, lenOutputs)
for i := 0; i < int(lenOutputs); i++ {
t.Outputs[i] = &Output{}
if err := t.Outputs[i].DecodeBinary(br); err != nil {
return err
}
t.Outputs[i].DecodeBinary(br)
}
lenScripts := br.ReadVarUint()
t.Scripts = make([]*Witness, lenScripts)
for i := 0; i < int(lenScripts); i++ {
t.Scripts[i] = &Witness{}
if err := t.Scripts[i].DecodeBinary(br); err != nil {
return err
}
t.Scripts[i].DecodeBinary(br)
}
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()
if br.Err == nil {
br.Err = t.createHash()
}
}
func (t *Transaction) decodeData(r *io.BinReader) error {
func (t *Transaction) decodeData(r *io.BinReader) {
switch t.Type {
case InvocationType:
t.Data = &InvocationTX{Version: t.Version}
return t.Data.(*InvocationTX).DecodeBinary(r)
t.Data.(*InvocationTX).DecodeBinary(r)
case MinerType:
t.Data = &MinerTX{}
return t.Data.(*MinerTX).DecodeBinary(r)
t.Data.(*MinerTX).DecodeBinary(r)
case ClaimType:
t.Data = &ClaimTX{}
return t.Data.(*ClaimTX).DecodeBinary(r)
t.Data.(*ClaimTX).DecodeBinary(r)
case ContractType:
t.Data = &ContractTX{}
return t.Data.(*ContractTX).DecodeBinary(r)
t.Data.(*ContractTX).DecodeBinary(r)
case RegisterType:
t.Data = &RegisterTX{}
return t.Data.(*RegisterTX).DecodeBinary(r)
t.Data.(*RegisterTX).DecodeBinary(r)
case IssueType:
t.Data = &IssueTX{}
return t.Data.(*IssueTX).DecodeBinary(r)
t.Data.(*IssueTX).DecodeBinary(r)
case EnrollmentType:
t.Data = &EnrollmentTX{}
return t.Data.(*EnrollmentTX).DecodeBinary(r)
t.Data.(*EnrollmentTX).DecodeBinary(r)
case PublishType:
t.Data = &PublishTX{Version: t.Version}
return t.Data.(*PublishTX).DecodeBinary(r)
t.Data.(*PublishTX).DecodeBinary(r)
case StateType:
t.Data = &StateTX{}
return t.Data.(*StateTX).DecodeBinary(r)
t.Data.(*StateTX).DecodeBinary(r)
default:
log.Warnf("invalid TX type %s", t.Type)
}
return nil
}
// EncodeBinary implements the payload interface.
func (t *Transaction) EncodeBinary(bw *io.BinWriter) error {
if err := t.encodeHashableFields(bw); err != nil {
return err
}
// EncodeBinary implements Serializable interface.
func (t *Transaction) EncodeBinary(bw *io.BinWriter) {
t.encodeHashableFields(bw)
bw.WriteVarUint(uint64(len(t.Scripts)))
if bw.Err != nil {
return bw.Err
}
for _, s := range t.Scripts {
if err := s.EncodeBinary(bw); err != nil {
return err
}
s.EncodeBinary(bw)
}
return nil
}
// 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(bw *io.BinWriter) error {
func (t *Transaction) encodeHashableFields(bw *io.BinWriter) {
bw.WriteLE(t.Type)
bw.WriteLE(t.Version)
if bw.Err != nil {
return bw.Err
}
// Underlying TXer.
if t.Data != nil {
if err := t.Data.EncodeBinary(bw); err != nil {
return err
}
t.Data.EncodeBinary(bw)
}
// Attributes
bw.WriteVarUint(uint64(len(t.Attributes)))
if bw.Err != nil {
return bw.Err
}
for _, attr := range t.Attributes {
if err := attr.EncodeBinary(bw); err != nil {
return err
}
attr.EncodeBinary(bw)
}
// Inputs
bw.WriteVarUint(uint64(len(t.Inputs)))
if bw.Err != nil {
return bw.Err
}
for _, in := range t.Inputs {
if err := in.EncodeBinary(bw); err != nil {
return err
}
in.EncodeBinary(bw)
}
// Outputs
bw.WriteVarUint(uint64(len(t.Outputs)))
if bw.Err != nil {
return bw.Err
}
for _, out := range t.Outputs {
if err := out.EncodeBinary(bw); err != nil {
return err
}
out.EncodeBinary(bw)
}
return nil
}
// createHash creates the hash of the transaction.
func (t *Transaction) createHash() error {
buf := io.NewBufBinWriter()
if err := t.encodeHashableFields(buf.BinWriter); err != nil {
return err
t.encodeHashableFields(buf.BinWriter)
if buf.Err != nil {
return buf.Err
}
t.hash = hash.DoubleSha256(buf.Bytes())
@ -266,9 +222,9 @@ func (t Transaction) GroupOutputByAssetID() map[util.Uint256][]*Output {
// Bytes convert the transaction to []byte
func (t *Transaction) Bytes() []byte {
buf := io.NewBufBinWriter()
if err := t.EncodeBinary(buf.BinWriter); err != nil {
t.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return nil
}
return buf.Bytes()
}

View file

@ -28,13 +28,14 @@ func TestWitnessEncodeDecode(t *testing.T) {
}
buf := io.NewBufBinWriter()
err = wit.EncodeBinary(buf.BinWriter)
assert.Nil(t, err)
wit.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
benc := buf.Bytes()
witDecode := &Witness{}
err = witDecode.DecodeBinary(io.NewBinReaderFromBuf(benc))
assert.Nil(t, err)
encreader := io.NewBinReaderFromBuf(benc)
witDecode.DecodeBinary(encreader)
assert.Nil(t, encreader.Err)
t.Log(len(witDecode.VerificationScript))
t.Log(len(witDecode.InvocationScript))
@ -61,8 +62,8 @@ func TestDecodeEncodeClaimTX(t *testing.T) {
assert.Equal(t, verif, hex.EncodeToString(tx.Scripts[0].VerificationScript))
buf := io.NewBufBinWriter()
err := tx.EncodeBinary(buf.BinWriter)
assert.Nil(t, err)
tx.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
assert.Equal(t, rawClaimTX, hex.EncodeToString(buf.Bytes()))
hash := "2c6a45547b3898318e400e541628990a07acb00f3b9a15a8e966ae49525304da"
@ -89,8 +90,8 @@ func TestDecodeEncodeInvocationTX(t *testing.T) {
assert.Equal(t, verif, hex.EncodeToString(tx.Scripts[0].VerificationScript))
buf := io.NewBufBinWriter()
err := tx.EncodeBinary(buf.BinWriter)
assert.Nil(t, err)
tx.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
assert.Equal(t, rawInvocationTX, hex.EncodeToString(buf.Bytes()))
}
@ -144,7 +145,7 @@ func TestDecodePublishTX(t *testing.T) {
assert.Equal(t, expectedTX.Version, actualTX.Version)
buf := io.NewBufBinWriter()
err := actualTX.EncodeBinary(buf.BinWriter)
assert.Nil(t, err)
actualTX.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
assert.Equal(t, rawPublishTX, hex.EncodeToString(buf.Bytes()))
}

View file

@ -15,19 +15,16 @@ type Witness struct {
VerificationScript []byte
}
// DecodeBinary implements the payload interface.
func (w *Witness) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (w *Witness) DecodeBinary(br *io.BinReader) {
w.InvocationScript = br.ReadBytes()
w.VerificationScript = br.ReadBytes()
return br.Err
}
// EncodeBinary implements the payload interface.
func (w *Witness) EncodeBinary(bw *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (w *Witness) EncodeBinary(bw *io.BinWriter) {
bw.WriteBytes(w.InvocationScript)
bw.WriteBytes(w.VerificationScript)
return bw.Err
}
// MarshalJSON implements the json marshaller interface.

View file

@ -21,8 +21,10 @@ func (u UnspentCoins) getAndUpdate(s storage.Store, hash util.Uint256) (*Unspent
unspent := &UnspentCoinState{}
key := storage.AppendPrefix(storage.STCoin, hash.BytesReverse())
if b, err := s.Get(key); err == nil {
if err := unspent.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil {
return nil, fmt.Errorf("failed to decode (UnspentCoinState): %s", err)
r := io.NewBinReaderFromBuf(b)
unspent.DecodeBinary(r)
if r.Err != nil {
return nil, fmt.Errorf("failed to decode (UnspentCoinState): %s", r.Err)
}
} else {
unspent = &UnspentCoinState{
@ -54,8 +56,9 @@ func NewUnspentCoinState(n int) *UnspentCoinState {
func (u UnspentCoins) commit(b storage.Batch) error {
buf := io.NewBufBinWriter()
for hash, state := range u {
if err := state.EncodeBinary(buf.BinWriter); err != nil {
return err
state.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return buf.Err
}
key := storage.AppendPrefix(storage.STCoin, hash.BytesReverse())
b.Put(key, buf.Bytes())
@ -65,16 +68,15 @@ func (u UnspentCoins) commit(b storage.Batch) error {
}
// EncodeBinary encodes UnspentCoinState to the given BinWriter.
func (s *UnspentCoinState) EncodeBinary(bw *io.BinWriter) error {
func (s *UnspentCoinState) EncodeBinary(bw *io.BinWriter) {
bw.WriteVarUint(uint64(len(s.states)))
for _, state := range s.states {
bw.WriteLE(byte(state))
}
return bw.Err
}
// DecodeBinary decodes UnspentCoinState from the given BinReader.
func (s *UnspentCoinState) DecodeBinary(br *io.BinReader) error {
func (s *UnspentCoinState) DecodeBinary(br *io.BinReader) {
lenStates := br.ReadVarUint()
s.states = make([]CoinState, lenStates)
for i := 0; i < int(lenStates); i++ {
@ -82,7 +84,6 @@ func (s *UnspentCoinState) DecodeBinary(br *io.BinReader) error {
br.ReadLE(&state)
s.states[i] = CoinState(state)
}
return br.Err
}
// IsDoubleSpend verifies that the input transactions are not double spent.
@ -95,7 +96,9 @@ func IsDoubleSpend(s storage.Store, tx *transaction.Transaction) bool {
unspent := &UnspentCoinState{}
key := storage.AppendPrefix(storage.STCoin, prevHash.BytesReverse())
if b, err := s.Get(key); err == nil {
if err := unspent.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil {
r := io.NewBinReaderFromBuf(b)
unspent.DecodeBinary(r)
if r.Err != nil {
return false
}
if unspent == nil {

View file

@ -20,9 +20,12 @@ func TestDecodeEncodeUnspentCoinState(t *testing.T) {
}
buf := io.NewBufBinWriter()
assert.Nil(t, unspent.EncodeBinary(buf.BinWriter))
unspent.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
unspentDecode := &UnspentCoinState{}
assert.Nil(t, unspentDecode.DecodeBinary(io.NewBinReaderFromBuf(buf.Bytes())))
r := io.NewBinReaderFromBuf(buf.Bytes())
unspentDecode.DecodeBinary(r)
assert.Nil(t, r.Err)
}
func TestCommitUnspentCoins(t *testing.T) {

View file

@ -211,11 +211,10 @@ func storeAsTransaction(batch storage.Batch, tx *transaction.Transaction, index
key := storage.AppendPrefix(storage.DataTransaction, tx.Hash().BytesReverse())
buf := io.NewBufBinWriter()
buf.WriteLE(index)
if err := tx.EncodeBinary(buf.BinWriter); err != nil {
return err
tx.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return buf.Err
}
batch.Put(key, buf.Bytes())
return nil
}

View file

@ -50,8 +50,10 @@ func NewPublicKeyFromString(s string) (*PublicKey, error) {
}
pubKey := new(PublicKey)
if err := pubKey.DecodeBinary(io.NewBinReaderFromBuf(b)); err != nil {
return nil, err
r := io.NewBinReaderFromBuf(b)
pubKey.DecodeBinary(r)
if r.Err != nil {
return nil, r.Err
}
return pubKey, nil
@ -122,37 +124,38 @@ func decodeCompressedY(x *big.Int, ylsb uint) (*big.Int, error) {
// DecodeBytes decodes a PublicKey from the given slice of bytes.
func (p *PublicKey) DecodeBytes(data []byte) error {
b := io.NewBinReaderFromBuf(data)
return p.DecodeBinary(b)
p.DecodeBinary(b)
return b.Err
}
// DecodeBinary decodes a PublicKey from the given BinReader.
func (p *PublicKey) DecodeBinary(r *io.BinReader) error {
func (p *PublicKey) DecodeBinary(r *io.BinReader) {
var prefix uint8
var x, y *big.Int
var err error
r.ReadLE(&prefix)
if r.Err != nil {
return r.Err
return
}
// Infinity
switch prefix {
case 0x00:
// noop, initialized to nil
return nil
return
case 0x02, 0x03:
// Compressed public keys
xbytes := make([]byte, 32)
r.ReadLE(xbytes)
if r.Err != nil {
return r.Err
return
}
x = new(big.Int).SetBytes(xbytes)
ylsb := uint(prefix & 0x1)
y, err = decodeCompressedY(x, ylsb)
if err != nil {
return err
return
}
case 0x04:
xbytes := make([]byte, 32)
@ -160,30 +163,30 @@ func (p *PublicKey) DecodeBinary(r *io.BinReader) error {
r.ReadLE(xbytes)
r.ReadLE(ybytes)
if r.Err != nil {
return r.Err
return
}
x = new(big.Int).SetBytes(xbytes)
y = new(big.Int).SetBytes(ybytes)
default:
return errors.Errorf("invalid prefix %d", prefix)
r.Err = errors.Errorf("invalid prefix %d", prefix)
return
}
c := elliptic.P256()
cp := c.Params()
if !c.IsOnCurve(x, y) {
return errors.New("enccoded point is not on the P256 curve")
r.Err = errors.New("enccoded point is not on the P256 curve")
return
}
if x.Cmp(cp.P) >= 0 || y.Cmp(cp.P) >= 0 {
return errors.New("enccoded point is not correct (X or Y is bigger than P")
r.Err = errors.New("enccoded point is not correct (X or Y is bigger than P")
return
}
p.X, p.Y = x, y
return nil
}
// EncodeBinary encodes a PublicKey to the given BinWriter.
func (p *PublicKey) EncodeBinary(w *io.BinWriter) error {
func (p *PublicKey) EncodeBinary(w *io.BinWriter) {
w.WriteLE(p.Bytes())
return w.Err
}
// Signature returns a NEO-specific hash of the key.

View file

@ -11,7 +11,7 @@ import (
func TestEncodeDecodeInfinity(t *testing.T) {
key := &PublicKey{}
buf := io.NewBufBinWriter()
assert.Nil(t, key.EncodeBinary(buf.BinWriter))
key.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
b := buf.Bytes()
assert.Equal(t, 1, len(b))
@ -27,7 +27,7 @@ func TestEncodeDecodePublicKey(t *testing.T) {
assert.Nil(t, err)
p := k.PublicKey()
buf := io.NewBufBinWriter()
assert.Nil(t, p.EncodeBinary(buf.BinWriter))
p.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
b := buf.Bytes()

View file

@ -1,7 +1,12 @@
package io
// Serializable defines the binary encoding/decoding interface.
// Serializable defines the binary encoding/decoding interface. Errors are
// returned via BinReader/BinWriter Err field. These functions must have safe
// behavior when passed BinReader/BinWriter with Err already set. Invocations
// to these functions tend to be nested, with this mechanism only the top-level
// caller should handle the error once and all the other code should just not
// panic in presence of error.
type Serializable interface {
DecodeBinary(*BinReader) error
EncodeBinary(*BinWriter) error
DecodeBinary(*BinReader)
EncodeBinary(*BinWriter)
}

View file

@ -80,9 +80,9 @@ func GetVarSize(value interface{}) int {
}
cw := counterWriter{}
w := NewBinWriterFromIO(&cw)
err := vser.EncodeBinary(w)
if err != nil {
panic(fmt.Sprintf("error serializing %s: %s", reflect.TypeOf(value), err.Error()))
vser.EncodeBinary(w)
if w.Err != nil {
panic(fmt.Sprintf("error serializing %s: %s", reflect.TypeOf(value), w.Err.Error()))
}
return cw.counter
case reflect.Slice, reflect.Array:

View file

@ -13,13 +13,10 @@ type smthSerializable struct {
some [42]byte
}
func (*smthSerializable) DecodeBinary(*BinReader) error {
return nil
}
func (*smthSerializable) DecodeBinary(*BinReader) {}
func (ss *smthSerializable) EncodeBinary(bw *BinWriter) error {
func (ss *smthSerializable) EncodeBinary(bw *BinWriter) {
bw.WriteLE(ss.some)
return nil
}
func TestVarSize(t *testing.T) {

View file

@ -78,8 +78,9 @@ func NewMessage(magic config.NetMode, cmd CommandType, p payload.Payload) *Messa
if p != nil {
buf := io.NewBufBinWriter()
if err := p.EncodeBinary(buf.BinWriter); err != nil {
panic(err)
p.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
panic(buf.Err)
}
b := buf.Bytes()
size = uint32(len(b))
@ -176,46 +177,26 @@ func (m *Message) decodePayload(br *io.BinReader) error {
switch m.CommandType() {
case CMDVersion:
p = &payload.Version{}
if err := p.DecodeBinary(r); err != nil {
return err
}
case CMDInv, CMDGetData:
p = &payload.Inventory{}
if err := p.DecodeBinary(r); err != nil {
return err
}
case CMDAddr:
p = &payload.AddressList{}
if err := p.DecodeBinary(r); err != nil {
return err
}
case CMDBlock:
p = &core.Block{}
if err := p.DecodeBinary(r); err != nil {
return err
}
case CMDGetBlocks:
fallthrough
case CMDGetHeaders:
p = &payload.GetBlocks{}
if err := p.DecodeBinary(r); err != nil {
return err
}
case CMDHeaders:
p = &payload.Headers{}
if err := p.DecodeBinary(r); err != nil {
return err
}
case CMDTX:
p = &transaction.Transaction{}
if err := p.DecodeBinary(r); err != nil {
return err
}
case CMDMerkleBlock:
p = &payload.MerkleBlock{}
if err := p.DecodeBinary(r); err != nil {
return err
}
}
p.DecodeBinary(r)
if r.Err != nil {
return r.Err
}
m.Payload = p
@ -229,12 +210,13 @@ func (m *Message) Encode(br *io.BinWriter) error {
br.WriteLE(m.Command)
br.WriteLE(m.Length)
br.WriteLE(m.Checksum)
if m.Payload != nil {
m.Payload.EncodeBinary(br)
}
if br.Err != nil {
return br.Err
}
if m.Payload != nil {
return m.Payload.EncodeBinary(br)
}
return nil
}

View file

@ -27,22 +27,20 @@ func NewAddressAndTime(e *net.TCPAddr, t time.Time) *AddressAndTime {
return &aat
}
// DecodeBinary implements the Payload interface.
func (p *AddressAndTime) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (p *AddressAndTime) DecodeBinary(br *io.BinReader) {
br.ReadLE(&p.Timestamp)
br.ReadLE(&p.Services)
br.ReadBE(&p.IP)
br.ReadBE(&p.Port)
return br.Err
}
// EncodeBinary implements the Payload interface.
func (p *AddressAndTime) EncodeBinary(bw *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (p *AddressAndTime) EncodeBinary(bw *io.BinWriter) {
bw.WriteLE(p.Timestamp)
bw.WriteLE(p.Services)
bw.WriteBE(p.IP)
bw.WriteBE(p.Port)
return bw.Err
}
// IPPortString makes a string from IP and port specified.
@ -67,33 +65,21 @@ func NewAddressList(n int) *AddressList {
return &alist
}
// DecodeBinary implements the Payload interface.
func (p *AddressList) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (p *AddressList) DecodeBinary(br *io.BinReader) {
listLen := br.ReadVarUint()
if br.Err != nil {
return br.Err
}
p.Addrs = make([]*AddressAndTime, listLen)
for i := 0; i < int(listLen); i++ {
p.Addrs[i] = &AddressAndTime{}
if err := p.Addrs[i].DecodeBinary(br); err != nil {
return err
}
p.Addrs[i].DecodeBinary(br)
}
return nil
}
// EncodeBinary implements the Payload interface.
func (p *AddressList) EncodeBinary(bw *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (p *AddressList) EncodeBinary(bw *io.BinWriter) {
bw.WriteVarUint(uint64(len(p.Addrs)))
if bw.Err != nil {
return bw.Err
}
for _, addr := range p.Addrs {
if err := addr.EncodeBinary(bw); err != nil {
return err
}
addr.EncodeBinary(bw)
}
return nil
}

View file

@ -23,14 +23,14 @@ func TestEncodeDecodeAddress(t *testing.T) {
copy(aatip, addr.IP[:])
assert.Equal(t, e.IP, aatip)
assert.Equal(t, e.Port, int(addr.Port))
err := addr.EncodeBinary(buf.BinWriter)
assert.Nil(t, err)
addr.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
b := buf.Bytes()
r := io.NewBinReaderFromBuf(b)
addrDecode := &AddressAndTime{}
err = addrDecode.DecodeBinary(r)
assert.Nil(t, err)
addrDecode.DecodeBinary(r)
assert.Nil(t, r.Err)
assert.Equal(t, addr, addrDecode)
}
@ -44,14 +44,14 @@ func TestEncodeDecodeAddressList(t *testing.T) {
}
buf := io.NewBufBinWriter()
err := addrList.EncodeBinary(buf.BinWriter)
assert.Nil(t, err)
addrList.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
b := buf.Bytes()
r := io.NewBinReaderFromBuf(b)
addrListDecode := &AddressList{}
err = addrListDecode.DecodeBinary(r)
assert.Nil(t, err)
addrListDecode.DecodeBinary(r)
assert.Nil(t, r.Err)
assert.Equal(t, addrList, addrListDecode)
}

View file

@ -21,20 +21,18 @@ func NewGetBlocks(start []util.Uint256, stop util.Uint256) *GetBlocks {
}
}
// DecodeBinary implements the payload interface.
func (p *GetBlocks) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (p *GetBlocks) DecodeBinary(br *io.BinReader) {
lenStart := br.ReadVarUint()
p.HashStart = make([]util.Uint256, lenStart)
br.ReadLE(&p.HashStart)
br.ReadLE(&p.HashStop)
return br.Err
}
// EncodeBinary implements the payload interface.
func (p *GetBlocks) EncodeBinary(bw *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (p *GetBlocks) EncodeBinary(bw *io.BinWriter) {
bw.WriteVarUint(uint64(len(p.HashStart)))
bw.WriteLE(p.HashStart)
bw.WriteLE(p.HashStop)
return bw.Err
}

View file

@ -19,14 +19,14 @@ func TestGetBlockEncodeDecode(t *testing.T) {
p := NewGetBlocks(start, util.Uint256{})
buf := io.NewBufBinWriter()
err := p.EncodeBinary(buf.BinWriter)
assert.Nil(t, err)
p.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
b := buf.Bytes()
r := io.NewBinReaderFromBuf(b)
pDecode := &GetBlocks{}
err = pDecode.DecodeBinary(r)
assert.Nil(t, err)
pDecode.DecodeBinary(r)
assert.Nil(t, r.Err)
assert.Equal(t, p, pDecode)
}
@ -42,13 +42,13 @@ func TestGetBlockEncodeDecodeWithHashStop(t *testing.T) {
)
p := NewGetBlocks(start, stop)
buf := io.NewBufBinWriter()
err := p.EncodeBinary(buf.BinWriter)
assert.Nil(t, err)
p.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
b := buf.Bytes()
r := io.NewBinReaderFromBuf(b)
pDecode := &GetBlocks{}
err = pDecode.DecodeBinary(r)
assert.Nil(t, err)
pDecode.DecodeBinary(r)
assert.Nil(t, r.Err)
assert.Equal(t, p, pDecode)
}

View file

@ -16,12 +16,10 @@ const (
maxHeadersAllowed = 2000
)
// DecodeBinary implements the Payload interface.
func (p *Headers) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (p *Headers) DecodeBinary(br *io.BinReader) {
lenHeaders := br.ReadVarUint()
if br.Err != nil {
return br.Err
}
// C# node does it silently
if lenHeaders > maxHeadersAllowed {
log.Warnf("received %d headers, capping to %d", lenHeaders, maxHeadersAllowed)
@ -32,26 +30,16 @@ func (p *Headers) DecodeBinary(br *io.BinReader) error {
for i := 0; i < int(lenHeaders); i++ {
header := &core.Header{}
if err := header.DecodeBinary(br); err != nil {
return err
}
header.DecodeBinary(br)
p.Hdrs[i] = header
}
return nil
}
// EncodeBinary implements the Payload interface.
func (p *Headers) EncodeBinary(bw *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (p *Headers) EncodeBinary(bw *io.BinWriter) {
bw.WriteVarUint(uint64(len(p.Hdrs)))
if bw.Err != nil {
return bw.Err
}
for _, header := range p.Hdrs {
if err := header.EncodeBinary(bw); err != nil {
return err
}
header.EncodeBinary(bw)
}
return nil
}

View file

@ -42,14 +42,14 @@ func TestHeadersEncodeDecode(t *testing.T) {
}}
buf := io.NewBufBinWriter()
err := headers.EncodeBinary(buf.BinWriter)
assert.Nil(t, err)
headers.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
b := buf.Bytes()
r := io.NewBinReaderFromBuf(b)
headersDecode := &Headers{}
err = headersDecode.DecodeBinary(r)
assert.Nil(t, err)
headersDecode.DecodeBinary(r)
assert.Nil(t, r.Err)
for i := 0; i < len(headers.Hdrs); i++ {
assert.Equal(t, headers.Hdrs[i].Version, headersDecode.Hdrs[i].Version)
@ -67,8 +67,8 @@ func TestBinEncodeDecode(t *testing.T) {
r := io.NewBinReaderFromBuf(rawBlockBytes)
err := headerMsg.DecodeBinary(r)
assert.Nil(t, err)
headerMsg.DecodeBinary(r)
assert.Nil(t, r.Err)
assert.Equal(t, 1, len(headerMsg.Hdrs))
header := headerMsg.Hdrs[0]
@ -78,7 +78,7 @@ func TestBinEncodeDecode(t *testing.T) {
buf := io.NewBufBinWriter()
err = headerMsg.EncodeBinary(buf.BinWriter)
assert.Equal(t, nil, err)
headerMsg.EncodeBinary(buf.BinWriter)
assert.Equal(t, nil, buf.Err)
assert.Equal(t, hex.EncodeToString(rawBlockBytes), hex.EncodeToString(buf.Bytes()))
}

View file

@ -54,8 +54,8 @@ func NewInventory(typ InventoryType, hashes []util.Uint256) *Inventory {
}
}
// DecodeBinary implements the Payload interface.
func (p *Inventory) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (p *Inventory) DecodeBinary(br *io.BinReader) {
br.ReadLE(&p.Type)
listLen := br.ReadVarUint()
@ -63,12 +63,10 @@ func (p *Inventory) DecodeBinary(br *io.BinReader) error {
for i := 0; i < int(listLen); i++ {
br.ReadLE(&p.Hashes[i])
}
return br.Err
}
// EncodeBinary implements the Payload interface.
func (p *Inventory) EncodeBinary(bw *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (p *Inventory) EncodeBinary(bw *io.BinWriter) {
bw.WriteLE(p.Type)
listLen := len(p.Hashes)
@ -76,6 +74,4 @@ func (p *Inventory) EncodeBinary(bw *io.BinWriter) error {
for i := 0; i < listLen; i++ {
bw.WriteLE(p.Hashes[i])
}
return bw.Err
}

View file

@ -17,14 +17,14 @@ func TestInventoryEncodeDecode(t *testing.T) {
inv := NewInventory(BlockType, hashes)
buf := io.NewBufBinWriter()
err := inv.EncodeBinary(buf.BinWriter)
assert.Nil(t, err)
inv.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
b := buf.Bytes()
r := io.NewBinReaderFromBuf(b)
invDecode := &Inventory{}
err = invDecode.DecodeBinary(r)
assert.Nil(t, err)
invDecode.DecodeBinary(r)
assert.Nil(t, r.Err)
assert.Equal(t, inv, invDecode)
}
@ -32,8 +32,8 @@ func TestEmptyInv(t *testing.T) {
msgInv := NewInventory(TXType, []Uint256{})
buf := io.NewBufBinWriter()
err := msgInv.EncodeBinary(buf.BinWriter)
assert.Nil(t, err)
msgInv.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
assert.Equal(t, []byte{byte(TXType), 0}, buf.Bytes())
assert.Equal(t, 0, len(msgInv.Hashes))
}

View file

@ -14,12 +14,10 @@ type MerkleBlock struct {
Flags []byte
}
// DecodeBinary implements the Payload interface.
func (m *MerkleBlock) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (m *MerkleBlock) DecodeBinary(br *io.BinReader) {
m.BlockBase = &core.BlockBase{}
if err := m.BlockBase.DecodeBinary(br); err != nil {
return err
}
m.BlockBase.DecodeBinary(br)
m.TxCount = int(br.ReadVarUint())
n := br.ReadVarUint()
@ -28,10 +26,9 @@ func (m *MerkleBlock) DecodeBinary(br *io.BinReader) error {
br.ReadLE(&m.Hashes[i])
}
m.Flags = br.ReadBytes()
return br.Err
}
// EncodeBinary implements the Payload interface.
func (m *MerkleBlock) EncodeBinary(bw *io.BinWriter) error {
return nil
// EncodeBinary implements Serializable interface.
func (m *MerkleBlock) EncodeBinary(bw *io.BinWriter) {
return
}

View file

@ -16,12 +16,8 @@ func NewNullPayload() *NullPayload {
return &NullPayload{}
}
// DecodeBinary implements the Payload interface.
func (p *NullPayload) DecodeBinary(r io.Reader) error {
return nil
}
// DecodeBinary implements Serializable interface.
func (p *NullPayload) DecodeBinary(r *io.BinReader) {}
// EncodeBinary implements the Payload interface.
func (p *NullPayload) EncodeBinary(r io.Writer) error {
return nil
}
// EncodeBinary implements Serializable interface.
func (p *NullPayload) EncodeBinary(w *io.BinWriter) {}

View file

@ -53,8 +53,8 @@ func NewVersion(id uint32, p uint16, ua string, h uint32, r bool) *Version {
}
}
// DecodeBinary implements the Payload interface.
func (p *Version) DecodeBinary(br *io.BinReader) error {
// DecodeBinary implements Serializable interface.
func (p *Version) DecodeBinary(br *io.BinReader) {
br.ReadLE(&p.Version)
br.ReadLE(&p.Services)
br.ReadLE(&p.Timestamp)
@ -63,11 +63,10 @@ func (p *Version) DecodeBinary(br *io.BinReader) error {
p.UserAgent = br.ReadBytes()
br.ReadLE(&p.StartHeight)
br.ReadLE(&p.Relay)
return br.Err
}
// EncodeBinary implements the Payload interface.
func (p *Version) EncodeBinary(br *io.BinWriter) error {
// EncodeBinary implements Serializable interface.
func (p *Version) EncodeBinary(br *io.BinWriter) {
br.WriteLE(p.Version)
br.WriteLE(p.Services)
br.WriteLE(p.Timestamp)
@ -77,5 +76,4 @@ func (p *Version) EncodeBinary(br *io.BinWriter) error {
br.WriteBytes(p.UserAgent)
br.WriteLE(p.StartHeight)
br.WriteLE(&p.Relay)
return br.Err
}

View file

@ -17,15 +17,15 @@ func TestVersionEncodeDecode(t *testing.T) {
version := NewVersion(id, port, useragent, height, relay)
buf := io.NewBufBinWriter()
err := version.EncodeBinary(buf.BinWriter)
assert.Nil(t, err)
version.EncodeBinary(buf.BinWriter)
assert.Nil(t, buf.Err)
b := buf.Bytes()
assert.Equal(t, io.GetVarSize(version), len(b))
r := io.NewBinReaderFromBuf(b)
versionDecoded := &Version{}
err = versionDecoded.DecodeBinary(r)
assert.Nil(t, err)
versionDecoded.DecodeBinary(r)
assert.Nil(t, r.Err)
assert.Equal(t, versionDecoded.Nonce, id)
assert.Equal(t, versionDecoded.Port, port)
assert.Equal(t, versionDecoded.UserAgent, []byte(useragent))

View file

@ -130,8 +130,9 @@ func (c *Client) SendToAddress(asset util.Uint256, address string, amount util.F
if rawTx, err = CreateRawContractTransaction(txParams); err != nil {
return nil, errors.Wrap(err, "failed to create raw transaction for `sendtoaddress`")
}
if err = rawTx.EncodeBinary(buf.BinWriter); err != nil {
return nil, errors.Wrap(err, "failed to encode raw transaction to binary for `sendtoaddress`")
rawTx.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return nil, errors.Wrap(buf.Err, "failed to encode raw transaction to binary for `sendtoaddress`")
}
rawTxStr = hex.EncodeToString(buf.Bytes())
if resp, err = c.sendRawTransaction(rawTxStr); err != nil {

View file

@ -296,27 +296,27 @@ func (s *Server) sendrawtransaction(reqParams Params) (interface{}, error) {
} else {
r := io.NewBinReaderFromBuf(byteTx)
tx := &transaction.Transaction{}
err = tx.DecodeBinary(r)
if err != nil {
err = errors.Wrap(err, "transaction DecodeBinary failed")
}
relayReason := s.coreServer.RelayTxn(tx)
switch relayReason {
case network.RelaySucceed:
results = true
case network.RelayAlreadyExists:
err = errors.New("block or transaction already exists and cannot be sent repeatedly")
case network.RelayOutOfMemory:
err = errors.New("the memory pool is full and no more transactions can be sent")
case network.RelayUnableToVerify:
err = errors.New("the block cannot be validated")
case network.RelayInvalid:
err = errors.New("block or transaction validation failed")
case network.RelayPolicyFail:
err = errors.New("one of the Policy filters failed")
default:
err = errors.New("unknown error")
tx.DecodeBinary(r)
if r.Err != nil {
err = errors.Wrap(r.Err, "transaction DecodeBinary failed")
} else {
relayReason := s.coreServer.RelayTxn(tx)
switch relayReason {
case network.RelaySucceed:
results = true
case network.RelayAlreadyExists:
err = errors.New("block or transaction already exists and cannot be sent repeatedly")
case network.RelayOutOfMemory:
err = errors.New("the memory pool is full and no more transactions can be sent")
case network.RelayUnableToVerify:
err = errors.New("the block cannot be validated")
case network.RelayInvalid:
err = errors.New("block or transaction validation failed")
case network.RelayPolicyFail:
err = errors.New("one of the Policy filters failed")
default:
err = errors.New("unknown error")
}
}
if err != nil {
resultsErr = NewInternalServerError(err.Error(), err)

View file

@ -73,8 +73,9 @@ func GetInvocationScript(tx *transaction.Transaction, wif keys.WIF) ([]byte, err
buf = io.NewBufBinWriter()
signature []byte
)
if err = tx.EncodeBinary(buf.BinWriter); err != nil {
return nil, errs.Wrap(err, "Failed to encode transaction to binary")
tx.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return nil, errs.Wrap(buf.Err, "Failed to encode transaction to binary")
}
data := buf.Bytes()
signature, err = wif.PrivateKey.Sign(data[:(len(data) - 1)])