state: Use last height changed if validator set is empty (#3560)

What happened:

New code was supposed to fall back to last height changed when/if it
failed to find validators at checkpoint height (to make release
non-breaking).

But because we did not check if validator set is empty, the fall back
logic was never executed => resulting in LoadValidators returning an
empty validator set for cases where `lastStoredHeight` is checkpoint
height (i.e. almost all heights if the application does not change
validator set often).

How it was found:

one of our users - @sunboshan reported a bug here
https://github.com/tendermint/tendermint/pull/3537#issuecomment-482711833

* use last height changed in validator set is empty
* add a changelog entry
This commit is contained in:
Anton Kaliaev
2019-04-15 18:53:38 +04:00
committed by Alexander Simmerl
parent f2119c35de
commit 50b87c3445
3 changed files with 28 additions and 11 deletions

View File

@@ -193,7 +193,7 @@ func LoadValidators(db dbm.DB, height int64) (*types.ValidatorSet, error) {
if valInfo.ValidatorSet == nil {
lastStoredHeight := lastStoredHeightFor(height, valInfo.LastHeightChanged)
valInfo2 := loadValidatorsInfo(db, lastStoredHeight)
if valInfo2 == nil {
if valInfo2 == nil || valInfo2.ValidatorSet == nil {
// TODO (melekes): remove the below if condition in the 0.33 major
// release and just panic. Old chains might panic otherwise if they
// haven't saved validators at intermediate (%valSetCheckpointInterval)
@@ -201,7 +201,7 @@ func LoadValidators(db dbm.DB, height int64) (*types.ValidatorSet, error) {
// https://github.com/tendermint/tendermint/issues/3543
valInfo2 = loadValidatorsInfo(db, valInfo.LastHeightChanged)
lastStoredHeight = valInfo.LastHeightChanged
if valInfo2 == nil {
if valInfo2 == nil || valInfo2.ValidatorSet == nil {
panic(
fmt.Sprintf("Couldn't find validators at height %d (height %d was originally requested)",
lastStoredHeight,