diff --git a/block/block.go b/block/block.go index 11c85e17..3235c567 100644 --- a/block/block.go +++ b/block/block.go @@ -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" ) @@ -48,7 +50,7 @@ type ( // Transactions returns block's transaction list. Transactions() []Transaction - // SetTransaction sets block's transaction list. + // SetTransactions sets block's transaction list. SetTransactions([]Transaction) } @@ -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. @@ -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) } diff --git a/block/block_test.go b/block/block_test.go index 06dad4f8..96e14098 100644 --- a/block/block_test.go +++ b/block/block_test.go @@ -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" @@ -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) }) diff --git a/config.go b/config.go index 39807759..bdd803b2 100644 --- a/config.go +++ b/config.go @@ -99,14 +99,14 @@ func defaultConfig() *Config { TimestampIncrement: defaultTimestampIncrement, GetKeyPair: nil, NewBlockFromContext: NewBlockFromContext, - RequestTx: func(h ...util.Uint256) {}, + RequestTx: func(...util.Uint256) {}, StopTxFlow: func() {}, - GetTx: func(h util.Uint256) block.Transaction { return nil }, + GetTx: func(util.Uint256) block.Transaction { return nil }, GetVerified: func() []block.Transaction { return make([]block.Transaction, 0) }, - VerifyBlock: func(b block.Block) bool { return true }, - Broadcast: func(m payload.ConsensusPayload) {}, - ProcessBlock: func(b block.Block) {}, - GetBlock: func(h util.Uint256) block.Block { return nil }, + VerifyBlock: func(block.Block) bool { return true }, + Broadcast: func(payload.ConsensusPayload) {}, + ProcessBlock: func(block.Block) {}, + GetBlock: func(util.Uint256) block.Block { return nil }, WatchOnly: func() bool { return false }, CurrentHeight: nil, CurrentBlockHash: nil, diff --git a/dbft_test.go b/dbft_test.go index de94b574..9ec9eddf 100644 --- a/dbft_test.go +++ b/dbft_test.go @@ -790,7 +790,7 @@ func (s *testState) getOptions() []Option { WithProcessBlock(func(b block.Block) { s.blocks = append(s.blocks, b) }), WithGetConsensusAddress(s.nextConsensus), WithWatchOnly(func() bool { return false }), - WithGetBlock(func(h util.Uint256) block.Block { return nil }), + WithGetBlock(func(util.Uint256) block.Block { return nil }), WithTimer(timer.New()), WithLogger(zap.NewNop()), WithNewBlockFromContext(NewBlockFromContext), @@ -809,7 +809,7 @@ func (s *testState) getOptions() []Option { verify := s.verify if verify == nil { - verify = func(b block.Block) bool { return true } + verify = func(block.Block) bool { return true } } opts = append(opts, WithVerifyBlock(verify)) diff --git a/merkle/merkle_tree_test.go b/merkle/merkle_tree_test.go index 7297d289..1a3ca870 100644 --- a/merkle/merkle_tree_test.go +++ b/merkle/merkle_tree_test.go @@ -6,7 +6,6 @@ import ( "testing" "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/stretchr/testify/require" ) diff --git a/payload/change_view.go b/payload/change_view.go index ababa394..3024564d 100644 --- a/payload/change_view.go +++ b/payload/change_view.go @@ -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 { @@ -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 + } + c.timestamp = aux.Timestamp + return nil } // NewViewNumber implements ChangeView interface. diff --git a/payload/commit.go b/payload/commit.go index ad441509..64f7676e 100644 --- a/payload/commit.go +++ b/payload/commit.go @@ -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 { @@ -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 + } + c.signature = aux.Signature + return nil } // Signature implements Commit interface. diff --git a/payload/compact.go b/payload/compact.go index 88a889ea..e1382232 100644 --- a/payload/compact.go +++ b/payload/compact.go @@ -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) } diff --git a/payload/consensus_message.go b/payload/consensus_message.go index 48e8cd52..0ebe8de7 100644 --- a/payload/consensus_message.go +++ b/payload/consensus_message.go @@ -1,9 +1,10 @@ package payload import ( + "bytes" + "encoding/gob" "fmt" - "github.com/nspcc-dev/neo-go/pkg/io" "github.com/pkg/errors" ) @@ -11,6 +12,12 @@ 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 @@ -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. @@ -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 + } + 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 + } + m.cmType = MessageType(aux.CMType) + m.viewNumber = aux.ViewNumber switch m.cmType { case ChangeViewType: @@ -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)) } - 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) } diff --git a/payload/message.go b/payload/message.go index 3475e42a..d8ed52db 100644 --- a/payload/message.go +++ b/payload/message.go @@ -1,8 +1,10 @@ package payload import ( + "bytes" + "encoding/gob" + "github.com/nspcc-dev/dbft/crypto" - "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/util" ) @@ -16,7 +18,7 @@ type ( // payload was originated from. ValidatorIndex() uint16 - // SetValidator index sets validator index. + // SetValidatorIndex sets validator index. SetValidatorIndex(i uint16) Height() uint32 @@ -37,49 +39,68 @@ type ( hash *util.Uint256 } + + // payloadAux is an auxiliary structure for Payload encoding. + payloadAux struct { + Version uint32 + ValidatorIndex uint16 + PrevHash util.Uint256 + Height uint32 + + Data []byte + } ) var _ ConsensusPayload = (*Payload)(nil) -// EncodeBinary implements io.Serializable interface. -func (p Payload) EncodeBinary(w *io.BinWriter) { - ww := io.NewBufBinWriter() - p.message.EncodeBinary(ww.BinWriter) - data := ww.Bytes() - - w.WriteU32LE(p.version) - w.WriteBytes(p.prevHash[:]) - w.WriteU32LE(p.height) - w.WriteU16LE(p.validatorIndex) - w.WriteVarBytes(data) +// EncodeBinary implements Serializable interface. +func (p Payload) EncodeBinary(w *gob.Encoder) error { + ww := bytes.Buffer{} + enc := gob.NewEncoder(&ww) + if err := p.message.EncodeBinary(enc); err != nil { + return err + } + + return w.Encode(&payloadAux{ + Version: p.version, + ValidatorIndex: p.validatorIndex, + PrevHash: p.prevHash, + Height: p.height, + Data: ww.Bytes(), + }) } -// DecodeBinary implements io.Serializable interface. -func (p *Payload) DecodeBinary(r *io.BinReader) { - p.version = r.ReadU32LE() - p.prevHash.DecodeBinary(r) - p.height = r.ReadU32LE() - p.validatorIndex = r.ReadU16LE() +// DecodeBinary implements Serializable interface. +func (p *Payload) DecodeBinary(r *gob.Decoder) error { + aux := new(payloadAux) + if err := r.Decode(aux); err != nil { + return err + } + + p.version = aux.Version + p.prevHash = aux.PrevHash + p.height = aux.Height + p.validatorIndex = aux.ValidatorIndex - data := r.ReadVarBytes() - rr := io.NewBinReaderFromBuf(data) - p.message.DecodeBinary(rr) + rr := bytes.NewReader(aux.Data) + dec := gob.NewDecoder(rr) + return p.message.DecodeBinary(dec) } // MarshalUnsigned implements ConsensusPayload interface. func (p Payload) MarshalUnsigned() []byte { - w := io.NewBufBinWriter() - p.EncodeBinary(w.BinWriter) + buf := bytes.Buffer{} + enc := gob.NewEncoder(&buf) + _ = p.EncodeBinary(enc) - return w.Bytes() + return buf.Bytes() } // UnmarshalUnsigned implements ConsensusPayload interface. func (p *Payload) UnmarshalUnsigned(data []byte) error { - r := io.NewBinReaderFromBuf(data) - p.DecodeBinary(r) - - return r.Err + r := bytes.NewReader(data) + dec := gob.NewDecoder(r) + return p.DecodeBinary(dec) } // Hash implements ConsensusPayload interface. diff --git a/payload/message_test.go b/payload/message_test.go index 482e1f17..82d27746 100644 --- a/payload/message_test.go +++ b/payload/message_test.go @@ -1,11 +1,12 @@ package payload import ( + "bytes" "crypto/rand" + "encoding/gob" "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" @@ -70,16 +71,16 @@ func TestPayload_EncodeDecode(t *testing.T) { m.SetPayload(&recoveryMessage{ changeViewPayloads: []changeViewCompact{ { - timestamp: 123, - validatorIndex: 1, - originalViewNumber: 3, + Timestamp: 123, + ValidatorIndex: 1, + OriginalViewNumber: 3, }, }, commitPayloads: []commitCompact{}, preparationPayloads: []preparationCompact{ - 1: {validatorIndex: 1}, - 3: {validatorIndex: 3}, - 4: {validatorIndex: 4}, + 1: {ValidatorIndex: 1}, + 3: {ValidatorIndex: 3}, + 4: {ValidatorIndex: 4}, }, prepareRequest: &prepareRequest{ nonce: 123, @@ -139,9 +140,9 @@ func TestRecoveryMessage_NoPayloads(t *testing.T) { func TestCompact_EncodeDecode(t *testing.T) { t.Run("ChangeView", func(t *testing.T) { p := &changeViewCompact{ - validatorIndex: 10, - originalViewNumber: 31, - timestamp: 98765, + ValidatorIndex: 10, + OriginalViewNumber: 31, + Timestamp: 98765, } testEncodeDecode(t, p, new(changeViewCompact)) @@ -149,7 +150,7 @@ func TestCompact_EncodeDecode(t *testing.T) { t.Run("Preparation", func(t *testing.T) { p := &preparationCompact{ - validatorIndex: 10, + ValidatorIndex: 10, } testEncodeDecode(t, p, new(preparationCompact)) @@ -157,10 +158,10 @@ func TestCompact_EncodeDecode(t *testing.T) { t.Run("Commit", func(t *testing.T) { p := &commitCompact{ - validatorIndex: 10, - viewNumber: 77, + ValidatorIndex: 10, + ViewNumber: 77, } - fillRandom(t, p.signature[:]) + fillRandom(t, p.Signature[:]) testEncodeDecode(t, p, new(commitCompact)) }) @@ -201,16 +202,17 @@ func TestMessageType_String(t *testing.T) { require.Equal(t, "RecoveryMessage", RecoveryMessageType.String()) } -func testEncodeDecode(t *testing.T, expected, actual io.Serializable) { - w := io.NewBufBinWriter() - expected.EncodeBinary(w.BinWriter) - require.NoError(t, w.Err) +func testEncodeDecode(t *testing.T, expected, actual Serializable) { + var buf bytes.Buffer + w := gob.NewEncoder(&buf) + err := expected.EncodeBinary(w) + require.NoError(t, err) - buf := w.Bytes() - r := io.NewBinReaderFromBuf(buf) + b := buf.Bytes() + r := gob.NewDecoder(bytes.NewReader(b)) - actual.DecodeBinary(r) - require.NoError(t, r.Err) + err = actual.DecodeBinary(r) + require.NoError(t, err) require.Equal(t, expected, actual) } diff --git a/payload/prepare_request.go b/payload/prepare_request.go index 8cd8c681..8d6b31eb 100644 --- a/payload/prepare_request.go +++ b/payload/prepare_request.go @@ -1,7 +1,8 @@ package payload import ( - "github.com/nspcc-dev/neo-go/pkg/io" + "encoding/gob" + "github.com/nspcc-dev/neo-go/pkg/util" ) @@ -29,29 +30,46 @@ type PrepareRequest interface { SetNextConsensus(nc util.Uint160) } -type prepareRequest struct { - transactionHashes []util.Uint256 - nonce uint64 - timestamp uint32 - nextConsensus util.Uint160 -} +type ( + prepareRequest struct { + transactionHashes []util.Uint256 + nonce uint64 + timestamp uint32 + nextConsensus util.Uint160 + } + // prepareRequestAux is an auxiliary structure for prepareRequest encoding. + prepareRequestAux struct { + TransactionHashes []util.Uint256 + Nonce uint64 + Timestamp uint32 + NextConsensus util.Uint160 + } +) var _ PrepareRequest = (*prepareRequest)(nil) -// EncodeBinary implements io.Serializable interface. -func (p prepareRequest) EncodeBinary(w *io.BinWriter) { - w.WriteU32LE(p.timestamp) - w.WriteU64LE(p.nonce) - w.WriteBytes(p.nextConsensus[:]) - w.WriteArray(p.transactionHashes) +// EncodeBinary implements Serializable interface. +func (p prepareRequest) EncodeBinary(w *gob.Encoder) error { + return w.Encode(&prepareRequestAux{ + TransactionHashes: p.transactionHashes, + Nonce: p.nonce, + Timestamp: p.timestamp, + NextConsensus: p.nextConsensus, + }) } -// DecodeBinary implements io.Serializable interface. -func (p *prepareRequest) DecodeBinary(r *io.BinReader) { - p.timestamp = r.ReadU32LE() - p.nonce = r.ReadU64LE() - r.ReadBytes(p.nextConsensus[:]) - r.ReadArray(&p.transactionHashes) +// DecodeBinary implements Serializable interface. +func (p *prepareRequest) DecodeBinary(r *gob.Decoder) error { + aux := new(prepareRequestAux) + if err := r.Decode(aux); err != nil { + return err + } + + p.timestamp = aux.Timestamp + p.nonce = aux.Nonce + p.nextConsensus = aux.NextConsensus + p.transactionHashes = aux.TransactionHashes + return nil } // Timestamp implements PrepareRequest interface. diff --git a/payload/prepare_response.go b/payload/prepare_response.go index 9765e8a0..0268d7df 100644 --- a/payload/prepare_response.go +++ b/payload/prepare_response.go @@ -1,7 +1,8 @@ package payload import ( - "github.com/nspcc-dev/neo-go/pkg/io" + "encoding/gob" + "github.com/nspcc-dev/neo-go/pkg/util" ) @@ -14,20 +15,34 @@ type PrepareResponse interface { SetPreparationHash(h util.Uint256) } -type prepareResponse struct { - preparationHash util.Uint256 -} +type ( + prepareResponse struct { + preparationHash util.Uint256 + } + // prepareResponseAux is an auxiliary structure for prepareResponse encoding. + prepareResponseAux struct { + PreparationHash util.Uint256 + } +) var _ PrepareResponse = (*prepareResponse)(nil) -// EncodeBinary implements io.Serializable interface. -func (p prepareResponse) EncodeBinary(w *io.BinWriter) { - w.WriteBytes(p.preparationHash[:]) +// EncodeBinary implements Serializable interface. +func (p prepareResponse) EncodeBinary(w *gob.Encoder) error { + return w.Encode(prepareResponseAux{ + PreparationHash: p.preparationHash, + }) } -// DecodeBinary implements io.Serializable interface. -func (p *prepareResponse) DecodeBinary(r *io.BinReader) { - r.ReadBytes(p.preparationHash[:]) +// DecodeBinary implements Serializable interface. +func (p *prepareResponse) DecodeBinary(r *gob.Decoder) error { + aux := new(prepareResponseAux) + if err := r.Decode(aux); err != nil { + return err + } + + p.preparationHash = aux.PreparationHash + return nil } // PreparationHash implements PrepareResponse interface. diff --git a/payload/recovery_message.go b/payload/recovery_message.go index c5afa696..117473e8 100644 --- a/payload/recovery_message.go +++ b/payload/recovery_message.go @@ -1,10 +1,10 @@ package payload import ( + "encoding/gob" "errors" "github.com/nspcc-dev/dbft/crypto" - "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/util" ) @@ -17,7 +17,7 @@ type ( GetPrepareRequest(p ConsensusPayload, validators []crypto.PublicKey, primary uint16) ConsensusPayload // GetPrepareResponses returns a slice of PrepareResponse in any order. GetPrepareResponses(p ConsensusPayload, validators []crypto.PublicKey) []ConsensusPayload - // GetChangeView returns a slice of ChangeView in any order. + // GetChangeViews returns a slice of ChangeView in any order. GetChangeViews(p ConsensusPayload, validators []crypto.PublicKey) []ConsensusPayload // GetCommits returns a slice of Commit in any order. GetCommits(p ConsensusPayload, validators []crypto.PublicKey) []ConsensusPayload @@ -36,6 +36,12 @@ type ( changeViewPayloads []changeViewCompact prepareRequest PrepareRequest } + // recoveryMessageAux is an auxiliary structure for recoveryMessage encoding. + recoveryMessageAux struct { + PreparationPayloads []preparationCompact + CommitPayloads []commitCompact + ChangeViewPayloads []changeViewCompact + } ) var _ RecoveryMessage = (*recoveryMessage)(nil) @@ -59,25 +65,25 @@ func (m *recoveryMessage) AddPayload(p ConsensusPayload) { m.preparationHash = &prepHash case PrepareResponseType: m.preparationPayloads = append(m.preparationPayloads, preparationCompact{ - validatorIndex: p.ValidatorIndex(), + ValidatorIndex: p.ValidatorIndex(), }) case ChangeViewType: m.changeViewPayloads = append(m.changeViewPayloads, changeViewCompact{ - validatorIndex: p.ValidatorIndex(), - originalViewNumber: p.ViewNumber(), - timestamp: 0, + ValidatorIndex: p.ValidatorIndex(), + OriginalViewNumber: p.ViewNumber(), + Timestamp: 0, }) case CommitType: cc := commitCompact{ - viewNumber: p.ViewNumber(), - validatorIndex: p.ValidatorIndex(), + ViewNumber: p.ViewNumber(), + ValidatorIndex: p.ValidatorIndex(), } - copy(cc.signature[:], p.GetCommit().Signature()) + copy(cc.Signature[:], p.GetCommit().Signature()) m.commitPayloads = append(m.commitPayloads, cc) } } -func fromPayload(t MessageType, recovery ConsensusPayload, p any) *Payload { +func fromPayload(t MessageType, recovery ConsensusPayload, p Serializable) *Payload { return &Payload{ message: message{ cmType: t, @@ -118,7 +124,7 @@ func (m *recoveryMessage) GetPrepareResponses(p ConsensusPayload, _ []crypto.Pub payloads[i] = fromPayload(PrepareResponseType, p, &prepareResponse{ preparationHash: *m.preparationHash, }) - payloads[i].SetValidatorIndex(resp.validatorIndex) + payloads[i].SetValidatorIndex(resp.ValidatorIndex) } return payloads @@ -130,10 +136,10 @@ func (m *recoveryMessage) GetChangeViews(p ConsensusPayload, _ []crypto.PublicKe for i, cv := range m.changeViewPayloads { payloads[i] = fromPayload(ChangeViewType, p, &changeView{ - newViewNumber: cv.originalViewNumber + 1, - timestamp: cv.timestamp, + newViewNumber: cv.OriginalViewNumber + 1, + timestamp: cv.Timestamp, }) - payloads[i].SetValidatorIndex(cv.validatorIndex) + payloads[i].SetValidatorIndex(cv.ValidatorIndex) } return payloads @@ -144,56 +150,89 @@ func (m *recoveryMessage) GetCommits(p ConsensusPayload, _ []crypto.PublicKey) [ payloads := make([]ConsensusPayload, len(m.commitPayloads)) for i, c := range m.commitPayloads { - payloads[i] = fromPayload(CommitType, p, &commit{signature: c.signature}) - payloads[i].SetValidatorIndex(c.validatorIndex) + payloads[i] = fromPayload(CommitType, p, &commit{signature: c.Signature}) + payloads[i].SetValidatorIndex(c.ValidatorIndex) } return payloads } -// EncodeBinary implements io.Serializable interface. -func (m recoveryMessage) EncodeBinary(w *io.BinWriter) { - w.WriteArray(m.changeViewPayloads) - +// EncodeBinary implements Serializable interface. +func (m recoveryMessage) EncodeBinary(w *gob.Encoder) error { hasReq := m.prepareRequest != nil - w.WriteBool(hasReq) - + if err := w.Encode(hasReq); err != nil { + return err + } if hasReq { - m.prepareRequest.(io.Serializable).EncodeBinary(w) + if err := m.prepareRequest.(Serializable).EncodeBinary(w); err != nil { + return err + } } else { if m.preparationHash == nil { - w.WriteVarUint(0) + if err := w.Encode(0); err != nil { + return err + } } else { - w.WriteVarUint(util.Uint256Size) - m.preparationHash.EncodeBinary(w) + if err := w.Encode(util.Uint256Size); err != nil { + return err + } + if err := w.Encode(m.preparationHash); err != nil { + return err + } } } - - w.WriteArray(m.preparationPayloads) - w.WriteArray(m.commitPayloads) + return w.Encode(&recoveryMessageAux{ + PreparationPayloads: m.preparationPayloads, + CommitPayloads: m.commitPayloads, + ChangeViewPayloads: m.changeViewPayloads, + }) } -// DecodeBinary implements io.Serializable interface. -func (m *recoveryMessage) DecodeBinary(r *io.BinReader) { - r.ReadArray(&m.changeViewPayloads) - - if hasReq := r.ReadBool(); hasReq { +// DecodeBinary implements Serializable interface. +func (m *recoveryMessage) DecodeBinary(r *gob.Decoder) error { + var hasReq bool + if err := r.Decode(&hasReq); err != nil { + return err + } + if hasReq { m.prepareRequest = new(prepareRequest) - m.prepareRequest.(io.Serializable).DecodeBinary(r) + if err := m.prepareRequest.(Serializable).DecodeBinary(r); err != nil { + return err + } } else { - l := r.ReadVarUint() + var l int + if err := r.Decode(&l); err != nil { + return err + } if l != 0 { if l == util.Uint256Size { m.preparationHash = new(util.Uint256) - m.preparationHash.DecodeBinary(r) + if err := r.Decode(m.preparationHash); err != nil { + return err + } } else { - r.Err = errors.New("wrong util.Uint256 length") + return errors.New("wrong util.Uint256 length") } } else { m.preparationHash = nil } } - r.ReadArray(&m.preparationPayloads) - r.ReadArray(&m.commitPayloads) + aux := new(recoveryMessageAux) + if err := r.Decode(aux); err != nil { + return err + } + m.preparationPayloads = aux.PreparationPayloads + if m.preparationPayloads == nil { + m.preparationPayloads = []preparationCompact{} + } + m.commitPayloads = aux.CommitPayloads + if m.commitPayloads == nil { + m.commitPayloads = []commitCompact{} + } + m.changeViewPayloads = aux.ChangeViewPayloads + if m.changeViewPayloads == nil { + m.changeViewPayloads = []changeViewCompact{} + } + return nil } diff --git a/payload/recovery_request.go b/payload/recovery_request.go index 44ce130c..4a8f1cc7 100644 --- a/payload/recovery_request.go +++ b/payload/recovery_request.go @@ -1,6 +1,8 @@ package payload -import "github.com/nspcc-dev/neo-go/pkg/io" +import ( + "encoding/gob" +) // RecoveryRequest represents dBFT RecoveryRequest message. type RecoveryRequest interface { @@ -10,20 +12,34 @@ type RecoveryRequest interface { SetTimestamp(ts uint64) } -type recoveryRequest struct { - timestamp uint32 -} +type ( + recoveryRequest struct { + timestamp uint32 + } + // recoveryRequestAux is an auxiliary structure for recoveryRequest encoding. + recoveryRequestAux struct { + Timestamp uint32 + } +) var _ RecoveryRequest = (*recoveryRequest)(nil) -// EncodeBinary implements io.Serializable interface. -func (m recoveryRequest) EncodeBinary(w *io.BinWriter) { - w.WriteU32LE(m.timestamp) +// EncodeBinary implements Serializable interface. +func (m recoveryRequest) EncodeBinary(w *gob.Encoder) error { + return w.Encode(&recoveryRequestAux{ + Timestamp: m.timestamp, + }) } -// DecodeBinary implements io.Serializable interface. -func (m *recoveryRequest) DecodeBinary(r *io.BinReader) { - m.timestamp = r.ReadU32LE() +// DecodeBinary implements Serializable interface. +func (m *recoveryRequest) DecodeBinary(r *gob.Decoder) error { + aux := new(recoveryRequestAux) + if err := r.Decode(aux); err != nil { + return err + } + + m.timestamp = aux.Timestamp + return nil } // Timestamp implements RecoveryRequest interface.