-
Notifications
You must be signed in to change notification settings - Fork 662
/
manager.go
157 lines (129 loc) · 4.06 KB
/
manager.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
150
151
152
153
154
155
156
157
// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package validators
import (
"errors"
"fmt"
"strings"
"sync"
"golang.org/x/exp/maps"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils"
"github.com/ava-labs/avalanchego/utils/crypto/bls"
)
var (
_ Manager = (*manager)(nil)
ErrMissingValidators = errors.New("missing validators")
)
// Manager holds the validator set of each subnet
type Manager interface {
fmt.Stringer
// Add a subnet's validator set to the manager.
//
// If the subnet had previously registered a validator set, false will be
// returned and the manager will not be modified.
Add(subnetID ids.ID, set Set) bool
// Get returns the validator set for the given subnet
// Returns false if the subnet doesn't exist
Get(ids.ID) (Set, bool)
}
// NewManager returns a new, empty manager
func NewManager() Manager {
return &manager{
subnetToVdrs: make(map[ids.ID]Set),
}
}
type manager struct {
lock sync.RWMutex
// Key: Subnet ID
// Value: The validators that validate the subnet
subnetToVdrs map[ids.ID]Set
}
func (m *manager) Add(subnetID ids.ID, set Set) bool {
m.lock.Lock()
defer m.lock.Unlock()
if _, exists := m.subnetToVdrs[subnetID]; exists {
return false
}
m.subnetToVdrs[subnetID] = set
return true
}
func (m *manager) Get(subnetID ids.ID) (Set, bool) {
m.lock.RLock()
defer m.lock.RUnlock()
vdrs, ok := m.subnetToVdrs[subnetID]
return vdrs, ok
}
func (m *manager) String() string {
m.lock.RLock()
defer m.lock.RUnlock()
subnets := maps.Keys(m.subnetToVdrs)
utils.Sort(subnets)
sb := strings.Builder{}
sb.WriteString(fmt.Sprintf("Validator Manager: (Size = %d)",
len(subnets),
))
for _, subnetID := range subnets {
vdrs := m.subnetToVdrs[subnetID]
sb.WriteString(fmt.Sprintf(
"\n Subnet[%s]: %s",
subnetID,
vdrs.PrefixedString(" "),
))
}
return sb.String()
}
// Add is a helper that fetches the validator set of [subnetID] from [m] and
// adds [nodeID] to the validator set.
// Returns an error if:
// - [subnetID] does not have a registered validator set in [m]
// - adding [nodeID] to the validator set returns an error
func Add(m Manager, subnetID ids.ID, nodeID ids.NodeID, pk *bls.PublicKey, txID ids.ID, weight uint64) error {
vdrs, ok := m.Get(subnetID)
if !ok {
return fmt.Errorf("%w: %s", ErrMissingValidators, subnetID)
}
return vdrs.Add(nodeID, pk, txID, weight)
}
// AddWeight is a helper that fetches the validator set of [subnetID] from [m]
// and adds [weight] to [nodeID] in the validator set.
// Returns an error if:
// - [subnetID] does not have a registered validator set in [m]
// - adding [weight] to [nodeID] in the validator set returns an error
func AddWeight(m Manager, subnetID ids.ID, nodeID ids.NodeID, weight uint64) error {
vdrs, ok := m.Get(subnetID)
if !ok {
return fmt.Errorf("%w: %s", ErrMissingValidators, subnetID)
}
return vdrs.AddWeight(nodeID, weight)
}
// RemoveWeight is a helper that fetches the validator set of [subnetID] from
// [m] and removes [weight] from [nodeID] in the validator set.
// Returns an error if:
// - [subnetID] does not have a registered validator set in [m]
// - removing [weight] from [nodeID] in the validator set returns an error
func RemoveWeight(m Manager, subnetID ids.ID, nodeID ids.NodeID, weight uint64) error {
vdrs, ok := m.Get(subnetID)
if !ok {
return fmt.Errorf("%w: %s", ErrMissingValidators, subnetID)
}
return vdrs.RemoveWeight(nodeID, weight)
}
// Contains is a helper that fetches the validator set of [subnetID] from [m]
// and returns if the validator set contains [nodeID]. If [m] does not contain a
// validator set for [subnetID], false is returned.
func Contains(m Manager, subnetID ids.ID, nodeID ids.NodeID) bool {
vdrs, ok := m.Get(subnetID)
if !ok {
return false
}
return vdrs.Contains(nodeID)
}
func NodeIDs(m Manager, subnetID ids.ID) ([]ids.NodeID, error) {
vdrs, exist := m.Get(subnetID)
if !exist {
return nil, fmt.Errorf("%w: %s", ErrMissingValidators, subnetID)
}
vdrsMap := vdrs.Map()
return maps.Keys(vdrsMap), nil
}