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 }