github.com/Finschia/ostracon@v1.1.5/types/validator_set.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "errors" 7 "fmt" 8 "math" 9 "math/big" 10 "sort" 11 "strings" 12 13 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 14 15 "github.com/Finschia/ostracon/crypto/merkle" 16 "github.com/Finschia/ostracon/crypto/tmhash" 17 tmmath "github.com/Finschia/ostracon/libs/math" 18 ) 19 20 const ( 21 // MaxTotalVotingPower - the maximum allowed total voting power. 22 // It needs to be sufficiently small to, in all cases: 23 // 1. prevent clipping in incrementProposerPriority() 24 // 2. let (diff+diffMax-1) not overflow in IncrementProposerPriority() 25 // (Proof of 1 is tricky, left to the reader). 26 // It could be higher, but this is sufficiently large for our purposes, 27 // and leaves room for defensive purposes. 28 MaxTotalVotingPower = int64(math.MaxInt64) / 8 29 30 // PriorityWindowSizeFactor - is a constant that when multiplied with the 31 // total voting power gives the maximum allowed distance between validator 32 // priorities. 33 PriorityWindowSizeFactor = 2 34 ) 35 36 // ErrTotalVotingPowerOverflow is returned if the total voting power of the 37 // resulting validator set exceeds MaxTotalVotingPower. 38 var ErrTotalVotingPowerOverflow = fmt.Errorf("total voting power of resulting valset exceeds max %d", 39 MaxTotalVotingPower) 40 41 // ValidatorSet represent a set of *Validator at a given height. 42 // 43 // The validators can be fetched by address or index. 44 // The index is in order of .VotingPower, so the indices are fixed for all 45 // rounds of a given blockchain height - ie. the validators are sorted by their 46 // voting power (descending). Secondary index - .Address (ascending). 47 // 48 // On the other hand, the .ProposerPriority of each validator and the 49 // designated .GetProposer() of a set changes every round, upon calling 50 // .IncrementProposerPriority(). 51 // 52 // NOTE: Not goroutine-safe. 53 // NOTE: All get/set to validators should copy the value for safety. 54 type ValidatorSet struct { 55 // NOTE: persisted via reflect, must be exported. 56 Validators []*Validator `json:"validators"` 57 58 // cached (unexported) 59 totalVotingPower int64 60 } 61 62 // NewValidatorSet initializes a ValidatorSet by copying over the values from 63 // `valz`, a list of Validators. If valz is nil or empty, the new ValidatorSet 64 // will have an empty list of Validators. 65 // 66 // The addresses of validators in `valz` must be unique otherwise the function 67 // panics. 68 // 69 // Note the validator set size has an implied limit equal to that of the 70 // MaxVotesCount - commits by a validator set larger than this will fail 71 // validation. 72 func NewValidatorSet(valz []*Validator) *ValidatorSet { 73 vals := &ValidatorSet{} 74 err := vals.updateWithChangeSet(valz, false) 75 if err != nil { 76 panic(fmt.Sprintf("Cannot create validator set: %v", err)) 77 } 78 return vals 79 } 80 81 func (vals *ValidatorSet) ValidateBasic() error { 82 if vals.IsNilOrEmpty() { 83 return errors.New("validator set is nil or empty") 84 } 85 86 for idx, val := range vals.Validators { 87 if err := val.ValidateBasic(); err != nil { 88 return fmt.Errorf("invalid validator #%d: %w", idx, err) 89 } 90 } 91 92 return nil 93 } 94 95 // IsNilOrEmpty returns true if validator set is nil or empty. 96 func (vals *ValidatorSet) IsNilOrEmpty() bool { 97 return vals == nil || len(vals.Validators) == 0 98 } 99 100 // CopyIncrementProposerPriority increments ProposerPriority and updates the 101 // proposer on a copy, and returns it. 102 func (vals *ValidatorSet) CopyIncrementProposerPriority(times int32) *ValidatorSet { 103 copy := vals.Copy() 104 copy.IncrementProposerPriority(times) 105 return copy 106 } 107 108 // TODO The current random selection by VRF uses VotingPower, so the processing on ProposerPriority can be removed, 109 // TODO but it remains for later verification of random selection based on ProposerPriority. 110 // IncrementProposerPriority increments ProposerPriority of each validator and updates the 111 // proposer. Panics if validator set is empty. 112 // `times` must be positive. 113 func (vals *ValidatorSet) IncrementProposerPriority(times int32) { 114 if vals.IsNilOrEmpty() { 115 panic("empty validator set") 116 } 117 if times <= 0 { 118 panic("Cannot call IncrementProposerPriority with non-positive times") 119 } 120 121 // Cap the difference between priorities to be proportional to 2*totalPower by 122 // re-normalizing priorities, i.e., rescale all priorities by multiplying with: 123 // 2*totalVotingPower/(maxPriority - minPriority) 124 diffMax := PriorityWindowSizeFactor * vals.TotalVotingPower() 125 vals.RescalePriorities(diffMax) 126 vals.shiftByAvgProposerPriority() 127 128 // Call IncrementProposerPriority(1) times times. 129 for i := int32(0); i < times; i++ { 130 _ = vals.incrementProposerPriority() 131 } 132 } 133 134 // RescalePriorities rescales the priorities such that the distance between the maximum and minimum 135 // is smaller than `diffMax`. 136 func (vals *ValidatorSet) RescalePriorities(diffMax int64) { 137 if vals.IsNilOrEmpty() { 138 panic("empty validator set") 139 } 140 // NOTE: This check is merely a sanity check which could be 141 // removed if all tests would init. voting power appropriately; 142 // i.e. diffMax should always be > 0 143 if diffMax <= 0 { 144 return 145 } 146 147 // Calculating ceil(diff/diffMax): 148 // Re-normalization is performed by dividing by an integer for simplicity. 149 // NOTE: This may make debugging priority issues easier as well. 150 diff := computeMaxMinPriorityDiff(vals) 151 ratio := (diff + diffMax - 1) / diffMax 152 if diff > diffMax { 153 for _, val := range vals.Validators { 154 val.ProposerPriority /= ratio 155 } 156 } 157 } 158 159 func (vals *ValidatorSet) incrementProposerPriority() *Validator { 160 for _, val := range vals.Validators { 161 // Check for overflow for sum. 162 newPrio := safeAddClip(val.ProposerPriority, val.VotingPower) 163 val.ProposerPriority = newPrio 164 } 165 // Decrement the validator with most ProposerPriority. 166 mostest := vals.getValWithMostPriority() 167 // Mind the underflow. 168 mostest.ProposerPriority = safeSubClip(mostest.ProposerPriority, vals.TotalVotingPower()) 169 170 return mostest 171 } 172 173 // Should not be called on an empty validator set. 174 func (vals *ValidatorSet) computeAvgProposerPriority() int64 { 175 n := int64(len(vals.Validators)) 176 sum := big.NewInt(0) 177 for _, val := range vals.Validators { 178 sum.Add(sum, big.NewInt(val.ProposerPriority)) 179 } 180 avg := sum.Div(sum, big.NewInt(n)) 181 if avg.IsInt64() { 182 return avg.Int64() 183 } 184 185 // This should never happen: each val.ProposerPriority is in bounds of int64. 186 panic(fmt.Sprintf("Cannot represent avg ProposerPriority as an int64 %v", avg)) 187 } 188 189 // Compute the difference between the max and min ProposerPriority of that set. 190 func computeMaxMinPriorityDiff(vals *ValidatorSet) int64 { 191 if vals.IsNilOrEmpty() { 192 panic("empty validator set") 193 } 194 max := int64(math.MinInt64) 195 min := int64(math.MaxInt64) 196 for _, v := range vals.Validators { 197 if v.ProposerPriority < min { 198 min = v.ProposerPriority 199 } 200 if v.ProposerPriority > max { 201 max = v.ProposerPriority 202 } 203 } 204 diff := max - min 205 if diff < 0 { 206 return -1 * diff 207 } 208 return diff 209 } 210 211 func (vals *ValidatorSet) getValWithMostPriority() *Validator { 212 var res *Validator 213 for _, val := range vals.Validators { 214 res = res.CompareProposerPriority(val) 215 } 216 return res 217 } 218 219 func (vals *ValidatorSet) shiftByAvgProposerPriority() { 220 if vals.IsNilOrEmpty() { 221 panic("empty validator set") 222 } 223 avgProposerPriority := vals.computeAvgProposerPriority() 224 for _, val := range vals.Validators { 225 val.ProposerPriority = safeSubClip(val.ProposerPriority, avgProposerPriority) 226 } 227 } 228 229 // Makes a copy of the validator list. 230 func validatorListCopy(valsList []*Validator) []*Validator { 231 if valsList == nil { 232 return nil 233 } 234 valsCopy := make([]*Validator, len(valsList)) 235 for i, val := range valsList { 236 valsCopy[i] = val.Copy() 237 } 238 return valsCopy 239 } 240 241 // Copy each validator into a new ValidatorSet. 242 func (vals *ValidatorSet) Copy() *ValidatorSet { 243 return &ValidatorSet{ 244 Validators: validatorListCopy(vals.Validators), 245 totalVotingPower: vals.totalVotingPower, 246 } 247 } 248 249 // HasAddress returns true if address given is in the validator set, false - 250 // otherwise. 251 func (vals *ValidatorSet) HasAddress(address []byte) bool { 252 for _, val := range vals.Validators { 253 if bytes.Equal(val.Address, address) { 254 return true 255 } 256 } 257 return false 258 } 259 260 // GetByAddress returns an index of the validator with address and validator 261 // itself (copy) if found. Otherwise, -1 and nil are returned. 262 func (vals *ValidatorSet) GetByAddress(address []byte) (index int32, val *Validator) { 263 for idx, val := range vals.Validators { 264 if bytes.Equal(val.Address, address) { 265 return int32(idx), val.Copy() 266 } 267 } 268 return -1, nil 269 } 270 271 // GetByIndex returns the validator's address and validator itself (copy) by 272 // index. 273 // It returns nil values if index is less than 0 or greater or equal to 274 // len(ValidatorSet.Validators). 275 func (vals *ValidatorSet) GetByIndex(index int32) (address []byte, val *Validator) { 276 if index < 0 || int(index) >= len(vals.Validators) { 277 return nil, nil 278 } 279 val = vals.Validators[index] 280 return val.Address, val.Copy() 281 } 282 283 // Size returns the length of the validator set. 284 func (vals *ValidatorSet) Size() int { 285 return len(vals.Validators) 286 } 287 288 // Forces recalculation of the set's total voting power. 289 // Panics if total voting power is bigger than MaxTotalVotingPower. 290 func (vals *ValidatorSet) updateTotalVotingPower() { 291 sum := int64(0) 292 for _, val := range vals.Validators { 293 // mind overflow 294 sum = safeAddClip(sum, val.VotingPower) 295 if sum > MaxTotalVotingPower { 296 panic(fmt.Sprintf( 297 "Total voting power should be guarded to not exceed %v; got: %v", 298 MaxTotalVotingPower, 299 sum)) 300 } 301 } 302 303 vals.totalVotingPower = sum 304 } 305 306 // TotalVotingPower returns the sum of the voting powers of all validators. 307 // It recomputes the total voting power if required. 308 func (vals *ValidatorSet) TotalVotingPower() int64 { 309 if vals.totalVotingPower == 0 { 310 vals.updateTotalVotingPower() 311 } 312 return vals.totalVotingPower 313 } 314 315 // Hash returns the Merkle root hash build using validators (as leaves) in the 316 // set. 317 func (vals *ValidatorSet) Hash() []byte { 318 bzs := make([][]byte, len(vals.Validators)) 319 for i, val := range vals.Validators { 320 bzs[i] = val.Bytes() 321 } 322 return merkle.HashFromByteSlices(bzs) 323 } 324 325 // Iterate will run the given function over the set. 326 func (vals *ValidatorSet) Iterate(fn func(index int, val *Validator) bool) { 327 for i, val := range vals.Validators { 328 stop := fn(i, val.Copy()) 329 if stop { 330 break 331 } 332 } 333 } 334 335 // Checks changes against duplicates, splits the changes in updates and 336 // removals, sorts them by address. 337 // 338 // Returns: 339 // updates, removals - the sorted lists of updates and removals 340 // err - non-nil if duplicate entries or entries with negative voting power are seen 341 // 342 // No changes are made to 'origChanges'. 343 func processChanges(origChanges []*Validator) (updates, removals []*Validator, err error) { 344 // Make a deep copy of the changes and sort by address. 345 changes := validatorListCopy(origChanges) 346 sort.Sort(ValidatorsByAddress(changes)) 347 348 removals = make([]*Validator, 0, len(changes)) 349 updates = make([]*Validator, 0, len(changes)) 350 var prevAddr Address 351 352 // Scan changes by address and append valid validators to updates or removals lists. 353 for _, valUpdate := range changes { 354 if bytes.Equal(valUpdate.Address, prevAddr) { 355 err = fmt.Errorf("duplicate entry %v in %v", valUpdate, changes) 356 return nil, nil, err 357 } 358 359 switch { 360 case valUpdate.VotingPower < 0: 361 err = fmt.Errorf("voting power can't be negative: %d", valUpdate.VotingPower) 362 return nil, nil, err 363 case valUpdate.VotingPower > MaxTotalVotingPower: 364 err = fmt.Errorf("to prevent clipping/overflow, voting power can't be higher than %d, got %d", 365 MaxTotalVotingPower, valUpdate.VotingPower) 366 return nil, nil, err 367 case valUpdate.VotingPower == 0: 368 removals = append(removals, valUpdate) 369 default: 370 updates = append(updates, valUpdate) 371 } 372 373 prevAddr = valUpdate.Address 374 } 375 376 return updates, removals, err 377 } 378 379 // verifyUpdates verifies a list of updates against a validator set, making sure the allowed 380 // total voting power would not be exceeded if these updates would be applied to the set. 381 // 382 // Inputs: 383 // updates - a list of proper validator changes, i.e. they have been verified by processChanges for duplicates 384 // 385 // and invalid values. 386 // 387 // vals - the original validator set. Note that vals is NOT modified by this function. 388 // removedPower - the total voting power that will be removed after the updates are verified and applied. 389 // 390 // Returns: 391 // tvpAfterUpdatesBeforeRemovals - the new total voting power if these updates would be applied without the removals. 392 // 393 // Note that this will be < 2 * MaxTotalVotingPower in case high power validators are removed and 394 // validators are added/ updated with high power values. 395 // 396 // err - non-nil if the maximum allowed total voting power would be exceeded 397 func verifyUpdates( 398 updates []*Validator, 399 vals *ValidatorSet, 400 removedPower int64, 401 ) (tvpAfterUpdatesBeforeRemovals int64, err error) { 402 403 delta := func(update *Validator, vals *ValidatorSet) int64 { 404 _, val := vals.GetByAddress(update.Address) 405 if val != nil { 406 return update.VotingPower - val.VotingPower 407 } 408 return update.VotingPower 409 } 410 411 updatesCopy := validatorListCopy(updates) 412 sort.Slice(updatesCopy, func(i, j int) bool { 413 return delta(updatesCopy[i], vals) < delta(updatesCopy[j], vals) 414 }) 415 416 tvpAfterRemovals := vals.TotalVotingPower() - removedPower 417 for _, upd := range updatesCopy { 418 tvpAfterRemovals += delta(upd, vals) 419 if tvpAfterRemovals > MaxTotalVotingPower { 420 return 0, ErrTotalVotingPowerOverflow 421 } 422 } 423 return tvpAfterRemovals + removedPower, nil 424 } 425 426 func numNewValidators(updates []*Validator, vals *ValidatorSet) int { 427 numNewValidators := 0 428 for _, valUpdate := range updates { 429 if !vals.HasAddress(valUpdate.Address) { 430 numNewValidators++ 431 } 432 } 433 return numNewValidators 434 } 435 436 // computeNewPriorities computes the proposer priority for the validators not present in the set based on 437 // 'updatedTotalVotingPower'. 438 // Leaves unchanged the priorities of validators that are changed. 439 // 440 // 'updates' parameter must be a list of unique validators to be added or updated. 441 // 442 // 'updatedTotalVotingPower' is the total voting power of a set where all updates would be applied but 443 // 444 // not the removals. It must be < 2*MaxTotalVotingPower and may be close to this limit if close to 445 // MaxTotalVotingPower will be removed. This is still safe from overflow since MaxTotalVotingPower is maxInt64/8. 446 // 447 // No changes are made to the validator set 'vals'. 448 func computeNewPriorities(updates []*Validator, vals *ValidatorSet, updatedTotalVotingPower int64) { 449 for _, valUpdate := range updates { 450 address := valUpdate.Address 451 _, val := vals.GetByAddress(address) 452 if val == nil { 453 // add val 454 // Set ProposerPriority to -C*totalVotingPower (with C ~= 1.125) to make sure validators can't 455 // un-bond and then re-bond to reset their (potentially previously negative) ProposerPriority to zero. 456 // 457 // Contract: updatedVotingPower < 2 * MaxTotalVotingPower to ensure ProposerPriority does 458 // not exceed the bounds of int64. 459 // 460 // Compute ProposerPriority = -1.125*totalVotingPower == -(updatedVotingPower + (updatedVotingPower >> 3)). 461 valUpdate.ProposerPriority = -(updatedTotalVotingPower + (updatedTotalVotingPower >> 3)) 462 } else { 463 valUpdate.ProposerPriority = val.ProposerPriority 464 } 465 } 466 467 } 468 469 // Merges the vals' validator list with the updates list. 470 // When two elements with same address are seen, the one from updates is selected. 471 // Expects updates to be a list of updates sorted by address with no duplicates or errors, 472 // must have been validated with verifyUpdates() and priorities computed with computeNewPriorities(). 473 func (vals *ValidatorSet) applyUpdates(updates []*Validator) { 474 existing := vals.Validators 475 sort.Sort(ValidatorsByAddress(existing)) 476 477 merged := make([]*Validator, len(existing)+len(updates)) 478 i := 0 479 480 for len(existing) > 0 && len(updates) > 0 { 481 if bytes.Compare(existing[0].Address, updates[0].Address) < 0 { // unchanged validator 482 merged[i] = existing[0] 483 existing = existing[1:] 484 } else { 485 // Apply add or update. 486 merged[i] = updates[0] 487 if bytes.Equal(existing[0].Address, updates[0].Address) { 488 // Validator is present in both, advance existing. 489 existing = existing[1:] 490 } 491 updates = updates[1:] 492 } 493 i++ 494 } 495 496 // Add the elements which are left. 497 for j := 0; j < len(existing); j++ { 498 merged[i] = existing[j] 499 i++ 500 } 501 // OR add updates which are left. 502 for j := 0; j < len(updates); j++ { 503 merged[i] = updates[j] 504 i++ 505 } 506 507 vals.Validators = merged[:i] 508 } 509 510 // Checks that the validators to be removed are part of the validator set. 511 // No changes are made to the validator set 'vals'. 512 func verifyRemovals(deletes []*Validator, vals *ValidatorSet) (votingPower int64, err error) { 513 removedVotingPower := int64(0) 514 for _, valUpdate := range deletes { 515 address := valUpdate.Address 516 _, val := vals.GetByAddress(address) 517 if val == nil { 518 return removedVotingPower, fmt.Errorf("failed to find validator %X to remove", address) 519 } 520 removedVotingPower += val.VotingPower 521 } 522 if len(deletes) > len(vals.Validators) { 523 panic("more deletes than validators") 524 } 525 return removedVotingPower, nil 526 } 527 528 // Removes the validators specified in 'deletes' from validator set 'vals'. 529 // Should not fail as verification has been done before. 530 // Expects vals to be sorted by address (done by applyUpdates). 531 func (vals *ValidatorSet) applyRemovals(deletes []*Validator) { 532 existing := vals.Validators 533 534 merged := make([]*Validator, len(existing)-len(deletes)) 535 i := 0 536 537 // Loop over deletes until we removed all of them. 538 for len(deletes) > 0 { 539 if bytes.Equal(existing[0].Address, deletes[0].Address) { 540 deletes = deletes[1:] 541 } else { // Leave it in the resulting slice. 542 merged[i] = existing[0] 543 i++ 544 } 545 existing = existing[1:] 546 } 547 548 // Add the elements which are left. 549 for j := 0; j < len(existing); j++ { 550 merged[i] = existing[j] 551 i++ 552 } 553 554 vals.Validators = merged[:i] 555 } 556 557 // Main function used by UpdateWithChangeSet() and NewValidatorSet(). 558 // If 'allowDeletes' is false then delete operations (identified by validators with voting power 0) 559 // are not allowed and will trigger an error if present in 'changes'. 560 // The 'allowDeletes' flag is set to false by NewValidatorSet() and to true by UpdateWithChangeSet(). 561 func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes bool) error { 562 if len(changes) == 0 { 563 return nil 564 } 565 566 // Check for duplicates within changes, split in 'updates' and 'deletes' lists (sorted). 567 updates, deletes, err := processChanges(changes) 568 if err != nil { 569 return err 570 } 571 572 if !allowDeletes && len(deletes) != 0 { 573 return fmt.Errorf("cannot process validators with voting power 0: %v", deletes) 574 } 575 576 // Check that the resulting set will not be empty. 577 if numNewValidators(updates, vals) == 0 && len(vals.Validators) == len(deletes) { 578 return errors.New("applying the validator changes would result in empty set") 579 } 580 581 // Verify that applying the 'deletes' against 'vals' will not result in error. 582 // Get the voting power that is going to be removed. 583 removedVotingPower, err := verifyRemovals(deletes, vals) 584 if err != nil { 585 return err 586 } 587 588 // Verify that applying the 'updates' against 'vals' will not result in error. 589 // Get the updated total voting power before removal. Note that this is < 2 * MaxTotalVotingPower 590 tvpAfterUpdatesBeforeRemovals, err := verifyUpdates(updates, vals, removedVotingPower) 591 if err != nil { 592 return err 593 } 594 595 // Compute the priorities for updates. 596 computeNewPriorities(updates, vals, tvpAfterUpdatesBeforeRemovals) 597 598 // Apply updates and removals. 599 vals.applyUpdates(updates) 600 vals.applyRemovals(deletes) 601 602 vals.updateTotalVotingPower() // will panic if total voting power > MaxTotalVotingPower 603 604 // Scale and center. 605 vals.RescalePriorities(PriorityWindowSizeFactor * vals.TotalVotingPower()) 606 vals.shiftByAvgProposerPriority() 607 608 sort.Sort(ValidatorsByVotingPower(vals.Validators)) 609 610 return nil 611 } 612 613 // UpdateWithChangeSet attempts to update the validator set with 'changes'. 614 // It performs the following steps: 615 // - validates the changes making sure there are no duplicates and splits them in updates and deletes 616 // - verifies that applying the changes will not result in errors 617 // - computes the total voting power BEFORE removals to ensure that in the next steps the priorities 618 // across old and newly added validators are fair 619 // - computes the priorities of new validators against the final set 620 // - applies the updates against the validator set 621 // - applies the removals against the validator set 622 // - performs scaling and centering of priority values 623 // 624 // If an error is detected during verification steps, it is returned and the validator set 625 // is not changed. 626 func (vals *ValidatorSet) UpdateWithChangeSet(changes []*Validator) error { 627 return vals.updateWithChangeSet(changes, true) 628 } 629 630 // VerifyCommit verifies +2/3 of the set had signed the given commit. 631 // 632 // It checks all the signatures! While it's safe to exit as soon as we have 633 // 2/3+ signatures, doing so would impact incentivization logic in the ABCI 634 // application that depends on the LastCommitInfo sent in BeginBlock, which 635 // includes which validators signed. For instance, Gaia incentivizes proposers 636 // with a bonus for including more than +2/3 of the signatures. 637 func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, 638 height int64, commit *Commit) error { 639 640 if vals == nil || commit == nil { 641 return fmt.Errorf("invalid nil vals or commit:[%v] or [%v]", vals, commit) 642 } 643 644 if vals.Size() != len(commit.Signatures) { 645 return NewErrInvalidCommitSignatures(vals.Size(), len(commit.Signatures)) 646 } 647 648 // Validate Height and BlockID. 649 if height != commit.Height { 650 return NewErrInvalidCommitHeight(height, commit.Height) 651 } 652 if !blockID.Equals(commit.BlockID) { 653 return fmt.Errorf("invalid commit -- wrong block ID: want %v, got %v", 654 blockID, commit.BlockID) 655 } 656 657 talliedVotingPower := int64(0) 658 votingPowerNeeded := vals.TotalVotingPower() * 2 / 3 // FIXME: 🏺 arithmetic overflow 659 for idx, commitSig := range commit.Signatures { 660 if commitSig.Absent() { 661 continue // OK, some signatures can be absent. 662 } 663 664 // The vals and commit have a 1-to-1 correspondance. 665 // This means we don't need the validator address or to do any lookup. 666 val := vals.Validators[idx] 667 668 // Validate signature. 669 voteSignBytes := commit.VoteSignBytes(chainID, int32(idx)) 670 if !val.PubKey.VerifySignature(voteSignBytes, commitSig.Signature) { 671 return fmt.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature) 672 } 673 // Good! 674 if commitSig.ForBlock() { 675 talliedVotingPower += val.VotingPower 676 } 677 // else { 678 // It's OK. We include stray signatures (~votes for nil) to measure 679 // validator availability. 680 // } 681 } 682 683 if got, needed := talliedVotingPower, votingPowerNeeded; got <= needed { 684 return ErrNotEnoughVotingPowerSigned{Got: got, Needed: needed} 685 } 686 687 return nil 688 } 689 690 // LIGHT CLIENT VERIFICATION METHODS 691 692 // VerifyCommitLight verifies +2/3 of the set had signed the given commit. 693 // 694 // This method is primarily used by the light client and does not check all the 695 // signatures. 696 func (vals *ValidatorSet) VerifyCommitLight(chainID string, blockID BlockID, 697 height int64, commit *Commit) error { 698 699 if vals == nil || commit == nil { 700 return fmt.Errorf("invalid nil vals or commit:[%v] or [%v]", vals, commit) 701 } 702 703 if vals.Size() != len(commit.Signatures) { 704 return NewErrInvalidCommitSignatures(vals.Size(), len(commit.Signatures)) 705 } 706 707 // Validate Height and BlockID. 708 if height != commit.Height { 709 return NewErrInvalidCommitHeight(height, commit.Height) 710 } 711 if !blockID.Equals(commit.BlockID) { 712 return fmt.Errorf("invalid commit -- wrong block ID: want %v, got %v", 713 blockID, commit.BlockID) 714 } 715 716 talliedVotingPower := int64(0) 717 votingPowerNeeded := vals.TotalVotingPower() * 2 / 3 // FIXME: 🏺 arithmetic overflow 718 for idx, commitSig := range commit.Signatures { 719 // No need to verify absent or nil votes. 720 if !commitSig.ForBlock() { 721 continue 722 } 723 724 // The vals and commit have a 1-to-1 correspondance. 725 // This means we don't need the validator address or to do any lookup. 726 val := vals.Validators[idx] 727 728 // Validate signature. 729 voteSignBytes := commit.VoteSignBytes(chainID, int32(idx)) 730 if !val.PubKey.VerifySignature(voteSignBytes, commitSig.Signature) { 731 return fmt.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature) 732 } 733 734 talliedVotingPower += val.VotingPower 735 736 // return as soon as +2/3 of the signatures are verified 737 if talliedVotingPower > votingPowerNeeded { 738 return nil 739 } 740 } 741 742 return ErrNotEnoughVotingPowerSigned{Got: talliedVotingPower, Needed: votingPowerNeeded} 743 } 744 745 // VerifyCommitLightTrusting verifies that trustLevel of the validator set signed 746 // this commit. 747 // 748 // NOTE the given validators do not necessarily correspond to the validator set 749 // for this commit, but there may be some intersection. 750 // 751 // This method is primarily used by the light client and does not check all the 752 // signatures. 753 func (vals *ValidatorSet) VerifyCommitLightTrusting(chainID string, commit *Commit, trustLevel tmmath.Fraction) error { 754 // sanity check 755 if trustLevel.Denominator == 0 { 756 return errors.New("trustLevel has zero Denominator") 757 } 758 759 var ( 760 talliedVotingPower int64 761 seenVals = make(map[int32]int, len(commit.Signatures)) // validator index -> commit index 762 ) 763 764 // Safely calculate voting power needed. 765 totalVotingPowerMulByNumerator, overflow := safeMul(vals.TotalVotingPower(), int64(trustLevel.Numerator)) 766 if overflow { 767 return errors.New("int64 overflow while calculating voting power needed. " + "please provide smaller trustLevel numerator") 768 } 769 votingPowerNeeded := totalVotingPowerMulByNumerator / int64(trustLevel.Denominator) 770 771 for idx, commitSig := range commit.Signatures { 772 // No need to verify absent or nil votes. 773 if !commitSig.ForBlock() { 774 continue 775 } 776 777 // We don't know the validators that committed this block, so we have to 778 // check for each vote if its validator is already known. 779 valIdx, val := vals.GetByAddress(commitSig.ValidatorAddress) 780 781 if val != nil { 782 // check for double vote of validator on the same commit 783 if firstIndex, ok := seenVals[valIdx]; ok { 784 secondIndex := idx 785 return fmt.Errorf("double vote from %v (%d and %d)", val, firstIndex, secondIndex) 786 } 787 seenVals[valIdx] = idx 788 789 // Verify Signature 790 voteSignBytes := commit.VoteSignBytes(chainID, int32(idx)) 791 if !val.PubKey.VerifySignature(voteSignBytes, commitSig.Signature) { 792 return fmt.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature) 793 } 794 795 talliedVotingPower += val.VotingPower 796 797 if talliedVotingPower > votingPowerNeeded { 798 return nil 799 } 800 } 801 } 802 803 return ErrNotEnoughVotingPowerSigned{Got: talliedVotingPower, Needed: votingPowerNeeded} 804 } 805 806 func (vals *ValidatorSet) SelectProposer(proofHash []byte, height int64, round int32) *Validator { 807 if vals.IsNilOrEmpty() { 808 panic("empty validator set") 809 } 810 seed := hashToSeed(MakeRoundHash(proofHash, height, round)) 811 random := nextRandom(&seed) 812 totalVotingPower := vals.TotalVotingPower() 813 thresholdVotingPower := dividePoint(random, totalVotingPower) 814 threshold := thresholdVotingPower 815 for _, val := range vals.Validators { 816 if threshold < uint64(val.VotingPower) { 817 return val 818 } 819 threshold -= uint64(val.VotingPower) 820 } 821 822 // This code will never be reached except in the following circumstances: 823 // 1) The totalVotingPower is not equal to the actual total VotingPower. 824 // 2) The length of vals.Validators is zero (but checked above). 825 // Both are due to unexpected state irregularities and can be identified by the output error message. 826 panic(fmt.Sprintf("Cannot select samples; r=%d, thresholdVotingPower=%d, totalVotingPower=%d: %+v", 827 random, thresholdVotingPower, totalVotingPower, vals)) 828 } 829 830 var divider *big.Int 831 832 func init() { 833 divider = new(big.Int).SetUint64(math.MaxInt64) 834 divider.Add(divider, big.NewInt(1)) 835 } 836 837 // dividePoint computes and returns the value in the [0, y) range when x≠0. 838 // Otherwise returns 0. 839 func dividePoint(x uint64, y int64) uint64 { 840 totalBig := big.NewInt(y) 841 a := new(big.Int).SetUint64(x & math.MaxInt64) 842 a.Mul(a, totalBig) 843 a.Div(a, divider) 844 return a.Uint64() 845 } 846 847 // nextRandom implements SplitMix64 (based on http://xoshiro.di.unimi.it/splitmix64.c) 848 // 849 // The PRNG used for this random selection: 850 // 1. must be deterministic. 851 // 2. should easily portable, independent of language or library 852 // 3. is not necessary to keep a long period like MT, since there aren't many random numbers to generate and 853 // we expect a certain amount of randomness in the seed. 854 // 855 // The shift-register type pRNG fits these requirements well, but there are too many variants. So we adopted SplitMix64, 856 // which is used in Java's SplittableStream. 857 // https://github.com/openjdk/jdk/blob/jdk-17+35/src/java.base/share/classes/java/util/SplittableRandom.java#L193-L197 858 func nextRandom(rand *uint64) uint64 { 859 *rand += uint64(0x9e3779b97f4a7c15) 860 var z = *rand 861 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9 862 z = (z ^ (z >> 27)) * 0x94d049bb133111eb 863 return z ^ (z >> 31) 864 } 865 866 //----------------- 867 868 // ErrNotEnoughVotingPowerSigned is returned when not enough validators signed 869 // a commit. 870 type ErrNotEnoughVotingPowerSigned struct { 871 Got int64 872 Needed int64 873 } 874 875 func (e ErrNotEnoughVotingPowerSigned) Error() string { 876 return fmt.Sprintf("invalid commit -- insufficient voting power: got %d, needed more than %d", e.Got, e.Needed) 877 } 878 879 //---------------- 880 881 // String returns a string representation of ValidatorSet. 882 // 883 // See StringIndented. 884 func (vals *ValidatorSet) String() string { 885 return vals.StringIndented("") 886 } 887 888 // StringIndented returns an intended String. 889 // 890 // See Validator#String. 891 func (vals *ValidatorSet) StringIndented(indent string) string { 892 if vals == nil { 893 return "nil-ValidatorSet" 894 } 895 var valStrings []string 896 vals.Iterate(func(index int, val *Validator) bool { 897 valStrings = append(valStrings, val.String()) 898 return false 899 }) 900 return fmt.Sprintf(`ValidatorSet{ 901 %s Validators: 902 %s %v 903 %s}`, 904 indent, indent, strings.Join(valStrings, "\n"+indent+" "), 905 indent) 906 907 } 908 909 //------------------------------------- 910 911 // ValidatorsByVotingPower implements sort.Interface for []*Validator based on 912 // the VotingPower and Address fields. 913 type ValidatorsByVotingPower []*Validator 914 915 func (valz ValidatorsByVotingPower) Len() int { return len(valz) } 916 917 func (valz ValidatorsByVotingPower) Less(i, j int) bool { 918 if valz[i].VotingPower == valz[j].VotingPower { 919 return bytes.Compare(valz[i].Address, valz[j].Address) == -1 920 } 921 return valz[i].VotingPower > valz[j].VotingPower 922 } 923 924 func (valz ValidatorsByVotingPower) Swap(i, j int) { 925 valz[i], valz[j] = valz[j], valz[i] 926 } 927 928 // ValidatorsByAddress implements sort.Interface for []*Validator based on 929 // the Address field. 930 type ValidatorsByAddress []*Validator 931 932 func (valz ValidatorsByAddress) Len() int { return len(valz) } 933 934 func (valz ValidatorsByAddress) Less(i, j int) bool { 935 return bytes.Compare(valz[i].Address, valz[j].Address) == -1 936 } 937 938 func (valz ValidatorsByAddress) Swap(i, j int) { 939 valz[i], valz[j] = valz[j], valz[i] 940 } 941 942 // ToProto converts ValidatorSet to protobuf 943 func (vals *ValidatorSet) ToProto() (*tmproto.ValidatorSet, error) { 944 if vals.IsNilOrEmpty() { 945 return &tmproto.ValidatorSet{}, nil // validator set should never be nil 946 } 947 948 vp := new(tmproto.ValidatorSet) 949 valsProto := make([]*tmproto.Validator, len(vals.Validators)) 950 for i := 0; i < len(vals.Validators); i++ { 951 valp, err := vals.Validators[i].ToProto() 952 if err != nil { 953 return nil, err 954 } 955 valsProto[i] = valp 956 } 957 vp.Validators = valsProto 958 959 vp.TotalVotingPower = vals.totalVotingPower 960 961 return vp, nil 962 } 963 964 // ValidatorSetFromProto sets a protobuf ValidatorSet to the given pointer. 965 // It returns an error if any of the validators from the set or the proposer 966 // is invalid 967 func ValidatorSetFromProto(vp *tmproto.ValidatorSet) (*ValidatorSet, error) { 968 if vp == nil { 969 return nil, errors.New("nil validator set") // validator set should never be nil, bigger issues are at play if empty 970 } 971 vals := new(ValidatorSet) 972 973 valsProto := make([]*Validator, len(vp.Validators)) 974 for i := 0; i < len(vp.Validators); i++ { 975 v, err := ValidatorFromProto(vp.Validators[i]) 976 if err != nil { 977 return nil, err 978 } 979 valsProto[i] = v 980 } 981 vals.Validators = valsProto 982 983 vals.totalVotingPower = vp.GetTotalVotingPower() 984 985 return vals, vals.ValidateBasic() 986 } 987 988 // ValidatorSetFromExistingValidators takes an existing array of validators and 989 // rebuilds the exact same validator set that corresponds to it without 990 // changing the proposer priority or power if any of the validators fail 991 // validate basic then an empty set is returned. 992 func ValidatorSetFromExistingValidators(valz []*Validator) (*ValidatorSet, error) { 993 if len(valz) == 0 { 994 return nil, errors.New("validator set is empty") 995 } 996 for _, val := range valz { 997 err := val.ValidateBasic() 998 if err != nil { 999 return nil, fmt.Errorf("can't create validator set: %w", err) 1000 } 1001 } 1002 1003 vals := &ValidatorSet{ 1004 Validators: valz, 1005 } 1006 vals.updateTotalVotingPower() 1007 sort.Sort(ValidatorsByVotingPower(vals.Validators)) 1008 return vals, nil 1009 } 1010 1011 //---------------------------------------- 1012 1013 // RandValidatorSet returns a randomized validator set (size: +numValidators+), 1014 // where each validator has a voting power of +votingPower+. 1015 // 1016 // EXPOSED FOR TESTING. 1017 func RandValidatorSet(numValidators int, votingPower int64) (*ValidatorSet, []PrivValidator) { 1018 var ( 1019 valz = make([]*Validator, numValidators) 1020 privValidators = make([]PrivValidator, numValidators) 1021 ) 1022 1023 for i := 0; i < numValidators; i++ { 1024 val, privValidator := RandValidator(false, votingPower) 1025 valz[i] = val 1026 privValidators[i] = privValidator 1027 } 1028 1029 vals := NewValidatorSet(valz) 1030 sort.Sort(PrivValidatorsByAddress(privValidators)) 1031 1032 return vals, privValidators 1033 } 1034 1035 // safe addition/subtraction/multiplication 1036 1037 func safeAdd(a, b int64) (int64, bool) { 1038 if b > 0 && a > math.MaxInt64-b { 1039 return -1, true 1040 } else if b < 0 && a < math.MinInt64-b { 1041 return -1, true 1042 } 1043 return a + b, false 1044 } 1045 1046 func safeSub(a, b int64) (int64, bool) { 1047 if b > 0 && a < math.MinInt64+b { 1048 return -1, true 1049 } else if b < 0 && a > math.MaxInt64+b { 1050 return -1, true 1051 } 1052 return a - b, false 1053 } 1054 1055 func safeAddClip(a, b int64) int64 { 1056 c, overflow := safeAdd(a, b) 1057 if overflow { 1058 if b < 0 { 1059 return math.MinInt64 1060 } 1061 return math.MaxInt64 1062 } 1063 return c 1064 } 1065 1066 func safeSubClip(a, b int64) int64 { 1067 c, overflow := safeSub(a, b) 1068 if overflow { 1069 if b > 0 { 1070 return math.MinInt64 1071 } 1072 return math.MaxInt64 1073 } 1074 return c 1075 } 1076 1077 func safeMul(a, b int64) (int64, bool) { 1078 if a == 0 || b == 0 { 1079 return 0, false 1080 } 1081 1082 absOfB := b 1083 if b < 0 { 1084 absOfB = -b 1085 } 1086 1087 absOfA := a 1088 if a < 0 { 1089 absOfA = -a 1090 } 1091 1092 if absOfA > math.MaxInt64/absOfB { 1093 return 0, true 1094 } 1095 1096 return a * b, false 1097 } 1098 1099 //---------------------------------------- 1100 1101 func hashToSeed(hash []byte) uint64 { 1102 for len(hash) < 8 { 1103 hash = append(hash, byte(0)) 1104 } 1105 return binary.LittleEndian.Uint64(hash[:8]) 1106 } 1107 1108 // MakeRoundHash combines the VRF hash, block height, and round to create a hash value for each round. This value is 1109 // used for random sampling of the Proposer. 1110 func MakeRoundHash(proofHash []byte, height int64, round int32) []byte { 1111 b := make([]byte, 16) 1112 binary.LittleEndian.PutUint64(b, uint64(height)) 1113 binary.LittleEndian.PutUint64(b[8:], uint64(round)) 1114 hash := tmhash.New() 1115 if _, err := hash.Write(proofHash); err != nil { 1116 panic(err) 1117 } 1118 if _, err := hash.Write(b[:8]); err != nil { 1119 panic(err) 1120 } 1121 if _, err := hash.Write(b[8:16]); err != nil { 1122 panic(err) 1123 } 1124 return hash.Sum(nil) 1125 }