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.

1059 lines
39 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
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 state
  2. import (
  3. "bytes"
  4. "fmt"
  5. "math"
  6. "math/big"
  7. "testing"
  8. "github.com/stretchr/testify/assert"
  9. "github.com/stretchr/testify/require"
  10. abci "github.com/tendermint/tendermint/abci/types"
  11. "github.com/tendermint/tendermint/crypto"
  12. "github.com/tendermint/tendermint/crypto/ed25519"
  13. cmn "github.com/tendermint/tendermint/libs/common"
  14. dbm "github.com/tendermint/tendermint/libs/db"
  15. cfg "github.com/tendermint/tendermint/config"
  16. "github.com/tendermint/tendermint/types"
  17. )
  18. // setupTestCase does setup common to all test cases.
  19. func setupTestCase(t *testing.T) (func(t *testing.T), dbm.DB, State) {
  20. config := cfg.ResetTestRoot("state_")
  21. dbType := dbm.DBBackendType(config.DBBackend)
  22. stateDB := dbm.NewDB("state", dbType, config.DBDir())
  23. state, err := LoadStateFromDBOrGenesisFile(stateDB, config.GenesisFile())
  24. assert.NoError(t, err, "expected no error on LoadStateFromDBOrGenesisFile")
  25. tearDown := func(t *testing.T) {}
  26. return tearDown, stateDB, state
  27. }
  28. // TestStateCopy tests the correct copying behaviour of State.
  29. func TestStateCopy(t *testing.T) {
  30. tearDown, _, state := setupTestCase(t)
  31. defer tearDown(t)
  32. // nolint: vetshadow
  33. assert := assert.New(t)
  34. stateCopy := state.Copy()
  35. assert.True(state.Equals(stateCopy),
  36. fmt.Sprintf("expected state and its copy to be identical.\ngot: %v\nexpected: %v\n",
  37. stateCopy, state))
  38. stateCopy.LastBlockHeight++
  39. assert.False(state.Equals(stateCopy), fmt.Sprintf(`expected states to be different. got same
  40. %v`, state))
  41. }
  42. //TestMakeGenesisStateNilValidators tests state's consistency when genesis file's validators field is nil.
  43. func TestMakeGenesisStateNilValidators(t *testing.T) {
  44. doc := types.GenesisDoc{
  45. ChainID: "dummy",
  46. Validators: nil,
  47. }
  48. require.Nil(t, doc.ValidateAndComplete())
  49. state, err := MakeGenesisState(&doc)
  50. require.Nil(t, err)
  51. require.Equal(t, 0, len(state.Validators.Validators))
  52. require.Equal(t, 0, len(state.NextValidators.Validators))
  53. }
  54. // TestStateSaveLoad tests saving and loading State from a db.
  55. func TestStateSaveLoad(t *testing.T) {
  56. tearDown, stateDB, state := setupTestCase(t)
  57. defer tearDown(t)
  58. // nolint: vetshadow
  59. assert := assert.New(t)
  60. state.LastBlockHeight++
  61. SaveState(stateDB, state)
  62. loadedState := LoadState(stateDB)
  63. assert.True(state.Equals(loadedState),
  64. fmt.Sprintf("expected state and its copy to be identical.\ngot: %v\nexpected: %v\n",
  65. loadedState, state))
  66. }
  67. // TestABCIResponsesSaveLoad tests saving and loading ABCIResponses.
  68. func TestABCIResponsesSaveLoad1(t *testing.T) {
  69. tearDown, stateDB, state := setupTestCase(t)
  70. defer tearDown(t)
  71. // nolint: vetshadow
  72. assert := assert.New(t)
  73. state.LastBlockHeight++
  74. // Build mock responses.
  75. block := makeBlock(state, 2)
  76. abciResponses := NewABCIResponses(block)
  77. abciResponses.DeliverTx[0] = &abci.ResponseDeliverTx{Data: []byte("foo"), Tags: nil}
  78. abciResponses.DeliverTx[1] = &abci.ResponseDeliverTx{Data: []byte("bar"), Log: "ok", Tags: nil}
  79. abciResponses.EndBlock = &abci.ResponseEndBlock{ValidatorUpdates: []abci.ValidatorUpdate{
  80. types.TM2PB.NewValidatorUpdate(ed25519.GenPrivKey().PubKey(), 10),
  81. }}
  82. saveABCIResponses(stateDB, block.Height, abciResponses)
  83. loadedABCIResponses, err := LoadABCIResponses(stateDB, block.Height)
  84. assert.Nil(err)
  85. assert.Equal(abciResponses, loadedABCIResponses,
  86. fmt.Sprintf("ABCIResponses don't match:\ngot: %v\nexpected: %v\n",
  87. loadedABCIResponses, abciResponses))
  88. }
  89. // TestResultsSaveLoad tests saving and loading ABCI results.
  90. func TestABCIResponsesSaveLoad2(t *testing.T) {
  91. tearDown, stateDB, _ := setupTestCase(t)
  92. defer tearDown(t)
  93. // nolint: vetshadow
  94. assert := assert.New(t)
  95. cases := [...]struct {
  96. // Height is implied to equal index+2,
  97. // as block 1 is created from genesis.
  98. added []*abci.ResponseDeliverTx
  99. expected types.ABCIResults
  100. }{
  101. 0: {
  102. nil,
  103. nil,
  104. },
  105. 1: {
  106. []*abci.ResponseDeliverTx{
  107. {Code: 32, Data: []byte("Hello"), Log: "Huh?"},
  108. },
  109. types.ABCIResults{
  110. {32, []byte("Hello")},
  111. }},
  112. 2: {
  113. []*abci.ResponseDeliverTx{
  114. {Code: 383},
  115. {Data: []byte("Gotcha!"),
  116. Tags: []cmn.KVPair{
  117. {Key: []byte("a"), Value: []byte("1")},
  118. {Key: []byte("build"), Value: []byte("stuff")},
  119. }},
  120. },
  121. types.ABCIResults{
  122. {383, nil},
  123. {0, []byte("Gotcha!")},
  124. }},
  125. 3: {
  126. nil,
  127. nil,
  128. },
  129. }
  130. // Query all before, this should return error.
  131. for i := range cases {
  132. h := int64(i + 1)
  133. res, err := LoadABCIResponses(stateDB, h)
  134. assert.Error(err, "%d: %#v", i, res)
  135. }
  136. // Add all cases.
  137. for i, tc := range cases {
  138. h := int64(i + 1) // last block height, one below what we save
  139. responses := &ABCIResponses{
  140. DeliverTx: tc.added,
  141. EndBlock: &abci.ResponseEndBlock{},
  142. }
  143. saveABCIResponses(stateDB, h, responses)
  144. }
  145. // Query all before, should return expected value.
  146. for i, tc := range cases {
  147. h := int64(i + 1)
  148. res, err := LoadABCIResponses(stateDB, h)
  149. assert.NoError(err, "%d", i)
  150. assert.Equal(tc.expected.Hash(), res.ResultsHash(), "%d", i)
  151. }
  152. }
  153. // TestValidatorSimpleSaveLoad tests saving and loading validators.
  154. func TestValidatorSimpleSaveLoad(t *testing.T) {
  155. tearDown, stateDB, state := setupTestCase(t)
  156. defer tearDown(t)
  157. // nolint: vetshadow
  158. assert := assert.New(t)
  159. // Can't load anything for height 0.
  160. v, err := LoadValidators(stateDB, 0)
  161. assert.IsType(ErrNoValSetForHeight{}, err, "expected err at height 0")
  162. // Should be able to load for height 1.
  163. v, err = LoadValidators(stateDB, 1)
  164. assert.Nil(err, "expected no err at height 1")
  165. assert.Equal(v.Hash(), state.Validators.Hash(), "expected validator hashes to match")
  166. // Should be able to load for height 2.
  167. v, err = LoadValidators(stateDB, 2)
  168. assert.Nil(err, "expected no err at height 2")
  169. assert.Equal(v.Hash(), state.NextValidators.Hash(), "expected validator hashes to match")
  170. // Increment height, save; should be able to load for next & next next height.
  171. state.LastBlockHeight++
  172. nextHeight := state.LastBlockHeight + 1
  173. saveValidatorsInfo(stateDB, nextHeight+1, state.LastHeightValidatorsChanged, state.NextValidators)
  174. vp0, err := LoadValidators(stateDB, nextHeight+0)
  175. assert.Nil(err, "expected no err")
  176. vp1, err := LoadValidators(stateDB, nextHeight+1)
  177. assert.Nil(err, "expected no err")
  178. assert.Equal(vp0.Hash(), state.Validators.Hash(), "expected validator hashes to match")
  179. assert.Equal(vp1.Hash(), state.NextValidators.Hash(), "expected next validator hashes to match")
  180. }
  181. // TestValidatorChangesSaveLoad tests saving and loading a validator set with changes.
  182. func TestOneValidatorChangesSaveLoad(t *testing.T) {
  183. tearDown, stateDB, state := setupTestCase(t)
  184. defer tearDown(t)
  185. // Change vals at these heights.
  186. changeHeights := []int64{1, 2, 4, 5, 10, 15, 16, 17, 20}
  187. N := len(changeHeights)
  188. // Build the validator history by running updateState
  189. // with the right validator set for each height.
  190. highestHeight := changeHeights[N-1] + 5
  191. changeIndex := 0
  192. _, val := state.Validators.GetByIndex(0)
  193. power := val.VotingPower
  194. var err error
  195. var validatorUpdates []*types.Validator
  196. for i := int64(1); i < highestHeight; i++ {
  197. // When we get to a change height, use the next pubkey.
  198. if changeIndex < len(changeHeights) && i == changeHeights[changeIndex] {
  199. changeIndex++
  200. power++
  201. }
  202. header, blockID, responses := makeHeaderPartsResponsesValPowerChange(state, i, power)
  203. validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.EndBlock.ValidatorUpdates)
  204. require.NoError(t, err)
  205. state, err = updateState(state, blockID, &header, responses, validatorUpdates)
  206. require.NoError(t, err)
  207. nextHeight := state.LastBlockHeight + 1
  208. saveValidatorsInfo(stateDB, nextHeight+1, state.LastHeightValidatorsChanged, state.NextValidators)
  209. }
  210. // On each height change, increment the power by one.
  211. testCases := make([]int64, highestHeight)
  212. changeIndex = 0
  213. power = val.VotingPower
  214. for i := int64(1); i < highestHeight+1; i++ {
  215. // We get to the height after a change height use the next pubkey (note
  216. // our counter starts at 0 this time).
  217. if changeIndex < len(changeHeights) && i == changeHeights[changeIndex]+1 {
  218. changeIndex++
  219. power++
  220. }
  221. testCases[i-1] = power
  222. }
  223. for i, power := range testCases {
  224. v, err := LoadValidators(stateDB, int64(i+1+1)) // +1 because vset changes delayed by 1 block.
  225. assert.Nil(t, err, fmt.Sprintf("expected no err at height %d", i))
  226. assert.Equal(t, v.Size(), 1, "validator set size is greater than 1: %d", v.Size())
  227. _, val := v.GetByIndex(0)
  228. assert.Equal(t, val.VotingPower, power, fmt.Sprintf(`unexpected powerat
  229. height %d`, i))
  230. }
  231. }
  232. func TestProposerFrequency(t *testing.T) {
  233. // some explicit test cases
  234. testCases := []struct {
  235. powers []int64
  236. }{
  237. // 2 vals
  238. {[]int64{1, 1}},
  239. {[]int64{1, 2}},
  240. {[]int64{1, 100}},
  241. {[]int64{5, 5}},
  242. {[]int64{5, 100}},
  243. {[]int64{50, 50}},
  244. {[]int64{50, 100}},
  245. {[]int64{1, 1000}},
  246. // 3 vals
  247. {[]int64{1, 1, 1}},
  248. {[]int64{1, 2, 3}},
  249. {[]int64{1, 2, 3}},
  250. {[]int64{1, 1, 10}},
  251. {[]int64{1, 1, 100}},
  252. {[]int64{1, 10, 100}},
  253. {[]int64{1, 1, 1000}},
  254. {[]int64{1, 10, 1000}},
  255. {[]int64{1, 100, 1000}},
  256. // 4 vals
  257. {[]int64{1, 1, 1, 1}},
  258. {[]int64{1, 2, 3, 4}},
  259. {[]int64{1, 1, 1, 10}},
  260. {[]int64{1, 1, 1, 100}},
  261. {[]int64{1, 1, 1, 1000}},
  262. {[]int64{1, 1, 10, 100}},
  263. {[]int64{1, 1, 10, 1000}},
  264. {[]int64{1, 1, 100, 1000}},
  265. {[]int64{1, 10, 100, 1000}},
  266. }
  267. for caseNum, testCase := range testCases {
  268. // run each case 5 times to sample different
  269. // initial priorities
  270. for i := 0; i < 5; i++ {
  271. valSet := genValSetWithPowers(testCase.powers)
  272. testProposerFreq(t, caseNum, valSet)
  273. }
  274. }
  275. // some random test cases with up to 300 validators
  276. maxVals := 100
  277. maxPower := 1000
  278. nTestCases := 5
  279. for i := 0; i < nTestCases; i++ {
  280. N := cmn.RandInt() % maxVals
  281. vals := make([]*types.Validator, N)
  282. totalVotePower := int64(0)
  283. for j := 0; j < N; j++ {
  284. // make sure votePower > 0
  285. votePower := int64(cmn.RandInt()%maxPower) + 1
  286. totalVotePower += votePower
  287. privVal := types.NewMockPV()
  288. pubKey := privVal.GetPubKey()
  289. val := types.NewValidator(pubKey, votePower)
  290. val.ProposerPriority = cmn.RandInt64()
  291. vals[j] = val
  292. }
  293. valSet := types.NewValidatorSet(vals)
  294. valSet.RescalePriorities(totalVotePower)
  295. testProposerFreq(t, i, valSet)
  296. }
  297. }
  298. // new val set with given powers and random initial priorities
  299. func genValSetWithPowers(powers []int64) *types.ValidatorSet {
  300. size := len(powers)
  301. vals := make([]*types.Validator, size)
  302. totalVotePower := int64(0)
  303. for i := 0; i < size; i++ {
  304. totalVotePower += powers[i]
  305. val := types.NewValidator(ed25519.GenPrivKey().PubKey(), powers[i])
  306. val.ProposerPriority = cmn.RandInt64()
  307. vals[i] = val
  308. }
  309. valSet := types.NewValidatorSet(vals)
  310. valSet.RescalePriorities(totalVotePower)
  311. return valSet
  312. }
  313. // test a proposer appears as frequently as expected
  314. func testProposerFreq(t *testing.T, caseNum int, valSet *types.ValidatorSet) {
  315. N := valSet.Size()
  316. totalPower := valSet.TotalVotingPower()
  317. // run the proposer selection and track frequencies
  318. runMult := 1
  319. runs := int(totalPower) * runMult
  320. freqs := make([]int, N)
  321. for i := 0; i < runs; i++ {
  322. prop := valSet.GetProposer()
  323. idx, _ := valSet.GetByAddress(prop.Address)
  324. freqs[idx] += 1
  325. valSet.IncrementProposerPriority(1)
  326. }
  327. // assert frequencies match expected (max off by 1)
  328. for i, freq := range freqs {
  329. _, val := valSet.GetByIndex(i)
  330. expectFreq := int(val.VotingPower) * runMult
  331. gotFreq := freq
  332. abs := int(math.Abs(float64(expectFreq - gotFreq)))
  333. // max bound on expected vs seen freq was proven
  334. // to be 1 for the 2 validator case in
  335. // https://github.com/cwgoes/tm-proposer-idris
  336. // and inferred to generalize to N-1
  337. bound := N - 1
  338. require.True(t, abs <= bound, fmt.Sprintf("Case %d val %d (%d): got %d, expected %d", caseNum, i, N, gotFreq, expectFreq))
  339. }
  340. }
  341. // TestProposerPriorityDoesNotGetResetToZero assert that we preserve accum when calling updateState
  342. // see https://github.com/tendermint/tendermint/issues/2718
  343. func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) {
  344. tearDown, _, state := setupTestCase(t)
  345. defer tearDown(t)
  346. val1VotingPower := int64(10)
  347. val1PubKey := ed25519.GenPrivKey().PubKey()
  348. val1 := &types.Validator{Address: val1PubKey.Address(), PubKey: val1PubKey, VotingPower: val1VotingPower}
  349. state.Validators = types.NewValidatorSet([]*types.Validator{val1})
  350. state.NextValidators = state.Validators
  351. // NewValidatorSet calls IncrementProposerPriority but uses on a copy of val1
  352. assert.EqualValues(t, 0, val1.ProposerPriority)
  353. block := makeBlock(state, state.LastBlockHeight+1)
  354. blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  355. abciResponses := &ABCIResponses{
  356. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  357. }
  358. validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  359. require.NoError(t, err)
  360. updatedState, err := updateState(state, blockID, &block.Header, abciResponses, validatorUpdates)
  361. assert.NoError(t, err)
  362. curTotal := val1VotingPower
  363. // one increment step and one validator: 0 + power - total_power == 0
  364. assert.Equal(t, 0+val1VotingPower-curTotal, updatedState.NextValidators.Validators[0].ProposerPriority)
  365. // add a validator
  366. val2PubKey := ed25519.GenPrivKey().PubKey()
  367. val2VotingPower := int64(100)
  368. updateAddVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(val2PubKey), Power: val2VotingPower}
  369. validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateAddVal})
  370. assert.NoError(t, err)
  371. updatedState2, err := updateState(updatedState, blockID, &block.Header, abciResponses, validatorUpdates)
  372. assert.NoError(t, err)
  373. require.Equal(t, len(updatedState2.NextValidators.Validators), 2)
  374. _, updatedVal1 := updatedState2.NextValidators.GetByAddress(val1PubKey.Address())
  375. _, addedVal2 := updatedState2.NextValidators.GetByAddress(val2PubKey.Address())
  376. // adding a validator should not lead to a ProposerPriority equal to zero (unless the combination of averaging and
  377. // incrementing would cause so; which is not the case here)
  378. // Steps from adding new validator:
  379. // 0 - val1 prio is 0, TVP after add:
  380. wantVal1Prio := int64(0)
  381. totalPowerAfter := val1VotingPower + val2VotingPower
  382. // 1. Add - Val2 should be initially added with (-123) =>
  383. wantVal2Prio := -(totalPowerAfter + (totalPowerAfter >> 3))
  384. // 2. Scale - noop
  385. // 3. Center - with avg, resulting val2:-61, val1:62
  386. avg := big.NewInt(0).Add(big.NewInt(wantVal1Prio), big.NewInt(wantVal2Prio))
  387. avg.Div(avg, big.NewInt(2))
  388. wantVal2Prio = wantVal2Prio - avg.Int64() // -61
  389. wantVal1Prio = wantVal1Prio - avg.Int64() // 62
  390. // 4. Steps from IncrementProposerPriority
  391. wantVal1Prio = wantVal1Prio + val1VotingPower // 72
  392. wantVal2Prio = wantVal2Prio + val2VotingPower // 39
  393. wantVal1Prio = wantVal1Prio - totalPowerAfter // -38 as val1 is proposer
  394. assert.Equal(t, wantVal1Prio, updatedVal1.ProposerPriority)
  395. assert.Equal(t, wantVal2Prio, addedVal2.ProposerPriority)
  396. // Updating a validator does not reset the ProposerPriority to zero:
  397. // 1. Add - Val2 VotingPower change to 1 =>
  398. updatedVotingPowVal2 := int64(1)
  399. updateVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(val2PubKey), Power: updatedVotingPowVal2}
  400. validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateVal})
  401. assert.NoError(t, err)
  402. // this will cause the diff of priorities (77)
  403. // to be larger than threshold == 2*totalVotingPower (22):
  404. updatedState3, err := updateState(updatedState2, blockID, &block.Header, abciResponses, validatorUpdates)
  405. assert.NoError(t, err)
  406. require.Equal(t, len(updatedState3.NextValidators.Validators), 2)
  407. _, prevVal1 := updatedState3.Validators.GetByAddress(val1PubKey.Address())
  408. _, prevVal2 := updatedState3.Validators.GetByAddress(val2PubKey.Address())
  409. _, updatedVal1 = updatedState3.NextValidators.GetByAddress(val1PubKey.Address())
  410. _, updatedVal2 := updatedState3.NextValidators.GetByAddress(val2PubKey.Address())
  411. // 2. Scale
  412. // old prios: v1(10):-38, v2(1):39
  413. wantVal1Prio = prevVal1.ProposerPriority
  414. wantVal2Prio = prevVal2.ProposerPriority
  415. // scale to diffMax = 22 = 2 * tvp, diff=39-(-38)=77
  416. // new totalPower
  417. totalPower := updatedVal1.VotingPower + updatedVal2.VotingPower
  418. dist := wantVal2Prio - wantVal1Prio
  419. // ratio := (dist + 2*totalPower - 1) / 2*totalPower = 98/22 = 4
  420. ratio := (dist + 2*totalPower - 1) / (2 * totalPower)
  421. // v1(10):-38/4, v2(1):39/4
  422. wantVal1Prio /= ratio // -9
  423. wantVal2Prio /= ratio // 9
  424. // 3. Center - noop
  425. // 4. IncrementProposerPriority() ->
  426. // v1(10):-9+10, v2(1):9+1 -> v2 proposer so subsract tvp(11)
  427. // v1(10):1, v2(1):-1
  428. wantVal2Prio += updatedVal2.VotingPower // 10 -> prop
  429. wantVal1Prio += updatedVal1.VotingPower // 1
  430. wantVal2Prio -= totalPower // -1
  431. assert.Equal(t, wantVal2Prio, updatedVal2.ProposerPriority)
  432. assert.Equal(t, wantVal1Prio, updatedVal1.ProposerPriority)
  433. }
  434. func TestProposerPriorityProposerAlternates(t *testing.T) {
  435. // Regression test that would fail if the inner workings of
  436. // IncrementProposerPriority change.
  437. // Additionally, make sure that same power validators alternate if both
  438. // have the same voting power (and the 2nd was added later).
  439. tearDown, _, state := setupTestCase(t)
  440. defer tearDown(t)
  441. val1VotingPower := int64(10)
  442. val1PubKey := ed25519.GenPrivKey().PubKey()
  443. val1 := &types.Validator{Address: val1PubKey.Address(), PubKey: val1PubKey, VotingPower: val1VotingPower}
  444. // reset state validators to above validator
  445. state.Validators = types.NewValidatorSet([]*types.Validator{val1})
  446. state.NextValidators = state.Validators
  447. // we only have one validator:
  448. assert.Equal(t, val1PubKey.Address(), state.Validators.Proposer.Address)
  449. block := makeBlock(state, state.LastBlockHeight+1)
  450. blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  451. // no updates:
  452. abciResponses := &ABCIResponses{
  453. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  454. }
  455. validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  456. require.NoError(t, err)
  457. updatedState, err := updateState(state, blockID, &block.Header, abciResponses, validatorUpdates)
  458. assert.NoError(t, err)
  459. // 0 + 10 (initial prio) - 10 (avg) - 10 (mostest - total) = -10
  460. totalPower := val1VotingPower
  461. wantVal1Prio := 0 + val1VotingPower - totalPower
  462. assert.Equal(t, wantVal1Prio, updatedState.NextValidators.Validators[0].ProposerPriority)
  463. assert.Equal(t, val1PubKey.Address(), updatedState.NextValidators.Proposer.Address)
  464. // add a validator with the same voting power as the first
  465. val2PubKey := ed25519.GenPrivKey().PubKey()
  466. updateAddVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(val2PubKey), Power: val1VotingPower}
  467. validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateAddVal})
  468. assert.NoError(t, err)
  469. updatedState2, err := updateState(updatedState, blockID, &block.Header, abciResponses, validatorUpdates)
  470. assert.NoError(t, err)
  471. require.Equal(t, len(updatedState2.NextValidators.Validators), 2)
  472. assert.Equal(t, updatedState2.Validators, updatedState.NextValidators)
  473. // val1 will still be proposer as val2 just got added:
  474. assert.Equal(t, val1PubKey.Address(), updatedState.NextValidators.Proposer.Address)
  475. assert.Equal(t, updatedState2.Validators.Proposer.Address, updatedState2.NextValidators.Proposer.Address)
  476. assert.Equal(t, updatedState2.Validators.Proposer.Address, val1PubKey.Address())
  477. assert.Equal(t, updatedState2.NextValidators.Proposer.Address, val1PubKey.Address())
  478. _, updatedVal1 := updatedState2.NextValidators.GetByAddress(val1PubKey.Address())
  479. _, oldVal1 := updatedState2.Validators.GetByAddress(val1PubKey.Address())
  480. _, updatedVal2 := updatedState2.NextValidators.GetByAddress(val2PubKey.Address())
  481. // 1. Add
  482. val2VotingPower := val1VotingPower
  483. totalPower = val1VotingPower + val2VotingPower // 20
  484. v2PrioWhenAddedVal2 := -(totalPower + (totalPower >> 3)) // -22
  485. // 2. Scale - noop
  486. // 3. Center
  487. avgSum := big.NewInt(0).Add(big.NewInt(v2PrioWhenAddedVal2), big.NewInt(oldVal1.ProposerPriority))
  488. avg := avgSum.Div(avgSum, big.NewInt(2)) // -11
  489. expectedVal2Prio := v2PrioWhenAddedVal2 - avg.Int64() // -11
  490. expectedVal1Prio := oldVal1.ProposerPriority - avg.Int64() // 11
  491. // 4. Increment
  492. expectedVal2Prio = expectedVal2Prio + val2VotingPower // -11 + 10 = -1
  493. expectedVal1Prio = expectedVal1Prio + val1VotingPower // 11 + 10 == 21
  494. expectedVal1Prio = expectedVal1Prio - totalPower // 1, val1 proposer
  495. assert.EqualValues(t, expectedVal1Prio, updatedVal1.ProposerPriority)
  496. assert.EqualValues(t, expectedVal2Prio, updatedVal2.ProposerPriority, "unexpected proposer priority for validator: %v", updatedVal2)
  497. validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  498. require.NoError(t, err)
  499. updatedState3, err := updateState(updatedState2, blockID, &block.Header, abciResponses, validatorUpdates)
  500. assert.NoError(t, err)
  501. assert.Equal(t, updatedState3.Validators.Proposer.Address, updatedState3.NextValidators.Proposer.Address)
  502. assert.Equal(t, updatedState3.Validators, updatedState2.NextValidators)
  503. _, updatedVal1 = updatedState3.NextValidators.GetByAddress(val1PubKey.Address())
  504. _, updatedVal2 = updatedState3.NextValidators.GetByAddress(val2PubKey.Address())
  505. // val1 will still be proposer:
  506. assert.Equal(t, val1PubKey.Address(), updatedState3.NextValidators.Proposer.Address)
  507. // check if expected proposer prio is matched:
  508. // Increment
  509. expectedVal2Prio2 := expectedVal2Prio + val2VotingPower // -1 + 10 = 9
  510. expectedVal1Prio2 := expectedVal1Prio + val1VotingPower // 1 + 10 == 11
  511. expectedVal1Prio2 = expectedVal1Prio2 - totalPower // -9, val1 proposer
  512. assert.EqualValues(t, expectedVal1Prio2, updatedVal1.ProposerPriority, "unexpected proposer priority for validator: %v", updatedVal2)
  513. assert.EqualValues(t, expectedVal2Prio2, updatedVal2.ProposerPriority, "unexpected proposer priority for validator: %v", updatedVal2)
  514. // no changes in voting power and both validators have same voting power
  515. // -> proposers should alternate:
  516. oldState := updatedState3
  517. abciResponses = &ABCIResponses{
  518. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  519. }
  520. validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  521. require.NoError(t, err)
  522. oldState, err = updateState(oldState, blockID, &block.Header, abciResponses, validatorUpdates)
  523. assert.NoError(t, err)
  524. expectedVal1Prio2 = 1
  525. expectedVal2Prio2 = -1
  526. expectedVal1Prio = -9
  527. expectedVal2Prio = 9
  528. for i := 0; i < 1000; i++ {
  529. // no validator updates:
  530. abciResponses := &ABCIResponses{
  531. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  532. }
  533. validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  534. require.NoError(t, err)
  535. updatedState, err := updateState(oldState, blockID, &block.Header, abciResponses, validatorUpdates)
  536. assert.NoError(t, err)
  537. // alternate (and cyclic priorities):
  538. assert.NotEqual(t, updatedState.Validators.Proposer.Address, updatedState.NextValidators.Proposer.Address, "iter: %v", i)
  539. assert.Equal(t, oldState.Validators.Proposer.Address, updatedState.NextValidators.Proposer.Address, "iter: %v", i)
  540. _, updatedVal1 = updatedState.NextValidators.GetByAddress(val1PubKey.Address())
  541. _, updatedVal2 = updatedState.NextValidators.GetByAddress(val2PubKey.Address())
  542. if i%2 == 0 {
  543. assert.Equal(t, updatedState.Validators.Proposer.Address, val2PubKey.Address())
  544. assert.Equal(t, expectedVal1Prio, updatedVal1.ProposerPriority) // -19
  545. assert.Equal(t, expectedVal2Prio, updatedVal2.ProposerPriority) // 0
  546. } else {
  547. assert.Equal(t, updatedState.Validators.Proposer.Address, val1PubKey.Address())
  548. assert.Equal(t, expectedVal1Prio2, updatedVal1.ProposerPriority) // -9
  549. assert.Equal(t, expectedVal2Prio2, updatedVal2.ProposerPriority) // -10
  550. }
  551. // update for next iteration:
  552. oldState = updatedState
  553. }
  554. }
  555. func TestLargeGenesisValidator(t *testing.T) {
  556. tearDown, _, state := setupTestCase(t)
  557. defer tearDown(t)
  558. genesisVotingPower := int64(types.MaxTotalVotingPower / 1000)
  559. genesisPubKey := ed25519.GenPrivKey().PubKey()
  560. // fmt.Println("genesis addr: ", genesisPubKey.Address())
  561. genesisVal := &types.Validator{Address: genesisPubKey.Address(), PubKey: genesisPubKey, VotingPower: genesisVotingPower}
  562. // reset state validators to above validator
  563. state.Validators = types.NewValidatorSet([]*types.Validator{genesisVal})
  564. state.NextValidators = state.Validators
  565. require.True(t, len(state.Validators.Validators) == 1)
  566. // update state a few times with no validator updates
  567. // asserts that the single validator's ProposerPrio stays the same
  568. oldState := state
  569. for i := 0; i < 10; i++ {
  570. // no updates:
  571. abciResponses := &ABCIResponses{
  572. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  573. }
  574. validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  575. require.NoError(t, err)
  576. block := makeBlock(oldState, oldState.LastBlockHeight+1)
  577. blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  578. updatedState, err := updateState(oldState, blockID, &block.Header, abciResponses, validatorUpdates)
  579. // no changes in voting power (ProposerPrio += VotingPower == Voting in 1st round; than shiftByAvg == 0,
  580. // than -Total == -Voting)
  581. // -> no change in ProposerPrio (stays zero):
  582. assert.EqualValues(t, oldState.NextValidators, updatedState.NextValidators)
  583. assert.EqualValues(t, 0, updatedState.NextValidators.Proposer.ProposerPriority)
  584. oldState = updatedState
  585. }
  586. // add another validator, do a few iterations (create blocks),
  587. // add more validators with same voting power as the 2nd
  588. // let the genesis validator "unbond",
  589. // see how long it takes until the effect wears off and both begin to alternate
  590. // see: https://github.com/tendermint/tendermint/issues/2960
  591. firstAddedValPubKey := ed25519.GenPrivKey().PubKey()
  592. firstAddedValVotingPower := int64(10)
  593. firstAddedVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(firstAddedValPubKey), Power: firstAddedValVotingPower}
  594. validatorUpdates, err := types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{firstAddedVal})
  595. assert.NoError(t, err)
  596. abciResponses := &ABCIResponses{
  597. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: []abci.ValidatorUpdate{firstAddedVal}},
  598. }
  599. block := makeBlock(oldState, oldState.LastBlockHeight+1)
  600. blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  601. updatedState, err := updateState(oldState, blockID, &block.Header, abciResponses, validatorUpdates)
  602. lastState := updatedState
  603. for i := 0; i < 200; i++ {
  604. // no updates:
  605. abciResponses := &ABCIResponses{
  606. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  607. }
  608. validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  609. require.NoError(t, err)
  610. block := makeBlock(lastState, lastState.LastBlockHeight+1)
  611. blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  612. updatedStateInner, err := updateState(lastState, blockID, &block.Header, abciResponses, validatorUpdates)
  613. lastState = updatedStateInner
  614. }
  615. // set state to last state of above iteration
  616. state = lastState
  617. // set oldState to state before above iteration
  618. oldState = updatedState
  619. _, oldGenesisVal := oldState.NextValidators.GetByAddress(genesisVal.Address)
  620. _, newGenesisVal := state.NextValidators.GetByAddress(genesisVal.Address)
  621. _, addedOldVal := oldState.NextValidators.GetByAddress(firstAddedValPubKey.Address())
  622. _, addedNewVal := state.NextValidators.GetByAddress(firstAddedValPubKey.Address())
  623. // expect large negative proposer priority for both (genesis validator decreased, 2nd validator increased):
  624. assert.True(t, oldGenesisVal.ProposerPriority > newGenesisVal.ProposerPriority)
  625. assert.True(t, addedOldVal.ProposerPriority < addedNewVal.ProposerPriority)
  626. // add 10 validators with the same voting power as the one added directly after genesis:
  627. for i := 0; i < 10; i++ {
  628. addedPubKey := ed25519.GenPrivKey().PubKey()
  629. addedVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(addedPubKey), Power: firstAddedValVotingPower}
  630. validatorUpdates, err := types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{addedVal})
  631. assert.NoError(t, err)
  632. abciResponses := &ABCIResponses{
  633. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: []abci.ValidatorUpdate{addedVal}},
  634. }
  635. block := makeBlock(oldState, oldState.LastBlockHeight+1)
  636. blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  637. state, err = updateState(state, blockID, &block.Header, abciResponses, validatorUpdates)
  638. }
  639. require.Equal(t, 10+2, len(state.NextValidators.Validators))
  640. // remove genesis validator:
  641. removeGenesisVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(genesisPubKey), Power: 0}
  642. abciResponses = &ABCIResponses{
  643. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: []abci.ValidatorUpdate{removeGenesisVal}},
  644. }
  645. block = makeBlock(oldState, oldState.LastBlockHeight+1)
  646. blockID = types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  647. validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  648. require.NoError(t, err)
  649. updatedState, err = updateState(state, blockID, &block.Header, abciResponses, validatorUpdates)
  650. require.NoError(t, err)
  651. // only the first added val (not the genesis val) should be left
  652. assert.Equal(t, 11, len(updatedState.NextValidators.Validators))
  653. // call update state until the effect for the 3rd added validator
  654. // being proposer for a long time after the genesis validator left wears off:
  655. curState := updatedState
  656. count := 0
  657. isProposerUnchanged := true
  658. for isProposerUnchanged {
  659. abciResponses := &ABCIResponses{
  660. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  661. }
  662. validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  663. require.NoError(t, err)
  664. block = makeBlock(curState, curState.LastBlockHeight+1)
  665. blockID = types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  666. curState, err = updateState(curState, blockID, &block.Header, abciResponses, validatorUpdates)
  667. if !bytes.Equal(curState.Validators.Proposer.Address, curState.NextValidators.Proposer.Address) {
  668. isProposerUnchanged = false
  669. }
  670. count++
  671. }
  672. updatedState = curState
  673. // the proposer changes after this number of blocks
  674. firstProposerChangeExpectedAfter := 1
  675. assert.Equal(t, firstProposerChangeExpectedAfter, count)
  676. // store proposers here to see if we see them again in the same order:
  677. numVals := len(updatedState.Validators.Validators)
  678. proposers := make([]*types.Validator, numVals)
  679. for i := 0; i < 100; i++ {
  680. // no updates:
  681. abciResponses := &ABCIResponses{
  682. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  683. }
  684. validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  685. require.NoError(t, err)
  686. block := makeBlock(updatedState, updatedState.LastBlockHeight+1)
  687. blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  688. updatedState, err = updateState(updatedState, blockID, &block.Header, abciResponses, validatorUpdates)
  689. if i > numVals { // expect proposers to cycle through after the first iteration (of numVals blocks):
  690. if proposers[i%numVals] == nil {
  691. proposers[i%numVals] = updatedState.NextValidators.Proposer
  692. } else {
  693. assert.Equal(t, proposers[i%numVals], updatedState.NextValidators.Proposer)
  694. }
  695. }
  696. }
  697. }
  698. func TestStoreLoadValidatorsIncrementsProposerPriority(t *testing.T) {
  699. const valSetSize = 2
  700. tearDown, stateDB, state := setupTestCase(t)
  701. state.Validators = genValSet(valSetSize)
  702. state.NextValidators = state.Validators.CopyIncrementProposerPriority(1)
  703. SaveState(stateDB, state)
  704. defer tearDown(t)
  705. nextHeight := state.LastBlockHeight + 1
  706. v0, err := LoadValidators(stateDB, nextHeight)
  707. assert.Nil(t, err)
  708. acc0 := v0.Validators[0].ProposerPriority
  709. v1, err := LoadValidators(stateDB, nextHeight+1)
  710. assert.Nil(t, err)
  711. acc1 := v1.Validators[0].ProposerPriority
  712. assert.NotEqual(t, acc1, acc0, "expected ProposerPriority value to change between heights")
  713. }
  714. // TestValidatorChangesSaveLoad tests saving and loading a validator set with
  715. // changes.
  716. func TestManyValidatorChangesSaveLoad(t *testing.T) {
  717. const valSetSize = 7
  718. tearDown, stateDB, state := setupTestCase(t)
  719. require.Equal(t, int64(0), state.LastBlockHeight)
  720. state.Validators = genValSet(valSetSize)
  721. state.NextValidators = state.Validators.CopyIncrementProposerPriority(1)
  722. SaveState(stateDB, state)
  723. defer tearDown(t)
  724. _, valOld := state.Validators.GetByIndex(0)
  725. var pubkeyOld = valOld.PubKey
  726. pubkey := ed25519.GenPrivKey().PubKey()
  727. const height = 1
  728. // Swap the first validator with a new one (validator set size stays the same).
  729. header, blockID, responses := makeHeaderPartsResponsesValPubKeyChange(state, height, pubkey)
  730. // Save state etc.
  731. var err error
  732. var validatorUpdates []*types.Validator
  733. validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.EndBlock.ValidatorUpdates)
  734. require.NoError(t, err)
  735. state, err = updateState(state, blockID, &header, responses, validatorUpdates)
  736. require.Nil(t, err)
  737. nextHeight := state.LastBlockHeight + 1
  738. saveValidatorsInfo(stateDB, nextHeight+1, state.LastHeightValidatorsChanged, state.NextValidators)
  739. // Load nextheight, it should be the oldpubkey.
  740. v0, err := LoadValidators(stateDB, nextHeight)
  741. assert.Nil(t, err)
  742. assert.Equal(t, valSetSize, v0.Size())
  743. index, val := v0.GetByAddress(pubkeyOld.Address())
  744. assert.NotNil(t, val)
  745. if index < 0 {
  746. t.Fatal("expected to find old validator")
  747. }
  748. // Load nextheight+1, it should be the new pubkey.
  749. v1, err := LoadValidators(stateDB, nextHeight+1)
  750. assert.Nil(t, err)
  751. assert.Equal(t, valSetSize, v1.Size())
  752. index, val = v1.GetByAddress(pubkey.Address())
  753. assert.NotNil(t, val)
  754. if index < 0 {
  755. t.Fatal("expected to find newly added validator")
  756. }
  757. }
  758. func genValSet(size int) *types.ValidatorSet {
  759. vals := make([]*types.Validator, size)
  760. for i := 0; i < size; i++ {
  761. vals[i] = types.NewValidator(ed25519.GenPrivKey().PubKey(), 10)
  762. }
  763. return types.NewValidatorSet(vals)
  764. }
  765. func TestStateMakeBlock(t *testing.T) {
  766. tearDown, _, state := setupTestCase(t)
  767. defer tearDown(t)
  768. proposerAddress := state.Validators.GetProposer().Address
  769. stateVersion := state.Version.Consensus
  770. block := makeBlock(state, 2)
  771. // test we set some fields
  772. assert.Equal(t, stateVersion, block.Version)
  773. assert.Equal(t, proposerAddress, block.ProposerAddress)
  774. }
  775. // TestConsensusParamsChangesSaveLoad tests saving and loading consensus params
  776. // with changes.
  777. func TestConsensusParamsChangesSaveLoad(t *testing.T) {
  778. tearDown, stateDB, state := setupTestCase(t)
  779. defer tearDown(t)
  780. // Change vals at these heights.
  781. changeHeights := []int64{1, 2, 4, 5, 10, 15, 16, 17, 20}
  782. N := len(changeHeights)
  783. // Each valset is just one validator.
  784. // create list of them.
  785. params := make([]types.ConsensusParams, N+1)
  786. params[0] = state.ConsensusParams
  787. for i := 1; i < N+1; i++ {
  788. params[i] = *types.DefaultConsensusParams()
  789. params[i].BlockSize.MaxBytes += int64(i)
  790. }
  791. // Build the params history by running updateState
  792. // with the right params set for each height.
  793. highestHeight := changeHeights[N-1] + 5
  794. changeIndex := 0
  795. cp := params[changeIndex]
  796. var err error
  797. var validatorUpdates []*types.Validator
  798. for i := int64(1); i < highestHeight; i++ {
  799. // When we get to a change height, use the next params.
  800. if changeIndex < len(changeHeights) && i == changeHeights[changeIndex] {
  801. changeIndex++
  802. cp = params[changeIndex]
  803. }
  804. header, blockID, responses := makeHeaderPartsResponsesParams(state, i, cp)
  805. validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.EndBlock.ValidatorUpdates)
  806. require.NoError(t, err)
  807. state, err = updateState(state, blockID, &header, responses, validatorUpdates)
  808. require.Nil(t, err)
  809. nextHeight := state.LastBlockHeight + 1
  810. saveConsensusParamsInfo(stateDB, nextHeight, state.LastHeightConsensusParamsChanged, state.ConsensusParams)
  811. }
  812. // Make all the test cases by using the same params until after the change.
  813. testCases := make([]paramsChangeTestCase, highestHeight)
  814. changeIndex = 0
  815. cp = params[changeIndex]
  816. for i := int64(1); i < highestHeight+1; i++ {
  817. // We get to the height after a change height use the next pubkey (note
  818. // our counter starts at 0 this time).
  819. if changeIndex < len(changeHeights) && i == changeHeights[changeIndex]+1 {
  820. changeIndex++
  821. cp = params[changeIndex]
  822. }
  823. testCases[i-1] = paramsChangeTestCase{i, cp}
  824. }
  825. for _, testCase := range testCases {
  826. p, err := LoadConsensusParams(stateDB, testCase.height)
  827. assert.Nil(t, err, fmt.Sprintf("expected no err at height %d", testCase.height))
  828. assert.Equal(t, testCase.params, p, fmt.Sprintf(`unexpected consensus params at
  829. height %d`, testCase.height))
  830. }
  831. }
  832. func makeParams(blockBytes, blockGas, evidenceAge int64) types.ConsensusParams {
  833. return types.ConsensusParams{
  834. BlockSize: types.BlockSizeParams{
  835. MaxBytes: blockBytes,
  836. MaxGas: blockGas,
  837. },
  838. Evidence: types.EvidenceParams{
  839. MaxAge: evidenceAge,
  840. },
  841. }
  842. }
  843. func TestApplyUpdates(t *testing.T) {
  844. initParams := makeParams(1, 2, 3)
  845. cases := [...]struct {
  846. init types.ConsensusParams
  847. updates abci.ConsensusParams
  848. expected types.ConsensusParams
  849. }{
  850. 0: {initParams, abci.ConsensusParams{}, initParams},
  851. 1: {initParams, abci.ConsensusParams{}, initParams},
  852. 2: {initParams,
  853. abci.ConsensusParams{
  854. BlockSize: &abci.BlockSizeParams{
  855. MaxBytes: 44,
  856. MaxGas: 55,
  857. },
  858. },
  859. makeParams(44, 55, 3)},
  860. 3: {initParams,
  861. abci.ConsensusParams{
  862. Evidence: &abci.EvidenceParams{
  863. MaxAge: 66,
  864. },
  865. },
  866. makeParams(1, 2, 66)},
  867. }
  868. for i, tc := range cases {
  869. res := tc.init.Update(&(tc.updates))
  870. assert.Equal(t, tc.expected, res, "case %d", i)
  871. }
  872. }
  873. func makeHeaderPartsResponsesValPubKeyChange(state State, height int64,
  874. pubkey crypto.PubKey) (types.Header, types.BlockID, *ABCIResponses) {
  875. block := makeBlock(state, state.LastBlockHeight+1)
  876. abciResponses := &ABCIResponses{
  877. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  878. }
  879. // If the pubkey is new, remove the old and add the new.
  880. _, val := state.NextValidators.GetByIndex(0)
  881. if !bytes.Equal(pubkey.Bytes(), val.PubKey.Bytes()) {
  882. abciResponses.EndBlock = &abci.ResponseEndBlock{
  883. ValidatorUpdates: []abci.ValidatorUpdate{
  884. types.TM2PB.NewValidatorUpdate(val.PubKey, 0),
  885. types.TM2PB.NewValidatorUpdate(pubkey, 10),
  886. },
  887. }
  888. }
  889. return block.Header, types.BlockID{block.Hash(), types.PartSetHeader{}}, abciResponses
  890. }
  891. func makeHeaderPartsResponsesValPowerChange(state State, height int64,
  892. power int64) (types.Header, types.BlockID, *ABCIResponses) {
  893. block := makeBlock(state, state.LastBlockHeight+1)
  894. abciResponses := &ABCIResponses{
  895. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  896. }
  897. // If the pubkey is new, remove the old and add the new.
  898. _, val := state.NextValidators.GetByIndex(0)
  899. if val.VotingPower != power {
  900. abciResponses.EndBlock = &abci.ResponseEndBlock{
  901. ValidatorUpdates: []abci.ValidatorUpdate{
  902. types.TM2PB.NewValidatorUpdate(val.PubKey, power),
  903. },
  904. }
  905. }
  906. return block.Header, types.BlockID{block.Hash(), types.PartSetHeader{}}, abciResponses
  907. }
  908. func makeHeaderPartsResponsesParams(state State, height int64,
  909. params types.ConsensusParams) (types.Header, types.BlockID, *ABCIResponses) {
  910. block := makeBlock(state, state.LastBlockHeight+1)
  911. abciResponses := &ABCIResponses{
  912. EndBlock: &abci.ResponseEndBlock{ConsensusParamUpdates: types.TM2PB.ConsensusParams(&params)},
  913. }
  914. return block.Header, types.BlockID{block.Hash(), types.PartSetHeader{}}, abciResponses
  915. }
  916. type paramsChangeTestCase struct {
  917. height int64
  918. params types.ConsensusParams
  919. }