Skip to content

Commit

Permalink
Merge branch 'feat/inactive-vals-v50' into ph/simulator
Browse files Browse the repository at this point in the history
  • Loading branch information
p-offtermatt committed Jul 15, 2024
2 parents 3af7e99 + 757680b commit 22de291
Show file tree
Hide file tree
Showing 13 changed files with 80 additions and 23 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/nightly-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,23 @@ jobs:
- name: E2E active set changes
run: go run ./tests/e2e/... --tc active-set-changes

inactive-provider-validators-on-consumer-test:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/setup-go@v5
with:
go-version: "1.22"
- uses: actions/checkout@v4
- name: Checkout LFS objects
run: git lfs checkout
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "1.22" # The Go version to download (if necessary) and use.
- name: E2E inactive provider validators on consumer
run: go run ./tests/e2e/... --tc inactive-provider-validators-on-consumer

nightly-test-fail:
needs:
- happy-path-test
Expand Down
9 changes: 5 additions & 4 deletions tests/e2e/steps_inactive_vals.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (
// high-level, this test does:
// - start the provider chain
// - start a consumer chain
// - check that non-consensus validators do not get slashed for downtime; and that they don't get rewards
// - check that active validators *do* get slashed for downtime, and don't get rewards while they are down
// - check that non-consensus validators do not get slashed for downtime on the provider; and that they don't get rewards
// - check that active validators *do* get slashed for downtime on the provider, and don't get rewards while they are down
// - check that non-consensus validators *do* get jailed for downtime on consumer chains
// - check that non-consensus validators *become* consensus validators when they have enough power
func stepsInactiveProviderValidators() []Step {
Expand Down Expand Up @@ -43,7 +43,9 @@ func stepsInactiveProviderValidators() []Step {
},
Rewards: &Rewards{
IsNativeDenom: true, // check for rewards in the provider denom
IsIncrementalReward: true, // check current rewards, because alice gets one block of rewards due to being in the genesis
IsIncrementalReward: true, // we need to get incremental rewards
// if we would look at total rewards, alice would trivially also get rewards,
// because she gets rewards in the first block due to being in the genesis
IsRewarded: map[ValidatorID]bool{
ValidatorID("alice"): false,
ValidatorID("bob"): true,
Expand Down Expand Up @@ -142,7 +144,6 @@ func stepsInactiveProviderValidators() []Step {
},
State: State{
ChainID("provi"): ChainState{
// check that now every validator got rewarded since the first block
Rewards: &Rewards{
IsNativeDenom: true, // check for rewards in the provider denom
IsIncrementalReward: true, // check rewards for currently produced blocks only
Expand Down
4 changes: 2 additions & 2 deletions x/ccv/no_valupdates_genutil/doc.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*
Package staking defines a "wrapper" module around the Cosmos SDK's native
x/staking module. In other words, it provides the exact same functionality as
x/genutil module. In other words, it provides the exact same functionality as
the native module in that it simply embeds the native module. However, it
overrides `EndBlock` which will return no validator set updates. Instead,
overrides `InitGenesis` which will return no validator set updates. Instead,
it is assumed that some other module will provide the validator set updates.
*/
package genutil
1 change: 0 additions & 1 deletion x/ccv/provider/keeper/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@ func TestInitAndExportGenesis(t *testing.T) {
)

mocks.MockStakingKeeper.EXPECT().GetBondedValidatorsByPower(gomock.Any()).Return(
// return an empty set of validators, since they are not tested against here
[]stakingtypes.Validator{
provVal,
}, nil).AnyTimes()
Expand Down
3 changes: 2 additions & 1 deletion x/ccv/provider/keeper/provider_consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func (k Keeper) SetLastProviderConsensusValidator(
}

// SetLastProviderConsensusValSet resets the stored last validator set sent to the consensus engine on the provider
// to the provided nextValidators.
// to the provided `nextValidators.
func (k Keeper) SetLastProviderConsensusValSet(ctx sdk.Context, nextValidators []types.ConsensusValidator) {
k.setValSet(ctx, []byte{types.LastProviderConsensusValsPrefix}, nextValidators)
}
Expand Down Expand Up @@ -59,6 +59,7 @@ func (k Keeper) GetLastTotalProviderConsensusPower(
return k.getTotalPower(ctx, []byte{types.LastProviderConsensusValsPrefix})
}

// CreateProviderConsensusValidator creates a new ConsensusValidator from the given staking validator
func (k Keeper) CreateProviderConsensusValidator(ctx sdk.Context, val stakingtypes.Validator) (types.ConsensusValidator, error) {
consAddr, err := val.GetConsAddr()
if err != nil {
Expand Down
22 changes: 22 additions & 0 deletions x/ccv/provider/keeper/provider_consensus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper_test
import (
"testing"

"cosmossdk.io/math"
"github.com/cometbft/cometbft/proto/tendermint/crypto"
"github.com/stretchr/testify/require"

Expand Down Expand Up @@ -100,3 +101,24 @@ func TestDeleteLastProviderConsensusValSet(t *testing.T) {
storedValidators := providerKeeper.GetLastProviderConsensusValSet(ctx)
require.Empty(t, storedValidators, "validator set should be empty")
}

func TestGetLastTotalProviderConsensusPower(t *testing.T) {
providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
defer ctrl.Finish()
validator1 := types.ConsensusValidator{
ProviderConsAddr: []byte("providerConsAddr1"),
Power: 2,
PublicKey: &crypto.PublicKey{},
}
validator2 := types.ConsensusValidator{
ProviderConsAddr: []byte("providerConsAddr2"),
Power: 3,
PublicKey: &crypto.PublicKey{},
}
nextValidators := []types.ConsensusValidator{validator1, validator2}
providerKeeper.SetLastProviderConsensusValSet(ctx, nextValidators)
// Get the total power of the last stored validator set
totalPower := providerKeeper.GetLastTotalProviderConsensusPower(ctx)
expectedTotalPower := math.NewInt(5)
require.Equal(t, expectedTotalPower, totalPower, "total power does not match")
}
6 changes: 3 additions & 3 deletions x/ccv/provider/keeper/relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,9 @@ func (k Keeper) EndBlockVSU(ctx sdk.Context) ([]abci.ValidatorUpdate, error) {
// The function returns the difference between the current validator set and the next validator set as a list of `abci.ValidatorUpdate` objects.
func (k Keeper) ProviderValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate {
// get the bonded validators from the staking module
bondedValidators, error := k.stakingKeeper.GetBondedValidatorsByPower(ctx)
if error != nil {
panic(fmt.Errorf("failed to get bonded validators: %w", error))
bondedValidators, err := k.stakingKeeper.GetBondedValidatorsByPower(ctx)
if err != nil {
panic(fmt.Errorf("failed to get bonded validators: %w", err))
}

// get the last validator set sent to consensus
Expand Down
2 changes: 1 addition & 1 deletion x/ccv/provider/keeper/relay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,7 @@ func TestEndBlockVSU(t *testing.T) {
testkeeper.SetupMocksForLastBondedValidatorsExpectation(mocks.MockStakingKeeper, 5, lastValidators, powers, -1)

sort.Slice(lastValidators, func(i, j int) bool {
return lastValidators[i].ConsensusPower(sdk.DefaultPowerReduction) >
return lastValidators[i].GetConsensusPower(sdk.DefaultPowerReduction) >
lastValidators[j].GetConsensusPower(sdk.DefaultPowerReduction)
})
mocks.MockStakingKeeper.EXPECT().GetBondedValidatorsByPower(gomock.Any()).Return(lastValidators, nil).AnyTimes()
Expand Down
4 changes: 2 additions & 2 deletions x/ccv/provider/keeper/validator_set_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@ func (k Keeper) isValidator(ctx sdk.Context, prefix []byte, providerAddr types.P
// getValSet returns all the validators stored under the given prefix.
func (k Keeper) getValSet(
ctx sdk.Context,
key []byte,
prefix []byte,
) (validators []types.ConsensusValidator) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, key)
iterator := storetypes.KVStorePrefixIterator(store, prefix)
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
Expand Down
16 changes: 8 additions & 8 deletions x/ccv/provider/keeper/validator_set_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)

// GetConsumerChainKey returns the store key for consumer validators of the consumer chain with `chainID`
func (k Keeper) GetConsumerChainKey(ctx sdk.Context, chainID string) []byte {
// GetConsumerChainConsensusValidatorsKey returns the store key for consumer validators of the consumer chain with `chainID`
func (k Keeper) GetConsumerChainConsensusValidatorsKey(ctx sdk.Context, chainID string) []byte {
return types.ChainIdWithLenKey(types.ConsumerValidatorBytePrefix, chainID)
}

Expand All @@ -23,13 +23,13 @@ func (k Keeper) SetConsumerValidator(
chainID string,
validator types.ConsensusValidator,
) {
k.setValidator(ctx, k.GetConsumerChainKey(ctx, chainID), validator)
k.setValidator(ctx, k.GetConsumerChainConsensusValidatorsKey(ctx, chainID), validator)
}

// SetConsumerValSet resets the current consumer validators with the `nextValidators` computed by
// `FilterValidators` and hence this method should only be called after `FilterValidators` has completed.
func (k Keeper) SetConsumerValSet(ctx sdk.Context, chainID string, nextValidators []types.ConsensusValidator) {
k.setValSet(ctx, k.GetConsumerChainKey(ctx, chainID), nextValidators)
k.setValSet(ctx, k.GetConsumerChainConsensusValidatorsKey(ctx, chainID), nextValidators)
}

// DeleteConsumerValidator removes consumer validator with `providerAddr` address
Expand All @@ -38,29 +38,29 @@ func (k Keeper) DeleteConsumerValidator(
chainID string,
providerConsAddr types.ProviderConsAddress,
) {
k.deleteValidator(ctx, k.GetConsumerChainKey(ctx, chainID), providerConsAddr)
k.deleteValidator(ctx, k.GetConsumerChainConsensusValidatorsKey(ctx, chainID), providerConsAddr)
}

// DeleteConsumerValSet deletes all the stored consumer validators for chain `chainID`
func (k Keeper) DeleteConsumerValSet(
ctx sdk.Context,
chainID string,
) {
k.deleteValSet(ctx, k.GetConsumerChainKey(ctx, chainID))
k.deleteValSet(ctx, k.GetConsumerChainConsensusValidatorsKey(ctx, chainID))
}

// IsConsumerValidator returns `true` if the consumer validator with `providerAddr` exists for chain `chainID`
// and `false` otherwise
func (k Keeper) IsConsumerValidator(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress) bool {
return k.isValidator(ctx, k.GetConsumerChainKey(ctx, chainID), providerAddr)
return k.isValidator(ctx, k.GetConsumerChainConsensusValidatorsKey(ctx, chainID), providerAddr)
}

// GetConsumerValSet returns all the consumer validators for chain `chainID`
func (k Keeper) GetConsumerValSet(
ctx sdk.Context,
chainID string,
) []types.ConsensusValidator {
return k.getValSet(ctx, k.GetConsumerChainKey(ctx, chainID))
return k.getValSet(ctx, k.GetConsumerChainConsensusValidatorsKey(ctx, chainID))
}

// DiffValidators compares the current and the next epoch's consumer validators and returns the `ValidatorUpdate` diff
Expand Down
16 changes: 16 additions & 0 deletions x/ccv/provider/migrations/vX/migrations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package v6

import (
sdk "github.com/cosmos/cosmos-sdk/types"
providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
)

// InitializeMaxValidatorsForExistingConsumers initializes the max validators
// parameter for existing consumers to the MaxProviderConsensusValidators parameter.
// This is necessary to avoid those consumer chains having an excessive amount of validators.
func InitializeMaxValidatorsForExistingConsumers(ctx sdk.Context, providerKeeper providerkeeper.Keeper) {
maxVals := providerKeeper.GetParams(ctx).MaxProviderConsensusValidators
for _, chainID := range providerKeeper.GetAllRegisteredConsumerChainIDs(ctx) {
providerKeeper.SetValidatorSetCap(ctx, chainID, uint32(maxVals))
}
}
2 changes: 1 addition & 1 deletion x/ccv/provider/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ const (
// minimum power required to be in the top N per consumer chain.
MinimumPowerInTopNBytePrefix

// LastProviderConsensusValsPrefix is byte prefix for storing the last validator set
// LastProviderConsensusValsPrefix is the byte prefix for storing the last validator set
// sent to the consensus engine of the provider chain
LastProviderConsensusValsPrefix

Expand Down
1 change: 1 addition & 0 deletions x/ccv/provider/types/keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ func getAllKeyPrefixes() []byte {
providertypes.ConsumerRewardsAllocationBytePrefix,
providertypes.ConsumerCommissionRatePrefix,
providertypes.MinimumPowerInTopNBytePrefix,
providertypes.LastProviderConsensusValsPrefix,
providertypes.ParametersByteKey,
}
}
Expand Down

0 comments on commit 22de291

Please sign in to comment.