Skip to content

Commit

Permalink
*: get rid of github.com/nspcc-dev/neo-go/pkg/io dependency
Browse files Browse the repository at this point in the history
Implement custom payloads serialization using gob package. A part of #2.

Signed-off-by: Anna Shaleva <[email protected]>
  • Loading branch information
AnnaShaleva committed Feb 9, 2024
1 parent 6d59675 commit ccdd6e3
Show file tree
Hide file tree
Showing 13 changed files with 381 additions and 228 deletions.
39 changes: 15 additions & 24 deletions block/block.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package block

import (
"bytes"
"encoding/gob"

"github.com/nspcc-dev/dbft/crypto"
"github.com/nspcc-dev/dbft/merkle"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/util"
)

Expand Down Expand Up @@ -135,10 +137,11 @@ func (b *neoBlock) Signature() []byte {
// 1. It must have only one valid result for one block.
// 2. Two different blocks must have different hash data.
func (b *neoBlock) GetHashData() []byte {
w := io.NewBufBinWriter()
b.EncodeBinary(w.BinWriter)
buf := bytes.Buffer{}
w := gob.NewEncoder(&buf)
_ = b.EncodeBinary(w)

return w.Bytes()
return buf.Bytes()
}

// Sign implements Block interface.
Expand Down Expand Up @@ -175,24 +178,12 @@ func (b *neoBlock) Hash() (h util.Uint256) {
return hash
}

// EncodeBinary implements io.Serializable interface.
func (b base) EncodeBinary(w *io.BinWriter) {
w.WriteU32LE(b.Version)
w.WriteBytes(b.PrevHash[:])
w.WriteBytes(b.MerkleRoot[:])
w.WriteU32LE(b.Timestamp)
w.WriteU32LE(b.Index)
w.WriteU64LE(b.ConsensusData)
w.WriteBytes(b.NextConsensus[:])
}

// DecodeBinary implements io.Serializable interface.
func (b *base) DecodeBinary(r *io.BinReader) {
b.Version = r.ReadU32LE()
r.ReadBytes(b.PrevHash[:])
r.ReadBytes(b.MerkleRoot[:])
b.Timestamp = r.ReadU32LE()
b.Index = r.ReadU32LE()
b.ConsensusData = r.ReadU64LE()
r.ReadBytes(b.NextConsensus[:])
// EncodeBinary implements Serializable interface.
func (b base) EncodeBinary(w *gob.Encoder) error {
return w.Encode(b)
}

// DecodeBinary implements Serializable interface.
func (b *base) DecodeBinary(r *gob.Decoder) error {
return r.Decode(b)
}
16 changes: 9 additions & 7 deletions block/block_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package block

import (
"bytes"
"crypto/rand"
"encoding/binary"
"encoding/gob"
"errors"
"testing"

"github.com/nspcc-dev/dbft/crypto"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -45,14 +46,15 @@ func TestNeoBlock_Setters(t *testing.T) {
assert.EqualValues(t, 100, b.Index())

t.Run("marshal block", func(t *testing.T) {
w := io.NewBufBinWriter()
b.EncodeBinary(w.BinWriter)
require.NoError(t, w.Err)
buf := bytes.Buffer{}
w := gob.NewEncoder(&buf)
err := b.EncodeBinary(w)
require.NoError(t, err)

r := io.NewBinReaderFromBuf(w.Bytes())
r := gob.NewDecoder(bytes.NewReader(buf.Bytes()))
newb := new(neoBlock)
newb.DecodeBinary(r)
require.NoError(t, r.Err)
err = newb.DecodeBinary(r)
require.NoError(t, err)
require.Equal(t, b.base, newb.base)
})

Expand Down
1 change: 0 additions & 1 deletion merkle/merkle_tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"testing"

"github.com/nspcc-dev/neo-go/pkg/util"

"github.com/stretchr/testify/require"
)

Expand Down
37 changes: 26 additions & 11 deletions payload/change_view.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package payload

import "github.com/nspcc-dev/neo-go/pkg/io"
import (
"encoding/gob"
)

// ChangeView represents dBFT ChangeView message.
type ChangeView interface {
Expand All @@ -23,21 +25,34 @@ type ChangeView interface {
SetReason(reason ChangeViewReason)
}

type changeView struct {
newViewNumber byte
timestamp uint32
}
type (
changeView struct {
newViewNumber byte
timestamp uint32
}
// changeViewAux is an auxiliary structure for changeView encoding.
changeViewAux struct {
Timestamp uint32
}
)

var _ ChangeView = (*changeView)(nil)

// EncodeBinary implements io.Serializable interface.
func (c changeView) EncodeBinary(w *io.BinWriter) {
w.WriteU32LE(c.timestamp)
// EncodeBinary implements Serializable interface.
func (c changeView) EncodeBinary(w *gob.Encoder) error {
return w.Encode(&changeViewAux{
Timestamp: c.timestamp,
})
}

// DecodeBinary implements io.Serializable interface.
func (c *changeView) DecodeBinary(r *io.BinReader) {
c.timestamp = r.ReadU32LE()
// DecodeBinary implements Serializable interface.
func (c *changeView) DecodeBinary(r *gob.Decoder) error {
aux := new(changeViewAux)
if err := r.Decode(aux); err != nil {
return err

Check warning on line 52 in payload/change_view.go

View check run for this annotation

Codecov / codecov/patch

payload/change_view.go#L52

Added line #L52 was not covered by tests
}
c.timestamp = aux.Timestamp
return nil
}

// NewViewNumber implements ChangeView interface.
Expand Down
35 changes: 25 additions & 10 deletions payload/commit.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package payload

import "github.com/nspcc-dev/neo-go/pkg/io"
import (
"encoding/gob"
)

// Commit is an interface for dBFT Commit message.
type Commit interface {
Expand All @@ -12,22 +14,35 @@ type Commit interface {
SetSignature(signature []byte)
}

type commit struct {
signature [signatureSize]byte
}
type (
commit struct {
signature [signatureSize]byte
}
// commitAux is an auxiliary structure for commit encoding.
commitAux struct {
Signature [signatureSize]byte
}
)

const signatureSize = 64

var _ Commit = (*commit)(nil)

// EncodeBinary implements io.Serializable interface.
func (c commit) EncodeBinary(w *io.BinWriter) {
w.WriteBytes(c.signature[:])
// EncodeBinary implements Serializable interface.
func (c commit) EncodeBinary(w *gob.Encoder) error {
return w.Encode(commitAux{
Signature: c.signature,
})
}

// DecodeBinary implements io.Serializable interface.
func (c *commit) DecodeBinary(r *io.BinReader) {
r.ReadBytes(c.signature[:])
// DecodeBinary implements Serializable interface.
func (c *commit) DecodeBinary(r *gob.Decoder) error {
aux := new(commitAux)
if err := r.Decode(aux); err != nil {
return err

Check warning on line 42 in payload/commit.go

View check run for this annotation

Codecov / codecov/patch

payload/commit.go#L42

Added line #L42 was not covered by tests
}
c.signature = aux.Signature
return nil
}

// Signature implements Commit interface.
Expand Down
62 changes: 28 additions & 34 deletions payload/compact.go
Original file line number Diff line number Diff line change
@@ -1,59 +1,53 @@
package payload

import "github.com/nspcc-dev/neo-go/pkg/io"
import (
"encoding/gob"
)

type (
changeViewCompact struct {
validatorIndex uint16
originalViewNumber byte
timestamp uint32
ValidatorIndex uint16
OriginalViewNumber byte
Timestamp uint32
}

commitCompact struct {
viewNumber byte
validatorIndex uint16
signature [signatureSize]byte
ViewNumber byte
ValidatorIndex uint16
Signature [signatureSize]byte
}

preparationCompact struct {
validatorIndex uint16
ValidatorIndex uint16
}
)

// EncodeBinary implements io.Serializable interface.
func (p changeViewCompact) EncodeBinary(w *io.BinWriter) {
w.WriteU16LE(p.validatorIndex)
w.WriteB(p.originalViewNumber)
w.WriteU32LE(p.timestamp)
// EncodeBinary implements Serializable interface.
func (p changeViewCompact) EncodeBinary(w *gob.Encoder) error {
return w.Encode(p)
}

// DecodeBinary implements io.Serializable interface.
func (p *changeViewCompact) DecodeBinary(r *io.BinReader) {
p.validatorIndex = r.ReadU16LE()
p.originalViewNumber = r.ReadB()
p.timestamp = r.ReadU32LE()
// DecodeBinary implements Serializable interface.
func (p *changeViewCompact) DecodeBinary(r *gob.Decoder) error {
return r.Decode(p)
}

// EncodeBinary implements io.Serializable interface.
func (p commitCompact) EncodeBinary(w *io.BinWriter) {
w.WriteB(p.viewNumber)
w.WriteU16LE(p.validatorIndex)
w.WriteBytes(p.signature[:])
// EncodeBinary implements Serializable interface.
func (p commitCompact) EncodeBinary(w *gob.Encoder) error {
return w.Encode(p)
}

// DecodeBinary implements io.Serializable interface.
func (p *commitCompact) DecodeBinary(r *io.BinReader) {
p.viewNumber = r.ReadB()
p.validatorIndex = r.ReadU16LE()
r.ReadBytes(p.signature[:])
// DecodeBinary implements Serializable interface.
func (p *commitCompact) DecodeBinary(r *gob.Decoder) error {
return r.Decode(p)
}

// EncodeBinary implements io.Serializable interface.
func (p preparationCompact) EncodeBinary(w *io.BinWriter) {
w.WriteU16LE(p.validatorIndex)
// EncodeBinary implements Serializable interface.
func (p preparationCompact) EncodeBinary(w *gob.Encoder) error {
return w.Encode(p)
}

// DecodeBinary implements io.Serializable interface.
func (p *preparationCompact) DecodeBinary(r *io.BinReader) {
p.validatorIndex = r.ReadU16LE()
// DecodeBinary implements Serializable interface.
func (p *preparationCompact) DecodeBinary(r *gob.Decoder) error {
return r.Decode(p)
}
52 changes: 39 additions & 13 deletions payload/consensus_message.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
package payload

import (
"bytes"
"encoding/gob"
"fmt"

"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/pkg/errors"
)

type (
// MessageType is a type for dBFT consensus messages.
MessageType byte

// Serializable is an interface for serializing consensus messages.
Serializable interface {
EncodeBinary(encoder *gob.Encoder) error
DecodeBinary(decoder *gob.Decoder) error
}

consensusMessage interface {
// ViewNumber returns view number when this message was originated.
ViewNumber() byte
Expand Down Expand Up @@ -47,6 +54,13 @@ type (

payload any
}

// messageAux is an auxiliary structure for message marshalling.
messageAux struct {
CMType byte
ViewNumber byte
Payload []byte
}
)

// 6 following constants enumerate all possible type of consensus message.
Expand Down Expand Up @@ -81,17 +95,28 @@ func (m MessageType) String() string {
}
}

// EncodeBinary implements io.Serializable interface.
func (m message) EncodeBinary(w *io.BinWriter) {
w.WriteB(byte(m.cmType))
w.WriteB(m.viewNumber)
m.payload.(io.Serializable).EncodeBinary(w)
// EncodeBinary implements Serializable interface.
func (m message) EncodeBinary(w *gob.Encoder) error {
ww := bytes.Buffer{}
enc := gob.NewEncoder(&ww)
if err := m.payload.(Serializable).EncodeBinary(enc); err != nil {
return err

Check warning on line 103 in payload/consensus_message.go

View check run for this annotation

Codecov / codecov/patch

payload/consensus_message.go#L103

Added line #L103 was not covered by tests
}
return w.Encode(&messageAux{
CMType: byte(m.cmType),
ViewNumber: m.viewNumber,
Payload: ww.Bytes(),
})
}

// DecodeBinary implements io.Serializable interface.
func (m *message) DecodeBinary(r *io.BinReader) {
m.cmType = MessageType(r.ReadB())
m.viewNumber = r.ReadB()
// DecodeBinary implements Serializable interface.
func (m *message) DecodeBinary(r *gob.Decoder) error {
aux := new(messageAux)
if err := r.Decode(aux); err != nil {
return err

Check warning on line 116 in payload/consensus_message.go

View check run for this annotation

Codecov / codecov/patch

payload/consensus_message.go#L116

Added line #L116 was not covered by tests
}
m.cmType = MessageType(aux.CMType)
m.viewNumber = aux.ViewNumber

switch m.cmType {
case ChangeViewType:
Expand All @@ -109,11 +134,12 @@ func (m *message) DecodeBinary(r *io.BinReader) {
case RecoveryMessageType:
m.payload = new(recoveryMessage)
default:
r.Err = errors.Errorf("invalid type: 0x%02x", byte(m.cmType))
return
return errors.Errorf("invalid type: 0x%02x", byte(m.cmType))

Check warning on line 137 in payload/consensus_message.go

View check run for this annotation

Codecov / codecov/patch

payload/consensus_message.go#L137

Added line #L137 was not covered by tests
}

m.payload.(io.Serializable).DecodeBinary(r)
rr := bytes.NewReader(aux.Payload)
dec := gob.NewDecoder(rr)
return m.payload.(Serializable).DecodeBinary(dec)
}

func (m message) GetChangeView() ChangeView { return m.payload.(ChangeView) }
Expand Down
Loading

0 comments on commit ccdd6e3

Please sign in to comment.