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

feat!: Add support for priority validators #2101

Merged
merged 41 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
536243a
Start adding priority validators
p-offtermatt Jul 26, 2024
7b7612e
Add new priority_validator field
p-offtermatt Jul 26, 2024
c3df006
Resolve conflicts with main
kirdatatjana Oct 7, 2024
f96fb22
Added priority list to the PowerShapingParameters
kirdatatjana Oct 15, 2024
e41bd64
Add documentation for priority list
kirdatatjana Oct 16, 2024
5893cd3
Add priority list in local-testnet.sh
kirdatatjana Oct 16, 2024
09beb73
Update .changelog/unreleased/features/provider/xxxx-priority-validato…
kirdatatjana Oct 16, 2024
d442765
Update x/ccv/provider/keeper/power_shaping.go
kirdatatjana Oct 16, 2024
e6b17ef
Update x/ccv/provider/keeper/power_shaping_test.go
kirdatatjana Oct 16, 2024
4083463
Update x/ccv/provider/keeper/power_shaping_test.go
kirdatatjana Oct 16, 2024
508aa1c
Update .changelog/unreleased/api-breaking/provider/xxxx-priority-vali…
kirdatatjana Oct 16, 2024
da41d15
Fix typo in provider.proto
kirdatatjana Oct 16, 2024
a7572eb
Merge branch 'ph/priority-validators' of https://github.com/cosmos/in…
kirdatatjana Oct 16, 2024
165ef87
Remove unnecessary priority list from test in steps_permissionless_ic…
kirdatatjana Oct 16, 2024
d5cb420
Remove comment from grpc_query.go
kirdatatjana Oct 16, 2024
b6788e6
Add e2e test for priority list
kirdatatjana Oct 16, 2024
1c19591
Improved e2e test
kirdatatjana Oct 17, 2024
b36e28f
Merge branch 'main' into ph/priority-validators
kirdatatjana Oct 17, 2024
171246d
Merge branch 'main' into ph/priority-validators
kirdatatjana Oct 17, 2024
ae2c771
Fixed some issues
kirdatatjana Oct 21, 2024
e40a8c6
Refactored code logic
kirdatatjana Oct 21, 2024
e878390
Refactored code logic
kirdatatjana Oct 22, 2024
837a078
Renamed files
kirdatatjana Oct 22, 2024
04e9c57
Removed priority list from migrations.go
kirdatatjana Oct 22, 2024
f866876
Fixed bug for priority list
kirdatatjana Oct 23, 2024
21d8ff7
Added priority list to e2e nightly tests
kirdatatjana Oct 23, 2024
abd2773
Update tx.go
kirdatatjana Oct 23, 2024
2c83503
Refactored TestCapValidatorSet
kirdatatjana Oct 23, 2024
a78038f
Merge branch 'ph/priority-validators' of https://github.com/cosmos/in…
kirdatatjana Oct 23, 2024
5ef9ff2
Small fixes
kirdatatjana Oct 24, 2024
ba04ab8
Small fixes
kirdatatjana Oct 24, 2024
d5d043b
Fix PartitionBasedOnPriorityList function
kirdatatjana Oct 24, 2024
31e8001
Update contrib/local-testnet.sh
kirdatatjana Oct 25, 2024
cc84d75
Moved 2101-introduce-priority-validators.md into state-breaking
kirdatatjana Oct 25, 2024
6336f9d
Merge branch 'ph/priority-validators' of https://github.com/cosmos/in…
kirdatatjana Oct 25, 2024
adc3a0e
Fixed TestGetConsumerChain
kirdatatjana Oct 25, 2024
94eba83
Added test case in TestCapValidatorSet
kirdatatjana Oct 25, 2024
a49866c
Revert changes made by the merge
kirdatatjana Oct 25, 2024
0b38ed4
Removed changes from ADRs that were already implemented
kirdatatjana Oct 25, 2024
a1d974d
Added a comment in CapValidatorSet function
kirdatatjana Oct 25, 2024
9f4d771
Removed unnecessary imports
kirdatatjana Oct 25, 2024
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
17 changes: 17 additions & 0 deletions .github/workflows/nightly-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,22 @@ jobs:
go-version: "1.22" # The Go version to download (if necessary) and use.
- name: E2E partial set security denylist
run: go run ./tests/e2e/... --tc partial-set-security-validators-denylisted
partial-set-security-validators-prioritylisted-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 partial set security prioritylist
run: go run ./tests/e2e/... --tc partial-set-security-validators-prioritylisted
partial-set-security-modification-proposal:
runs-on: ubuntu-latest
timeout-minutes: 20
Expand Down Expand Up @@ -376,6 +392,7 @@ jobs:
- partial-set-security-validators-power-cap-test
- partial-set-security-validators-allowlisted-test
- partial-set-security-validators-denylisted-test
- partial-set-security-validators-prioritylisted-test
- partial-set-security-modification-proposal
- active-set-changes-test
- permissionless-basic-test
Expand Down
4 changes: 2 additions & 2 deletions x/ccv/provider/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ where create_consumer.json has the following structure:
"denylist": [],
"min_stake": "0",
"allow_inactive_vals": false,
"prioritylist": []
"prioritylist": []
},
"allowlisted_reward_denoms": {
"denoms": ["ibc/...", "ibc/..."]
Expand Down Expand Up @@ -354,7 +354,7 @@ where update_consumer.json has the following structure:
"denylist": [],
"min_stake": "0",
"allow_inactive_vals": false,
"prioritylist": []
"prioritylist": []
},
"allowlisted_reward_denoms": {
"denoms": ["ibc/...", "ibc/..."]
Expand Down
17 changes: 8 additions & 9 deletions x/ccv/provider/keeper/power_shaping.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"

"github.com/cosmos/interchain-security/v6/x/ccv/provider/types"
providertypes "github.com/cosmos/interchain-security/v6/x/ccv/provider/types"
kirdatatjana marked this conversation as resolved.
Show resolved Hide resolved
ccvtypes "github.com/cosmos/interchain-security/v6/x/ccv/types"
)

