github.com/bloxroute-labs/bor@v0.1.4/consensus/bor/validator_set.go (about) 1 package bor 2 3 // Tendermint leader selection algorithm 4 5 import ( 6 "bytes" 7 "fmt" 8 "math" 9 "math/big" 10 "sort" 11 "strings" 12 13 "github.com/maticnetwork/bor/common" 14 ) 15 16 // MaxTotalVotingPower - the maximum allowed total voting power. 17 // It needs to be sufficiently small to, in all cases: 18 // 1. prevent clipping in incrementProposerPriority() 19 // 2. let (diff+diffMax-1) not overflow in IncrementProposerPriority() 20 // (Proof of 1 is tricky, left to the reader). 21 // It could be higher, but this is sufficiently large for our purposes, 22 // and leaves room for defensive purposes. 23 // PriorityWindowSizeFactor - is a constant that when multiplied with the total voting power gives 24 // the maximum allowed distance between validator priorities. 25 26 const ( 27 MaxTotalVotingPower = int64(math.MaxInt64) / 8 28 PriorityWindowSizeFactor = 2 29 ) 30 31 // ValidatorSet represent a set of *Validator at a given height. 32 // The validators can be fetched by address or index. 33 // The index is in order of .Address, so the indices are fixed 34 // for all rounds of a given blockchain height - ie. the validators 35 // are sorted by their address. 36 // On the other hand, the .ProposerPriority of each validator and 37 // the designated .GetProposer() of a set changes every round, 38 // upon calling .IncrementProposerPriority(). 39 // NOTE: Not goroutine-safe. 40 // NOTE: All get/set to validators should copy the value for safety. 41 type ValidatorSet struct { 42 // NOTE: persisted via reflect, must be exported. 43 Validators []*Validator `json:"validators"` 44 Proposer *Validator `json:"proposer"` 45 46 // cached (unexported) 47 totalVotingPower int64 48 } 49 50 // NewValidatorSet initializes a ValidatorSet by copying over the 51 // values from `valz`, a list of Validators. If valz is nil or empty, 52 // the new ValidatorSet will have an empty list of Validators. 53 // The addresses of validators in `valz` must be unique otherwise the 54 // function panics. 55 func NewValidatorSet(valz []*Validator) *ValidatorSet { 56 vals := &ValidatorSet{} 57 err := vals.updateWithChangeSet(valz, false) 58 if err != nil { 59 panic(fmt.Sprintf("cannot create validator set: %s", err)) 60 } 61 if len(valz) > 0 { 62 vals.IncrementProposerPriority(1) 63 } 64 return vals 65 } 66 67 // Nil or empty validator sets are invalid. 68 func (vals *ValidatorSet) IsNilOrEmpty() bool { 69 return vals == nil || len(vals.Validators) == 0 70 } 71 72 // Increment ProposerPriority and update the proposer on a copy, and return it. 73 func (vals *ValidatorSet) CopyIncrementProposerPriority(times int) *ValidatorSet { 74 copy := vals.Copy() 75 copy.IncrementProposerPriority(times) 76 return copy 77 } 78 79 // IncrementProposerPriority increments ProposerPriority of each validator and updates the 80 // proposer. Panics if validator set is empty. 81 // `times` must be positive. 82 func (vals *ValidatorSet) IncrementProposerPriority(times int) { 83 if vals.IsNilOrEmpty() { 84 panic("empty validator set") 85 } 86 if times <= 0 { 87 panic("Cannot call IncrementProposerPriority with non-positive times") 88 } 89 90 // Cap the difference between priorities to be proportional to 2*totalPower by 91 // re-normalizing priorities, i.e., rescale all priorities by multiplying with: 92 // 2*totalVotingPower/(maxPriority - minPriority) 93 diffMax := PriorityWindowSizeFactor * vals.TotalVotingPower() 94 vals.RescalePriorities(diffMax) 95 vals.shiftByAvgProposerPriority() 96 97 var proposer *Validator 98 // Call IncrementProposerPriority(1) times times. 99 for i := 0; i < times; i++ { 100 proposer = vals.incrementProposerPriority() 101 } 102 103 vals.Proposer = proposer 104 } 105 106 func (vals *ValidatorSet) RescalePriorities(diffMax int64) { 107 if vals.IsNilOrEmpty() { 108 panic("empty validator set") 109 } 110 // NOTE: This check is merely a sanity check which could be 111 // removed if all tests would init. voting power appropriately; 112 // i.e. diffMax should always be > 0 113 if diffMax <= 0 { 114 return 115 } 116 117 // Calculating ceil(diff/diffMax): 118 // Re-normalization is performed by dividing by an integer for simplicity. 119 // NOTE: This may make debugging priority issues easier as well. 120 diff := computeMaxMinPriorityDiff(vals) 121 ratio := (diff + diffMax - 1) / diffMax 122 if diff > diffMax { 123 for _, val := range vals.Validators { 124 val.ProposerPriority = val.ProposerPriority / ratio 125 } 126 } 127 } 128 129 func (vals *ValidatorSet) incrementProposerPriority() *Validator { 130 for _, val := range vals.Validators { 131 // Check for overflow for sum. 132 newPrio := safeAddClip(val.ProposerPriority, val.VotingPower) 133 val.ProposerPriority = newPrio 134 } 135 // Decrement the validator with most ProposerPriority. 136 mostest := vals.getValWithMostPriority() 137 // Mind the underflow. 138 mostest.ProposerPriority = safeSubClip(mostest.ProposerPriority, vals.TotalVotingPower()) 139 140 return mostest 141 } 142 143 // Should not be called on an empty validator set. 144 func (vals *ValidatorSet) computeAvgProposerPriority() int64 { 145 n := int64(len(vals.Validators)) 146 sum := big.NewInt(0) 147 for _, val := range vals.Validators { 148 sum.Add(sum, big.NewInt(val.ProposerPriority)) 149 } 150 avg := sum.Div(sum, big.NewInt(n)) 151 if avg.IsInt64() { 152 return avg.Int64() 153 } 154 155 // This should never happen: each val.ProposerPriority is in bounds of int64. 156 panic(fmt.Sprintf("Cannot represent avg ProposerPriority as an int64 %v", avg)) 157 } 158 159 // Compute the difference between the max and min ProposerPriority of that set. 160 func computeMaxMinPriorityDiff(vals *ValidatorSet) int64 { 161 if vals.IsNilOrEmpty() { 162 panic("empty validator set") 163 } 164 max := int64(math.MinInt64) 165 min := int64(math.MaxInt64) 166 for _, v := range vals.Validators { 167 if v.ProposerPriority < min { 168 min = v.ProposerPriority 169 } 170 if v.ProposerPriority > max { 171 max = v.ProposerPriority 172 } 173 } 174 diff := max - min 175 if diff < 0 { 176 return -1 * diff 177 } else { 178 return diff 179 } 180 } 181 182 func (vals *ValidatorSet) getValWithMostPriority() *Validator { 183 var res *Validator 184 for _, val := range vals.Validators { 185 res = res.CompareProposerPriority(val) 186 } 187 return res 188 } 189 190 func (vals *ValidatorSet) shiftByAvgProposerPriority() { 191 if vals.IsNilOrEmpty() { 192 panic("empty validator set") 193 } 194 avgProposerPriority := vals.computeAvgProposerPriority() 195 for _, val := range vals.Validators { 196 val.ProposerPriority = safeSubClip(val.ProposerPriority, avgProposerPriority) 197 } 198 } 199 200 // Makes a copy of the validator list. 201 func validatorListCopy(valsList []*Validator) []*Validator { 202 if valsList == nil { 203 return nil 204 } 205 valsCopy := make([]*Validator, len(valsList)) 206 for i, val := range valsList { 207 valsCopy[i] = val.Copy() 208 } 209 return valsCopy 210 } 211 212 // Copy each validator into a new ValidatorSet. 213 func (vals *ValidatorSet) Copy() *ValidatorSet { 214 return &ValidatorSet{ 215 Validators: validatorListCopy(vals.Validators), 216 Proposer: vals.Proposer, 217 totalVotingPower: vals.totalVotingPower, 218 } 219 } 220 221 // HasAddress returns true if address given is in the validator set, false - 222 // otherwise. 223 func (vals *ValidatorSet) HasAddress(address []byte) bool { 224 idx := sort.Search(len(vals.Validators), func(i int) bool { 225 return bytes.Compare(address, vals.Validators[i].Address.Bytes()) <= 0 226 }) 227 return idx < len(vals.Validators) && bytes.Equal(vals.Validators[idx].Address.Bytes(), address) 228 } 229 230 // GetByAddress returns an index of the validator with address and validator 231 // itself if found. Otherwise, -1 and nil are returned. 232 func (vals *ValidatorSet) GetByAddress(address common.Address) (index int, val *Validator) { 233 idx := sort.Search(len(vals.Validators), func(i int) bool { 234 return bytes.Compare(address.Bytes(), vals.Validators[i].Address.Bytes()) <= 0 235 }) 236 if idx < len(vals.Validators) && bytes.Equal(vals.Validators[idx].Address.Bytes(), address.Bytes()) { 237 return idx, vals.Validators[idx].Copy() 238 } 239 return -1, nil 240 } 241 242 // GetByIndex returns the validator's address and validator itself by index. 243 // It returns nil values if index is less than 0 or greater or equal to 244 // len(ValidatorSet.Validators). 245 func (vals *ValidatorSet) GetByIndex(index int) (address []byte, val *Validator) { 246 if index < 0 || index >= len(vals.Validators) { 247 return nil, nil 248 } 249 val = vals.Validators[index] 250 return val.Address.Bytes(), val.Copy() 251 } 252 253 // Size returns the length of the validator set. 254 func (vals *ValidatorSet) Size() int { 255 return len(vals.Validators) 256 } 257 258 // Force recalculation of the set's total voting power. 259 func (vals *ValidatorSet) updateTotalVotingPower() { 260 261 sum := int64(0) 262 for _, val := range vals.Validators { 263 // mind overflow 264 sum = safeAddClip(sum, val.VotingPower) 265 if sum > MaxTotalVotingPower { 266 panic(fmt.Sprintf( 267 "Total voting power should be guarded to not exceed %v; got: %v", 268 MaxTotalVotingPower, 269 sum)) 270 } 271 } 272 273 vals.totalVotingPower = sum 274 } 275 276 // TotalVotingPower returns the sum of the voting powers of all validators. 277 // It recomputes the total voting power if required. 278 func (vals *ValidatorSet) TotalVotingPower() int64 { 279 if vals.totalVotingPower == 0 { 280 vals.updateTotalVotingPower() 281 } 282 return vals.totalVotingPower 283 } 284 285 // GetProposer returns the current proposer. If the validator set is empty, nil 286 // is returned. 287 func (vals *ValidatorSet) GetProposer() (proposer *Validator) { 288 if len(vals.Validators) == 0 { 289 return nil 290 } 291 if vals.Proposer == nil { 292 vals.Proposer = vals.findProposer() 293 } 294 return vals.Proposer.Copy() 295 } 296 297 func (vals *ValidatorSet) findProposer() *Validator { 298 var proposer *Validator 299 for _, val := range vals.Validators { 300 if proposer == nil || !bytes.Equal(val.Address.Bytes(), proposer.Address.Bytes()) { 301 proposer = proposer.CompareProposerPriority(val) 302 } 303 } 304 return proposer 305 } 306 307 // Hash returns the Merkle root hash build using validators (as leaves) in the 308 // set. 309 // func (vals *ValidatorSet) Hash() []byte { 310 // if len(vals.Validators) == 0 { 311 // return nil 312 // } 313 // bzs := make([][]byte, len(vals.Validators)) 314 // for i, val := range vals.Validators { 315 // bzs[i] = val.Bytes() 316 // } 317 // return merkle.SimpleHashFromByteSlices(bzs) 318 // } 319 320 // Iterate will run the given function over the set. 321 func (vals *ValidatorSet) Iterate(fn func(index int, val *Validator) bool) { 322 for i, val := range vals.Validators { 323 stop := fn(i, val.Copy()) 324 if stop { 325 break 326 } 327 } 328 } 329 330 // Checks changes against duplicates, splits the changes in updates and removals, sorts them by address. 331 // 332 // Returns: 333 // updates, removals - the sorted lists of updates and removals 334 // err - non-nil if duplicate entries or entries with negative voting power are seen 335 // 336 // No changes are made to 'origChanges'. 337 func processChanges(origChanges []*Validator) (updates, removals []*Validator, err error) { 338 // Make a deep copy of the changes and sort by address. 339 changes := validatorListCopy(origChanges) 340 sort.Sort(ValidatorsByAddress(changes)) 341 342 removals = make([]*Validator, 0, len(changes)) 343 updates = make([]*Validator, 0, len(changes)) 344 var prevAddr common.Address 345 346 // Scan changes by address and append valid validators to updates or removals lists. 347 for _, valUpdate := range changes { 348 if bytes.Equal(valUpdate.Address.Bytes(), prevAddr.Bytes()) { 349 err = fmt.Errorf("duplicate entry %v in %v", valUpdate, changes) 350 return nil, nil, err 351 } 352 if valUpdate.VotingPower < 0 { 353 err = fmt.Errorf("voting power can't be negative: %v", valUpdate) 354 return nil, nil, err 355 } 356 if valUpdate.VotingPower > MaxTotalVotingPower { 357 err = fmt.Errorf("to prevent clipping/ overflow, voting power can't be higher than %v: %v ", 358 MaxTotalVotingPower, valUpdate) 359 return nil, nil, err 360 } 361 if valUpdate.VotingPower == 0 { 362 removals = append(removals, valUpdate) 363 } else { 364 updates = append(updates, valUpdate) 365 } 366 prevAddr = valUpdate.Address 367 } 368 return updates, removals, err 369 } 370 371 // Verifies a list of updates against a validator set, making sure the allowed 372 // total voting power would not be exceeded if these updates would be applied to the set. 373 // 374 // Returns: 375 // updatedTotalVotingPower - the new total voting power if these updates would be applied 376 // numNewValidators - number of new validators 377 // err - non-nil if the maximum allowed total voting power would be exceeded 378 // 379 // 'updates' should be a list of proper validator changes, i.e. they have been verified 380 // by processChanges for duplicates and invalid values. 381 // No changes are made to the validator set 'vals'. 382 func verifyUpdates(updates []*Validator, vals *ValidatorSet) (updatedTotalVotingPower int64, numNewValidators int, err error) { 383 384 updatedTotalVotingPower = vals.TotalVotingPower() 385 386 for _, valUpdate := range updates { 387 address := valUpdate.Address 388 _, val := vals.GetByAddress(address) 389 if val == nil { 390 // New validator, add its voting power the the total. 391 updatedTotalVotingPower += valUpdate.VotingPower 392 numNewValidators++ 393 } else { 394 // Updated validator, add the difference in power to the total. 395 updatedTotalVotingPower += valUpdate.VotingPower - val.VotingPower 396 } 397 overflow := updatedTotalVotingPower > MaxTotalVotingPower 398 if overflow { 399 err = fmt.Errorf( 400 "failed to add/update validator %v, total voting power would exceed the max allowed %v", 401 valUpdate, MaxTotalVotingPower) 402 return 0, 0, err 403 } 404 } 405 406 return updatedTotalVotingPower, numNewValidators, nil 407 } 408 409 // Computes the proposer priority for the validators not present in the set based on 'updatedTotalVotingPower'. 410 // Leaves unchanged the priorities of validators that are changed. 411 // 412 // 'updates' parameter must be a list of unique validators to be added or updated. 413 // No changes are made to the validator set 'vals'. 414 func computeNewPriorities(updates []*Validator, vals *ValidatorSet, updatedTotalVotingPower int64) { 415 416 for _, valUpdate := range updates { 417 address := valUpdate.Address 418 _, val := vals.GetByAddress(address) 419 if val == nil { 420 // add val 421 // Set ProposerPriority to -C*totalVotingPower (with C ~= 1.125) to make sure validators can't 422 // un-bond and then re-bond to reset their (potentially previously negative) ProposerPriority to zero. 423 // 424 // Contract: updatedVotingPower < MaxTotalVotingPower to ensure ProposerPriority does 425 // not exceed the bounds of int64. 426 // 427 // Compute ProposerPriority = -1.125*totalVotingPower == -(updatedVotingPower + (updatedVotingPower >> 3)). 428 valUpdate.ProposerPriority = -(updatedTotalVotingPower + (updatedTotalVotingPower >> 3)) 429 } else { 430 valUpdate.ProposerPriority = val.ProposerPriority 431 } 432 } 433 434 } 435 436 // Merges the vals' validator list with the updates list. 437 // When two elements with same address are seen, the one from updates is selected. 438 // Expects updates to be a list of updates sorted by address with no duplicates or errors, 439 // must have been validated with verifyUpdates() and priorities computed with computeNewPriorities(). 440 func (vals *ValidatorSet) applyUpdates(updates []*Validator) { 441 442 existing := vals.Validators 443 merged := make([]*Validator, len(existing)+len(updates)) 444 i := 0 445 446 for len(existing) > 0 && len(updates) > 0 { 447 if bytes.Compare(existing[0].Address.Bytes(), updates[0].Address.Bytes()) < 0 { // unchanged validator 448 merged[i] = existing[0] 449 existing = existing[1:] 450 } else { 451 // Apply add or update. 452 merged[i] = updates[0] 453 if bytes.Equal(existing[0].Address.Bytes(), updates[0].Address.Bytes()) { 454 // Validator is present in both, advance existing. 455 existing = existing[1:] 456 } 457 updates = updates[1:] 458 } 459 i++ 460 } 461 462 // Add the elements which are left. 463 for j := 0; j < len(existing); j++ { 464 merged[i] = existing[j] 465 i++ 466 } 467 // OR add updates which are left. 468 for j := 0; j < len(updates); j++ { 469 merged[i] = updates[j] 470 i++ 471 } 472 473 vals.Validators = merged[:i] 474 } 475 476 // Checks that the validators to be removed are part of the validator set. 477 // No changes are made to the validator set 'vals'. 478 func verifyRemovals(deletes []*Validator, vals *ValidatorSet) error { 479 480 for _, valUpdate := range deletes { 481 address := valUpdate.Address 482 _, val := vals.GetByAddress(address) 483 if val == nil { 484 return fmt.Errorf("failed to find validator %X to remove", address) 485 } 486 } 487 if len(deletes) > len(vals.Validators) { 488 panic("more deletes than validators") 489 } 490 return nil 491 } 492 493 // Removes the validators specified in 'deletes' from validator set 'vals'. 494 // Should not fail as verification has been done before. 495 func (vals *ValidatorSet) applyRemovals(deletes []*Validator) { 496 497 existing := vals.Validators 498 499 merged := make([]*Validator, len(existing)-len(deletes)) 500 i := 0 501 502 // Loop over deletes until we removed all of them. 503 for len(deletes) > 0 { 504 if bytes.Equal(existing[0].Address.Bytes(), deletes[0].Address.Bytes()) { 505 deletes = deletes[1:] 506 } else { // Leave it in the resulting slice. 507 merged[i] = existing[0] 508 i++ 509 } 510 existing = existing[1:] 511 } 512 513 // Add the elements which are left. 514 for j := 0; j < len(existing); j++ { 515 merged[i] = existing[j] 516 i++ 517 } 518 519 vals.Validators = merged[:i] 520 } 521 522 // Main function used by UpdateWithChangeSet() and NewValidatorSet(). 523 // If 'allowDeletes' is false then delete operations (identified by validators with voting power 0) 524 // are not allowed and will trigger an error if present in 'changes'. 525 // The 'allowDeletes' flag is set to false by NewValidatorSet() and to true by UpdateWithChangeSet(). 526 func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes bool) error { 527 528 if len(changes) <= 0 { 529 return nil 530 } 531 532 // Check for duplicates within changes, split in 'updates' and 'deletes' lists (sorted). 533 updates, deletes, err := processChanges(changes) 534 if err != nil { 535 return err 536 } 537 538 if !allowDeletes && len(deletes) != 0 { 539 return fmt.Errorf("cannot process validators with voting power 0: %v", deletes) 540 } 541 542 // Verify that applying the 'deletes' against 'vals' will not result in error. 543 if err := verifyRemovals(deletes, vals); err != nil { 544 return err 545 } 546 547 // Verify that applying the 'updates' against 'vals' will not result in error. 548 updatedTotalVotingPower, numNewValidators, err := verifyUpdates(updates, vals) 549 if err != nil { 550 return err 551 } 552 553 // Check that the resulting set will not be empty. 554 if numNewValidators == 0 && len(vals.Validators) == len(deletes) { 555 return fmt.Errorf("applying the validator changes would result in empty set") 556 } 557 558 // Compute the priorities for updates. 559 computeNewPriorities(updates, vals, updatedTotalVotingPower) 560 561 // Apply updates and removals. 562 vals.applyUpdates(updates) 563 vals.applyRemovals(deletes) 564 565 vals.updateTotalVotingPower() 566 567 // Scale and center. 568 vals.RescalePriorities(PriorityWindowSizeFactor * vals.TotalVotingPower()) 569 vals.shiftByAvgProposerPriority() 570 571 return nil 572 } 573 574 // UpdateWithChangeSet attempts to update the validator set with 'changes'. 575 // It performs the following steps: 576 // - validates the changes making sure there are no duplicates and splits them in updates and deletes 577 // - verifies that applying the changes will not result in errors 578 // - computes the total voting power BEFORE removals to ensure that in the next steps the priorities 579 // across old and newly added validators are fair 580 // - computes the priorities of new validators against the final set 581 // - applies the updates against the validator set 582 // - applies the removals against the validator set 583 // - performs scaling and centering of priority values 584 // If an error is detected during verification steps, it is returned and the validator set 585 // is not changed. 586 func (vals *ValidatorSet) UpdateWithChangeSet(changes []*Validator) error { 587 return vals.updateWithChangeSet(changes, true) 588 } 589 590 //----------------- 591 // ErrTooMuchChange 592 593 func IsErrTooMuchChange(err error) bool { 594 switch err.(type) { 595 case errTooMuchChange: 596 return true 597 default: 598 return false 599 } 600 } 601 602 type errTooMuchChange struct { 603 got int64 604 needed int64 605 } 606 607 func (e errTooMuchChange) Error() string { 608 return fmt.Sprintf("Invalid commit -- insufficient old voting power: got %v, needed %v", e.got, e.needed) 609 } 610 611 //---------------- 612 613 func (vals *ValidatorSet) String() string { 614 return vals.StringIndented("") 615 } 616 617 func (vals *ValidatorSet) StringIndented(indent string) string { 618 if vals == nil { 619 return "nil-ValidatorSet" 620 } 621 var valStrings []string 622 vals.Iterate(func(index int, val *Validator) bool { 623 valStrings = append(valStrings, val.String()) 624 return false 625 }) 626 return fmt.Sprintf(`ValidatorSet{ 627 %s Proposer: %v 628 %s Validators: 629 %s %v 630 %s}`, 631 indent, vals.GetProposer().String(), 632 indent, 633 indent, strings.Join(valStrings, "\n"+indent+" "), 634 indent) 635 636 } 637 638 //------------------------------------- 639 // Implements sort for sorting validators by address. 640 641 // Sort validators by address. 642 type ValidatorsByAddress []*Validator 643 644 func (valz ValidatorsByAddress) Len() int { 645 return len(valz) 646 } 647 648 func (valz ValidatorsByAddress) Less(i, j int) bool { 649 return bytes.Compare(valz[i].Address.Bytes(), valz[j].Address.Bytes()) == -1 650 } 651 652 func (valz ValidatorsByAddress) Swap(i, j int) { 653 it := valz[i] 654 valz[i] = valz[j] 655 valz[j] = it 656 } 657 658 /////////////////////////////////////////////////////////////////////////////// 659 // safe addition/subtraction 660 661 func safeAdd(a, b int64) (int64, bool) { 662 if b > 0 && a > math.MaxInt64-b { 663 return -1, true 664 } else if b < 0 && a < math.MinInt64-b { 665 return -1, true 666 } 667 return a + b, false 668 } 669 670 func safeSub(a, b int64) (int64, bool) { 671 if b > 0 && a < math.MinInt64+b { 672 return -1, true 673 } else if b < 0 && a > math.MaxInt64+b { 674 return -1, true 675 } 676 return a - b, false 677 } 678 679 func safeAddClip(a, b int64) int64 { 680 c, overflow := safeAdd(a, b) 681 if overflow { 682 if b < 0 { 683 return math.MinInt64 684 } 685 return math.MaxInt64 686 } 687 return c 688 } 689 690 func safeSubClip(a, b int64) int64 { 691 c, overflow := safeSub(a, b) 692 if overflow { 693 if b > 0 { 694 return math.MinInt64 695 } 696 return math.MaxInt64 697 } 698 return c 699 }