Skip to content

Commit 390b52a

Browse files
Permission rly v2 per client (#8172)
* define params v2 type * add validation tests * set in keeper per clientID * simplify msg * permission params to authority and client creator * consistency on string check * use bech32 consistently * add permissioning to updateClient and v2 rly msgs * updateclient test * test permissioning * lint * add queries * prevent re-registerCounterparty * change params to config * cleanup and lint * permission rly cli + delete creator msg (#8174) * add cli commands for client params and creator * add queries to parent cmd * add delete client creator msg * add tests * fix after merge * fix client config cli --------- Co-authored-by: Gjermund Garaba <[email protected]>
1 parent 2127cfa commit 390b52a

File tree

34 files changed

+3459
-231
lines changed

34 files changed

+3459
-231
lines changed

modules/apps/transfer/types/packet.pb.go

Lines changed: 17 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

modules/core/02-client/client/cli/cli.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ func GetQueryCmd() *cobra.Command {
2929
GetCmdQueryHeader(),
3030
GetCmdSelfConsensusState(),
3131
GetCmdClientParams(),
32+
GetCmdClientParams(),
33+
GetCmdQueryClientCreator(),
34+
GetCmdQueryClientConfig(),
3235
)
3336

3437
return queryCmd
@@ -52,6 +55,8 @@ func NewTxCmd() *cobra.Command {
5255
newUpgradeClientCmd(),
5356
newSubmitRecoverClientProposalCmd(),
5457
newScheduleIBCUpgradeProposalCmd(),
58+
newUpdateClientConfigCmd(),
59+
newDeleteClientCreatorCmd(),
5560
)
5661

5762
return txCmd

modules/core/02-client/client/cli/query.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ func GetCmdQueryClientStates() *cobra.Command {
5959
return cmd
6060
}
6161

62+
// GetCmdQueryCounterpartyInfo defines the command to query the counterparty chain
6263
func GetCmdQueryCounterpartyInfo() *cobra.Command {
6364
cmd := &cobra.Command{
6465
Use: "counterparty-info [client-id]",
@@ -91,6 +92,72 @@ func GetCmdQueryCounterpartyInfo() *cobra.Command {
9192
return cmd
9293
}
9394

95+
// GetCmdQueryClientCreator defines the command to query the creator of a client
96+
func GetCmdQueryClientCreator() *cobra.Command {
97+
cmd := &cobra.Command{
98+
Use: "creator [client-id]",
99+
Short: "Query a client's creator",
100+
Long: "Query a client's creator",
101+
Example: fmt.Sprintf("%s query %s %s creator 08-wasm-0", version.AppName, ibcexported.ModuleName, types.SubModuleName),
102+
Args: cobra.ExactArgs(1),
103+
RunE: func(cmd *cobra.Command, args []string) error {
104+
clientCtx, err := client.GetClientQueryContext(cmd)
105+
if err != nil {
106+
return err
107+
}
108+
clientID := args[0]
109+
110+
queryClient := types.NewQueryClient(clientCtx)
111+
req := &types.QueryClientCreatorRequest{
112+
ClientId: clientID,
113+
}
114+
paramsResp, err := queryClient.ClientCreator(cmd.Context(), req)
115+
if err != nil {
116+
return err
117+
}
118+
119+
return clientCtx.PrintProto(paramsResp)
120+
},
121+
}
122+
123+
flags.AddQueryFlagsToCmd(cmd)
124+
125+
return cmd
126+
}
127+
128+
// GetCmdQueryClientConfig defines the command to query a client's configuration
129+
func GetCmdQueryClientConfig() *cobra.Command {
130+
cmd := &cobra.Command{
131+
Use: "config [client-id]",
132+
Short: "Query a client's config",
133+
Long: "Query a client's config",
134+
Example: fmt.Sprintf("%s query %s %s params 08-wasm-0", version.AppName, ibcexported.ModuleName, types.SubModuleName),
135+
Args: cobra.ExactArgs(1),
136+
RunE: func(cmd *cobra.Command, args []string) error {
137+
clientCtx, err := client.GetClientQueryContext(cmd)
138+
if err != nil {
139+
return err
140+
}
141+
clientID := args[0]
142+
143+
queryClient := clienttypesv2.NewQueryClient(clientCtx)
144+
req := &clienttypesv2.QueryConfigRequest{
145+
ClientId: clientID,
146+
}
147+
paramsResp, err := queryClient.Config(cmd.Context(), req)
148+
if err != nil {
149+
return err
150+
}
151+
152+
return clientCtx.PrintProto(paramsResp)
153+
},
154+
}
155+
156+
flags.AddQueryFlagsToCmd(cmd)
157+
158+
return cmd
159+
}
160+
94161
// GetCmdQueryClientState defines the command to query the state of a client with
95162
// a given id as defined in https://github.com/cosmos/ibc/tree/master/spec/core/ics-002-client-semantics#query
96163
func GetCmdQueryClientState() *cobra.Command {

modules/core/02-client/client/cli/tx.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,64 @@ func newAddCounterpartyCmd() *cobra.Command {
123123
return cmd
124124
}
125125

126+
// newDeleteClientCreatorCmd defines the command to delete the client creator for a given client.
127+
func newDeleteClientCreatorCmd() *cobra.Command {
128+
cmd := &cobra.Command{
129+
Use: "delete-client-creator [client-id]",
130+
Short: "delete the client creator",
131+
Example: fmt.Sprintf("%s tx ibc %s delete-client-creator 07-tendermint-0", version.AppName, types.SubModuleName),
132+
Args: cobra.ExactArgs(1),
133+
RunE: func(cmd *cobra.Command, args []string) error {
134+
clientCtx, err := client.GetClientTxContext(cmd)
135+
if err != nil {
136+
return err
137+
}
138+
139+
clientID := args[0]
140+
141+
msg := types.NewMsgDeleteClientCreator(clientID, clientCtx.GetFromAddress().String())
142+
143+
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
144+
},
145+
}
146+
147+
flags.AddTxFlagsToCmd(cmd)
148+
return cmd
149+
}
150+
151+
// newUpdateClientConfigCmd defines the command to update the client config (allowed relayers) for a given client.
152+
func newUpdateClientConfigCmd() *cobra.Command {
153+
cmd := &cobra.Command{
154+
Use: "update-client-config client-id [allowed-relayer-addresses...]",
155+
Short: "update allowed relayers for a client (replaces existing list, and no addresses means empty list and permissionless relaying)",
156+
Example: fmt.Sprintf("%s tx ibc %s update-client-params 08-wasm-0 cosmos123... cosmos456...", version.AppName, types.SubModuleName),
157+
Args: cobra.MinimumNArgs(1),
158+
RunE: func(cmd *cobra.Command, args []string) error {
159+
clientCtx, err := client.GetClientTxContext(cmd)
160+
if err != nil {
161+
return err
162+
}
163+
164+
clientID := args[0]
165+
166+
// NOTE: Make sure all fields are gathered from the user for the config objects, as it replaces the entire existing config.
167+
// In other words, if we add a new field to the config object, we need to make sure it is gathered here
168+
var allowedRelayers []string
169+
for _, relayerAddress := range args[1:] {
170+
_ = sdk.MustAccAddressFromBech32(relayerAddress)
171+
allowedRelayers = append(allowedRelayers, relayerAddress)
172+
}
173+
174+
msg := clienttypesv2.NewMsgUpdateClientConfig(clientID, clientCtx.GetFromAddress().String(), clienttypesv2.NewConfig(allowedRelayers...))
175+
176+
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
177+
},
178+
}
179+
180+
flags.AddTxFlagsToCmd(cmd)
181+
return cmd
182+
}
183+
126184
// newUpdateClientCmd defines the command to update an IBC client.
127185
func newUpdateClientCmd() *cobra.Command {
128186
cmd := &cobra.Command{

modules/core/02-client/keeper/grpc_query.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,24 @@ func (q *queryServer) ClientStatus(goCtx context.Context, req *types.QueryClient
261261
}, nil
262262
}
263263

264+
// ClientCreator implements the Query/ClientCreator gRPC method
265+
func (q *queryServer) ClientCreator(goCtx context.Context, req *types.QueryClientCreatorRequest) (*types.QueryClientCreatorResponse, error) {
266+
if req == nil {
267+
return nil, status.Error(codes.InvalidArgument, "empty request")
268+
}
269+
270+
if err := host.ClientIdentifierValidator(req.ClientId); err != nil {
271+
return nil, status.Error(codes.InvalidArgument, err.Error())
272+
}
273+
274+
ctx := sdk.UnwrapSDKContext(goCtx)
275+
creator := q.GetClientCreator(ctx, req.ClientId)
276+
277+
return &types.QueryClientCreatorResponse{
278+
Creator: creator.String(),
279+
}, nil
280+
}
281+
264282
// ClientParams implements the Query/ClientParams gRPC method
265283
func (q *queryServer) ClientParams(goCtx context.Context, _ *types.QueryClientParamsRequest) (*types.QueryClientParamsResponse, error) {
266284
ctx := sdk.UnwrapSDKContext(goCtx)

modules/core/02-client/keeper/grpc_query_test.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,83 @@ func (suite *KeeperTestSuite) TestQueryUpgradedConsensusStates() {
780780
}
781781
}
782782

783+
func (suite *KeeperTestSuite) TestQueryCreator() {
784+
var (
785+
req *types.QueryClientCreatorRequest
786+
expRes *types.QueryClientCreatorResponse
787+
path *ibctesting.Path
788+
)
789+
790+
testCases := []struct {
791+
name string
792+
malleate func()
793+
expError error
794+
}{
795+
{
796+
"req is nil",
797+
func() {
798+
req = nil
799+
},
800+
status.Error(codes.InvalidArgument, "empty request"),
801+
},
802+
{
803+
"invalid clientID",
804+
func() {
805+
req = &types.QueryClientCreatorRequest{}
806+
},
807+
status.Error(codes.InvalidArgument, "identifier cannot be blank: invalid identifier"),
808+
},
809+
{
810+
"client not found",
811+
func() {
812+
req = &types.QueryClientCreatorRequest{
813+
ClientId: ibctesting.FirstClientID,
814+
}
815+
expRes = &types.QueryClientCreatorResponse{
816+
Creator: "",
817+
}
818+
},
819+
nil,
820+
},
821+
{
822+
"success",
823+
func() {
824+
path.SetupClients()
825+
req = &types.QueryClientCreatorRequest{
826+
ClientId: path.EndpointA.ClientID,
827+
}
828+
expRes = &types.QueryClientCreatorResponse{
829+
Creator: suite.chainA.SenderAccount.GetAddress().String(),
830+
}
831+
},
832+
nil,
833+
},
834+
}
835+
836+
for _, tc := range testCases {
837+
tc := tc
838+
839+
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
840+
suite.SetupTest() // reset
841+
path = ibctesting.NewPath(suite.chainA, suite.chainB)
842+
843+
tc.malleate()
844+
ctx := suite.chainA.GetContext()
845+
queryServer := keeper.NewQueryServer(suite.chainA.GetSimApp().IBCKeeper.ClientKeeper)
846+
res, err := queryServer.ClientCreator(ctx, req)
847+
848+
if tc.expError == nil {
849+
suite.Require().NoError(err)
850+
suite.Require().NotNil(res)
851+
suite.Require().Equal(expRes, res)
852+
} else {
853+
suite.Require().Error(err)
854+
suite.Require().ErrorIs(err, tc.expError)
855+
}
856+
})
857+
}
858+
}
859+
783860
func (suite *KeeperTestSuite) TestQueryClientParams() {
784861
ctx := suite.chainA.GetContext()
785862
expParams := types.DefaultParams()

modules/core/02-client/types/msgs.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ var (
2020
_ sdk.Msg = (*MsgUpdateParams)(nil)
2121
_ sdk.Msg = (*MsgIBCSoftwareUpgrade)(nil)
2222
_ sdk.Msg = (*MsgRecoverClient)(nil)
23+
_ sdk.Msg = (*MsgDeleteClientCreator)(nil)
2324

2425
_ sdk.HasValidateBasic = (*MsgCreateClient)(nil)
2526
_ sdk.HasValidateBasic = (*MsgUpdateClient)(nil)
@@ -28,6 +29,7 @@ var (
2829
_ sdk.HasValidateBasic = (*MsgUpdateParams)(nil)
2930
_ sdk.HasValidateBasic = (*MsgIBCSoftwareUpgrade)(nil)
3031
_ sdk.HasValidateBasic = (*MsgRecoverClient)(nil)
32+
_ sdk.HasValidateBasic = (*MsgDeleteClientCreator)(nil)
3133

3234
_ codectypes.UnpackInterfacesMessage = (*MsgCreateClient)(nil)
3335
_ codectypes.UnpackInterfacesMessage = (*MsgUpdateClient)(nil)
@@ -318,3 +320,25 @@ func (msg *MsgUpdateParams) ValidateBasic() error {
318320
}
319321
return msg.Params.Validate()
320322
}
323+
324+
// NewMsgDeleteClientCreator creates a new instance of MsgDeleteClientCreator.
325+
func NewMsgDeleteClientCreator(clientID string, signer string) *MsgDeleteClientCreator {
326+
return &MsgDeleteClientCreator{
327+
ClientId: clientID,
328+
Signer: signer,
329+
}
330+
}
331+
332+
// ValidateBasic performs basic validation of the MsgDeleteClientCreator fields.
333+
func (msg *MsgDeleteClientCreator) ValidateBasic() error {
334+
if _, err := sdk.AccAddressFromBech32(msg.Signer); err != nil {
335+
return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err)
336+
}
337+
if err := host.ClientIdentifierValidator(msg.ClientId); err != nil {
338+
return err
339+
}
340+
if !IsValidClientID(msg.ClientId) {
341+
return errorsmod.Wrapf(host.ErrInvalidID, "client ID %s must be in valid format: {string}-{number}", msg.ClientId)
342+
}
343+
return nil
344+
}

0 commit comments

Comments
 (0)