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!: migrations for permissionless #2177

Merged
merged 3 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
37 changes: 35 additions & 2 deletions proto/interchain_security/ccv/provider/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,36 @@ service Query {
"/interchain_security/ccv/provider/consumer_chains";
}

// [DEPRECATED]: Use `QueryConsumersThatAreAboutToStart` instead
// QueryConsumerChainStarts queries consumer chain start proposals.
rpc QueryConsumerChainStarts(QueryConsumerChainStartProposalsRequest)
returns (QueryConsumerChainStartProposalsResponse) {
option deprecated = true;
insumity marked this conversation as resolved.
Show resolved Hide resolved
option (google.api.http).get =
"/interchain_security/ccv/provider/consumer_chain_start_proposals";
}

rpc QueryConsumersThatAreAboutToStart(QueryConsumersThatAreAboutToStartRequest)
mpoke marked this conversation as resolved.
Show resolved Hide resolved
returns (QueryConsumersThatAreAboutToStartResponse) {
option (google.api.http).get =
"/interchain_security/ccv/provider/consumers_that_are_about_to_start";
}

// [DEPRECATED]: Use `QueryConsumersThatAreAboutToStop` instead
// QueryConsumerChainStops queries consumer chain stop proposals.
rpc QueryConsumerChainStops(QueryConsumerChainStopProposalsRequest)
returns (QueryConsumerChainStopProposalsResponse) {
option deprecated = true;
option (google.api.http).get =
"/interchain_security/ccv/provider/consumer_chain_stop_proposals";
}

rpc QueryConsumersThatAreAboutToStop(QueryConsumersThatAreAboutToStopRequest)
returns (QueryConsumersThatAreAboutToStopResponse) {
option (google.api.http).get =
"/interchain_security/ccv/provider/consumers_that_are_about_to_stop";
}

// QueryValidatorConsumerAddr queries the address
// assigned by a validator for a consumer chain.
rpc QueryValidatorConsumerAddr(QueryValidatorConsumerAddrRequest)
Expand Down Expand Up @@ -195,18 +211,35 @@ message QueryConsumerChainsRequest {}

message QueryConsumerChainsResponse { repeated Chain chains = 1; }

// [DEPRECATED] use `QueryConsumersThatAreAboutToStartRequest` instead
message QueryConsumerChainStartProposalsRequest {}

// [DEPRECATED] use `QueryConsumersThatAreAboutToStartResponse` instead
message QueryConsumerChainStartProposalsResponse {
ConsumerAdditionProposals proposals = 1;
ConsumerAdditionProposals proposals = 1 [deprecated = true];
}

message QueryConsumersThatAreAboutToStartRequest {}

message QueryConsumersThatAreAboutToStartResponse {
repeated string consumer_ids = 1;
}

// [DEPRECATED] use `QueryConsumersThatAreAboutToStopRequest` instead
message QueryConsumerChainStopProposalsRequest {}

// [DEPRECATED] use `QueryConsumersThatAreAboutToStopResponse` instead
message QueryConsumerChainStopProposalsResponse {
ConsumerRemovalProposals proposals = 1;
ConsumerRemovalProposals proposals = 1 [deprecated = true];
}

message QueryConsumersThatAreAboutToStopRequest {}

message QueryConsumersThatAreAboutToStopResponse {
repeated string consumer_ids = 1;
}


