-
Notifications
You must be signed in to change notification settings - Fork 14
/
message.go
99 lines (80 loc) · 2.14 KB
/
message.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package pbft
import (
"bytes"
"fmt"
)
type MsgType int32
const (
MessageReq_RoundChange MsgType = 0
MessageReq_Preprepare MsgType = 1
MessageReq_Commit MsgType = 2
MessageReq_Prepare MsgType = 3
)
func (m MsgType) String() string {
switch m {
case MessageReq_RoundChange:
return "RoundChange"
case MessageReq_Preprepare:
return "Preprepare"
case MessageReq_Commit:
return "Commit"
case MessageReq_Prepare:
return "Prepare"
default:
panic(fmt.Sprintf("BUG: Bad msgtype %d", m))
}
}
type MessageReq struct {
// type is the type of the message
Type MsgType `json:"type"`
// from is the address of the sender
From NodeID `json:"from"`
// seal is the committed seal for the proposal (only for commit messages)
Seal []byte `json:"seal"`
// view is the view assigned to the message
View *View `json:"view"`
// hash of the proposal
Hash []byte `json:"hash"`
// proposal is the arbitrary data proposal (only for preprepare messages)
Proposal []byte `json:"proposal"`
}
func (m MessageReq) String() string {
return fmt.Sprintf("message - type: %s from: %s, view: %v, proposal: %v, hash: %v, seal: %v", m.Type, m.From, m.View, m.Proposal, m.Hash, m.Seal)
}
func (m *MessageReq) Validate() error {
// Hash field has to exist for state != RoundStateChange
if m.Type != MessageReq_RoundChange {
if m.Hash == nil {
return fmt.Errorf("hash is empty for type %s", m.Type.String())
}
}
// TODO
return nil
}
func (m *MessageReq) SetProposal(proposal []byte) {
m.Proposal = append([]byte{}, proposal...)
}
func (m *MessageReq) Copy() *MessageReq {
mm := new(MessageReq)
*mm = *m
if m.View != nil {
mm.View = m.View.Copy()
}
if m.Proposal != nil {
mm.SetProposal(m.Proposal)
}
if m.Seal != nil {
mm.Seal = append([]byte{}, m.Seal...)
}
return mm
}
// Equal compares if two messages are equal
func (m *MessageReq) Equal(other *MessageReq) bool {
return other != nil &&
m.Type == other.Type && m.From == other.From &&
bytes.Equal(m.Proposal, other.Proposal) &&
bytes.Equal(m.Hash, other.Hash) &&
bytes.Equal(m.Seal, other.Seal) &&
m.View.Round == other.View.Round &&
m.View.Sequence == other.View.Sequence
}