You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

601 lines
18 KiB

Normalize priorities to not exceed total voting power (#3049) * more proposer priority tests - test that we don't reset to zero when updating / adding - test that same power validators alternate * add another test to track / simulate similar behaviour as in #2960 * address some of Chris' review comments * address some more of Chris' review comments * temporarily pushing branch with the following changes: The total power might change if: - a validator is added - a validator is removed - a validator is updated Decrement the accums (of all validators) directly after any of these events (by the inverse of the change) * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * fix tests * add comment * update changelog pending & some minor changes * comment about division will floor the result & fix typo * Update TestLargeGenesisValidator: - remove TODO and increase large genesis validator's voting power accordingly * move changelog entry to P2P Protocol * Ceil instead of flooring when dividing & update test * quickly fix failing TestProposerPriorityDoesNotGetResetToZero: - divide by Ceil((maxPriority - minPriority) / 2*totalVotingPower) * fix typo: rename getValWitMostPriority -> getValWithMostPriority * test proposer frequencies * return absolute value for diff. keep testing * use for loop for div * cleanup, more tests * spellcheck * get rid of using floats: manually ceil where necessary * Remove float, simplify, fix tests to match chris's proof (#3157)
6 years ago
Normalize priorities to not exceed total voting power (#3049) * more proposer priority tests - test that we don't reset to zero when updating / adding - test that same power validators alternate * add another test to track / simulate similar behaviour as in #2960 * address some of Chris' review comments * address some more of Chris' review comments * temporarily pushing branch with the following changes: The total power might change if: - a validator is added - a validator is removed - a validator is updated Decrement the accums (of all validators) directly after any of these events (by the inverse of the change) * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * fix tests * add comment * update changelog pending & some minor changes * comment about division will floor the result & fix typo * Update TestLargeGenesisValidator: - remove TODO and increase large genesis validator's voting power accordingly * move changelog entry to P2P Protocol * Ceil instead of flooring when dividing & update test * quickly fix failing TestProposerPriorityDoesNotGetResetToZero: - divide by Ceil((maxPriority - minPriority) / 2*totalVotingPower) * fix typo: rename getValWitMostPriority -> getValWithMostPriority * test proposer frequencies * return absolute value for diff. keep testing * use for loop for div * cleanup, more tests * spellcheck * get rid of using floats: manually ceil where necessary * Remove float, simplify, fix tests to match chris's proof (#3157)
6 years ago
Normalize priorities to not exceed total voting power (#3049) * more proposer priority tests - test that we don't reset to zero when updating / adding - test that same power validators alternate * add another test to track / simulate similar behaviour as in #2960 * address some of Chris' review comments * address some more of Chris' review comments * temporarily pushing branch with the following changes: The total power might change if: - a validator is added - a validator is removed - a validator is updated Decrement the accums (of all validators) directly after any of these events (by the inverse of the change) * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * fix tests * add comment * update changelog pending & some minor changes * comment about division will floor the result & fix typo * Update TestLargeGenesisValidator: - remove TODO and increase large genesis validator's voting power accordingly * move changelog entry to P2P Protocol * Ceil instead of flooring when dividing & update test * quickly fix failing TestProposerPriorityDoesNotGetResetToZero: - divide by Ceil((maxPriority - minPriority) / 2*totalVotingPower) * fix typo: rename getValWitMostPriority -> getValWithMostPriority * test proposer frequencies * return absolute value for diff. keep testing * use for loop for div * cleanup, more tests * spellcheck * get rid of using floats: manually ceil where necessary * Remove float, simplify, fix tests to match chris's proof (#3157)
6 years ago
Normalize priorities to not exceed total voting power (#3049) * more proposer priority tests - test that we don't reset to zero when updating / adding - test that same power validators alternate * add another test to track / simulate similar behaviour as in #2960 * address some of Chris' review comments * address some more of Chris' review comments * temporarily pushing branch with the following changes: The total power might change if: - a validator is added - a validator is removed - a validator is updated Decrement the accums (of all validators) directly after any of these events (by the inverse of the change) * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * fix tests * add comment * update changelog pending & some minor changes * comment about division will floor the result & fix typo * Update TestLargeGenesisValidator: - remove TODO and increase large genesis validator's voting power accordingly * move changelog entry to P2P Protocol * Ceil instead of flooring when dividing & update test * quickly fix failing TestProposerPriorityDoesNotGetResetToZero: - divide by Ceil((maxPriority - minPriority) / 2*totalVotingPower) * fix typo: rename getValWitMostPriority -> getValWithMostPriority * test proposer frequencies * return absolute value for diff. keep testing * use for loop for div * cleanup, more tests * spellcheck * get rid of using floats: manually ceil where necessary * Remove float, simplify, fix tests to match chris's proof (#3157)
6 years ago
Normalize priorities to not exceed total voting power (#3049) * more proposer priority tests - test that we don't reset to zero when updating / adding - test that same power validators alternate * add another test to track / simulate similar behaviour as in #2960 * address some of Chris' review comments * address some more of Chris' review comments * temporarily pushing branch with the following changes: The total power might change if: - a validator is added - a validator is removed - a validator is updated Decrement the accums (of all validators) directly after any of these events (by the inverse of the change) * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * fix tests * add comment * update changelog pending & some minor changes * comment about division will floor the result & fix typo * Update TestLargeGenesisValidator: - remove TODO and increase large genesis validator's voting power accordingly * move changelog entry to P2P Protocol * Ceil instead of flooring when dividing & update test * quickly fix failing TestProposerPriorityDoesNotGetResetToZero: - divide by Ceil((maxPriority - minPriority) / 2*totalVotingPower) * fix typo: rename getValWitMostPriority -> getValWithMostPriority * test proposer frequencies * return absolute value for diff. keep testing * use for loop for div * cleanup, more tests * spellcheck * get rid of using floats: manually ceil where necessary * Remove float, simplify, fix tests to match chris's proof (#3157)
6 years ago
Normalize priorities to not exceed total voting power (#3049) * more proposer priority tests - test that we don't reset to zero when updating / adding - test that same power validators alternate * add another test to track / simulate similar behaviour as in #2960 * address some of Chris' review comments * address some more of Chris' review comments * temporarily pushing branch with the following changes: The total power might change if: - a validator is added - a validator is removed - a validator is updated Decrement the accums (of all validators) directly after any of these events (by the inverse of the change) * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * fix tests * add comment * update changelog pending & some minor changes * comment about division will floor the result & fix typo * Update TestLargeGenesisValidator: - remove TODO and increase large genesis validator's voting power accordingly * move changelog entry to P2P Protocol * Ceil instead of flooring when dividing & update test * quickly fix failing TestProposerPriorityDoesNotGetResetToZero: - divide by Ceil((maxPriority - minPriority) / 2*totalVotingPower) * fix typo: rename getValWitMostPriority -> getValWithMostPriority * test proposer frequencies * return absolute value for diff. keep testing * use for loop for div * cleanup, more tests * spellcheck * get rid of using floats: manually ceil where necessary * Remove float, simplify, fix tests to match chris's proof (#3157)
6 years ago
Normalize priorities to not exceed total voting power (#3049) * more proposer priority tests - test that we don't reset to zero when updating / adding - test that same power validators alternate * add another test to track / simulate similar behaviour as in #2960 * address some of Chris' review comments * address some more of Chris' review comments * temporarily pushing branch with the following changes: The total power might change if: - a validator is added - a validator is removed - a validator is updated Decrement the accums (of all validators) directly after any of these events (by the inverse of the change) * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * fix tests * add comment * update changelog pending & some minor changes * comment about division will floor the result & fix typo * Update TestLargeGenesisValidator: - remove TODO and increase large genesis validator's voting power accordingly * move changelog entry to P2P Protocol * Ceil instead of flooring when dividing & update test * quickly fix failing TestProposerPriorityDoesNotGetResetToZero: - divide by Ceil((maxPriority - minPriority) / 2*totalVotingPower) * fix typo: rename getValWitMostPriority -> getValWithMostPriority * test proposer frequencies * return absolute value for diff. keep testing * use for loop for div * cleanup, more tests * spellcheck * get rid of using floats: manually ceil where necessary * Remove float, simplify, fix tests to match chris's proof (#3157)
6 years ago
Normalize priorities to not exceed total voting power (#3049) * more proposer priority tests - test that we don't reset to zero when updating / adding - test that same power validators alternate * add another test to track / simulate similar behaviour as in #2960 * address some of Chris' review comments * address some more of Chris' review comments * temporarily pushing branch with the following changes: The total power might change if: - a validator is added - a validator is removed - a validator is updated Decrement the accums (of all validators) directly after any of these events (by the inverse of the change) * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * fix tests * add comment * update changelog pending & some minor changes * comment about division will floor the result & fix typo * Update TestLargeGenesisValidator: - remove TODO and increase large genesis validator's voting power accordingly * move changelog entry to P2P Protocol * Ceil instead of flooring when dividing & update test * quickly fix failing TestProposerPriorityDoesNotGetResetToZero: - divide by Ceil((maxPriority - minPriority) / 2*totalVotingPower) * fix typo: rename getValWitMostPriority -> getValWithMostPriority * test proposer frequencies * return absolute value for diff. keep testing * use for loop for div * cleanup, more tests * spellcheck * get rid of using floats: manually ceil where necessary * Remove float, simplify, fix tests to match chris's proof (#3157)
6 years ago
Normalize priorities to not exceed total voting power (#3049) * more proposer priority tests - test that we don't reset to zero when updating / adding - test that same power validators alternate * add another test to track / simulate similar behaviour as in #2960 * address some of Chris' review comments * address some more of Chris' review comments * temporarily pushing branch with the following changes: The total power might change if: - a validator is added - a validator is removed - a validator is updated Decrement the accums (of all validators) directly after any of these events (by the inverse of the change) * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * fix tests * add comment * update changelog pending & some minor changes * comment about division will floor the result & fix typo * Update TestLargeGenesisValidator: - remove TODO and increase large genesis validator's voting power accordingly * move changelog entry to P2P Protocol * Ceil instead of flooring when dividing & update test * quickly fix failing TestProposerPriorityDoesNotGetResetToZero: - divide by Ceil((maxPriority - minPriority) / 2*totalVotingPower) * fix typo: rename getValWitMostPriority -> getValWithMostPriority * test proposer frequencies * return absolute value for diff. keep testing * use for loop for div * cleanup, more tests * spellcheck * get rid of using floats: manually ceil where necessary * Remove float, simplify, fix tests to match chris's proof (#3157)
6 years ago
Normalize priorities to not exceed total voting power (#3049) * more proposer priority tests - test that we don't reset to zero when updating / adding - test that same power validators alternate * add another test to track / simulate similar behaviour as in #2960 * address some of Chris' review comments * address some more of Chris' review comments * temporarily pushing branch with the following changes: The total power might change if: - a validator is added - a validator is removed - a validator is updated Decrement the accums (of all validators) directly after any of these events (by the inverse of the change) * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * fix tests * add comment * update changelog pending & some minor changes * comment about division will floor the result & fix typo * Update TestLargeGenesisValidator: - remove TODO and increase large genesis validator's voting power accordingly * move changelog entry to P2P Protocol * Ceil instead of flooring when dividing & update test * quickly fix failing TestProposerPriorityDoesNotGetResetToZero: - divide by Ceil((maxPriority - minPriority) / 2*totalVotingPower) * fix typo: rename getValWitMostPriority -> getValWithMostPriority * test proposer frequencies * return absolute value for diff. keep testing * use for loop for div * cleanup, more tests * spellcheck * get rid of using floats: manually ceil where necessary * Remove float, simplify, fix tests to match chris's proof (#3157)
6 years ago
Normalize priorities to not exceed total voting power (#3049) * more proposer priority tests - test that we don't reset to zero when updating / adding - test that same power validators alternate * add another test to track / simulate similar behaviour as in #2960 * address some of Chris' review comments * address some more of Chris' review comments * temporarily pushing branch with the following changes: The total power might change if: - a validator is added - a validator is removed - a validator is updated Decrement the accums (of all validators) directly after any of these events (by the inverse of the change) * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * fix tests * add comment * update changelog pending & some minor changes * comment about division will floor the result & fix typo * Update TestLargeGenesisValidator: - remove TODO and increase large genesis validator's voting power accordingly * move changelog entry to P2P Protocol * Ceil instead of flooring when dividing & update test * quickly fix failing TestProposerPriorityDoesNotGetResetToZero: - divide by Ceil((maxPriority - minPriority) / 2*totalVotingPower) * fix typo: rename getValWitMostPriority -> getValWithMostPriority * test proposer frequencies * return absolute value for diff. keep testing * use for loop for div * cleanup, more tests * spellcheck * get rid of using floats: manually ceil where necessary * Remove float, simplify, fix tests to match chris's proof (#3157)
6 years ago
Normalize priorities to not exceed total voting power (#3049) * more proposer priority tests - test that we don't reset to zero when updating / adding - test that same power validators alternate * add another test to track / simulate similar behaviour as in #2960 * address some of Chris' review comments * address some more of Chris' review comments * temporarily pushing branch with the following changes: The total power might change if: - a validator is added - a validator is removed - a validator is updated Decrement the accums (of all validators) directly after any of these events (by the inverse of the change) * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * fix tests * add comment * update changelog pending & some minor changes * comment about division will floor the result & fix typo * Update TestLargeGenesisValidator: - remove TODO and increase large genesis validator's voting power accordingly * move changelog entry to P2P Protocol * Ceil instead of flooring when dividing & update test * quickly fix failing TestProposerPriorityDoesNotGetResetToZero: - divide by Ceil((maxPriority - minPriority) / 2*totalVotingPower) * fix typo: rename getValWitMostPriority -> getValWithMostPriority * test proposer frequencies * return absolute value for diff. keep testing * use for loop for div * cleanup, more tests * spellcheck * get rid of using floats: manually ceil where necessary * Remove float, simplify, fix tests to match chris's proof (#3157)
6 years ago
Normalize priorities to not exceed total voting power (#3049) * more proposer priority tests - test that we don't reset to zero when updating / adding - test that same power validators alternate * add another test to track / simulate similar behaviour as in #2960 * address some of Chris' review comments * address some more of Chris' review comments * temporarily pushing branch with the following changes: The total power might change if: - a validator is added - a validator is removed - a validator is updated Decrement the accums (of all validators) directly after any of these events (by the inverse of the change) * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * Fix 2960 by re-normalizing / scaling priorities to be in bounds of total power, additionally: - remove heap where it doesn't make sense - avg. only at the end of IncrementProposerPriority instead of each iteration - update (and slightly improve) TestAveragingInIncrementProposerPriorityWithVotingPower to reflect above changes * fix tests * add comment * update changelog pending & some minor changes * comment about division will floor the result & fix typo * Update TestLargeGenesisValidator: - remove TODO and increase large genesis validator's voting power accordingly * move changelog entry to P2P Protocol * Ceil instead of flooring when dividing & update test * quickly fix failing TestProposerPriorityDoesNotGetResetToZero: - divide by Ceil((maxPriority - minPriority) / 2*totalVotingPower) * fix typo: rename getValWitMostPriority -> getValWithMostPriority * test proposer frequencies * return absolute value for diff. keep testing * use for loop for div * cleanup, more tests * spellcheck * get rid of using floats: manually ceil where necessary * Remove float, simplify, fix tests to match chris's proof (#3157)
6 years ago
  1. package types
  2. import (
  3. "bytes"
  4. "fmt"
  5. "math"
  6. "strings"
  7. "testing"
  8. "testing/quick"
  9. "github.com/stretchr/testify/assert"
  10. "github.com/tendermint/tendermint/crypto"
  11. "github.com/tendermint/tendermint/crypto/ed25519"
  12. cmn "github.com/tendermint/tendermint/libs/common"
  13. tmtime "github.com/tendermint/tendermint/types/time"
  14. )
  15. func TestValidatorSetBasic(t *testing.T) {
  16. // empty or nil validator lists are allowed,
  17. // but attempting to IncrementProposerPriority on them will panic.
  18. vset := NewValidatorSet([]*Validator{})
  19. assert.Panics(t, func() { vset.IncrementProposerPriority(1) })
  20. vset = NewValidatorSet(nil)
  21. assert.Panics(t, func() { vset.IncrementProposerPriority(1) })
  22. assert.EqualValues(t, vset, vset.Copy())
  23. assert.False(t, vset.HasAddress([]byte("some val")))
  24. idx, val := vset.GetByAddress([]byte("some val"))
  25. assert.Equal(t, -1, idx)
  26. assert.Nil(t, val)
  27. addr, val := vset.GetByIndex(-100)
  28. assert.Nil(t, addr)
  29. assert.Nil(t, val)
  30. addr, val = vset.GetByIndex(0)
  31. assert.Nil(t, addr)
  32. assert.Nil(t, val)
  33. addr, val = vset.GetByIndex(100)
  34. assert.Nil(t, addr)
  35. assert.Nil(t, val)
  36. assert.Zero(t, vset.Size())
  37. assert.Equal(t, int64(0), vset.TotalVotingPower())
  38. assert.Nil(t, vset.GetProposer())
  39. assert.Nil(t, vset.Hash())
  40. // add
  41. val = randValidator_(vset.TotalVotingPower())
  42. assert.True(t, vset.Add(val))
  43. assert.True(t, vset.HasAddress(val.Address))
  44. idx, val2 := vset.GetByAddress(val.Address)
  45. assert.Equal(t, 0, idx)
  46. assert.Equal(t, val, val2)
  47. addr, val2 = vset.GetByIndex(0)
  48. assert.Equal(t, []byte(val.Address), addr)
  49. assert.Equal(t, val, val2)
  50. assert.Equal(t, 1, vset.Size())
  51. assert.Equal(t, val.VotingPower, vset.TotalVotingPower())
  52. assert.Equal(t, val, vset.GetProposer())
  53. assert.NotNil(t, vset.Hash())
  54. assert.NotPanics(t, func() { vset.IncrementProposerPriority(1) })
  55. // update
  56. assert.False(t, vset.Update(randValidator_(vset.TotalVotingPower())))
  57. _, val = vset.GetByAddress(val.Address)
  58. val.VotingPower += 100
  59. proposerPriority := val.ProposerPriority
  60. // Mimic update from types.PB2TM.ValidatorUpdates which does not know about ProposerPriority
  61. // and hence defaults to 0.
  62. val.ProposerPriority = 0
  63. assert.True(t, vset.Update(val))
  64. _, val = vset.GetByAddress(val.Address)
  65. assert.Equal(t, proposerPriority, val.ProposerPriority)
  66. // remove
  67. val2, removed := vset.Remove(randValidator_(vset.TotalVotingPower()).Address)
  68. assert.Nil(t, val2)
  69. assert.False(t, removed)
  70. val2, removed = vset.Remove(val.Address)
  71. assert.Equal(t, val.Address, val2.Address)
  72. assert.True(t, removed)
  73. }
  74. func TestCopy(t *testing.T) {
  75. vset := randValidatorSet(10)
  76. vsetHash := vset.Hash()
  77. if len(vsetHash) == 0 {
  78. t.Fatalf("ValidatorSet had unexpected zero hash")
  79. }
  80. vsetCopy := vset.Copy()
  81. vsetCopyHash := vsetCopy.Hash()
  82. if !bytes.Equal(vsetHash, vsetCopyHash) {
  83. t.Fatalf("ValidatorSet copy had wrong hash. Orig: %X, Copy: %X", vsetHash, vsetCopyHash)
  84. }
  85. }
  86. // Test that IncrementProposerPriority requires positive times.
  87. func TestIncrementProposerPriorityPositiveTimes(t *testing.T) {
  88. vset := NewValidatorSet([]*Validator{
  89. newValidator([]byte("foo"), 1000),
  90. newValidator([]byte("bar"), 300),
  91. newValidator([]byte("baz"), 330),
  92. })
  93. assert.Panics(t, func() { vset.IncrementProposerPriority(-1) })
  94. assert.Panics(t, func() { vset.IncrementProposerPriority(0) })
  95. vset.IncrementProposerPriority(1)
  96. }
  97. func BenchmarkValidatorSetCopy(b *testing.B) {
  98. b.StopTimer()
  99. vset := NewValidatorSet([]*Validator{})
  100. for i := 0; i < 1000; i++ {
  101. privKey := ed25519.GenPrivKey()
  102. pubKey := privKey.PubKey()
  103. val := NewValidator(pubKey, 0)
  104. if !vset.Add(val) {
  105. panic("Failed to add validator")
  106. }
  107. }
  108. b.StartTimer()
  109. for i := 0; i < b.N; i++ {
  110. vset.Copy()
  111. }
  112. }
  113. //-------------------------------------------------------------------
  114. func TestProposerSelection1(t *testing.T) {
  115. vset := NewValidatorSet([]*Validator{
  116. newValidator([]byte("foo"), 1000),
  117. newValidator([]byte("bar"), 300),
  118. newValidator([]byte("baz"), 330),
  119. })
  120. var proposers []string
  121. for i := 0; i < 99; i++ {
  122. val := vset.GetProposer()
  123. proposers = append(proposers, string(val.Address))
  124. vset.IncrementProposerPriority(1)
  125. }
  126. expected := `foo baz foo bar foo foo baz foo bar foo foo baz foo foo bar foo baz foo foo bar foo foo baz foo bar foo foo baz foo bar foo foo baz foo foo bar foo baz foo foo bar foo baz foo foo bar foo baz foo foo bar foo baz foo foo foo baz bar foo foo foo baz foo bar foo foo baz foo bar foo foo baz foo bar foo foo baz foo bar foo foo baz foo foo bar foo baz foo foo bar foo baz foo foo bar foo baz foo foo`
  127. if expected != strings.Join(proposers, " ") {
  128. t.Errorf("Expected sequence of proposers was\n%v\nbut got \n%v", expected, strings.Join(proposers, " "))
  129. }
  130. }
  131. func TestProposerSelection2(t *testing.T) {
  132. addr0 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
  133. addr1 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
  134. addr2 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}
  135. // when all voting power is same, we go in order of addresses
  136. val0, val1, val2 := newValidator(addr0, 100), newValidator(addr1, 100), newValidator(addr2, 100)
  137. valList := []*Validator{val0, val1, val2}
  138. vals := NewValidatorSet(valList)
  139. for i := 0; i < len(valList)*5; i++ {
  140. ii := (i) % len(valList)
  141. prop := vals.GetProposer()
  142. if !bytes.Equal(prop.Address, valList[ii].Address) {
  143. t.Fatalf("(%d): Expected %X. Got %X", i, valList[ii].Address, prop.Address)
  144. }
  145. vals.IncrementProposerPriority(1)
  146. }
  147. // One validator has more than the others, but not enough to propose twice in a row
  148. *val2 = *newValidator(addr2, 400)
  149. vals = NewValidatorSet(valList)
  150. // vals.IncrementProposerPriority(1)
  151. prop := vals.GetProposer()
  152. if !bytes.Equal(prop.Address, addr2) {
  153. t.Fatalf("Expected address with highest voting power to be first proposer. Got %X", prop.Address)
  154. }
  155. vals.IncrementProposerPriority(1)
  156. prop = vals.GetProposer()
  157. if !bytes.Equal(prop.Address, addr0) {
  158. t.Fatalf("Expected smallest address to be validator. Got %X", prop.Address)
  159. }
  160. // One validator has more than the others, and enough to be proposer twice in a row
  161. *val2 = *newValidator(addr2, 401)
  162. vals = NewValidatorSet(valList)
  163. prop = vals.GetProposer()
  164. if !bytes.Equal(prop.Address, addr2) {
  165. t.Fatalf("Expected address with highest voting power to be first proposer. Got %X", prop.Address)
  166. }
  167. vals.IncrementProposerPriority(1)
  168. prop = vals.GetProposer()
  169. if !bytes.Equal(prop.Address, addr2) {
  170. t.Fatalf("Expected address with highest voting power to be second proposer. Got %X", prop.Address)
  171. }
  172. vals.IncrementProposerPriority(1)
  173. prop = vals.GetProposer()
  174. if !bytes.Equal(prop.Address, addr0) {
  175. t.Fatalf("Expected smallest address to be validator. Got %X", prop.Address)
  176. }
  177. // each validator should be the proposer a proportional number of times
  178. val0, val1, val2 = newValidator(addr0, 4), newValidator(addr1, 5), newValidator(addr2, 3)
  179. valList = []*Validator{val0, val1, val2}
  180. propCount := make([]int, 3)
  181. vals = NewValidatorSet(valList)
  182. N := 1
  183. for i := 0; i < 120*N; i++ {
  184. prop := vals.GetProposer()
  185. ii := prop.Address[19]
  186. propCount[ii]++
  187. vals.IncrementProposerPriority(1)
  188. }
  189. if propCount[0] != 40*N {
  190. t.Fatalf("Expected prop count for validator with 4/12 of voting power to be %d/%d. Got %d/%d", 40*N, 120*N, propCount[0], 120*N)
  191. }
  192. if propCount[1] != 50*N {
  193. t.Fatalf("Expected prop count for validator with 5/12 of voting power to be %d/%d. Got %d/%d", 50*N, 120*N, propCount[1], 120*N)
  194. }
  195. if propCount[2] != 30*N {
  196. t.Fatalf("Expected prop count for validator with 3/12 of voting power to be %d/%d. Got %d/%d", 30*N, 120*N, propCount[2], 120*N)
  197. }
  198. }
  199. func TestProposerSelection3(t *testing.T) {
  200. vset := NewValidatorSet([]*Validator{
  201. newValidator([]byte("a"), 1),
  202. newValidator([]byte("b"), 1),
  203. newValidator([]byte("c"), 1),
  204. newValidator([]byte("d"), 1),
  205. })
  206. proposerOrder := make([]*Validator, 4)
  207. for i := 0; i < 4; i++ {
  208. proposerOrder[i] = vset.GetProposer()
  209. vset.IncrementProposerPriority(1)
  210. }
  211. // i for the loop
  212. // j for the times
  213. // we should go in order for ever, despite some IncrementProposerPriority with times > 1
  214. var i, j int
  215. for ; i < 10000; i++ {
  216. got := vset.GetProposer().Address
  217. expected := proposerOrder[j%4].Address
  218. if !bytes.Equal(got, expected) {
  219. t.Fatalf(fmt.Sprintf("vset.Proposer (%X) does not match expected proposer (%X) for (%d, %d)", got, expected, i, j))
  220. }
  221. // serialize, deserialize, check proposer
  222. b := vset.toBytes()
  223. vset.fromBytes(b)
  224. computed := vset.GetProposer() // findGetProposer()
  225. if i != 0 {
  226. if !bytes.Equal(got, computed.Address) {
  227. t.Fatalf(fmt.Sprintf("vset.Proposer (%X) does not match computed proposer (%X) for (%d, %d)", got, computed.Address, i, j))
  228. }
  229. }
  230. // times is usually 1
  231. times := 1
  232. mod := (cmn.RandInt() % 5) + 1
  233. if cmn.RandInt()%mod > 0 {
  234. // sometimes its up to 5
  235. times = (cmn.RandInt() % 4) + 1
  236. }
  237. vset.IncrementProposerPriority(times)
  238. j += times
  239. }
  240. }
  241. func newValidator(address []byte, power int64) *Validator {
  242. return &Validator{Address: address, VotingPower: power}
  243. }
  244. func randPubKey() crypto.PubKey {
  245. var pubKey [32]byte
  246. copy(pubKey[:], cmn.RandBytes(32))
  247. return ed25519.PubKeyEd25519(pubKey)
  248. }
  249. func randValidator_(totalVotingPower int64) *Validator {
  250. // this modulo limits the ProposerPriority/VotingPower to stay in the
  251. // bounds of MaxTotalVotingPower minus the already existing voting power:
  252. val := NewValidator(randPubKey(), cmn.RandInt64()%(MaxTotalVotingPower-totalVotingPower))
  253. val.ProposerPriority = cmn.RandInt64() % (MaxTotalVotingPower - totalVotingPower)
  254. return val
  255. }
  256. func randValidatorSet(numValidators int) *ValidatorSet {
  257. validators := make([]*Validator, numValidators)
  258. totalVotingPower := int64(0)
  259. for i := 0; i < numValidators; i++ {
  260. validators[i] = randValidator_(totalVotingPower)
  261. totalVotingPower += validators[i].VotingPower
  262. }
  263. return NewValidatorSet(validators)
  264. }
  265. func (valSet *ValidatorSet) toBytes() []byte {
  266. bz, err := cdc.MarshalBinaryLengthPrefixed(valSet)
  267. if err != nil {
  268. panic(err)
  269. }
  270. return bz
  271. }
  272. func (valSet *ValidatorSet) fromBytes(b []byte) {
  273. err := cdc.UnmarshalBinaryLengthPrefixed(b, &valSet)
  274. if err != nil {
  275. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  276. panic(err)
  277. }
  278. }
  279. //-------------------------------------------------------------------
  280. func TestValidatorSetTotalVotingPowerPanicsOnOverflow(t *testing.T) {
  281. // NewValidatorSet calls IncrementProposerPriority which calls TotalVotingPower()
  282. // which should panic on overflows:
  283. shouldPanic := func() {
  284. NewValidatorSet([]*Validator{
  285. {Address: []byte("a"), VotingPower: math.MaxInt64, ProposerPriority: 0},
  286. {Address: []byte("b"), VotingPower: math.MaxInt64, ProposerPriority: 0},
  287. {Address: []byte("c"), VotingPower: math.MaxInt64, ProposerPriority: 0},
  288. })
  289. }
  290. assert.Panics(t, shouldPanic)
  291. }
  292. func TestAvgProposerPriority(t *testing.T) {
  293. // Create Validator set without calling IncrementProposerPriority:
  294. tcs := []struct {
  295. vs ValidatorSet
  296. want int64
  297. }{
  298. 0: {ValidatorSet{Validators: []*Validator{{ProposerPriority: 0}, {ProposerPriority: 0}, {ProposerPriority: 0}}}, 0},
  299. 1: {ValidatorSet{Validators: []*Validator{{ProposerPriority: math.MaxInt64}, {ProposerPriority: 0}, {ProposerPriority: 0}}}, math.MaxInt64 / 3},
  300. 2: {ValidatorSet{Validators: []*Validator{{ProposerPriority: math.MaxInt64}, {ProposerPriority: 0}}}, math.MaxInt64 / 2},
  301. 3: {ValidatorSet{Validators: []*Validator{{ProposerPriority: math.MaxInt64}, {ProposerPriority: math.MaxInt64}}}, math.MaxInt64},
  302. 4: {ValidatorSet{Validators: []*Validator{{ProposerPriority: math.MinInt64}, {ProposerPriority: math.MinInt64}}}, math.MinInt64},
  303. }
  304. for i, tc := range tcs {
  305. got := tc.vs.computeAvgProposerPriority()
  306. assert.Equal(t, tc.want, got, "test case: %v", i)
  307. }
  308. }
  309. func TestAveragingInIncrementProposerPriority(t *testing.T) {
  310. // Test that the averaging works as expected inside of IncrementProposerPriority.
  311. // Each validator comes with zero voting power which simplifies reasoning about
  312. // the expected ProposerPriority.
  313. tcs := []struct {
  314. vs ValidatorSet
  315. times int
  316. avg int64
  317. }{
  318. 0: {ValidatorSet{
  319. Validators: []*Validator{
  320. {Address: []byte("a"), ProposerPriority: 1},
  321. {Address: []byte("b"), ProposerPriority: 2},
  322. {Address: []byte("c"), ProposerPriority: 3}}},
  323. 1, 2},
  324. 1: {ValidatorSet{
  325. Validators: []*Validator{
  326. {Address: []byte("a"), ProposerPriority: 10},
  327. {Address: []byte("b"), ProposerPriority: -10},
  328. {Address: []byte("c"), ProposerPriority: 1}}},
  329. // this should average twice but the average should be 0 after the first iteration
  330. // (voting power is 0 -> no changes)
  331. 11, 1 / 3},
  332. 2: {ValidatorSet{
  333. Validators: []*Validator{
  334. {Address: []byte("a"), ProposerPriority: 100},
  335. {Address: []byte("b"), ProposerPriority: -10},
  336. {Address: []byte("c"), ProposerPriority: 1}}},
  337. 1, 91 / 3},
  338. }
  339. for i, tc := range tcs {
  340. // work on copy to have the old ProposerPriorities:
  341. newVset := tc.vs.CopyIncrementProposerPriority(tc.times)
  342. for _, val := range tc.vs.Validators {
  343. _, updatedVal := newVset.GetByAddress(val.Address)
  344. assert.Equal(t, updatedVal.ProposerPriority, val.ProposerPriority-tc.avg, "test case: %v", i)
  345. }
  346. }
  347. }
  348. func TestAveragingInIncrementProposerPriorityWithVotingPower(t *testing.T) {
  349. // Other than TestAveragingInIncrementProposerPriority this is a more complete test showing
  350. // how each ProposerPriority changes in relation to the validator's voting power respectively.
  351. // average is zero in each round:
  352. vp0 := int64(10)
  353. vp1 := int64(1)
  354. vp2 := int64(1)
  355. total := vp0 + vp1 + vp2
  356. avg := (vp0 + vp1 + vp2 - total) / 3
  357. vals := ValidatorSet{Validators: []*Validator{
  358. {Address: []byte{0}, ProposerPriority: 0, VotingPower: vp0},
  359. {Address: []byte{1}, ProposerPriority: 0, VotingPower: vp1},
  360. {Address: []byte{2}, ProposerPriority: 0, VotingPower: vp2}}}
  361. tcs := []struct {
  362. vals *ValidatorSet
  363. wantProposerPrioritys []int64
  364. times int
  365. wantProposer *Validator
  366. }{
  367. 0: {
  368. vals.Copy(),
  369. []int64{
  370. // Acumm+VotingPower-Avg:
  371. 0 + vp0 - total - avg, // mostest will be subtracted by total voting power (12)
  372. 0 + vp1,
  373. 0 + vp2},
  374. 1,
  375. vals.Validators[0]},
  376. 1: {
  377. vals.Copy(),
  378. []int64{
  379. (0 + vp0 - total) + vp0 - total - avg, // this will be mostest on 2nd iter, too
  380. (0 + vp1) + vp1,
  381. (0 + vp2) + vp2},
  382. 2,
  383. vals.Validators[0]}, // increment twice -> expect average to be subtracted twice
  384. 2: {
  385. vals.Copy(),
  386. []int64{
  387. 0 + 3*(vp0-total) - avg, // still mostest
  388. 0 + 3*vp1,
  389. 0 + 3*vp2},
  390. 3,
  391. vals.Validators[0]},
  392. 3: {
  393. vals.Copy(),
  394. []int64{
  395. 0 + 4*(vp0-total), // still mostest
  396. 0 + 4*vp1,
  397. 0 + 4*vp2},
  398. 4,
  399. vals.Validators[0]},
  400. 4: {
  401. vals.Copy(),
  402. []int64{
  403. 0 + 4*(vp0-total) + vp0, // 4 iters was mostest
  404. 0 + 5*vp1 - total, // now this val is mostest for the 1st time (hence -12==totalVotingPower)
  405. 0 + 5*vp2},
  406. 5,
  407. vals.Validators[1]},
  408. 5: {
  409. vals.Copy(),
  410. []int64{
  411. 0 + 6*vp0 - 5*total, // mostest again
  412. 0 + 6*vp1 - total, // mostest once up to here
  413. 0 + 6*vp2},
  414. 6,
  415. vals.Validators[0]},
  416. 6: {
  417. vals.Copy(),
  418. []int64{
  419. 0 + 7*vp0 - 6*total, // in 7 iters this val is mostest 6 times
  420. 0 + 7*vp1 - total, // in 7 iters this val is mostest 1 time
  421. 0 + 7*vp2},
  422. 7,
  423. vals.Validators[0]},
  424. 7: {
  425. vals.Copy(),
  426. []int64{
  427. 0 + 8*vp0 - 7*total, // mostest again
  428. 0 + 8*vp1 - total,
  429. 0 + 8*vp2},
  430. 8,
  431. vals.Validators[0]},
  432. 8: {
  433. vals.Copy(),
  434. []int64{
  435. 0 + 9*vp0 - 7*total,
  436. 0 + 9*vp1 - total,
  437. 0 + 9*vp2 - total}, // mostest
  438. 9,
  439. vals.Validators[2]},
  440. 9: {
  441. vals.Copy(),
  442. []int64{
  443. 0 + 10*vp0 - 8*total, // after 10 iters this is mostest again
  444. 0 + 10*vp1 - total, // after 6 iters this val is "mostest" once and not in between
  445. 0 + 10*vp2 - total}, // in between 10 iters this val is "mostest" once
  446. 10,
  447. vals.Validators[0]},
  448. 10: {
  449. vals.Copy(),
  450. []int64{
  451. 0 + 11*vp0 - 9*total,
  452. 0 + 11*vp1 - total, // after 6 iters this val is "mostest" once and not in between
  453. 0 + 11*vp2 - total}, // after 10 iters this val is "mostest" once
  454. 11,
  455. vals.Validators[0]},
  456. }
  457. for i, tc := range tcs {
  458. tc.vals.IncrementProposerPriority(tc.times)
  459. assert.Equal(t, tc.wantProposer.Address, tc.vals.GetProposer().Address,
  460. "test case: %v",
  461. i)
  462. for valIdx, val := range tc.vals.Validators {
  463. assert.Equal(t,
  464. tc.wantProposerPrioritys[valIdx],
  465. val.ProposerPriority,
  466. "test case: %v, validator: %v",
  467. i,
  468. valIdx)
  469. }
  470. }
  471. }
  472. func TestSafeAdd(t *testing.T) {
  473. f := func(a, b int64) bool {
  474. c, overflow := safeAdd(a, b)
  475. return overflow || (!overflow && c == a+b)
  476. }
  477. if err := quick.Check(f, nil); err != nil {
  478. t.Error(err)
  479. }
  480. }
  481. func TestSafeAddClip(t *testing.T) {
  482. assert.EqualValues(t, math.MaxInt64, safeAddClip(math.MaxInt64, 10))
  483. assert.EqualValues(t, math.MaxInt64, safeAddClip(math.MaxInt64, math.MaxInt64))
  484. assert.EqualValues(t, math.MinInt64, safeAddClip(math.MinInt64, -10))
  485. }
  486. func TestSafeSubClip(t *testing.T) {
  487. assert.EqualValues(t, math.MinInt64, safeSubClip(math.MinInt64, 10))
  488. assert.EqualValues(t, 0, safeSubClip(math.MinInt64, math.MinInt64))
  489. assert.EqualValues(t, math.MinInt64, safeSubClip(math.MinInt64, math.MaxInt64))
  490. assert.EqualValues(t, math.MaxInt64, safeSubClip(math.MaxInt64, -10))
  491. }
  492. //-------------------------------------------------------------------
  493. func TestValidatorSetVerifyCommit(t *testing.T) {
  494. privKey := ed25519.GenPrivKey()
  495. pubKey := privKey.PubKey()
  496. v1 := NewValidator(pubKey, 1000)
  497. vset := NewValidatorSet([]*Validator{v1})
  498. chainID := "mychainID"
  499. blockID := BlockID{Hash: []byte("hello")}
  500. height := int64(5)
  501. vote := &Vote{
  502. ValidatorAddress: v1.Address,
  503. ValidatorIndex: 0,
  504. Height: height,
  505. Round: 0,
  506. Timestamp: tmtime.Now(),
  507. Type: PrecommitType,
  508. BlockID: blockID,
  509. }
  510. sig, err := privKey.Sign(vote.SignBytes(chainID))
  511. assert.NoError(t, err)
  512. vote.Signature = sig
  513. commit := &Commit{
  514. BlockID: blockID,
  515. Precommits: []*Vote{vote},
  516. }
  517. badChainID := "notmychainID"
  518. badBlockID := BlockID{Hash: []byte("goodbye")}
  519. badHeight := height + 1
  520. badCommit := &Commit{
  521. BlockID: blockID,
  522. Precommits: []*Vote{nil},
  523. }
  524. // test some error cases
  525. // TODO: test more cases!
  526. cases := []struct {
  527. chainID string
  528. blockID BlockID
  529. height int64
  530. commit *Commit
  531. }{
  532. {badChainID, blockID, height, commit},
  533. {chainID, badBlockID, height, commit},
  534. {chainID, blockID, badHeight, commit},
  535. {chainID, blockID, height, badCommit},
  536. }
  537. for i, c := range cases {
  538. err := vset.VerifyCommit(c.chainID, c.blockID, c.height, c.commit)
  539. assert.NotNil(t, err, i)
  540. }
  541. // test a good one
  542. err = vset.VerifyCommit(chainID, blockID, height, commit)
  543. assert.Nil(t, err)
  544. }