Skip to content

Commit 7b7931b

Browse files
ceyonurabi87StephenButtolph
authored
Redesign validator set management to enable tracking all subnets (#1857)
Signed-off-by: Ceyhun Onur <ceyhunonur54@gmail.com> Co-authored-by: Alberto Benegiamo <alberto.benegiamo@gmail.com> Co-authored-by: Stephen Buttolph <stephen@avalabs.org>
1 parent 4cd7051 commit 7b7931b

File tree

76 files changed

+1950
-1374
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+1950
-1374
lines changed

api/info/service.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717
"github.com/ava-labs/avalanchego/network"
1818
"github.com/ava-labs/avalanchego/network/peer"
1919
"github.com/ava-labs/avalanchego/snow/networking/benchlist"
20-
"github.com/ava-labs/avalanchego/snow/validators"
2120
"github.com/ava-labs/avalanchego/utils/constants"
2221
"github.com/ava-labs/avalanchego/utils/ips"
2322
"github.com/ava-labs/avalanchego/utils/json"
@@ -37,7 +36,6 @@ type Info struct {
3736
networking network.Network
3837
chainManager chains.Manager
3938
vmManager vms.Manager
40-
validators validators.Set
4139
benchlist benchlist.Manager
4240
}
4341

@@ -65,7 +63,6 @@ func NewService(
6563
vmManager vms.Manager,
6664
myIP ips.DynamicIPPort,
6765
network network.Network,
68-
validators validators.Set,
6966
benchlist benchlist.Manager,
7067
) (http.Handler, error) {
7168
server := rpc.NewServer()
@@ -80,7 +77,6 @@ func NewService(
8077
vmManager: vmManager,
8178
myIP: myIP,
8279
networking: network,
83-
validators: validators,
8480
benchlist: benchlist,
8581
},
8682
"info",

chains/manager.go

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -148,15 +148,15 @@ type ChainParameters struct {
148148
// The IDs of the feature extensions this chain is running.
149149
FxIDs []ids.ID
150150
// Invariant: Only used when [ID] is the P-chain ID.
151-
CustomBeacons validators.Set
151+
CustomBeacons validators.Manager
152152
}
153153

154154
type chain struct {
155155
Name string
156156
Context *snow.ConsensusContext
157157
VM common.VM
158158
Handler handler.Handler
159-
Beacons validators.Set
159+
Beacons validators.Manager
160160
}
161161

162162
// ChainConfig is configuration settings for the current execution.
@@ -531,15 +531,10 @@ func (m *manager) buildChain(chainParams ChainParameters, sb subnets.Subnet) (*c
531531
}
532532
}
533533

534-
var vdrs validators.Set // Validators validating this blockchain
535-
var hasValidators bool
536-
if m.SybilProtectionEnabled {
537-
vdrs, hasValidators = m.Validators.Get(chainParams.SubnetID)
538-
} else { // Sybil protection is disabled. Every peer validates every subnet.
539-
vdrs, hasValidators = m.Validators.Get(constants.PrimaryNetworkID)
540-
}
541-
if !hasValidators {
542-
return nil, fmt.Errorf("couldn't get validator set of subnet with ID %s. The subnet may not exist", chainParams.SubnetID)
534+
vdrs := m.Validators
535+
if !m.SybilProtectionEnabled {
536+
// If sybil protection is disabled, everyone validates every chain
537+
vdrs = validators.NewOverriddenManager(constants.PrimaryNetworkID, vdrs)
543538
}
544539

545540
var chain *chain
@@ -594,7 +589,7 @@ func (m *manager) AddRegistrant(r Registrant) {
594589
func (m *manager) createAvalancheChain(
595590
ctx *snow.ConsensusContext,
596591
genesisData []byte,
597-
vdrs validators.Set,
592+
vdrs validators.Manager,
598593
vm vertex.LinearizableVMWithEngine,
599594
fxs []*common.Fx,
600595
sb subnets.Subnet,
@@ -816,7 +811,10 @@ func (m *manager) createAvalancheChain(
816811
appSender: snowmanMessageSender,
817812
}
818813

819-
bootstrapWeight := vdrs.Weight()
814+
bootstrapWeight, err := vdrs.TotalWeight(ctx.SubnetID)
815+
if err != nil {
816+
return nil, fmt.Errorf("error while fetching weight for subnet %s: %w", ctx.SubnetID, err)
817+
}
820818

821819
consensusParams := sb.Config().ConsensusParameters
822820
sampleK := consensusParams.K
@@ -828,7 +826,7 @@ func (m *manager) createAvalancheChain(
828826
if err != nil {
829827
return nil, fmt.Errorf("error creating peer tracker: %w", err)
830828
}
831-
vdrs.RegisterCallbackListener(connectedValidators)
829+
vdrs.RegisterCallbackListener(ctx.SubnetID, connectedValidators)
832830

833831
// Asynchronously passes messages from the network to the consensus engine
834832
h, err := handler.New(
@@ -848,7 +846,7 @@ func (m *manager) createAvalancheChain(
848846

849847
connectedBeacons := tracker.NewPeers()
850848
startupTracker := tracker.NewStartup(connectedBeacons, (3*bootstrapWeight+3)/4)
851-
vdrs.RegisterCallbackListener(startupTracker)
849+
vdrs.RegisterCallbackListener(ctx.SubnetID, startupTracker)
852850

853851
snowmanCommonCfg := common.Config{
854852
Ctx: ctx,
@@ -998,8 +996,8 @@ func (m *manager) createAvalancheChain(
998996
func (m *manager) createSnowmanChain(
999997
ctx *snow.ConsensusContext,
1000998
genesisData []byte,
1001-
vdrs validators.Set,
1002-
beacons validators.Set,
999+
vdrs validators.Manager,
1000+
beacons validators.Manager,
10031001
vm block.ChainVM,
10041002
fxs []*common.Fx,
10051003
sb subnets.Subnet,
@@ -1164,7 +1162,10 @@ func (m *manager) createSnowmanChain(
11641162
return nil, err
11651163
}
11661164

1167-
bootstrapWeight := beacons.Weight()
1165+
bootstrapWeight, err := beacons.TotalWeight(ctx.SubnetID)
1166+
if err != nil {
1167+
return nil, fmt.Errorf("error while fetching weight for subnet %s: %w", ctx.SubnetID, err)
1168+
}
11681169

11691170
consensusParams := sb.Config().ConsensusParameters
11701171
sampleK := consensusParams.K
@@ -1176,7 +1177,7 @@ func (m *manager) createSnowmanChain(
11761177
if err != nil {
11771178
return nil, fmt.Errorf("error creating peer tracker: %w", err)
11781179
}
1179-
vdrs.RegisterCallbackListener(connectedValidators)
1180+
vdrs.RegisterCallbackListener(ctx.SubnetID, connectedValidators)
11801181

11811182
// Asynchronously passes messages from the network to the consensus engine
11821183
h, err := handler.New(
@@ -1196,7 +1197,7 @@ func (m *manager) createSnowmanChain(
11961197

11971198
connectedBeacons := tracker.NewPeers()
11981199
startupTracker := tracker.NewStartup(connectedBeacons, (3*bootstrapWeight+3)/4)
1199-
beacons.RegisterCallbackListener(startupTracker)
1200+
beacons.RegisterCallbackListener(ctx.SubnetID, startupTracker)
12001201

12011202
commonCfg := common.Config{
12021203
Ctx: ctx,
@@ -1358,7 +1359,7 @@ func (m *manager) registerBootstrappedHealthChecks() error {
13581359
if !m.IsBootstrapped(constants.PlatformChainID) {
13591360
return "node is currently bootstrapping", nil
13601361
}
1361-
if !validators.Contains(m.Validators, constants.PrimaryNetworkID, m.NodeID) {
1362+
if !m.Validators.Contains(constants.PrimaryNetworkID, m.NodeID) {
13621363
return "node is not a primary network validator", nil
13631364
}
13641365

network/config.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ type Config struct {
134134
TLSKey crypto.Signer `json:"-"`
135135

136136
// TrackedSubnets of the node.
137-
TrackedSubnets set.Set[ids.ID] `json:"-"`
138-
Beacons validators.Set `json:"-"`
137+
TrackedSubnets set.Set[ids.ID] `json:"-"`
138+
Beacons validators.Manager `json:"-"`
139139

140140
// Validators are the current validators in the Avalanche network
141141
Validators validators.Manager `json:"-"`

network/example_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ func (t *testExternalHandler) Disconnected(nodeID ids.NodeID) {
5858
)
5959
}
6060

61-
type testAggressiveValidatorSet struct {
62-
validators.Set
61+
type testAggressiveValidatorManager struct {
62+
validators.Manager
6363
}
6464

65-
func (*testAggressiveValidatorSet) Contains(ids.NodeID) bool {
65+
func (*testAggressiveValidatorManager) Contains(ids.ID, ids.NodeID) bool {
6666
return true
6767
}
6868

@@ -78,8 +78,8 @@ func ExampleNewTestNetwork() {
7878

7979
// Needs to be periodically updated by the caller to have the latest
8080
// validator set
81-
validators := &testAggressiveValidatorSet{
82-
Set: validators.NewSet(),
81+
validators := &testAggressiveValidatorManager{
82+
Manager: validators.NewManager(),
8383
}
8484

8585
// If we want to be able to communicate with non-primary network subnets, we

network/network.go

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import (
3131
"github.com/ava-labs/avalanchego/proto/pb/p2p"
3232
"github.com/ava-labs/avalanchego/snow/networking/router"
3333
"github.com/ava-labs/avalanchego/snow/networking/sender"
34-
"github.com/ava-labs/avalanchego/snow/validators"
3534
"github.com/ava-labs/avalanchego/subnets"
3635
"github.com/ava-labs/avalanchego/utils/constants"
3736
"github.com/ava-labs/avalanchego/utils/ips"
@@ -55,12 +54,10 @@ var (
5554
_ sender.ExternalSender = (*network)(nil)
5655
_ Network = (*network)(nil)
5756

58-
errMissingPrimaryValidators = errors.New("missing primary validator set")
59-
errNotValidator = errors.New("node is not a validator")
60-
errNotTracked = errors.New("subnet is not tracked")
61-
errSubnetNotExist = errors.New("subnet does not exist")
62-
errExpectedProxy = errors.New("expected proxy")
63-
errExpectedTCPProtocol = errors.New("expected TCP protocol")
57+
errNotValidator = errors.New("node is not a validator")
58+
errNotTracked = errors.New("subnet is not tracked")
59+
errExpectedProxy = errors.New("expected proxy")
60+
errExpectedTCPProtocol = errors.New("expected TCP protocol")
6461
)
6562

6663
// Network defines the functionality of the networking library.
@@ -189,11 +186,6 @@ func NewNetwork(
189186
dialer dialer.Dialer,
190187
router router.ExternalHandler,
191188
) (Network, error) {
192-
primaryNetworkValidators, ok := config.Validators.Get(constants.PrimaryNetworkID)
193-
if !ok {
194-
return nil, errMissingPrimaryValidators
195-
}
196-
197189
if config.ProxyEnabled {
198190
// Wrap the listener to process the proxy header.
199191
listener = &proxyproto.Listener{
@@ -220,7 +212,7 @@ func NewNetwork(
220212
log,
221213
config.Namespace,
222214
metricsRegisterer,
223-
primaryNetworkValidators,
215+
config.Validators,
224216
config.ThrottlerConfig.InboundMsgThrottlerConfig,
225217
config.ResourceTracker,
226218
config.CPUTargeter,
@@ -234,7 +226,7 @@ func NewNetwork(
234226
log,
235227
config.Namespace,
236228
metricsRegisterer,
237-
primaryNetworkValidators,
229+
config.Validators,
238230
config.ThrottlerConfig.OutboundMsgThrottlerConfig,
239231
)
240232
if err != nil {
@@ -468,7 +460,7 @@ func (n *network) Connected(nodeID ids.NodeID) {
468460
// peer is a validator/beacon.
469461
func (n *network) AllowConnection(nodeID ids.NodeID) bool {
470462
return !n.config.RequireValidatorToConnect ||
471-
validators.Contains(n.config.Validators, constants.PrimaryNetworkID, n.config.MyNodeID) ||
463+
n.config.Validators.Contains(constants.PrimaryNetworkID, n.config.MyNodeID) ||
472464
n.WantsConnection(nodeID)
473465
}
474466

@@ -807,7 +799,7 @@ func (n *network) WantsConnection(nodeID ids.NodeID) bool {
807799
}
808800

809801
func (n *network) wantsConnection(nodeID ids.NodeID) bool {
810-
return validators.Contains(n.config.Validators, constants.PrimaryNetworkID, nodeID) ||
802+
return n.config.Validators.Contains(constants.PrimaryNetworkID, nodeID) ||
811803
n.manuallyTrackedIDs.Contains(nodeID)
812804
}
813805

@@ -862,7 +854,7 @@ func (n *network) getPeers(
862854
continue
863855
}
864856

865-
isValidator := validators.Contains(n.config.Validators, subnetID, nodeID)
857+
isValidator := n.config.Validators.Contains(subnetID, nodeID)
866858
// check if the peer is allowed to connect to the subnet
867859
if !allower.IsAllowed(nodeID, isValidator) {
868860
continue
@@ -881,14 +873,9 @@ func (n *network) samplePeers(
881873
numPeersToSample int,
882874
allower subnets.Allower,
883875
) []peer.Peer {
884-
subnetValidators, ok := n.config.Validators.Get(subnetID)
885-
if !ok {
886-
return nil
887-
}
888-
889876
// If there are fewer validators than [numValidatorsToSample], then only
890877
// sample [numValidatorsToSample] validators.
891-
subnetValidatorsLen := subnetValidators.Len()
878+
subnetValidatorsLen := n.config.Validators.Count(subnetID)
892879
if subnetValidatorsLen < numValidatorsToSample {
893880
numValidatorsToSample = subnetValidatorsLen
894881
}
@@ -906,7 +893,7 @@ func (n *network) samplePeers(
906893
}
907894

908895
peerID := p.ID()
909-
isValidator := subnetValidators.Contains(peerID)
896+
isValidator := n.config.Validators.Contains(subnetID, peerID)
910897
// check if the peer is allowed to connect to the subnet
911898
if !allower.IsAllowed(peerID, isValidator) {
912899
return false
@@ -1343,18 +1330,18 @@ func (n *network) NodeUptime(subnetID ids.ID) (UptimeResult, error) {
13431330
return UptimeResult{}, errNotTracked
13441331
}
13451332

1346-
validators, ok := n.config.Validators.Get(subnetID)
1347-
if !ok {
1348-
return UptimeResult{}, errSubnetNotExist
1349-
}
1350-
1351-
myStake := validators.GetWeight(n.config.MyNodeID)
1333+
myStake := n.config.Validators.GetWeight(subnetID, n.config.MyNodeID)
13521334
if myStake == 0 {
13531335
return UptimeResult{}, errNotValidator
13541336
}
13551337

1338+
totalWeightInt, err := n.config.Validators.TotalWeight(subnetID)
1339+
if err != nil {
1340+
return UptimeResult{}, fmt.Errorf("error while fetching weight for subnet %s: %w", subnetID, err)
1341+
}
1342+
13561343
var (
1357-
totalWeight = float64(validators.Weight())
1344+
totalWeight = float64(totalWeightInt)
13581345
totalWeightedPercent = 100 * float64(myStake)
13591346
rewardingStake = float64(myStake)
13601347
)
@@ -1366,7 +1353,7 @@ func (n *network) NodeUptime(subnetID ids.ID) (UptimeResult, error) {
13661353
peer, _ := n.connectedPeers.GetByIndex(i)
13671354

13681355
nodeID := peer.ID()
1369-
weight := validators.GetWeight(nodeID)
1356+
weight := n.config.Validators.GetWeight(subnetID, nodeID)
13701357
if weight == 0 {
13711358
// this is not a validator skip it.
13721359
continue

0 commit comments

Comments
 (0)