Skip to content

Commit 958fa08

Browse files
committed
have a constant define min num of bonded in proposer set
1 parent 5a2e6d4 commit 958fa08

5 files changed

Lines changed: 45 additions & 45 deletions

File tree

tests/integration/staking/keeper/genesis_test.go

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,10 @@ func TestInitGenesis(t *testing.T) {
143143
}
144144

145145
func TestInitGenesisWithProposerSet(t *testing.T) {
146-
f, addrs := bootstrapGenesisTest(t, 3)
146+
f, addrs := bootstrapGenesisTest(t, 6)
147147

148-
validators := make([]types.Validator, 3)
149-
for i := 0; i < 3; i++ {
148+
validators := make([]types.Validator, 6)
149+
for i := 0; i < 6; i++ {
150150
pk, err := codectypes.NewAnyWithValue(PKs[i])
151151
assert.NilError(t, err)
152152

@@ -162,8 +162,11 @@ func TestInitGenesisWithProposerSet(t *testing.T) {
162162
params := types.DefaultParams()
163163
params.BondDenom = sdk.DefaultBondDenom
164164

165-
// Set only first two validators as proposers
166-
proposers := []string{validators[0].OperatorAddress, validators[1].OperatorAddress}
165+
// Set first 5 validators as proposers (meets MIN_BONDED_IN_PROPOSER_SET requirement)
166+
proposers := make([]string, 5)
167+
for i := 0; i < 5; i++ {
168+
proposers[i] = validators[i].OperatorAddress
169+
}
167170
genesisState := &types.GenesisState{
168171
Params: params,
169172
Validators: validators,
@@ -176,7 +179,7 @@ func TestInitGenesisWithProposerSet(t *testing.T) {
176179
f.sdkCtx,
177180
f.bankKeeper,
178181
types.BondedPoolName,
179-
sdk.NewCoins(sdk.NewCoin(params.BondDenom, math.NewInt(300))),
182+
sdk.NewCoins(sdk.NewCoin(params.BondDenom, math.NewInt(600))),
180183
),
181184
)
182185

@@ -186,19 +189,11 @@ func TestInitGenesisWithProposerSet(t *testing.T) {
186189
// Verify proposer set in state.
187190
actualProposers, err := f.stakingKeeper.GetProposers(f.sdkCtx)
188191
assert.NilError(t, err)
189-
assert.DeepEqual(
190-
t,
191-
[]string{validators[0].OperatorAddress, validators[1].OperatorAddress},
192-
actualProposers,
193-
)
192+
assert.DeepEqual(t, proposers, actualProposers)
194193

195194
// Verify proposer set in genesis export
196195
exportedGenesis := f.stakingKeeper.ExportGenesis(f.sdkCtx)
197-
assert.DeepEqual(
198-
t,
199-
[]string{validators[0].OperatorAddress, validators[1].OperatorAddress},
200-
exportedGenesis.Proposers,
201-
)
196+
assert.DeepEqual(t, proposers, exportedGenesis.Proposers)
202197
}
203198

204199
func TestInitGenesis_PoolsBalanceMismatch(t *testing.T) {

x/staking/keeper/proposer_set.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@ package keeper
33
import (
44
"context"
55
"encoding/json"
6-
"fmt"
76

7+
errorsmod "cosmossdk.io/errors"
88
"github.com/cosmos/cosmos-sdk/x/staking/types"
99
)
1010

11+
const (
12+
// minimum number of bonded validators required in a proposer set
13+
MIN_BONDED_IN_PROPOSER_SET = 5
14+
)
15+
1116
// GetProposers returns all proposers by their operator addresses.
1217
// Note: Returns empty array when no proposers are set
1318
func (k Keeper) GetProposers(ctx context.Context) ([]string, error) {
@@ -49,12 +54,13 @@ func (k Keeper) SetProposers(ctx context.Context, proposers []string) error {
4954
// checkProposerSetInvariant validates invariants of a proposer set, which are:
5055
// - all proposers are valid operator addresses
5156
// - all proposers correspond to existing validators
52-
// - at least one proposer is bonded
57+
// - at least MIN_BONDED_IN_PROPOSER_SET proposers are bonded
5358
func (k Keeper) checkProposerSetInvariants(ctx context.Context, proposers []string) error {
5459
if len(proposers) == 0 {
5560
return nil // Valid as x/staking will default to all validators being proposers.
5661
}
5762

63+
bonded := 0
5864
for _, proposerAddr := range proposers {
5965
operatorAddr, err := k.validatorAddressCodec.StringToBytes(proposerAddr)
6066
if err != nil {
@@ -65,10 +71,17 @@ func (k Keeper) checkProposerSetInvariants(ctx context.Context, proposers []stri
6571
if err != nil {
6672
return err
6773
}
74+
6875
if validator.Status == types.Bonded {
69-
return nil
76+
bonded++
7077
}
7178
}
7279

73-
return fmt.Errorf("at least one proposer must be bonded")
80+
if bonded < MIN_BONDED_IN_PROPOSER_SET {
81+
return errorsmod.Wrapf(types.ErrInsufficientBondedValidators,
82+
"proposer set only has %d bonded validators, less than the required %d",
83+
bonded, MIN_BONDED_IN_PROPOSER_SET)
84+
}
85+
86+
return nil
7487
}

x/staking/keeper/proposer_set_test.go

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ func (s *KeeperTestSuite) TestGetSetProposers() {
1515
require.NoError(err)
1616
require.Empty(proposers)
1717

18-
// Create three bonded validators and one unbonding validator
19-
validators := make([]string, 4)
20-
for i := 0; i < 4; i++ {
18+
// Create six validators: 5 bonded and 1 unbonding
19+
validators := make([]string, 6)
20+
for i := 0; i < 6; i++ {
2121
valPubKey := PKs[i]
2222
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
2323
validator := testutil.NewValidator(s.T(), valAddr, valPubKey)
24-
if i == 3 {
24+
if i == 5 {
2525
validator.Status = types.Unbonding
2626
} else {
2727
validator.Status = types.Bonded
@@ -31,25 +31,21 @@ func (s *KeeperTestSuite) TestGetSetProposers() {
3131
require.NoError(err)
3232
}
3333

34-
// Set the first validator as a proposer and verify
35-
err = keeper.SetProposers(ctx, validators[:1])
34+
// Set first 5 validators as proposers and verify
35+
err = keeper.SetProposers(ctx, validators[:5])
3636
require.NoError(err)
3737

3838
proposers, err = keeper.GetProposers(ctx)
3939
require.NoError(err)
40-
require.Equal(validators[:1], proposers)
40+
require.Equal(validators[:5], proposers)
4141

42-
// Set last two validators as proposers and verify
43-
// Should succeed as there's at least one bonded proposer
44-
err = keeper.SetProposers(ctx, validators[2:])
45-
require.NoError(err)
46-
47-
proposers, err = keeper.GetProposers(ctx)
48-
require.NoError(err)
49-
require.Equal(validators[2:], proposers)
42+
// Set last 5 validators as proposers
43+
// Should fail as there are insufficient bonded proposers
44+
err = keeper.SetProposers(ctx, validators[1:])
45+
require.Error(err)
46+
require.ErrorContains(err, "proposer set only has 4 bonded validators, less than the required 5")
5047

5148
// Set all validators as proposers and verify
52-
// Should succeed as there's at least one bonded proposer
5349
err = keeper.SetProposers(ctx, validators)
5450
require.NoError(err)
5551

@@ -74,9 +70,11 @@ func (s *KeeperTestSuite) TestSetProposersErrors() {
7470
valPubKey := PKs[0]
7571
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
7672
validator := testutil.NewValidator(s.T(), valAddr, valPubKey)
73+
err := keeper.SetValidator(ctx, validator)
74+
require.NoError(err)
7775

7876
// Should return error given invalid addresses
79-
err := keeper.SetProposers(ctx, []string{"invalid-address"})
77+
err = keeper.SetProposers(ctx, []string{"invalid-address"})
8078
require.Error(err, "SetProposers with invalid address should return error")
8179

8280
// Should return error for non-operator addresses (e.g. account and consensus addresses)
@@ -93,11 +91,4 @@ func (s *KeeperTestSuite) TestSetProposersErrors() {
9391
nonExistentValAddr := sdk.ValAddress(nonExistentPubKey.Address().Bytes())
9492
err = keeper.SetProposers(ctx, []string{nonExistentValAddr.String()})
9593
require.ErrorContains(err, "validator does not exist")
96-
97-
// Should return error if no proposer is bonded.
98-
validator.Status = types.Unbonded
99-
err = keeper.SetValidator(ctx, validator)
100-
require.NoError(err)
101-
err = keeper.SetProposers(ctx, []string{validator.OperatorAddress})
102-
require.ErrorContains(err, "at least one proposer must be bonded")
10394
}

x/staking/types/errors.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,5 @@ var (
4848
ErrInvalidSigner = errors.Register(ModuleName, 43, "expected authority account as only signer for proposal message")
4949
ErrBadRedelegationSrc = errors.Register(ModuleName, 44, "redelegation source validator not found")
5050
ErrNoUnbondingType = errors.Register(ModuleName, 45, "unbonding type not found")
51+
ErrInsufficientBondedValidators = errors.Register(ModuleName, 500, "insufficient number of bonded validators")
5152
)

x/staking/types/keys.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ var (
5959

6060
// key for proposer set
6161
// Note: all validators default to being proposers if proposer set is empty
62-
ProposerSetKey = []byte("ProposerSet")
62+
ProposerSetKey = []byte("PS")
6363
)
6464

6565
// UnbondingType defines the type of unbonding operation

0 commit comments

Comments
 (0)