Skip to content

Commit

Permalink
fix(state): handle ValidatorSetUpdate with no validator changes (#774)
Browse files Browse the repository at this point in the history
* fix(state): correctly update validators on

* doc(abci): describe ValidatorSetUpdate message
  • Loading branch information
lklimek authored Apr 5, 2024
1 parent e4c934f commit 9b897e1
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 3 deletions.
15 changes: 15 additions & 0 deletions abci/types/types.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 12 additions & 1 deletion internal/state/current_round_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import (
"bytes"
"fmt"

"github.com/rs/zerolog"

abci "github.com/dashpay/tenderdash/abci/types"
tmbytes "github.com/dashpay/tenderdash/libs/bytes"
tmtypes "github.com/dashpay/tenderdash/proto/tendermint/types"
"github.com/dashpay/tenderdash/types"
"github.com/rs/zerolog"
)

const (
Expand Down Expand Up @@ -341,6 +342,16 @@ func valsetUpdate(
nValSet = types.NewValidatorSetWithLocalNodeProTxHash(validatorUpdates, thresholdPubKey,
currentVals.QuorumType, quorumHash, nodeProTxHash)
}
} else {
// validators not changed, but we might have a new quorum hash or threshold public key
if !quorumHash.IsZero() {
nValSet.QuorumHash = quorumHash
}

if thresholdPubKey != nil {
nValSet.ThresholdPublicKey = thresholdPubKey
}
}

return nValSet, nil
}
2 changes: 1 addition & 1 deletion internal/state/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ func execBlock(
logger.Error("executing block", "err", err)
return responseFinalizeBlock, err
}
logger.Info("executed block", "height", block.Height)
logger.Debug("executed block", "height", block.Height)

return responseFinalizeBlock, nil
}
Expand Down
33 changes: 33 additions & 0 deletions internal/state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,39 @@ func TestOneValidatorChangesSaveLoad(t *testing.T) {
}
}

// TestEmptyValidatorUpdates tests that the validator set is updated correctly when there are no validator updates.
func TestEmptyValidatorUpdates(t *testing.T) {
tearDown, _, state := setupTestCase(t)
defer tearDown(t)

firstNode := state.Validators.GetByIndex(0)
require.NotZero(t, firstNode.ProTxHash)
ctx := dash.ContextWithProTxHash(context.Background(), firstNode.ProTxHash)

newPrivKey := bls12381.GenPrivKeyFromSecret([]byte("test"))
newPubKey := newPrivKey.PubKey()
newQuorumHash := crypto.RandQuorumHash()

expectValidators := types.ValidatorListString(state.Validators.Validators)

resp := abci.ResponseProcessProposal{
ValidatorSetUpdate: &abci.ValidatorSetUpdate{
ValidatorUpdates: nil,
ThresholdPublicKey: cryptoenc.MustPubKeyToProto(newPubKey),
QuorumHash: newQuorumHash,
}}

changes, err := state.NewStateChangeset(
ctx,
sm.RoundParamsFromProcessProposal(&resp, nil, 0),
)
require.NoError(t, err)

assert.EqualValues(t, newQuorumHash, changes.NextValidators.QuorumHash, "quorum hash should be updated")
assert.EqualValues(t, newPubKey, changes.NextValidators.ThresholdPublicKey, "threshold public key should be updated")
assert.Equal(t, expectValidators, types.ValidatorListString(changes.NextValidators.Validators), "validator should not change")
}

//func TestProposerFrequency(t *testing.T) {
// ctx, cancel := context.WithCancel(context.Background())
// defer cancel()
Expand Down
15 changes: 15 additions & 0 deletions proto/tendermint/abci/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,21 @@ message ValidatorUpdate {
string node_address = 4 [(gogoproto.nullable) = true];
}

// ValidatorSetUpdate represents a change in the validator set.
// It can be used to add, remove, or update a validator.
//
// Validator set update consists of multiple ValidatorUpdate records,
// each of them can be used to add, remove, or update a validator, according to the
// following rules:
//
// 1. If a validator with the same public key already exists in the validator set
// and power is greater than 0, the existing validator will be updated with the new power.
// 2. If a validator with the same public key already exists in the validator set
// and power is 0, the existing validator will be removed from the validator set.
// 3. If a validator with the same public key does not exist in the validator set and the power is greater than 0,
// a new validator will be added to the validator set.
// 4. As a special case, if quorum hash has changed, all existing validators will be removed before applying
// the new validator set update.
message ValidatorSetUpdate {
repeated ValidatorUpdate validator_updates = 1 [(gogoproto.nullable) = false];
tendermint.crypto.PublicKey threshold_public_key = 2 [(gogoproto.nullable) = false];
Expand Down
16 changes: 15 additions & 1 deletion spec/abci++/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1179,7 +1179,21 @@ Validator
<a name="tendermint-abci-ValidatorSetUpdate"></a>

### ValidatorSetUpdate

ValidatorSetUpdate represents a change in the validator set.
It can be used to add, remove, or update a validator.

Validator set update consists of multiple ValidatorUpdate records,
each of them can be used to add, remove, or update a validator, according to the
following rules:

1. If a validator with the same public key already exists in the validator set
and power is greater than 0, the existing validator will be updated with the new power.
2. If a validator with the same public key already exists in the validator set
and power is 0, the existing validator will be removed from the validator set.
3. If a validator with the same public key does not exist in the validator set and the power is greater than 0,
a new validator will be added to the validator set.
4. As a special case, if quorum hash has changed, all existing validators will be removed before applying
the new validator set update.


| Field | Type | Label | Description |
Expand Down

0 comments on commit 9b897e1

Please sign in to comment.