forked from TrueCloudLab/neoneo-go
Merge pull request #400 from nspcc-dev/move-rw-to-io
Move BinReader/BinWriter to io and simplify things BinReader and BinWriter don't belong to util, actually util shouldn't exist at all. Moving them to io and using them for all encoding/decoding purposes allows to simplify a lot of code, especially in the error handling space. These interfaces are designed to absorb errors until someone can do something meaningful with them (usually that's the top caller of encode/decode functions) and our current use of them is inconsistent. This patchset moves BinReader/BinWriter and size calculations (that are mostly about Serializable things) to io package and makes all the other code use them for encoding/decoding purposes.
This commit is contained in:
commit
39a024eb03
75 changed files with 981 additions and 1189 deletions
|
@ -1,12 +1,11 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/storage"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -21,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(bytes.NewReader(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)
|
||||
|
@ -34,10 +35,11 @@ func (a Accounts) getAndUpdate(s storage.Store, hash util.Uint160) (*AccountStat
|
|||
|
||||
// commit writes all account states to the given Batch.
|
||||
func (a Accounts) commit(b storage.Batch) error {
|
||||
buf := new(bytes.Buffer)
|
||||
buf := io.NewBufBinWriter()
|
||||
for hash, state := range a {
|
||||
if err := state.EncodeBinary(buf); 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,9 +68,8 @@ func NewAccountState(scriptHash util.Uint160) *AccountState {
|
|||
}
|
||||
}
|
||||
|
||||
// DecodeBinary decodes AccountState from the given io.Reader.
|
||||
func (s *AccountState) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// DecodeBinary decodes AccountState from the given BinReader.
|
||||
func (s *AccountState) DecodeBinary(br *io.BinReader) {
|
||||
br.ReadLE(&s.Version)
|
||||
br.ReadLE(&s.ScriptHash)
|
||||
br.ReadLE(&s.IsFrozen)
|
||||
|
@ -76,9 +77,7 @@ func (s *AccountState) DecodeBinary(r io.Reader) 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(r); err != nil {
|
||||
return err
|
||||
}
|
||||
s.Votes[i].DecodeBinary(br)
|
||||
}
|
||||
|
||||
s.Balances = make(map[util.Uint256]util.Fixed8)
|
||||
|
@ -90,21 +89,16 @@ func (s *AccountState) DecodeBinary(r io.Reader) error {
|
|||
br.ReadLE(&val)
|
||||
s.Balances[key] = val
|
||||
}
|
||||
|
||||
return br.Err
|
||||
}
|
||||
|
||||
// EncodeBinary encode AccountState to the given io.Writer.
|
||||
func (s *AccountState) EncodeBinary(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
// EncodeBinary encodes AccountState to the given BinWriter.
|
||||
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(w); err != nil {
|
||||
return err
|
||||
}
|
||||
point.EncodeBinary(bw)
|
||||
}
|
||||
|
||||
balances := s.nonZeroBalances()
|
||||
|
@ -113,8 +107,6 @@ func (s *AccountState) EncodeBinary(w io.Writer) error {
|
|||
bw.WriteLE(k)
|
||||
bw.WriteLE(v)
|
||||
}
|
||||
|
||||
return bw.Err
|
||||
}
|
||||
|
||||
// Returns only the non-zero balances for the account.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
@ -30,15 +30,14 @@ func TestDecodeEncodeAccountState(t *testing.T) {
|
|||
Balances: balances,
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if err := a.EncodeBinary(buf); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
buf := io.NewBufBinWriter()
|
||||
a.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
|
||||
aDecode := &AccountState{}
|
||||
if err := aDecode.DecodeBinary(buf); 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)
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/storage"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -16,10 +14,11 @@ const feeMode = 0x0
|
|||
type Assets map[util.Uint256]*AssetState
|
||||
|
||||
func (a Assets) commit(b storage.Batch) error {
|
||||
buf := new(bytes.Buffer)
|
||||
buf := io.NewBufBinWriter()
|
||||
for hash, state := range a {
|
||||
if err := state.EncodeBinary(buf); 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())
|
||||
|
@ -45,9 +44,8 @@ type AssetState struct {
|
|||
IsFrozen bool
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (a *AssetState) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// DecodeBinary implements Serializable interface.
|
||||
func (a *AssetState) DecodeBinary(br *io.BinReader) {
|
||||
br.ReadLE(&a.ID)
|
||||
br.ReadLE(&a.AssetType)
|
||||
|
||||
|
@ -59,24 +57,16 @@ func (a *AssetState) DecodeBinary(r io.Reader) 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(r); 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(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
// EncodeBinary implements Serializable interface.
|
||||
func (a *AssetState) EncodeBinary(bw *io.BinWriter) {
|
||||
bw.WriteLE(a.ID)
|
||||
bw.WriteLE(a.AssetType)
|
||||
bw.WriteString(a.Name)
|
||||
|
@ -86,17 +76,12 @@ func (a *AssetState) EncodeBinary(w io.Writer) error {
|
|||
bw.WriteLE(a.FeeMode)
|
||||
bw.WriteLE(a.FeeAddress)
|
||||
|
||||
if bw.Err != nil {
|
||||
return bw.Err
|
||||
}
|
||||
if err := a.Owner.EncodeBinary(w); 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.
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
@ -26,9 +26,12 @@ func TestEncodeDecodeAssetState(t *testing.T) {
|
|||
IsFrozen: false,
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
assert.Nil(t, asset.EncodeBinary(buf))
|
||||
buf := io.NewBufBinWriter()
|
||||
asset.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
assetDecode := &AssetState{}
|
||||
assert.Nil(t, assetDecode.DecodeBinary(buf))
|
||||
r := io.NewBinReaderFromBuf(buf.Bytes())
|
||||
assetDecode.DecodeBinary(r)
|
||||
assert.Nil(t, r.Err)
|
||||
assert.Equal(t, asset, assetDecode)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -73,22 +71,14 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) {
|
|||
Trimmed: true,
|
||||
}
|
||||
|
||||
r := bytes.NewReader(b)
|
||||
if err := block.decodeHashableFields(r); err != nil {
|
||||
return block, err
|
||||
}
|
||||
br := io.NewBinReaderFromBuf(b)
|
||||
block.decodeHashableFields(br)
|
||||
|
||||
br := util.BinReader{R: r}
|
||||
var padding uint8
|
||||
br.ReadLE(&padding)
|
||||
if br.Err != nil {
|
||||
return block, br.Err
|
||||
}
|
||||
|
||||
block.Script = &transaction.Witness{}
|
||||
if err := block.Script.DecodeBinary(r); err != nil {
|
||||
return block, err
|
||||
}
|
||||
block.Script.DecodeBinary(br)
|
||||
|
||||
lenTX := br.ReadVarUint()
|
||||
block.Transactions = make([]*transaction.Transaction, lenTX)
|
||||
|
@ -105,67 +95,40 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) {
|
|||
// in storage.
|
||||
// Notice that only the hashes of the transactions are stored.
|
||||
func (b *Block) Trim() ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := b.encodeHashableFields(buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bw := util.BinWriter{W: buf}
|
||||
bw.WriteLE(uint8(1))
|
||||
if bw.Err != nil {
|
||||
return nil, bw.Err
|
||||
}
|
||||
if err := b.Script.EncodeBinary(buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf := io.NewBufBinWriter()
|
||||
b.encodeHashableFields(buf.BinWriter)
|
||||
buf.WriteLE(uint8(1))
|
||||
b.Script.EncodeBinary(buf.BinWriter)
|
||||
|
||||
bw.WriteVarUint(uint64(len(b.Transactions)))
|
||||
buf.WriteVarUint(uint64(len(b.Transactions)))
|
||||
for _, tx := range b.Transactions {
|
||||
bw.WriteLE(tx.Hash())
|
||||
buf.WriteLE(tx.Hash())
|
||||
}
|
||||
if bw.Err != nil {
|
||||
return nil, bw.Err
|
||||
if buf.Err != nil {
|
||||
return nil, buf.Err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// DecodeBinary decodes the block from the given reader.
|
||||
func (b *Block) DecodeBinary(r io.Reader) error {
|
||||
if err := b.BlockBase.DecodeBinary(r); 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)
|
||||
|
||||
br := util.BinReader{R: r}
|
||||
lentx := br.ReadVarUint()
|
||||
if br.Err != nil {
|
||||
return br.Err
|
||||
}
|
||||
b.Transactions = make([]*transaction.Transaction, lentx)
|
||||
for i := 0; i < int(lentx); i++ {
|
||||
b.Transactions[i] = &transaction.Transaction{}
|
||||
if err := b.Transactions[i].DecodeBinary(r); err != nil {
|
||||
return err
|
||||
}
|
||||
b.Transactions[i].DecodeBinary(br)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeBinary encodes the block to the given writer.
|
||||
func (b *Block) EncodeBinary(w io.Writer) error {
|
||||
err := b.BlockBase.EncodeBinary(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bw := util.BinWriter{W: w}
|
||||
// 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(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tx.EncodeBinary(bw)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -59,37 +58,26 @@ func (b *BlockBase) Hash() util.Uint256 {
|
|||
return b.hash
|
||||
}
|
||||
|
||||
// DecodeBinary implements the payload interface.
|
||||
func (b *BlockBase) DecodeBinary(r io.Reader) error {
|
||||
if err := b.decodeHashableFields(r); err != nil {
|
||||
return err
|
||||
}
|
||||
// DecodeBinary implements Serializable interface.
|
||||
func (b *BlockBase) DecodeBinary(br *io.BinReader) {
|
||||
b.decodeHashableFields(br)
|
||||
|
||||
var padding uint8
|
||||
br := util.BinReader{R: r}
|
||||
br.ReadLE(&padding)
|
||||
if br.Err != nil {
|
||||
return br.Err
|
||||
}
|
||||
if padding != 1 {
|
||||
return fmt.Errorf("format error: padding must equal 1 got %d", padding)
|
||||
br.Err = fmt.Errorf("format error: padding must equal 1 got %d", padding)
|
||||
return
|
||||
}
|
||||
|
||||
b.Script = &transaction.Witness{}
|
||||
return b.Script.DecodeBinary(r)
|
||||
b.Script.DecodeBinary(br)
|
||||
}
|
||||
|
||||
// EncodeBinary implements the Payload interface
|
||||
func (b *BlockBase) EncodeBinary(w io.Writer) error {
|
||||
if err := b.encodeHashableFields(w); err != nil {
|
||||
return err
|
||||
}
|
||||
bw := util.BinWriter{W: w}
|
||||
// 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(w)
|
||||
b.Script.EncodeBinary(bw)
|
||||
}
|
||||
|
||||
// createHash creates the hash of the block.
|
||||
|
@ -99,9 +87,10 @@ func (b *BlockBase) EncodeBinary(w io.Writer) error {
|
|||
// Since MerkleRoot already contains the hash value of all transactions,
|
||||
// the modification of transaction will influence the hash value of the block.
|
||||
func (b *BlockBase) createHash() error {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := b.encodeHashableFields(buf); err != nil {
|
||||
return err
|
||||
buf := io.NewBufBinWriter()
|
||||
b.encodeHashableFields(buf.BinWriter)
|
||||
if buf.Err != nil {
|
||||
return buf.Err
|
||||
}
|
||||
b.hash = hash.DoubleSha256(buf.Bytes())
|
||||
|
||||
|
@ -110,8 +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(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
func (b *BlockBase) encodeHashableFields(bw *io.BinWriter) {
|
||||
bw.WriteLE(b.Version)
|
||||
bw.WriteLE(b.PrevHash)
|
||||
bw.WriteLE(b.MerkleRoot)
|
||||
|
@ -119,13 +107,11 @@ func (b *BlockBase) encodeHashableFields(w io.Writer) 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(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
func (b *BlockBase) decodeHashableFields(br *io.BinReader) {
|
||||
br.ReadLE(&b.Version)
|
||||
br.ReadLE(&b.PrevHash)
|
||||
br.ReadLE(&b.MerkleRoot)
|
||||
|
@ -134,11 +120,9 @@ func (b *BlockBase) decodeHashableFields(r io.Reader) 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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -24,9 +24,9 @@ func TestDecodeBlock1(t *testing.T) {
|
|||
}
|
||||
|
||||
block := &Block{}
|
||||
if err := block.DecodeBinary(bytes.NewReader(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)
|
||||
|
@ -109,9 +109,9 @@ func TestBinBlockDecodeEncode(t *testing.T) {
|
|||
|
||||
b := Block{}
|
||||
|
||||
r := bytes.NewReader(rawtxBytes)
|
||||
err := b.DecodeBinary(r)
|
||||
assert.Nil(t, err)
|
||||
r := io.NewBinReaderFromBuf(rawtxBytes)
|
||||
b.DecodeBinary(r)
|
||||
assert.Nil(t, r.Err)
|
||||
expected := map[string]bool{ // 18 trans
|
||||
|
||||
"009f61f481f47eb7478e887871e4e744669d461b13d68e04250035260171d706": false,
|
||||
|
@ -165,10 +165,10 @@ func TestBinBlockDecodeEncode(t *testing.T) {
|
|||
}
|
||||
assert.Equal(t, true, val)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
buf := io.NewBufBinWriter()
|
||||
|
||||
err = b.EncodeBinary(buf)
|
||||
assert.Nil(t, err)
|
||||
b.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
|
||||
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
|
||||
}
|
||||
|
@ -185,9 +185,9 @@ func TestBlockSizeCalculation(t *testing.T) {
|
|||
|
||||
b := Block{}
|
||||
|
||||
r := bytes.NewReader(rawBlockBytes)
|
||||
err := b.DecodeBinary(r)
|
||||
assert.Nil(t, err)
|
||||
r := io.NewBinReaderFromBuf(rawBlockBytes)
|
||||
b.DecodeBinary(r)
|
||||
assert.Nil(t, r.Err)
|
||||
|
||||
expected := []struct {
|
||||
ID string
|
||||
|
@ -225,7 +225,7 @@ func TestBlockSizeCalculation(t *testing.T) {
|
|||
txID := tx.Hash()
|
||||
assert.Equal(t, expected[i].ID, txID.ReverseString())
|
||||
|
||||
assert.Equal(t, expected[i].Size, tx.Size())
|
||||
assert.Equal(t, expected[i].Size, io.GetVarSize(tx))
|
||||
assert.Equal(t, expected[i].Type, tx.Type.String())
|
||||
assert.Equal(t, expected[i].Version, int(tx.Version))
|
||||
assert.Equal(t, expected[i].InputsLen, len(tx.Inputs))
|
||||
|
@ -250,11 +250,12 @@ func TestBlockSizeCalculation(t *testing.T) {
|
|||
assert.Equal(t, "552102486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a7021024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d2102aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e2103b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c2103b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a2102ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba5542102df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e89509357ae", hex.EncodeToString(b.Script.VerificationScript))
|
||||
assert.Equal(t, "0006d3ff96e269f599eb1b5c5a527c218439e498dcc65b63794591bbcdc0516b", b.Hash().ReverseString())
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
buf := io.NewBufBinWriter()
|
||||
|
||||
err = b.EncodeBinary(buf)
|
||||
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, buf.Len())
|
||||
assert.Equal(t, rawBlock, hex.EncodeToString(buf.Bytes()))
|
||||
assert.Equal(t, 7360, len(benc))
|
||||
assert.Equal(t, rawBlock, hex.EncodeToString(benc))
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"sync/atomic"
|
||||
|
@ -12,6 +10,7 @@ import (
|
|||
"github.com/CityOfZion/neo-go/config"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/storage"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
@ -243,9 +242,9 @@ func (bc *Blockchain) AddHeaders(headers ...*Header) (err error) {
|
|||
func (bc *Blockchain) processHeader(h *Header, batch storage.Batch, headerList *HeaderHashList) error {
|
||||
headerList.Add(h.Hash())
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
buf := io.NewBufBinWriter()
|
||||
for int(h.Index)-headerBatchCount >= int(bc.storedHeaderCount) {
|
||||
if err := headerList.Write(buf, int(bc.storedHeaderCount), headerBatchCount); err != nil {
|
||||
if err := headerList.Write(buf.BinWriter, int(bc.storedHeaderCount), headerBatchCount); err != nil {
|
||||
return err
|
||||
}
|
||||
key := storage.AppendPrefixInt(storage.IXHeaderHashList, int(bc.storedHeaderCount))
|
||||
|
@ -255,8 +254,9 @@ func (bc *Blockchain) processHeader(h *Header, batch storage.Batch, headerList *
|
|||
}
|
||||
|
||||
buf.Reset()
|
||||
if err := h.EncodeBinary(buf); err != nil {
|
||||
return err
|
||||
h.EncodeBinary(buf.BinWriter)
|
||||
if buf.Err != nil {
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
key := storage.AppendPrefix(storage.DataBlock, h.Hash().BytesReverse())
|
||||
|
@ -467,17 +467,17 @@ func (bc *Blockchain) GetTransaction(hash util.Uint256) (*transaction.Transactio
|
|||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
r := bytes.NewReader(b)
|
||||
r := io.NewBinReaderFromBuf(b)
|
||||
|
||||
var height uint32
|
||||
if err := binary.Read(r, binary.LittleEndian, &height); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
r.ReadLE(&height)
|
||||
|
||||
tx := &transaction.Transaction{}
|
||||
if err := tx.DecodeBinary(r); err != nil {
|
||||
return nil, 0, err
|
||||
tx.DecodeBinary(r)
|
||||
if r.Err != nil {
|
||||
return nil, 0, r.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(bytes.NewReader(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(bytes.NewReader(v)); err == nil && a.ScriptHash == scriptHash {
|
||||
r := io.NewBinReaderFromBuf(v)
|
||||
a.DecodeBinary(r)
|
||||
if r.Err == nil && a.ScriptHash == scriptHash {
|
||||
as = &a
|
||||
}
|
||||
})
|
||||
|
@ -628,7 +632,7 @@ func (bc *Blockchain) References(t *transaction.Transaction) map[util.Uint256]*t
|
|||
|
||||
// FeePerByte returns network fee divided by the size of the transaction
|
||||
func (bc *Blockchain) FeePerByte(t *transaction.Transaction) util.Fixed8 {
|
||||
return bc.NetworkFee(t).Div(int64(t.Size()))
|
||||
return bc.NetworkFee(t).Div(int64(io.GetVarSize(t)))
|
||||
}
|
||||
|
||||
// NetworkFee returns network fee
|
||||
|
@ -669,8 +673,8 @@ func (bc *Blockchain) GetMemPool() MemPool {
|
|||
// Verify verifies whether a transaction is bonafide or not.
|
||||
// Golang implementation of Verify method in C# (https://github.com/neo-project/neo/blob/master/neo/Network/P2P/Payloads/Transaction.cs#L270).
|
||||
func (bc *Blockchain) Verify(t *transaction.Transaction) error {
|
||||
if t.Size() > transaction.MaxTransactionSize {
|
||||
return errors.Errorf("invalid transaction size = %d. It shoud be less then MaxTransactionSize = %d", t.Size(), transaction.MaxTransactionSize)
|
||||
if io.GetVarSize(t) > transaction.MaxTransactionSize {
|
||||
return errors.Errorf("invalid transaction size = %d. It shoud be less then MaxTransactionSize = %d", io.GetVarSize(t), transaction.MaxTransactionSize)
|
||||
}
|
||||
if ok := bc.verifyInputs(t); !ok {
|
||||
return errors.New("invalid transaction's inputs")
|
||||
|
@ -921,9 +925,10 @@ func (bc *Blockchain) VerifyWitnesses(t *transaction.Transaction) error {
|
|||
}
|
||||
|
||||
func hashAndIndexToBytes(h util.Uint256, index uint32) []byte {
|
||||
buf := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(buf, index)
|
||||
return append(h.BytesReverse(), buf...)
|
||||
buf := io.NewBufBinWriter()
|
||||
buf.WriteLE(h.BytesReverse())
|
||||
buf.WriteLE(index)
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func (bc *Blockchain) secondsPerBlock() int {
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
|
||||
"github.com/CityOfZion/neo-go/config"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/storage"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -141,11 +141,11 @@ func TestGetTransaction(t *testing.T) {
|
|||
}
|
||||
assert.Equal(t, block.Index, height)
|
||||
assert.Equal(t, block.Transactions[0], tx)
|
||||
assert.Equal(t, 10, tx.Size())
|
||||
assert.Equal(t, 1, util.GetVarSize(tx.Attributes))
|
||||
assert.Equal(t, 1, util.GetVarSize(tx.Inputs))
|
||||
assert.Equal(t, 1, util.GetVarSize(tx.Outputs))
|
||||
assert.Equal(t, 1, util.GetVarSize(tx.Scripts))
|
||||
assert.Equal(t, 10, io.GetVarSize(tx))
|
||||
assert.Equal(t, 1, io.GetVarSize(tx.Attributes))
|
||||
assert.Equal(t, 1, io.GetVarSize(tx.Inputs))
|
||||
assert.Equal(t, 1, io.GetVarSize(tx.Outputs))
|
||||
assert.Equal(t, 1, io.GetVarSize(tx.Scripts))
|
||||
}
|
||||
|
||||
func newTestChain(t *testing.T) *Blockchain {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
)
|
||||
|
||||
// Header holds the head info of a block.
|
||||
|
@ -14,28 +14,20 @@ type Header struct {
|
|||
_ uint8
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (h *Header) DecodeBinary(r io.Reader) 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
|
||||
if err := binary.Read(r, binary.LittleEndian, &padding); err != nil {
|
||||
return err
|
||||
}
|
||||
r.ReadLE(&padding)
|
||||
|
||||
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.Writer) error {
|
||||
if err := h.BlockBase.EncodeBinary(w); err != nil {
|
||||
return err
|
||||
}
|
||||
return binary.Write(w, binary.LittleEndian, uint8(0))
|
||||
// EncodeBinary implements Serializable interface.
|
||||
func (h *Header) EncodeBinary(w *io.BinWriter) {
|
||||
h.BlockBase.EncodeBinary(w)
|
||||
w.WriteLE(uint8(0))
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -56,10 +55,9 @@ func (l *HeaderHashList) Slice(start, end int) []util.Uint256 {
|
|||
return l.hashes[start:end]
|
||||
}
|
||||
|
||||
// WriteTo will write n underlying hashes to the given io.Writer
|
||||
// WriteTo will write n underlying hashes to the given BinWriter
|
||||
// starting from start.
|
||||
func (l *HeaderHashList) Write(w io.Writer, start, n int) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
func (l *HeaderHashList) Write(bw *io.BinWriter, start, n int) error {
|
||||
bw.WriteVarUint(uint64(n))
|
||||
hashes := l.Slice(start, start+n)
|
||||
for _, hash := range hashes {
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestHeaderEncodeDecode(t *testing.T) {
|
||||
|
@ -25,37 +26,20 @@ func TestHeaderEncodeDecode(t *testing.T) {
|
|||
},
|
||||
}}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if err := header.EncodeBinary(buf); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
buf := io.NewBufBinWriter()
|
||||
header.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
|
||||
headerDecode := &Header{}
|
||||
if err := headerDecode.DecodeBinary(buf); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if header.Version != headerDecode.Version {
|
||||
t.Fatal("expected both versions to be equal")
|
||||
}
|
||||
if !header.PrevHash.Equals(headerDecode.PrevHash) {
|
||||
t.Fatal("expected both prev hashes to be equal")
|
||||
}
|
||||
if !header.MerkleRoot.Equals(headerDecode.MerkleRoot) {
|
||||
t.Fatal("expected both merkle roots to be equal")
|
||||
}
|
||||
if header.Index != headerDecode.Index {
|
||||
t.Fatal("expected both indexes to be equal")
|
||||
}
|
||||
if header.ConsensusData != headerDecode.ConsensusData {
|
||||
t.Fatal("expected both consensus data fields to be equal")
|
||||
}
|
||||
if !header.NextConsensus.Equals(headerDecode.NextConsensus) {
|
||||
t.Fatalf("expected both next consensus fields to be equal")
|
||||
}
|
||||
if !bytes.Equal(header.Script.InvocationScript, headerDecode.Script.InvocationScript) {
|
||||
t.Fatalf("expected equal invocation scripts %v and %v", header.Script.InvocationScript, headerDecode.Script.InvocationScript)
|
||||
}
|
||||
if !bytes.Equal(header.Script.VerificationScript, headerDecode.Script.VerificationScript) {
|
||||
t.Fatalf("expected equal verification scripts %v and %v", header.Script.VerificationScript, headerDecode.Script.VerificationScript)
|
||||
}
|
||||
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")
|
||||
assert.Equal(t, header.Index, headerDecode.Index, "expected both indexes to be equal")
|
||||
assert.Equal(t, header.ConsensusData, headerDecode.ConsensusData, "expected both consensus data fields to be equal")
|
||||
assert.Equal(t, header.NextConsensus, headerDecode.NextConsensus, "expected both next consensus fields to be equal")
|
||||
assert.Equal(t, header.Script.InvocationScript, headerDecode.Script.InvocationScript, "expected equal invocation scripts")
|
||||
assert.Equal(t, header.Script.VerificationScript, headerDecode.Script.VerificationScript, "expected equal verification scripts")
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -11,6 +10,7 @@ import (
|
|||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -63,8 +63,10 @@ func getDecodedBlock(t *testing.T, i int) *Block {
|
|||
}
|
||||
|
||||
block := &Block{}
|
||||
if err := block.DecodeBinary(bytes.NewReader(b)); err != nil {
|
||||
t.Fatal(err)
|
||||
r := io.NewBinReaderFromBuf(b)
|
||||
block.DecodeBinary(r)
|
||||
if r.Err != nil {
|
||||
t.Fatal(r.Err)
|
||||
}
|
||||
|
||||
return block
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/storage"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -21,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(bytes.NewReader(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{
|
||||
|
@ -35,10 +36,11 @@ func (s SpentCoins) getAndUpdate(store storage.Store, hash util.Uint256) (*Spent
|
|||
}
|
||||
|
||||
func (s SpentCoins) commit(b storage.Batch) error {
|
||||
buf := new(bytes.Buffer)
|
||||
buf := io.NewBufBinWriter()
|
||||
for hash, state := range s {
|
||||
if err := state.EncodeBinary(buf); 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())
|
||||
|
@ -65,9 +67,8 @@ func NewSpentCoinState(hash util.Uint256, height uint32) *SpentCoinState {
|
|||
}
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (s *SpentCoinState) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// DecodeBinary implements Serializable interface.
|
||||
func (s *SpentCoinState) DecodeBinary(br *io.BinReader) {
|
||||
br.ReadLE(&s.txHash)
|
||||
br.ReadLE(&s.txHeight)
|
||||
|
||||
|
@ -82,12 +83,10 @@ func (s *SpentCoinState) DecodeBinary(r io.Reader) error {
|
|||
br.ReadLE(&value)
|
||||
s.items[key] = value
|
||||
}
|
||||
return br.Err
|
||||
}
|
||||
|
||||
// EncodeBinary implements the Payload interface.
|
||||
func (s *SpentCoinState) EncodeBinary(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
// 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)))
|
||||
|
@ -95,5 +94,4 @@ func (s *SpentCoinState) EncodeBinary(w io.Writer) error {
|
|||
bw.WriteLE(k)
|
||||
bw.WriteLE(v)
|
||||
}
|
||||
return bw.Err
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/storage"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
@ -20,10 +20,13 @@ func TestEncodeDecodeSpentCoinState(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
assert.Nil(t, spent.EncodeBinary(buf))
|
||||
buf := io.NewBufBinWriter()
|
||||
spent.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
spentDecode := new(SpentCoinState)
|
||||
assert.Nil(t, spentDecode.DecodeBinary(buf))
|
||||
r := io.NewBinReaderFromBuf(buf.Bytes())
|
||||
spentDecode.DecodeBinary(r)
|
||||
assert.Nil(t, r.Err)
|
||||
assert.Equal(t, spent, spentDecode)
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"encoding/binary"
|
||||
"sort"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -84,7 +85,7 @@ func HeaderHashes(s Store) ([]util.Uint256, error) {
|
|||
// the given byte array.
|
||||
func read2000Uint256Hashes(b []byte) ([]util.Uint256, error) {
|
||||
r := bytes.NewReader(b)
|
||||
br := util.BinReader{R: r}
|
||||
br := io.NewBinReaderFromIO(r)
|
||||
lenHashes := br.ReadVarUint()
|
||||
hashes := make([]util.Uint256, lenHashes)
|
||||
br.ReadLE(hashes)
|
||||
|
|
|
@ -4,9 +4,8 @@ import (
|
|||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
)
|
||||
|
||||
// Attribute represents a Transaction attribute.
|
||||
|
@ -15,9 +14,8 @@ type Attribute struct {
|
|||
Data []byte
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (attr *Attribute) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// DecodeBinary implements Serializable interface.
|
||||
func (attr *Attribute) DecodeBinary(br *io.BinReader) {
|
||||
br.ReadLE(&attr.Usage)
|
||||
|
||||
// very special case
|
||||
|
@ -25,7 +23,7 @@ func (attr *Attribute) DecodeBinary(r io.Reader) 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 {
|
||||
|
@ -45,16 +43,15 @@ func (attr *Attribute) DecodeBinary(r io.Reader) 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(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
// EncodeBinary implements Serializable interface.
|
||||
func (attr *Attribute) EncodeBinary(bw *io.BinWriter) {
|
||||
bw.WriteLE(&attr.Usage)
|
||||
switch attr.Usage {
|
||||
case ECDH02, ECDH03:
|
||||
|
@ -71,27 +68,8 @@ func (attr *Attribute) EncodeBinary(w io.Writer) 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
|
||||
}
|
||||
|
||||
// Size returns the size in number bytes of the Attribute
|
||||
func (attr *Attribute) Size() int {
|
||||
sz := 1 // usage
|
||||
switch attr.Usage {
|
||||
case ContractHash, ECDH02, ECDH03, Vote,
|
||||
Hash1, Hash2, Hash3, Hash4, Hash5, Hash6, Hash7, Hash8, Hash9, Hash10, Hash11, Hash12, Hash13, Hash14, Hash15:
|
||||
sz += 32 // uint8 + 32 = size(attrUsage) + 32
|
||||
case Script:
|
||||
sz += 20 // uint8 + 20 = size(attrUsage) + 20
|
||||
case DescriptionURL:
|
||||
sz += 1 + len(attr.Data)
|
||||
default:
|
||||
sz += util.GetVarSize(attr.Data)
|
||||
}
|
||||
return sz
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json Marschaller interface
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
)
|
||||
|
||||
// ClaimTX represents a claim transaction.
|
||||
|
@ -11,43 +9,20 @@ type ClaimTX struct {
|
|||
Claims []*Input
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (tx *ClaimTX) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// 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(r); err != nil {
|
||||
return err
|
||||
}
|
||||
tx.Claims[i].DecodeBinary(br)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeBinary implements the Payload interface.
|
||||
func (tx *ClaimTX) EncodeBinary(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
// 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(w); err != nil {
|
||||
return err
|
||||
}
|
||||
claim.EncodeBinary(bw)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Size returns serialized binary size for this transaction.
|
||||
func (tx *ClaimTX) Size() int {
|
||||
sz := util.GetVarSize(uint64(len(tx.Claims)))
|
||||
for _, claim := range tx.Claims {
|
||||
sz += claim.Size()
|
||||
}
|
||||
return sz
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"io"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
)
|
||||
|
||||
// ContractTX represents a contract transaction.
|
||||
|
@ -15,17 +15,10 @@ func NewContractTX() *Transaction {
|
|||
}
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (tx *ContractTX) DecodeBinary(r io.Reader) 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.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Size returns serialized binary size for this transaction.
|
||||
func (tx *ContractTX) Size() int {
|
||||
return 0
|
||||
// EncodeBinary implements Serializable interface.
|
||||
func (tx *ContractTX) EncodeBinary(w *io.BinWriter) {
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -29,9 +29,9 @@ func TestEncodeDecodeContract(t *testing.T) {
|
|||
assert.Equal(t, "bdf6cc3b9af12a7565bda80933a75ee8cef1bc771d0d58effc08e4c8b436da79", tx.Hash().ReverseString())
|
||||
|
||||
// Encode
|
||||
buf := new(bytes.Buffer)
|
||||
buf := io.NewBufBinWriter()
|
||||
|
||||
err := tx.EncodeBinary(buf)
|
||||
assert.Equal(t, nil, err)
|
||||
tx.EncodeBinary(buf.BinWriter)
|
||||
assert.Equal(t, nil, buf.Err)
|
||||
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
)
|
||||
|
||||
// EnrollmentTX transaction represents an enrollment form, which indicates
|
||||
|
@ -16,18 +15,13 @@ type EnrollmentTX struct {
|
|||
PublicKey *keys.PublicKey
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (tx *EnrollmentTX) DecodeBinary(r io.Reader) 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.Writer) error {
|
||||
return tx.PublicKey.EncodeBinary(w)
|
||||
}
|
||||
|
||||
// Size returns serialized binary size for this transaction.
|
||||
func (tx *EnrollmentTX) Size() int {
|
||||
return len(tx.PublicKey.Bytes())
|
||||
// EncodeBinary implements Serializable interface.
|
||||
func (tx *EnrollmentTX) EncodeBinary(w *io.BinWriter) {
|
||||
tx.PublicKey.EncodeBinary(w)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -16,9 +16,9 @@ func TestEncodeDecodeEnrollment(t *testing.T) {
|
|||
assert.IsType(t, tx.Data, &EnrollmentTX{})
|
||||
assert.Equal(t, 0, int(tx.Version))
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err := tx.EncodeBinary(buf)
|
||||
buf := io.NewBufBinWriter()
|
||||
tx.EncodeBinary(buf.BinWriter)
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, nil, buf.Err)
|
||||
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -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(bytes.NewReader(b))
|
||||
assert.Nil(t, err2)
|
||||
r := io.NewBinReaderFromBuf(b)
|
||||
tx.DecodeBinary(r)
|
||||
assert.Nil(t, r.Err)
|
||||
return tx
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -15,23 +14,14 @@ type Input struct {
|
|||
PrevIndex uint16 `json:"vout"`
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (in *Input) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// 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(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
// EncodeBinary implements Serializable interface.
|
||||
func (in *Input) EncodeBinary(bw *io.BinWriter) {
|
||||
bw.WriteLE(in.PrevHash)
|
||||
bw.WriteLE(in.PrevIndex)
|
||||
return bw.Err
|
||||
}
|
||||
|
||||
// Size returns the size in bytes of the Input
|
||||
func (in Input) Size() int {
|
||||
return in.PrevHash.Size() + 2 // 2 = sizeOf uint16
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -32,33 +31,20 @@ func NewInvocationTX(script []byte) *Transaction {
|
|||
}
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (tx *InvocationTX) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// 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(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
// 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
|
||||
}
|
||||
|
||||
// Size returns serialized binary size for this transaction.
|
||||
func (tx *InvocationTX) Size() int {
|
||||
sz := util.GetVarSize(tx.Script)
|
||||
if tx.Version >= 1 {
|
||||
sz += tx.Gas.Size()
|
||||
}
|
||||
return sz
|
||||
}
|
||||
|
|
|
@ -1,24 +1,17 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"io"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
)
|
||||
|
||||
// IssueTX represents a issue transaction.
|
||||
// This TX has not special attributes.
|
||||
type IssueTX struct{}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (tx *IssueTX) DecodeBinary(r io.Reader) 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.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Size returns serialized binary size for this transaction.
|
||||
func (tx *IssueTX) Size() int {
|
||||
return 0
|
||||
// EncodeBinary implements Serializable interface.
|
||||
func (tx *IssueTX) EncodeBinary(w *io.BinWriter) {
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
)
|
||||
|
||||
// MinerTX represents a miner transaction.
|
||||
|
@ -11,17 +10,12 @@ type MinerTX struct {
|
|||
Nonce uint32
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (tx *MinerTX) DecodeBinary(r io.Reader) error {
|
||||
return binary.Read(r, binary.LittleEndian, &tx.Nonce)
|
||||
// DecodeBinary implements Serializable interface.
|
||||
func (tx *MinerTX) DecodeBinary(r *io.BinReader) {
|
||||
r.ReadLE(&tx.Nonce)
|
||||
}
|
||||
|
||||
// EncodeBinary implements the Payload interface.
|
||||
func (tx *MinerTX) EncodeBinary(w io.Writer) error {
|
||||
return binary.Write(w, binary.LittleEndian, tx.Nonce)
|
||||
}
|
||||
|
||||
// Size returns serialized binary size for this transaction.
|
||||
func (tx *MinerTX) Size() int {
|
||||
return 4 // Nonce
|
||||
// EncodeBinary implements Serializable interface.
|
||||
func (tx *MinerTX) EncodeBinary(w *io.BinWriter) {
|
||||
w.WriteLE(tx.Nonce)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -21,10 +21,10 @@ func TestEncodeDecodeMiner(t *testing.T) {
|
|||
assert.Equal(t, "a1f219dc6be4c35eca172e65e02d4591045220221b1543f1a4b67b9e9442c264", tx.Hash().ReverseString())
|
||||
|
||||
// Encode
|
||||
buf := new(bytes.Buffer)
|
||||
buf := io.NewBufBinWriter()
|
||||
|
||||
err := tx.EncodeBinary(buf)
|
||||
assert.Equal(t, nil, err)
|
||||
tx.EncodeBinary(buf.BinWriter)
|
||||
assert.Equal(t, nil, buf.Err)
|
||||
|
||||
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ package transaction
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -33,27 +33,18 @@ func NewOutput(assetID util.Uint256, amount util.Fixed8, scriptHash util.Uint160
|
|||
}
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (out *Output) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// 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(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
// 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
|
||||
}
|
||||
|
||||
// Size returns the size in bytes of the Output
|
||||
func (out *Output) Size() int {
|
||||
return out.AssetID.Size() + out.Amount.Size() + out.ScriptHash.Size()
|
||||
}
|
||||
|
||||
// MarshalJSON implements the Marshaler interface
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
// PublishTX represents a publish transaction.
|
||||
|
@ -22,9 +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(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// DecodeBinary implements Serializable interface.
|
||||
func (tx *PublishTX) DecodeBinary(br *io.BinReader) {
|
||||
tx.Script = br.ReadBytes()
|
||||
|
||||
lenParams := br.ReadVarUint()
|
||||
|
@ -50,13 +47,10 @@ func (tx *PublishTX) DecodeBinary(r io.Reader) 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(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
// 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 {
|
||||
|
@ -71,19 +65,4 @@ func (tx *PublishTX) EncodeBinary(w io.Writer) error {
|
|||
bw.WriteString(tx.Author)
|
||||
bw.WriteString(tx.Email)
|
||||
bw.WriteString(tx.Description)
|
||||
return bw.Err
|
||||
}
|
||||
|
||||
// Size returns serialized binary size for this transaction.
|
||||
func (tx *PublishTX) Size() int {
|
||||
sz := util.GetVarSize(tx.Script) + util.GetVarSize(uint64(len(tx.ParamList)))
|
||||
sz += 1 * len(tx.ParamList)
|
||||
sz++
|
||||
if tx.Version >= 1 {
|
||||
sz++
|
||||
}
|
||||
sz += util.GetVarSize(tx.Name) + util.GetVarSize(tx.CodeVersion)
|
||||
sz += util.GetVarSize(tx.Author) + util.GetVarSize(tx.Email)
|
||||
sz += util.GetVarSize(tx.Description)
|
||||
return sz
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -29,41 +28,27 @@ type RegisterTX struct {
|
|||
Admin util.Uint160
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (tx *RegisterTX) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// 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(r); err != nil {
|
||||
return err
|
||||
}
|
||||
tx.Owner.DecodeBinary(br)
|
||||
|
||||
br.ReadLE(&tx.Admin)
|
||||
return br.Err
|
||||
}
|
||||
|
||||
// EncodeBinary implements the Payload interface.
|
||||
func (tx *RegisterTX) EncodeBinary(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
// 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
|
||||
}
|
||||
|
||||
// Size returns serialized binary size for this transaction.
|
||||
func (tx *RegisterTX) Size() int {
|
||||
return 1 + util.GetVarSize(tx.Name) + tx.Amount.Size() + 1 + len(tx.Owner.Bytes()) + tx.Admin.Size()
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
@ -26,11 +26,15 @@ func TestRegisterTX(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
assert.Nil(t, tx.EncodeBinary(buf))
|
||||
buf := io.NewBufBinWriter()
|
||||
tx.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
|
||||
b := buf.Bytes()
|
||||
txDecode := &Transaction{}
|
||||
assert.Nil(t, txDecode.DecodeBinary(buf))
|
||||
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)
|
||||
|
@ -45,7 +49,9 @@ func TestDecodeRegisterTXFromRawString(t *testing.T) {
|
|||
}
|
||||
|
||||
tx := &Transaction{}
|
||||
assert.Nil(t, tx.DecodeBinary(bytes.NewReader(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)
|
||||
|
@ -56,10 +62,14 @@ func TestDecodeRegisterTXFromRawString(t *testing.T) {
|
|||
assert.Equal(t, "Abf2qMs1pzQb8kYk9RuxtUb9jtRKJVuBJt", crypto.AddressFromUint160(txData.Admin))
|
||||
assert.Equal(t, "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", tx.Hash().ReverseString())
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
assert.Nil(t, tx.EncodeBinary(buf))
|
||||
buf := io.NewBufBinWriter()
|
||||
tx.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
benc := buf.Bytes()
|
||||
|
||||
txDecode := &Transaction{}
|
||||
assert.Nil(t, txDecode.DecodeBinary(buf))
|
||||
encreader := io.NewBinReaderFromBuf(benc)
|
||||
txDecode.DecodeBinary(encreader)
|
||||
assert.Nil(t, encreader.Err)
|
||||
assert.Equal(t, tx, txDecode)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
)
|
||||
|
||||
// StateTX represents a state transaction.
|
||||
|
@ -11,44 +9,20 @@ type StateTX struct {
|
|||
Descriptors []*StateDescriptor
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (tx *StateTX) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
lenDesc := br.ReadVarUint()
|
||||
if br.Err != nil {
|
||||
return br.Err
|
||||
}
|
||||
// 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{}
|
||||
if err := tx.Descriptors[i].DecodeBinary(r); err != nil {
|
||||
return err
|
||||
}
|
||||
tx.Descriptors[i].DecodeBinary(r)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeBinary implements the Payload interface.
|
||||
func (tx *StateTX) EncodeBinary(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
bw.WriteVarUint(uint64(len(tx.Descriptors)))
|
||||
if bw.Err != nil {
|
||||
return bw.Err
|
||||
}
|
||||
// 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 nil
|
||||
}
|
||||
|
||||
// Size returns serialized binary size for this transaction.
|
||||
func (tx *StateTX) Size() int {
|
||||
sz := util.GetVarSize(uint64(len(tx.Descriptors)))
|
||||
for _, desc := range tx.Descriptors {
|
||||
sz += desc.Size()
|
||||
}
|
||||
return sz
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
)
|
||||
|
||||
// DescStateType represents the type of StateDescriptor.
|
||||
|
@ -23,29 +21,19 @@ type StateDescriptor struct {
|
|||
Field string
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (s *StateDescriptor) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
br.ReadLE(&s.Type)
|
||||
// DecodeBinary implements Serializable interface.
|
||||
func (s *StateDescriptor) DecodeBinary(r *io.BinReader) {
|
||||
r.ReadLE(&s.Type)
|
||||
|
||||
s.Key = br.ReadBytes()
|
||||
s.Value = br.ReadBytes()
|
||||
s.Field = br.ReadString()
|
||||
|
||||
return br.Err
|
||||
s.Key = r.ReadBytes()
|
||||
s.Value = r.ReadBytes()
|
||||
s.Field = r.ReadString()
|
||||
}
|
||||
|
||||
// EncodeBinary implements the Payload interface.
|
||||
func (s *StateDescriptor) EncodeBinary(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
bw.WriteLE(s.Type)
|
||||
bw.WriteBytes(s.Key)
|
||||
bw.WriteBytes(s.Value)
|
||||
bw.WriteString(s.Field)
|
||||
return bw.Err
|
||||
}
|
||||
|
||||
// Size returns serialized binary size for state descriptor.
|
||||
func (s *StateDescriptor) Size() int {
|
||||
return 1 + util.GetVarSize(s.Key) + util.GetVarSize(s.Value) + util.GetVarSize(s.Field)
|
||||
// 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)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -30,11 +30,9 @@ func TestEncodeDecodeState(t *testing.T) {
|
|||
assert.Equal(t, Validator, descriptor.Type)
|
||||
|
||||
// Encode
|
||||
buf := io.NewBufBinWriter()
|
||||
tx.EncodeBinary(buf.BinWriter)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
err := tx.EncodeBinary(buf)
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, nil, buf.Err)
|
||||
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -76,174 +74,126 @@ func (t *Transaction) AddInput(in *Input) {
|
|||
t.Inputs = append(t.Inputs, in)
|
||||
}
|
||||
|
||||
// DecodeBinary implements the payload interface.
|
||||
func (t *Transaction) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// 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(r); 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(r); 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(r); 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(r); 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(r); 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.Reader) 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(w io.Writer) error {
|
||||
if err := t.encodeHashableFields(w); err != nil {
|
||||
return err
|
||||
}
|
||||
bw := util.BinWriter{W: w}
|
||||
// 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(w); 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(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
|
||||
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(w); 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(w); 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(w); 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(w); err != nil {
|
||||
return err
|
||||
}
|
||||
out.EncodeBinary(bw)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// createHash creates the hash of the transaction.
|
||||
func (t *Transaction) createHash() error {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := t.encodeHashableFields(buf); err != nil {
|
||||
return err
|
||||
buf := io.NewBufBinWriter()
|
||||
t.encodeHashableFields(buf.BinWriter)
|
||||
if buf.Err != nil {
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
t.hash = hash.DoubleSha256(buf.Bytes())
|
||||
|
@ -269,22 +219,12 @@ func (t Transaction) GroupOutputByAssetID() map[util.Uint256][]*Output {
|
|||
return m
|
||||
}
|
||||
|
||||
// Size returns the size of the transaction in term of bytes
|
||||
func (t *Transaction) Size() int {
|
||||
attrSize := util.GetVarSize(t.Attributes)
|
||||
inputSize := util.GetVarSize(t.Inputs)
|
||||
outputSize := util.GetVarSize(t.Outputs)
|
||||
witnesSize := util.GetVarSize(t.Scripts)
|
||||
// uint8 + uint8 + attrSize + inputSize + outputSize + witnesSize
|
||||
return 2 + attrSize + inputSize + outputSize + witnesSize + t.Data.Size()
|
||||
}
|
||||
|
||||
// Bytes convert the transaction to []byte
|
||||
func (t *Transaction) Bytes() []byte {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := t.EncodeBinary(buf); err != nil {
|
||||
buf := io.NewBufBinWriter()
|
||||
t.EncodeBinary(buf.BinWriter)
|
||||
if buf.Err != nil {
|
||||
return nil
|
||||
}
|
||||
return buf.Bytes()
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -27,15 +27,15 @@ func TestWitnessEncodeDecode(t *testing.T) {
|
|||
VerificationScript: verif,
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if err := wit.EncodeBinary(buf); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
buf := io.NewBufBinWriter()
|
||||
wit.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
|
||||
benc := buf.Bytes()
|
||||
witDecode := &Witness{}
|
||||
if err := witDecode.DecodeBinary(buf); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
encreader := io.NewBinReaderFromBuf(benc)
|
||||
witDecode.DecodeBinary(encreader)
|
||||
assert.Nil(t, encreader.Err)
|
||||
t.Log(len(witDecode.VerificationScript))
|
||||
t.Log(len(witDecode.InvocationScript))
|
||||
|
||||
|
@ -61,10 +61,9 @@ func TestDecodeEncodeClaimTX(t *testing.T) {
|
|||
assert.Equal(t, invoc, hex.EncodeToString(tx.Scripts[0].InvocationScript))
|
||||
assert.Equal(t, verif, hex.EncodeToString(tx.Scripts[0].VerificationScript))
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if err := tx.EncodeBinary(buf); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
buf := io.NewBufBinWriter()
|
||||
tx.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
assert.Equal(t, rawClaimTX, hex.EncodeToString(buf.Bytes()))
|
||||
|
||||
hash := "2c6a45547b3898318e400e541628990a07acb00f3b9a15a8e966ae49525304da"
|
||||
|
@ -90,10 +89,10 @@ func TestDecodeEncodeInvocationTX(t *testing.T) {
|
|||
assert.Equal(t, invoc, hex.EncodeToString(tx.Scripts[0].InvocationScript))
|
||||
assert.Equal(t, verif, hex.EncodeToString(tx.Scripts[0].VerificationScript))
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if err := tx.EncodeBinary(buf); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
buf := io.NewBufBinWriter()
|
||||
tx.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
|
||||
assert.Equal(t, rawInvocationTX, hex.EncodeToString(buf.Bytes()))
|
||||
}
|
||||
|
||||
|
@ -145,8 +144,8 @@ func TestDecodePublishTX(t *testing.T) {
|
|||
assert.Equal(t, expectedTX.Type, actualTX.Type)
|
||||
assert.Equal(t, expectedTX.Version, actualTX.Version)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err := actualTX.EncodeBinary(buf)
|
||||
assert.Nil(t, err)
|
||||
buf := io.NewBufBinWriter()
|
||||
actualTX.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
assert.Equal(t, rawPublishTX, hex.EncodeToString(buf.Bytes()))
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
package transaction
|
||||
|
||||
import "io"
|
||||
import "github.com/CityOfZion/neo-go/pkg/io"
|
||||
|
||||
// TXer is interface that can act as the underlying data of
|
||||
// a transaction.
|
||||
type TXer interface {
|
||||
DecodeBinary(io.Reader) error
|
||||
EncodeBinary(io.Writer) error
|
||||
Size() int
|
||||
io.Serializable
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ package transaction
|
|||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -15,23 +15,16 @@ type Witness struct {
|
|||
VerificationScript []byte
|
||||
}
|
||||
|
||||
// DecodeBinary implements the payload interface.
|
||||
func (w *Witness) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
|
||||
// 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(writer io.Writer) error {
|
||||
bw := util.BinWriter{W: writer}
|
||||
|
||||
// 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.
|
||||
|
@ -44,11 +37,6 @@ func (w *Witness) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(data)
|
||||
}
|
||||
|
||||
// Size returns the size in bytes of the Witness.
|
||||
func (w *Witness) Size() int {
|
||||
return util.GetVarSize(w.InvocationScript) + util.GetVarSize(w.VerificationScript)
|
||||
}
|
||||
|
||||
// ScriptHash returns the hash of the VerificationScript.
|
||||
func (w Witness) ScriptHash() util.Uint160 {
|
||||
return hash.Hash160(w.VerificationScript)
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/storage"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -22,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(bytes.NewReader(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{
|
||||
|
@ -53,10 +54,11 @@ func NewUnspentCoinState(n int) *UnspentCoinState {
|
|||
|
||||
// commit writes all unspent coin states to the given Batch.
|
||||
func (u UnspentCoins) commit(b storage.Batch) error {
|
||||
buf := new(bytes.Buffer)
|
||||
buf := io.NewBufBinWriter()
|
||||
for hash, state := range u {
|
||||
if err := state.EncodeBinary(buf); 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,19 +67,16 @@ func (u UnspentCoins) commit(b storage.Batch) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// EncodeBinary encodes UnspentCoinState to the given io.Writer.
|
||||
func (s *UnspentCoinState) EncodeBinary(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
// EncodeBinary encodes UnspentCoinState to the given BinWriter.
|
||||
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 io.Reader.
|
||||
func (s *UnspentCoinState) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// DecodeBinary decodes UnspentCoinState from the given BinReader.
|
||||
func (s *UnspentCoinState) DecodeBinary(br *io.BinReader) {
|
||||
lenStates := br.ReadVarUint()
|
||||
s.states = make([]CoinState, lenStates)
|
||||
for i := 0; i < int(lenStates); i++ {
|
||||
|
@ -85,7 +84,6 @@ func (s *UnspentCoinState) DecodeBinary(r io.Reader) error {
|
|||
br.ReadLE(&state)
|
||||
s.states[i] = CoinState(state)
|
||||
}
|
||||
return br.Err
|
||||
}
|
||||
|
||||
// IsDoubleSpend verifies that the input transactions are not double spent.
|
||||
|
@ -98,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(bytes.NewReader(b)); err != nil {
|
||||
r := io.NewBinReaderFromBuf(b)
|
||||
unspent.DecodeBinary(r)
|
||||
if r.Err != nil {
|
||||
return false
|
||||
}
|
||||
if unspent == nil {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/storage"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -19,10 +19,13 @@ func TestDecodeEncodeUnspentCoinState(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
assert.Nil(t, unspent.EncodeBinary(buf))
|
||||
buf := io.NewBufBinWriter()
|
||||
unspent.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
unspentDecode := &UnspentCoinState{}
|
||||
assert.Nil(t, unspentDecode.DecodeBinary(buf))
|
||||
r := io.NewBinReaderFromBuf(buf.Bytes())
|
||||
unspentDecode.DecodeBinary(r)
|
||||
assert.Nil(t, r.Err)
|
||||
}
|
||||
|
||||
func TestCommitUnspentCoins(t *testing.T) {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"time"
|
||||
|
||||
"github.com/CityOfZion/neo-go/config"
|
||||
|
@ -10,6 +8,7 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||
|
@ -181,11 +180,9 @@ func headerSliceReverse(dest []*Header) {
|
|||
// storeAsCurrentBlock stores the given block witch prefix
|
||||
// SYSCurrentBlock.
|
||||
func storeAsCurrentBlock(batch storage.Batch, block *Block) {
|
||||
buf := new(bytes.Buffer)
|
||||
buf.Write(block.Hash().BytesReverse())
|
||||
b := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(b, block.Index)
|
||||
buf.Write(b)
|
||||
buf := io.NewBufBinWriter()
|
||||
buf.WriteLE(block.Hash().BytesReverse())
|
||||
buf.WriteLE(block.Index)
|
||||
batch.Put(storage.SYSCurrentBlock.Bytes(), buf.Bytes())
|
||||
}
|
||||
|
||||
|
@ -193,17 +190,18 @@ func storeAsCurrentBlock(batch storage.Batch, block *Block) {
|
|||
func storeAsBlock(batch storage.Batch, block *Block, sysFee uint32) error {
|
||||
var (
|
||||
key = storage.AppendPrefix(storage.DataBlock, block.Hash().BytesReverse())
|
||||
buf = new(bytes.Buffer)
|
||||
buf = io.NewBufBinWriter()
|
||||
)
|
||||
|
||||
b := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(b, sysFee)
|
||||
|
||||
// sysFee needs to be handled somehow
|
||||
// buf.WriteLE(sysFee)
|
||||
b, err := block.Trim()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf.Write(b)
|
||||
buf.WriteLE(b)
|
||||
if buf.Err != nil {
|
||||
return buf.Err
|
||||
}
|
||||
batch.Put(key, buf.Bytes())
|
||||
return nil
|
||||
}
|
||||
|
@ -211,15 +209,12 @@ func storeAsBlock(batch storage.Batch, block *Block, sysFee uint32) error {
|
|||
// storeAsTransaction stores the given TX as DataTransaction.
|
||||
func storeAsTransaction(batch storage.Batch, tx *transaction.Transaction, index uint32) error {
|
||||
key := storage.AppendPrefix(storage.DataTransaction, tx.Hash().BytesReverse())
|
||||
buf := new(bytes.Buffer)
|
||||
if err := tx.EncodeBinary(buf); err != nil {
|
||||
return err
|
||||
buf := io.NewBufBinWriter()
|
||||
buf.WriteLE(index)
|
||||
tx.EncodeBinary(buf.BinWriter)
|
||||
if buf.Err != nil {
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
dest := make([]byte, buf.Len()+4)
|
||||
binary.LittleEndian.PutUint32(dest[:4], index)
|
||||
copy(dest[4:], buf.Bytes())
|
||||
batch.Put(key, dest)
|
||||
|
||||
batch.Put(key, buf.Bytes())
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -5,14 +5,13 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/x509"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -51,8 +50,10 @@ func NewPublicKeyFromString(s string) (*PublicKey, error) {
|
|||
}
|
||||
|
||||
pubKey := new(PublicKey)
|
||||
if err := pubKey.DecodeBinary(bytes.NewReader(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,69 +123,70 @@ 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 {
|
||||
var datab []byte
|
||||
copy(datab, data)
|
||||
b := bytes.NewBuffer(datab)
|
||||
return p.DecodeBinary(b)
|
||||
b := io.NewBinReaderFromBuf(data)
|
||||
p.DecodeBinary(b)
|
||||
return b.Err
|
||||
}
|
||||
|
||||
// DecodeBinary decodes a PublicKey from the given io.Reader.
|
||||
func (p *PublicKey) DecodeBinary(r io.Reader) error {
|
||||
// DecodeBinary decodes a PublicKey from the given BinReader.
|
||||
func (p *PublicKey) DecodeBinary(r *io.BinReader) {
|
||||
var prefix uint8
|
||||
var x, y *big.Int
|
||||
var err error
|
||||
|
||||
if err = binary.Read(r, binary.LittleEndian, &prefix); err != nil {
|
||||
return err
|
||||
r.ReadLE(&prefix)
|
||||
if r.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Infinity
|
||||
switch prefix {
|
||||
case 0x00:
|
||||
// noop, initialized to nil
|
||||
return nil
|
||||
return
|
||||
case 0x02, 0x03:
|
||||
// Compressed public keys
|
||||
xbytes := make([]byte, 32)
|
||||
if _, err := io.ReadFull(r, xbytes); err != nil {
|
||||
return err
|
||||
r.ReadLE(xbytes)
|
||||
if r.Err != nil {
|
||||
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)
|
||||
ybytes := make([]byte, 32)
|
||||
if _, err = io.ReadFull(r, xbytes); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = io.ReadFull(r, ybytes); err != nil {
|
||||
return err
|
||||
r.ReadLE(xbytes)
|
||||
r.ReadLE(ybytes)
|
||||
if r.Err != nil {
|
||||
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 io.Writer.
|
||||
func (p *PublicKey) EncodeBinary(w io.Writer) error {
|
||||
return binary.Write(w, binary.LittleEndian, p.Bytes())
|
||||
// EncodeBinary encodes a PublicKey to the given BinWriter.
|
||||
func (p *PublicKey) EncodeBinary(w *io.BinWriter) {
|
||||
w.WriteLE(p.Bytes())
|
||||
}
|
||||
|
||||
// Signature returns a NEO-specific hash of the key.
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
package keys
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEncodeDecodeInfinity(t *testing.T) {
|
||||
key := &PublicKey{}
|
||||
buf := new(bytes.Buffer)
|
||||
assert.Nil(t, key.EncodeBinary(buf))
|
||||
assert.Equal(t, 1, buf.Len())
|
||||
buf := io.NewBufBinWriter()
|
||||
key.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
b := buf.Bytes()
|
||||
assert.Equal(t, 1, len(b))
|
||||
|
||||
keyDecode := &PublicKey{}
|
||||
assert.Nil(t, keyDecode.DecodeBinary(buf))
|
||||
assert.Nil(t, keyDecode.DecodeBytes(b))
|
||||
assert.Equal(t, []byte{0x00}, keyDecode.Bytes())
|
||||
}
|
||||
|
||||
|
@ -24,11 +26,13 @@ func TestEncodeDecodePublicKey(t *testing.T) {
|
|||
k, err := NewPrivateKey()
|
||||
assert.Nil(t, err)
|
||||
p := k.PublicKey()
|
||||
buf := new(bytes.Buffer)
|
||||
assert.Nil(t, p.EncodeBinary(buf))
|
||||
buf := io.NewBufBinWriter()
|
||||
p.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
b := buf.Bytes()
|
||||
|
||||
pDecode := &PublicKey{}
|
||||
assert.Nil(t, pDecode.DecodeBinary(buf))
|
||||
assert.Nil(t, pDecode.DecodeBytes(b))
|
||||
assert.Equal(t, p.X, pDecode.X)
|
||||
}
|
||||
}
|
||||
|
|
39
pkg/io/binaryBufWriter.go
Normal file
39
pkg/io/binaryBufWriter.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
package io
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// BufBinWriter is an additional layer on top of BinWriter that
|
||||
// automatically creates buffer to write into that you can get after all
|
||||
// writes via Bytes().
|
||||
type BufBinWriter struct {
|
||||
*BinWriter
|
||||
buf *bytes.Buffer
|
||||
}
|
||||
|
||||
// NewBufBinWriter makes a BufBinWriter with an empty byte buffer.
|
||||
func NewBufBinWriter() *BufBinWriter {
|
||||
b := new(bytes.Buffer)
|
||||
return &BufBinWriter{BinWriter: NewBinWriterFromIO(b), buf: b}
|
||||
}
|
||||
|
||||
// Bytes returns resulting buffer and makes future writes return an error.
|
||||
func (bw *BufBinWriter) Bytes() []byte {
|
||||
if bw.Err != nil {
|
||||
return nil
|
||||
}
|
||||
bw.Err = errors.New("buffer already drained")
|
||||
return bw.buf.Bytes()
|
||||
}
|
||||
|
||||
// Reset resets the state of the buffer, making it usable again. It can
|
||||
// make buffer usage somewhat more efficient, because you don't need to
|
||||
// create it again, but beware that the buffer is gonna be the same as the one
|
||||
// returned by Bytes(), so if you need that data after Reset() you have to copy
|
||||
// it yourself.
|
||||
func (bw *BufBinWriter) Reset() {
|
||||
bw.Err = nil
|
||||
bw.buf.Reset()
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package util
|
||||
package io
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
@ -8,17 +9,28 @@ import (
|
|||
//BinReader is a convenient wrapper around a io.Reader and err object
|
||||
// Used to simplify error handling when reading into a struct with many fields
|
||||
type BinReader struct {
|
||||
R io.Reader
|
||||
r io.Reader
|
||||
Err error
|
||||
}
|
||||
|
||||
// NewBinReaderFromIO makes a BinReader from io.Reader.
|
||||
func NewBinReaderFromIO(ior io.Reader) *BinReader {
|
||||
return &BinReader{r: ior}
|
||||
}
|
||||
|
||||
// NewBinReaderFromBuf makes a BinReader from byte buffer.
|
||||
func NewBinReaderFromBuf(b []byte) *BinReader {
|
||||
r := bytes.NewReader(b)
|
||||
return NewBinReaderFromIO(r)
|
||||
}
|
||||
|
||||
// ReadLE reads from the underlying io.Reader
|
||||
// into the interface v in little-endian format
|
||||
func (r *BinReader) ReadLE(v interface{}) {
|
||||
if r.Err != nil {
|
||||
return
|
||||
}
|
||||
r.Err = binary.Read(r.R, binary.LittleEndian, v)
|
||||
r.Err = binary.Read(r.r, binary.LittleEndian, v)
|
||||
}
|
||||
|
||||
// ReadBE reads from the underlying io.Reader
|
||||
|
@ -27,7 +39,7 @@ func (r *BinReader) ReadBE(v interface{}) {
|
|||
if r.Err != nil {
|
||||
return
|
||||
}
|
||||
r.Err = binary.Read(r.R, binary.BigEndian, v)
|
||||
r.Err = binary.Read(r.r, binary.BigEndian, v)
|
||||
}
|
||||
|
||||
// ReadVarUint reads a variable-length-encoded integer from the
|
||||
|
@ -38,21 +50,21 @@ func (r *BinReader) ReadVarUint() uint64 {
|
|||
}
|
||||
|
||||
var b uint8
|
||||
r.Err = binary.Read(r.R, binary.LittleEndian, &b)
|
||||
r.Err = binary.Read(r.r, binary.LittleEndian, &b)
|
||||
|
||||
if b == 0xfd {
|
||||
var v uint16
|
||||
r.Err = binary.Read(r.R, binary.LittleEndian, &v)
|
||||
r.Err = binary.Read(r.r, binary.LittleEndian, &v)
|
||||
return uint64(v)
|
||||
}
|
||||
if b == 0xfe {
|
||||
var v uint32
|
||||
r.Err = binary.Read(r.R, binary.LittleEndian, &v)
|
||||
r.Err = binary.Read(r.r, binary.LittleEndian, &v)
|
||||
return uint64(v)
|
||||
}
|
||||
if b == 0xff {
|
||||
var v uint64
|
||||
r.Err = binary.Read(r.R, binary.LittleEndian, &v)
|
||||
r.Err = binary.Read(r.r, binary.LittleEndian, &v)
|
||||
return v
|
||||
}
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
package util
|
||||
package io
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
|
@ -10,16 +9,21 @@ import (
|
|||
// Used to simplify error handling when writing into a io.Writer
|
||||
// from a struct with many fields
|
||||
type BinWriter struct {
|
||||
W io.Writer
|
||||
w io.Writer
|
||||
Err error
|
||||
}
|
||||
|
||||
// NewBinWriterFromIO makes a BinWriter from io.Writer.
|
||||
func NewBinWriterFromIO(iow io.Writer) *BinWriter {
|
||||
return &BinWriter{w: iow}
|
||||
}
|
||||
|
||||
// WriteLE writes into the underlying io.Writer from an object v in little-endian format
|
||||
func (w *BinWriter) WriteLE(v interface{}) {
|
||||
if w.Err != nil {
|
||||
return
|
||||
}
|
||||
w.Err = binary.Write(w.W, binary.LittleEndian, v)
|
||||
w.Err = binary.Write(w.w, binary.LittleEndian, v)
|
||||
}
|
||||
|
||||
// WriteBE writes into the underlying io.Writer from an object v in big-endian format
|
||||
|
@ -27,7 +31,7 @@ func (w *BinWriter) WriteBE(v interface{}) {
|
|||
if w.Err != nil {
|
||||
return
|
||||
}
|
||||
w.Err = binary.Write(w.W, binary.BigEndian, v)
|
||||
w.Err = binary.Write(w.w, binary.BigEndian, v)
|
||||
}
|
||||
|
||||
// WriteVarUint writes a uint64 into the underlying writer using variable-length encoding
|
||||
|
@ -36,33 +40,24 @@ func (w *BinWriter) WriteVarUint(val uint64) {
|
|||
return
|
||||
}
|
||||
|
||||
if val < 0 {
|
||||
w.Err = errors.New("value out of range")
|
||||
return
|
||||
}
|
||||
|
||||
if w.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if val < 0xfd {
|
||||
w.Err = binary.Write(w.W, binary.LittleEndian, uint8(val))
|
||||
w.Err = binary.Write(w.w, binary.LittleEndian, uint8(val))
|
||||
return
|
||||
}
|
||||
if val < 0xFFFF {
|
||||
w.Err = binary.Write(w.W, binary.LittleEndian, byte(0xfd))
|
||||
w.Err = binary.Write(w.W, binary.LittleEndian, uint16(val))
|
||||
w.Err = binary.Write(w.w, binary.LittleEndian, byte(0xfd))
|
||||
w.Err = binary.Write(w.w, binary.LittleEndian, uint16(val))
|
||||
return
|
||||
}
|
||||
if val < 0xFFFFFFFF {
|
||||
w.Err = binary.Write(w.W, binary.LittleEndian, byte(0xfe))
|
||||
w.Err = binary.Write(w.W, binary.LittleEndian, uint32(val))
|
||||
w.Err = binary.Write(w.w, binary.LittleEndian, byte(0xfe))
|
||||
w.Err = binary.Write(w.w, binary.LittleEndian, uint32(val))
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
w.Err = binary.Write(w.W, binary.LittleEndian, byte(0xff))
|
||||
w.Err = binary.Write(w.W, binary.LittleEndian, val)
|
||||
w.Err = binary.Write(w.w, binary.LittleEndian, byte(0xff))
|
||||
w.Err = binary.Write(w.w, binary.LittleEndian, val)
|
||||
|
||||
}
|
||||
|
193
pkg/io/binaryrw_test.go
Normal file
193
pkg/io/binaryrw_test.go
Normal file
|
@ -0,0 +1,193 @@
|
|||
package io
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// mocks io.Reader and io.Writer, always fails to Write() or Read().
|
||||
type badRW struct{}
|
||||
|
||||
func (w *badRW) Write(p []byte) (int, error) {
|
||||
return 0, errors.New("it always fails")
|
||||
}
|
||||
|
||||
func (w *badRW) Read(p []byte) (int, error) {
|
||||
return w.Write(p)
|
||||
}
|
||||
|
||||
func TestWriteLE(t *testing.T) {
|
||||
var (
|
||||
val uint32 = 0xdeadbeef
|
||||
readval uint32
|
||||
bin []byte = []byte{0xef, 0xbe, 0xad, 0xde}
|
||||
)
|
||||
bw := NewBufBinWriter()
|
||||
bw.WriteLE(val)
|
||||
assert.Nil(t, bw.Err)
|
||||
wrotebin := bw.Bytes()
|
||||
assert.Equal(t, wrotebin, bin)
|
||||
br := NewBinReaderFromBuf(bin)
|
||||
br.ReadLE(&readval)
|
||||
assert.Nil(t, br.Err)
|
||||
assert.Equal(t, val, readval)
|
||||
}
|
||||
|
||||
func TestWriteBE(t *testing.T) {
|
||||
var (
|
||||
val uint32 = 0xdeadbeef
|
||||
readval uint32
|
||||
bin []byte = []byte{0xde, 0xad, 0xbe, 0xef}
|
||||
)
|
||||
bw := NewBufBinWriter()
|
||||
bw.WriteBE(val)
|
||||
assert.Nil(t, bw.Err)
|
||||
wrotebin := bw.Bytes()
|
||||
assert.Equal(t, wrotebin, bin)
|
||||
br := NewBinReaderFromBuf(bin)
|
||||
br.ReadBE(&readval)
|
||||
assert.Nil(t, br.Err)
|
||||
assert.Equal(t, val, readval)
|
||||
}
|
||||
|
||||
func TestWriterErrHandling(t *testing.T) {
|
||||
var badio = &badRW{}
|
||||
bw := NewBinWriterFromIO(badio)
|
||||
bw.WriteLE(uint32(0))
|
||||
assert.NotNil(t, bw.Err)
|
||||
// these should work (without panic), preserving the Err
|
||||
bw.WriteLE(uint32(0))
|
||||
bw.WriteBE(uint32(0))
|
||||
bw.WriteVarUint(0)
|
||||
bw.WriteBytes([]byte{0x55, 0xaa})
|
||||
bw.WriteString("neo")
|
||||
assert.NotNil(t, bw.Err)
|
||||
}
|
||||
|
||||
func TestReaderErrHandling(t *testing.T) {
|
||||
var (
|
||||
i uint32 = 0xdeadbeef
|
||||
iorig = i
|
||||
badio = &badRW{}
|
||||
)
|
||||
br := NewBinReaderFromIO(badio)
|
||||
br.ReadLE(&i)
|
||||
assert.NotNil(t, br.Err)
|
||||
// i shouldn't change
|
||||
assert.Equal(t, i, iorig)
|
||||
// these should work (without panic), preserving the Err
|
||||
br.ReadLE(&i)
|
||||
br.ReadBE(&i)
|
||||
assert.Equal(t, i, iorig)
|
||||
val := br.ReadVarUint()
|
||||
assert.Equal(t, val, uint64(0))
|
||||
b := br.ReadBytes()
|
||||
assert.Equal(t, b, []byte{})
|
||||
s := br.ReadString()
|
||||
assert.Equal(t, s, "")
|
||||
assert.NotNil(t, br.Err)
|
||||
}
|
||||
|
||||
func TestBufBinWriterErr(t *testing.T) {
|
||||
bw := NewBufBinWriter()
|
||||
bw.WriteLE(uint32(0))
|
||||
assert.Nil(t, bw.Err)
|
||||
// inject error
|
||||
bw.Err = errors.New("oopsie")
|
||||
res := bw.Bytes()
|
||||
assert.NotNil(t, bw.Err)
|
||||
assert.Nil(t, res)
|
||||
}
|
||||
|
||||
func TestBufBinWriterReset(t *testing.T) {
|
||||
bw := NewBufBinWriter()
|
||||
for i := 0; i < 3; i++ {
|
||||
bw.WriteLE(uint32(i))
|
||||
assert.Nil(t, bw.Err)
|
||||
_ = bw.Bytes()
|
||||
assert.NotNil(t, bw.Err)
|
||||
bw.Reset()
|
||||
assert.Nil(t, bw.Err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteString(t *testing.T) {
|
||||
var (
|
||||
str string = "teststring"
|
||||
)
|
||||
bw := NewBufBinWriter()
|
||||
bw.WriteString(str)
|
||||
assert.Nil(t, bw.Err)
|
||||
wrotebin := bw.Bytes()
|
||||
// +1 byte for length
|
||||
assert.Equal(t, len(wrotebin), len(str)+1)
|
||||
br := NewBinReaderFromBuf(wrotebin)
|
||||
readstr := br.ReadString()
|
||||
assert.Nil(t, br.Err)
|
||||
assert.Equal(t, str, readstr)
|
||||
}
|
||||
|
||||
func TestWriteVarUint1(t *testing.T) {
|
||||
var (
|
||||
val = uint64(1)
|
||||
)
|
||||
bw := NewBufBinWriter()
|
||||
bw.WriteVarUint(val)
|
||||
assert.Nil(t, bw.Err)
|
||||
buf := bw.Bytes()
|
||||
assert.Equal(t, 1, len(buf))
|
||||
br := NewBinReaderFromBuf(buf)
|
||||
res := br.ReadVarUint()
|
||||
assert.Nil(t, br.Err)
|
||||
assert.Equal(t, val, res)
|
||||
}
|
||||
|
||||
func TestWriteVarUint1000(t *testing.T) {
|
||||
var (
|
||||
val = uint64(1000)
|
||||
)
|
||||
bw := NewBufBinWriter()
|
||||
bw.WriteVarUint(val)
|
||||
assert.Nil(t, bw.Err)
|
||||
buf := bw.Bytes()
|
||||
assert.Equal(t, 3, len(buf))
|
||||
assert.Equal(t, byte(0xfd), buf[0])
|
||||
br := NewBinReaderFromBuf(buf)
|
||||
res := br.ReadVarUint()
|
||||
assert.Nil(t, br.Err)
|
||||
assert.Equal(t, val, res)
|
||||
}
|
||||
|
||||
func TestWriteVarUint100000(t *testing.T) {
|
||||
var (
|
||||
val = uint64(100000)
|
||||
)
|
||||
bw := NewBufBinWriter()
|
||||
bw.WriteVarUint(val)
|
||||
assert.Nil(t, bw.Err)
|
||||
buf := bw.Bytes()
|
||||
assert.Equal(t, 5, len(buf))
|
||||
assert.Equal(t, byte(0xfe), buf[0])
|
||||
br := NewBinReaderFromBuf(buf)
|
||||
res := br.ReadVarUint()
|
||||
assert.Nil(t, br.Err)
|
||||
assert.Equal(t, val, res)
|
||||
}
|
||||
|
||||
func TestWriteVarUint100000000000(t *testing.T) {
|
||||
var (
|
||||
val = uint64(1000000000000)
|
||||
)
|
||||
bw := NewBufBinWriter()
|
||||
bw.WriteVarUint(val)
|
||||
assert.Nil(t, bw.Err)
|
||||
buf := bw.Bytes()
|
||||
assert.Equal(t, 9, len(buf))
|
||||
assert.Equal(t, byte(0xff), buf[0])
|
||||
br := NewBinReaderFromBuf(buf)
|
||||
res := br.ReadVarUint()
|
||||
assert.Nil(t, br.Err)
|
||||
assert.Equal(t, val, res)
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
package io
|
||||
|
||||
import "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 {
|
||||
Size() int
|
||||
DecodeBinary(io.Reader) error
|
||||
EncodeBinary(io.Writer) error
|
||||
DecodeBinary(*BinReader)
|
||||
EncodeBinary(*BinWriter)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package util
|
||||
package io
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -19,6 +17,20 @@ var (
|
|||
i64 int64
|
||||
)
|
||||
|
||||
// This structure is used to calculate the wire size of the serializable
|
||||
// structure. It's an io.Writer that doesn't do any real writes, but instead
|
||||
// just counts the number of bytes to be written.
|
||||
type counterWriter struct {
|
||||
counter int
|
||||
}
|
||||
|
||||
// Write implements the io.Writer interface
|
||||
func (cw *counterWriter) Write(p []byte) (int, error) {
|
||||
n := len(p)
|
||||
cw.counter += n
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// GetVarIntSize returns the size in number of bytes of a variable integer
|
||||
// (reference: GetVarSize(int value), https://github.com/neo-project/neo/blob/master/neo/IO/Helper.cs)
|
||||
func GetVarIntSize(value int) int {
|
||||
|
@ -61,16 +73,27 @@ func GetVarSize(value interface{}) int {
|
|||
reflect.Uint32,
|
||||
reflect.Uint64:
|
||||
return GetVarIntSize(int(v.Uint()))
|
||||
case reflect.Ptr:
|
||||
vser, ok := v.Interface().(Serializable)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("unable to calculate GetVarSize for a non-Serializable pointer"))
|
||||
}
|
||||
cw := counterWriter{}
|
||||
w := NewBinWriterFromIO(&cw)
|
||||
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:
|
||||
valueLength := v.Len()
|
||||
valueSize := 0
|
||||
|
||||
if valueLength != 0 {
|
||||
switch reflect.ValueOf(value).Index(0).Interface().(type) {
|
||||
case io.Serializable:
|
||||
case Serializable:
|
||||
for i := 0; i < valueLength; i++ {
|
||||
elem := v.Index(i).Interface().(io.Serializable)
|
||||
valueSize += elem.Size()
|
||||
valueSize += GetVarSize(v.Index(i).Interface())
|
||||
}
|
||||
case uint8, int8:
|
||||
valueSize = valueLength
|
|
@ -1,27 +1,31 @@
|
|||
package util
|
||||
package io
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// Mock structure to test getting size of an array of serializable things
|
||||
type smthSerializable struct {
|
||||
some [42]byte
|
||||
}
|
||||
|
||||
func (*smthSerializable) DecodeBinary(io.Reader) error {
|
||||
return nil
|
||||
func (*smthSerializable) DecodeBinary(*BinReader) {}
|
||||
|
||||
func (ss *smthSerializable) EncodeBinary(bw *BinWriter) {
|
||||
bw.WriteLE(ss.some)
|
||||
}
|
||||
|
||||
func (*smthSerializable) EncodeBinary(io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
// Mock structure that gives error in EncodeBinary().
|
||||
type smthNotReallySerializable struct{}
|
||||
|
||||
func (*smthSerializable) Size() int {
|
||||
return 42
|
||||
func (*smthNotReallySerializable) DecodeBinary(*BinReader) {}
|
||||
|
||||
func (*smthNotReallySerializable) EncodeBinary(bw *BinWriter) {
|
||||
bw.Err = fmt.Errorf("smth bad happened in smthNotReallySerializable")
|
||||
}
|
||||
|
||||
func TestVarSize(t *testing.T) {
|
||||
|
@ -87,7 +91,7 @@ func TestVarSize(t *testing.T) {
|
|||
},
|
||||
{
|
||||
// The neo C# implementation doe not allowed this!
|
||||
Uint160{1, 2, 4, 5, 6},
|
||||
util.Uint160{1, 2, 4, 5, 6},
|
||||
"test_Uint160_1",
|
||||
21,
|
||||
},
|
||||
|
@ -153,7 +157,7 @@ func TestVarSize(t *testing.T) {
|
|||
241,
|
||||
},
|
||||
// The neo C# implementation doe not allowed this!
|
||||
{Uint256{1, 2, 3, 4, 5, 6},
|
||||
{util.Uint256{1, 2, 3, 4, 5, 6},
|
||||
"test_Uint256_1",
|
||||
33,
|
||||
},
|
||||
|
@ -184,11 +188,19 @@ func TestVarSize(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestVarSizePanic(t *testing.T) {
|
||||
func panicVarSize(t *testing.T, v interface{}) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
assert.NotNil(t, r)
|
||||
}()
|
||||
|
||||
_ = GetVarSize(t)
|
||||
_ = GetVarSize(v)
|
||||
// this should never execute
|
||||
assert.Nil(t, t)
|
||||
}
|
||||
|
||||
func TestVarSizePanic(t *testing.T) {
|
||||
panicVarSize(t, t)
|
||||
panicVarSize(t, struct{}{})
|
||||
panicVarSize(t, &smthNotReallySerializable{})
|
||||
}
|
|
@ -1,18 +1,15 @@
|
|||
package network
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/config"
|
||||
"github.com/CityOfZion/neo-go/pkg/core"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/network/payload"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -80,12 +77,14 @@ func NewMessage(magic config.NetMode, cmd CommandType, p payload.Payload) *Messa
|
|||
)
|
||||
|
||||
if p != nil {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := p.EncodeBinary(buf); err != nil {
|
||||
panic(err)
|
||||
buf := io.NewBufBinWriter()
|
||||
p.EncodeBinary(buf.BinWriter)
|
||||
if buf.Err != nil {
|
||||
panic(buf.Err)
|
||||
}
|
||||
size = uint32(buf.Len())
|
||||
checksum = hash.Checksum(buf.Bytes())
|
||||
b := buf.Bytes()
|
||||
size = uint32(len(b))
|
||||
checksum = hash.Checksum(b)
|
||||
} else {
|
||||
checksum = hash.Checksum([]byte{})
|
||||
}
|
||||
|
@ -147,8 +146,7 @@ func (m *Message) CommandType() CommandType {
|
|||
}
|
||||
|
||||
// Decode a Message from the given reader.
|
||||
func (m *Message) Decode(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
func (m *Message) Decode(br *io.BinReader) error {
|
||||
br.ReadLE(&m.Magic)
|
||||
br.ReadLE(&m.Command)
|
||||
br.ReadLE(&m.Length)
|
||||
|
@ -160,69 +158,45 @@ func (m *Message) Decode(r io.Reader) error {
|
|||
if m.Length == 0 {
|
||||
return nil
|
||||
}
|
||||
return m.decodePayload(r)
|
||||
return m.decodePayload(br)
|
||||
}
|
||||
|
||||
func (m *Message) decodePayload(r io.Reader) error {
|
||||
buf := new(bytes.Buffer)
|
||||
n, err := io.CopyN(buf, r, int64(m.Length))
|
||||
if err != nil {
|
||||
return err
|
||||
func (m *Message) decodePayload(br *io.BinReader) error {
|
||||
buf := make([]byte, m.Length)
|
||||
br.ReadLE(buf)
|
||||
if br.Err != nil {
|
||||
return br.Err
|
||||
}
|
||||
|
||||
if uint32(n) != m.Length {
|
||||
return fmt.Errorf("expected to have read exactly %d bytes got %d", m.Length, n)
|
||||
}
|
||||
|
||||
// Compare the checksum of the payload.
|
||||
if !compareChecksum(m.Checksum, buf.Bytes()) {
|
||||
if !compareChecksum(m.Checksum, buf) {
|
||||
return errChecksumMismatch
|
||||
}
|
||||
|
||||
r := io.NewBinReaderFromBuf(buf)
|
||||
var p payload.Payload
|
||||
switch m.CommandType() {
|
||||
case CMDVersion:
|
||||
p = &payload.Version{}
|
||||
if err := p.DecodeBinary(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
case CMDInv, CMDGetData:
|
||||
p = &payload.Inventory{}
|
||||
if err := p.DecodeBinary(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
case CMDAddr:
|
||||
p = &payload.AddressList{}
|
||||
if err := p.DecodeBinary(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
case CMDBlock:
|
||||
p = &core.Block{}
|
||||
if err := p.DecodeBinary(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
case CMDGetBlocks:
|
||||
fallthrough
|
||||
case CMDGetHeaders:
|
||||
p = &payload.GetBlocks{}
|
||||
if err := p.DecodeBinary(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
case CMDHeaders:
|
||||
p = &payload.Headers{}
|
||||
if err := p.DecodeBinary(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
case CMDTX:
|
||||
p = &transaction.Transaction{}
|
||||
if err := p.DecodeBinary(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
case CMDMerkleBlock:
|
||||
p = &payload.MerkleBlock{}
|
||||
if err := p.DecodeBinary(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
p.DecodeBinary(r)
|
||||
if r.Err != nil {
|
||||
return r.Err
|
||||
}
|
||||
|
||||
m.Payload = p
|
||||
|
@ -230,19 +204,19 @@ func (m *Message) decodePayload(r io.Reader) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Encode a Message to any given io.Writer.
|
||||
func (m *Message) Encode(w io.Writer) error {
|
||||
br := util.BinWriter{W: w}
|
||||
// Encode a Message to any given BinWriter.
|
||||
func (m *Message) Encode(br *io.BinWriter) error {
|
||||
br.WriteLE(m.Magic)
|
||||
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(w)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
)
|
||||
|
||||
// AddressAndTime payload.
|
||||
|
@ -28,24 +27,20 @@ func NewAddressAndTime(e *net.TCPAddr, t time.Time) *AddressAndTime {
|
|||
return &aat
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (p *AddressAndTime) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// 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(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
// 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.
|
||||
|
@ -70,35 +65,21 @@ func NewAddressList(n int) *AddressList {
|
|||
return &alist
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (p *AddressList) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// 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(r); err != nil {
|
||||
return err
|
||||
}
|
||||
p.Addrs[i].DecodeBinary(br)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeBinary implements the Payload interface.
|
||||
func (p *AddressList) EncodeBinary(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
// 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(w); err != nil {
|
||||
return err
|
||||
}
|
||||
addr.EncodeBinary(bw)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -15,7 +15,7 @@ func TestEncodeDecodeAddress(t *testing.T) {
|
|||
e, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:2000")
|
||||
ts = time.Now()
|
||||
addr = NewAddressAndTime(e, ts)
|
||||
buf = new(bytes.Buffer)
|
||||
buf = io.NewBufBinWriter()
|
||||
)
|
||||
|
||||
assert.Equal(t, ts.UTC().Unix(), int64(addr.Timestamp))
|
||||
|
@ -23,12 +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)
|
||||
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(buf)
|
||||
assert.Nil(t, err)
|
||||
addrDecode.DecodeBinary(r)
|
||||
assert.Nil(t, r.Err)
|
||||
|
||||
assert.Equal(t, addr, addrDecode)
|
||||
}
|
||||
|
@ -41,13 +43,15 @@ func TestEncodeDecodeAddressList(t *testing.T) {
|
|||
addrList.Addrs[i] = NewAddressAndTime(e, time.Now())
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err := addrList.EncodeBinary(buf)
|
||||
assert.Nil(t, err)
|
||||
buf := io.NewBufBinWriter()
|
||||
addrList.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
|
||||
b := buf.Bytes()
|
||||
r := io.NewBinReaderFromBuf(b)
|
||||
addrListDecode := &AddressList{}
|
||||
err = addrListDecode.DecodeBinary(buf)
|
||||
assert.Nil(t, err)
|
||||
addrListDecode.DecodeBinary(r)
|
||||
assert.Nil(t, r.Err)
|
||||
|
||||
assert.Equal(t, addrList, addrListDecode)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -22,25 +21,18 @@ func NewGetBlocks(start []util.Uint256, stop util.Uint256) *GetBlocks {
|
|||
}
|
||||
}
|
||||
|
||||
// DecodeBinary implements the payload interface.
|
||||
func (p *GetBlocks) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// 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(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
// 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
|
||||
}
|
||||
|
||||
// Size implements the payload interface.
|
||||
func (p *GetBlocks) Size() uint32 { return 0 }
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
@ -18,13 +18,15 @@ func TestGetBlockEncodeDecode(t *testing.T) {
|
|||
}
|
||||
|
||||
p := NewGetBlocks(start, util.Uint256{})
|
||||
buf := new(bytes.Buffer)
|
||||
err := p.EncodeBinary(buf)
|
||||
assert.Nil(t, err)
|
||||
buf := io.NewBufBinWriter()
|
||||
p.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
|
||||
b := buf.Bytes()
|
||||
r := io.NewBinReaderFromBuf(b)
|
||||
pDecode := &GetBlocks{}
|
||||
err = pDecode.DecodeBinary(buf)
|
||||
assert.Nil(t, err)
|
||||
pDecode.DecodeBinary(r)
|
||||
assert.Nil(t, r.Err)
|
||||
assert.Equal(t, p, pDecode)
|
||||
}
|
||||
|
||||
|
@ -39,12 +41,14 @@ func TestGetBlockEncodeDecodeWithHashStop(t *testing.T) {
|
|||
stop = hash.Sha256([]byte("e"))
|
||||
)
|
||||
p := NewGetBlocks(start, stop)
|
||||
buf := new(bytes.Buffer)
|
||||
err := p.EncodeBinary(buf)
|
||||
assert.Nil(t, err)
|
||||
buf := io.NewBufBinWriter()
|
||||
p.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
|
||||
b := buf.Bytes()
|
||||
r := io.NewBinReaderFromBuf(b)
|
||||
pDecode := &GetBlocks{}
|
||||
err = pDecode.DecodeBinary(buf)
|
||||
assert.Nil(t, err)
|
||||
pDecode.DecodeBinary(r)
|
||||
assert.Nil(t, r.Err)
|
||||
assert.Equal(t, p, pDecode)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
@ -18,13 +16,10 @@ const (
|
|||
maxHeadersAllowed = 2000
|
||||
)
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (p *Headers) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// 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)
|
||||
|
@ -35,27 +30,16 @@ func (p *Headers) DecodeBinary(r io.Reader) error {
|
|||
|
||||
for i := 0; i < int(lenHeaders); i++ {
|
||||
header := &core.Header{}
|
||||
if err := header.DecodeBinary(r); err != nil {
|
||||
return err
|
||||
}
|
||||
header.DecodeBinary(br)
|
||||
p.Hdrs[i] = header
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeBinary implements the Payload interface.
|
||||
func (p *Headers) EncodeBinary(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
// 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(w); err != nil {
|
||||
return err
|
||||
}
|
||||
header.EncodeBinary(bw)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -41,13 +41,15 @@ func TestHeadersEncodeDecode(t *testing.T) {
|
|||
}},
|
||||
}}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err := headers.EncodeBinary(buf)
|
||||
assert.Nil(t, err)
|
||||
buf := io.NewBufBinWriter()
|
||||
headers.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
|
||||
b := buf.Bytes()
|
||||
r := io.NewBinReaderFromBuf(b)
|
||||
headersDecode := &Headers{}
|
||||
err = headersDecode.DecodeBinary(buf)
|
||||
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)
|
||||
|
@ -63,10 +65,10 @@ func TestBinEncodeDecode(t *testing.T) {
|
|||
|
||||
rawBlockBytes, _ := hex.DecodeString(rawBlockHeaders)
|
||||
|
||||
r := bytes.NewReader(rawBlockBytes)
|
||||
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]
|
||||
|
@ -74,9 +76,9 @@ func TestBinEncodeDecode(t *testing.T) {
|
|||
|
||||
assert.Equal(t, "f3c4ec44c07eccbda974f1ee34bc6654ab6d3f22cd89c2e5c593a16d6cc7e6e8", hash.ReverseString())
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
buf := io.NewBufBinWriter()
|
||||
|
||||
err = headerMsg.EncodeBinary(buf)
|
||||
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()))
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -55,9 +54,8 @@ func NewInventory(typ InventoryType, hashes []util.Uint256) *Inventory {
|
|||
}
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (p *Inventory) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// DecodeBinary implements Serializable interface.
|
||||
func (p *Inventory) DecodeBinary(br *io.BinReader) {
|
||||
br.ReadLE(&p.Type)
|
||||
|
||||
listLen := br.ReadVarUint()
|
||||
|
@ -65,13 +63,10 @@ func (p *Inventory) DecodeBinary(r io.Reader) 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(w io.Writer) error {
|
||||
bw := util.BinWriter{W: w}
|
||||
// EncodeBinary implements Serializable interface.
|
||||
func (p *Inventory) EncodeBinary(bw *io.BinWriter) {
|
||||
bw.WriteLE(p.Type)
|
||||
|
||||
listLen := len(p.Hashes)
|
||||
|
@ -79,6 +74,4 @@ func (p *Inventory) EncodeBinary(w io.Writer) error {
|
|||
for i := 0; i < listLen; i++ {
|
||||
bw.WriteLE(p.Hashes[i])
|
||||
}
|
||||
|
||||
return bw.Err
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
. "github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
@ -16,22 +16,24 @@ func TestInventoryEncodeDecode(t *testing.T) {
|
|||
}
|
||||
inv := NewInventory(BlockType, hashes)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err := inv.EncodeBinary(buf)
|
||||
assert.Nil(t, err)
|
||||
buf := io.NewBufBinWriter()
|
||||
inv.EncodeBinary(buf.BinWriter)
|
||||
assert.Nil(t, buf.Err)
|
||||
|
||||
b := buf.Bytes()
|
||||
r := io.NewBinReaderFromBuf(b)
|
||||
invDecode := &Inventory{}
|
||||
err = invDecode.DecodeBinary(buf)
|
||||
assert.Nil(t, err)
|
||||
invDecode.DecodeBinary(r)
|
||||
assert.Nil(t, r.Err)
|
||||
assert.Equal(t, inv, invDecode)
|
||||
}
|
||||
|
||||
func TestEmptyInv(t *testing.T) {
|
||||
msgInv := NewInventory(TXType, []Uint256{})
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err := msgInv.EncodeBinary(buf)
|
||||
assert.Nil(t, err)
|
||||
buf := io.NewBufBinWriter()
|
||||
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))
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -15,13 +14,10 @@ type MerkleBlock struct {
|
|||
Flags []byte
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (m *MerkleBlock) DecodeBinary(r io.Reader) error {
|
||||
// DecodeBinary implements Serializable interface.
|
||||
func (m *MerkleBlock) DecodeBinary(br *io.BinReader) {
|
||||
m.BlockBase = &core.BlockBase{}
|
||||
if err := m.BlockBase.DecodeBinary(r); err != nil {
|
||||
return err
|
||||
}
|
||||
br := util.BinReader{R: r}
|
||||
m.BlockBase.DecodeBinary(br)
|
||||
|
||||
m.TxCount = int(br.ReadVarUint())
|
||||
n := br.ReadVarUint()
|
||||
|
@ -30,10 +26,17 @@ func (m *MerkleBlock) DecodeBinary(r io.Reader) error {
|
|||
br.ReadLE(&m.Hashes[i])
|
||||
}
|
||||
m.Flags = br.ReadBytes()
|
||||
return br.Err
|
||||
}
|
||||
|
||||
// EncodeBinary implements the Payload interface.
|
||||
func (m *MerkleBlock) EncodeBinary(w io.Writer) error {
|
||||
return nil
|
||||
// EncodeBinary implements Serializable interface.
|
||||
func (m *MerkleBlock) EncodeBinary(bw *io.BinWriter) {
|
||||
m.BlockBase = &core.BlockBase{}
|
||||
m.BlockBase.EncodeBinary(bw)
|
||||
|
||||
bw.WriteVarUint(uint64(m.TxCount))
|
||||
bw.WriteVarUint(uint64(len(m.Hashes)))
|
||||
for i := 0; i < len(m.Hashes); i++ {
|
||||
bw.WriteLE(m.Hashes[i])
|
||||
}
|
||||
bw.WriteBytes(m.Flags)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package payload
|
||||
|
||||
import "io"
|
||||
import "github.com/CityOfZion/neo-go/pkg/io"
|
||||
|
||||
// Payload is anything that can be binary encoded/decoded.
|
||||
type Payload interface {
|
||||
EncodeBinary(io.Writer) error
|
||||
DecodeBinary(io.Reader) error
|
||||
io.Serializable
|
||||
}
|
||||
|
||||
// NullPayload is a dummy payload with no fields.
|
||||
|
@ -17,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) {}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
)
|
||||
|
||||
// Size of the payload not counting UserAgent encoding (which is at least 1 byte
|
||||
|
@ -54,9 +53,8 @@ func NewVersion(id uint32, p uint16, ua string, h uint32, r bool) *Version {
|
|||
}
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Payload interface.
|
||||
func (p *Version) DecodeBinary(r io.Reader) error {
|
||||
br := util.BinReader{R: r}
|
||||
// DecodeBinary implements Serializable interface.
|
||||
func (p *Version) DecodeBinary(br *io.BinReader) {
|
||||
br.ReadLE(&p.Version)
|
||||
br.ReadLE(&p.Services)
|
||||
br.ReadLE(&p.Timestamp)
|
||||
|
@ -65,12 +63,10 @@ func (p *Version) DecodeBinary(r io.Reader) 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(w io.Writer) error {
|
||||
br := util.BinWriter{W: w}
|
||||
// EncodeBinary implements Serializable interface.
|
||||
func (p *Version) EncodeBinary(br *io.BinWriter) {
|
||||
br.WriteLE(p.Version)
|
||||
br.WriteLE(p.Services)
|
||||
br.WriteLE(p.Timestamp)
|
||||
|
@ -80,10 +76,4 @@ func (p *Version) EncodeBinary(w io.Writer) error {
|
|||
br.WriteBytes(p.UserAgent)
|
||||
br.WriteLE(p.StartHeight)
|
||||
br.WriteLE(&p.Relay)
|
||||
return br.Err
|
||||
}
|
||||
|
||||
// Size implements the payloader interface.
|
||||
func (p *Version) Size() uint32 {
|
||||
return uint32(minVersionSize + util.GetVarSize(p.UserAgent))
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -16,14 +16,16 @@ func TestVersionEncodeDecode(t *testing.T) {
|
|||
|
||||
version := NewVersion(id, port, useragent, height, relay)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err := version.EncodeBinary(buf)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, int(version.Size()), buf.Len())
|
||||
buf := io.NewBufBinWriter()
|
||||
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(buf)
|
||||
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))
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/network/payload"
|
||||
)
|
||||
|
||||
|
@ -68,7 +69,8 @@ func (p *TCPPeer) writeMsg(msg *Message) error {
|
|||
case err := <-p.done:
|
||||
return err
|
||||
default:
|
||||
return msg.Encode(p.conn)
|
||||
w := io.NewBinWriterFromIO(p.conn)
|
||||
return msg.Encode(w)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
@ -77,9 +78,10 @@ func (t *TCPTransport) handleConn(conn net.Conn) {
|
|||
|
||||
t.server.register <- p
|
||||
|
||||
r := io.NewBinReaderFromIO(p.conn)
|
||||
for {
|
||||
msg := &Message{}
|
||||
if err = msg.Decode(p.conn); err != nil {
|
||||
if err = msg.Decode(r); err != nil {
|
||||
break
|
||||
}
|
||||
if err = t.server.handleMessage(p, msg); err != nil {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -113,7 +113,7 @@ func (c *Client) sendRawTransaction(rawTX string) (*response, error) {
|
|||
func (c *Client) SendToAddress(asset util.Uint256, address string, amount util.Fixed8) (*SendToAddressResponse, error) {
|
||||
var (
|
||||
err error
|
||||
buf = &bytes.Buffer{}
|
||||
buf = io.NewBufBinWriter()
|
||||
rawTx *transaction.Transaction
|
||||
rawTxStr string
|
||||
txParams = ContractTxParams{
|
||||
|
@ -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); 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 {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
@ -11,6 +10,7 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/core"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/network"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/result"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/wrappers"
|
||||
|
@ -294,29 +294,29 @@ func (s *Server) sendrawtransaction(reqParams Params) (interface{}, error) {
|
|||
} else if byteTx, err := hex.DecodeString(param.StringVal); err != nil {
|
||||
resultsErr = errInvalidParams
|
||||
} else {
|
||||
r := bytes.NewReader(byteTx)
|
||||
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)
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
errs "github.com/pkg/errors"
|
||||
)
|
||||
|
@ -71,11 +70,12 @@ func GetInvocationScript(tx *transaction.Transaction, wif keys.WIF) ([]byte, err
|
|||
)
|
||||
var (
|
||||
err error
|
||||
buf = new(bytes.Buffer)
|
||||
buf = io.NewBufBinWriter()
|
||||
signature []byte
|
||||
)
|
||||
if err = tx.EncodeBinary(buf); 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)])
|
||||
|
|
|
@ -3,6 +3,7 @@ package wrappers
|
|||
import (
|
||||
"github.com/CityOfZion/neo-go/pkg/core"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -30,7 +31,7 @@ func NewTransactionOutputRaw(tx *transaction.Transaction, header *core.Header, c
|
|||
return TransactionOutputRaw{
|
||||
Transaction: tx,
|
||||
TxHash: tx.Hash(),
|
||||
Size: tx.Size(),
|
||||
Size: io.GetVarSize(tx),
|
||||
SysFee: chain.SystemFee(tx),
|
||||
NetFee: chain.NetworkFee(tx),
|
||||
Blockhash: header.Hash(),
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package smartcontract
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
@ -22,8 +21,7 @@ func TestCreateMultiSigRedeemScript(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(out)
|
||||
br := util.BinReader{R: buf}
|
||||
br := io.NewBinReaderFromBuf(out)
|
||||
var b uint8
|
||||
br.ReadLE(&b)
|
||||
assert.Equal(t, vm.PUSH3, vm.Instruction(b))
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestWriteVarUint1(t *testing.T) {
|
||||
var (
|
||||
val = uint64(1)
|
||||
buf = new(bytes.Buffer)
|
||||
)
|
||||
bw := BinWriter{W: buf}
|
||||
bw.WriteVarUint(val)
|
||||
assert.Nil(t, bw.Err)
|
||||
assert.Equal(t, 1, buf.Len())
|
||||
}
|
||||
|
||||
func TestWriteVarUint1000(t *testing.T) {
|
||||
var (
|
||||
val = uint64(1000)
|
||||
buf = new(bytes.Buffer)
|
||||
)
|
||||
bw := BinWriter{W: buf}
|
||||
bw.WriteVarUint(val)
|
||||
assert.Nil(t, bw.Err)
|
||||
assert.Equal(t, 3, buf.Len())
|
||||
assert.Equal(t, byte(0xfd), buf.Bytes()[0])
|
||||
br := BinReader{R: buf}
|
||||
res := br.ReadVarUint()
|
||||
assert.Nil(t, br.Err)
|
||||
assert.Equal(t, val, res)
|
||||
}
|
||||
|
||||
func TestWriteVarUint100000(t *testing.T) {
|
||||
var (
|
||||
val = uint64(100000)
|
||||
buf = new(bytes.Buffer)
|
||||
)
|
||||
bw := BinWriter{W: buf}
|
||||
bw.WriteVarUint(val)
|
||||
assert.Nil(t, bw.Err)
|
||||
assert.Equal(t, 5, buf.Len())
|
||||
assert.Equal(t, byte(0xfe), buf.Bytes()[0])
|
||||
br := BinReader{R: buf}
|
||||
res := br.ReadVarUint()
|
||||
assert.Nil(t, br.Err)
|
||||
assert.Equal(t, val, res)
|
||||
}
|
||||
|
||||
func TestWriteVarUint100000000000(t *testing.T) {
|
||||
var (
|
||||
val = uint64(1000000000000)
|
||||
buf = new(bytes.Buffer)
|
||||
)
|
||||
bw := BinWriter{W: buf}
|
||||
bw.WriteVarUint(val)
|
||||
assert.Nil(t, bw.Err)
|
||||
assert.Equal(t, 9, buf.Len())
|
||||
assert.Equal(t, byte(0xff), buf.Bytes()[0])
|
||||
br := BinReader{R: buf}
|
||||
res := br.ReadVarUint()
|
||||
assert.Nil(t, br.Err)
|
||||
assert.Equal(t, val, res)
|
||||
}
|
|
@ -104,11 +104,6 @@ func (f *Fixed8) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Size returns the size in number of bytes of Fixed8.
|
||||
func (f *Fixed8) Size() int {
|
||||
return 8
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json marshaller interface.
|
||||
func (f Fixed8) MarshalJSON() ([]byte, error) {
|
||||
return []byte(`"` + f.String() + `"`), nil
|
||||
|
|
|
@ -70,11 +70,6 @@ func (u *Uint160) UnmarshalJSON(data []byte) (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
// Size returns the length of the bytes representation of Uint160
|
||||
func (u Uint160) Size() int {
|
||||
return uint160Size
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json marshaller interface.
|
||||
func (u Uint160) MarshalJSON() ([]byte, error) {
|
||||
return []byte(`"0x` + u.String() + `"`), nil
|
||||
|
|
|
@ -82,11 +82,6 @@ func (u *Uint256) UnmarshalJSON(data []byte) (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
// Size returns the length of the bytes representation of Uint256
|
||||
func (u Uint256) Size() int {
|
||||
return uint256Size
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json marshaller interface.
|
||||
func (u Uint256) MarshalJSON() ([]byte, error) {
|
||||
return []byte(`"0x` + u.ReverseString() + `"`), nil
|
||||
|
|
Loading…
Reference in a new issue