message Chain {
string chain_id = 1;
string client_id = 2;
Expand Down
51 changes: 0 additions & 51 deletions tests/integration/provider_gov_hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,57 +13,6 @@ import (
testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
)

// TestAfterPropSubmissionAndVotingPeriodEnded tests AfterProposalSubmission and AfterProposalVotingPeriodEnded hooks
// require adding a proposal in the gov module and registering a consumer chain with the provider module
func (s *CCVTestSuite) TestAfterPropSubmissionAndVotingPeriodEnded() {
ctx := s.providerChain.GetContext()
providerKeeper := s.providerApp.GetProviderKeeper()
govKeeper := s.providerApp.GetTestGovKeeper()
proposer := s.providerChain.SenderAccount

msgUpdateConsumer := testkeeper.GetTestMsgUpdateConsumer()

proposal, err := v1.NewProposal([]sdk.Msg{&msgUpdateConsumer}, 1, time.Now(), time.Now().Add(1*time.Hour), "metadata", "title", "summary", proposer.GetAddress(), false)
s.Require().NoError(err)

err = govKeeper.SetProposal(ctx, proposal)
s.Require().NoError(err)

// the proposal can only be submitted if the owner of the chain is the gov module
providerKeeper.SetConsumerOwnerAddress(ctx, msgUpdateConsumer.ConsumerId, "some bogus address")

err = providerKeeper.Hooks().AfterProposalSubmission(ctx, proposal.Id)
s.Require().Error(err)

// the proposal can only be submitted if the owner of the chain is the gov module
govModuleAddress := "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn"
providerKeeper.SetConsumerOwnerAddress(ctx, msgUpdateConsumer.ConsumerId, govModuleAddress)

err = providerKeeper.Hooks().AfterProposalSubmission(ctx, proposal.Id)
s.Require().NoError(err)

// verify that the proposal id is created
consumerIdOnProvider, ok := providerKeeper.GetProposalIdToConsumerId(ctx, proposal.Id)
s.Require().True(ok)
s.Require().NotEmpty(consumerIdOnProvider)
s.Require().Equal(msgUpdateConsumer.ConsumerId, consumerIdOnProvider)

providerKeeper.Hooks().AfterProposalVotingPeriodEnded(ctx, proposal.Id)
// verify that the proposal id is deleted
s.Require().Empty(providerKeeper.GetProposalIdToConsumerId(ctx, proposal.Id))

// assert that a proposal with more than one `MsgUpdateConsumer` messages fails
proposal, err = v1.NewProposal([]sdk.Msg{&msgUpdateConsumer, &msgUpdateConsumer}, 1, time.Now(), time.Now().Add(1*time.Hour), "metadata", "title", "summary", proposer.GetAddress(), false)
s.Require().NoError(err)

err = govKeeper.SetProposal(ctx, proposal)
s.Require().NoError(err)

err = providerKeeper.Hooks().AfterProposalSubmission(ctx, proposal.Id)
s.Require().Error(err)

}

func (s *CCVTestSuite) TestGetConsumerAdditionFromProp() {
ctx := s.providerChain.GetContext()
proposer := s.providerChain.SenderAccount
Expand Down
78 changes: 64 additions & 14 deletions x/ccv/provider/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ func NewQueryCmd() *cobra.Command {
cmd.AddCommand(CmdConsumerGenesis())
cmd.AddCommand(CmdConsumerChains())
cmd.AddCommand(CmdConsumerStartProposals())
cmd.AddCommand(CmdListConsumersThatAreAboutToStart())
cmd.AddCommand(CmdConsumerStopProposals())
cmd.AddCommand(CmdListConsumersThatAreAboutToStop())
cmd.AddCommand(CmdConsumerValidatorKeyAssignment())
cmd.AddCommand(CmdProviderValidatorKey())
cmd.AddCommand(CmdThrottleState())
Expand Down Expand Up @@ -103,8 +105,10 @@ func CmdConsumerChains() *cobra.Command {
func CmdProposedConsumerChains() *cobra.Command {
cmd := &cobra.Command{
Use: "list-proposed-consumer-chains",
Short: "Query chainIDs in consumer addition proposal before voting finishes",
Args: cobra.ExactArgs(0),
Short: "Query consumer chains that currently try to join ICS through governance",
Long: `Query to retrieve all the consumer ids of MsgUpdateConsumer messages that currently reside in active
proposals.`,
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) (err error) {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
Expand All @@ -130,12 +134,8 @@ func CmdProposedConsumerChains() *cobra.Command {
func CmdConsumerStartProposals() *cobra.Command {
cmd := &cobra.Command{
Use: "list-start-proposals",
Short: "Query consumer chains start proposals on provider chain.",
Long: `Query mature and pending consumer chains start proposals on provider chain.
Matured proposals will be executed on the next block - their spawn_time has passed
Pending proposals are waiting for their spawn_time to pass.
`,
Args: cobra.ExactArgs(0),
Short: "DEPRECATED! Use `list-consumers-that-will-start` instead.",
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) (err error) {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
Expand All @@ -158,15 +158,38 @@ func CmdConsumerStartProposals() *cobra.Command {
return cmd
}

func CmdListConsumersThatAreAboutToStart() *cobra.Command {
cmd := &cobra.Command{
Use: "list-consumers-that-will-start",
Short: "Query all the consumer chains that are initialized and about to start.",
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) (err error) {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)

req := &types.QueryConsumersThatAreAboutToStartRequest{}
res, err := queryClient.QueryConsumersThatAreAboutToStart(cmd.Context(), req)
if err != nil {
return err
}

return clientCtx.PrintProto(res)
},
}

flags.AddQueryFlagsToCmd(cmd)

return cmd
}

func CmdConsumerStopProposals() *cobra.Command {
cmd := &cobra.Command{
Use: "list-stop-proposals",
Short: "Query consumer chains stop proposals on provider chain.",
Long: `Query mature and pending consumer chains stop proposals on provider chain.
Matured proposals will be executed on the next block - their stop_time has passed
Pending proposals are waiting for their stop_time to pass.
`,
Args: cobra.ExactArgs(0),
Short: "DEPRECATED! Use `list-consumers-that-will-stop` instead.",
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) (err error) {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
Expand All @@ -189,6 +212,33 @@ func CmdConsumerStopProposals() *cobra.Command {
return cmd
}

func CmdListConsumersThatAreAboutToStop() *cobra.Command {
cmd := &cobra.Command{
Use: "list-consumers-that-will-stop",
Short: "Query all the consumer chains that are launched and about to stop.",
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) (err error) {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)

req := &types.QueryConsumersThatAreAboutToStopRequest{}
res, err := queryClient.QueryConsumersThatAreAboutToStop(cmd.Context(), req)
if err != nil {
return err
}

return clientCtx.PrintProto(res)
},
}

flags.AddQueryFlagsToCmd(cmd)

return cmd
}

// TODO: fix naming
func CmdConsumerValidatorKeyAssignment() *cobra.Command {
bech32PrefixConsAddr := sdk.GetConfig().GetBech32ConsensusAddrPrefix()
Expand Down
2 changes: 0 additions & 2 deletions x/ccv/provider/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,6 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState {
k.GetValidatorSetUpdateId(ctx),
k.GetAllValsetUpdateBlockHeights(ctx),
consumerStates,
k.GetAllPendingConsumerAdditionProps(ctx),
k.GetAllPendingConsumerRemovalProps(ctx),
params,
k.GetAllValidatorConsumerPubKeys(ctx, nil),
k.GetAllValidatorsByConsumerAddr(ctx, nil),
Expand Down
12 changes: 0 additions & 12 deletions x/ccv/provider/keeper/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,6 @@ func TestInitAndExportGenesis(t *testing.T) {
nil,
),
},
[]providertypes.ConsumerAdditionProposal{{
ChainId: cChainIDs[0],
SpawnTime: oneHourFromNow,
}},
[]providertypes.ConsumerRemovalProposal{{
ChainId: cChainIDs[0],
StopTime: oneHourFromNow,
}},
params,
[]providertypes.ValidatorConsumerPubKey{
{
Expand Down Expand Up @@ -139,10 +131,6 @@ func TestInitAndExportGenesis(t *testing.T) {
height, found := pk.GetValsetUpdateBlockHeight(ctx, vscID)
require.True(t, found)
require.Equal(t, initHeight, height)
addProp, found := pk.GetPendingConsumerAdditionProp(ctx, oneHourFromNow, cChainIDs[0])
require.True(t, found)
require.Equal(t, provGenesis.ConsumerAdditionProposals[0], addProp)
require.True(t, pk.PendingConsumerRemovalPropExists(ctx, cChainIDs[0], oneHourFromNow))
require.Equal(t, provGenesis.Params, pk.GetParams(ctx))

providerConsensusValSet, err := pk.GetLastProviderConsensusValSet(ctx)
Expand Down
59 changes: 39 additions & 20 deletions x/ccv/provider/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package keeper
import (
"context"
"fmt"
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
"math"

"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
Expand Down Expand Up @@ -105,39 +107,34 @@ func (k Keeper) GetConsumerChain(ctx sdk.Context, consumerId string) (types.Chai
}, nil
}

// TODO (PERMISSIONLESS)
func (k Keeper) QueryConsumerChainStarts(goCtx context.Context, req *types.QueryConsumerChainStartProposalsRequest) (*types.QueryConsumerChainStartProposalsResponse, error) {
mpoke marked this conversation as resolved.
Show resolved Hide resolved
return nil, status.Error(codes.Unimplemented, "This query is not supported anymore. Use `QueryConsumersThatAreAboutToStart` instead")
}

func (k Keeper) QueryConsumersThatAreAboutToStart(goCtx context.Context, req *types.QueryConsumersThatAreAboutToStartRequest) (*types.QueryConsumersThatAreAboutToStartResponse, error) {
insumity marked this conversation as resolved.
Show resolved Hide resolved
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}

ctx := sdk.UnwrapSDKContext(goCtx)
var props []*types.ConsumerAdditionProposal

for _, prop := range k.GetAllPendingConsumerAdditionProps(ctx) {
// prevent implicit memory aliasing
p := prop
props = append(props, &p)
}

return &types.QueryConsumerChainStartProposalsResponse{Proposals: &types.ConsumerAdditionProposals{Pending: props}}, nil
consumerIds := k.GetInitializedConsumersReadyToLaunch(ctx, math.MaxUint32)
return &types.QueryConsumersThatAreAboutToStartResponse{ConsumerIds: consumerIds}, nil
}

// TODO (PERMISSIONLESS)
func (k Keeper) QueryConsumerChainStops(goCtx context.Context, req *types.QueryConsumerChainStopProposalsRequest) (*types.QueryConsumerChainStopProposalsResponse, error) {
return nil, status.Error(codes.Unimplemented, "This query is not supported anymore. Use `QueryConsumersThatAreAboutToStop` instead")
}

func (k Keeper) QueryConsumersThatAreAboutToStop(goCtx context.Context, req *types.QueryConsumersThatAreAboutToStopRequest) (*types.QueryConsumersThatAreAboutToStopResponse, error) {
insumity marked this conversation as resolved.
Show resolved Hide resolved
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}

ctx := sdk.UnwrapSDKContext(goCtx)
var props []*types.ConsumerRemovalProposal
for _, prop := range k.GetAllPendingConsumerRemovalProps(ctx) {
// prevent implicit memory aliasing
p := prop
props = append(props, &p)
}

return &types.QueryConsumerChainStopProposalsResponse{Proposals: &types.ConsumerRemovalProposals{Pending: props}}, nil
consumerIds := k.GetLaunchedConsumersReadyToStop(ctx, math.MaxUint32)
return &types.QueryConsumersThatAreAboutToStopResponse{ConsumerIds: consumerIds}, nil
}

func (k Keeper) QueryValidatorConsumerAddr(goCtx context.Context, req *types.QueryValidatorConsumerAddrRequest) (*types.QueryValidatorConsumerAddrResponse, error) {
Expand Down Expand Up @@ -232,18 +229,40 @@ func (k Keeper) QueryRegisteredConsumerRewardDenoms(goCtx context.Context, req *
}, nil
}

// TODO (PERMISSIONLESS)
func (k Keeper) QueryProposedConsumerChainIDs(goCtx context.Context, req *types.QueryProposedChainIDsRequest) (*types.QueryProposedChainIDsResponse, error) {
insumity marked this conversation as resolved.
Show resolved Hide resolved
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}

ctx := sdk.UnwrapSDKContext(goCtx)

chains := k.GetAllProposedConsumerChainIDs(ctx)
var proposals []govv1.Proposal
err := k.govKeeper.Proposals.Walk(ctx, nil, func(proposalId uint64, proposal govv1.Proposal) (stop bool, err error) {
proposals = append(proposals, proposal)
mpoke marked this conversation as resolved.
Show resolved Hide resolved
return false, nil
})
if err != nil {
return nil, status.Error(codes.Internal, "failed to retrieve proposals")
}

var proposedChains []types.ProposedChain
for _, proposal := range proposals {
status := proposal.Status
if status != govv1.ProposalStatus_PROPOSAL_STATUS_DEPOSIT_PERIOD && status != govv1.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD {
// we only care about active proposals
continue
}

messages := proposal.GetMessages()
for _, msg := range messages {
if sdkMsg, isMsgUpdateConsumer := msg.GetCachedValue().(*types.MsgUpdateConsumer); isMsgUpdateConsumer {
proposedChains = append(proposedChains, types.ProposedChain{ProposalID: proposal.Id, ConsumerId: sdkMsg.ConsumerId})
mpoke marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

return &types.QueryProposedChainIDsResponse{
ProposedChains: chains,
ProposedChains: proposedChains,
}, nil
}

Expand Down
4 changes: 4 additions & 0 deletions x/ccv/provider/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,3 +384,7 @@ func TestQueryConsumerIdFromClientId(t *testing.T) {
require.NoError(t, err)
require.Equal(t, expectedConsumerId, res.ConsumerId)
}

func TestQueryProposedConsumerChainIDs(t *testing.T) {
// TODO (PERMISSIONLESS)
insumity marked this conversation as resolved.
Show resolved Hide resolved
}
Loading
Loading