github.com/MetalBlockchain/metalgo@v1.11.9/vms/platformvm/state/stakers.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package state
     5  
     6  import (
     7  	"github.com/google/btree"
     8  
     9  	"github.com/MetalBlockchain/metalgo/database"
    10  	"github.com/MetalBlockchain/metalgo/ids"
    11  )
    12  
    13  type Stakers interface {
    14  	CurrentStakers
    15  	PendingStakers
    16  }
    17  
    18  type CurrentStakers interface {
    19  	// GetCurrentValidator returns the [staker] describing the validator on
    20  	// [subnetID] with [nodeID]. If the validator does not exist,
    21  	// [database.ErrNotFound] is returned.
    22  	GetCurrentValidator(subnetID ids.ID, nodeID ids.NodeID) (*Staker, error)
    23  
    24  	// PutCurrentValidator adds the [staker] describing a validator to the
    25  	// staker set.
    26  	//
    27  	// Invariant: [staker] is not currently a CurrentValidator
    28  	PutCurrentValidator(staker *Staker)
    29  
    30  	// DeleteCurrentValidator removes the [staker] describing a validator from
    31  	// the staker set.
    32  	//
    33  	// Invariant: [staker] is currently a CurrentValidator
    34  	DeleteCurrentValidator(staker *Staker)
    35  
    36  	// SetDelegateeReward sets the accrued delegation rewards for [nodeID] on
    37  	// [subnetID] to [amount].
    38  	SetDelegateeReward(subnetID ids.ID, nodeID ids.NodeID, amount uint64) error
    39  
    40  	// GetDelegateeReward returns the accrued delegation rewards for [nodeID] on
    41  	// [subnetID].
    42  	GetDelegateeReward(subnetID ids.ID, nodeID ids.NodeID) (uint64, error)
    43  
    44  	// GetCurrentDelegatorIterator returns the delegators associated with the
    45  	// validator on [subnetID] with [nodeID]. Delegators are sorted by their
    46  	// removal from current staker set.
    47  	GetCurrentDelegatorIterator(subnetID ids.ID, nodeID ids.NodeID) (StakerIterator, error)
    48  
    49  	// PutCurrentDelegator adds the [staker] describing a delegator to the
    50  	// staker set.
    51  	//
    52  	// Invariant: [staker] is not currently a CurrentDelegator
    53  	PutCurrentDelegator(staker *Staker)
    54  
    55  	// DeleteCurrentDelegator removes the [staker] describing a delegator from
    56  	// the staker set.
    57  	//
    58  	// Invariant: [staker] is currently a CurrentDelegator
    59  	DeleteCurrentDelegator(staker *Staker)
    60  
    61  	// GetCurrentStakerIterator returns stakers in order of their removal from
    62  	// the current staker set.
    63  	GetCurrentStakerIterator() (StakerIterator, error)
    64  }
    65  
    66  type PendingStakers interface {
    67  	// GetPendingValidator returns the Staker describing the validator on
    68  	// [subnetID] with [nodeID]. If the validator does not exist,
    69  	// [database.ErrNotFound] is returned.
    70  	GetPendingValidator(subnetID ids.ID, nodeID ids.NodeID) (*Staker, error)
    71  
    72  	// PutPendingValidator adds the [staker] describing a validator to the
    73  	// staker set.
    74  	PutPendingValidator(staker *Staker)
    75  
    76  	// DeletePendingValidator removes the [staker] describing a validator from
    77  	// the staker set.
    78  	DeletePendingValidator(staker *Staker)
    79  
    80  	// GetPendingDelegatorIterator returns the delegators associated with the
    81  	// validator on [subnetID] with [nodeID]. Delegators are sorted by their
    82  	// removal from pending staker set.
    83  	GetPendingDelegatorIterator(subnetID ids.ID, nodeID ids.NodeID) (StakerIterator, error)
    84  
    85  	// PutPendingDelegator adds the [staker] describing a delegator to the
    86  	// staker set.
    87  	PutPendingDelegator(staker *Staker)
    88  
    89  	// DeletePendingDelegator removes the [staker] describing a delegator from
    90  	// the staker set.
    91  	DeletePendingDelegator(staker *Staker)
    92  
    93  	// GetPendingStakerIterator returns stakers in order of their removal from
    94  	// the pending staker set.
    95  	GetPendingStakerIterator() (StakerIterator, error)
    96  }
    97  
    98  type baseStakers struct {
    99  	// subnetID --> nodeID --> current state for the validator of the subnet
   100  	validators map[ids.ID]map[ids.NodeID]*baseStaker
   101  	stakers    *btree.BTreeG[*Staker]
   102  	// subnetID --> nodeID --> diff for that validator since the last db write
   103  	validatorDiffs map[ids.ID]map[ids.NodeID]*diffValidator
   104  }
   105  
   106  type baseStaker struct {
   107  	validator  *Staker
   108  	delegators *btree.BTreeG[*Staker]
   109  }
   110  
   111  func newBaseStakers() *baseStakers {
   112  	return &baseStakers{
   113  		validators:     make(map[ids.ID]map[ids.NodeID]*baseStaker),
   114  		stakers:        btree.NewG(defaultTreeDegree, (*Staker).Less),
   115  		validatorDiffs: make(map[ids.ID]map[ids.NodeID]*diffValidator),
   116  	}
   117  }
   118  
   119  func (v *baseStakers) GetValidator(subnetID ids.ID, nodeID ids.NodeID) (*Staker, error) {
   120  	subnetValidators, ok := v.validators[subnetID]
   121  	if !ok {
   122  		return nil, database.ErrNotFound
   123  	}
   124  	validator, ok := subnetValidators[nodeID]
   125  	if !ok {
   126  		return nil, database.ErrNotFound
   127  	}
   128  	if validator.validator == nil {
   129  		return nil, database.ErrNotFound
   130  	}
   131  	return validator.validator, nil
   132  }
   133  
   134  func (v *baseStakers) PutValidator(staker *Staker) {
   135  	validator := v.getOrCreateValidator(staker.SubnetID, staker.NodeID)
   136  	validator.validator = staker
   137  
   138  	validatorDiff := v.getOrCreateValidatorDiff(staker.SubnetID, staker.NodeID)
   139  	validatorDiff.validatorStatus = added
   140  	validatorDiff.validator = staker
   141  
   142  	v.stakers.ReplaceOrInsert(staker)
   143  }
   144  
   145  func (v *baseStakers) DeleteValidator(staker *Staker) {
   146  	validator := v.getOrCreateValidator(staker.SubnetID, staker.NodeID)
   147  	validator.validator = nil
   148  	v.pruneValidator(staker.SubnetID, staker.NodeID)
   149  
   150  	validatorDiff := v.getOrCreateValidatorDiff(staker.SubnetID, staker.NodeID)
   151  	validatorDiff.validatorStatus = deleted
   152  	validatorDiff.validator = staker
   153  
   154  	v.stakers.Delete(staker)
   155  }
   156  
   157  func (v *baseStakers) GetDelegatorIterator(subnetID ids.ID, nodeID ids.NodeID) StakerIterator {
   158  	subnetValidators, ok := v.validators[subnetID]
   159  	if !ok {
   160  		return EmptyIterator
   161  	}
   162  	validator, ok := subnetValidators[nodeID]
   163  	if !ok {
   164  		return EmptyIterator
   165  	}
   166  	return NewTreeIterator(validator.delegators)
   167  }
   168  
   169  func (v *baseStakers) PutDelegator(staker *Staker) {
   170  	validator := v.getOrCreateValidator(staker.SubnetID, staker.NodeID)
   171  	if validator.delegators == nil {
   172  		validator.delegators = btree.NewG(defaultTreeDegree, (*Staker).Less)
   173  	}
   174  	validator.delegators.ReplaceOrInsert(staker)
   175  
   176  	validatorDiff := v.getOrCreateValidatorDiff(staker.SubnetID, staker.NodeID)
   177  	if validatorDiff.addedDelegators == nil {
   178  		validatorDiff.addedDelegators = btree.NewG(defaultTreeDegree, (*Staker).Less)
   179  	}
   180  	validatorDiff.addedDelegators.ReplaceOrInsert(staker)
   181  
   182  	v.stakers.ReplaceOrInsert(staker)
   183  }
   184  
   185  func (v *baseStakers) DeleteDelegator(staker *Staker) {
   186  	validator := v.getOrCreateValidator(staker.SubnetID, staker.NodeID)
   187  	if validator.delegators != nil {
   188  		validator.delegators.Delete(staker)
   189  	}
   190  	v.pruneValidator(staker.SubnetID, staker.NodeID)
   191  
   192  	validatorDiff := v.getOrCreateValidatorDiff(staker.SubnetID, staker.NodeID)
   193  	if validatorDiff.deletedDelegators == nil {
   194  		validatorDiff.deletedDelegators = make(map[ids.ID]*Staker)
   195  	}
   196  	validatorDiff.deletedDelegators[staker.TxID] = staker
   197  
   198  	v.stakers.Delete(staker)
   199  }
   200  
   201  func (v *baseStakers) GetStakerIterator() StakerIterator {
   202  	return NewTreeIterator(v.stakers)
   203  }
   204  
   205  func (v *baseStakers) getOrCreateValidator(subnetID ids.ID, nodeID ids.NodeID) *baseStaker {
   206  	subnetValidators, ok := v.validators[subnetID]
   207  	if !ok {
   208  		subnetValidators = make(map[ids.NodeID]*baseStaker)
   209  		v.validators[subnetID] = subnetValidators
   210  	}
   211  	validator, ok := subnetValidators[nodeID]
   212  	if !ok {
   213  		validator = &baseStaker{}
   214  		subnetValidators[nodeID] = validator
   215  	}
   216  	return validator
   217  }
   218  
   219  // pruneValidator assumes that the named validator is currently in the
   220  // [validators] map.
   221  func (v *baseStakers) pruneValidator(subnetID ids.ID, nodeID ids.NodeID) {
   222  	subnetValidators := v.validators[subnetID]
   223  	validator := subnetValidators[nodeID]
   224  	if validator.validator != nil {
   225  		return
   226  	}
   227  	if validator.delegators != nil && validator.delegators.Len() > 0 {
   228  		return
   229  	}
   230  	delete(subnetValidators, nodeID)
   231  	if len(subnetValidators) == 0 {
   232  		delete(v.validators, subnetID)
   233  	}
   234  }
   235  
   236  func (v *baseStakers) getOrCreateValidatorDiff(subnetID ids.ID, nodeID ids.NodeID) *diffValidator {
   237  	subnetValidatorDiffs, ok := v.validatorDiffs[subnetID]
   238  	if !ok {
   239  		subnetValidatorDiffs = make(map[ids.NodeID]*diffValidator)
   240  		v.validatorDiffs[subnetID] = subnetValidatorDiffs
   241  	}
   242  	validatorDiff, ok := subnetValidatorDiffs[nodeID]
   243  	if !ok {
   244  		validatorDiff = &diffValidator{
   245  			validatorStatus: unmodified,
   246  		}
   247  		subnetValidatorDiffs[nodeID] = validatorDiff
   248  	}
   249  	return validatorDiff
   250  }
   251  
   252  type diffStakers struct {
   253  	// subnetID --> nodeID --> diff for that validator
   254  	validatorDiffs map[ids.ID]map[ids.NodeID]*diffValidator
   255  	addedStakers   *btree.BTreeG[*Staker]
   256  	deletedStakers map[ids.ID]*Staker
   257  }
   258  
   259  type diffValidator struct {
   260  	// validatorStatus describes whether a validator has been added or removed.
   261  	//
   262  	// validatorStatus is not affected by delegators ops so unmodified does not
   263  	// mean that diffValidator hasn't change, since delegators may have changed.
   264  	validatorStatus diffValidatorStatus
   265  	validator       *Staker
   266  
   267  	addedDelegators   *btree.BTreeG[*Staker]
   268  	deletedDelegators map[ids.ID]*Staker
   269  }
   270  
   271  // GetValidator attempts to fetch the validator with the given subnetID and
   272  // nodeID.
   273  // Invariant: Assumes that the validator will never be removed and then added.
   274  func (s *diffStakers) GetValidator(subnetID ids.ID, nodeID ids.NodeID) (*Staker, diffValidatorStatus) {
   275  	subnetValidatorDiffs, ok := s.validatorDiffs[subnetID]
   276  	if !ok {
   277  		return nil, unmodified
   278  	}
   279  
   280  	validatorDiff, ok := subnetValidatorDiffs[nodeID]
   281  	if !ok {
   282  		return nil, unmodified
   283  	}
   284  
   285  	if validatorDiff.validatorStatus == added {
   286  		return validatorDiff.validator, added
   287  	}
   288  	return nil, validatorDiff.validatorStatus
   289  }
   290  
   291  func (s *diffStakers) PutValidator(staker *Staker) {
   292  	validatorDiff := s.getOrCreateDiff(staker.SubnetID, staker.NodeID)
   293  	validatorDiff.validatorStatus = added
   294  	validatorDiff.validator = staker
   295  
   296  	if s.addedStakers == nil {
   297  		s.addedStakers = btree.NewG(defaultTreeDegree, (*Staker).Less)
   298  	}
   299  	s.addedStakers.ReplaceOrInsert(staker)
   300  }
   301  
   302  func (s *diffStakers) DeleteValidator(staker *Staker) {
   303  	validatorDiff := s.getOrCreateDiff(staker.SubnetID, staker.NodeID)
   304  	if validatorDiff.validatorStatus == added {
   305  		// This validator was added and immediately removed in this diff. We
   306  		// treat it as if it was never added.
   307  		validatorDiff.validatorStatus = unmodified
   308  		s.addedStakers.Delete(validatorDiff.validator)
   309  		validatorDiff.validator = nil
   310  	} else {
   311  		validatorDiff.validatorStatus = deleted
   312  		validatorDiff.validator = staker
   313  		if s.deletedStakers == nil {
   314  			s.deletedStakers = make(map[ids.ID]*Staker)
   315  		}
   316  		s.deletedStakers[staker.TxID] = staker
   317  	}
   318  }
   319  
   320  func (s *diffStakers) GetDelegatorIterator(
   321  	parentIterator StakerIterator,
   322  	subnetID ids.ID,
   323  	nodeID ids.NodeID,
   324  ) StakerIterator {
   325  	var (
   326  		addedDelegatorIterator = EmptyIterator
   327  		deletedDelegators      map[ids.ID]*Staker
   328  	)
   329  	if subnetValidatorDiffs, ok := s.validatorDiffs[subnetID]; ok {
   330  		if validatorDiff, ok := subnetValidatorDiffs[nodeID]; ok {
   331  			addedDelegatorIterator = NewTreeIterator(validatorDiff.addedDelegators)
   332  			deletedDelegators = validatorDiff.deletedDelegators
   333  		}
   334  	}
   335  
   336  	return NewMaskedIterator(
   337  		NewMergedIterator(
   338  			parentIterator,
   339  			addedDelegatorIterator,
   340  		),
   341  		deletedDelegators,
   342  	)
   343  }
   344  
   345  func (s *diffStakers) PutDelegator(staker *Staker) {
   346  	validatorDiff := s.getOrCreateDiff(staker.SubnetID, staker.NodeID)
   347  	if validatorDiff.addedDelegators == nil {
   348  		validatorDiff.addedDelegators = btree.NewG(defaultTreeDegree, (*Staker).Less)
   349  	}
   350  	validatorDiff.addedDelegators.ReplaceOrInsert(staker)
   351  
   352  	if s.addedStakers == nil {
   353  		s.addedStakers = btree.NewG(defaultTreeDegree, (*Staker).Less)
   354  	}
   355  	s.addedStakers.ReplaceOrInsert(staker)
   356  }
   357  
   358  func (s *diffStakers) DeleteDelegator(staker *Staker) {
   359  	validatorDiff := s.getOrCreateDiff(staker.SubnetID, staker.NodeID)
   360  	if validatorDiff.deletedDelegators == nil {
   361  		validatorDiff.deletedDelegators = make(map[ids.ID]*Staker)
   362  	}
   363  	validatorDiff.deletedDelegators[staker.TxID] = staker
   364  
   365  	if s.deletedStakers == nil {
   366  		s.deletedStakers = make(map[ids.ID]*Staker)
   367  	}
   368  	s.deletedStakers[staker.TxID] = staker
   369  }
   370  
   371  func (s *diffStakers) GetStakerIterator(parentIterator StakerIterator) StakerIterator {
   372  	return NewMaskedIterator(
   373  		NewMergedIterator(
   374  			parentIterator,
   375  			NewTreeIterator(s.addedStakers),
   376  		),
   377  		s.deletedStakers,
   378  	)
   379  }
   380  
   381  func (s *diffStakers) getOrCreateDiff(subnetID ids.ID, nodeID ids.NodeID) *diffValidator {
   382  	if s.validatorDiffs == nil {
   383  		s.validatorDiffs = make(map[ids.ID]map[ids.NodeID]*diffValidator)
   384  	}
   385  	subnetValidatorDiffs, ok := s.validatorDiffs[subnetID]
   386  	if !ok {
   387  		subnetValidatorDiffs = make(map[ids.NodeID]*diffValidator)
   388  		s.validatorDiffs[subnetID] = subnetValidatorDiffs
   389  	}
   390  	validatorDiff, ok := subnetValidatorDiffs[nodeID]
   391  	if !ok {
   392  		validatorDiff = &diffValidator{
   393  			validatorStatus: unmodified,
   394  		}
   395  		subnetValidatorDiffs[nodeID] = validatorDiff
   396  	}
   397  	return validatorDiff
   398  }