Skip to content

Separate subnet stake connected health and metrics from P-chain #1358

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 37 commits into from
Jun 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
fbb8220
move percent connected health checks and metrics to handlers
ceyonur Apr 14, 2023
46335b0
add & fix tests
ceyonur Apr 27, 2023
9992c4d
move stake metrics to state
ceyonur Apr 27, 2023
359195a
Merge branch 'dev' into tag-stake-connected-health
ceyonur Apr 27, 2023
185a97d
Merge branch 'dev' into tag-stake-connected-health
ceyonur Apr 27, 2023
d52875d
use contains
ceyonur Apr 27, 2023
7286e88
Update snow/context.go
ceyonur Apr 28, 2023
327b157
expand peer tracker for total weight & use it in handler
ceyonur May 23, 2023
003f0b0
remove duplicate code
ceyonur May 23, 2023
8243dd7
Merge branch 'dev' into tag-stake-connected-health
ceyonur May 23, 2023
5756f92
move UntilUnstake metrics to platformvm
ceyonur May 23, 2023
4c2cbef
Merge branch 'tag-stake-connected-health' of github.com:ava-labs/aval…
ceyonur May 23, 2023
98ebbd1
Merge branch 'dev' into tag-stake-connected-health
ceyonur May 23, 2023
1eda131
use peerTracker instead of validators for weight
ceyonur May 23, 2023
20d7302
move min stake calculation to consensus params
ceyonur May 25, 2023
3b2f91b
fix race in percent calculation
ceyonur May 25, 2023
df87993
nit
StephenButtolph May 25, 2023
647a306
nit
StephenButtolph May 26, 2023
696da19
nit
StephenButtolph May 26, 2023
467ea62
Remove unsafe exported function + potential deadlock
StephenButtolph May 26, 2023
a1e6df4
nit
StephenButtolph May 26, 2023
317ba04
nits
StephenButtolph May 26, 2023
1dc5034
nit
StephenButtolph May 26, 2023
225136b
nit
StephenButtolph May 26, 2023
60dad1b
cleanup chain manager slightly
StephenButtolph May 26, 2023
c348b2e
Merge branch 'dev' into tag-stake-connected-health
StephenButtolph May 26, 2023
108a634
Merge branch 'dev' into tag-stake-connected-health
abi87 May 29, 2023
58cf93c
merged
StephenButtolph May 30, 2023
ce45da6
make metric update async
StephenButtolph May 30, 2023
09eca53
reduce diff
StephenButtolph May 30, 2023
ba65433
reduce diff
StephenButtolph May 30, 2023
d9bc124
lint
StephenButtolph May 30, 2023
52efbab
merged
StephenButtolph Jun 1, 2023
2841bf8
fixes from code review
StephenButtolph Jun 1, 2023
31be198
Merge branch 'dev' into tag-stake-connected-health
hexfusion Jun 5, 2023
fbcfc49
Merge branch 'dev' into tag-stake-connected-health
StephenButtolph Jun 7, 2023
775ca0e
Merge branch 'dev' into tag-stake-connected-health
StephenButtolph Jun 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 39 additions & 29 deletions chains/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ var (
errUnknownVMType = errors.New("the vm should have type avalanche.DAGVM or snowman.ChainVM")
errCreatePlatformVM = errors.New("attempted to create a chain running the PlatformVM")
errNotBootstrapped = errors.New("subnets not bootstrapped")
errNoPlatformSubnetConfig = errors.New("subnet config for platform chain not found")
errNoPrimaryNetworkConfig = errors.New("no subnet config for primary network found")

_ Manager = (*manager)(nil)
)
Expand Down Expand Up @@ -145,7 +145,7 @@ type ChainParameters struct {
VMID ids.ID
// The IDs of the feature extensions this chain is running.
FxIDs []ids.ID
// Should only be set if the default beacons can't be used.
// Invariant: Only used when [ID] is the P-chain ID.
CustomBeacons validators.Set
}

Expand Down Expand Up @@ -521,48 +521,43 @@ func (m *manager) buildChain(chainParams ChainParameters, sb subnets.Subnet) (*c
}

