-
Notifications
You must be signed in to change notification settings - Fork 211
/
types.go
149 lines (127 loc) · 3.2 KB
/
types.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package hare3
import (
"fmt"
"go.uber.org/zap/zapcore"
"github.com/spacemeshos/go-spacemesh/codec"
"github.com/spacemeshos/go-spacemesh/common/types"
"github.com/spacemeshos/go-spacemesh/hash"
"github.com/spacemeshos/go-spacemesh/log"
)
type Round uint8
var roundNames = [...]string{"preround", "hardlock", "softlock", "propose", "wait1", "wait2", "commit", "notify"}
func (r Round) String() string {
return roundNames[r]
}
// NOTE(dshulyak) changes in order is a breaking change.
const (
preround Round = iota
hardlock
softlock
propose
wait1
wait2
commit
notify
)
//go:generate scalegen
type IterRound struct {
Iter uint8
Round Round
}
// Delay returns number of network delays since specified iterround.
func (ir IterRound) Delay(since IterRound) int {
delay := int(ir.Absolute() - since.Absolute())
if delay < 0 {
return 0
}
return delay
}
func (ir IterRound) IsMessageRound() bool {
switch ir.Round {
case preround:
return true
case propose:
return true
case commit:
return true
case notify:
return true
}
return false
}
func (ir IterRound) Absolute() uint32 {
return uint32(ir.Iter*uint8(notify) + uint8(ir.Round))
}
type Value struct {
// Proposals is set in messages for preround and propose rounds.
Proposals []types.ProposalID `scale:"max=200"`
// Reference is set in messages for commit and notify rounds.
Reference *types.Hash32
}
type Body struct {
Layer types.LayerID
IterRound
Value Value
Eligibility types.HareEligibility
}
type Message struct {
Body
Sender types.NodeID
Signature types.EdSignature
}
func (m *Message) ToHash() types.Hash32 {
hash := hash.New()
codec.MustEncodeTo(hash, &m.Body)
var rst types.Hash32
hash.Sum(rst[:0])
return rst
}
func (m *Message) ToMetadata() types.HareMetadata {
return types.HareMetadata{
Layer: m.Layer,
Round: m.Absolute(),
MsgHash: m.ToHash(),
}
}
func (m *Message) ToMalfeasanceProof() types.HareProofMsg {
return types.HareProofMsg{
InnerMsg: m.ToMetadata(),
SmesherID: m.Sender,
Signature: m.Signature,
}
}
func (m *Message) key() messageKey {
return messageKey{
Sender: m.Sender,
IterRound: m.IterRound,
}
}
func (m *Message) ToBytes() []byte {
return codec.MustEncode(m)
}
func (m *Message) Validate() error {
if (m.Round == commit || m.Round == notify) && m.Value.Reference == nil {
return fmt.Errorf("reference can't be nil in commit or notify rounds")
} else if (m.Round == preround || m.Round == propose) && m.Value.Reference != nil {
return fmt.Errorf("reference is set to not nil in round %s", m.Round)
}
return nil
}
func (m *Message) MarshalLogObject(encoder zapcore.ObjectEncoder) error {
encoder.AddUint32("lid", m.Layer.Uint32())
encoder.AddUint8("iter", m.Iter)
encoder.AddString("round", m.Round.String())
encoder.AddString("sender", m.Sender.ShortString())
if m.Value.Proposals != nil {
encoder.AddArray("full", zapcore.ArrayMarshalerFunc(func(encoder log.ArrayEncoder) error {
for _, id := range m.Value.Proposals {
encoder.AppendString(types.Hash20(id).ShortString())
}
return nil
}))
} else if m.Value.Reference != nil {
encoder.AddString("ref", m.Value.Reference.ShortString())
}
encoder.AddUint16("vrf_count", m.Eligibility.Count)
return nil
}