Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: power shaping #2207

Merged
merged 4 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions tests/integration/partial_set_security_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package integration

import (
"github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
"slices"
"sort"
"testing"

"github.com/cosmos/interchain-security/v5/x/ccv/provider/types"

"cosmossdk.io/math"
ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -152,9 +153,14 @@ func TestMinStake(t *testing.T) {
// adjust parameters

// set the minStake according to the test case
providerKeeper.SetConsumerPowerShapingParameters(s.providerChain.GetContext(), s.getFirstBundle().ConsumerId, types.PowerShapingParameters{
MinStake: tc.minStake,
})
err = providerKeeper.SetConsumerPowerShapingParameters(
s.providerChain.GetContext(),
s.getFirstBundle().ConsumerId,
types.PowerShapingParameters{
MinStake: tc.minStake,
},
)
s.Require().NoError(err)

// delegate and undelegate to trigger a vscupdate

Expand Down
3 changes: 2 additions & 1 deletion tests/mbt/driver/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,9 +389,10 @@ func (s *Driver) ConfigureNewPath(consumerChain, providerChain *ibctesting.TestC
require.NoError(s.t, err, "Error setting consumer genesis on provider for chain %v", consumerChain.ChainID)

// set the top N percentage to 100 to simulate a full consumer
s.providerKeeper().SetConsumerPowerShapingParameters(providerChain.GetContext(), consumerChain.ChainID, types.PowerShapingParameters{
err = s.providerKeeper().SetConsumerPowerShapingParameters(providerChain.GetContext(), consumerChain.ChainID, types.PowerShapingParameters{
Top_N: 100,
})
require.NoError(s.t, err, "Error setting consumer top N for chain %v", consumerChain.ChainID)

// Client ID is set in InitGenesis and we treat it as a black box. So
// must query it to use it with the endpoint.
Expand Down
11 changes: 7 additions & 4 deletions testutil/keeper/unit_test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,15 @@ func SetupForStoppingConsumerChain(t *testing.T, ctx sdk.Context,
gomock.InOrder(expectations...)

providerKeeper.SetConsumerChainId(ctx, consumerId, "chainID")
providerKeeper.SetConsumerMetadata(ctx, consumerId, GetTestConsumerMetadata())
providerKeeper.SetConsumerInitializationParameters(ctx, consumerId, GetTestInitializationParameters())
providerKeeper.SetConsumerPowerShapingParameters(ctx, consumerId, GetTestPowerShapingParameters())
err := providerKeeper.SetConsumerMetadata(ctx, consumerId, GetTestConsumerMetadata())
require.NoError(t, err)
err = providerKeeper.SetConsumerInitializationParameters(ctx, consumerId, GetTestInitializationParameters())
require.NoError(t, err)
err = providerKeeper.SetConsumerPowerShapingParameters(ctx, consumerId, GetTestPowerShapingParameters())
require.NoError(t, err)
providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.ConsumerPhase_CONSUMER_PHASE_INITIALIZED)

err := providerKeeper.CreateConsumerClient(ctx, consumerId)
err = providerKeeper.CreateConsumerClient(ctx, consumerId)
require.NoError(t, err)
// set the mapping consumer ID <> client ID for the consumer chain
providerKeeper.SetConsumerClientId(ctx, consumerId, "clientID")
Expand Down
20 changes: 13 additions & 7 deletions x/ccv/provider/keeper/consumer_lifecycle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,11 +398,14 @@ func TestCreateConsumerClient(t *testing.T) {

// Call method with same arbitrary values as defined above in mock expectations.
providerKeeper.SetConsumerChainId(ctx, "0", "chainID")
providerKeeper.SetConsumerMetadata(ctx, "0", testkeeper.GetTestConsumerMetadata())
providerKeeper.SetConsumerInitializationParameters(ctx, "0", testkeeper.GetTestInitializationParameters())
providerKeeper.SetConsumerPowerShapingParameters(ctx, "0", testkeeper.GetTestPowerShapingParameters())
err := providerKeeper.CreateConsumerClient(ctx, "0")
err := providerKeeper.SetConsumerMetadata(ctx, "0", testkeeper.GetTestConsumerMetadata())
require.NoError(t, err)
err = providerKeeper.SetConsumerInitializationParameters(ctx, "0", testkeeper.GetTestInitializationParameters())
require.NoError(t, err)
err = providerKeeper.SetConsumerPowerShapingParameters(ctx, "0", testkeeper.GetTestPowerShapingParameters())
require.NoError(t, err)

err = providerKeeper.CreateConsumerClient(ctx, "0")
if tc.expClientCreated {
require.NoError(t, err)
testCreatedConsumerClient(t, ctx, providerKeeper, "0", "clientID")
Expand Down Expand Up @@ -526,9 +529,12 @@ func TestMakeConsumerGenesis(t *testing.T) {
UnbondingPeriod: unbondingPeriod,
}
providerKeeper.SetConsumerChainId(ctx, "0", "testchain1")
providerKeeper.SetConsumerMetadata(ctx, "0", consumerMetadata)
providerKeeper.SetConsumerInitializationParameters(ctx, "0", initializationParameters)
providerKeeper.SetConsumerPowerShapingParameters(ctx, "0", providertypes.PowerShapingParameters{})
err := providerKeeper.SetConsumerMetadata(ctx, "0", consumerMetadata)
require.NoError(t, err)
err = providerKeeper.SetConsumerInitializationParameters(ctx, "0", initializationParameters)
require.NoError(t, err)
err = providerKeeper.SetConsumerPowerShapingParameters(ctx, "0", providertypes.PowerShapingParameters{})
require.NoError(t, err)

actualGenesis, _, err := providerKeeper.MakeConsumerGenesis(ctx, "0")
require.NoError(t, err)
Expand Down
15 changes: 10 additions & 5 deletions x/ccv/provider/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ func TestQueryConsumerValidators(t *testing.T) {
require.Equal(t, res.Validators[0].ProviderAddress, providerAddr1.String())

// update consumer TopN param
pk.SetConsumerPowerShapingParameters(ctx, consumerId, types.PowerShapingParameters{Top_N: 50})
err = pk.SetConsumerPowerShapingParameters(ctx, consumerId, types.PowerShapingParameters{Top_N: 50})
require.NoError(t, err)

// expect both opted-in and topN validator
expRes := types.QueryConsumerValidatorsResponse{
Expand Down Expand Up @@ -445,13 +446,14 @@ func TestGetConsumerChain(t *testing.T) {
clientID := fmt.Sprintf("client-%d", len(consumerID)-i)
topN := topNs[i]
pk.SetConsumerClientId(ctx, consumerID, clientID)
pk.SetConsumerPowerShapingParameters(ctx, consumerID, types.PowerShapingParameters{
err := pk.SetConsumerPowerShapingParameters(ctx, consumerID, types.PowerShapingParameters{
Top_N: topN,
ValidatorSetCap: validatorSetCaps[i],
ValidatorsPowerCap: validatorPowerCaps[i],
MinStake: minStakes[i].Uint64(),
AllowInactiveVals: allowInactiveVals[i],
})
require.NoError(t, err)
pk.SetMinimumPowerInTopN(ctx, consumerID, expectedMinPowerInTopNs[i])
for _, addr := range allowlists[i] {
pk.SetAllowlist(ctx, consumerID, addr)
Expand Down Expand Up @@ -532,7 +534,8 @@ func TestQueryConsumerChain(t *testing.T) {
_, err = providerKeeper.QueryConsumerChain(ctx, &req)
require.Error(t, err)

providerKeeper.SetConsumerMetadata(ctx, consumerId, types.ConsumerMetadata{Name: chainId})
err = providerKeeper.SetConsumerMetadata(ctx, consumerId, types.ConsumerMetadata{Name: chainId})
require.NoError(t, err)

expRes := types.QueryConsumerChainResponse{
ChainId: chainId,
Expand All @@ -548,17 +551,19 @@ func TestQueryConsumerChain(t *testing.T) {
require.NoError(t, err)
require.Equal(t, &expRes, res)

providerKeeper.SetConsumerInitializationParameters(
err = providerKeeper.SetConsumerInitializationParameters(
ctx,
consumerId,
types.ConsumerInitializationParameters{SpawnTime: ctx.BlockTime()},
)
require.NoError(t, err)

providerKeeper.SetConsumerPowerShapingParameters(
err = providerKeeper.SetConsumerPowerShapingParameters(
ctx,
consumerId,
types.PowerShapingParameters{Top_N: uint32(50)},
)
require.NoError(t, err)

expRes.InitParams = &types.ConsumerInitializationParameters{SpawnTime: ctx.BlockTime()}
expRes.PowerShapingParams = &types.PowerShapingParameters{Top_N: uint32(50)}
Expand Down
215 changes: 0 additions & 215 deletions x/ccv/provider/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -867,221 +867,6 @@ func (k Keeper) DeleteConsumerCommissionRate(
store.Delete(types.ConsumerCommissionRateKey(consumerId, providerAddr))
}

// SetAllowlist allowlists validator with `providerAddr` address on chain `consumerId`
func (k Keeper) SetAllowlist(
ctx sdk.Context,
consumerId string,
providerAddr types.ProviderConsAddress,
) {
store := ctx.KVStore(k.storeKey)
store.Set(types.AllowlistKey(consumerId, providerAddr), []byte{})
}

// GetAllowList returns all allowlisted validators
func (k Keeper) GetAllowList(
ctx sdk.Context,
consumerId string,
) (providerConsAddresses []types.ProviderConsAddress) {
store := ctx.KVStore(k.storeKey)
key := types.StringIdWithLenKey(types.AllowlistKeyPrefix(), consumerId)
iterator := storetypes.KVStorePrefixIterator(store, key)
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
providerConsAddresses = append(providerConsAddresses, types.NewProviderConsAddress(iterator.Key()[len(key):]))
}

return providerConsAddresses
}

// IsAllowlisted returns `true` if validator with `providerAddr` has been allowlisted on chain `consumerId`
func (k Keeper) IsAllowlisted(
ctx sdk.Context,
consumerId string,
providerAddr types.ProviderConsAddress,
) bool {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.AllowlistKey(consumerId, providerAddr))
return bz != nil
}

// DeleteAllowlist deletes all allowlisted validators
func (k Keeper) DeleteAllowlist(ctx sdk.Context, consumerId string) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, types.StringIdWithLenKey(types.AllowlistKeyPrefix(), consumerId))
defer iterator.Close()

keysToDel := [][]byte{}
for ; iterator.Valid(); iterator.Next() {
keysToDel = append(keysToDel, iterator.Key())
}

for _, key := range keysToDel {
store.Delete(key)
}
}

// IsAllowlistEmpty returns `true` if no validator is allowlisted on chain `consumerId`
func (k Keeper) IsAllowlistEmpty(ctx sdk.Context, consumerId string) bool {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, types.StringIdWithLenKey(types.AllowlistKeyPrefix(), consumerId))
defer iterator.Close()

return !iterator.Valid()
}

// UpdateAllowlist populates the allowlist store for the consumer chain with this consumer id
func (k Keeper) UpdateAllowlist(ctx sdk.Context, consumerId string, allowlist []string) {
k.DeleteAllowlist(ctx, consumerId)
for _, address := range allowlist {
consAddr, err := sdk.ConsAddressFromBech32(address)
if err != nil {
continue
}

k.SetAllowlist(ctx, consumerId, types.NewProviderConsAddress(consAddr))
}
}

// SetDenylist denylists validator with `providerAddr` address on chain `consumerId`
func (k Keeper) SetDenylist(
ctx sdk.Context,
consumerId string,
providerAddr types.ProviderConsAddress,
) {
store := ctx.KVStore(k.storeKey)
store.Set(types.DenylistKey(consumerId, providerAddr), []byte{})
}

// GetDenyList returns all denylisted validators
func (k Keeper) GetDenyList(
ctx sdk.Context,
consumerId string,
) (providerConsAddresses []types.ProviderConsAddress) {
store := ctx.KVStore(k.storeKey)
key := types.StringIdWithLenKey(types.DenylistKeyPrefix(), consumerId)
iterator := storetypes.KVStorePrefixIterator(store, key)
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
providerConsAddresses = append(providerConsAddresses, types.NewProviderConsAddress(iterator.Key()[len(key):]))
}

return providerConsAddresses
}

// IsDenylisted returns `true` if validator with `providerAddr` has been denylisted on chain `consumerId`
func (k Keeper) IsDenylisted(
ctx sdk.Context,
consumerId string,
providerAddr types.ProviderConsAddress,
) bool {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.DenylistKey(consumerId, providerAddr))
return bz != nil
}

// DeleteDenylist deletes all denylisted validators
func (k Keeper) DeleteDenylist(ctx sdk.Context, consumerId string) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, types.StringIdWithLenKey(types.DenylistKeyPrefix(), consumerId))
defer iterator.Close()

keysToDel := [][]byte{}
for ; iterator.Valid(); iterator.Next() {
keysToDel = append(keysToDel, iterator.Key())
}

for _, key := range keysToDel {
store.Delete(key)
}
}

// IsDenylistEmpty returns `true` if no validator is denylisted on chain `consumerId`
func (k Keeper) IsDenylistEmpty(ctx sdk.Context, consumerId string) bool {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, types.StringIdWithLenKey(types.DenylistKeyPrefix(), consumerId))
defer iterator.Close()

return !iterator.Valid()
}

// UpdateDenylist populates the denylist store for the consumer chain with this consumer id
func (k Keeper) UpdateDenylist(ctx sdk.Context, consumerId string, denylist []string) {
k.DeleteDenylist(ctx, consumerId)
for _, address := range denylist {
consAddr, err := sdk.ConsAddressFromBech32(address)
if err != nil {
continue
}

k.SetDenylist(ctx, consumerId, types.NewProviderConsAddress(consAddr))
}
}

// SetMinimumPowerInTopN sets the minimum power required for a validator to be in the top N
// for a given consumer chain.
func (k Keeper) SetMinimumPowerInTopN(
ctx sdk.Context,
consumerId string,
power int64,
) {
store := ctx.KVStore(k.storeKey)

buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, uint64(power))

store.Set(types.MinimumPowerInTopNKey(consumerId), buf)
}

// GetMinimumPowerInTopN returns the minimum power required for a validator to be in the top N
// for a given consumer chain.
func (k Keeper) GetMinimumPowerInTopN(
ctx sdk.Context,
consumerId string,
) (int64, bool) {
store := ctx.KVStore(k.storeKey)
buf := store.Get(types.MinimumPowerInTopNKey(consumerId))
if buf == nil {
return 0, false
}
return int64(binary.BigEndian.Uint64(buf)), true
}

// DeleteMinimumPowerInTopN removes the minimum power required for a validator to be in the top N
// for a given consumer chain.
func (k Keeper) DeleteMinimumPowerInTopN(
ctx sdk.Context,
consumerId string,
) {
store := ctx.KVStore(k.storeKey)
store.Delete(types.MinimumPowerInTopNKey(consumerId))
}

// UpdateMinimumPowerInTopN populates the minimum power in Top N for the consumer chain with this consumer id
func (k Keeper) UpdateMinimumPowerInTopN(ctx sdk.Context, consumerId string, oldTopN uint32, newTopN uint32) error {
// if the top N changes, we need to update the new minimum power in top N
if newTopN != oldTopN {
if newTopN > 0 {
// if the chain receives a non-zero top N value, store the minimum power in the top N
bondedValidators, err := k.GetLastProviderConsensusActiveValidators(ctx)
if err != nil {
return err
}
minPower, err := k.ComputeMinPowerInTopN(ctx, bondedValidators, newTopN)
if err != nil {
return err
}
k.SetMinimumPowerInTopN(ctx, consumerId, minPower)
} else {
// if the chain receives a zero top N value, we delete the min power
k.DeleteMinimumPowerInTopN(ctx, consumerId)
}
}

return nil
}

func (k Keeper) UnbondingCanComplete(ctx sdk.Context, id uint64) error {
return k.stakingKeeper.UnbondingCanComplete(ctx, id)
}
Expand Down
Loading
Loading