Expand Down Expand Up @@ -628,7 +629,7 @@ func (k Keeper) UpdatePrioritylist(ctx sdk.Context, consumerId string, priorityl

// FilterAndSortPriorityList filters the priority list to include only validators that can validate the chain
kirdatatjana marked this conversation as resolved.
Show resolved Hide resolved
// and splits the validators into priority and non-priority sets.
func (k Keeper) FilterAndSortPriorityList(ctx sdk.Context, priorityList []string, nextValidators []types.ConsensusValidator) ([]types.ConsensusValidator, []types.ConsensusValidator) {
func (k Keeper) FilterAndSortPriorityList(ctx sdk.Context, consumerId string, nextValidators []types.ConsensusValidator) ([]types.ConsensusValidator, []types.ConsensusValidator) {
validatorMap := make(map[string]types.ConsensusValidator)
for _, v := range nextValidators {
validatorMap[string(v.ProviderConsAddr)] = v
kirdatatjana marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -639,14 +640,12 @@ func (k Keeper) FilterAndSortPriorityList(ctx sdk.Context, priorityList []string
addedAddresses := make(map[string]bool)
kirdatatjana marked this conversation as resolved.
Show resolved Hide resolved

// Form priorityValidators
for _, address := range priorityList {
for _, validator := range nextValidators {
if string(validator.ProviderConsAddr) == address {
if !addedAddresses[address] {
priorityValidators = append(priorityValidators, validator)
addedAddresses[address] = true
}
break
for _, validator := range nextValidators {
addr := providertypes.NewProviderConsAddress(validator.ProviderConsAddr)
if k.IsPrioritylisted(ctx, consumerId, addr) {
if !addedAddresses[string(validator.ProviderConsAddr)] {
priorityValidators = append(priorityValidators, validator)
addedAddresses[string(validator.ProviderConsAddr)] = true
}
}
}
Expand Down
132 changes: 22 additions & 110 deletions x/ccv/provider/keeper/power_shaping_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,16 +250,21 @@ func TestCapValidatorSet(t *testing.T) {
providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
defer ctrl.Finish()

validatorA := providertypes.ConsensusValidator{ProviderConsAddr: []byte("providerConsAddrA"), Power: 1, PublicKey: &crypto.PublicKey{}}
validatorB := providertypes.ConsensusValidator{ProviderConsAddr: []byte("providerConsAddrB"), Power: 2, PublicKey: &crypto.PublicKey{}}
validatorC := providertypes.ConsensusValidator{ProviderConsAddr: []byte("providerConsAddrC"), Power: 3, PublicKey: &crypto.PublicKey{}}
validatorD := providertypes.ConsensusValidator{ProviderConsAddr: []byte("providerConsAddrD"), Power: 4, PublicKey: &crypto.PublicKey{}}
consAddrA, _ := sdk.ConsAddressFromBech32("cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6")
consAddrB, _ := sdk.ConsAddressFromBech32("cosmosvalcons1nx7n5uh0ztxsynn4sje6eyq2ud6rc6klc96w39")
consAddrC, _ := sdk.ConsAddressFromBech32("cosmosvalcons1qmq08eruchr5sf5s3rwz7djpr5a25f7xw4mceq")
consAddrD, _ := sdk.ConsAddressFromBech32("cosmosvalcons1kswr5sq599365kcjmhgufevfps9njf43e4lwdk")

validatorA := providertypes.ConsensusValidator{ProviderConsAddr: consAddrA, Power: 1, PublicKey: &crypto.PublicKey{}}
validatorB := providertypes.ConsensusValidator{ProviderConsAddr: consAddrB, Power: 2, PublicKey: &crypto.PublicKey{}}
validatorC := providertypes.ConsensusValidator{ProviderConsAddr: consAddrC, Power: 3, PublicKey: &crypto.PublicKey{}}
validatorD := providertypes.ConsensusValidator{ProviderConsAddr: consAddrD, Power: 4, PublicKey: &crypto.PublicKey{}}
validators := []providertypes.ConsensusValidator{validatorA, validatorB, validatorC, validatorD}

// Initial error check
powerShapingParameters, err := providerKeeper.GetConsumerPowerShapingParameters(ctx, CONSUMER_ID)
require.Error(t, err)
priorityValidators, nonPriorityValidators := providerKeeper.FilterAndSortPriorityList(ctx, powerShapingParameters.Prioritylist, validators)
priorityValidators, nonPriorityValidators := providerKeeper.FilterAndSortPriorityList(ctx, CONSUMER_ID, validators)
consumerValidators := providerKeeper.CapValidatorSet(ctx, powerShapingParameters, append(priorityValidators, nonPriorityValidators...))
require.Equal(t, []providertypes.ConsensusValidator{validatorD, validatorC, validatorB, validatorA}, consumerValidators)

Expand Down Expand Up @@ -296,22 +301,22 @@ func TestCapValidatorSet(t *testing.T) {
},
{
name: "ValidatorSetCap = 2, with priority list",
powerShapingParameters: providertypes.PowerShapingParameters{ValidatorSetCap: 2, Prioritylist: []string{string(validatorA.ProviderConsAddr), string(validatorB.ProviderConsAddr)}},
powerShapingParameters: providertypes.PowerShapingParameters{ValidatorSetCap: 2, Prioritylist: []string{"cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6", "cosmosvalcons1nx7n5uh0ztxsynn4sje6eyq2ud6rc6klc96w39"}},
kirdatatjana marked this conversation as resolved.
Show resolved Hide resolved
expectedValidators: []providertypes.ConsensusValidator{validatorB, validatorA},
},
{
name: "ValidatorSetCap = 3, with partial priority list",
powerShapingParameters: providertypes.PowerShapingParameters{ValidatorSetCap: 3, Prioritylist: []string{string(validatorA.ProviderConsAddr)}},
powerShapingParameters: providertypes.PowerShapingParameters{ValidatorSetCap: 3, Prioritylist: []string{"cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6"}},
expectedValidators: []providertypes.ConsensusValidator{validatorA, validatorD, validatorC},
},
{
name: "All validators in priority list",
powerShapingParameters: providertypes.PowerShapingParameters{ValidatorSetCap: 4, Prioritylist: []string{string(validatorC.ProviderConsAddr), string(validatorA.ProviderConsAddr), string(validatorD.ProviderConsAddr), string(validatorB.ProviderConsAddr)}},
powerShapingParameters: providertypes.PowerShapingParameters{ValidatorSetCap: 4, Prioritylist: []string{"cosmosvalcons1qmq08eruchr5sf5s3rwz7djpr5a25f7xw4mceq", "cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6", "cosmosvalcons1kswr5sq599365kcjmhgufevfps9njf43e4lwdk", "cosmosvalcons1nx7n5uh0ztxsynn4sje6eyq2ud6rc6klc96w39"}},
expectedValidators: []providertypes.ConsensusValidator{validatorD, validatorC, validatorB, validatorA},
},
{
name: "ValidatorSetCap = 1 (capping to highest power, with priority list)",
powerShapingParameters: providertypes.PowerShapingParameters{ValidatorSetCap: 1, Prioritylist: []string{string(validatorA.ProviderConsAddr)}},
powerShapingParameters: providertypes.PowerShapingParameters{ValidatorSetCap: 1, Prioritylist: []string{"cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6"}},
expectedValidators: []providertypes.ConsensusValidator{validatorA},
},
kirdatatjana marked this conversation as resolved.
Show resolved Hide resolved
}
Expand All @@ -328,9 +333,8 @@ func TestCapValidatorSet(t *testing.T) {
require.NoError(t, err)
require.Equal(t, tc.powerShapingParameters, powerShapingParameters)
}

priorityValidators, nonPriorityValidators := providerKeeper.FilterAndSortPriorityList(ctx, tc.powerShapingParameters.Prioritylist, validators)
consumerValidators := providerKeeper.CapValidatorSet(ctx, tc.powerShapingParameters, append(priorityValidators, nonPriorityValidators...))
priorityValidators, nonPriorityValidators := providerKeeper.FilterAndSortPriorityList(ctx, CONSUMER_ID, validators)
consumerValidators := providerKeeper.CapValidatorSet(ctx, powerShapingParameters, append(priorityValidators, nonPriorityValidators...))
require.Equal(t, tc.expectedValidators, consumerValidators)
})
}
Expand Down Expand Up @@ -767,13 +771,16 @@ func TestConsumerPowerShapingParameters(t *testing.T) {
sortProviderConsAddr(expectedAllowlist)
expectedDenylist := []providertypes.ProviderConsAddress{providerConsAddr[2], providerConsAddr[3]}
sortProviderConsAddr(expectedDenylist)
expectedPrioritylist := []providertypes.ProviderConsAddress{providerConsAddr[1]}
sortProviderConsAddr(expectedPrioritylist)
err = providerKeeper.SetConsumerPowerShapingParameters(ctx, consumerId, expectedPowerShapingParameters)
require.NoError(t, err)
actualPowerShapingParameters, err := providerKeeper.GetConsumerPowerShapingParameters(ctx, consumerId)
require.NoError(t, err)
require.Equal(t, expectedPowerShapingParameters, actualPowerShapingParameters)
require.Equal(t, expectedAllowlist, providerKeeper.GetAllowList(ctx, consumerId))
require.Equal(t, expectedDenylist, providerKeeper.GetDenyList(ctx, consumerId))
require.Equal(t, expectedPrioritylist, providerKeeper.GetPriorityList(ctx, consumerId))
kirdatatjana marked this conversation as resolved.
Show resolved Hide resolved

// assert that overwriting the current initialization record works
expectedPowerShapingParameters = providertypes.PowerShapingParameters{
Expand All @@ -790,13 +797,16 @@ func TestConsumerPowerShapingParameters(t *testing.T) {
sortProviderConsAddr(expectedAllowlist)
expectedDenylist = []providertypes.ProviderConsAddress{providerConsAddr[2], providerConsAddr[3]}
sortProviderConsAddr(expectedDenylist)
expectedPrioritylist = []providertypes.ProviderConsAddress{providerConsAddr[4], providerConsAddr[5]}
sortProviderConsAddr(expectedAllowlist)
err = providerKeeper.SetConsumerPowerShapingParameters(ctx, consumerId, expectedPowerShapingParameters)
require.NoError(t, err)
actualPowerShapingParameters, err = providerKeeper.GetConsumerPowerShapingParameters(ctx, consumerId)
require.NoError(t, err)
require.Equal(t, expectedPowerShapingParameters, actualPowerShapingParameters)
require.Equal(t, expectedAllowlist, providerKeeper.GetAllowList(ctx, consumerId))
require.Equal(t, expectedDenylist, providerKeeper.GetDenyList(ctx, consumerId))
require.Equal(t, expectedPrioritylist, providerKeeper.GetPriorityList(ctx, consumerId))
}

// TestAllowlist tests the `SetAllowlist`, `IsAllowlisted`, `DeleteAllowlist`, and `IsAllowlistEmpty` methods
Expand Down Expand Up @@ -1071,101 +1081,3 @@ func TestUpdatePrioritylist(t *testing.T) {
}
require.Equal(t, expectedPrioritylist, providerKeeper.GetPriorityList(ctx, consumerId))
}

func TestFilterAndSortPriorityList(t *testing.T) {
kirdatatjana marked this conversation as resolved.
Show resolved Hide resolved
providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
defer ctrl.Finish()

// Create test validators
validator1 := providertypes.ConsensusValidator{
ProviderConsAddr: []byte("providerConsAddr1"),
Power: 300,
PublicKey: &crypto.PublicKey{},
}
validator2 := providertypes.ConsensusValidator{
ProviderConsAddr: []byte("providerConsAddr2"),
Power: 200,
PublicKey: &crypto.PublicKey{},
}
validator3 := providertypes.ConsensusValidator{
ProviderConsAddr: []byte("providerConsAddr3"),
Power: 150,
PublicKey: &crypto.PublicKey{},
}
validator4 := providertypes.ConsensusValidator{
ProviderConsAddr: []byte("providerConsAddr4"),
Power: 50,
PublicKey: &crypto.PublicKey{},
}

validators := []providertypes.ConsensusValidator{validator1, validator2, validator3, validator4}

testCases := []struct {
name string
priorityList []string
expectedPriority []providertypes.ConsensusValidator
expectedNonPriority []providertypes.ConsensusValidator
}{
{
name: "Empty priority list",
priorityList: []string{},
expectedPriority: []providertypes.ConsensusValidator{},
expectedNonPriority: []providertypes.ConsensusValidator{validator1, validator2, validator3, validator4},
},
{
name: "Priority list with non-existent addresses",
priorityList: []string{"providerConsAddr5", "providerConsAddr6"},
expectedPriority: []providertypes.ConsensusValidator{},
expectedNonPriority: []providertypes.ConsensusValidator{validator1, validator2, validator3, validator4},
},
{
name: "Priority list with some existing addresses",
priorityList: []string{"providerConsAddr2", "providerConsAddr5", "providerConsAddr4"},
expectedPriority: []providertypes.ConsensusValidator{validator2, validator4},
expectedNonPriority: []providertypes.ConsensusValidator{validator1, validator3},
},
{
name: "Priority list with all existing addresses",
priorityList: []string{"providerConsAddr4", "providerConsAddr1", "providerConsAddr3", "providerConsAddr2"},
expectedPriority: []providertypes.ConsensusValidator{validator1, validator2, validator3, validator4},
expectedNonPriority: []providertypes.ConsensusValidator{},
},
{
name: "Priority list with duplicate addresses",
priorityList: []string{"providerConsAddr1", "providerConsAddr2", "providerConsAddr1", "providerConsAddr3"},
expectedPriority: []providertypes.ConsensusValidator{validator1, validator2, validator3},
expectedNonPriority: []providertypes.ConsensusValidator{validator4},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
priorityResult, nonPriorityResult := providerKeeper.FilterAndSortPriorityList(ctx, tc.priorityList, validators)

// Check priority validators
require.Equal(t, len(tc.expectedPriority), len(priorityResult), "Length of priority result doesn't match expected")
for i, v := range priorityResult {
require.Equal(t, tc.expectedPriority[i].ProviderConsAddr, v.ProviderConsAddr, "Priority validator address doesn't match expected at index %d", i)
require.Equal(t, tc.expectedPriority[i].Power, v.Power, "Priority validator power doesn't match expected at index %d", i)
}

// Check non-priority validators
require.Equal(t, len(tc.expectedNonPriority), len(nonPriorityResult), "Length of non-priority result doesn't match expected")
for i, v := range nonPriorityResult {
require.Equal(t, tc.expectedNonPriority[i].ProviderConsAddr, v.ProviderConsAddr, "Non-priority validator address doesn't match expected at index %d", i)
require.Equal(t, tc.expectedNonPriority[i].Power, v.Power, "Non-priority validator power doesn't match expected at index %d", i)
}

// Check if both results are sorted by power in descending order
checkSortedByPower(t, priorityResult)
checkSortedByPower(t, nonPriorityResult)
})
}
}

// Checks if validators are sorted by power in descending order
func checkSortedByPower(t *testing.T, validators []providertypes.ConsensusValidator) {
for i := 1; i < len(validators); i++ {
require.GreaterOrEqual(t, validators[i-1].Power, validators[i].Power, "Validators are not sorted by power in descending order")
}
}
2 changes: 1 addition & 1 deletion x/ccv/provider/keeper/validator_set_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ func (k Keeper) ComputeNextValidators(
return []types.ConsensusValidator{}, err
}

priorityValidators, nonPriorityValidators := k.FilterAndSortPriorityList(ctx, powerShapingParameters.Prioritylist, nextValidators)
priorityValidators, nonPriorityValidators := k.FilterAndSortPriorityList(ctx, consumerId, nextValidators)

nextValidators = k.CapValidatorSet(ctx, powerShapingParameters, append(priorityValidators, nonPriorityValidators...))

Expand Down
Loading