diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 6692088da..352742fbb 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -3,7 +3,7 @@ \*\* Special thanks to external contributors on this release: -@erikgrinaker, @PSalant726 +@erikgrinaker, @PSalant726, @gchaincl Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermint). @@ -72,3 +72,4 @@ program](https://hackerone.com/tendermint). - [rpc/lib][\#4051](https://github.com/tendermint/tendermint/pull/4131) Fix RPC client, which was previously resolving https protocol to http (@yenkhoon) - [rpc][\#4141](https://github.com/tendermint/tendermint/pull/4141) JSONRPCClient: validate that Response.ID matches Request.ID - [rpc][\#4141](https://github.com/tendermint/tendermint/pull/4141) WSClient: check for unsolicited responses +- [types][\4164](https://github.com/tendermint/tendermint/pull/4164) Prevent temporary power overflows on validator updates diff --git a/types/validator_set.go b/types/validator_set.go index af7991494..4e68b22cc 100644 --- a/types/validator_set.go +++ b/types/validator_set.go @@ -399,13 +399,14 @@ func verifyUpdates( // Updated validator, add the difference in power to the total. updatedTotalVotingPower += valUpdate.VotingPower - val.VotingPower } - overflow := updatedTotalVotingPower > MaxTotalVotingPower - if overflow { - err = fmt.Errorf( - "failed to add/update validator %v, total voting power would exceed the max allowed %v", - valUpdate, MaxTotalVotingPower) - return 0, 0, err - } + } + + overflow := updatedTotalVotingPower > MaxTotalVotingPower + if overflow { + err = fmt.Errorf( + "failed to add/update validator, total voting power would exceed the max allowed %v", + MaxTotalVotingPower) + return 0, 0, err } return updatedTotalVotingPower, numNewValidators, nil diff --git a/types/validator_set_test.go b/types/validator_set_test.go index ae8ff47ec..455e15801 100644 --- a/types/validator_set_test.go +++ b/types/validator_set_test.go @@ -354,6 +354,21 @@ func TestValidatorSetTotalVotingPowerPanicsOnOverflow(t *testing.T) { assert.Panics(t, shouldPanic) } +func TestValidatorSetShouldNotErrorOnTemporalOverflow(t *testing.T) { + // Updating the validator set might trigger an Overflow error during the update process + valSet := NewValidatorSet([]*Validator{ + {Address: []byte("b"), VotingPower: MaxTotalVotingPower - 1, ProposerPriority: 0}, + {Address: []byte("a"), VotingPower: 1, ProposerPriority: 0}, + }) + + err := valSet.UpdateWithChangeSet([]*Validator{ + {Address: []byte("b"), VotingPower: 1, ProposerPriority: 0}, + {Address: []byte("a"), VotingPower: MaxTotalVotingPower - 1, ProposerPriority: 0}, + }) + + assert.NoError(t, err) +} + func TestAvgProposerPriority(t *testing.T) { // Create Validator set without calling IncrementProposerPriority: tcs := []struct {