Skip to content

Commit e0ed581

Browse files
Merge branch 'master' into update-versions-v1.11.0-fuji
2 parents 5ccd9c3 + d372402 commit e0ed581

Some content is hidden

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

60 files changed

+2463
-744
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
os: [macos-12, ubuntu-20.04, ubuntu-22.04, windows-2022, [self-hosted, linux, ARM64, focal], [self-hosted, linux, ARM64, jammy]]
3333
steps:
3434
- uses: actions/checkout@v4
35-
- uses: actions/setup-go@v5
35+
- uses: actions/setup-go@v3
3636
with:
3737
go-version: ${{ env.go_version }}
3838
check-latest: true

chains/manager.go

Lines changed: 9 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ var (
9494
errUnknownVMType = errors.New("the vm should have type avalanche.DAGVM or snowman.ChainVM")
9595
errCreatePlatformVM = errors.New("attempted to create a chain running the PlatformVM")
9696
errNotBootstrapped = errors.New("subnets not bootstrapped")
97-
errNoPrimaryNetworkConfig = errors.New("no subnet config for primary network found")
9897
errPartialSyncAsAValidator = errors.New("partial sync should not be configured for a validator")
9998

10099
fxs = map[ids.ID]fx.Factory{
@@ -230,6 +229,8 @@ type ManagerConfig struct {
230229
StateSyncBeacons []ids.NodeID
231230

232231
ChainDataDir string
232+
233+
Subnets *Subnets
233234
}
234235

235236
type manager struct {
@@ -253,11 +254,6 @@ type manager struct {
253254
chainCreatorShutdownCh chan struct{}
254255
chainCreatorExited sync.WaitGroup
255256

256-
subnetsLock sync.RWMutex
257-
// Key: Subnet's ID
258-
// Value: Subnet description
259-
subnets map[ids.ID]subnets.Subnet
260-
261257
chainsLock sync.Mutex
262258
// Key: Chain's ID
263259
// Value: The chain
@@ -274,7 +270,6 @@ func New(config *ManagerConfig) Manager {
274270
ManagerConfig: *config,
275271
stakingSigner: config.StakingTLSCert.PrivateKey.(crypto.Signer),
276272
stakingCert: staking.CertificateFromX509(config.StakingTLSCert.Leaf),
277-
subnets: make(map[ids.ID]subnets.Subnet),
278273
chains: make(map[ids.ID]handler.Handler),
279274
chainsQueue: buffer.NewUnboundedBlockingDeque[ChainParameters](initialQueueSize),
280275
unblockChainCreatorCh: make(chan struct{}),
@@ -285,25 +280,10 @@ func New(config *ManagerConfig) Manager {
285280
// QueueChainCreation queues a chain creation request
286281
// Invariant: Tracked Subnet must be checked before calling this function
287282
func (m *manager) QueueChainCreation(chainParams ChainParameters) {
288-
m.subnetsLock.Lock()
289-
subnetID := chainParams.SubnetID
290-
sb, exists := m.subnets[subnetID]
291-
if !exists {
292-
sbConfig, ok := m.SubnetConfigs[subnetID]
293-
if !ok {
294-
// default to primary subnet config
295-
sbConfig = m.SubnetConfigs[constants.PrimaryNetworkID]
296-
}
297-
sb = subnets.New(m.NodeID, sbConfig)
298-
m.subnets[chainParams.SubnetID] = sb
299-
}
300-
addedChain := sb.AddChain(chainParams.ID)
301-
m.subnetsLock.Unlock()
302-
303-
if !addedChain {
283+
if sb, _ := m.Subnets.GetOrCreate(chainParams.SubnetID); !sb.AddChain(chainParams.ID) {
304284
m.Log.Debug("skipping chain creation",
305285
zap.String("reason", "chain already staged"),
306-
zap.Stringer("subnetID", subnetID),
286+
zap.Stringer("subnetID", chainParams.SubnetID),
307287
zap.Stringer("chainID", chainParams.ID),
308288
zap.Stringer("vmID", chainParams.VMID),
309289
)
@@ -313,7 +293,7 @@ func (m *manager) QueueChainCreation(chainParams ChainParameters) {
313293
if ok := m.chainsQueue.PushRight(chainParams); !ok {
314294
m.Log.Warn("skipping chain creation",
315295
zap.String("reason", "couldn't enqueue chain"),
316-
zap.Stringer("subnetID", subnetID),
296+
zap.Stringer("subnetID", chainParams.SubnetID),
317297
zap.Stringer("chainID", chainParams.ID),
318298
zap.Stringer("vmID", chainParams.VMID),
319299
)
@@ -331,9 +311,7 @@ func (m *manager) createChain(chainParams ChainParameters) {
331311
zap.Stringer("vmID", chainParams.VMID),
332312
)
333313

334-
m.subnetsLock.RLock()
335-
sb := m.subnets[chainParams.SubnetID]
336-
m.subnetsLock.RUnlock()
314+
sb, _ := m.Subnets.GetOrCreate(chainParams.SubnetID)
337315

338316
// Note: buildChain builds all chain's relevant objects (notably engine and handler)
339317
// but does not start their operations. Starting of the handler (which could potentially
@@ -1304,23 +1282,9 @@ func (m *manager) IsBootstrapped(id ids.ID) bool {
13041282
return chain.Context().State.Get().State == snow.NormalOp
13051283
}
13061284

1307-
func (m *manager) subnetsNotBootstrapped() []ids.ID {
1308-
m.subnetsLock.RLock()
1309-
defer m.subnetsLock.RUnlock()
1310-
1311-
subnetsBootstrapping := make([]ids.ID, 0, len(m.subnets))
1312-
for subnetID, subnet := range m.subnets {
1313-
if !subnet.IsBootstrapped() {
1314-
subnetsBootstrapping = append(subnetsBootstrapping, subnetID)
1315-
}
1316-
}
1317-
return subnetsBootstrapping
1318-
}
1319-
13201285
func (m *manager) registerBootstrappedHealthChecks() error {
13211286
bootstrappedCheck := health.CheckerFunc(func(context.Context) (interface{}, error) {
1322-
subnetIDs := m.subnetsNotBootstrapped()
1323-
if len(subnetIDs) != 0 {
1287+
if subnetIDs := m.Subnets.Bootstrapping(); len(subnetIDs) != 0 {
13241288
return subnetIDs, errNotBootstrapped
13251289
}
13261290
return []ids.ID{}, nil
@@ -1362,18 +1326,9 @@ func (m *manager) registerBootstrappedHealthChecks() error {
13621326

13631327
// Starts chain creation loop to process queued chains
13641328
func (m *manager) StartChainCreator(platformParams ChainParameters) error {
1365-
// Get the Primary Network's subnet config. If it wasn't registered, then we
1366-
// throw a fatal error.
1367-
sbConfig, ok := m.SubnetConfigs[constants.PrimaryNetworkID]
1368-
if !ok {
1369-
return errNoPrimaryNetworkConfig
1370-
}
1371-
1372-
sb := subnets.New(m.NodeID, sbConfig)
1373-
m.subnetsLock.Lock()
1374-
m.subnets[platformParams.SubnetID] = sb
1329+
// Add the P-Chain to the Primary Network
1330+
sb, _ := m.Subnets.GetOrCreate(constants.PrimaryNetworkID)
13751331
sb.AddChain(platformParams.ID)
1376-
m.subnetsLock.Unlock()
13771332

13781333
// The P-chain is created synchronously to ensure that `VM.Initialize` has
13791334
// finished before returning from this function. This is required because

chains/subnets.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
2+
// See the file LICENSE for licensing terms.
3+
4+
package chains
5+
6+
import (
7+
"errors"
8+
"sync"
9+
10+
"github.com/ava-labs/avalanchego/ids"
11+
"github.com/ava-labs/avalanchego/subnets"
12+
"github.com/ava-labs/avalanchego/utils/constants"
13+
)
14+
15+
var ErrNoPrimaryNetworkConfig = errors.New("no subnet config for primary network found")
16+
17+
// Subnets holds the currently running subnets on this node
18+
type Subnets struct {
19+
nodeID ids.NodeID
20+
configs map[ids.ID]subnets.Config
21+
22+
lock sync.RWMutex
23+
subnets map[ids.ID]subnets.Subnet
24+
}
25+
26+
// GetOrCreate returns a subnet running on this node, or creates one if it was
27+
// not running before. Returns the subnet and if the subnet was created.
28+
func (s *Subnets) GetOrCreate(subnetID ids.ID) (subnets.Subnet, bool) {
29+
s.lock.Lock()
30+
defer s.lock.Unlock()
31+
32+
if subnet, ok := s.subnets[subnetID]; ok {
33+
return subnet, false
34+
}
35+
36+
// Default to the primary network config if a subnet config was not
37+
// specified
38+
config, ok := s.configs[subnetID]
39+
if !ok {
40+
config = s.configs[constants.PrimaryNetworkID]
41+
}
42+
43+
subnet := subnets.New(s.nodeID, config)
44+
s.subnets[subnetID] = subnet
45+
46+
return subnet, true
47+
}
48+
49+
// Bootstrapping returns the subnetIDs of any chains that are still
50+
// bootstrapping.
51+
func (s *Subnets) Bootstrapping() []ids.ID {
52+
s.lock.RLock()
53+
defer s.lock.RUnlock()
54+
55+
subnetsBootstrapping := make([]ids.ID, 0, len(s.subnets))
56+
for subnetID, subnet := range s.subnets {
57+
if !subnet.IsBootstrapped() {
58+
subnetsBootstrapping = append(subnetsBootstrapping, subnetID)
59+
}
60+
}
61+
62+
return subnetsBootstrapping
63+
}
64+
65+
// NewSubnets returns an instance of Subnets
66+
func NewSubnets(
67+
nodeID ids.NodeID,
68+
configs map[ids.ID]subnets.Config,
69+
) (*Subnets, error) {
70+
if _, ok := configs[constants.PrimaryNetworkID]; !ok {
71+
return nil, ErrNoPrimaryNetworkConfig
72+
}
73+
74+
s := &Subnets{
75+
nodeID: nodeID,
76+
configs: configs,
77+
subnets: make(map[ids.ID]subnets.Subnet),
78+
}
79+
80+
_, _ = s.GetOrCreate(constants.PrimaryNetworkID)
81+
return s, nil
82+
}

chains/subnets_test.go

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
2+
// See the file LICENSE for licensing terms.
3+
4+
package chains
5+
6+
import (
7+
"testing"
8+
9+
"github.com/stretchr/testify/require"
10+
11+
"github.com/ava-labs/avalanchego/ids"
12+
"github.com/ava-labs/avalanchego/subnets"
13+
"github.com/ava-labs/avalanchego/utils/constants"
14+
)
15+
16+
func TestNewSubnets(t *testing.T) {
17+
require := require.New(t)
18+
config := map[ids.ID]subnets.Config{
19+
constants.PrimaryNetworkID: {},
20+
}
21+
22+
subnets, err := NewSubnets(ids.EmptyNodeID, config)
23+
require.NoError(err)
24+
25+
subnet, ok := subnets.GetOrCreate(constants.PrimaryNetworkID)
26+
require.False(ok)
27+
require.Equal(config[constants.PrimaryNetworkID], subnet.Config())
28+
}
29+
30+
func TestNewSubnetsNoPrimaryNetworkConfig(t *testing.T) {
31+
require := require.New(t)
32+
config := map[ids.ID]subnets.Config{}
33+
34+
_, err := NewSubnets(ids.EmptyNodeID, config)
35+
require.ErrorIs(err, ErrNoPrimaryNetworkConfig)
36+
}
37+
38+
func TestSubnetsGetOrCreate(t *testing.T) {
39+
testSubnetID := ids.GenerateTestID()
40+
41+
type args struct {
42+
subnetID ids.ID
43+
want bool
44+
}
45+
46+
tests := []struct {
47+
name string
48+
args []args
49+
}{
50+
{
51+
name: "adding duplicate subnet is a noop",
52+
args: []args{
53+
{
54+
subnetID: testSubnetID,
55+
want: true,
56+
},
57+
{
58+
subnetID: testSubnetID,
59+
},
60+
},
61+
},
62+
{
63+
name: "adding unique subnets succeeds",
64+
args: []args{
65+
{
66+
subnetID: ids.GenerateTestID(),
67+
want: true,
68+
},
69+
{
70+
subnetID: ids.GenerateTestID(),
71+
want: true,
72+
},
73+
{
74+
subnetID: ids.GenerateTestID(),
75+
want: true,
76+
},
77+
},
78+
},
79+
}
80+
81+
for _, tt := range tests {
82+
t.Run(tt.name, func(t *testing.T) {
83+
require := require.New(t)
84+
config := map[ids.ID]subnets.Config{
85+
constants.PrimaryNetworkID: {},
86+
}
87+
subnets, err := NewSubnets(ids.EmptyNodeID, config)
88+
require.NoError(err)
89+
90+
for _, arg := range tt.args {
91+
_, got := subnets.GetOrCreate(arg.subnetID)
92+
require.Equal(arg.want, got)
93+
}
94+
})
95+
}
96+
}
97+
98+
func TestSubnetConfigs(t *testing.T) {
99+
testSubnetID := ids.GenerateTestID()
100+
101+
tests := []struct {
102+
name string
103+
config map[ids.ID]subnets.Config
104+
subnetID ids.ID
105+
want subnets.Config
106+
}{
107+
{
108+
name: "default to primary network config",
109+
config: map[ids.ID]subnets.Config{
110+
constants.PrimaryNetworkID: {},
111+
},
112+
subnetID: testSubnetID,
113+
want: subnets.Config{},
114+
},
115+
{
116+
name: "use subnet config",
117+
config: map[ids.ID]subnets.Config{
118+
constants.PrimaryNetworkID: {},
119+
testSubnetID: {
120+
GossipConfig: subnets.GossipConfig{
121+
AcceptedFrontierValidatorSize: 123456789,
122+
},
123+
},
124+
},
125+
subnetID: testSubnetID,
126+
want: subnets.Config{
127+
GossipConfig: subnets.GossipConfig{
128+
AcceptedFrontierValidatorSize: 123456789,
129+
},
130+
},
131+
},
132+
}
133+
134+
for _, tt := range tests {
135+
t.Run(tt.name, func(t *testing.T) {
136+
require := require.New(t)
137+
138+
subnets, err := NewSubnets(ids.EmptyNodeID, tt.config)
139+
require.NoError(err)
140+
141+
subnet, ok := subnets.GetOrCreate(tt.subnetID)
142+
require.True(ok)
143+
144+
require.Equal(tt.want, subnet.Config())
145+
})
146+
}
147+
}
148+
149+
func TestSubnetsBootstrapping(t *testing.T) {
150+
require := require.New(t)
151+
152+
config := map[ids.ID]subnets.Config{
153+
constants.PrimaryNetworkID: {},
154+
}
155+
156+
subnets, err := NewSubnets(ids.EmptyNodeID, config)
157+
require.NoError(err)
158+
159+
subnetID := ids.GenerateTestID()
160+
chainID := ids.GenerateTestID()
161+
162+
subnet, ok := subnets.GetOrCreate(subnetID)
163+
require.True(ok)
164+
165+
// Start bootstrapping
166+
subnet.AddChain(chainID)
167+
bootstrapping := subnets.Bootstrapping()
168+
require.Contains(bootstrapping, subnetID)
169+
170+
// Finish bootstrapping
171+
subnet.Bootstrapped(chainID)
172+
require.Empty(subnets.Bootstrapping())
173+
}

0 commit comments

Comments
 (0)