Skip to content

Commit

Permalink
Track all subnet validator sets in the validator manager (#2253)
Browse files Browse the repository at this point in the history
  • Loading branch information
StephenButtolph committed Nov 4, 2023
1 parent cec1cd1 commit aaed8f3
Show file tree
Hide file tree
Showing 14 changed files with 44 additions and 127 deletions.
10 changes: 3 additions & 7 deletions snow/validators/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"go.uber.org/zap"

"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils"
"github.com/ava-labs/avalanchego/utils/crypto/bls"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/utils/set"
Expand All @@ -18,7 +17,6 @@ var _ SetCallbackListener = (*logger)(nil)

type logger struct {
log logging.Logger
enabled *utils.Atomic[bool]
subnetID ids.ID
nodeIDs set.Set[ids.NodeID]
}
Expand All @@ -27,14 +25,12 @@ type logger struct {
// the specified validators
func NewLogger(
log logging.Logger,
enabled *utils.Atomic[bool],
subnetID ids.ID,
nodeIDs ...ids.NodeID,
) SetCallbackListener {
nodeIDSet := set.Of(nodeIDs...)
return &logger{
log: log,
enabled: enabled,
subnetID: subnetID,
nodeIDs: nodeIDSet,
}
Expand All @@ -46,7 +42,7 @@ func (l *logger) OnValidatorAdded(
txID ids.ID,
weight uint64,
) {
if l.enabled.Get() && l.nodeIDs.Contains(nodeID) {
if l.nodeIDs.Contains(nodeID) {
var pkBytes []byte
if pk != nil {
pkBytes = bls.PublicKeyToBytes(pk)
Expand All @@ -65,7 +61,7 @@ func (l *logger) OnValidatorRemoved(
nodeID ids.NodeID,
weight uint64,
) {
if l.enabled.Get() && l.nodeIDs.Contains(nodeID) {
if l.nodeIDs.Contains(nodeID) {
l.log.Info("node removed from validator set",
zap.Stringer("subnetID", l.subnetID),
zap.Stringer("nodeID", nodeID),
Expand All @@ -79,7 +75,7 @@ func (l *logger) OnValidatorWeightChanged(
oldWeight uint64,
newWeight uint64,
) {
if l.enabled.Get() && l.nodeIDs.Contains(nodeID) {
if l.nodeIDs.Contains(nodeID) {
l.log.Info("validator weight changed",
zap.Stringer("subnetID", l.subnetID),
zap.Stringer("nodeID", nodeID),
Expand Down
1 change: 0 additions & 1 deletion vms/platformvm/block/builder/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,6 @@ func defaultState(
ctx,
metrics.Noop,
rewards,
&utils.Atomic[bool]{},
)
require.NoError(err)

Expand Down
1 change: 0 additions & 1 deletion vms/platformvm/block/executor/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,6 @@ func defaultState(
ctx,
metrics.Noop,
rewards,
&utils.Atomic[bool]{},
)
if err != nil {
panic(err)
Expand Down
2 changes: 1 addition & 1 deletion vms/platformvm/block/executor/proposal_block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -947,7 +947,7 @@ func TestBanffProposalBlockTrackedSubnet(t *testing.T) {
require.NoError(propBlk.Accept(context.Background()))
require.NoError(commitBlk.Accept(context.Background()))
_, ok := env.config.Validators.GetValidator(subnetID, subnetValidatorNodeID)
require.Equal(tracked, ok)
require.True(ok)
})
}
}
Expand Down
2 changes: 1 addition & 1 deletion vms/platformvm/block/executor/standard_block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,7 @@ func TestBanffStandardBlockTrackedSubnet(t *testing.T) {
require.NoError(block.Verify(context.Background()))
require.NoError(block.Accept(context.Background()))
_, ok := env.config.Validators.GetValidator(subnetID, subnetValidatorNodeID)
require.Equal(tracked, ok)
require.True(ok)
})
}
}
Expand Down
14 changes: 0 additions & 14 deletions vms/platformvm/state/mock_state.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

98 changes: 31 additions & 67 deletions vms/platformvm/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,6 @@ type State interface {

GetBlockIDAtHeight(height uint64) (ids.ID, error)

// ApplyCurrentValidators adds all the current validators and delegators of
// [subnetID] into [vdrs].
ApplyCurrentValidators(subnetID ids.ID, vdrs validators.Manager) error

// ApplyValidatorWeightDiffs iterates from [startHeight] towards the genesis
// block until it has applied all of the diffs up to and including
// [endHeight]. Applying the diffs modifies [validators].
Expand Down Expand Up @@ -290,11 +286,10 @@ type stateBlk struct {
type state struct {
validatorState

cfg *config.Config
ctx *snow.Context
metrics metrics.Metrics
rewards reward.Calculator
bootstrapped *utils.Atomic[bool]
cfg *config.Config
ctx *snow.Context
metrics metrics.Metrics
rewards reward.Calculator

baseDB *versiondb.Database

Expand Down Expand Up @@ -461,7 +456,6 @@ func New(
ctx *snow.Context,
metrics metrics.Metrics,
rewards reward.Calculator,
bootstrapped *utils.Atomic[bool],
) (State, error) {
s, err := newState(
db,
Expand All @@ -471,7 +465,6 @@ func New(
ctx,
metricsReg,
rewards,
bootstrapped,
)
if err != nil {
return nil, err
Expand Down Expand Up @@ -516,7 +509,6 @@ func newState(
ctx *snow.Context,
metricsReg prometheus.Registerer,
rewards reward.Calculator,
bootstrapped *utils.Atomic[bool],
) (*state, error) {
blockIDCache, err := metercacher.New[uint64, ids.ID](
"block_id_cache",
Expand Down Expand Up @@ -635,12 +627,11 @@ func newState(
return &state{
validatorState: newValidatorState(),

cfg: cfg,
ctx: ctx,
metrics: metrics,
rewards: rewards,
bootstrapped: bootstrapped,
baseDB: baseDB,
cfg: cfg,
ctx: ctx,
metrics: metrics,
rewards: rewards,
baseDB: baseDB,

addedBlockIDs: make(map[uint64]ids.ID),
blockIDCache: blockIDCache,
Expand Down Expand Up @@ -1139,26 +1130,6 @@ func (s *state) SetCurrentSupply(subnetID ids.ID, cs uint64) {
}
}

func (s *state) ApplyCurrentValidators(subnetID ids.ID, vdrs validators.Manager) error {
for nodeID, validator := range s.currentStakers.validators[subnetID] {
staker := validator.validator
if err := vdrs.AddStaker(subnetID, nodeID, staker.PublicKey, staker.TxID, staker.Weight); err != nil {
return err
}

delegatorIterator := NewTreeIterator(validator.delegators)
for delegatorIterator.Next() {
staker := delegatorIterator.Value()
if err := vdrs.AddWeight(subnetID, nodeID, staker.Weight); err != nil {
delegatorIterator.Release()
return err
}
}
delegatorIterator.Release()
}
return nil
}

func (s *state) ApplyValidatorWeightDiffs(
ctx context.Context,
validators map[ids.NodeID]*validators.GetValidatorOutput,
Expand Down Expand Up @@ -1689,38 +1660,36 @@ func (s *state) loadPendingValidators() error {
// Invariant: initValidatorSets requires loadCurrentValidators to have already
// been called.
func (s *state) initValidatorSets() error {
if s.cfg.Validators.Count(constants.PrimaryNetworkID) != 0 {
// Enforce the invariant that the validator set is empty here.
return errValidatorSetAlreadyPopulated
}
err := s.ApplyCurrentValidators(constants.PrimaryNetworkID, s.cfg.Validators)
if err != nil {
return err
}
for subnetID, validators := range s.currentStakers.validators {
if s.cfg.Validators.Count(subnetID) != 0 {
// Enforce the invariant that the validator set is empty here.
return fmt.Errorf("%w: %s", errValidatorSetAlreadyPopulated, subnetID)
}

vl := validators.NewLogger(s.ctx.Log, s.bootstrapped, constants.PrimaryNetworkID, s.ctx.NodeID)
s.cfg.Validators.RegisterCallbackListener(constants.PrimaryNetworkID, vl)
for nodeID, validator := range validators {
validatorStaker := validator.validator
if err := s.cfg.Validators.AddStaker(subnetID, nodeID, validatorStaker.PublicKey, validatorStaker.TxID, validatorStaker.Weight); err != nil {
return err
}

delegatorIterator := NewTreeIterator(validator.delegators)
for delegatorIterator.Next() {
delegatorStaker := delegatorIterator.Value()
if err := s.cfg.Validators.AddWeight(subnetID, nodeID, delegatorStaker.Weight); err != nil {
delegatorIterator.Release()
return err
}
}
delegatorIterator.Release()
}
}

s.metrics.SetLocalStake(s.cfg.Validators.GetWeight(constants.PrimaryNetworkID, s.ctx.NodeID))
totalWeight, err := s.cfg.Validators.TotalWeight(constants.PrimaryNetworkID)
if err != nil {
return fmt.Errorf("failed to get total weight of primary network validators: %w", err)
}
s.metrics.SetTotalStake(totalWeight)

for subnetID := range s.cfg.TrackedSubnets {
if s.cfg.Validators.Count(subnetID) != 0 {
// Enforce the invariant that the validator set is empty here.
return errValidatorSetAlreadyPopulated
}
err := s.ApplyCurrentValidators(subnetID, s.cfg.Validators)
if err != nil {
return err
}

vl := validators.NewLogger(s.ctx.Log, s.bootstrapped, subnetID, s.ctx.NodeID)
s.cfg.Validators.RegisterCallbackListener(subnetID, vl)
}
return nil
}

Expand Down Expand Up @@ -2109,11 +2078,6 @@ func (s *state) writeCurrentStakers(updateValidators bool, height uint64) error
continue
}

// We only track the current validator set of tracked subnets.
if subnetID != constants.PrimaryNetworkID && !s.cfg.TrackedSubnets.Contains(subnetID) {
continue
}

if weightDiff.Decrease {
err = s.cfg.Validators.RemoveWeight(subnetID, nodeID, weightDiff.Amount)
} else {
Expand Down
2 changes: 0 additions & 2 deletions vms/platformvm/state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"github.com/ava-labs/avalanchego/snow"
"github.com/ava-labs/avalanchego/snow/choices"
"github.com/ava-labs/avalanchego/snow/validators"
"github.com/ava-labs/avalanchego/utils"
"github.com/ava-labs/avalanchego/utils/constants"
"github.com/ava-labs/avalanchego/utils/crypto/bls"
"github.com/ava-labs/avalanchego/utils/units"
Expand Down Expand Up @@ -178,7 +177,6 @@ func newStateFromDB(require *require.Assertions, db database.Database) State {
MintingPeriod: 365 * 24 * time.Hour,
SupplyCap: 720 * units.MegaAvax,
}),
&utils.Atomic[bool]{},
)
require.NoError(err)
require.NotNil(state)
Expand Down
2 changes: 1 addition & 1 deletion vms/platformvm/txs/executor/advance_time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ func TestTrackedSubnet(t *testing.T) {
env.state.SetHeight(dummyHeight)
require.NoError(env.state.Commit())
_, ok := env.config.Validators.GetValidator(subnetID, ids.NodeID(subnetValidatorNodeID))
require.Equal(tracked, ok)
require.True(ok)
})
}
}
Expand Down
1 change: 0 additions & 1 deletion vms/platformvm/txs/executor/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,6 @@ func defaultState(
ctx,
metrics.Noop,
rewards,
&utils.Atomic[bool]{},
)
if err != nil {
panic(err)
Expand Down
21 changes: 1 addition & 20 deletions vms/platformvm/validators/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@ type State interface {
GetLastAccepted() ids.ID
GetStatelessBlock(blockID ids.ID) (block.Block, error)

// ApplyCurrentValidators adds all the current validators and delegators of
// [subnetID] into [vdrs].
ApplyCurrentValidators(subnetID ids.ID, vdrs validators.Manager) error

// ApplyValidatorWeightDiffs iterates from [startHeight] towards the genesis
// block until it has applied all of the diffs up to and including
// [endHeight]. Applying the diffs modifies [validators].
Expand Down Expand Up @@ -346,22 +342,7 @@ func (m *manager) getCurrentValidatorSets(
ctx context.Context,
subnetID ids.ID,
) (map[ids.NodeID]*validators.GetValidatorOutput, map[ids.NodeID]*validators.GetValidatorOutput, uint64, error) {
subnetManager := m.cfg.Validators
if subnetManager.Count(subnetID) == 0 {
// If this subnet isn't tracked, there will not be any registered
// validators. To calculate the current validators we need to first
// fetch them from state. We generate a new manager as we don't want to
// modify that long-lived reference.
//
// TODO: remove this once all subnets are included in the validator
// manager.
subnetManager = validators.NewManager()
if err := m.state.ApplyCurrentValidators(subnetID, subnetManager); err != nil {
return nil, nil, 0, err
}
}

subnetMap := subnetManager.GetMap(subnetID)
subnetMap := m.cfg.Validators.GetMap(subnetID)
primaryMap := m.cfg.Validators.GetMap(constants.PrimaryNetworkID)
currentHeight, err := m.getCurrentHeight(ctx)
return subnetMap, primaryMap, currentHeight, err
Expand Down
2 changes: 0 additions & 2 deletions vms/platformvm/validators/manager_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/snow"
"github.com/ava-labs/avalanchego/snow/validators"
"github.com/ava-labs/avalanchego/utils"
"github.com/ava-labs/avalanchego/utils/constants"
"github.com/ava-labs/avalanchego/utils/crypto/bls"
"github.com/ava-labs/avalanchego/utils/formatting"
Expand Down Expand Up @@ -129,7 +128,6 @@ func BenchmarkGetValidatorSet(b *testing.B) {
MintingPeriod: 365 * 24 * time.Hour,
SupplyCap: 720 * units.MegaAvax,
}),
new(utils.Atomic[bool]),
)
require.NoError(err)

Expand Down
9 changes: 6 additions & 3 deletions vms/platformvm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ func (vm *VM) Initialize(
vm.ctx,
vm.metrics,
rewards,
&vm.bootstrapped,
)
if err != nil {
return err
Expand Down Expand Up @@ -304,17 +303,21 @@ func (vm *VM) onNormalOperationsStarted() error {
}

primaryVdrIDs := vm.Validators.GetValidatorIDs(constants.PrimaryNetworkID)

if err := vm.uptimeManager.StartTracking(primaryVdrIDs, constants.PrimaryNetworkID); err != nil {
return err
}

vl := validators.NewLogger(vm.ctx.Log, constants.PrimaryNetworkID, vm.ctx.NodeID)
vm.Validators.RegisterCallbackListener(constants.PrimaryNetworkID, vl)

for subnetID := range vm.TrackedSubnets {
vdrIDs := vm.Validators.GetValidatorIDs(subnetID)

if err := vm.uptimeManager.StartTracking(vdrIDs, subnetID); err != nil {
return err
}

vl := validators.NewLogger(vm.ctx.Log, subnetID, vm.ctx.NodeID)
vm.Validators.RegisterCallbackListener(subnetID, vl)
}

if err := vm.state.Commit(); err != nil {
Expand Down

0 comments on commit aaed8f3

Please sign in to comment.