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!: enable unjail on pre-ccv chains #2396

Merged
merged 11 commits into from
Dec 11, 2024
4 changes: 3 additions & 1 deletion scripts/test_doc/test_documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
|----------|-------------------|
[TestDemocracyRewardsDistribution](../../tests/integration/democracy.go#L77) | TestDemocracyRewardsDistribution checks that rewards to democracy representatives, community pool, and provider redistribution account are done correctly.<details><summary>Details</summary>* Set up a democracy consumer chain.<br>* Create a new block.<br>* Check that rewards to democracy representatives, community pool, and provider redistribution account are distributed in the right proportions.</details> |
[TestDemocracyMsgUpdateParams](../../tests/integration/democracy.go#L187) | TestDemocracyMsgUpdateParams checks that the consumer parameters can be updated through a governance proposal.<details><summary>Details</summary>* Set up a democracy consumer chain.<br>* Submit a proposal containing changes to the consumer module parameters.<br>* Check that the proposal is executed, and the parameters are updated.</details> |
[TestDemocracyValidatorUnjail](../../tests/integration/democracy.go#L243) | TestDemocracyValidatorUnjail checks that the consumer validator can be unjailed when there is a standalone staking keeper available.<details><summary>Details</summary>* Set up a democracy consumer chain.<br>* Jail a validator.<br>* Check that the validator is jailed.<br>* Unjail the validator.<br>* Check that the validator is unjailed.</details> |
</details>

# [distribution.go](../../tests/integration/distribution.go)
Expand Down Expand Up @@ -127,7 +128,8 @@

| Function | Short Description |
|----------|-------------------|
[TestUndelegationCompletion](../../tests/integration/unbonding.go#L16) | TestUndelegationCompletion tests that undelegations complete after the unbonding period elapses on the provider, regardless of the consumer's state<details><summary>Details</summary>* Set up CCV channel.<br>* Perform initial delegation of tokens followed by a partial undelegation (1/4 of the tokens).<br>* Verify that the staking unbonding operation is created as expected.<br>* Increment provider block height.<br>* Check that the unbonding operation has been completed.<br>* Verify that the token balances are correctly updated and the expected amount of tokens has been returned to the account.</details> |
[TestUndelegationCompletion](../../tests/integration/unbonding.go#L17) | TestUndelegationCompletion tests that undelegations complete after the unbonding period elapses on the provider, regardless of the consumer's state<details><summary>Details</summary>* Set up CCV channel.<br>* Perform initial delegation of tokens followed by a partial undelegation (1/4 of the tokens).<br>* Verify that the staking unbonding operation is created as expected.<br>* Increment provider block height.<br>* Check that the unbonding operation has been completed.<br>* Verify that the token balances are correctly updated and the expected amount of tokens has been returned to the account.</details> |
[TestConsumerUnjailNoOp](../../tests/integration/unbonding.go#L50) | TestConsumerUnjailNoOp check that consumerKeeper can call .Unjail() without error. This operation must only be available in case the app also implements a "standalone" staking keeper. |
</details>

# [valset_update.go](../../tests/integration/valset_update.go)
Expand Down
46 changes: 46 additions & 0 deletions tests/integration/democracy.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,52 @@ func (s *ConsumerDemocracyTestSuite) TestDemocracyMsgUpdateParams() {
s.Assert().Equal(votersOldBalances, getAccountsBalances(s.consumerCtx(), bankKeeper, bondDenom, votingAccounts))
}

// TestDemocracyValidatorUnjail checks that the consumer validator can be unjailed when there is a standalone staking keeper available.
// @Long Description@
// * Set up a democracy consumer chain.
// * Jail a validator.
// * Check that the validator is jailed.
// * Unjail the validator.
// * Check that the validator is unjailed.
func (s *ConsumerDemocracyTestSuite) TestDemocracyValidatorUnjail() {
stakingKeeper := s.consumerApp.GetTestStakingKeeper()
consumerKeeper := s.consumerApp.GetConsumerKeeper()

validators, err := stakingKeeper.GetAllValidators(s.consumerCtx())
s.Require().NoError(err)

// setting up pre-conditions
// validator[0] is expected to be jailed
expectJailed := validators[0]
consAddr, err := expectJailed.GetConsAddr()
s.Require().NoError(err)
stakingKeeper.GetValidatorSet().Jail(s.consumerCtx(), consAddr)

s.consumerChain.NextBlock()

validators, err = stakingKeeper.GetAllValidators(s.consumerCtx())
s.Require().NoError(err)
for _, validator := range validators {
if validator.OperatorAddress == expectJailed.OperatorAddress {
s.Require().True(validator.IsJailed())
} else {
s.Require().False(validator.IsJailed())
}
}

// confirm unjail will not error and properly unjail
// in case of a consumer chain without standalone staking the call is a no-op
err = consumerKeeper.Unjail(s.consumerCtx(), consAddr)
s.Require().NoError(err)
s.consumerChain.NextBlock()

validators, err = stakingKeeper.GetAllValidators(s.consumerCtx())
s.Require().NoError(err)
for _, validator := range validators {
s.Require().False(validator.IsJailed())
}
}

func submitProposalWithDepositAndVote(govKeeper govkeeper.Keeper, ctx sdk.Context, msgs []sdk.Msg,
accounts []ibctesting.SenderAccount, proposer sdk.AccAddress, depositAmount sdk.Coins,
) error {
Expand Down
11 changes: 11 additions & 0 deletions tests/integration/unbonding.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package integration

import (
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
)

// TestUndelegationCompletion tests that undelegations complete after
Expand Down Expand Up @@ -43,3 +44,13 @@ func (s *CCVTestSuite) TestUndelegationCompletion() {
"unexpected initial balance after unbonding; test: %s",
)
}

// TestConsumerUnjailNoOp check that consumerKeeper can call .Unjail() without error.
// This operation must only be available in case the app also implements a "standalone" staking keeper.
func (s *CCVTestSuite) TestConsumerUnjailNoOp() {
consumerKeeper := s.consumerApp.GetConsumerKeeper()

// this is a no-op
err := consumerKeeper.Unjail(s.consumerCtx(), sdk.ConsAddress([]byte{0x01, 0x02, 0x03}))
s.Require().NoError(err)
}
8 changes: 8 additions & 0 deletions testutil/integration/debug_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ func TestDemocracyMsgUpdateParams(t *testing.T) {
runConsumerDemocracyTestByName(t, "TestDemocracyMsgUpdateParams")
}

func TestDemocracyUnjail(t *testing.T) {
runConsumerDemocracyTestByName(t, "TestDemocracyValidatorUnjail")
}

//
// Distribution tests
//
Expand Down Expand Up @@ -193,6 +197,10 @@ func TestUndelegationCompletion(t *testing.T) {
runCCVTestByName(t, "TestUndelegationCompletion")
}

func TestConsumerUnjailNoOp(t *testing.T) {
runCCVTestByName(t, "TestConsumerUnjailNoOp")
}

//
// Val set update tests
//
Expand Down
2 changes: 1 addition & 1 deletion x/ccv/consumer/keeper/changeover.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
// ChangeoverIsComplete returns whether the standalone to consumer changeover process is complete.
func (k Keeper) ChangeoverIsComplete(ctx sdk.Context) bool {
if !k.IsPrevStandaloneChain(ctx) {
panic("ChangeoverIsComplete should only be called on previously standalone consumers")
return true
}
return ctx.BlockHeight() >= k.FirstConsumerHeight(ctx)
}
Expand Down
35 changes: 24 additions & 11 deletions x/ccv/consumer/keeper/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,14 @@ func (k Keeper) IterateValidators(context.Context, func(index int64, validator s
return nil
}

// Validator - unimplemented on CCV keeper
func (k Keeper) Validator(ctx context.Context, addr sdk.ValAddress) (stakingtypes.ValidatorI, error) {
panic("unimplemented on CCV keeper")
// Validator - unimplemented on CCV keeper but implemented on standalone keeper
func (k Keeper) Validator(sdkCtx context.Context, addr sdk.ValAddress) (stakingtypes.ValidatorI, error) {
ctx := sdk.UnwrapSDKContext(sdkCtx)
if k.ChangeoverIsComplete(ctx) && k.standaloneStakingKeeper != nil {
return k.standaloneStakingKeeper.Validator(ctx, addr)
}

return stakingtypes.Validator{}, errors.New("unimplemented on CCV keeper")
}

// IsJailed returns the outstanding slashing flag for the given validator address
Expand Down Expand Up @@ -174,16 +179,24 @@ func (k Keeper) SlashWithInfractionReason(goCtx context.Context, addr sdk.ConsAd
// the provider validator set will soon be in effect, and jailing is n/a.
func (k Keeper) Jail(context.Context, sdk.ConsAddress) error { return nil }

// Unjail - unimplemented on CCV keeper
// Unjail is enabled for previously standalone chains and chains implementing democracy staking.
//
// This method should be a no-op even during a standalone to consumer changeover.
// Once the upgrade has happened as a part of the changeover,
// the provider validator set will soon be in effect, and jailing is n/a.
func (k Keeper) Unjail(context.Context, sdk.ConsAddress) error { return nil }
// This method should be a no-op for consumer chains that launched with the CCV module first.
func (k Keeper) Unjail(sdkCtx context.Context, addr sdk.ConsAddress) error {
ctx := sdk.UnwrapSDKContext(sdkCtx)
if k.ChangeoverIsComplete(ctx) && k.standaloneStakingKeeper != nil {
return k.standaloneStakingKeeper.Unjail(ctx, addr)
}
return nil
MSalopek marked this conversation as resolved.
Show resolved Hide resolved
}

// Delegation - unimplemented on CCV keeper
func (k Keeper) Delegation(ctx context.Context, addr sdk.AccAddress, valAddr sdk.ValAddress) (stakingtypes.DelegationI, error) {
panic("unimplemented on CCV keeper")
// Delegation - unimplemented on CCV keeper but implemented on standalone keeper
func (k Keeper) Delegation(sdkCtx context.Context, addr sdk.AccAddress, valAddr sdk.ValAddress) (stakingtypes.DelegationI, error) {
ctx := sdk.UnwrapSDKContext(sdkCtx)
if k.ChangeoverIsComplete(ctx) && k.standaloneStakingKeeper != nil {
return k.standaloneStakingKeeper.Delegation(ctx, addr, valAddr)
}
return stakingtypes.Delegation{}, errors.New("unimplemented on CCV keeper")
}

// MaxValidators - unimplemented on CCV keeper
Expand Down
7 changes: 7 additions & 0 deletions x/ccv/consumer/keeper/validators_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,13 @@ func TestIsValidatorJailed(t *testing.T) {
isJailed3, err := consumerKeeper.IsValidatorJailed(ctx, consAddr)
require.NoError(t, err)
require.True(t, isJailed3)

// confirm that unjail returns no error and validator remains jailed
mocks.MockStakingKeeper.EXPECT().IsValidatorJailed(ctx, consAddr).Return(true, nil).Times(1)
require.NoError(t, consumerKeeper.Unjail(ctx, consAddr))
isJailed3, err = consumerKeeper.IsValidatorJailed(ctx, consAddr)
require.NoError(t, err)
require.True(t, isJailed3)
}

func TestSlash(t *testing.T) {
Expand Down