var vdrs validators.Set // Validators validating this blockchain
var ok bool
var hasValidators bool
if m.SybilProtectionEnabled {
vdrs, ok = m.Validators.Get(chainParams.SubnetID)
vdrs, hasValidators = m.Validators.Get(chainParams.SubnetID)
} else { // Sybil protection is disabled. Every peer validates every subnet.
vdrs, ok = m.Validators.Get(constants.PrimaryNetworkID)
vdrs, hasValidators = m.Validators.Get(constants.PrimaryNetworkID)
}
if !ok {
if !hasValidators {
return nil, fmt.Errorf("couldn't get validator set of subnet with ID %s. The subnet may not exist", chainParams.SubnetID)
}

beacons := vdrs
if chainParams.CustomBeacons != nil {
beacons = chainParams.CustomBeacons
}

bootstrapWeight := beacons.Weight()

var chain *chain
switch vm := vm.(type) {
case vertex.LinearizableVMWithEngine:
chain, err = m.createAvalancheChain(
ctx,
chainParams.GenesisData,
vdrs,
beacons,
vm,
fxs,
bootstrapWeight,
sb,
)
if err != nil {
return nil, fmt.Errorf("error while creating new avalanche vm %w", err)
}
case block.ChainVM:
beacons := vdrs
if chainParams.ID == constants.PlatformChainID {
beacons = chainParams.CustomBeacons
}

chain, err = m.createSnowmanChain(
ctx,
chainParams.GenesisData,
vdrs,
beacons,
vm,
fxs,
bootstrapWeight,
sb,
)
if err != nil {
Expand All @@ -588,11 +583,9 @@ func (m *manager) AddRegistrant(r Registrant) {
func (m *manager) createAvalancheChain(
ctx *snow.ConsensusContext,
genesisData []byte,
vdrs,
beacons validators.Set,
vdrs validators.Set,
vm vertex.LinearizableVMWithEngine,
fxs []*common.Fx,
bootstrapWeight uint64,
sb subnets.Subnet,
) (*chain, error) {
ctx.Lock.Lock()
Expand Down Expand Up @@ -806,12 +799,20 @@ func (m *manager) createAvalancheChain(
appSender: snowmanMessageSender,
}

bootstrapWeight := vdrs.Weight()

consensusParams := sb.Config().ConsensusParameters
sampleK := consensusParams.K
if uint64(sampleK) > bootstrapWeight {
sampleK = int(bootstrapWeight)
}

connectedValidators, err := tracker.NewMeteredPeers("", ctx.Registerer)
if err != nil {
return nil, fmt.Errorf("error creating peer tracker: %w", err)
}
vdrs.RegisterCallbackListener(connectedValidators)

// Asynchronously passes messages from the network to the consensus engine
h, err := handler.New(
ctx,
Expand All @@ -822,18 +823,19 @@ func (m *manager) createAvalancheChain(
m.ResourceTracker,
validators.UnhandledSubnetConnector, // avalanche chains don't use subnet connector
sb,
connectedValidators,
)
if err != nil {
return nil, fmt.Errorf("error initializing network handler: %w", err)
}

connectedPeers := tracker.NewPeers()
startupTracker := tracker.NewStartup(connectedPeers, (3*bootstrapWeight+3)/4)
beacons.RegisterCallbackListener(startupTracker)
connectedBeacons := tracker.NewPeers()
startupTracker := tracker.NewStartup(connectedBeacons, (3*bootstrapWeight+3)/4)
vdrs.RegisterCallbackListener(startupTracker)

snowmanCommonCfg := common.Config{
Ctx: ctx,
Beacons: beacons,
Beacons: vdrs,
SampleK: sampleK,
Alpha: bootstrapWeight/2 + 1, // must be > 50%
StartupTracker: startupTracker,
Expand Down Expand Up @@ -898,7 +900,7 @@ func (m *manager) createAvalancheChain(

avalancheCommonCfg := common.Config{
Ctx: ctx,
Beacons: beacons,
Beacons: vdrs,
SampleK: sampleK,
StartupTracker: startupTracker,
Alpha: bootstrapWeight/2 + 1, // must be > 50%
Expand Down Expand Up @@ -979,11 +981,10 @@ func (m *manager) createAvalancheChain(
func (m *manager) createSnowmanChain(
ctx *snow.ConsensusContext,
genesisData []byte,
vdrs,
vdrs validators.Set,
beacons validators.Set,
vm block.ChainVM,
fxs []*common.Fx,
bootstrapWeight uint64,
sb subnets.Subnet,
) (*chain, error) {
ctx.Lock.Lock()
Expand Down Expand Up @@ -1140,12 +1141,20 @@ func (m *manager) createSnowmanChain(
return nil, err
}

bootstrapWeight := beacons.Weight()

consensusParams := sb.Config().ConsensusParameters
sampleK := consensusParams.K
if uint64(sampleK) > bootstrapWeight {
sampleK = int(bootstrapWeight)
}

connectedValidators, err := tracker.NewMeteredPeers("", ctx.Registerer)
if err != nil {
return nil, fmt.Errorf("error creating peer tracker: %w", err)
}
vdrs.RegisterCallbackListener(connectedValidators)

// Asynchronously passes messages from the network to the consensus engine
h, err := handler.New(
ctx,
Expand All @@ -1156,13 +1165,14 @@ func (m *manager) createSnowmanChain(
m.ResourceTracker,
subnetConnector,
sb,
connectedValidators,
)
if err != nil {
return nil, fmt.Errorf("couldn't initialize message handler: %w", err)
}

connectedPeers := tracker.NewPeers()
startupTracker := tracker.NewStartup(connectedPeers, (3*bootstrapWeight+3)/4)
connectedBeacons := tracker.NewPeers()
startupTracker := tracker.NewStartup(connectedBeacons, (3*bootstrapWeight+3)/4)
beacons.RegisterCallbackListener(startupTracker)

commonCfg := common.Config{
Expand Down Expand Up @@ -1320,7 +1330,7 @@ func (m *manager) StartChainCreator(platformParams ChainParameters) error {
// throw a fatal error.
sbConfig, ok := m.SubnetConfigs[constants.PrimaryNetworkID]
if !ok {
return errNoPlatformSubnetConfig
return errNoPrimaryNetworkConfig
}

sb := subnets.New(m.NodeID, sbConfig)
Expand Down
18 changes: 0 additions & 18 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -1453,15 +1453,6 @@ func GetNodeConfig(v *viper.Viper) (node.Config, error) {
return node.Config{}, err
}

// Node health
nodeConfig.MinPercentConnectedStakeHealthy = map[ids.ID]float64{
constants.PrimaryNetworkID: calcMinConnectedStake(primaryNetworkConfig.ConsensusParameters),
}

for subnetID, config := range subnetConfigs {
nodeConfig.MinPercentConnectedStakeHealthy[subnetID] = calcMinConnectedStake(config.ConsensusParameters)
}

// Chain Configs
nodeConfig.ChainConfigs, err = getChainConfigs(v)
if err != nil {
Expand Down Expand Up @@ -1516,15 +1507,6 @@ func GetNodeConfig(v *viper.Viper) (node.Config, error) {
return nodeConfig, nil
}

// calcMinConnectedStake takes [consensusParams] as input and calculates the
// expected min connected stake percentage according to alpha and k.
func calcMinConnectedStake(consensusParams snowball.Parameters) float64 {
alpha := consensusParams.Alpha
k := consensusParams.K
r := float64(alpha) / float64(k)
return r*(1-constants.MinConnectedStakeBuffer) + constants.MinConnectedStakeBuffer
}

func providedFlags(v *viper.Viper) map[string]interface{} {
settings := v.AllSettings()
customSettings := make(map[string]interface{}, len(settings))
Expand Down
8 changes: 0 additions & 8 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -551,14 +551,6 @@ func TestGetSubnetConfigsFromFlags(t *testing.T) {
}
}

func TestCalcMinConnectedStake(t *testing.T) {
v := setupViperFlags()
defaultParams := getConsensusConfig(v)
defaultExpectedMinStake := 0.8
minStake := calcMinConnectedStake(defaultParams)
require.Equal(t, defaultExpectedMinStake, minStake)
}

// setups config json file and writes content
func setupConfigJSON(t *testing.T, rootPath string, value string) string {
configFilePath := filepath.Join(rootPath, "config.json")
Expand Down
17 changes: 9 additions & 8 deletions config/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/ava-labs/avalanchego/database/leveldb"
"github.com/ava-labs/avalanchego/database/memdb"
"github.com/ava-labs/avalanchego/genesis"
"github.com/ava-labs/avalanchego/snow/consensus/snowball"
"github.com/ava-labs/avalanchego/trace"
"github.com/ava-labs/avalanchego/utils/compression"
"github.com/ava-labs/avalanchego/utils/constants"
Expand Down Expand Up @@ -309,16 +310,16 @@ func addNodeFlags(fs *pflag.FlagSet) {
fs.Uint(BootstrapAncestorsMaxContainersReceivedKey, 2000, "This node reads at most this many containers from an incoming Ancestors message")

// Consensus
fs.Int(SnowSampleSizeKey, 20, "Number of nodes to query for each network poll")
fs.Int(SnowQuorumSizeKey, 15, "Alpha value to use for required number positive results")
fs.Int(SnowSampleSizeKey, snowball.DefaultParameters.K, "Number of nodes to query for each network poll")
fs.Int(SnowQuorumSizeKey, snowball.DefaultParameters.Alpha, "Alpha value to use for required number positive results")
// TODO: Replace this temporary flag description after the X-chain
// linearization with "Beta value to use for virtuous transactions"
fs.Int(SnowVirtuousCommitThresholdKey, 15, "This flag is temporarily ignored due to the X-chain linearization")
fs.Int(SnowRogueCommitThresholdKey, 20, "Beta value to use for rogue transactions")
fs.Int(SnowConcurrentRepollsKey, 4, "Minimum number of concurrent polls for finalizing consensus")
fs.Int(SnowOptimalProcessingKey, 10, "Optimal number of processing containers in consensus")
fs.Int(SnowMaxProcessingKey, 256, "Maximum number of processing items to be considered healthy")
fs.Duration(SnowMaxTimeProcessingKey, 30*time.Second, "Maximum amount of time an item should be processing and still be healthy")
fs.Int(SnowVirtuousCommitThresholdKey, snowball.DefaultParameters.BetaVirtuous, "This flag is temporarily ignored due to the X-chain linearization")
fs.Int(SnowRogueCommitThresholdKey, snowball.DefaultParameters.BetaRogue, "Beta value to use for rogue transactions")
fs.Int(SnowConcurrentRepollsKey, snowball.DefaultParameters.ConcurrentRepolls, "Minimum number of concurrent polls for finalizing consensus")
fs.Int(SnowOptimalProcessingKey, snowball.DefaultParameters.OptimalProcessing, "Optimal number of processing containers in consensus")
fs.Int(SnowMaxProcessingKey, snowball.DefaultParameters.MaxOutstandingItems, "Maximum number of processing items to be considered healthy")
fs.Duration(SnowMaxTimeProcessingKey, snowball.DefaultParameters.MaxItemProcessingTime, "Maximum amount of time an item should be processing and still be healthy")

// ProposerVM
fs.Bool(ProposerVMUseCurrentHeightKey, false, "Have the ProposerVM always report the last accepted P-chain block height")
Expand Down
4 changes: 0 additions & 4 deletions node/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,6 @@ type Config struct {

TraceConfig trace.Config `json:"traceConfig"`

// See comment on [MinPercentConnectedStakeHealthy] in platformvm.Config
// TODO: consider moving to subnet config
MinPercentConnectedStakeHealthy map[ids.ID]float64 `json:"minPercentConnectedStakeHealthy"`

// See comment on [UseCurrentHeight] in platformvm.Config
UseCurrentHeight bool `json:"useCurrentHeight"`

Expand Down
55 changes: 27 additions & 28 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -787,34 +787,33 @@ func (n *Node) initVMs() error {
errs.Add(
vmRegisterer.Register(context.TODO(), constants.PlatformVMID, &platformvm.Factory{
Config: platformconfig.Config{
Chains: n.chainManager,
Validators: vdrs,
UptimeLockedCalculator: n.uptimeCalculator,
SybilProtectionEnabled: n.Config.SybilProtectionEnabled,
TrackedSubnets: n.Config.TrackedSubnets,
TxFee: n.Config.TxFee,
CreateAssetTxFee: n.Config.CreateAssetTxFee,
CreateSubnetTxFee: n.Config.CreateSubnetTxFee,
TransformSubnetTxFee: n.Config.TransformSubnetTxFee,
CreateBlockchainTxFee: n.Config.CreateBlockchainTxFee,
AddPrimaryNetworkValidatorFee: n.Config.AddPrimaryNetworkValidatorFee,
AddPrimaryNetworkDelegatorFee: n.Config.AddPrimaryNetworkDelegatorFee,
AddSubnetValidatorFee: n.Config.AddSubnetValidatorFee,
AddSubnetDelegatorFee: n.Config.AddSubnetDelegatorFee,
UptimePercentage: n.Config.UptimeRequirement,
MinValidatorStake: n.Config.MinValidatorStake,
MaxValidatorStake: n.Config.MaxValidatorStake,
MinDelegatorStake: n.Config.MinDelegatorStake,
MinDelegationFee: n.Config.MinDelegationFee,
MinStakeDuration: n.Config.MinStakeDuration,
MaxStakeDuration: n.Config.MaxStakeDuration,
RewardConfig: n.Config.RewardConfig,
ApricotPhase3Time: version.GetApricotPhase3Time(n.Config.NetworkID),
ApricotPhase5Time: version.GetApricotPhase5Time(n.Config.NetworkID),
BanffTime: version.GetBanffTime(n.Config.NetworkID),
CortinaTime: version.GetCortinaTime(n.Config.NetworkID),
MinPercentConnectedStakeHealthy: n.Config.MinPercentConnectedStakeHealthy,
UseCurrentHeight: n.Config.UseCurrentHeight,
Chains: n.chainManager,
Validators: vdrs,
UptimeLockedCalculator: n.uptimeCalculator,
SybilProtectionEnabled: n.Config.SybilProtectionEnabled,
TrackedSubnets: n.Config.TrackedSubnets,
TxFee: n.Config.TxFee,
CreateAssetTxFee: n.Config.CreateAssetTxFee,
CreateSubnetTxFee: n.Config.CreateSubnetTxFee,
TransformSubnetTxFee: n.Config.TransformSubnetTxFee,
CreateBlockchainTxFee: n.Config.CreateBlockchainTxFee,
AddPrimaryNetworkValidatorFee: n.Config.AddPrimaryNetworkValidatorFee,
AddPrimaryNetworkDelegatorFee: n.Config.AddPrimaryNetworkDelegatorFee,
AddSubnetValidatorFee: n.Config.AddSubnetValidatorFee,
AddSubnetDelegatorFee: n.Config.AddSubnetDelegatorFee,
UptimePercentage: n.Config.UptimeRequirement,
MinValidatorStake: n.Config.MinValidatorStake,
MaxValidatorStake: n.Config.MaxValidatorStake,
MinDelegatorStake: n.Config.MinDelegatorStake,
MinDelegationFee: n.Config.MinDelegationFee,
MinStakeDuration: n.Config.MinStakeDuration,
MaxStakeDuration: n.Config.MaxStakeDuration,
RewardConfig: n.Config.RewardConfig,
ApricotPhase3Time: version.GetApricotPhase3Time(n.Config.NetworkID),
ApricotPhase5Time: version.GetApricotPhase5Time(n.Config.NetworkID),
BanffTime: version.GetBanffTime(n.Config.NetworkID),
CortinaTime: version.GetCortinaTime(n.Config.NetworkID),
UseCurrentHeight: n.Config.UseCurrentHeight,
},
}),
vmRegisterer.Register(context.TODO(), constants.AVMID, &avm.Factory{
Expand Down
Loading