Skip to content
This repository has been archived by the owner on Nov 7, 2023. It is now read-only.

Restructure Protobuf-based message implementation #148

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ require (
github.com/spf13/viper v1.3.1
github.com/stretchr/objx v0.0.0-20180825064932-ef50b0de2877 // indirect
github.com/stretchr/testify v1.2.2
golang.org/x/net v0.0.0-20181217023233-e147a9138326
golang.org/x/net v0.0.0-20181217023233-e147a9138326 // indirect
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f
golang.org/x/sys v0.0.0-20181213200352-4d1cda033e06 // indirect
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
google.golang.org/genproto v0.0.0-20181217193449-09cd0d62f46c // indirect
google.golang.org/grpc v1.18.0
gopkg.in/yaml.v2 v2.2.2
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ golang.org/x/sys v0.0.0-20181213200352-4d1cda033e06/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181217193449-09cd0d62f46c h1:e2ImTtBojL8kivfJ1B6rjiMeRj3yfUuK7k+HD1+D1lw=
Expand Down
45 changes: 13 additions & 32 deletions messages/protobuf/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,66 +15,47 @@
package protobuf

import (
"github.com/golang/protobuf/proto"

"github.com/hyperledger-labs/minbft/messages"
"github.com/hyperledger-labs/minbft/messages/protobuf/pb"
)

type commit struct {
Commit
}

func newCommit() *commit {
return &commit{}
pbMsg *pb.Commit
}

func (m *commit) init(r uint32, prep messages.Prepare) {
req := prep.Request()

m.Commit = Commit{Msg: &Commit_M{
func newCommit(r uint32, prep messages.Prepare) *commit {
return &commit{pbMsg: &pb.Commit{
ReplicaId: r,
PrimaryId: prep.ReplicaID(),
View: prep.View(),
Request: pbRequestFromAPI(req),
PrimaryUi: prep.UIBytes(),
Prepare: pbPrepareFromAPI(prep),
}}
}

func (m *commit) set(pbMsg *Commit) {
m.Commit = *pbMsg
func newCommitFromPb(pbMsg *pb.Commit) *commit {
return &commit{pbMsg: pbMsg}
}

func (m *commit) MarshalBinary() ([]byte, error) {
return proto.Marshal(&Message{Type: &Message_Commit{Commit: &m.Commit}})
return marshalMessage(m.pbMsg)
}

func (m *commit) ReplicaID() uint32 {
return m.Msg.GetReplicaId()
return m.pbMsg.GetReplicaId()
}

func (m *commit) Prepare() messages.Prepare {
prep := newPrepare()
prep.set(&Prepare{
Msg: &Prepare_M{
ReplicaId: m.Msg.GetPrimaryId(),
View: m.Msg.GetView(),
Request: m.Msg.GetRequest(),
},
ReplicaUi: m.Msg.GetPrimaryUi(),
})
return prep
return newPrepareFromPb(m.pbMsg.GetPrepare())
}

func (m *commit) CertifiedPayload() []byte {
return MarshalOrPanic(m.Msg)
return pb.AuthenBytesFromCommit(m.pbMsg)
}

func (m *commit) UIBytes() []byte {
return m.ReplicaUi
return m.pbMsg.Ui
}

func (m *commit) SetUIBytes(uiBytes []byte) {
m.ReplicaUi = uiBytes
m.pbMsg.Ui = uiBytes
}

func (commit) ImplementsReplicaMessage() {}
Expand Down
29 changes: 22 additions & 7 deletions messages/protobuf/commit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,29 @@ func TestCommit(t *testing.T) {
requirePrepEqual(t, prep, comm.Prepare())
})
t.Run("CertifiedPayload", func(t *testing.T) {
comm := randComm(impl)
r := comm.ReplicaID()
p := rand.Uint32()
v := rand.Uint64()
req := randReq(impl)
prepCV := rand.Uint64()
prep := newTestPrep(impl, p, v, req, prepCV)

r := rand.Uint32()
cv := rand.Uint64()
comm := newTestComm(impl, r, prep, cv)
cp := comm.CertifiedPayload()
require.NotEqual(t, cp, newTestComm(impl, r, randPrep(impl)).CertifiedPayload())

require.NotEqual(t, cp, newTestComm(impl, r,
newTestPrep(impl, rand.Uint32(), v, req, prepCV), cv).CertifiedPayload())
require.NotEqual(t, cp, newTestComm(impl, r,
newTestPrep(impl, p, rand.Uint64(), req, prepCV), cv).CertifiedPayload())
require.NotEqual(t, cp, newTestComm(impl, r,
newTestPrep(impl, p, v, randReq(impl), prepCV), cv).CertifiedPayload())
require.NotEqual(t, cp, newTestComm(impl, r,
newTestPrep(impl, p, v, req, rand.Uint64()), cv).CertifiedPayload())
})
t.Run("SetUIBytes", func(t *testing.T) {
comm := randComm(impl)
uiBytes := newTestUI(comm.CertifiedPayload())
uiBytes := randUI(comm.CertifiedPayload())
comm.SetUIBytes(uiBytes)
require.Equal(t, uiBytes, comm.UIBytes())
})
Expand All @@ -52,12 +67,12 @@ func TestCommit(t *testing.T) {
}

func randComm(impl messages.MessageImpl) messages.Commit {
return newTestComm(impl, rand.Uint32(), randPrep(impl))
return newTestComm(impl, rand.Uint32(), randPrep(impl), rand.Uint64())
}

func newTestComm(impl messages.MessageImpl, r uint32, prep messages.Prepare) messages.Commit {
func newTestComm(impl messages.MessageImpl, r uint32, prep messages.Prepare, cv uint64) messages.Commit {
comm := impl.NewCommit(r, prep)
uiBytes := newTestUI(comm.CertifiedPayload())
uiBytes := newTestUI(cv, comm.CertifiedPayload())
comm.SetUIBytes(uiBytes)
return comm
}
Expand Down
82 changes: 46 additions & 36 deletions messages/protobuf/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,70 +12,80 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// Package protobuf implements protocol message interface using
// Protocol Buffers as serialization mechanism.
package protobuf

import (
fmt "fmt"
"golang.org/x/xerrors"

"github.com/golang/protobuf/proto"

"github.com/hyperledger-labs/minbft/messages"
"github.com/hyperledger-labs/minbft/messages/protobuf/pb"
)

type impl struct{}

// NewImpl returns the package's implementation of protocol messages.
func NewImpl() messages.MessageImpl {
return &impl{}
}

func (*impl) NewFromBinary(data []byte) (messages.Message, error) {
msg := &Message{}
if err := proto.Unmarshal(data, msg); err != nil {
return nil, fmt.Errorf("failed to unmarshal message wrapper: %s", err)
pbMsg := &pb.Message{}
if err := proto.Unmarshal(data, pbMsg); err != nil {
return nil, xerrors.Errorf("failed to unmarshal message wrapper: %w", err)
}

switch t := msg.Type.(type) {
case *Message_Request:
req := newRequest()
req.set(t.Request)
return req, nil
case *Message_Prepare:
prep := newPrepare()
prep.set(t.Prepare)
return prep, nil
case *Message_Commit:
comm := newCommit()
comm.set(t.Commit)
return comm, nil
case *Message_Reply:
reply := newReply()
reply.set(t.Reply)
return reply, nil
default:
return nil, fmt.Errorf("unknown message type")
}
return typedMessageFromPb(pbMsg)
}

func (*impl) NewRequest(cl uint32, seq uint64, op []byte) messages.Request {
m := newRequest()
m.init(cl, seq, op)
return m
return newRequest(cl, seq, op)
}

func (*impl) NewPrepare(r uint32, v uint64, req messages.Request) messages.Prepare {
m := newPrepare()
m.init(r, v, req)
return m
return newPrepare(r, v, req)
}

func (*impl) NewCommit(r uint32, prep messages.Prepare) messages.Commit {
m := newCommit()
m.init(r, prep)
return m
return newCommit(r, prep)
}

func (*impl) NewReply(r, cl uint32, seq uint64, res []byte) messages.Reply {
m := newReply()
m.init(r, cl, seq, res)
return m
return newReply(r, cl, seq, res)
}

func typedMessageFromPb(pbMsg *pb.Message) (messages.Message, error) {
switch t := pbMsg.Typed.(type) {
case *pb.Message_Request:
return newRequestFromPb(t.Request), nil
case *pb.Message_Reply:
return newReplyFromPb(t.Reply), nil
case *pb.Message_Prepare:
return newPrepareFromPb(t.Prepare), nil
case *pb.Message_Commit:
return newCommitFromPb(t.Commit), nil
default:
return nil, xerrors.New("unknown message type")
}
}

func marshalMessage(m proto.Message) ([]byte, error) {
pbMsg := &pb.Message{}
switch m := m.(type) {
case *pb.Request:
pbMsg.Typed = &pb.Message_Request{Request: m}
case *pb.Reply:
pbMsg.Typed = &pb.Message_Reply{Reply: m}
case *pb.Prepare:
pbMsg.Typed = &pb.Message_Prepare{Prepare: m}
case *pb.Commit:
pbMsg.Typed = &pb.Message_Commit{Commit: m}
default:
panic("marshaling unknown message type")
}

return proto.Marshal(pbMsg)
}
Loading