From d1a4e43c48b0a1b1ce46866bf7b12d7697d9d6f3 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Mon, 16 Sep 2019 19:31:49 +0300 Subject: [PATCH] io: redo Serializable to return errors in BinReader/BinWriter Further simplifies error handling. --- pkg/core/account_state.go | 27 +++--- pkg/core/account_state_test.go | 11 +-- pkg/core/asset_state.go | 31 ++----- pkg/core/asset_state_test.go | 7 +- pkg/core/block.go | 59 +++--------- pkg/core/block_base.go | 47 ++++------ pkg/core/block_test.go | 22 ++--- pkg/core/blockchain.go | 20 ++-- pkg/core/header.go | 20 ++-- pkg/core/header_test.go | 11 +-- pkg/core/helper_test.go | 6 +- pkg/core/spent_coin_state.go | 21 +++-- pkg/core/spent_coin_state_test.go | 7 +- pkg/core/transaction/attribute.go | 18 ++-- pkg/core/transaction/claim.go | 24 ++--- pkg/core/transaction/contract.go | 10 +- pkg/core/transaction/contract_test.go | 4 +- pkg/core/transaction/enrollment.go | 12 +-- pkg/core/transaction/enrollment_test.go | 4 +- pkg/core/transaction/helper_test.go | 5 +- pkg/core/transaction/input.go | 10 +- pkg/core/transaction/invocation.go | 10 +- pkg/core/transaction/issue.go | 10 +- pkg/core/transaction/miner.go | 10 +- pkg/core/transaction/miner_test.go | 4 +- pkg/core/transaction/output.go | 10 +- pkg/core/transaction/publish.go | 11 +-- pkg/core/transaction/register.go | 17 +--- pkg/core/transaction/register_test.go | 18 +++- pkg/core/transaction/state.go | 20 ++-- pkg/core/transaction/state_descriptor.go | 11 +-- pkg/core/transaction/state_test.go | 5 +- pkg/core/transaction/transaction.go | 112 +++++++---------------- pkg/core/transaction/transaction_test.go | 21 +++-- pkg/core/transaction/witness.go | 11 +-- pkg/core/unspent_coin_state.go | 21 +++-- pkg/core/unspent_coint_state_test.go | 7 +- pkg/core/util.go | 7 +- pkg/crypto/keys/publickey.go | 35 +++---- pkg/crypto/keys/publickey_test.go | 4 +- pkg/io/serializable.go | 11 ++- pkg/io/size.go | 6 +- pkg/io/size_test.go | 7 +- pkg/network/message.go | 40 +++----- pkg/network/payload/address.go | 34 ++----- pkg/network/payload/address_test.go | 16 ++-- pkg/network/payload/getblocks.go | 10 +- pkg/network/payload/getblocks_test.go | 16 ++-- pkg/network/payload/headers.go | 26 ++---- pkg/network/payload/headers_test.go | 16 ++-- pkg/network/payload/inventory.go | 12 +-- pkg/network/payload/inventory_test.go | 12 +-- pkg/network/payload/merkleblock.go | 15 ++- pkg/network/payload/payload.go | 12 +-- pkg/network/payload/version.go | 10 +- pkg/network/payload/version_test.go | 8 +- pkg/rpc/rpc.go | 5 +- pkg/rpc/server.go | 42 ++++----- pkg/rpc/txBuilder.go | 5 +- 59 files changed, 418 insertions(+), 605 deletions(-) diff --git a/pkg/core/account_state.go b/pkg/core/account_state.go index d5c1f6bbb..87c9771a0 100644 --- a/pkg/core/account_state.go +++ b/pkg/core/account_state.go @@ -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. diff --git a/pkg/core/account_state_test.go b/pkg/core/account_state_test.go index a6b0a8645..b00225984 100644 --- a/pkg/core/account_state_test.go +++ b/pkg/core/account_state_test.go @@ -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) diff --git a/pkg/core/asset_state.go b/pkg/core/asset_state.go index 712be5bcc..3a553d7ef 100644 --- a/pkg/core/asset_state.go +++ b/pkg/core/asset_state.go @@ -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. diff --git a/pkg/core/asset_state_test.go b/pkg/core/asset_state_test.go index cbebd3db2..203897c47 100644 --- a/pkg/core/asset_state_test.go +++ b/pkg/core/asset_state_test.go @@ -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) } diff --git a/pkg/core/block.go b/pkg/core/block.go index 19d8cedd7..27ec6b225 100644 --- a/pkg/core/block.go +++ b/pkg/core/block.go @@ -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 } diff --git a/pkg/core/block_base.go b/pkg/core/block_base.go index 4e063db0e..6b77e1b5b 100644 --- a/pkg/core/block_base.go +++ b/pkg/core/block_base.go @@ -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() + } } diff --git a/pkg/core/block_test.go b/pkg/core/block_test.go index 546d1de47..a26007d7e 100644 --- a/pkg/core/block_test.go +++ b/pkg/core/block_test.go @@ -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)) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 08e5b298a..21ca332a4 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -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 } }) diff --git a/pkg/core/header.go b/pkg/core/header.go index 659270cc5..0ce253ddb 100644 --- a/pkg/core/header.go +++ b/pkg/core/header.go @@ -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 } diff --git a/pkg/core/header_test.go b/pkg/core/header_test.go index 8b7bcf19f..81cd2a242 100644 --- a/pkg/core/header_test.go +++ b/pkg/core/header_test.go @@ -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") diff --git a/pkg/core/helper_test.go b/pkg/core/helper_test.go index 1ab25d3e9..65c44a8c0 100644 --- a/pkg/core/helper_test.go +++ b/pkg/core/helper_test.go @@ -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 diff --git a/pkg/core/spent_coin_state.go b/pkg/core/spent_coin_state.go index 21db15fb9..978ff2a02 100644 --- a/pkg/core/spent_coin_state.go +++ b/pkg/core/spent_coin_state.go @@ -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 } diff --git a/pkg/core/spent_coin_state_test.go b/pkg/core/spent_coin_state_test.go index dde497e3d..0736196ed 100644 --- a/pkg/core/spent_coin_state_test.go +++ b/pkg/core/spent_coin_state_test.go @@ -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) } diff --git a/pkg/core/transaction/attribute.go b/pkg/core/transaction/attribute.go index 425dd72e6..40b4ff7fb 100644 --- a/pkg/core/transaction/attribute.go +++ b/pkg/core/transaction/attribute.go @@ -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 diff --git a/pkg/core/transaction/claim.go b/pkg/core/transaction/claim.go index 61d44614c..7140f6aad 100644 --- a/pkg/core/transaction/claim.go +++ b/pkg/core/transaction/claim.go @@ -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 } diff --git a/pkg/core/transaction/contract.go b/pkg/core/transaction/contract.go index 4c445da21..32e66388f 100644 --- a/pkg/core/transaction/contract.go +++ b/pkg/core/transaction/contract.go @@ -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) { } diff --git a/pkg/core/transaction/contract_test.go b/pkg/core/transaction/contract_test.go index 43e7d19b2..6d6ed4ef0 100644 --- a/pkg/core/transaction/contract_test.go +++ b/pkg/core/transaction/contract_test.go @@ -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())) } diff --git a/pkg/core/transaction/enrollment.go b/pkg/core/transaction/enrollment.go index d01b3eedb..79e3c3b2e 100644 --- a/pkg/core/transaction/enrollment.go +++ b/pkg/core/transaction/enrollment.go @@ -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) } diff --git a/pkg/core/transaction/enrollment_test.go b/pkg/core/transaction/enrollment_test.go index fa669fc0e..beb4f46f9 100644 --- a/pkg/core/transaction/enrollment_test.go +++ b/pkg/core/transaction/enrollment_test.go @@ -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())) } diff --git a/pkg/core/transaction/helper_test.go b/pkg/core/transaction/helper_test.go index 2cc7cc121..beca5cf6a 100644 --- a/pkg/core/transaction/helper_test.go +++ b/pkg/core/transaction/helper_test.go @@ -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 } diff --git a/pkg/core/transaction/input.go b/pkg/core/transaction/input.go index a5a13411d..f5e25dcc7 100644 --- a/pkg/core/transaction/input.go +++ b/pkg/core/transaction/input.go @@ -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 } diff --git a/pkg/core/transaction/invocation.go b/pkg/core/transaction/invocation.go index 43a2409ed..2ac3550e0 100644 --- a/pkg/core/transaction/invocation.go +++ b/pkg/core/transaction/invocation.go @@ -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 } diff --git a/pkg/core/transaction/issue.go b/pkg/core/transaction/issue.go index 9f412e97a..5e09bb171 100644 --- a/pkg/core/transaction/issue.go +++ b/pkg/core/transaction/issue.go @@ -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) { } diff --git a/pkg/core/transaction/miner.go b/pkg/core/transaction/miner.go index 923253926..1e1ab3753 100644 --- a/pkg/core/transaction/miner.go +++ b/pkg/core/transaction/miner.go @@ -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 } diff --git a/pkg/core/transaction/miner_test.go b/pkg/core/transaction/miner_test.go index c5c7a77ee..4ef3e2334 100644 --- a/pkg/core/transaction/miner_test.go +++ b/pkg/core/transaction/miner_test.go @@ -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())) } diff --git a/pkg/core/transaction/output.go b/pkg/core/transaction/output.go index a6aacbdca..489059839 100644 --- a/pkg/core/transaction/output.go +++ b/pkg/core/transaction/output.go @@ -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 diff --git a/pkg/core/transaction/publish.go b/pkg/core/transaction/publish.go index 6a07fdfce..e46ce6a56 100644 --- a/pkg/core/transaction/publish.go +++ b/pkg/core/transaction/publish.go @@ -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 } diff --git a/pkg/core/transaction/register.go b/pkg/core/transaction/register.go index c3c227165..fde7687ef 100644 --- a/pkg/core/transaction/register.go +++ b/pkg/core/transaction/register.go @@ -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 } diff --git a/pkg/core/transaction/register_test.go b/pkg/core/transaction/register_test.go index c8a9419d7..77ee583ac 100644 --- a/pkg/core/transaction/register_test.go +++ b/pkg/core/transaction/register_test.go @@ -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) } diff --git a/pkg/core/transaction/state.go b/pkg/core/transaction/state.go index 8723b972d..22a214e99 100644 --- a/pkg/core/transaction/state.go +++ b/pkg/core/transaction/state.go @@ -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 } diff --git a/pkg/core/transaction/state_descriptor.go b/pkg/core/transaction/state_descriptor.go index 40dbbcf14..087ea5baf 100644 --- a/pkg/core/transaction/state_descriptor.go +++ b/pkg/core/transaction/state_descriptor.go @@ -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 } diff --git a/pkg/core/transaction/state_test.go b/pkg/core/transaction/state_test.go index eb425b42e..290bfe744 100644 --- a/pkg/core/transaction/state_test.go +++ b/pkg/core/transaction/state_test.go @@ -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())) } diff --git a/pkg/core/transaction/transaction.go b/pkg/core/transaction/transaction.go index 628677f21..13bdca753 100644 --- a/pkg/core/transaction/transaction.go +++ b/pkg/core/transaction/transaction.go @@ -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() - } diff --git a/pkg/core/transaction/transaction_test.go b/pkg/core/transaction/transaction_test.go index a5387bb5f..2c416c570 100644 --- a/pkg/core/transaction/transaction_test.go +++ b/pkg/core/transaction/transaction_test.go @@ -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())) } diff --git a/pkg/core/transaction/witness.go b/pkg/core/transaction/witness.go index 9256ecc16..8640dca74 100644 --- a/pkg/core/transaction/witness.go +++ b/pkg/core/transaction/witness.go @@ -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. diff --git a/pkg/core/unspent_coin_state.go b/pkg/core/unspent_coin_state.go index 504dc68dd..9f8026578 100644 --- a/pkg/core/unspent_coin_state.go +++ b/pkg/core/unspent_coin_state.go @@ -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 { diff --git a/pkg/core/unspent_coint_state_test.go b/pkg/core/unspent_coint_state_test.go index 8fb649f19..658233ebc 100644 --- a/pkg/core/unspent_coint_state_test.go +++ b/pkg/core/unspent_coint_state_test.go @@ -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) { diff --git a/pkg/core/util.go b/pkg/core/util.go index b092a2da4..05a189d26 100644 --- a/pkg/core/util.go +++ b/pkg/core/util.go @@ -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 } diff --git a/pkg/crypto/keys/publickey.go b/pkg/crypto/keys/publickey.go index 2a30c2626..bcb6cf68a 100644 --- a/pkg/crypto/keys/publickey.go +++ b/pkg/crypto/keys/publickey.go @@ -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. diff --git a/pkg/crypto/keys/publickey_test.go b/pkg/crypto/keys/publickey_test.go index 71e73f5ef..199577d6e 100644 --- a/pkg/crypto/keys/publickey_test.go +++ b/pkg/crypto/keys/publickey_test.go @@ -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() diff --git a/pkg/io/serializable.go b/pkg/io/serializable.go index 2063d2c6d..8e132b86b 100644 --- a/pkg/io/serializable.go +++ b/pkg/io/serializable.go @@ -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) } diff --git a/pkg/io/size.go b/pkg/io/size.go index ca966740c..ea8bcc562 100644 --- a/pkg/io/size.go +++ b/pkg/io/size.go @@ -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: diff --git a/pkg/io/size_test.go b/pkg/io/size_test.go index 85275fe94..d3a5ad561 100644 --- a/pkg/io/size_test.go +++ b/pkg/io/size_test.go @@ -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) { diff --git a/pkg/network/message.go b/pkg/network/message.go index 69fe8b2d8..1f702fc9f 100644 --- a/pkg/network/message.go +++ b/pkg/network/message.go @@ -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 } diff --git a/pkg/network/payload/address.go b/pkg/network/payload/address.go index e562f0b21..eae7bc670 100644 --- a/pkg/network/payload/address.go +++ b/pkg/network/payload/address.go @@ -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 } diff --git a/pkg/network/payload/address_test.go b/pkg/network/payload/address_test.go index dbe5db885..bfd2f2ded 100644 --- a/pkg/network/payload/address_test.go +++ b/pkg/network/payload/address_test.go @@ -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) } diff --git a/pkg/network/payload/getblocks.go b/pkg/network/payload/getblocks.go index 3298c5b5a..0029cb26c 100644 --- a/pkg/network/payload/getblocks.go +++ b/pkg/network/payload/getblocks.go @@ -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 } diff --git a/pkg/network/payload/getblocks_test.go b/pkg/network/payload/getblocks_test.go index 5844c9bbd..dfa35bef0 100644 --- a/pkg/network/payload/getblocks_test.go +++ b/pkg/network/payload/getblocks_test.go @@ -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) } diff --git a/pkg/network/payload/headers.go b/pkg/network/payload/headers.go index 66771fb5e..c85ecab2e 100644 --- a/pkg/network/payload/headers.go +++ b/pkg/network/payload/headers.go @@ -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 } diff --git a/pkg/network/payload/headers_test.go b/pkg/network/payload/headers_test.go index 2ee849f27..3c421077b 100644 --- a/pkg/network/payload/headers_test.go +++ b/pkg/network/payload/headers_test.go @@ -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())) } diff --git a/pkg/network/payload/inventory.go b/pkg/network/payload/inventory.go index ade25c9c8..4ce9ca939 100644 --- a/pkg/network/payload/inventory.go +++ b/pkg/network/payload/inventory.go @@ -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 } diff --git a/pkg/network/payload/inventory_test.go b/pkg/network/payload/inventory_test.go index acbe7c7c2..5e1d8ea92 100644 --- a/pkg/network/payload/inventory_test.go +++ b/pkg/network/payload/inventory_test.go @@ -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)) } diff --git a/pkg/network/payload/merkleblock.go b/pkg/network/payload/merkleblock.go index 2c9cf979c..59f733754 100644 --- a/pkg/network/payload/merkleblock.go +++ b/pkg/network/payload/merkleblock.go @@ -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 } diff --git a/pkg/network/payload/payload.go b/pkg/network/payload/payload.go index 72587cef6..112008ffd 100644 --- a/pkg/network/payload/payload.go +++ b/pkg/network/payload/payload.go @@ -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) {} diff --git a/pkg/network/payload/version.go b/pkg/network/payload/version.go index 2cb79fbe2..1343298b2 100644 --- a/pkg/network/payload/version.go +++ b/pkg/network/payload/version.go @@ -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 } diff --git a/pkg/network/payload/version_test.go b/pkg/network/payload/version_test.go index 5c4b3b73e..4af2e2425 100644 --- a/pkg/network/payload/version_test.go +++ b/pkg/network/payload/version_test.go @@ -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)) diff --git a/pkg/rpc/rpc.go b/pkg/rpc/rpc.go index 09684d114..fae42b549 100644 --- a/pkg/rpc/rpc.go +++ b/pkg/rpc/rpc.go @@ -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 { diff --git a/pkg/rpc/server.go b/pkg/rpc/server.go index db73d2ae1..9d5070e61 100644 --- a/pkg/rpc/server.go +++ b/pkg/rpc/server.go @@ -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) diff --git a/pkg/rpc/txBuilder.go b/pkg/rpc/txBuilder.go index d68f3b12a..72a2298af 100644 --- a/pkg/rpc/txBuilder.go +++ b/pkg/rpc/txBuilder.go @@ -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)])