-
Notifications
You must be signed in to change notification settings - Fork 211
/
eligibility_tracker.go
68 lines (59 loc) · 1.77 KB
/
eligibility_tracker.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
package hare
import (
"sync"
"github.com/spacemeshos/go-spacemesh/common/types"
)
type Cred struct {
Count uint16
Honest bool
}
type EligibilityTracker struct {
expectedSize int
// the eligible identities (string(publicKeyBytes)) for each round and whether it is honest
nodesByRound map[uint32]map[types.NodeID]*Cred
mu sync.RWMutex
}
func NewEligibilityTracker(size int) *EligibilityTracker {
return &EligibilityTracker{
expectedSize: size,
nodesByRound: make(map[uint32]map[types.NodeID]*Cred, size),
}
}
func (et *EligibilityTracker) ForEach(round uint32, apply func(types.NodeID, *Cred)) {
et.mu.RLock()
defer et.mu.RUnlock()
_, ok := et.nodesByRound[round]
if !ok {
return
}
for pubKey, crd := range et.nodesByRound[round] {
apply(pubKey, crd)
}
}
// Track records a miner's eligibility in a given round and returns if it was known malicious prior to the update.
func (et *EligibilityTracker) Track(nodeID types.NodeID, round uint32, count uint16, honest bool) bool {
et.mu.Lock()
defer et.mu.Unlock()
if _, ok := et.nodesByRound[round]; !ok {
et.nodesByRound[round] = make(map[types.NodeID]*Cred, et.expectedSize)
}
cred, ok := et.nodesByRound[round][nodeID]
wasDishonest := cred != nil && !cred.Honest
if !ok {
et.nodesByRound[round][nodeID] = &Cred{Count: count, Honest: honest}
} else if !honest { // only update if the identity is newly malicious
et.nodesByRound[round][nodeID].Honest = false
}
return wasDishonest
}
// Dishonest returns whether an eligible identity is known malicious.
func (et *EligibilityTracker) Dishonest(nodeID types.NodeID, round uint32) bool {
et.mu.RLock()
defer et.mu.RUnlock()
if _, ok := et.nodesByRound[round]; ok {
if cred, ok2 := et.nodesByRound[round][nodeID]; ok2 {
return !cred.Honest
}
}
return false
}