Skip to content

Commit

Permalink
feat!: Add slashing logic for PSS (#1710)
Browse files Browse the repository at this point in the history
* add check for consumer validators in downtime logic

* fix UT

* try to fix weird errors in gh worfklow

* fix silly merge bug

* nits
  • Loading branch information
sainoe committed Mar 20, 2024
1 parent 31a9ee3 commit 3ca33ec
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 22 deletions.
1 change: 0 additions & 1 deletion x/ccv/provider/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

ibctesting "github.com/cosmos/ibc-go/v7/testing"
"github.com/stretchr/testify/require"

cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
sdk "github.com/cosmos/cosmos-sdk/types"

Expand Down
8 changes: 8 additions & 0 deletions x/ccv/provider/keeper/relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,14 @@ func (k Keeper) HandleSlashPacket(ctx sdk.Context, chainID string, data ccv.Slas
"infractionType", data.Infraction,
)

// Check that the validator belongs to the consumer chain valset
if !k.IsConsumerValidator(ctx, chainID, providerConsAddr) {
k.Logger(ctx).Error("cannot jail validator %s that does not belong to consumer %s valset",
providerConsAddr.String(), chainID)
// drop packet
return
}

// Obtain validator from staking keeper
validator, found := k.stakingKeeper.GetValidatorByConsAddr(ctx, providerConsAddr.ToSdkConsAddr())

Expand Down
65 changes: 44 additions & 21 deletions x/ccv/provider/keeper/relay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
cryptotestutil "github.com/cosmos/interchain-security/v4/testutil/crypto"
testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
"github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
"github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
)
Expand Down Expand Up @@ -136,6 +137,9 @@ func TestOnRecvDowntimeSlashPacket(t *testing.T) {
// Now set slash meter to positive value and assert slash packet handled result is returned
providerKeeper.SetSlashMeter(ctx, math.NewInt(5))

// Set the consumer validator
providerKeeper.SetConsumerValidator(ctx, "chain-1", types.ConsumerValidator{ProviderConsAddr: packetData.Validator.Address})

// Mock call to GetEffectiveValPower, so that it returns 2.
providerAddr := providertypes.NewProviderConsAddress(packetData.Validator.Address)
calls := []*gomock.Call{
Expand Down Expand Up @@ -289,8 +293,11 @@ func TestValidateSlashPacket(t *testing.T) {
func TestHandleSlashPacket(t *testing.T) {
chainId := "consumer-id"
validVscID := uint64(234)

providerConsAddr := cryptotestutil.NewCryptoIdentityFromIntSeed(7842334).ProviderConsAddress()
consumerConsAddr := cryptotestutil.NewCryptoIdentityFromIntSeed(784987634).ConsumerConsAddress()
// this "dummy" consensus address won't be stored on the provider states
dummyConsAddr := cryptotestutil.NewCryptoIdentityFromIntSeed(784987639).ConsumerConsAddress()

testCases := []struct {
name string
Expand All @@ -299,6 +306,20 @@ func TestHandleSlashPacket(t *testing.T) {
expectedCalls func(sdk.Context, testkeeper.MockedKeepers, ccv.SlashPacketData) []*gomock.Call
expectedSlashAcksLen int
}{
{
"validator isn't a consumer validator",
ccv.SlashPacketData{
Validator: abci.Validator{Address: dummyConsAddr.ToSdkConsAddr()},
ValsetUpdateId: validVscID,
Infraction: stakingtypes.Infraction_INFRACTION_DOWNTIME,
},
func(ctx sdk.Context, mocks testkeeper.MockedKeepers,
expectedPacketData ccv.SlashPacketData,
) []*gomock.Call {
return []*gomock.Call{}
},
0,
},
{
"unfound validator",
ccv.SlashPacketData{
Expand Down Expand Up @@ -403,34 +424,36 @@ func TestHandleSlashPacket(t *testing.T) {
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(
t, testkeeper.NewInMemKeeperParams(t))

providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(
t, testkeeper.NewInMemKeeperParams(t))

// Setup expected mock calls
gomock.InOrder(tc.expectedCalls(ctx, mocks, tc.packetData)...)
// Setup expected mock calls
gomock.InOrder(tc.expectedCalls(ctx, mocks, tc.packetData)...)

// Setup init chain height and a single valid valset update ID to block height mapping.
providerKeeper.SetInitChainHeight(ctx, chainId, 5)
providerKeeper.SetValsetUpdateBlockHeight(ctx, validVscID, 99)
// Setup init chain height and a single valid valset update ID to block height mapping.
providerKeeper.SetInitChainHeight(ctx, chainId, 5)
providerKeeper.SetValsetUpdateBlockHeight(ctx, validVscID, 99)

// Setup consumer address to provider address mapping.
require.NotEmpty(t, tc.packetData.Validator.Address)
providerKeeper.SetValidatorByConsumerAddr(ctx, chainId, consumerConsAddr, providerConsAddr)
// Setup consumer address to provider address mapping.
require.NotEmpty(t, tc.packetData.Validator.Address)
providerKeeper.SetValidatorByConsumerAddr(ctx, chainId, consumerConsAddr, providerConsAddr)
providerKeeper.SetConsumerValidator(ctx, chainId, types.ConsumerValidator{ProviderConsAddr: providerConsAddr.Address.Bytes()})

// Execute method and assert expected mock calls.
providerKeeper.HandleSlashPacket(ctx, chainId, tc.packetData)
// Execute method and assert expected mock calls.
providerKeeper.HandleSlashPacket(ctx, chainId, tc.packetData)

require.Equal(t, tc.expectedSlashAcksLen, len(providerKeeper.GetSlashAcks(ctx, chainId)))
require.Equal(t, tc.expectedSlashAcksLen, len(providerKeeper.GetSlashAcks(ctx, chainId)))

if tc.expectedSlashAcksLen == 1 {
// must match the consumer address
require.Equal(t, consumerConsAddr.String(), providerKeeper.GetSlashAcks(ctx, chainId)[0])
require.NotEqual(t, providerConsAddr.String(), providerKeeper.GetSlashAcks(ctx, chainId)[0])
require.NotEqual(t, providerConsAddr.String(), consumerConsAddr.String())
}
if tc.expectedSlashAcksLen == 1 {
// must match the consumer address
require.Equal(t, consumerConsAddr.String(), providerKeeper.GetSlashAcks(ctx, chainId)[0])
require.NotEqual(t, providerConsAddr.String(), providerKeeper.GetSlashAcks(ctx, chainId)[0])
require.NotEqual(t, providerConsAddr.String(), consumerConsAddr.String())
}

ctrl.Finish()
ctrl.Finish()
})
}
}

Expand Down

0 comments on commit 3ca33ec

Please sign in to comment.