Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
insumity committed Aug 27, 2024
1 parent f7e5b3c commit e6a1bfc
Show file tree
Hide file tree
Showing 17 changed files with 1,327 additions and 583 deletions.
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;
option (google.api.http).get =
"/interchain_security/ccv/provider/consumer_chain_start_proposals";
}

rpc QueryConsumersThatAreAboutToStart(QueryConsumersThatAreAboutToStartRequest)
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) {
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) {
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) {
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) {
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)
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})
}
}
}

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)
}
Loading

0 comments on commit e6a1bfc

Please sign in to comment.