-
Notifications
You must be signed in to change notification settings - Fork 671
/
subnet.go
105 lines (83 loc) · 2.34 KB
/
subnet.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
// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package subnets
import (
"sync"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/snow/engine/common"
"github.com/ava-labs/avalanchego/utils/set"
)
var _ Subnet = (*subnet)(nil)
type Allower interface {
// IsAllowed filters out nodes that are not allowed to connect to this subnet
IsAllowed(nodeID ids.NodeID, isValidator bool) bool
}
// Subnet keeps track of the currently bootstrapping chains in a subnet. If no
// chains in the subnet are currently bootstrapping, the subnet is considered
// bootstrapped.
type Subnet interface {
common.BootstrapTracker
// AddChain adds a chain to this Subnet
AddChain(chainID ids.ID) bool
// Config returns config of this Subnet
Config() Config
Allower
}
type subnet struct {
lock sync.RWMutex
bootstrapping set.Set[ids.ID]
bootstrapped set.Set[ids.ID]
once sync.Once
bootstrappedSema chan struct{}
config Config
myNodeID ids.NodeID
}
func New(myNodeID ids.NodeID, config Config) Subnet {
return &subnet{
bootstrappedSema: make(chan struct{}),
config: config,
myNodeID: myNodeID,
}
}
func (s *subnet) IsBootstrapped() bool {
s.lock.RLock()
defer s.lock.RUnlock()
return s.bootstrapping.Len() == 0
}
func (s *subnet) Bootstrapped(chainID ids.ID) {
s.lock.Lock()
defer s.lock.Unlock()
s.bootstrapping.Remove(chainID)
s.bootstrapped.Add(chainID)
if s.bootstrapping.Len() > 0 {
return
}
s.once.Do(func() {
close(s.bootstrappedSema)
})
}
func (s *subnet) OnBootstrapCompleted() chan struct{} {
return s.bootstrappedSema
}
func (s *subnet) AddChain(chainID ids.ID) bool {
s.lock.Lock()
defer s.lock.Unlock()
if s.bootstrapping.Contains(chainID) || s.bootstrapped.Contains(chainID) {
return false
}
s.bootstrapping.Add(chainID)
return true
}
func (s *subnet) Config() Config {
return s.config
}
func (s *subnet) IsAllowed(nodeID ids.NodeID, isValidator bool) bool {
// Case 1: NodeID is this node
// Case 2: This subnet is not validator-only subnet
// Case 3: NodeID is a validator for this chain
// Case 4: NodeID is explicitly allowed whether it's subnet validator or not
return nodeID == s.myNodeID ||
!s.config.ValidatorOnly ||
isValidator ||
s.config.AllowedNodes.Contains(nodeID)
}