Skip to content

Commit

Permalink
Merge branch 'main' into dong/TestRemoveZoneAndAssociatedRecords
Browse files Browse the repository at this point in the history
  • Loading branch information
DongLieu committed Nov 6, 2023
2 parents 1d0e32e + 6c56845 commit 14dcb33
Show file tree
Hide file tree
Showing 13 changed files with 2,226 additions and 5,799 deletions.
6,787 changes: 1,485 additions & 5,302 deletions docs/swagger.yml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package quicksilver.interchainstaking.v1;
import "cosmos/base/v1beta1/coin.proto";
import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
import "google/protobuf/timestamp.proto";

option go_package = "github.com/quicksilver-zone/quicksilver/x/interchainstaking/types";
Expand Down Expand Up @@ -158,8 +157,6 @@ message Validator {
(gogoproto.nullable) = false,
(gogoproto.stdtime) = true
];
// consensus_pubkey is the consensus public key of the validator, as a Protobuf Any.
google.protobuf.Any consensus_pubkey = 10 [(cosmos_proto.accepts_interface) = "cosmos.crypto.PubKey"];
}

message DelegatorIntent {
Expand Down
60 changes: 59 additions & 1 deletion x/interchainstaking/keeper/callbacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"

clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
Expand Down Expand Up @@ -76,7 +77,8 @@ func (c Callbacks) RegisterCallbacks() icqtypes.QueryCallbacks {
AddCallback("perfbalance", Callback(PerfBalanceCallback)).
AddCallback("accountbalance", Callback(AccountBalanceCallback)).
AddCallback("allbalances", Callback(AllBalancesCallback)).
AddCallback("delegationaccountbalance", Callback(DelegationAccountBalanceCallback))
AddCallback("delegationaccountbalance", Callback(DelegationAccountBalanceCallback)).
AddCallback("signinginfo", Callback(SigningInfoCallback))

return a.(Callbacks)
}
Expand Down Expand Up @@ -258,6 +260,62 @@ func DepositIntervalCallback(k *Keeper, ctx sdk.Context, args []byte, query icqt
return nil
}

func SigningInfoCallback(k *Keeper, ctx sdk.Context, args []byte, query icqtypes.Query) error {
zone, found := k.GetZone(ctx, query.GetChainId())
if !found {
return fmt.Errorf("no registered zone for chain id: %s", zone.ChainId)
}

k.Logger(ctx).Debug("Validator signing info callback", "zone", zone.ChainId)

valSigningInfo := slashingtypes.ValidatorSigningInfo{}
if len(args) == 0 {
return errors.New("attempted to unmarshal zero length byte slice (10)")
}
err := k.cdc.Unmarshal(args, &valSigningInfo)
if err != nil {
return err
}
if valSigningInfo.Tombstoned {
consAddr, err := sdk.ConsAddressFromBech32(valSigningInfo.Address)
if err != nil {
return err
}
valAddr, found := k.GetValidatorAddrByConsAddr(ctx, zone.ChainId, consAddr)
if !found {
return fmt.Errorf("can not get validator address from consensus address: %s", valSigningInfo.Address)
}

k.Logger(ctx).Error("Tombstoned validator found", "valoper", valAddr)

valAddrBytes, err := addressutils.ValAddressFromBech32(valAddr, zone.GetValoperPrefix())
if err != nil {
return err
}
val, found := k.GetValidator(ctx, zone.ChainId, valAddrBytes)
if !found {
err := k.SetValidator(ctx, zone.ChainId, types.Validator{
ValoperAddress: valAddr,
Jailed: true,
Tombstoned: true,
})
if err != nil {
return err
}
} else {
val.Tombstoned = true
if err = k.SetValidator(ctx, zone.ChainId, val); err != nil {
return err
}
}
k.Logger(ctx).Info("%q on chainID: %q was found to already have been tombstoned, added information", val.ValoperAddress, zone.ChainId)

return nil
}

return nil
}

// pulled directly from ibc-go tm light client
// checkTrustedHeader checks that consensus state matches trusted fields of Header.
func checkTrustedHeader(header *tmclienttypes.Header, consState *tmclienttypes.ConsensusState) error {
Expand Down
220 changes: 217 additions & 3 deletions x/interchainstaking/keeper/callbacks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@ import (

"cosmossdk.io/math"

codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/bech32"
"github.com/cosmos/cosmos-sdk/types/query"
"github.com/cosmos/cosmos-sdk/types/tx"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"

ibctypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
Expand Down Expand Up @@ -466,6 +469,8 @@ func (suite *KeeperTestSuite) TestHandleValidatorCallback() {

func (suite *KeeperTestSuite) TestHandleValidatorCallbackJailedWithSlashing() {
completion := time.Now().UTC().Add(time.Hour)
pkAny, err := codectypes.NewAnyWithValue(PKs[0])
suite.Require().NoError(err)

tests := []struct {
name string
Expand All @@ -478,7 +483,7 @@ func (suite *KeeperTestSuite) TestHandleValidatorCallbackJailedWithSlashing() {
name: "jailed; single distribution",
validator: func(ctx sdk.Context, qs *app.Quicksilver, zone icstypes.Zone) *stakingtypes.Validator {
vals := qs.InterchainstakingKeeper.GetValidators(ctx, zone.ChainId)
return &stakingtypes.Validator{OperatorAddress: vals[0].ValoperAddress, Jailed: true, Status: stakingtypes.Bonded, Tokens: vals[0].VotingPower.Mul(sdk.NewInt(19)).Quo(sdk.NewInt(20)), DelegatorShares: vals[0].DelegatorShares, Commission: stakingtypes.NewCommission(vals[0].CommissionRate, sdk.MustNewDecFromStr("0.5"), sdk.MustNewDecFromStr("0.5"))}
return &stakingtypes.Validator{OperatorAddress: vals[0].ValoperAddress, ConsensusPubkey: pkAny, Jailed: true, Status: stakingtypes.Bonded, Tokens: vals[0].VotingPower.Mul(sdk.NewInt(19)).Quo(sdk.NewInt(20)), DelegatorShares: vals[0].DelegatorShares, Commission: stakingtypes.NewCommission(vals[0].CommissionRate, sdk.MustNewDecFromStr("0.5"), sdk.MustNewDecFromStr("0.5"))}
},
expected: func(ctx sdk.Context, qs *app.Quicksilver, zone icstypes.Zone) *icstypes.Validator {
vals := qs.InterchainstakingKeeper.GetValidators(ctx, zone.ChainId)
Expand Down Expand Up @@ -528,7 +533,7 @@ func (suite *KeeperTestSuite) TestHandleValidatorCallbackJailedWithSlashing() {
name: "jailed; multi distribution",
validator: func(ctx sdk.Context, qs *app.Quicksilver, zone icstypes.Zone) *stakingtypes.Validator {
vals := qs.InterchainstakingKeeper.GetValidators(ctx, zone.ChainId)
return &stakingtypes.Validator{OperatorAddress: vals[0].ValoperAddress, Jailed: true, Status: stakingtypes.Bonded, Tokens: vals[0].VotingPower.Mul(sdk.NewInt(19)).Quo(sdk.NewInt(20)), DelegatorShares: vals[0].DelegatorShares, Commission: stakingtypes.NewCommission(vals[0].CommissionRate, sdk.MustNewDecFromStr("0.5"), sdk.MustNewDecFromStr("0.5"))}
return &stakingtypes.Validator{OperatorAddress: vals[0].ValoperAddress, ConsensusPubkey: pkAny, Jailed: true, Status: stakingtypes.Bonded, Tokens: vals[0].VotingPower.Mul(sdk.NewInt(19)).Quo(sdk.NewInt(20)), DelegatorShares: vals[0].DelegatorShares, Commission: stakingtypes.NewCommission(vals[0].CommissionRate, sdk.MustNewDecFromStr("0.5"), sdk.MustNewDecFromStr("0.5"))}
},
expected: func(ctx sdk.Context, qs *app.Quicksilver, zone icstypes.Zone) *icstypes.Validator {
vals := qs.InterchainstakingKeeper.GetValidators(ctx, zone.ChainId)
Expand Down Expand Up @@ -586,7 +591,7 @@ func (suite *KeeperTestSuite) TestHandleValidatorCallbackJailedWithSlashing() {
name: "jailed; multi distribution, unrelated validators - no-op",
validator: func(ctx sdk.Context, qs *app.Quicksilver, zone icstypes.Zone) *stakingtypes.Validator {
vals := qs.InterchainstakingKeeper.GetValidators(ctx, zone.ChainId)
return &stakingtypes.Validator{OperatorAddress: vals[0].ValoperAddress, Jailed: true, Status: stakingtypes.Bonded, Tokens: vals[0].VotingPower.Mul(sdk.NewInt(19)).Quo(sdk.NewInt(20)), DelegatorShares: vals[0].DelegatorShares, Commission: stakingtypes.NewCommission(vals[0].CommissionRate, sdk.MustNewDecFromStr("0.5"), sdk.MustNewDecFromStr("0.5"))}
return &stakingtypes.Validator{OperatorAddress: vals[0].ValoperAddress, ConsensusPubkey: pkAny, Jailed: true, Status: stakingtypes.Bonded, Tokens: vals[0].VotingPower.Mul(sdk.NewInt(19)).Quo(sdk.NewInt(20)), DelegatorShares: vals[0].DelegatorShares, Commission: stakingtypes.NewCommission(vals[0].CommissionRate, sdk.MustNewDecFromStr("0.5"), sdk.MustNewDecFromStr("0.5"))}
},
expected: func(ctx sdk.Context, qs *app.Quicksilver, zone icstypes.Zone) *icstypes.Validator {
vals := qs.InterchainstakingKeeper.GetValidators(ctx, zone.ChainId)
Expand Down Expand Up @@ -1954,6 +1959,215 @@ func (suite *KeeperTestSuite) TestDepositTxCallback() {
}
}

func (suite *KeeperTestSuite) TestSigningInfoCallback() {
validator := addressutils.GenerateValAddressForTest()
pubKey := simapp.CreateTestPubKeys(1)[0]

pkAny, err := codectypes.NewAnyWithValue(pubKey)
suite.Require().NoError(err)

newValidator := stakingtypes.Validator{
OperatorAddress: validator.String(),
ConsensusPubkey: pkAny,
}
consAddr, err := newValidator.GetConsAddr()
suite.NoError(err)

bech32ConsAddress := addressutils.MustEncodeAddressToBech32(sdk.Bech32PrefixConsAddr, consAddr)
testCases := []struct {
name string
malleate func(quicksilver *app.Quicksilver, ctx sdk.Context) []byte
query icqtypes.Query
expectErr bool
check func(quicksilver *app.Quicksilver, ctx sdk.Context)
}{
// successful callback tombstoned validator
{
name: "successful callback not tombstoned validator ",
malleate: func(quicksilver *app.Quicksilver, ctx sdk.Context) []byte {
info := slashingtypes.ValidatorSigningInfo{
Tombstoned: false,
}
cdc := quicksilver.InterchainstakingKeeper.GetCodec()
bz := cdc.MustMarshal(&info)
return bz
},
query: icqtypes.Query{
ChainId: suite.chainB.ChainID,
},
expectErr: false,
check: func(quicksilver *app.Quicksilver, ctx sdk.Context) {
zone, found := quicksilver.InterchainstakingKeeper.GetZone(ctx, suite.chainB.ChainID)
suite.True(found)

valAddrBytes, err := addressutils.ValAddressFromBech32(validator.String(), zone.GetValoperPrefix())
suite.NoError(err)
_, found = quicksilver.InterchainstakingKeeper.GetValidator(ctx, zone.ChainId, valAddrBytes)
suite.False(found)
},
},
// wrong chain id
{
name: "wrong chain id",
malleate: func(quicksilver *app.Quicksilver, ctx sdk.Context) []byte {
info := slashingtypes.ValidatorSigningInfo{}
cdc := quicksilver.InterchainstakingKeeper.GetCodec()
bz := cdc.MustMarshal(&info)
return bz
},
query: icqtypes.Query{
ChainId: "wrong-chain-id",
},
expectErr: true,
},
// args has no len
{
name: "args has no len",
malleate: func(quicksilver *app.Quicksilver, ctx sdk.Context) []byte {
return []byte{}
},
query: icqtypes.Query{
ChainId: suite.chainB.ChainID,
},
expectErr: true,
},
// wrong type args
{
name: "wrong type args",
malleate: func(quicksilver *app.Quicksilver, ctx sdk.Context) []byte {
return []byte("wrong type")
},
query: icqtypes.Query{
ChainId: suite.chainB.ChainID,
},
expectErr: true,
},
// consaddress decoding err
{
name: "consaddress decoding err",
malleate: func(quicksilver *app.Quicksilver, ctx sdk.Context) []byte {
info := slashingtypes.ValidatorSigningInfo{
Address: "wrong bech32 address",
Tombstoned: true,
}
cdc := quicksilver.InterchainstakingKeeper.GetCodec()
bz := cdc.MustMarshal(&info)
return bz
},
query: icqtypes.Query{
ChainId: suite.chainB.ChainID,
},
expectErr: true,
},
// can't get validator address from consensus address
{
name: "can't get validator address from consensus address",
malleate: func(quicksilver *app.Quicksilver, ctx sdk.Context) []byte {
info := slashingtypes.ValidatorSigningInfo{
Address: bech32ConsAddress,
Tombstoned: true,
}
cdc := quicksilver.InterchainstakingKeeper.GetCodec()
bz := cdc.MustMarshal(&info)
return bz
},
query: icqtypes.Query{
ChainId: suite.chainB.ChainID,
},
expectErr: true,
},
// success case not found validator
{
name: "success case not found validator",
malleate: func(quicksilver *app.Quicksilver, ctx sdk.Context) []byte {
zone, found := quicksilver.InterchainstakingKeeper.GetZone(ctx, suite.chainB.ChainID)
suite.True(found)
quicksilver.InterchainstakingKeeper.SetValidatorAddrByConsAddr(ctx, zone.ChainId, newValidator.OperatorAddress, consAddr)
info := slashingtypes.ValidatorSigningInfo{
Address: bech32ConsAddress,
Tombstoned: true,
}
cdc := quicksilver.InterchainstakingKeeper.GetCodec()
bz := cdc.MustMarshal(&info)
return bz
},
query: icqtypes.Query{
ChainId: suite.chainB.ChainID,
},
expectErr: false,
check: func(quicksilver *app.Quicksilver, ctx sdk.Context) {
zone, found := quicksilver.InterchainstakingKeeper.GetZone(ctx, suite.chainB.ChainID)
suite.True(found)

valAddrBytes, err := addressutils.ValAddressFromBech32(validator.String(), zone.GetValoperPrefix())
suite.NoError(err)
newVal, found := quicksilver.InterchainstakingKeeper.GetValidator(ctx, zone.ChainId, valAddrBytes)
suite.True(found)
suite.True(newVal.Jailed)
suite.True(newVal.Tombstoned)
},
},
// success case found validator
{
name: "success case found validator",
malleate: func(quicksilver *app.Quicksilver, ctx sdk.Context) []byte {
zone, found := quicksilver.InterchainstakingKeeper.GetZone(ctx, suite.chainB.ChainID)
suite.True(found)
quicksilver.InterchainstakingKeeper.SetValidatorAddrByConsAddr(ctx, zone.ChainId, newValidator.OperatorAddress, consAddr)
err := quicksilver.InterchainstakingKeeper.SetValidator(ctx, zone.ChainId, icstypes.Validator{
ValoperAddress: validator.String(),
Jailed: false,
Tombstoned: false,
})
suite.NoError(err)

info := slashingtypes.ValidatorSigningInfo{
Address: bech32ConsAddress,
Tombstoned: true,
}
cdc := quicksilver.InterchainstakingKeeper.GetCodec()
bz := cdc.MustMarshal(&info)
return bz
},
query: icqtypes.Query{
ChainId: suite.chainB.ChainID,
},
expectErr: false,
check: func(quicksilver *app.Quicksilver, ctx sdk.Context) {
zone, found := quicksilver.InterchainstakingKeeper.GetZone(ctx, suite.chainB.ChainID)
suite.True(found)

valAddrBytes, err := addressutils.ValAddressFromBech32(validator.String(), zone.GetValoperPrefix())
suite.NoError(err)
newVal, found := quicksilver.InterchainstakingKeeper.GetValidator(ctx, zone.ChainId, valAddrBytes)
suite.True(found)
suite.False(newVal.Jailed)
suite.True(newVal.Tombstoned)
},
},
}

for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest()
suite.setupTestZones()

quicksilver := suite.GetQuicksilverApp(suite.chainA)
quicksilver.InterchainstakingKeeper.CallbackHandler().RegisterCallbacks()
ctx := suite.chainA.GetContext()

data := tc.malleate(quicksilver, ctx)
err := keeper.SigningInfoCallback(quicksilver.InterchainstakingKeeper, ctx, data, tc.query)
if tc.expectErr {
suite.Error(err)
} else {
suite.NoError(err)
tc.check(quicksilver, ctx)
}
})
}
}

func (suite *KeeperTestSuite) TestCheckTMHeaderForZone() {
testCases := []struct {
name string
Expand Down
Loading

0 comments on commit 14dcb33

Please sign in to comment.