mirror of
https://github.com/luxfi/vm.git
synced 2026-10-30 15:13:40 +00:00
135 lines
3.0 KiB
Go
135 lines
3.0 KiB
Go
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package nets
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/math/set"
|
|
)
|
|
|
|
type chain 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
|
|
}
|
|
|
|
var _ Net = (*chain)(nil)
|
|
|
|
type Allower interface {
|
|
// IsAllowed filters out nodes that are not allowed to connect to this chain
|
|
IsAllowed(nodeID ids.NodeID, isValidator bool) bool
|
|
}
|
|
|
|
// Net keeps track of the currently bootstrapping chains in a chain. If no
|
|
// chains in the net are currently bootstrapping, the net is considered
|
|
// bootstrapped.
|
|
type Net interface {
|
|
// IsBootstrapped returns true if the chains in this chain are done bootstrapping
|
|
IsBootstrapped() bool
|
|
|
|
// Bootstrapped marks the chain as done bootstrapping
|
|
Bootstrapped(chainID ids.ID)
|
|
|
|
// OnBootstrapCompleted is called when bootstrapping completes
|
|
OnBootstrapCompleted() error
|
|
|
|
// AddChain adds a chain to this Net
|
|
AddChain(chainID ids.ID) bool
|
|
|
|
// Config returns config of this Net
|
|
Config() Config
|
|
|
|
Allower
|
|
}
|
|
|
|
type net 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) Net {
|
|
return &chain{
|
|
bootstrapping: make(set.Set[ids.ID]),
|
|
bootstrapped: make(set.Set[ids.ID]),
|
|
bootstrappedSema: make(chan struct{}),
|
|
config: config,
|
|
myNodeID: myNodeID,
|
|
}
|
|
}
|
|
|
|
func (s *chain) IsBootstrapped() bool {
|
|
s.lock.RLock()
|
|
defer s.lock.RUnlock()
|
|
|
|
return s.bootstrapping.Len() == 0
|
|
}
|
|
|
|
func (s *chain) 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 *chain) AllBootstrapped() <-chan struct{} {
|
|
return s.bootstrappedSema
|
|
}
|
|
|
|
func (s *chain) OnBootstrapCompleted() error {
|
|
// Mark net as having completed bootstrap
|
|
// This is called when all chains in the net have bootstrapped
|
|
return nil
|
|
}
|
|
|
|
func (s *chain) OnBootstrapStarted() error {
|
|
// Mark net as starting bootstrap
|
|
return nil
|
|
}
|
|
|
|
func (s *chain) 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 *chain) Config() Config {
|
|
return s.config
|
|
}
|
|
|
|
func (s *chain) IsAllowed(nodeID ids.NodeID, isValidator bool) bool {
|
|
// Case 1: NodeID is this node
|
|
// Case 2: This net is not validator-only chain
|
|
// Case 3: NodeID is a validator for this chain
|
|
// Case 4: NodeID is explicitly allowed whether it's net validator or not
|
|
return nodeID == s.myNodeID ||
|
|
!s.config.ValidatorOnly ||
|
|
isValidator ||
|
|
s.config.AllowedNodes.Contains(nodeID)
|
|
}
|