-
Notifications
You must be signed in to change notification settings - Fork 211
/
notifytracker.go
76 lines (61 loc) · 2.13 KB
/
notifytracker.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
package hare
import (
"encoding/binary"
"hash/fnv"
)
// notifyTracker tracks notify messages.
// It also provides the number of notifications tracked for a given set.
type notifyTracker struct {
notifies map[string]struct{} // tracks PubKey->Notification
tracker *RefCountTracker // tracks ref count to each seen set
certificates map[uint32]struct{} // tracks Set->certificate
}
func newNotifyTracker(expectedSize int) *notifyTracker {
nt := ¬ifyTracker{}
nt.notifies = make(map[string]struct{}, expectedSize)
nt.tracker = NewRefCountTracker()
nt.certificates = make(map[uint32]struct{}, expectedSize)
return nt
}
// OnNotify tracks the provided notification message.
// Returns true if the InnerMsg didn't affect the state, false otherwise
func (nt *notifyTracker) OnNotify(msg *Msg) bool {
pub := msg.PubKey
if _, exist := nt.notifies[pub.String()]; exist { // already seenSenders
return true // ignored
}
// keep msg for pub
nt.notifies[pub.String()] = struct{}{}
// track that set
s := NewSet(msg.InnerMsg.Values)
nt.onCertificate(msg.InnerMsg.Cert.AggMsgs.Messages[0].InnerMsg.K, s)
nt.tracker.Track(s.ID())
return false
}
// NotificationsCount returns the number of notifications tracked for the provided set
func (nt *notifyTracker) NotificationsCount(s *Set) int {
return int(nt.tracker.CountStatus(s.ID()))
}
// calculates a unique id for the provided k and set.
func calcID(k int32, set *Set) uint32 {
hash := fnv.New32()
// write K
buff := make([]byte, 4)
binary.LittleEndian.PutUint32(buff, uint32(k)) // K>=0 because this not pre-round
hash.Write(buff)
// TODO: is this hash enough for this usage?
// write set ObjectID
buff = make([]byte, 4)
binary.LittleEndian.PutUint32(buff, uint32(set.ID()))
hash.Write(buff)
return hash.Sum32()
}
// tracks certificates
func (nt *notifyTracker) onCertificate(k int32, set *Set) {
nt.certificates[calcID(k, set)] = struct{}{}
}
// HasCertificate returns true if a certificate exist for the provided set in the provided round, false otherwise.
func (nt *notifyTracker) HasCertificate(k int32, set *Set) bool {
_, exist := nt.certificates[calcID(k, set)]
return exist
}