github.com/aakash4dev/cometbft@v0.38.2/types/validator_set.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "math" 8 "math/big" 9 "sort" 10 "strings" 11 12 "github.com/aakash4dev/cometbft/crypto/merkle" 13 cmtmath "github.com/aakash4dev/cometbft/libs/math" 14 cmtproto "github.com/aakash4dev/cometbft/proto/tendermint/types" 15 ) 16 17 const ( 18 // MaxTotalVotingPower - the maximum allowed total voting power. 19 // It needs to be sufficiently small to, in all cases: 20 // 1. prevent clipping in incrementProposerPriority() 21 // 2. let (diff+diffMax-1) not overflow in IncrementProposerPriority() 22 // (Proof of 1 is tricky, left to the reader). 23 // It could be higher, but this is sufficiently large for our purposes, 24 // and leaves room for defensive purposes. 25 MaxTotalVotingPower = int64(math.MaxInt64) / 8 26 27 // PriorityWindowSizeFactor - is a constant that when multiplied with the 28 // total voting power gives the maximum allowed distance between validator 29 // priorities. 30 PriorityWindowSizeFactor = 2 31 ) 32 33 // ErrTotalVotingPowerOverflow is returned if the total voting power of the 34 // resulting validator set exceeds MaxTotalVotingPower. 35 var ErrTotalVotingPowerOverflow = fmt.Errorf("total voting power of resulting valset exceeds max %d", 36 MaxTotalVotingPower) 37 38 // ValidatorSet represent a set of *Validator at a given height. 39 // 40 // The validators can be fetched by address or index. 41 // The index is in order of .VotingPower, so the indices are fixed for all 42 // rounds of a given blockchain height - ie. the validators are sorted by their 43 // voting power (descending). Secondary index - .Address (ascending). 44 // 45 // On the other hand, the .ProposerPriority of each validator and the 46 // designated .GetProposer() of a set changes every round, upon calling 47 // .IncrementProposerPriority(). 48 // 49 // NOTE: Not goroutine-safe. 50 // NOTE: All get/set to validators should copy the value for safety. 51 type ValidatorSet struct { 52 // NOTE: persisted via reflect, must be exported. 53 Validators []*Validator `json:"validators"` 54 Proposer *Validator `json:"proposer"` 55 56 // cached (unexported) 57 totalVotingPower int64 58 } 59 60 // NewValidatorSet initializes a ValidatorSet by copying over the values from 61 // `valz`, a list of Validators. If valz is nil or empty, the new ValidatorSet 62 // will have an empty list of Validators. 63 // 64 // The addresses of validators in `valz` must be unique otherwise the function 65 // panics. 66 // 67 // Note the validator set size has an implied limit equal to that of the 68 // MaxVotesCount - commits by a validator set larger than this will fail 69 // validation. 70 func NewValidatorSet(valz []*Validator) *ValidatorSet { 71 vals := &ValidatorSet{} 72 err := vals.updateWithChangeSet(valz, false) 73 if err != nil { 74 panic(fmt.Sprintf("Cannot create validator set: %v", err)) 75 } 76 if len(valz) > 0 { 77 vals.IncrementProposerPriority(1) 78 } 79 return vals 80 } 81 82 func (vals *ValidatorSet) ValidateBasic() error { 83 if vals.IsNilOrEmpty() { 84 return errors.New("validator set is nil or empty") 85 } 86 87 for idx, val := range vals.Validators { 88 if err := val.ValidateBasic(); err != nil { 89 return fmt.Errorf("invalid validator #%d: %w", idx, err) 90 } 91 } 92 93 if err := vals.Proposer.ValidateBasic(); err != nil { 94 return fmt.Errorf("proposer failed validate basic, error: %w", err) 95 } 96 97 return nil 98 } 99 100 // IsNilOrEmpty returns true if validator set is nil or empty. 101 func (vals *ValidatorSet) IsNilOrEmpty() bool { 102 return vals == nil || len(vals.Validators) == 0 103 } 104 105 // CopyIncrementProposerPriority increments ProposerPriority and updates the 106 // proposer on a copy, and returns it. 107 func (vals *ValidatorSet) CopyIncrementProposerPriority(times int32) *ValidatorSet { 108 cp := vals.Copy() 109 cp.IncrementProposerPriority(times) 110 return cp 111 } 112 113 // IncrementProposerPriority increments ProposerPriority of each validator and 114 // updates the proposer. Panics if validator set is empty. 115 // `times` must be positive. 116 func (vals *ValidatorSet) IncrementProposerPriority(times int32) { 117 if vals.IsNilOrEmpty() { 118 panic("empty validator set") 119 } 120 if times <= 0 { 121 panic("Cannot call IncrementProposerPriority with non-positive times") 122 } 123 124 // Cap the difference between priorities to be proportional to 2*totalPower by 125 // re-normalizing priorities, i.e., rescale all priorities by multiplying with: 126 // 2*totalVotingPower/(maxPriority - minPriority) 127 diffMax := PriorityWindowSizeFactor * vals.TotalVotingPower() 128 vals.RescalePriorities(diffMax) 129 vals.shiftByAvgProposerPriority() 130 131 var proposer *Validator 132 // Call IncrementProposerPriority(1) times times. 133 for i := int32(0); i < times; i++ { 134 proposer = vals.incrementProposerPriority() 135 } 136 137 vals.Proposer = proposer 138 } 139 140 // RescalePriorities rescales the priorities such that the distance between the 141 // maximum and minimum is smaller than `diffMax`. Panics if validator set is 142 // empty. 143 func (vals *ValidatorSet) RescalePriorities(diffMax int64) { 144 if vals.IsNilOrEmpty() { 145 panic("empty validator set") 146 } 147 // NOTE: This check is merely a sanity check which could be 148 // removed if all tests would init. voting power appropriately; 149 // i.e. diffMax should always be > 0 150 if diffMax <= 0 { 151 return 152 } 153 154 // Calculating ceil(diff/diffMax): 155 // Re-normalization is performed by dividing by an integer for simplicity. 156 // NOTE: This may make debugging priority issues easier as well. 157 diff := computeMaxMinPriorityDiff(vals) 158 ratio := (diff + diffMax - 1) / diffMax 159 if diff > diffMax { 160 for _, val := range vals.Validators { 161 val.ProposerPriority /= ratio 162 } 163 } 164 } 165 166 func (vals *ValidatorSet) incrementProposerPriority() *Validator { 167 for _, val := range vals.Validators { 168 // Check for overflow for sum. 169 newPrio := safeAddClip(val.ProposerPriority, val.VotingPower) 170 val.ProposerPriority = newPrio 171 } 172 // Decrement the validator with most ProposerPriority. 173 mostest := vals.getValWithMostPriority() 174 // Mind the underflow. 175 mostest.ProposerPriority = safeSubClip(mostest.ProposerPriority, vals.TotalVotingPower()) 176 177 return mostest 178 } 179 180 // Should not be called on an empty validator set. 181 func (vals *ValidatorSet) computeAvgProposerPriority() int64 { 182 n := int64(len(vals.Validators)) 183 sum := big.NewInt(0) 184 for _, val := range vals.Validators { 185 sum.Add(sum, big.NewInt(val.ProposerPriority)) 186 } 187 avg := sum.Div(sum, big.NewInt(n)) 188 if avg.IsInt64() { 189 return avg.Int64() 190 } 191 192 // This should never happen: each val.ProposerPriority is in bounds of int64. 193 panic(fmt.Sprintf("Cannot represent avg ProposerPriority as an int64 %v", avg)) 194 } 195 196 // Compute the difference between the max and min ProposerPriority of that set. 197 func computeMaxMinPriorityDiff(vals *ValidatorSet) int64 { 198 if vals.IsNilOrEmpty() { 199 panic("empty validator set") 200 } 201 max := int64(math.MinInt64) 202 min := int64(math.MaxInt64) 203 for _, v := range vals.Validators { 204 if v.ProposerPriority < min { 205 min = v.ProposerPriority 206 } 207 if v.ProposerPriority > max { 208 max = v.ProposerPriority 209 } 210 } 211 diff := max - min 212 if diff < 0 { 213 return -1 * diff 214 } 215 return diff 216 } 217 218 func (vals *ValidatorSet) getValWithMostPriority() *Validator { 219 var res *Validator 220 for _, val := range vals.Validators { 221 res = res.CompareProposerPriority(val) 222 } 223 return res 224 } 225 226 func (vals *ValidatorSet) shiftByAvgProposerPriority() { 227 if vals.IsNilOrEmpty() { 228 panic("empty validator set") 229 } 230 avgProposerPriority := vals.computeAvgProposerPriority() 231 for _, val := range vals.Validators { 232 val.ProposerPriority = safeSubClip(val.ProposerPriority, avgProposerPriority) 233 } 234 } 235 236 // Makes a copy of the validator list. 237 func validatorListCopy(valsList []*Validator) []*Validator { 238 if valsList == nil { 239 return nil 240 } 241 valsCopy := make([]*Validator, len(valsList)) 242 for i, val := range valsList { 243 valsCopy[i] = val.Copy() 244 } 245 return valsCopy 246 } 247 248 // Copy each validator into a new ValidatorSet. 249 func (vals *ValidatorSet) Copy() *ValidatorSet { 250 return &ValidatorSet{ 251 Validators: validatorListCopy(vals.Validators), 252 Proposer: vals.Proposer, 253 totalVotingPower: vals.totalVotingPower, 254 } 255 } 256 257 // HasAddress returns true if address given is in the validator set, false - 258 // otherwise. 259 func (vals *ValidatorSet) HasAddress(address []byte) bool { 260 for _, val := range vals.Validators { 261 if bytes.Equal(val.Address, address) { 262 return true 263 } 264 } 265 return false 266 } 267 268 // GetByAddress returns an index of the validator with address and validator 269 // itself (copy) if found. Otherwise, -1 and nil are returned. 270 func (vals *ValidatorSet) GetByAddress(address []byte) (index int32, val *Validator) { 271 for idx, val := range vals.Validators { 272 if bytes.Equal(val.Address, address) { 273 return int32(idx), val.Copy() 274 } 275 } 276 return -1, nil 277 } 278 279 // GetByIndex returns the validator's address and validator itself (copy) by 280 // index. 281 // It returns nil values if index is less than 0 or greater or equal to 282 // len(ValidatorSet.Validators). 283 func (vals *ValidatorSet) GetByIndex(index int32) (address []byte, val *Validator) { 284 if index < 0 || int(index) >= len(vals.Validators) { 285 return nil, nil 286 } 287 val = vals.Validators[index] 288 return val.Address, val.Copy() 289 } 290 291 // Size returns the length of the validator set. 292 func (vals *ValidatorSet) Size() int { 293 return len(vals.Validators) 294 } 295 296 // Forces recalculation of the set's total voting power. 297 // Panics if total voting power is bigger than MaxTotalVotingPower. 298 func (vals *ValidatorSet) updateTotalVotingPower() { 299 sum := int64(0) 300 for _, val := range vals.Validators { 301 // mind overflow 302 sum = safeAddClip(sum, val.VotingPower) 303 if sum > MaxTotalVotingPower { 304 panic(fmt.Sprintf( 305 "Total voting power should be guarded to not exceed %v; got: %v", 306 MaxTotalVotingPower, 307 sum)) 308 } 309 } 310 311 vals.totalVotingPower = sum 312 } 313 314 // TotalVotingPower returns the sum of the voting powers of all validators. 315 // It recomputes the total voting power if required. 316 func (vals *ValidatorSet) TotalVotingPower() int64 { 317 if vals.totalVotingPower == 0 { 318 vals.updateTotalVotingPower() 319 } 320 return vals.totalVotingPower 321 } 322 323 // GetProposer returns the current proposer. If the validator set is empty, nil 324 // is returned. 325 func (vals *ValidatorSet) GetProposer() (proposer *Validator) { 326 if len(vals.Validators) == 0 { 327 return nil 328 } 329 if vals.Proposer == nil { 330 vals.Proposer = vals.findProposer() 331 } 332 return vals.Proposer.Copy() 333 } 334 335 func (vals *ValidatorSet) findProposer() *Validator { 336 var proposer *Validator 337 for _, val := range vals.Validators { 338 if proposer == nil || !bytes.Equal(val.Address, proposer.Address) { 339 proposer = proposer.CompareProposerPriority(val) 340 } 341 } 342 return proposer 343 } 344 345 // Hash returns the Merkle root hash build using validators (as leaves) in the 346 // set. 347 func (vals *ValidatorSet) Hash() []byte { 348 bzs := make([][]byte, len(vals.Validators)) 349 for i, val := range vals.Validators { 350 bzs[i] = val.Bytes() 351 } 352 return merkle.HashFromByteSlices(bzs) 353 } 354 355 // Iterate will run the given function over the set. 356 func (vals *ValidatorSet) Iterate(fn func(index int, val *Validator) bool) { 357 for i, val := range vals.Validators { 358 stop := fn(i, val.Copy()) 359 if stop { 360 break 361 } 362 } 363 } 364 365 // Checks changes against duplicates, splits the changes in updates and 366 // removals, sorts them by address. 367 // 368 // Returns: 369 // updates, removals - the sorted lists of updates and removals 370 // err - non-nil if duplicate entries or entries with negative voting power are seen 371 // 372 // No changes are made to 'origChanges'. 373 func processChanges(origChanges []*Validator) (updates, removals []*Validator, err error) { 374 // Make a deep copy of the changes and sort by address. 375 changes := validatorListCopy(origChanges) 376 sort.Sort(ValidatorsByAddress(changes)) 377 378 removals = make([]*Validator, 0, len(changes)) 379 updates = make([]*Validator, 0, len(changes)) 380 var prevAddr Address 381 382 // Scan changes by address and append valid validators to updates or removals lists. 383 for _, valUpdate := range changes { 384 if bytes.Equal(valUpdate.Address, prevAddr) { 385 err = fmt.Errorf("duplicate entry %v in %v", valUpdate, changes) 386 return nil, nil, err 387 } 388 389 switch { 390 case valUpdate.VotingPower < 0: 391 err = fmt.Errorf("voting power can't be negative: %d", valUpdate.VotingPower) 392 return nil, nil, err 393 case valUpdate.VotingPower > MaxTotalVotingPower: 394 err = fmt.Errorf("to prevent clipping/overflow, voting power can't be higher than %d, got %d", 395 MaxTotalVotingPower, valUpdate.VotingPower) 396 return nil, nil, err 397 case valUpdate.VotingPower == 0: 398 removals = append(removals, valUpdate) 399 default: 400 updates = append(updates, valUpdate) 401 } 402 403 prevAddr = valUpdate.Address 404 } 405 406 return updates, removals, err 407 } 408 409 // verifyUpdates verifies a list of updates against a validator set, making sure the allowed 410 // total voting power would not be exceeded if these updates would be applied to the set. 411 // 412 // Inputs: 413 // updates - a list of proper validator changes, i.e. they have been verified by processChanges for duplicates 414 // 415 // and invalid values. 416 // 417 // vals - the original validator set. Note that vals is NOT modified by this function. 418 // removedPower - the total voting power that will be removed after the updates are verified and applied. 419 // 420 // Returns: 421 // tvpAfterUpdatesBeforeRemovals - the new total voting power if these updates would be applied without the removals. 422 // 423 // Note that this will be < 2 * MaxTotalVotingPower in case high power validators are removed and 424 // validators are added/ updated with high power values. 425 // 426 // err - non-nil if the maximum allowed total voting power would be exceeded 427 func verifyUpdates( 428 updates []*Validator, 429 vals *ValidatorSet, 430 removedPower int64, 431 ) (tvpAfterUpdatesBeforeRemovals int64, err error) { 432 delta := func(update *Validator, vals *ValidatorSet) int64 { 433 _, val := vals.GetByAddress(update.Address) 434 if val != nil { 435 return update.VotingPower - val.VotingPower 436 } 437 return update.VotingPower 438 } 439 440 updatesCopy := validatorListCopy(updates) 441 sort.Slice(updatesCopy, func(i, j int) bool { 442 return delta(updatesCopy[i], vals) < delta(updatesCopy[j], vals) 443 }) 444 445 tvpAfterRemovals := vals.TotalVotingPower() - removedPower 446 for _, upd := range updatesCopy { 447 tvpAfterRemovals += delta(upd, vals) 448 if tvpAfterRemovals > MaxTotalVotingPower { 449 return 0, ErrTotalVotingPowerOverflow 450 } 451 } 452 return tvpAfterRemovals + removedPower, nil 453 } 454 455 func numNewValidators(updates []*Validator, vals *ValidatorSet) int { 456 numNewValidators := 0 457 for _, valUpdate := range updates { 458 if !vals.HasAddress(valUpdate.Address) { 459 numNewValidators++ 460 } 461 } 462 return numNewValidators 463 } 464 465 // computeNewPriorities computes the proposer priority for the validators not present in the set based on 466 // 'updatedTotalVotingPower'. 467 // Leaves unchanged the priorities of validators that are changed. 468 // 469 // 'updates' parameter must be a list of unique validators to be added or updated. 470 // 471 // 'updatedTotalVotingPower' is the total voting power of a set where all updates would be applied but 472 // 473 // not the removals. It must be < 2*MaxTotalVotingPower and may be close to this limit if close to 474 // MaxTotalVotingPower will be removed. This is still safe from overflow since MaxTotalVotingPower is maxInt64/8. 475 // 476 // No changes are made to the validator set 'vals'. 477 func computeNewPriorities(updates []*Validator, vals *ValidatorSet, updatedTotalVotingPower int64) { 478 for _, valUpdate := range updates { 479 address := valUpdate.Address 480 _, val := vals.GetByAddress(address) 481 if val == nil { 482 // add val 483 // Set ProposerPriority to -C*totalVotingPower (with C ~= 1.125) to make sure validators can't 484 // un-bond and then re-bond to reset their (potentially previously negative) ProposerPriority to zero. 485 // 486 // Contract: updatedVotingPower < 2 * MaxTotalVotingPower to ensure ProposerPriority does 487 // not exceed the bounds of int64. 488 // 489 // Compute ProposerPriority = -1.125*totalVotingPower == -(updatedVotingPower + (updatedVotingPower >> 3)). 490 valUpdate.ProposerPriority = -(updatedTotalVotingPower + (updatedTotalVotingPower >> 3)) 491 } else { 492 valUpdate.ProposerPriority = val.ProposerPriority 493 } 494 } 495 } 496 497 // Merges the vals' validator list with the updates list. 498 // When two elements with same address are seen, the one from updates is selected. 499 // Expects updates to be a list of updates sorted by address with no duplicates or errors, 500 // must have been validated with verifyUpdates() and priorities computed with computeNewPriorities(). 501 func (vals *ValidatorSet) applyUpdates(updates []*Validator) { 502 existing := vals.Validators 503 sort.Sort(ValidatorsByAddress(existing)) 504 505 merged := make([]*Validator, len(existing)+len(updates)) 506 i := 0 507 508 for len(existing) > 0 && len(updates) > 0 { 509 if bytes.Compare(existing[0].Address, updates[0].Address) < 0 { // unchanged validator 510 merged[i] = existing[0] 511 existing = existing[1:] 512 } else { 513 // Apply add or update. 514 merged[i] = updates[0] 515 if bytes.Equal(existing[0].Address, updates[0].Address) { 516 // Validator is present in both, advance existing. 517 existing = existing[1:] 518 } 519 updates = updates[1:] 520 } 521 i++ 522 } 523 524 // Add the elements which are left. 525 for j := 0; j < len(existing); j++ { 526 merged[i] = existing[j] 527 i++ 528 } 529 // OR add updates which are left. 530 for j := 0; j < len(updates); j++ { 531 merged[i] = updates[j] 532 i++ 533 } 534 535 vals.Validators = merged[:i] 536 } 537 538 // Checks that the validators to be removed are part of the validator set. 539 // No changes are made to the validator set 'vals'. 540 func verifyRemovals(deletes []*Validator, vals *ValidatorSet) (votingPower int64, err error) { 541 removedVotingPower := int64(0) 542 for _, valUpdate := range deletes { 543 address := valUpdate.Address 544 _, val := vals.GetByAddress(address) 545 if val == nil { 546 return removedVotingPower, fmt.Errorf("failed to find validator %X to remove", address) 547 } 548 removedVotingPower += val.VotingPower 549 } 550 if len(deletes) > len(vals.Validators) { 551 panic("more deletes than validators") 552 } 553 return removedVotingPower, nil 554 } 555 556 // Removes the validators specified in 'deletes' from validator set 'vals'. 557 // Should not fail as verification has been done before. 558 // Expects vals to be sorted by address (done by applyUpdates). 559 func (vals *ValidatorSet) applyRemovals(deletes []*Validator) { 560 existing := vals.Validators 561 562 merged := make([]*Validator, len(existing)-len(deletes)) 563 i := 0 564 565 // Loop over deletes until we removed all of them. 566 for len(deletes) > 0 { 567 if bytes.Equal(existing[0].Address, deletes[0].Address) { 568 deletes = deletes[1:] 569 } else { // Leave it in the resulting slice. 570 merged[i] = existing[0] 571 i++ 572 } 573 existing = existing[1:] 574 } 575 576 // Add the elements which are left. 577 for j := 0; j < len(existing); j++ { 578 merged[i] = existing[j] 579 i++ 580 } 581 582 vals.Validators = merged[:i] 583 } 584 585 // Main function used by UpdateWithChangeSet() and NewValidatorSet(). 586 // If 'allowDeletes' is false then delete operations (identified by validators with voting power 0) 587 // are not allowed and will trigger an error if present in 'changes'. 588 // The 'allowDeletes' flag is set to false by NewValidatorSet() and to true by UpdateWithChangeSet(). 589 func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes bool) error { 590 if len(changes) == 0 { 591 return nil 592 } 593 594 // Check for duplicates within changes, split in 'updates' and 'deletes' lists (sorted). 595 updates, deletes, err := processChanges(changes) 596 if err != nil { 597 return err 598 } 599 600 if !allowDeletes && len(deletes) != 0 { 601 return fmt.Errorf("cannot process validators with voting power 0: %v", deletes) 602 } 603 604 // Check that the resulting set will not be empty. 605 if numNewValidators(updates, vals) == 0 && len(vals.Validators) == len(deletes) { 606 return errors.New("applying the validator changes would result in empty set") 607 } 608 609 // Verify that applying the 'deletes' against 'vals' will not result in error. 610 // Get the voting power that is going to be removed. 611 removedVotingPower, err := verifyRemovals(deletes, vals) 612 if err != nil { 613 return err 614 } 615 616 // Verify that applying the 'updates' against 'vals' will not result in error. 617 // Get the updated total voting power before removal. Note that this is < 2 * MaxTotalVotingPower 618 tvpAfterUpdatesBeforeRemovals, err := verifyUpdates(updates, vals, removedVotingPower) 619 if err != nil { 620 return err 621 } 622 623 // Compute the priorities for updates. 624 computeNewPriorities(updates, vals, tvpAfterUpdatesBeforeRemovals) 625 626 // Apply updates and removals. 627 vals.applyUpdates(updates) 628 vals.applyRemovals(deletes) 629 630 vals.updateTotalVotingPower() // will panic if total voting power > MaxTotalVotingPower 631 632 // Scale and center. 633 vals.RescalePriorities(PriorityWindowSizeFactor * vals.TotalVotingPower()) 634 vals.shiftByAvgProposerPriority() 635 636 sort.Sort(ValidatorsByVotingPower(vals.Validators)) 637 638 return nil 639 } 640 641 // UpdateWithChangeSet attempts to update the validator set with 'changes'. 642 // It performs the following steps: 643 // - validates the changes making sure there are no duplicates and splits them in updates and deletes 644 // - verifies that applying the changes will not result in errors 645 // - computes the total voting power BEFORE removals to ensure that in the next steps the priorities 646 // across old and newly added validators are fair 647 // - computes the priorities of new validators against the final set 648 // - applies the updates against the validator set 649 // - applies the removals against the validator set 650 // - performs scaling and centering of priority values 651 // 652 // If an error is detected during verification steps, it is returned and the validator set 653 // is not changed. 654 func (vals *ValidatorSet) UpdateWithChangeSet(changes []*Validator) error { 655 return vals.updateWithChangeSet(changes, true) 656 } 657 658 // VerifyCommit verifies +2/3 of the set had signed the given commit and all 659 // other signatures are valid 660 func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, 661 height int64, commit *Commit, 662 ) error { 663 return VerifyCommit(chainID, vals, blockID, height, commit) 664 } 665 666 // LIGHT CLIENT VERIFICATION METHODS 667 668 // VerifyCommitLight verifies +2/3 of the set had signed the given commit. 669 func (vals *ValidatorSet) VerifyCommitLight(chainID string, blockID BlockID, 670 height int64, commit *Commit, 671 ) error { 672 return VerifyCommitLight(chainID, vals, blockID, height, commit) 673 } 674 675 // VerifyCommitLightTrusting verifies that trustLevel of the validator set signed 676 // this commit. 677 func (vals *ValidatorSet) VerifyCommitLightTrusting(chainID string, commit *Commit, trustLevel cmtmath.Fraction) error { 678 return VerifyCommitLightTrusting(chainID, vals, commit, trustLevel) 679 } 680 681 // findPreviousProposer reverses the compare proposer priority function to find the validator 682 // with the lowest proposer priority which would have been the previous proposer. 683 // 684 // Is used when recreating a validator set from an existing array of validators. 685 func (vals *ValidatorSet) findPreviousProposer() *Validator { 686 var previousProposer *Validator 687 for _, val := range vals.Validators { 688 if previousProposer == nil { 689 previousProposer = val 690 continue 691 } 692 if previousProposer == previousProposer.CompareProposerPriority(val) { 693 previousProposer = val 694 } 695 } 696 return previousProposer 697 } 698 699 //----------------- 700 701 // IsErrNotEnoughVotingPowerSigned returns true if err is 702 // ErrNotEnoughVotingPowerSigned. 703 func IsErrNotEnoughVotingPowerSigned(err error) bool { 704 return errors.As(err, &ErrNotEnoughVotingPowerSigned{}) 705 } 706 707 // ErrNotEnoughVotingPowerSigned is returned when not enough validators signed 708 // a commit. 709 type ErrNotEnoughVotingPowerSigned struct { 710 Got int64 711 Needed int64 712 } 713 714 func (e ErrNotEnoughVotingPowerSigned) Error() string { 715 return fmt.Sprintf("invalid commit -- insufficient voting power: got %d, needed more than %d", e.Got, e.Needed) 716 } 717 718 //---------------- 719 720 // String returns a string representation of ValidatorSet. 721 // 722 // See StringIndented. 723 func (vals *ValidatorSet) String() string { 724 return vals.StringIndented("") 725 } 726 727 // StringIndented returns an intended String. 728 // 729 // See Validator#String. 730 func (vals *ValidatorSet) StringIndented(indent string) string { 731 if vals == nil { 732 return "nil-ValidatorSet" 733 } 734 var valStrings []string 735 vals.Iterate(func(index int, val *Validator) bool { 736 valStrings = append(valStrings, val.String()) 737 return false 738 }) 739 return fmt.Sprintf(`ValidatorSet{ 740 %s Proposer: %v 741 %s Validators: 742 %s %v 743 %s}`, 744 indent, vals.GetProposer().String(), 745 indent, 746 indent, strings.Join(valStrings, "\n"+indent+" "), 747 indent) 748 } 749 750 //------------------------------------- 751 752 // ValidatorsByVotingPower implements sort.Interface for []*Validator based on 753 // the VotingPower and Address fields. 754 type ValidatorsByVotingPower []*Validator 755 756 func (valz ValidatorsByVotingPower) Len() int { return len(valz) } 757 758 func (valz ValidatorsByVotingPower) Less(i, j int) bool { 759 if valz[i].VotingPower == valz[j].VotingPower { 760 return bytes.Compare(valz[i].Address, valz[j].Address) == -1 761 } 762 return valz[i].VotingPower > valz[j].VotingPower 763 } 764 765 func (valz ValidatorsByVotingPower) Swap(i, j int) { 766 valz[i], valz[j] = valz[j], valz[i] 767 } 768 769 // ValidatorsByAddress implements sort.Interface for []*Validator based on 770 // the Address field. 771 type ValidatorsByAddress []*Validator 772 773 func (valz ValidatorsByAddress) Len() int { return len(valz) } 774 775 func (valz ValidatorsByAddress) Less(i, j int) bool { 776 return bytes.Compare(valz[i].Address, valz[j].Address) == -1 777 } 778 779 func (valz ValidatorsByAddress) Swap(i, j int) { 780 valz[i], valz[j] = valz[j], valz[i] 781 } 782 783 // ToProto converts ValidatorSet to protobuf 784 func (vals *ValidatorSet) ToProto() (*cmtproto.ValidatorSet, error) { 785 if vals.IsNilOrEmpty() { 786 return &cmtproto.ValidatorSet{}, nil // validator set should never be nil 787 } 788 789 vp := new(cmtproto.ValidatorSet) 790 valsProto := make([]*cmtproto.Validator, len(vals.Validators)) 791 for i := 0; i < len(vals.Validators); i++ { 792 valp, err := vals.Validators[i].ToProto() 793 if err != nil { 794 return nil, err 795 } 796 valsProto[i] = valp 797 } 798 vp.Validators = valsProto 799 800 valProposer, err := vals.Proposer.ToProto() 801 if err != nil { 802 return nil, fmt.Errorf("toProto: validatorSet proposer error: %w", err) 803 } 804 vp.Proposer = valProposer 805 806 // NOTE: Sometimes we use the bytes of the proto form as a hash. This means that we need to 807 // be consistent with cached data 808 vp.TotalVotingPower = 0 809 810 return vp, nil 811 } 812 813 // ValidatorSetFromProto sets a protobuf ValidatorSet to the given pointer. 814 // It returns an error if any of the validators from the set or the proposer 815 // is invalid 816 func ValidatorSetFromProto(vp *cmtproto.ValidatorSet) (*ValidatorSet, error) { 817 if vp == nil { 818 return nil, errors.New("nil validator set") // validator set should never be nil, bigger issues are at play if empty 819 } 820 vals := new(ValidatorSet) 821 822 valsProto := make([]*Validator, len(vp.Validators)) 823 for i := 0; i < len(vp.Validators); i++ { 824 v, err := ValidatorFromProto(vp.Validators[i]) 825 if err != nil { 826 return nil, err 827 } 828 valsProto[i] = v 829 } 830 vals.Validators = valsProto 831 832 p, err := ValidatorFromProto(vp.GetProposer()) 833 if err != nil { 834 return nil, fmt.Errorf("fromProto: validatorSet proposer error: %w", err) 835 } 836 837 vals.Proposer = p 838 839 // NOTE: We can't trust the total voting power given to us by other peers. If someone were to 840 // inject a non-zeo value that wasn't the correct voting power we could assume a wrong total 841 // power hence we need to recompute it. 842 // FIXME: We should look to remove TotalVotingPower from proto or add it in the validators hash 843 // so we don't have to do this 844 vals.TotalVotingPower() 845 846 return vals, vals.ValidateBasic() 847 } 848 849 // ValidatorSetFromExistingValidators takes an existing array of validators and 850 // rebuilds the exact same validator set that corresponds to it without 851 // changing the proposer priority or power if any of the validators fail 852 // validate basic then an empty set is returned. 853 func ValidatorSetFromExistingValidators(valz []*Validator) (*ValidatorSet, error) { 854 if len(valz) == 0 { 855 return nil, errors.New("validator set is empty") 856 } 857 for _, val := range valz { 858 err := val.ValidateBasic() 859 if err != nil { 860 return nil, fmt.Errorf("can't create validator set: %w", err) 861 } 862 } 863 864 vals := &ValidatorSet{ 865 Validators: valz, 866 } 867 vals.Proposer = vals.findPreviousProposer() 868 vals.updateTotalVotingPower() 869 sort.Sort(ValidatorsByVotingPower(vals.Validators)) 870 return vals, nil 871 } 872 873 //---------------------------------------- 874 875 // RandValidatorSet returns a randomized validator set (size: +numValidators+), 876 // where each validator has a voting power of +votingPower+. 877 // 878 // EXPOSED FOR TESTING. 879 func RandValidatorSet(numValidators int, votingPower int64) (*ValidatorSet, []PrivValidator) { 880 var ( 881 valz = make([]*Validator, numValidators) 882 privValidators = make([]PrivValidator, numValidators) 883 ) 884 885 for i := 0; i < numValidators; i++ { 886 val, privValidator := RandValidator(false, votingPower) 887 valz[i] = val 888 privValidators[i] = privValidator 889 } 890 891 sort.Sort(PrivValidatorsByAddress(privValidators)) 892 893 return NewValidatorSet(valz), privValidators 894 } 895 896 // safe addition/subtraction/multiplication 897 898 func safeAdd(a, b int64) (int64, bool) { 899 if b > 0 && a > math.MaxInt64-b { 900 return -1, true 901 } else if b < 0 && a < math.MinInt64-b { 902 return -1, true 903 } 904 return a + b, false 905 } 906 907 func safeSub(a, b int64) (int64, bool) { 908 if b > 0 && a < math.MinInt64+b { 909 return -1, true 910 } else if b < 0 && a > math.MaxInt64+b { 911 return -1, true 912 } 913 return a - b, false 914 } 915 916 func safeAddClip(a, b int64) int64 { 917 c, overflow := safeAdd(a, b) 918 if overflow { 919 if b < 0 { 920 return math.MinInt64 921 } 922 return math.MaxInt64 923 } 924 return c 925 } 926 927 func safeSubClip(a, b int64) int64 { 928 c, overflow := safeSub(a, b) 929 if overflow { 930 if b > 0 { 931 return math.MinInt64 932 } 933 return math.MaxInt64 934 } 935 return c 936 } 937 938 func safeMul(a, b int64) (int64, bool) { 939 if a == 0 || b == 0 { 940 return 0, false 941 } 942 943 absOfB := b 944 if b < 0 { 945 absOfB = -b 946 } 947 948 absOfA := a 949 if a < 0 { 950 absOfA = -a 951 } 952 953 if absOfA > math.MaxInt64/absOfB { 954 return 0, true 955 } 956 957 return a * b, false 958 }