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.

1034 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
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. votePower := int64(cmn.RandInt() % maxPower)
  285. totalVotePower += votePower
  286. privVal := types.NewMockPV()
  287. pubKey := privVal.GetPubKey()
  288. val := types.NewValidator(pubKey, votePower)
  289. val.ProposerPriority = cmn.RandInt64()
  290. vals[j] = val
  291. }
  292. valSet := types.NewValidatorSet(vals)
  293. valSet.RescalePriorities(totalVotePower)
  294. testProposerFreq(t, i, valSet)
  295. }
  296. }
  297. // new val set with given powers and random initial priorities
  298. func genValSetWithPowers(powers []int64) *types.ValidatorSet {
  299. size := len(powers)
  300. vals := make([]*types.Validator, size)
  301. totalVotePower := int64(0)
  302. for i := 0; i < size; i++ {
  303. totalVotePower += powers[i]
  304. val := types.NewValidator(ed25519.GenPrivKey().PubKey(), powers[i])
  305. val.ProposerPriority = cmn.RandInt64()
  306. vals[i] = val
  307. }
  308. valSet := types.NewValidatorSet(vals)
  309. valSet.RescalePriorities(totalVotePower)
  310. return valSet
  311. }
  312. // test a proposer appears as frequently as expected
  313. func testProposerFreq(t *testing.T, caseNum int, valSet *types.ValidatorSet) {
  314. N := valSet.Size()
  315. totalPower := valSet.TotalVotingPower()
  316. // run the proposer selection and track frequencies
  317. runMult := 1
  318. runs := int(totalPower) * runMult
  319. freqs := make([]int, N)
  320. for i := 0; i < runs; i++ {
  321. prop := valSet.GetProposer()
  322. idx, _ := valSet.GetByAddress(prop.Address)
  323. freqs[idx] += 1
  324. valSet.IncrementProposerPriority(1)
  325. }
  326. // assert frequencies match expected (max off by 1)
  327. for i, freq := range freqs {
  328. _, val := valSet.GetByIndex(i)
  329. expectFreq := int(val.VotingPower) * runMult
  330. gotFreq := freq
  331. abs := int(math.Abs(float64(expectFreq - gotFreq)))
  332. // max bound on expected vs seen freq was proven
  333. // to be 1 for the 2 validator case in
  334. // https://github.com/cwgoes/tm-proposer-idris
  335. // and inferred to generalize to N-1
  336. bound := N - 1
  337. require.True(t, abs <= bound, fmt.Sprintf("Case %d val %d (%d): got %d, expected %d", caseNum, i, N, gotFreq, expectFreq))
  338. }
  339. }
  340. // TestProposerPriorityDoesNotGetResetToZero assert that we preserve accum when calling updateState
  341. // see https://github.com/tendermint/tendermint/issues/2718
  342. func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) {
  343. tearDown, _, state := setupTestCase(t)
  344. defer tearDown(t)
  345. val1VotingPower := int64(10)
  346. val1PubKey := ed25519.GenPrivKey().PubKey()
  347. val1 := &types.Validator{Address: val1PubKey.Address(), PubKey: val1PubKey, VotingPower: val1VotingPower}
  348. state.Validators = types.NewValidatorSet([]*types.Validator{val1})
  349. state.NextValidators = state.Validators
  350. // NewValidatorSet calls IncrementProposerPriority but uses on a copy of val1
  351. assert.EqualValues(t, 0, val1.ProposerPriority)
  352. block := makeBlock(state, state.LastBlockHeight+1)
  353. blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  354. abciResponses := &ABCIResponses{
  355. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  356. }
  357. validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  358. require.NoError(t, err)
  359. updatedState, err := updateState(state, blockID, &block.Header, abciResponses, validatorUpdates)
  360. assert.NoError(t, err)
  361. curTotal := val1VotingPower
  362. // one increment step and one validator: 0 + power - total_power == 0
  363. assert.Equal(t, 0+val1VotingPower-curTotal, updatedState.NextValidators.Validators[0].ProposerPriority)
  364. // add a validator
  365. val2PubKey := ed25519.GenPrivKey().PubKey()
  366. val2VotingPower := int64(100)
  367. updateAddVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(val2PubKey), Power: val2VotingPower}
  368. validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateAddVal})
  369. assert.NoError(t, err)
  370. updatedState2, err := updateState(updatedState, blockID, &block.Header, abciResponses, validatorUpdates)
  371. assert.NoError(t, err)
  372. require.Equal(t, len(updatedState2.NextValidators.Validators), 2)
  373. _, updatedVal1 := updatedState2.NextValidators.GetByAddress(val1PubKey.Address())
  374. _, addedVal2 := updatedState2.NextValidators.GetByAddress(val2PubKey.Address())
  375. // adding a validator should not lead to a ProposerPriority equal to zero (unless the combination of averaging and
  376. // incrementing would cause so; which is not the case here)
  377. totalPowerBefore2 := curTotal
  378. // while adding we compute prio == -1.125 * total:
  379. wantVal2ProposerPrio := -(totalPowerBefore2 + (totalPowerBefore2 >> 3))
  380. wantVal2ProposerPrio = wantVal2ProposerPrio + val2VotingPower
  381. // then increment:
  382. totalPowerAfter := val1VotingPower + val2VotingPower
  383. // mostest:
  384. wantVal2ProposerPrio = wantVal2ProposerPrio - totalPowerAfter
  385. avg := big.NewInt(0).Add(big.NewInt(val1VotingPower), big.NewInt(wantVal2ProposerPrio))
  386. avg.Div(avg, big.NewInt(2))
  387. wantVal2ProposerPrio = wantVal2ProposerPrio - avg.Int64()
  388. wantVal1Prio := 0 + val1VotingPower - avg.Int64()
  389. assert.Equal(t, wantVal1Prio, updatedVal1.ProposerPriority)
  390. assert.Equal(t, wantVal2ProposerPrio, addedVal2.ProposerPriority)
  391. // Updating a validator does not reset the ProposerPriority to zero:
  392. updatedVotingPowVal2 := int64(1)
  393. updateVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(val2PubKey), Power: updatedVotingPowVal2}
  394. validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateVal})
  395. assert.NoError(t, err)
  396. // this will cause the diff of priorities (31)
  397. // to be larger than threshold == 2*totalVotingPower (22):
  398. updatedState3, err := updateState(updatedState2, blockID, &block.Header, abciResponses, validatorUpdates)
  399. assert.NoError(t, err)
  400. require.Equal(t, len(updatedState3.NextValidators.Validators), 2)
  401. _, prevVal1 := updatedState3.Validators.GetByAddress(val1PubKey.Address())
  402. _, updatedVal2 := updatedState3.NextValidators.GetByAddress(val2PubKey.Address())
  403. // divide previous priorities by 2 == CEIL(31/22) as diff > threshold:
  404. expectedVal1PrioBeforeAvg := prevVal1.ProposerPriority/2 + prevVal1.VotingPower
  405. wantVal2ProposerPrio = wantVal2ProposerPrio/2 + updatedVotingPowVal2
  406. // val1 will be proposer:
  407. total := val1VotingPower + updatedVotingPowVal2
  408. expectedVal1PrioBeforeAvg = expectedVal1PrioBeforeAvg - total
  409. avgI64 := (wantVal2ProposerPrio + expectedVal1PrioBeforeAvg) / 2
  410. wantVal2ProposerPrio = wantVal2ProposerPrio - avgI64
  411. wantVal1Prio = expectedVal1PrioBeforeAvg - avgI64
  412. assert.Equal(t, wantVal2ProposerPrio, updatedVal2.ProposerPriority)
  413. _, updatedVal1 = updatedState3.NextValidators.GetByAddress(val1PubKey.Address())
  414. assert.Equal(t, wantVal1Prio, updatedVal1.ProposerPriority)
  415. }
  416. func TestProposerPriorityProposerAlternates(t *testing.T) {
  417. // Regression test that would fail if the inner workings of
  418. // IncrementProposerPriority change.
  419. // Additionally, make sure that same power validators alternate if both
  420. // have the same voting power (and the 2nd was added later).
  421. tearDown, _, state := setupTestCase(t)
  422. defer tearDown(t)
  423. val1VotingPower := int64(10)
  424. val1PubKey := ed25519.GenPrivKey().PubKey()
  425. val1 := &types.Validator{Address: val1PubKey.Address(), PubKey: val1PubKey, VotingPower: val1VotingPower}
  426. // reset state validators to above validator
  427. state.Validators = types.NewValidatorSet([]*types.Validator{val1})
  428. state.NextValidators = state.Validators
  429. // we only have one validator:
  430. assert.Equal(t, val1PubKey.Address(), state.Validators.Proposer.Address)
  431. block := makeBlock(state, state.LastBlockHeight+1)
  432. blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  433. // no updates:
  434. abciResponses := &ABCIResponses{
  435. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  436. }
  437. validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  438. require.NoError(t, err)
  439. updatedState, err := updateState(state, blockID, &block.Header, abciResponses, validatorUpdates)
  440. assert.NoError(t, err)
  441. // 0 + 10 (initial prio) - 10 (avg) - 10 (mostest - total) = -10
  442. totalPower := val1VotingPower
  443. wantVal1Prio := 0 + val1VotingPower - totalPower
  444. assert.Equal(t, wantVal1Prio, updatedState.NextValidators.Validators[0].ProposerPriority)
  445. assert.Equal(t, val1PubKey.Address(), updatedState.NextValidators.Proposer.Address)
  446. // add a validator with the same voting power as the first
  447. val2PubKey := ed25519.GenPrivKey().PubKey()
  448. updateAddVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(val2PubKey), Power: val1VotingPower}
  449. validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateAddVal})
  450. assert.NoError(t, err)
  451. updatedState2, err := updateState(updatedState, blockID, &block.Header, abciResponses, validatorUpdates)
  452. assert.NoError(t, err)
  453. require.Equal(t, len(updatedState2.NextValidators.Validators), 2)
  454. assert.Equal(t, updatedState2.Validators, updatedState.NextValidators)
  455. // val1 will still be proposer as val2 just got added:
  456. assert.Equal(t, val1PubKey.Address(), updatedState.NextValidators.Proposer.Address)
  457. assert.Equal(t, updatedState2.Validators.Proposer.Address, updatedState2.NextValidators.Proposer.Address)
  458. assert.Equal(t, updatedState2.Validators.Proposer.Address, val1PubKey.Address())
  459. assert.Equal(t, updatedState2.NextValidators.Proposer.Address, val1PubKey.Address())
  460. _, updatedVal1 := updatedState2.NextValidators.GetByAddress(val1PubKey.Address())
  461. _, oldVal1 := updatedState2.Validators.GetByAddress(val1PubKey.Address())
  462. _, updatedVal2 := updatedState2.NextValidators.GetByAddress(val2PubKey.Address())
  463. totalPower = val1VotingPower // no update
  464. v2PrioWhenAddedVal2 := -(totalPower + (totalPower >> 3))
  465. v2PrioWhenAddedVal2 = v2PrioWhenAddedVal2 + val1VotingPower // -11 + 10 == -1
  466. v1PrioWhenAddedVal2 := oldVal1.ProposerPriority + val1VotingPower // -10 + 10 == 0
  467. totalPower = 2 * val1VotingPower // now we have to validators with that power
  468. v1PrioWhenAddedVal2 = v1PrioWhenAddedVal2 - totalPower // mostest
  469. // have to express the AVG in big.Ints as -1/2 == -1 in big.Int while -1/2 == 0 in int64
  470. avgSum := big.NewInt(0).Add(big.NewInt(v2PrioWhenAddedVal2), big.NewInt(v1PrioWhenAddedVal2))
  471. avg := avgSum.Div(avgSum, big.NewInt(2))
  472. expectedVal2Prio := v2PrioWhenAddedVal2 - avg.Int64()
  473. totalPower = 2 * val1VotingPower // 10 + 10
  474. expectedVal1Prio := oldVal1.ProposerPriority + val1VotingPower - avg.Int64() - totalPower
  475. // val1's ProposerPriority story: -10 (see above) + 10 (voting pow) - (-1) (avg) - 20 (total) == -19
  476. assert.EqualValues(t, expectedVal1Prio, updatedVal1.ProposerPriority)
  477. // val2 prio when added: -(totalVotingPower + (totalVotingPower >> 3)) == -11
  478. // -> -11 + 10 (voting power) - (-1) (avg) == 0
  479. assert.EqualValues(t, expectedVal2Prio, updatedVal2.ProposerPriority, "unexpected proposer priority for validator: %v", updatedVal2)
  480. validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  481. require.NoError(t, err)
  482. updatedState3, err := updateState(updatedState2, blockID, &block.Header, abciResponses, validatorUpdates)
  483. assert.NoError(t, err)
  484. // proposer changes from now on (every iteration) as long as there are no changes in the validator set:
  485. assert.NotEqual(t, updatedState3.Validators.Proposer.Address, updatedState3.NextValidators.Proposer.Address)
  486. assert.Equal(t, updatedState3.Validators, updatedState2.NextValidators)
  487. _, updatedVal1 = updatedState3.NextValidators.GetByAddress(val1PubKey.Address())
  488. _, oldVal1 = updatedState3.Validators.GetByAddress(val1PubKey.Address())
  489. _, updatedVal2 = updatedState3.NextValidators.GetByAddress(val2PubKey.Address())
  490. _, oldVal2 := updatedState3.Validators.GetByAddress(val2PubKey.Address())
  491. // val2 will be proposer:
  492. assert.Equal(t, val2PubKey.Address(), updatedState3.NextValidators.Proposer.Address)
  493. // check if expected proposer prio is matched:
  494. expectedVal1Prio2 := oldVal1.ProposerPriority + val1VotingPower
  495. expectedVal2Prio2 := oldVal2.ProposerPriority + val1VotingPower - totalPower
  496. avgSum = big.NewInt(expectedVal1Prio + expectedVal2Prio)
  497. avg = avgSum.Div(avgSum, big.NewInt(2))
  498. expectedVal1Prio -= avg.Int64()
  499. expectedVal2Prio -= avg.Int64()
  500. // -19 + 10 - 0 (avg) == -9
  501. assert.EqualValues(t, expectedVal1Prio2, updatedVal1.ProposerPriority, "unexpected proposer priority for validator: %v", updatedVal2)
  502. // 0 + 10 - 0 (avg) - 20 (total) == -10
  503. assert.EqualValues(t, expectedVal2Prio2, updatedVal2.ProposerPriority, "unexpected proposer priority for validator: %v", updatedVal2)
  504. // no changes in voting power and both validators have same voting power
  505. // -> proposers should alternate:
  506. oldState := updatedState3
  507. for i := 0; i < 1000; i++ {
  508. // no validator updates:
  509. abciResponses := &ABCIResponses{
  510. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  511. }
  512. validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  513. require.NoError(t, err)
  514. updatedState, err := updateState(oldState, blockID, &block.Header, abciResponses, validatorUpdates)
  515. assert.NoError(t, err)
  516. // alternate (and cyclic priorities):
  517. assert.NotEqual(t, updatedState.Validators.Proposer.Address, updatedState.NextValidators.Proposer.Address, "iter: %v", i)
  518. assert.Equal(t, oldState.Validators.Proposer.Address, updatedState.NextValidators.Proposer.Address, "iter: %v", i)
  519. _, updatedVal1 = updatedState.NextValidators.GetByAddress(val1PubKey.Address())
  520. _, updatedVal2 = updatedState.NextValidators.GetByAddress(val2PubKey.Address())
  521. if i%2 == 0 {
  522. assert.Equal(t, updatedState.Validators.Proposer.Address, val2PubKey.Address())
  523. assert.Equal(t, expectedVal1Prio, updatedVal1.ProposerPriority) // -19
  524. assert.Equal(t, expectedVal2Prio, updatedVal2.ProposerPriority) // 0
  525. } else {
  526. assert.Equal(t, updatedState.Validators.Proposer.Address, val1PubKey.Address())
  527. assert.Equal(t, expectedVal1Prio2, updatedVal1.ProposerPriority) // -9
  528. assert.Equal(t, expectedVal2Prio2, updatedVal2.ProposerPriority) // -10
  529. }
  530. // update for next iteration:
  531. oldState = updatedState
  532. }
  533. }
  534. func TestLargeGenesisValidator(t *testing.T) {
  535. tearDown, _, state := setupTestCase(t)
  536. defer tearDown(t)
  537. genesisVotingPower := int64(types.MaxTotalVotingPower / 1000)
  538. genesisPubKey := ed25519.GenPrivKey().PubKey()
  539. // fmt.Println("genesis addr: ", genesisPubKey.Address())
  540. genesisVal := &types.Validator{Address: genesisPubKey.Address(), PubKey: genesisPubKey, VotingPower: genesisVotingPower}
  541. // reset state validators to above validator
  542. state.Validators = types.NewValidatorSet([]*types.Validator{genesisVal})
  543. state.NextValidators = state.Validators
  544. require.True(t, len(state.Validators.Validators) == 1)
  545. // update state a few times with no validator updates
  546. // asserts that the single validator's ProposerPrio stays the same
  547. oldState := state
  548. for i := 0; i < 10; i++ {
  549. // no updates:
  550. abciResponses := &ABCIResponses{
  551. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  552. }
  553. validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  554. require.NoError(t, err)
  555. block := makeBlock(oldState, oldState.LastBlockHeight+1)
  556. blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  557. updatedState, err := updateState(oldState, blockID, &block.Header, abciResponses, validatorUpdates)
  558. // no changes in voting power (ProposerPrio += VotingPower == Voting in 1st round; than shiftByAvg == 0,
  559. // than -Total == -Voting)
  560. // -> no change in ProposerPrio (stays zero):
  561. assert.EqualValues(t, oldState.NextValidators, updatedState.NextValidators)
  562. assert.EqualValues(t, 0, updatedState.NextValidators.Proposer.ProposerPriority)
  563. oldState = updatedState
  564. }
  565. // add another validator, do a few iterations (create blocks),
  566. // add more validators with same voting power as the 2nd
  567. // let the genesis validator "unbond",
  568. // see how long it takes until the effect wears off and both begin to alternate
  569. // see: https://github.com/tendermint/tendermint/issues/2960
  570. firstAddedValPubKey := ed25519.GenPrivKey().PubKey()
  571. firstAddedValVotingPower := int64(10)
  572. firstAddedVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(firstAddedValPubKey), Power: firstAddedValVotingPower}
  573. validatorUpdates, err := types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{firstAddedVal})
  574. assert.NoError(t, err)
  575. abciResponses := &ABCIResponses{
  576. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: []abci.ValidatorUpdate{firstAddedVal}},
  577. }
  578. block := makeBlock(oldState, oldState.LastBlockHeight+1)
  579. blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  580. updatedState, err := updateState(oldState, blockID, &block.Header, abciResponses, validatorUpdates)
  581. lastState := updatedState
  582. for i := 0; i < 200; i++ {
  583. // no updates:
  584. abciResponses := &ABCIResponses{
  585. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  586. }
  587. validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  588. require.NoError(t, err)
  589. block := makeBlock(lastState, lastState.LastBlockHeight+1)
  590. blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  591. updatedStateInner, err := updateState(lastState, blockID, &block.Header, abciResponses, validatorUpdates)
  592. lastState = updatedStateInner
  593. }
  594. // set state to last state of above iteration
  595. state = lastState
  596. // set oldState to state before above iteration
  597. oldState = updatedState
  598. _, oldGenesisVal := oldState.NextValidators.GetByAddress(genesisVal.Address)
  599. _, newGenesisVal := state.NextValidators.GetByAddress(genesisVal.Address)
  600. _, addedOldVal := oldState.NextValidators.GetByAddress(firstAddedValPubKey.Address())
  601. _, addedNewVal := state.NextValidators.GetByAddress(firstAddedValPubKey.Address())
  602. // expect large negative proposer priority for both (genesis validator decreased, 2nd validator increased):
  603. assert.True(t, oldGenesisVal.ProposerPriority > newGenesisVal.ProposerPriority)
  604. assert.True(t, addedOldVal.ProposerPriority < addedNewVal.ProposerPriority)
  605. // add 10 validators with the same voting power as the one added directly after genesis:
  606. for i := 0; i < 10; i++ {
  607. addedPubKey := ed25519.GenPrivKey().PubKey()
  608. addedVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(addedPubKey), Power: firstAddedValVotingPower}
  609. validatorUpdates, err := types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{addedVal})
  610. assert.NoError(t, err)
  611. abciResponses := &ABCIResponses{
  612. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: []abci.ValidatorUpdate{addedVal}},
  613. }
  614. block := makeBlock(oldState, oldState.LastBlockHeight+1)
  615. blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  616. state, err = updateState(state, blockID, &block.Header, abciResponses, validatorUpdates)
  617. }
  618. require.Equal(t, 10+2, len(state.NextValidators.Validators))
  619. // remove genesis validator:
  620. removeGenesisVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(genesisPubKey), Power: 0}
  621. abciResponses = &ABCIResponses{
  622. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: []abci.ValidatorUpdate{removeGenesisVal}},
  623. }
  624. block = makeBlock(oldState, oldState.LastBlockHeight+1)
  625. blockID = types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  626. validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  627. require.NoError(t, err)
  628. updatedState, err = updateState(state, blockID, &block.Header, abciResponses, validatorUpdates)
  629. require.NoError(t, err)
  630. // only the first added val (not the genesis val) should be left
  631. assert.Equal(t, 11, len(updatedState.NextValidators.Validators))
  632. // call update state until the effect for the 3rd added validator
  633. // being proposer for a long time after the genesis validator left wears off:
  634. curState := updatedState
  635. count := 0
  636. isProposerUnchanged := true
  637. for isProposerUnchanged {
  638. abciResponses := &ABCIResponses{
  639. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  640. }
  641. validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  642. require.NoError(t, err)
  643. block = makeBlock(curState, curState.LastBlockHeight+1)
  644. blockID = types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  645. curState, err = updateState(curState, blockID, &block.Header, abciResponses, validatorUpdates)
  646. if !bytes.Equal(curState.Validators.Proposer.Address, curState.NextValidators.Proposer.Address) {
  647. isProposerUnchanged = false
  648. }
  649. count++
  650. }
  651. updatedState = curState
  652. // the proposer changes after this number of blocks
  653. firstProposerChangeExpectedAfter := 1
  654. assert.Equal(t, firstProposerChangeExpectedAfter, count)
  655. // store proposers here to see if we see them again in the same order:
  656. numVals := len(updatedState.Validators.Validators)
  657. proposers := make([]*types.Validator, numVals)
  658. for i := 0; i < 100; i++ {
  659. // no updates:
  660. abciResponses := &ABCIResponses{
  661. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  662. }
  663. validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
  664. require.NoError(t, err)
  665. block := makeBlock(updatedState, updatedState.LastBlockHeight+1)
  666. blockID := types.BlockID{block.Hash(), block.MakePartSet(testPartSize).Header()}
  667. updatedState, err = updateState(updatedState, blockID, &block.Header, abciResponses, validatorUpdates)
  668. if i > numVals { // expect proposers to cycle through after the first iteration (of numVals blocks):
  669. if proposers[i%numVals] == nil {
  670. proposers[i%numVals] = updatedState.NextValidators.Proposer
  671. } else {
  672. assert.Equal(t, proposers[i%numVals], updatedState.NextValidators.Proposer)
  673. }
  674. }
  675. }
  676. }
  677. func TestStoreLoadValidatorsIncrementsProposerPriority(t *testing.T) {
  678. const valSetSize = 2
  679. tearDown, stateDB, state := setupTestCase(t)
  680. state.Validators = genValSet(valSetSize)
  681. state.NextValidators = state.Validators.CopyIncrementProposerPriority(1)
  682. SaveState(stateDB, state)
  683. defer tearDown(t)
  684. nextHeight := state.LastBlockHeight + 1
  685. v0, err := LoadValidators(stateDB, nextHeight)
  686. assert.Nil(t, err)
  687. acc0 := v0.Validators[0].ProposerPriority
  688. v1, err := LoadValidators(stateDB, nextHeight+1)
  689. assert.Nil(t, err)
  690. acc1 := v1.Validators[0].ProposerPriority
  691. assert.NotEqual(t, acc1, acc0, "expected ProposerPriority value to change between heights")
  692. }
  693. // TestValidatorChangesSaveLoad tests saving and loading a validator set with
  694. // changes.
  695. func TestManyValidatorChangesSaveLoad(t *testing.T) {
  696. const valSetSize = 7
  697. tearDown, stateDB, state := setupTestCase(t)
  698. require.Equal(t, int64(0), state.LastBlockHeight)
  699. state.Validators = genValSet(valSetSize)
  700. state.NextValidators = state.Validators.CopyIncrementProposerPriority(1)
  701. SaveState(stateDB, state)
  702. defer tearDown(t)
  703. _, valOld := state.Validators.GetByIndex(0)
  704. var pubkeyOld = valOld.PubKey
  705. pubkey := ed25519.GenPrivKey().PubKey()
  706. const height = 1
  707. // Swap the first validator with a new one (validator set size stays the same).
  708. header, blockID, responses := makeHeaderPartsResponsesValPubKeyChange(state, height, pubkey)
  709. // Save state etc.
  710. var err error
  711. var validatorUpdates []*types.Validator
  712. validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.EndBlock.ValidatorUpdates)
  713. require.NoError(t, err)
  714. state, err = updateState(state, blockID, &header, responses, validatorUpdates)
  715. require.Nil(t, err)
  716. nextHeight := state.LastBlockHeight + 1
  717. saveValidatorsInfo(stateDB, nextHeight+1, state.LastHeightValidatorsChanged, state.NextValidators)
  718. // Load nextheight, it should be the oldpubkey.
  719. v0, err := LoadValidators(stateDB, nextHeight)
  720. assert.Nil(t, err)
  721. assert.Equal(t, valSetSize, v0.Size())
  722. index, val := v0.GetByAddress(pubkeyOld.Address())
  723. assert.NotNil(t, val)
  724. if index < 0 {
  725. t.Fatal("expected to find old validator")
  726. }
  727. // Load nextheight+1, it should be the new pubkey.
  728. v1, err := LoadValidators(stateDB, nextHeight+1)
  729. assert.Nil(t, err)
  730. assert.Equal(t, valSetSize, v1.Size())
  731. index, val = v1.GetByAddress(pubkey.Address())
  732. assert.NotNil(t, val)
  733. if index < 0 {
  734. t.Fatal("expected to find newly added validator")
  735. }
  736. }
  737. func genValSet(size int) *types.ValidatorSet {
  738. vals := make([]*types.Validator, size)
  739. for i := 0; i < size; i++ {
  740. vals[i] = types.NewValidator(ed25519.GenPrivKey().PubKey(), 10)
  741. }
  742. return types.NewValidatorSet(vals)
  743. }
  744. func TestStateMakeBlock(t *testing.T) {
  745. tearDown, _, state := setupTestCase(t)
  746. defer tearDown(t)
  747. proposerAddress := state.Validators.GetProposer().Address
  748. stateVersion := state.Version.Consensus
  749. block := makeBlock(state, 2)
  750. // test we set some fields
  751. assert.Equal(t, stateVersion, block.Version)
  752. assert.Equal(t, proposerAddress, block.ProposerAddress)
  753. }
  754. // TestConsensusParamsChangesSaveLoad tests saving and loading consensus params
  755. // with changes.
  756. func TestConsensusParamsChangesSaveLoad(t *testing.T) {
  757. tearDown, stateDB, state := setupTestCase(t)
  758. defer tearDown(t)
  759. // Change vals at these heights.
  760. changeHeights := []int64{1, 2, 4, 5, 10, 15, 16, 17, 20}
  761. N := len(changeHeights)
  762. // Each valset is just one validator.
  763. // create list of them.
  764. params := make([]types.ConsensusParams, N+1)
  765. params[0] = state.ConsensusParams
  766. for i := 1; i < N+1; i++ {
  767. params[i] = *types.DefaultConsensusParams()
  768. params[i].BlockSize.MaxBytes += int64(i)
  769. }
  770. // Build the params history by running updateState
  771. // with the right params set for each height.
  772. highestHeight := changeHeights[N-1] + 5
  773. changeIndex := 0
  774. cp := params[changeIndex]
  775. var err error
  776. var validatorUpdates []*types.Validator
  777. for i := int64(1); i < highestHeight; i++ {
  778. // When we get to a change height, use the next params.
  779. if changeIndex < len(changeHeights) && i == changeHeights[changeIndex] {
  780. changeIndex++
  781. cp = params[changeIndex]
  782. }
  783. header, blockID, responses := makeHeaderPartsResponsesParams(state, i, cp)
  784. validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.EndBlock.ValidatorUpdates)
  785. require.NoError(t, err)
  786. state, err = updateState(state, blockID, &header, responses, validatorUpdates)
  787. require.Nil(t, err)
  788. nextHeight := state.LastBlockHeight + 1
  789. saveConsensusParamsInfo(stateDB, nextHeight, state.LastHeightConsensusParamsChanged, state.ConsensusParams)
  790. }
  791. // Make all the test cases by using the same params until after the change.
  792. testCases := make([]paramsChangeTestCase, highestHeight)
  793. changeIndex = 0
  794. cp = params[changeIndex]
  795. for i := int64(1); i < highestHeight+1; i++ {
  796. // We get to the height after a change height use the next pubkey (note
  797. // our counter starts at 0 this time).
  798. if changeIndex < len(changeHeights) && i == changeHeights[changeIndex]+1 {
  799. changeIndex++
  800. cp = params[changeIndex]
  801. }
  802. testCases[i-1] = paramsChangeTestCase{i, cp}
  803. }
  804. for _, testCase := range testCases {
  805. p, err := LoadConsensusParams(stateDB, testCase.height)
  806. assert.Nil(t, err, fmt.Sprintf("expected no err at height %d", testCase.height))
  807. assert.Equal(t, testCase.params, p, fmt.Sprintf(`unexpected consensus params at
  808. height %d`, testCase.height))
  809. }
  810. }
  811. func makeParams(blockBytes, blockGas, evidenceAge int64) types.ConsensusParams {
  812. return types.ConsensusParams{
  813. BlockSize: types.BlockSizeParams{
  814. MaxBytes: blockBytes,
  815. MaxGas: blockGas,
  816. },
  817. Evidence: types.EvidenceParams{
  818. MaxAge: evidenceAge,
  819. },
  820. }
  821. }
  822. func pk() []byte {
  823. return ed25519.GenPrivKey().PubKey().Bytes()
  824. }
  825. func TestApplyUpdates(t *testing.T) {
  826. initParams := makeParams(1, 2, 3)
  827. cases := [...]struct {
  828. init types.ConsensusParams
  829. updates abci.ConsensusParams
  830. expected types.ConsensusParams
  831. }{
  832. 0: {initParams, abci.ConsensusParams{}, initParams},
  833. 1: {initParams, abci.ConsensusParams{}, initParams},
  834. 2: {initParams,
  835. abci.ConsensusParams{
  836. BlockSize: &abci.BlockSizeParams{
  837. MaxBytes: 44,
  838. MaxGas: 55,
  839. },
  840. },
  841. makeParams(44, 55, 3)},
  842. 3: {initParams,
  843. abci.ConsensusParams{
  844. Evidence: &abci.EvidenceParams{
  845. MaxAge: 66,
  846. },
  847. },
  848. makeParams(1, 2, 66)},
  849. }
  850. for i, tc := range cases {
  851. res := tc.init.Update(&(tc.updates))
  852. assert.Equal(t, tc.expected, res, "case %d", i)
  853. }
  854. }
  855. func makeHeaderPartsResponsesValPubKeyChange(state State, height int64,
  856. pubkey crypto.PubKey) (types.Header, types.BlockID, *ABCIResponses) {
  857. block := makeBlock(state, state.LastBlockHeight+1)
  858. abciResponses := &ABCIResponses{
  859. EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
  860. }
  861. // If the pubkey is new, remove the old and add the new.
  862. _, val := state.NextValidators.GetByIndex(0)
  863. if !bytes.Equal(pubkey.Bytes(), val.PubKey.Bytes()) {
  864. abciResponses.EndBlock = &abci.ResponseEndBlock{
  865. ValidatorUpdates: []abci.ValidatorUpdate{
  866. types.TM2PB.NewValidatorUpdate(val.PubKey, 0),
  867. types.TM2PB.NewValidatorUpdate(pubkey, 10),
  868. },
  869. }
  870. }
  871. return block.Header, types.BlockID{block.Hash(), types.PartSetHeader{}}, abciResponses
  872. }
  873. func makeHeaderPartsResponsesValPowerChange(state State, height int64,
  874. power int64) (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 val.VotingPower != power {
  882. abciResponses.EndBlock = &abci.ResponseEndBlock{
  883. ValidatorUpdates: []abci.ValidatorUpdate{
  884. types.TM2PB.NewValidatorUpdate(val.PubKey, power),
  885. },
  886. }
  887. }
  888. return block.Header, types.BlockID{block.Hash(), types.PartSetHeader{}}, abciResponses
  889. }
  890. func makeHeaderPartsResponsesParams(state State, height int64,
  891. params types.ConsensusParams) (types.Header, types.BlockID, *ABCIResponses) {
  892. block := makeBlock(state, state.LastBlockHeight+1)
  893. abciResponses := &ABCIResponses{
  894. EndBlock: &abci.ResponseEndBlock{ConsensusParamUpdates: types.TM2PB.ConsensusParams(&params)},
  895. }
  896. return block.Header, types.BlockID{block.Hash(), types.PartSetHeader{}}, abciResponses
  897. }
  898. type paramsChangeTestCase struct {
  899. height int64
  900. params types.ConsensusParams
  901. }