Skip to content

Commit

Permalink
init commit
Browse files Browse the repository at this point in the history
  • Loading branch information
insumity committed Nov 13, 2024
1 parent f5c1a60 commit 151a2b1
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 1 deletion.
38 changes: 37 additions & 1 deletion x/ccv/provider/keeper/consumer_lifecycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,33 @@ func (k Keeper) ConsumeIdsFromTimeQueue(
return result, nil
}

// HasActiveConsumerValidator checks whether at least one active validator is opted in to chain with `consumerId`
func (k Keeper) HasActiveConsumerValidator(ctx sdk.Context, consumerId string, activeValidators []stakingtypes.Validator) (bool, error) {
currentValidatorSet, err := k.GetConsumerValSet(ctx, consumerId)
if err != nil {
return false, err
}

isActiveValidator := make(map[string]bool)
for _, val := range activeValidators {
consAddr, err := val.GetConsAddr()
if err != nil {
return false, fmt.Errorf("creating consumer genesis state, consumerId(%s): %w", consumerId, err)
}
providerConsAddr := types.NewProviderConsAddress(consAddr)
isActiveValidator[providerConsAddr.String()] = true
}

for _, val := range currentValidatorSet {
providerConsAddr := types.NewProviderConsAddress(val.ProviderConsAddr)
if isActiveValidator[providerConsAddr.String()] {
return true, nil
}
}

return false, nil
}

// LaunchConsumer launches the chain with the provided consumer id by creating the consumer client and the respective
// consumer genesis file
//
Expand All @@ -205,8 +232,17 @@ func (k Keeper) LaunchConsumer(
if err != nil {
return fmt.Errorf("computing consumer next validator set, consumerId(%s): %w", consumerId, err)
}

if len(initialValUpdates) == 0 {
return fmt.Errorf("cannot launch consumer with no validator opted in, consumerId(%s)", consumerId)
return fmt.Errorf("cannot launch consumer with no consumer validator, consumerId(%s)", consumerId)
}

hasActiveConsumerValidator, err := k.HasActiveConsumerValidator(ctx, consumerId, activeValidators)
if err != nil {
return fmt.Errorf("cannot check if chain has an active consumer validator, consumerId(%s): %w", consumerId, err)
}
if !hasActiveConsumerValidator {
return fmt.Errorf("cannot launch consumer with no active consumer validator, consumerId(%s)", consumerId)
}

// create consumer genesis
Expand Down
61 changes: 61 additions & 0 deletions x/ccv/provider/keeper/consumer_lifecycle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,67 @@ func TestConsumeIdsFromTimeQueue(t *testing.T) {
}
}

func TestHasActiveValidatorOptedIn(t *testing.T) {
keeperParams := testkeeper.NewInMemKeeperParams(t)
providerKeeper, ctx, _, mocks := testkeeper.GetProviderKeeperAndCtx(t, keeperParams)

// set 5 bonded validators with powers 5, 4, 3, 2, and 1
NumberOfBondedValidators := 5
var bondedValidators []stakingtypes.Validator
for i := 0; i < NumberOfBondedValidators; i++ {
power := int64(NumberOfBondedValidators - i)
bondedValidators = append(bondedValidators, createStakingValidator(ctx, mocks, power, i))
}
mocks.MockStakingKeeper.EXPECT().GetBondedValidatorsByPower(gomock.Any()).Return(bondedValidators, nil).AnyTimes()

// get the consensus addresses of the previously-set bonded validators
var consensusAddresses [][]byte
for i := 0; i < NumberOfBondedValidators; i++ {
consAddr, _ := bondedValidators[i].GetConsAddr()
consensusAddresses = append(consensusAddresses, consAddr)
}

// Set the maximum number of provider consensus active validators (i.e., active validators) to 3. As a result
// `bondedValidators[4]` (with power of 4), `bondedValidators[3]` (with power of 3), `bondedValidators[2]` (with power of 2)
// are the active validators, and `bondedValidators[1]` (with power of 1) and `bondedValidators[0]` (with power of 0)
// are non-active validators.
maxProviderConsensusValidators := int64(3)
params := providerKeeper.GetParams(ctx)
params.MaxProviderConsensusValidators = maxProviderConsensusValidators
providerKeeper.SetParams(ctx, params)

activeValidators, _ := providerKeeper.GetLastProviderConsensusActiveValidators(ctx)

consumerId := "0"

// consumer chain has only non-active validators
err := providerKeeper.SetConsumerValSet(ctx, consumerId, []providertypes.ConsensusValidator{
{ProviderConsAddr: consensusAddresses[3]},
{ProviderConsAddr: consensusAddresses[4]}})
require.NoError(t, err)
hasActiveValidatorOptedIn, err := providerKeeper.HasActiveConsumerValidator(ctx, consumerId, activeValidators)
require.NoError(t, err)
require.False(t, hasActiveValidatorOptedIn)

// consumer chain has one active validator
err = providerKeeper.SetConsumerValSet(ctx, consumerId, []providertypes.ConsensusValidator{
{ProviderConsAddr: consensusAddresses[2]}})
require.NoError(t, err)
hasActiveValidatorOptedIn, err = providerKeeper.HasActiveConsumerValidator(ctx, consumerId, activeValidators)
require.NoError(t, err)
require.True(t, hasActiveValidatorOptedIn)

// consumer chain has one active and two non-active validators
err = providerKeeper.SetConsumerValSet(ctx, consumerId, []providertypes.ConsensusValidator{
{ProviderConsAddr: consensusAddresses[3]},
{ProviderConsAddr: consensusAddresses[4]},
{ProviderConsAddr: consensusAddresses[1]}})
require.NoError(t, err)
hasActiveValidatorOptedIn, err = providerKeeper.HasActiveConsumerValidator(ctx, consumerId, activeValidators)
require.NoError(t, err)
require.True(t, hasActiveValidatorOptedIn)
}

func TestCreateConsumerClient(t *testing.T) {
type testCase struct {
description string
Expand Down

0 comments on commit 151a2b1

Please sign in to comment.