github.com/vipernet-xyz/tm@v0.34.24/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/vipernet-xyz/tm/crypto/merkle" 13 tmmath "github.com/vipernet-xyz/tm/libs/math" 14 tmproto "github.com/vipernet-xyz/tm/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 copy := vals.Copy() 109 copy.IncrementProposerPriority(times) 110 return copy 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 433 delta := func(update *Validator, vals *ValidatorSet) int64 { 434 _, val := vals.GetByAddress(update.Address) 435 if val != nil { 436 return update.VotingPower - val.VotingPower 437 } 438 return update.VotingPower 439 } 440 441 updatesCopy := validatorListCopy(updates) 442 sort.Slice(updatesCopy, func(i, j int) bool { 443 return delta(updatesCopy[i], vals) < delta(updatesCopy[j], vals) 444 }) 445 446 tvpAfterRemovals := vals.TotalVotingPower() - removedPower 447 for _, upd := range updatesCopy { 448 tvpAfterRemovals += delta(upd, vals) 449 if tvpAfterRemovals > MaxTotalVotingPower { 450 return 0, ErrTotalVotingPowerOverflow 451 } 452 } 453 return tvpAfterRemovals + removedPower, nil 454 } 455 456 func numNewValidators(updates []*Validator, vals *ValidatorSet) int { 457 numNewValidators := 0 458 for _, valUpdate := range updates { 459 if !vals.HasAddress(valUpdate.Address) { 460 numNewValidators++ 461 } 462 } 463 return numNewValidators 464 } 465 466 // computeNewPriorities computes the proposer priority for the validators not present in the set based on 467 // 'updatedTotalVotingPower'. 468 // Leaves unchanged the priorities of validators that are changed. 469 // 470 // 'updates' parameter must be a list of unique validators to be added or updated. 471 // 472 // 'updatedTotalVotingPower' is the total voting power of a set where all updates would be applied but 473 // 474 // not the removals. It must be < 2*MaxTotalVotingPower and may be close to this limit if close to 475 // MaxTotalVotingPower will be removed. This is still safe from overflow since MaxTotalVotingPower is maxInt64/8. 476 // 477 // No changes are made to the validator set 'vals'. 478 func computeNewPriorities(updates []*Validator, vals *ValidatorSet, updatedTotalVotingPower int64) { 479 for _, valUpdate := range updates { 480 address := valUpdate.Address 481 _, val := vals.GetByAddress(address) 482 if val == nil { 483 // add val 484 // Set ProposerPriority to -C*totalVotingPower (with C ~= 1.125) to make sure validators can't 485 // un-bond and then re-bond to reset their (potentially previously negative) ProposerPriority to zero. 486 // 487 // Contract: updatedVotingPower < 2 * MaxTotalVotingPower to ensure ProposerPriority does 488 // not exceed the bounds of int64. 489 // 490 // Compute ProposerPriority = -1.125*totalVotingPower == -(updatedVotingPower + (updatedVotingPower >> 3)). 491 valUpdate.ProposerPriority = -(updatedTotalVotingPower + (updatedTotalVotingPower >> 3)) 492 } else { 493 valUpdate.ProposerPriority = val.ProposerPriority 494 } 495 } 496 497 } 498 499 // Merges the vals' validator list with the updates list. 500 // When two elements with same address are seen, the one from updates is selected. 501 // Expects updates to be a list of updates sorted by address with no duplicates or errors, 502 // must have been validated with verifyUpdates() and priorities computed with computeNewPriorities(). 503 func (vals *ValidatorSet) applyUpdates(updates []*Validator) { 504 existing := vals.Validators 505 sort.Sort(ValidatorsByAddress(existing)) 506 507 merged := make([]*Validator, len(existing)+len(updates)) 508 i := 0 509 510 for len(existing) > 0 && len(updates) > 0 { 511 if bytes.Compare(existing[0].Address, updates[0].Address) < 0 { // unchanged validator 512 merged[i] = existing[0] 513 existing = existing[1:] 514 } else { 515 // Apply add or update. 516 merged[i] = updates[0] 517 if bytes.Equal(existing[0].Address, updates[0].Address) { 518 // Validator is present in both, advance existing. 519 existing = existing[1:] 520 } 521 updates = updates[1:] 522 } 523 i++ 524 } 525 526 // Add the elements which are left. 527 for j := 0; j < len(existing); j++ { 528 merged[i] = existing[j] 529 i++ 530 } 531 // OR add updates which are left. 532 for j := 0; j < len(updates); j++ { 533 merged[i] = updates[j] 534 i++ 535 } 536 537 vals.Validators = merged[:i] 538 } 539 540 // Checks that the validators to be removed are part of the validator set. 541 // No changes are made to the validator set 'vals'. 542 func verifyRemovals(deletes []*Validator, vals *ValidatorSet) (votingPower int64, err error) { 543 removedVotingPower := int64(0) 544 for _, valUpdate := range deletes { 545 address := valUpdate.Address 546 _, val := vals.GetByAddress(address) 547 if val == nil { 548 return removedVotingPower, fmt.Errorf("failed to find validator %X to remove", address) 549 } 550 removedVotingPower += val.VotingPower 551 } 552 if len(deletes) > len(vals.Validators) { 553 panic("more deletes than validators") 554 } 555 return removedVotingPower, nil 556 } 557 558 // Removes the validators specified in 'deletes' from validator set 'vals'. 559 // Should not fail as verification has been done before. 560 // Expects vals to be sorted by address (done by applyUpdates). 561 func (vals *ValidatorSet) applyRemovals(deletes []*Validator) { 562 existing := vals.Validators 563 564 merged := make([]*Validator, len(existing)-len(deletes)) 565 i := 0 566 567 // Loop over deletes until we removed all of them. 568 for len(deletes) > 0 { 569 if bytes.Equal(existing[0].Address, deletes[0].Address) { 570 deletes = deletes[1:] 571 } else { // Leave it in the resulting slice. 572 merged[i] = existing[0] 573 i++ 574 } 575 existing = existing[1:] 576 } 577 578 // Add the elements which are left. 579 for j := 0; j < len(existing); j++ { 580 merged[i] = existing[j] 581 i++ 582 } 583 584 vals.Validators = merged[:i] 585 } 586 587 // Main function used by UpdateWithChangeSet() and NewValidatorSet(). 588 // If 'allowDeletes' is false then delete operations (identified by validators with voting power 0) 589 // are not allowed and will trigger an error if present in 'changes'. 590 // The 'allowDeletes' flag is set to false by NewValidatorSet() and to true by UpdateWithChangeSet(). 591 func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes bool) error { 592 if len(changes) == 0 { 593 return nil 594 } 595 596 // Check for duplicates within changes, split in 'updates' and 'deletes' lists (sorted). 597 updates, deletes, err := processChanges(changes) 598 if err != nil { 599 return err 600 } 601 602 if !allowDeletes && len(deletes) != 0 { 603 return fmt.Errorf("cannot process validators with voting power 0: %v", deletes) 604 } 605 606 // Check that the resulting set will not be empty. 607 if numNewValidators(updates, vals) == 0 && len(vals.Validators) == len(deletes) { 608 return errors.New("applying the validator changes would result in empty set") 609 } 610 611 // Verify that applying the 'deletes' against 'vals' will not result in error. 612 // Get the voting power that is going to be removed. 613 removedVotingPower, err := verifyRemovals(deletes, vals) 614 if err != nil { 615 return err 616 } 617 618 // Verify that applying the 'updates' against 'vals' will not result in error. 619 // Get the updated total voting power before removal. Note that this is < 2 * MaxTotalVotingPower 620 tvpAfterUpdatesBeforeRemovals, err := verifyUpdates(updates, vals, removedVotingPower) 621 if err != nil { 622 return err 623 } 624 625 // Compute the priorities for updates. 626 computeNewPriorities(updates, vals, tvpAfterUpdatesBeforeRemovals) 627 628 // Apply updates and removals. 629 vals.applyUpdates(updates) 630 vals.applyRemovals(deletes) 631 632 vals.updateTotalVotingPower() // will panic if total voting power > MaxTotalVotingPower 633 634 // Scale and center. 635 vals.RescalePriorities(PriorityWindowSizeFactor * vals.TotalVotingPower()) 636 vals.shiftByAvgProposerPriority() 637 638 sort.Sort(ValidatorsByVotingPower(vals.Validators)) 639 640 return nil 641 } 642 643 // UpdateWithChangeSet attempts to update the validator set with 'changes'. 644 // It performs the following steps: 645 // - validates the changes making sure there are no duplicates and splits them in updates and deletes 646 // - verifies that applying the changes will not result in errors 647 // - computes the total voting power BEFORE removals to ensure that in the next steps the priorities 648 // across old and newly added validators are fair 649 // - computes the priorities of new validators against the final set 650 // - applies the updates against the validator set 651 // - applies the removals against the validator set 652 // - performs scaling and centering of priority values 653 // 654 // If an error is detected during verification steps, it is returned and the validator set 655 // is not changed. 656 func (vals *ValidatorSet) UpdateWithChangeSet(changes []*Validator) error { 657 return vals.updateWithChangeSet(changes, true) 658 } 659 660 // VerifyCommit verifies +2/3 of the set had signed the given commit. 661 // 662 // It checks all the signatures! While it's safe to exit as soon as we have 663 // 2/3+ signatures, doing so would impact incentivization logic in the ABCI 664 // application that depends on the LastCommitInfo sent in BeginBlock, which 665 // includes which validators signed. For instance, Gaia incentivizes proposers 666 // with a bonus for including more than +2/3 of the signatures. 667 func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, 668 height int64, commit *Commit) error { 669 670 if vals.Size() != len(commit.Signatures) { 671 return NewErrInvalidCommitSignatures(vals.Size(), len(commit.Signatures)) 672 } 673 674 // Validate Height and BlockID. 675 if height != commit.Height { 676 return NewErrInvalidCommitHeight(height, commit.Height) 677 } 678 if !blockID.Equals(commit.BlockID) { 679 return fmt.Errorf("invalid commit -- wrong block ID: want %v, got %v", 680 blockID, commit.BlockID) 681 } 682 683 talliedVotingPower := int64(0) 684 votingPowerNeeded := vals.TotalVotingPower() * 2 / 3 685 for idx, commitSig := range commit.Signatures { 686 if commitSig.Absent() { 687 continue // OK, some signatures can be absent. 688 } 689 690 // The vals and commit have a 1-to-1 correspondance. 691 // This means we don't need the validator address or to do any lookup. 692 val := vals.Validators[idx] 693 694 // Validate signature. 695 voteSignBytes := commit.VoteSignBytes(chainID, int32(idx)) 696 if !val.PubKey.VerifySignature(voteSignBytes, commitSig.Signature) { 697 return fmt.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature) 698 } 699 // Good! 700 if commitSig.ForBlock() { 701 talliedVotingPower += val.VotingPower 702 } 703 // else { 704 // It's OK. We include stray signatures (~votes for nil) to measure 705 // validator availability. 706 // } 707 } 708 709 if got, needed := talliedVotingPower, votingPowerNeeded; got <= needed { 710 return ErrNotEnoughVotingPowerSigned{Got: got, Needed: needed} 711 } 712 713 return nil 714 } 715 716 // LIGHT CLIENT VERIFICATION METHODS 717 718 // VerifyCommitLight verifies +2/3 of the set had signed the given commit. 719 // 720 // This method is primarily used by the light client and does not check all the 721 // signatures. 722 func (vals *ValidatorSet) VerifyCommitLight(chainID string, blockID BlockID, 723 height int64, commit *Commit) error { 724 725 if vals.Size() != len(commit.Signatures) { 726 return NewErrInvalidCommitSignatures(vals.Size(), len(commit.Signatures)) 727 } 728 729 // Validate Height and BlockID. 730 if height != commit.Height { 731 return NewErrInvalidCommitHeight(height, commit.Height) 732 } 733 if !blockID.Equals(commit.BlockID) { 734 return fmt.Errorf("invalid commit -- wrong block ID: want %v, got %v", 735 blockID, commit.BlockID) 736 } 737 738 talliedVotingPower := int64(0) 739 votingPowerNeeded := vals.TotalVotingPower() * 2 / 3 740 for idx, commitSig := range commit.Signatures { 741 // No need to verify absent or nil votes. 742 if !commitSig.ForBlock() { 743 continue 744 } 745 746 // The vals and commit have a 1-to-1 correspondance. 747 // This means we don't need the validator address or to do any lookup. 748 val := vals.Validators[idx] 749 750 // Validate signature. 751 voteSignBytes := commit.VoteSignBytes(chainID, int32(idx)) 752 if !val.PubKey.VerifySignature(voteSignBytes, commitSig.Signature) { 753 return fmt.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature) 754 } 755 756 talliedVotingPower += val.VotingPower 757 758 // return as soon as +2/3 of the signatures are verified 759 if talliedVotingPower > votingPowerNeeded { 760 return nil 761 } 762 } 763 764 return ErrNotEnoughVotingPowerSigned{Got: talliedVotingPower, Needed: votingPowerNeeded} 765 } 766 767 // VerifyCommitLightTrusting verifies that trustLevel of the validator set signed 768 // this commit. 769 // 770 // NOTE the given validators do not necessarily correspond to the validator set 771 // for this commit, but there may be some intersection. 772 // 773 // This method is primarily used by the light client and does not check all the 774 // signatures. 775 func (vals *ValidatorSet) VerifyCommitLightTrusting(chainID string, commit *Commit, trustLevel tmmath.Fraction) error { 776 // sanity check 777 if trustLevel.Denominator == 0 { 778 return errors.New("trustLevel has zero Denominator") 779 } 780 781 var ( 782 talliedVotingPower int64 783 seenVals = make(map[int32]int, len(commit.Signatures)) // validator index -> commit index 784 ) 785 786 // Safely calculate voting power needed. 787 totalVotingPowerMulByNumerator, overflow := safeMul(vals.TotalVotingPower(), int64(trustLevel.Numerator)) 788 if overflow { 789 return errors.New("int64 overflow while calculating voting power needed. please provide smaller trustLevel numerator") 790 } 791 votingPowerNeeded := totalVotingPowerMulByNumerator / int64(trustLevel.Denominator) 792 793 for idx, commitSig := range commit.Signatures { 794 // No need to verify absent or nil votes. 795 if !commitSig.ForBlock() { 796 continue 797 } 798 799 // We don't know the validators that committed this block, so we have to 800 // check for each vote if its validator is already known. 801 valIdx, val := vals.GetByAddress(commitSig.ValidatorAddress) 802 803 if val != nil { 804 // check for double vote of validator on the same commit 805 if firstIndex, ok := seenVals[valIdx]; ok { 806 secondIndex := idx 807 return fmt.Errorf("double vote from %v (%d and %d)", val, firstIndex, secondIndex) 808 } 809 seenVals[valIdx] = idx 810 811 // Validate signature. 812 voteSignBytes := commit.VoteSignBytes(chainID, int32(idx)) 813 if !val.PubKey.VerifySignature(voteSignBytes, commitSig.Signature) { 814 return fmt.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature) 815 } 816 817 talliedVotingPower += val.VotingPower 818 819 if talliedVotingPower > votingPowerNeeded { 820 return nil 821 } 822 } 823 } 824 825 return ErrNotEnoughVotingPowerSigned{Got: talliedVotingPower, Needed: votingPowerNeeded} 826 } 827 828 // findPreviousProposer reverses the compare proposer priority function to find the validator 829 // with the lowest proposer priority which would have been the previous proposer. 830 // 831 // Is used when recreating a validator set from an existing array of validators. 832 func (vals *ValidatorSet) findPreviousProposer() *Validator { 833 var previousProposer *Validator 834 for _, val := range vals.Validators { 835 if previousProposer == nil { 836 previousProposer = val 837 continue 838 } 839 if previousProposer == previousProposer.CompareProposerPriority(val) { 840 previousProposer = val 841 } 842 } 843 return previousProposer 844 } 845 846 //----------------- 847 848 // IsErrNotEnoughVotingPowerSigned returns true if err is 849 // ErrNotEnoughVotingPowerSigned. 850 func IsErrNotEnoughVotingPowerSigned(err error) bool { 851 return errors.As(err, &ErrNotEnoughVotingPowerSigned{}) 852 } 853 854 // ErrNotEnoughVotingPowerSigned is returned when not enough validators signed 855 // a commit. 856 type ErrNotEnoughVotingPowerSigned struct { 857 Got int64 858 Needed int64 859 } 860 861 func (e ErrNotEnoughVotingPowerSigned) Error() string { 862 return fmt.Sprintf("invalid commit -- insufficient voting power: got %d, needed more than %d", e.Got, e.Needed) 863 } 864 865 //---------------- 866 867 // String returns a string representation of ValidatorSet. 868 // 869 // See StringIndented. 870 func (vals *ValidatorSet) String() string { 871 return vals.StringIndented("") 872 } 873 874 // StringIndented returns an intended String. 875 // 876 // See Validator#String. 877 func (vals *ValidatorSet) StringIndented(indent string) string { 878 if vals == nil { 879 return "nil-ValidatorSet" 880 } 881 var valStrings []string 882 vals.Iterate(func(index int, val *Validator) bool { 883 valStrings = append(valStrings, val.String()) 884 return false 885 }) 886 return fmt.Sprintf(`ValidatorSet{ 887 %s Proposer: %v 888 %s Validators: 889 %s %v 890 %s}`, 891 indent, vals.GetProposer().String(), 892 indent, 893 indent, strings.Join(valStrings, "\n"+indent+" "), 894 indent) 895 896 } 897 898 //------------------------------------- 899 900 // ValidatorsByVotingPower implements sort.Interface for []*Validator based on 901 // the VotingPower and Address fields. 902 type ValidatorsByVotingPower []*Validator 903 904 func (valz ValidatorsByVotingPower) Len() int { return len(valz) } 905 906 func (valz ValidatorsByVotingPower) Less(i, j int) bool { 907 if valz[i].VotingPower == valz[j].VotingPower { 908 return bytes.Compare(valz[i].Address, valz[j].Address) == -1 909 } 910 return valz[i].VotingPower > valz[j].VotingPower 911 } 912 913 func (valz ValidatorsByVotingPower) Swap(i, j int) { 914 valz[i], valz[j] = valz[j], valz[i] 915 } 916 917 // ValidatorsByAddress implements sort.Interface for []*Validator based on 918 // the Address field. 919 type ValidatorsByAddress []*Validator 920 921 func (valz ValidatorsByAddress) Len() int { return len(valz) } 922 923 func (valz ValidatorsByAddress) Less(i, j int) bool { 924 return bytes.Compare(valz[i].Address, valz[j].Address) == -1 925 } 926 927 func (valz ValidatorsByAddress) Swap(i, j int) { 928 valz[i], valz[j] = valz[j], valz[i] 929 } 930 931 // ToProto converts ValidatorSet to protobuf 932 func (vals *ValidatorSet) ToProto() (*tmproto.ValidatorSet, error) { 933 if vals.IsNilOrEmpty() { 934 return &tmproto.ValidatorSet{}, nil // validator set should never be nil 935 } 936 937 vp := new(tmproto.ValidatorSet) 938 valsProto := make([]*tmproto.Validator, len(vals.Validators)) 939 for i := 0; i < len(vals.Validators); i++ { 940 valp, err := vals.Validators[i].ToProto() 941 if err != nil { 942 return nil, err 943 } 944 valsProto[i] = valp 945 } 946 vp.Validators = valsProto 947 948 valProposer, err := vals.Proposer.ToProto() 949 if err != nil { 950 return nil, fmt.Errorf("toProto: validatorSet proposer error: %w", err) 951 } 952 vp.Proposer = valProposer 953 954 // NOTE: Sometimes we use the bytes of the proto form as a hash. This means that we need to 955 // be consistent with cached data 956 vp.TotalVotingPower = 0 957 958 return vp, nil 959 } 960 961 // ValidatorSetFromProto sets a protobuf ValidatorSet to the given pointer. 962 // It returns an error if any of the validators from the set or the proposer 963 // is invalid 964 func ValidatorSetFromProto(vp *tmproto.ValidatorSet) (*ValidatorSet, error) { 965 if vp == nil { 966 return nil, errors.New("nil validator set") // validator set should never be nil, bigger issues are at play if empty 967 } 968 vals := new(ValidatorSet) 969 970 valsProto := make([]*Validator, len(vp.Validators)) 971 for i := 0; i < len(vp.Validators); i++ { 972 v, err := ValidatorFromProto(vp.Validators[i]) 973 if err != nil { 974 return nil, err 975 } 976 valsProto[i] = v 977 } 978 vals.Validators = valsProto 979 980 p, err := ValidatorFromProto(vp.GetProposer()) 981 if err != nil { 982 return nil, fmt.Errorf("fromProto: validatorSet proposer error: %w", err) 983 } 984 985 vals.Proposer = p 986 987 // NOTE: We can't trust the total voting power given to us by other peers. If someone were to 988 // inject a non-zeo value that wasn't the correct voting power we could assume a wrong total 989 // power hence we need to recompute it. 990 // FIXME: We should look to remove TotalVotingPower from proto or add it in the validators hash 991 // so we don't have to do this 992 vals.TotalVotingPower() 993 994 return vals, vals.ValidateBasic() 995 } 996 997 // ValidatorSetFromExistingValidators takes an existing array of validators and 998 // rebuilds the exact same validator set that corresponds to it without 999 // changing the proposer priority or power if any of the validators fail 1000 // validate basic then an empty set is returned. 1001 func ValidatorSetFromExistingValidators(valz []*Validator) (*ValidatorSet, error) { 1002 if len(valz) == 0 { 1003 return nil, errors.New("validator set is empty") 1004 } 1005 for _, val := range valz { 1006 err := val.ValidateBasic() 1007 if err != nil { 1008 return nil, fmt.Errorf("can't create validator set: %w", err) 1009 } 1010 } 1011 1012 vals := &ValidatorSet{ 1013 Validators: valz, 1014 } 1015 vals.Proposer = vals.findPreviousProposer() 1016 vals.updateTotalVotingPower() 1017 sort.Sort(ValidatorsByVotingPower(vals.Validators)) 1018 return vals, nil 1019 } 1020 1021 //---------------------------------------- 1022 1023 // RandValidatorSet returns a randomized validator set (size: +numValidators+), 1024 // where each validator has a voting power of +votingPower+. 1025 // 1026 // EXPOSED FOR TESTING. 1027 func RandValidatorSet(numValidators int, votingPower int64) (*ValidatorSet, []PrivValidator) { 1028 var ( 1029 valz = make([]*Validator, numValidators) 1030 privValidators = make([]PrivValidator, numValidators) 1031 ) 1032 1033 for i := 0; i < numValidators; i++ { 1034 val, privValidator := RandValidator(false, votingPower) 1035 valz[i] = val 1036 privValidators[i] = privValidator 1037 } 1038 1039 sort.Sort(PrivValidatorsByAddress(privValidators)) 1040 1041 return NewValidatorSet(valz), privValidators 1042 } 1043 1044 // safe addition/subtraction/multiplication 1045 1046 func safeAdd(a, b int64) (int64, bool) { 1047 if b > 0 && a > math.MaxInt64-b { 1048 return -1, true 1049 } else if b < 0 && a < math.MinInt64-b { 1050 return -1, true 1051 } 1052 return a + b, false 1053 } 1054 1055 func safeSub(a, b int64) (int64, bool) { 1056 if b > 0 && a < math.MinInt64+b { 1057 return -1, true 1058 } else if b < 0 && a > math.MaxInt64+b { 1059 return -1, true 1060 } 1061 return a - b, false 1062 } 1063 1064 func safeAddClip(a, b int64) int64 { 1065 c, overflow := safeAdd(a, b) 1066 if overflow { 1067 if b < 0 { 1068 return math.MinInt64 1069 } 1070 return math.MaxInt64 1071 } 1072 return c 1073 } 1074 1075 func safeSubClip(a, b int64) int64 { 1076 c, overflow := safeSub(a, b) 1077 if overflow { 1078 if b > 0 { 1079 return math.MinInt64 1080 } 1081 return math.MaxInt64 1082 } 1083 return c 1084 } 1085 1086 func safeMul(a, b int64) (int64, bool) { 1087 if a == 0 || b == 0 { 1088 return 0, false 1089 } 1090 1091 absOfB := b 1092 if b < 0 { 1093 absOfB = -b 1094 } 1095 1096 absOfA := a 1097 if a < 0 { 1098 absOfA = -a 1099 } 1100 1101 if absOfA > math.MaxInt64/absOfB { 1102 return 0, true 1103 } 1104 1105 return a * b, false 1106 }