diff --git a/modules/core/02-client/keeper/keeper.go b/modules/core/02-client/keeper/keeper.go index 4275ae4048b..f3a7102a0e6 100644 --- a/modules/core/02-client/keeper/keeper.go +++ b/modules/core/02-client/keeper/keeper.go @@ -115,6 +115,45 @@ func (k *Keeper) SetClientState(ctx context.Context, clientID string, clientStat store.Set(host.ClientStateKey(), types.MustMarshalClientState(k.cdc, clientState)) } +// GetClientCreator returns the creator of a client +func (k *Keeper) GetClientCreator(ctx context.Context, clientID string) sdk.AccAddress { + store := k.ClientStore(ctx, clientID) + bz := store.Get(types.CreatorKey()) + if len(bz) == 0 { + return nil + } + return sdk.AccAddress(bz) +} + +// SetClientCreator sets the creator of a client +func (k *Keeper) SetClientCreator(ctx context.Context, clientID string, creator sdk.AccAddress) { + store := k.ClientStore(ctx, clientID) + store.Set(types.CreatorKey(), creator.Bytes()) +} + +// DeleteClientCreator deletes the creator of a client +func (k *Keeper) DeleteClientCreator(ctx context.Context, clientID string) { + store := k.ClientStore(ctx, clientID) + store.Delete(types.CreatorKey()) +} + +func (k *Keeper) SetClientCounterparty(ctx context.Context, clientID string, counterparty types.CounterpartyInfo) { + store := k.ClientStore(ctx, clientID) + store.Set(types.CounterpartyKey(), k.cdc.MustMarshal(&counterparty)) +} + +func (k *Keeper) GetClientCounterparty(ctx context.Context, clientID string) (types.CounterpartyInfo, bool) { + store := k.ClientStore(ctx, clientID) + bz := store.Get(types.CounterpartyKey()) + if len(bz) == 0 { + return types.CounterpartyInfo{}, false + } + + var counterparty types.CounterpartyInfo + k.cdc.MustUnmarshal(bz, &counterparty) + return counterparty, true +} + // GetClientConsensusState gets the stored consensus state from a client at a given height. func (k *Keeper) GetClientConsensusState(ctx context.Context, clientID string, height exported.Height) (exported.ConsensusState, bool) { store := k.ClientStore(ctx, clientID) diff --git a/modules/core/02-client/keeper/keeper_test.go b/modules/core/02-client/keeper/keeper_test.go index 2e9dbe09fbc..83c7594126e 100644 --- a/modules/core/02-client/keeper/keeper_test.go +++ b/modules/core/02-client/keeper/keeper_test.go @@ -127,6 +127,25 @@ func (suite *KeeperTestSuite) TestSetClientState() { suite.Require().Equal(clientState, retrievedState, "Client states are not equal") } +func (suite *KeeperTestSuite) TestSetClientCreator() { + creator := suite.chainA.SenderAccount.GetAddress() + suite.keeper.SetClientCreator(suite.ctx, testClientID, creator) + getCreator := suite.keeper.GetClientCreator(suite.ctx, testClientID) + suite.Require().Equal(creator, getCreator) + suite.keeper.DeleteClientCreator(suite.ctx, testClientID) + getCreator = suite.keeper.GetClientCreator(suite.ctx, testClientID) + suite.Require().Equal(sdk.AccAddress(nil), getCreator) +} + +func (suite *KeeperTestSuite) TestSetClientCounterparty() { + counterparty := types.NewCounterpartyInfo([][]byte{[]byte("ibc"), []byte("channel-7")}) + suite.keeper.SetClientCounterparty(suite.ctx, testClientID, counterparty) + + retrievedCounterparty, found := suite.keeper.GetClientCounterparty(suite.ctx, testClientID) + suite.Require().True(found, "GetCounterparty failed") + suite.Require().Equal(counterparty, retrievedCounterparty, "Counterparties are not equal") +} + func (suite *KeeperTestSuite) TestSetClientConsensusState() { suite.keeper.SetClientConsensusState(suite.ctx, testClientID, testClientHeight, suite.consensusState) diff --git a/modules/core/02-client/types/counterparty.go b/modules/core/02-client/types/counterparty.go new file mode 100644 index 00000000000..3abed9259d7 --- /dev/null +++ b/modules/core/02-client/types/counterparty.go @@ -0,0 +1,7 @@ +package types + +func NewCounterpartyInfo(counterpartyMessagingKey [][]byte) CounterpartyInfo { + return CounterpartyInfo{ + CounterpartyMessagingKey: counterpartyMessagingKey, + } +} diff --git a/modules/core/02-client/types/counterparty.pb.go b/modules/core/02-client/types/counterparty.pb.go new file mode 100644 index 00000000000..9f7cdb2fdd9 --- /dev/null +++ b/modules/core/02-client/types/counterparty.pb.go @@ -0,0 +1,806 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: ibc/core/client/v2/counterparty.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/types/msgservice" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// CounterpartyInfo defines the key that the counterparty will use to message our client +type CounterpartyInfo struct { + // counterparty messaging key prefix is the key that the counterparty will store + // all outgoing IBC packet messages intended for our chain. + // the provable messages will be stored with the following key prefix and the + // ICS24 standardized path for the given message type + CounterpartyMessagingKey [][]byte `protobuf:"bytes,1,rep,name=counterparty_messaging_key,json=counterpartyMessagingKey,proto3" json:"counterparty_messaging_key,omitempty"` +} + +func (m *CounterpartyInfo) Reset() { *m = CounterpartyInfo{} } +func (m *CounterpartyInfo) String() string { return proto.CompactTextString(m) } +func (*CounterpartyInfo) ProtoMessage() {} +func (*CounterpartyInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_bc4a81c3d2196cf1, []int{0} +} +func (m *CounterpartyInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CounterpartyInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CounterpartyInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *CounterpartyInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_CounterpartyInfo.Merge(m, src) +} +func (m *CounterpartyInfo) XXX_Size() int { + return m.Size() +} +func (m *CounterpartyInfo) XXX_DiscardUnknown() { + xxx_messageInfo_CounterpartyInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_CounterpartyInfo proto.InternalMessageInfo + +func (m *CounterpartyInfo) GetCounterpartyMessagingKey() [][]byte { + if m != nil { + return m.CounterpartyMessagingKey + } + return nil +} + +// MsgRegisterCounterparty defines a message to register a counterparty on a client +type MsgRegisterCounterparty struct { + // client identifier + ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + // counterparty messaging key + CounterpartyMessagingKey [][]byte `protobuf:"bytes,2,rep,name=counterparty_messaging_key,json=counterpartyMessagingKey,proto3" json:"counterparty_messaging_key,omitempty"` + // signer address + Signer string `protobuf:"bytes,3,opt,name=signer,proto3" json:"signer,omitempty"` +} + +func (m *MsgRegisterCounterparty) Reset() { *m = MsgRegisterCounterparty{} } +func (m *MsgRegisterCounterparty) String() string { return proto.CompactTextString(m) } +func (*MsgRegisterCounterparty) ProtoMessage() {} +func (*MsgRegisterCounterparty) Descriptor() ([]byte, []int) { + return fileDescriptor_bc4a81c3d2196cf1, []int{1} +} +func (m *MsgRegisterCounterparty) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRegisterCounterparty) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRegisterCounterparty.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgRegisterCounterparty) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRegisterCounterparty.Merge(m, src) +} +func (m *MsgRegisterCounterparty) XXX_Size() int { + return m.Size() +} +func (m *MsgRegisterCounterparty) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRegisterCounterparty.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRegisterCounterparty proto.InternalMessageInfo + +// MsgRegisterCounterpartyResponse defines the Msg/RegisterCounterparty response type. +type MsgRegisterCounterpartyResponse struct { +} + +func (m *MsgRegisterCounterpartyResponse) Reset() { *m = MsgRegisterCounterpartyResponse{} } +func (m *MsgRegisterCounterpartyResponse) String() string { return proto.CompactTextString(m) } +func (*MsgRegisterCounterpartyResponse) ProtoMessage() {} +func (*MsgRegisterCounterpartyResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_bc4a81c3d2196cf1, []int{2} +} +func (m *MsgRegisterCounterpartyResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRegisterCounterpartyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRegisterCounterpartyResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgRegisterCounterpartyResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRegisterCounterpartyResponse.Merge(m, src) +} +func (m *MsgRegisterCounterpartyResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgRegisterCounterpartyResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRegisterCounterpartyResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRegisterCounterpartyResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*CounterpartyInfo)(nil), "ibc.core.client.v2.CounterpartyInfo") + proto.RegisterType((*MsgRegisterCounterparty)(nil), "ibc.core.client.v2.MsgRegisterCounterparty") + proto.RegisterType((*MsgRegisterCounterpartyResponse)(nil), "ibc.core.client.v2.MsgRegisterCounterpartyResponse") +} + +func init() { + proto.RegisterFile("ibc/core/client/v2/counterparty.proto", fileDescriptor_bc4a81c3d2196cf1) +} + +var fileDescriptor_bc4a81c3d2196cf1 = []byte{ + // 360 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xcd, 0x4c, 0x4a, 0xd6, + 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x4f, 0xce, 0xc9, 0x4c, 0xcd, 0x2b, 0xd1, 0x2f, 0x33, 0xd2, 0x4f, + 0xce, 0x2f, 0xcd, 0x2b, 0x49, 0x2d, 0x2a, 0x48, 0x2c, 0x2a, 0xa9, 0xd4, 0x2b, 0x28, 0xca, 0x2f, + 0xc9, 0x17, 0x12, 0xca, 0x4c, 0x4a, 0xd6, 0x03, 0x29, 0xd3, 0x83, 0x28, 0xd3, 0x2b, 0x33, 0x92, + 0x12, 0x4f, 0xce, 0x2f, 0xce, 0xcd, 0x2f, 0xd6, 0xcf, 0x2d, 0x4e, 0xd7, 0x2f, 0x33, 0x04, 0x51, + 0x10, 0xc5, 0x52, 0x22, 0xe9, 0xf9, 0xe9, 0xf9, 0x60, 0xa6, 0x3e, 0x88, 0x05, 0x11, 0x55, 0x0a, + 0xe0, 0x12, 0x70, 0x46, 0x32, 0xd8, 0x33, 0x2f, 0x2d, 0x5f, 0xc8, 0x86, 0x4b, 0x0a, 0xd9, 0xb2, + 0xf8, 0xdc, 0xd4, 0xe2, 0xe2, 0xc4, 0xf4, 0xcc, 0xbc, 0xf4, 0xf8, 0xec, 0xd4, 0x4a, 0x09, 0x46, + 0x05, 0x66, 0x0d, 0x9e, 0x20, 0x09, 0x64, 0x15, 0xbe, 0x30, 0x05, 0xde, 0xa9, 0x95, 0x4a, 0x73, + 0x19, 0xb9, 0xc4, 0x7d, 0x8b, 0xd3, 0x83, 0x52, 0xd3, 0x33, 0x8b, 0x4b, 0x52, 0x8b, 0x90, 0x4d, + 0x17, 0x92, 0xe6, 0xe2, 0x84, 0xb8, 0x34, 0x3e, 0x33, 0x45, 0x82, 0x51, 0x81, 0x51, 0x83, 0x33, + 0x88, 0x03, 0x22, 0xe0, 0x99, 0x42, 0xc0, 0x5a, 0x26, 0xfc, 0xd6, 0x0a, 0x89, 0x71, 0xb1, 0x15, + 0x67, 0xa6, 0xe7, 0xa5, 0x16, 0x49, 0x30, 0x83, 0xcd, 0x85, 0xf2, 0xac, 0xf8, 0x3b, 0x16, 0xc8, + 0x33, 0x34, 0x3d, 0xdf, 0xa0, 0x05, 0x15, 0x50, 0x52, 0xe4, 0x92, 0xc7, 0xe1, 0xbc, 0xa0, 0xd4, + 0xe2, 0x82, 0xfc, 0xbc, 0xe2, 0x54, 0xa3, 0x49, 0x8c, 0x5c, 0xfc, 0xc8, 0x12, 0xbe, 0xc5, 0xe9, + 0x42, 0x15, 0x5c, 0x22, 0x58, 0xbd, 0xa4, 0xad, 0x87, 0x19, 0x09, 0x7a, 0x38, 0x2c, 0x90, 0x32, + 0x26, 0x41, 0x31, 0xcc, 0x35, 0x52, 0xac, 0x0d, 0xcf, 0x37, 0x68, 0x31, 0x3a, 0x05, 0x9d, 0x78, + 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, + 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x45, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, + 0x5e, 0x72, 0x7e, 0xae, 0x3e, 0x34, 0xf6, 0x33, 0x93, 0x92, 0x75, 0xd3, 0xf3, 0xf5, 0xcb, 0x2c, + 0xf5, 0x73, 0xf3, 0x53, 0x4a, 0x73, 0x52, 0x8b, 0x21, 0xa9, 0xc9, 0xc0, 0x48, 0x17, 0x9a, 0xa0, + 0x4a, 0x2a, 0x0b, 0x52, 0x8b, 0x93, 0xd8, 0xc0, 0x89, 0xc0, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, + 0x63, 0x9f, 0xd3, 0xcf, 0x70, 0x02, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// CounterpartyMsgClient is the client API for CounterpartyMsg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type CounterpartyMsgClient interface { + // RegisterCounterparty defines a rpc handler method for MsgRegisterCounterparty. + RegisterCounterparty(ctx context.Context, in *MsgRegisterCounterparty, opts ...grpc.CallOption) (*MsgRegisterCounterpartyResponse, error) +} + +type counterpartyMsgClient struct { + cc grpc1.ClientConn +} + +func NewCounterpartyMsgClient(cc grpc1.ClientConn) CounterpartyMsgClient { + return &counterpartyMsgClient{cc} +} + +func (c *counterpartyMsgClient) RegisterCounterparty(ctx context.Context, in *MsgRegisterCounterparty, opts ...grpc.CallOption) (*MsgRegisterCounterpartyResponse, error) { + out := new(MsgRegisterCounterpartyResponse) + err := c.cc.Invoke(ctx, "/ibc.core.client.v2.CounterpartyMsg/RegisterCounterparty", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// CounterpartyMsgServer is the server API for CounterpartyMsg service. +type CounterpartyMsgServer interface { + // RegisterCounterparty defines a rpc handler method for MsgRegisterCounterparty. + RegisterCounterparty(context.Context, *MsgRegisterCounterparty) (*MsgRegisterCounterpartyResponse, error) +} + +// UnimplementedCounterpartyMsgServer can be embedded to have forward compatible implementations. +type UnimplementedCounterpartyMsgServer struct { +} + +func (*UnimplementedCounterpartyMsgServer) RegisterCounterparty(ctx context.Context, req *MsgRegisterCounterparty) (*MsgRegisterCounterpartyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RegisterCounterparty not implemented") +} + +func RegisterCounterpartyMsgServer(s grpc1.Server, srv CounterpartyMsgServer) { + s.RegisterService(&_CounterpartyMsg_serviceDesc, srv) +} + +func _CounterpartyMsg_RegisterCounterparty_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRegisterCounterparty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CounterpartyMsgServer).RegisterCounterparty(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ibc.core.client.v2.CounterpartyMsg/RegisterCounterparty", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CounterpartyMsgServer).RegisterCounterparty(ctx, req.(*MsgRegisterCounterparty)) + } + return interceptor(ctx, in, info, handler) +} + +var _CounterpartyMsg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "ibc.core.client.v2.CounterpartyMsg", + HandlerType: (*CounterpartyMsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "RegisterCounterparty", + Handler: _CounterpartyMsg_RegisterCounterparty_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "ibc/core/client/v2/counterparty.proto", +} + +func (m *CounterpartyInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CounterpartyInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CounterpartyInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.CounterpartyMessagingKey) > 0 { + for iNdEx := len(m.CounterpartyMessagingKey) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.CounterpartyMessagingKey[iNdEx]) + copy(dAtA[i:], m.CounterpartyMessagingKey[iNdEx]) + i = encodeVarintCounterparty(dAtA, i, uint64(len(m.CounterpartyMessagingKey[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *MsgRegisterCounterparty) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgRegisterCounterparty) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRegisterCounterparty) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintCounterparty(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0x1a + } + if len(m.CounterpartyMessagingKey) > 0 { + for iNdEx := len(m.CounterpartyMessagingKey) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.CounterpartyMessagingKey[iNdEx]) + copy(dAtA[i:], m.CounterpartyMessagingKey[iNdEx]) + i = encodeVarintCounterparty(dAtA, i, uint64(len(m.CounterpartyMessagingKey[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if len(m.ClientId) > 0 { + i -= len(m.ClientId) + copy(dAtA[i:], m.ClientId) + i = encodeVarintCounterparty(dAtA, i, uint64(len(m.ClientId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgRegisterCounterpartyResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgRegisterCounterpartyResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRegisterCounterpartyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintCounterparty(dAtA []byte, offset int, v uint64) int { + offset -= sovCounterparty(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *CounterpartyInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.CounterpartyMessagingKey) > 0 { + for _, b := range m.CounterpartyMessagingKey { + l = len(b) + n += 1 + l + sovCounterparty(uint64(l)) + } + } + return n +} + +func (m *MsgRegisterCounterparty) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ClientId) + if l > 0 { + n += 1 + l + sovCounterparty(uint64(l)) + } + if len(m.CounterpartyMessagingKey) > 0 { + for _, b := range m.CounterpartyMessagingKey { + l = len(b) + n += 1 + l + sovCounterparty(uint64(l)) + } + } + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovCounterparty(uint64(l)) + } + return n +} + +func (m *MsgRegisterCounterpartyResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovCounterparty(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozCounterparty(x uint64) (n int) { + return sovCounterparty(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *CounterpartyInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCounterparty + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CounterpartyInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CounterpartyInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CounterpartyMessagingKey", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCounterparty + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCounterparty + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCounterparty + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CounterpartyMessagingKey = append(m.CounterpartyMessagingKey, make([]byte, postIndex-iNdEx)) + copy(m.CounterpartyMessagingKey[len(m.CounterpartyMessagingKey)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCounterparty(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCounterparty + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRegisterCounterparty) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCounterparty + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgRegisterCounterparty: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRegisterCounterparty: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClientId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCounterparty + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthCounterparty + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthCounterparty + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClientId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CounterpartyMessagingKey", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCounterparty + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCounterparty + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCounterparty + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CounterpartyMessagingKey = append(m.CounterpartyMessagingKey, make([]byte, postIndex-iNdEx)) + copy(m.CounterpartyMessagingKey[len(m.CounterpartyMessagingKey)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCounterparty + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthCounterparty + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthCounterparty + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCounterparty(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCounterparty + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRegisterCounterpartyResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCounterparty + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgRegisterCounterpartyResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRegisterCounterpartyResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipCounterparty(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCounterparty + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipCounterparty(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCounterparty + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCounterparty + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCounterparty + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthCounterparty + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupCounterparty + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthCounterparty + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthCounterparty = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowCounterparty = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupCounterparty = fmt.Errorf("proto: unexpected end of group") +) diff --git a/modules/core/02-client/types/errors.go b/modules/core/02-client/types/errors.go index 62d906bc40c..116e322ac6d 100644 --- a/modules/core/02-client/types/errors.go +++ b/modules/core/02-client/types/errors.go @@ -38,4 +38,5 @@ var ( ErrFailedNonMembershipVerification = errorsmod.Register(SubModuleName, 31, "non-membership verification failed") ErrRouteNotFound = errorsmod.Register(SubModuleName, 32, "light client module route not found") ErrClientTypeNotSupported = errorsmod.Register(SubModuleName, 33, "client type not supported") + ErrInvalidCounterparty = errorsmod.Register(SubModuleName, 34, "invalid counterparty") ) diff --git a/modules/core/02-client/types/keys.go b/modules/core/02-client/types/keys.go index 76ce77f08c7..f286b28523d 100644 --- a/modules/core/02-client/types/keys.go +++ b/modules/core/02-client/types/keys.go @@ -29,6 +29,10 @@ const ( // ParamsKey is the store key for the IBC client parameters ParamsKey = "clientParams" + KeyCreator = "creator" + + KeyCounterparty = "counterparty" + // AllowAllClients is the value that if set in AllowedClients param // would allow any wired up light client modules to be allowed AllowAllClients = "*" @@ -91,3 +95,11 @@ func MustParseClientIdentifier(clientID string) string { return clientType } + +func CreatorKey() []byte { + return []byte(KeyCreator) +} + +func CounterpartyKey() []byte { + return []byte(KeyCounterparty) +} diff --git a/modules/core/02-client/types/msgs.go b/modules/core/02-client/types/msgs.go index a520a46ab7c..119bca08e11 100644 --- a/modules/core/02-client/types/msgs.go +++ b/modules/core/02-client/types/msgs.go @@ -22,6 +22,8 @@ var ( _ sdk.Msg = (*MsgIBCSoftwareUpgrade)(nil) _ sdk.Msg = (*MsgRecoverClient)(nil) + _ sdk.Msg = (*MsgRegisterCounterparty)(nil) + _ sdk.HasValidateBasic = (*MsgCreateClient)(nil) _ sdk.HasValidateBasic = (*MsgUpdateClient)(nil) _ sdk.HasValidateBasic = (*MsgSubmitMisbehaviour)(nil) @@ -29,6 +31,7 @@ var ( _ sdk.HasValidateBasic = (*MsgUpdateParams)(nil) _ sdk.HasValidateBasic = (*MsgIBCSoftwareUpgrade)(nil) _ sdk.HasValidateBasic = (*MsgRecoverClient)(nil) + _ sdk.HasValidateBasic = (*MsgRegisterCounterparty)(nil) _ gogoprotoany.UnpackInterfacesMessage = (*MsgCreateClient)(nil) _ gogoprotoany.UnpackInterfacesMessage = (*MsgUpdateClient)(nil) @@ -320,3 +323,23 @@ func (msg *MsgUpdateParams) ValidateBasic() error { } return msg.Params.Validate() } + +// NewMsgRegisterCounterparty creates a new instance of MsgRegisterCounterparty. +func NewMsgRegisterCounterparty(clientId string, counterpartyMsgKey [][]byte, signer string) *MsgRegisterCounterparty { + return &MsgRegisterCounterparty{ + ClientId: clientId, + CounterpartyMessagingKey: counterpartyMsgKey, + Signer: signer, + } +} + +// ValidateBasic performs basic checks on a MsgRegisterCounterparty. +func (msg *MsgRegisterCounterparty) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Signer); err != nil { + return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) + } + if len(msg.CounterpartyMessagingKey) == 0 { + return errorsmod.Wrap(ErrInvalidCounterparty, "counterparty messaging key cannot be empty") + } + return host.ClientIdentifierValidator(msg.ClientId) +} diff --git a/modules/core/02-client/types/msgs_test.go b/modules/core/02-client/types/msgs_test.go index 112b7beb211..1e8d71a5cf3 100644 --- a/modules/core/02-client/types/msgs_test.go +++ b/modules/core/02-client/types/msgs_test.go @@ -981,3 +981,60 @@ func TestMsgUpdateParamsGetSigners(t *testing.T) { } } } + +func TestMsgRegisterCounterpartyValidateBasic(t *testing.T) { + signer := ibctesting.TestAccAddress + testCases := []struct { + name string + msg *types.MsgRegisterCounterparty + expError error + }{ + { + "success", + types.NewMsgRegisterCounterparty( + "testclientid", + [][]byte{[]byte("ibc"), []byte("channel-9")}, + signer, + ), + nil, + }, + { + "failure: empty client id", + types.NewMsgRegisterCounterparty( + "", + [][]byte{[]byte("ibc"), []byte("channel-9")}, + signer, + ), + host.ErrInvalidID, + }, + { + "failure: empty counterparty messaging key", + types.NewMsgRegisterCounterparty( + "testclientid", + [][]byte{}, + signer, + ), + types.ErrInvalidCounterparty, + }, + { + "failure: empty signer", + types.NewMsgRegisterCounterparty( + "testclientid", + [][]byte{[]byte("ibc"), []byte("channel-9")}, + "badsigner", + ), + ibcerrors.ErrInvalidAddress, + }, + } + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.expError == nil { + require.NoError(t, err) + } else { + require.ErrorIs(t, err, tc.expError) + } + }) + } +} diff --git a/modules/core/04-channel/v2/types/query.pb.go b/modules/core/04-channel/v2/types/query.pb.go index 90f01927af7..c6db77defa7 100644 --- a/modules/core/04-channel/v2/types/query.pb.go +++ b/modules/core/04-channel/v2/types/query.pb.go @@ -6,11 +6,11 @@ package types import ( context "context" fmt "fmt" - types1 "github.com/cosmos/cosmos-sdk/codec/types" query "github.com/cosmos/cosmos-sdk/types/query" _ "github.com/cosmos/gogoproto/gogoproto" grpc1 "github.com/cosmos/gogoproto/grpc" proto "github.com/cosmos/gogoproto/proto" + any "github.com/cosmos/gogoproto/types/any" types "github.com/cosmos/ibc-go/v9/modules/core/02-client/types" _ "google.golang.org/genproto/googleapis/api/annotations" grpc "google.golang.org/grpc" @@ -304,7 +304,7 @@ func (m *QueryChannelConsensusStateRequest) GetRevisionHeight() uint64 { // Query/QueryChannelConsensusState RPC method type QueryChannelConsensusStateResponse struct { // consensus state associated with the channel - ConsensusState *types1.Any `protobuf:"bytes,1,opt,name=consensus_state,json=consensusState,proto3" json:"consensus_state,omitempty"` + ConsensusState *any.Any `protobuf:"bytes,1,opt,name=consensus_state,json=consensusState,proto3" json:"consensus_state,omitempty"` // client ID associated with the consensus state ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` // merkle proof of existence @@ -346,7 +346,7 @@ func (m *QueryChannelConsensusStateResponse) XXX_DiscardUnknown() { var xxx_messageInfo_QueryChannelConsensusStateResponse proto.InternalMessageInfo -func (m *QueryChannelConsensusStateResponse) GetConsensusState() *types1.Any { +func (m *QueryChannelConsensusStateResponse) GetConsensusState() *any.Any { if m != nil { return m.ConsensusState } @@ -3886,7 +3886,7 @@ func (m *QueryChannelConsensusStateResponse) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.ConsensusState == nil { - m.ConsensusState = &types1.Any{} + m.ConsensusState = &any.Any{} } if err := m.ConsensusState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err diff --git a/modules/core/keeper/msg_server.go b/modules/core/keeper/msg_server.go index e99b58d3b9c..9410634ef52 100644 --- a/modules/core/keeper/msg_server.go +++ b/modules/core/keeper/msg_server.go @@ -40,9 +40,29 @@ func (k *Keeper) CreateClient(ctx context.Context, msg *clienttypes.MsgCreateCli return nil, err } + // set the client creator so that eureka counterparty can be set by same relayer + k.ClientKeeper.SetClientCreator(ctx, clientID, sdk.AccAddress(msg.Signer)) + return &clienttypes.MsgCreateClientResponse{ClientId: clientID}, nil } +// RegisterCounterparty will register the eureka counterparty info for the given client id +// it must be called by the same relayer that called CreateClient +func (k *Keeper) RegisterCounterparty(ctx context.Context, msg *clienttypes.MsgRegisterCounterparty) (*clienttypes.MsgRegisterCounterpartyResponse, error) { + creator := k.ClientKeeper.GetClientCreator(ctx, msg.ClientId) + if !creator.Equals(sdk.AccAddress(msg.Signer)) { + return nil, errorsmod.Wrapf(ibcerrors.ErrUnauthorized, "expected same signer as createClient submittor %s, got %s", creator, msg.Signer) + } + + counterpartyInfo := clienttypes.CounterpartyInfo{ + CounterpartyMessagingKey: msg.CounterpartyMessagingKey, + } + k.ClientKeeper.SetClientCounterparty(ctx, msg.ClientId, counterpartyInfo) + + k.ClientKeeper.DeleteClientCreator(ctx, msg.ClientId) + return &clienttypes.MsgRegisterCounterpartyResponse{}, nil +} + // UpdateClient defines a rpc handler method for MsgUpdateClient. func (k *Keeper) UpdateClient(ctx context.Context, msg *clienttypes.MsgUpdateClient) (*clienttypes.MsgUpdateClientResponse, error) { clientMsg, err := clienttypes.UnpackClientMessage(msg.ClientMessage) diff --git a/modules/core/keeper/msg_server_test.go b/modules/core/keeper/msg_server_test.go index 83f444f1c7d..a36afc1f54d 100644 --- a/modules/core/keeper/msg_server_test.go +++ b/modules/core/keeper/msg_server_test.go @@ -31,6 +31,62 @@ var ( maxSequence = uint64(10) ) +// TestRegisterCounterparty tests that counterpartyInfo is correctly stored +// and only if the submittor is the same submittor as prior createClient msg +func (suite *KeeperTestSuite) TestRegisterCounterparty() { + var path *ibctesting.Path + testCases := []struct { + name string + malleate func() + expError error + }{ + { + "success", + func() { + path.SetupClients() + }, + nil, + }, + { + "client not created first", + func() {}, + ibcerrors.ErrUnauthorized, + }, + { + "creator is different than expected", + func() { + path.SetupClients() + path.EndpointA.Chain.App.GetIBCKeeper().ClientKeeper.SetClientCreator(suite.chainA.GetContext(), path.EndpointA.ClientID, sdk.AccAddress(ibctesting.TestAccAddress)) + }, + ibcerrors.ErrUnauthorized, + }, + } + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + suite.SetupTest() + path = ibctesting.NewPath(suite.chainA, suite.chainB) + + tc.malleate() + counterpartyKey := [][]byte{[]byte("ibc"), []byte("channel-7")} + msg := clienttypes.NewMsgRegisterCounterparty(path.EndpointA.ClientID, counterpartyKey, suite.chainA.SenderAccount.GetAddress().String()) + _, err := suite.chainA.App.GetIBCKeeper().RegisterCounterparty(suite.chainA.GetContext(), msg) + if tc.expError != nil { + suite.Require().Error(err) + suite.Require().True(errors.Is(err, tc.expError)) + } else { + suite.Require().NoError(err) + counterpartyInfo, ok := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientCounterparty(suite.chainA.GetContext(), path.EndpointA.ClientID) + suite.Require().True(ok) + suite.Require().Equal(counterpartyInfo, clienttypes.CounterpartyInfo{counterpartyKey}) + creator := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientCreator(suite.chainA.GetContext(), path.EndpointA.ClientID) + suite.Require().Empty(creator) + } + }) + } + +} + // tests the IBC handler receiving a packet on ordered and unordered channels. // It verifies that the storing of an acknowledgement on success occurs. It // tests high level properties like ordering and basic sanity checks. More diff --git a/proto/ibc/core/client/v2/counterparty.proto b/proto/ibc/core/client/v2/counterparty.proto new file mode 100644 index 00000000000..fd5424e3fcb --- /dev/null +++ b/proto/ibc/core/client/v2/counterparty.proto @@ -0,0 +1,42 @@ +syntax = "proto3"; + +package ibc.core.client.v2; + +option go_package = "github.com/cosmos/ibc-go/v9/modules/core/02-client/types"; + +import "cosmos/msg/v1/msg.proto"; +import "gogoproto/gogo.proto"; + +// CounterpartyInfo defines the key that the counterparty will use to message our client +message CounterpartyInfo { + // counterparty messaging key prefix is the key that the counterparty will store + // all outgoing IBC packet messages intended for our chain. + // the provable messages will be stored with the following key prefix and the + // ICS24 standardized path for the given message type + repeated bytes counterparty_messaging_key = 1; +} + +// CounterpartyMsg defines the ibc/client CounterpartyMsg service. +service CounterpartyMsg { + option (cosmos.msg.v1.service) = true; + + // RegisterCounterparty defines a rpc handler method for MsgRegisterCounterparty. + rpc RegisterCounterparty(MsgRegisterCounterparty) returns (MsgRegisterCounterpartyResponse); +} + +// MsgRegisterCounterparty defines a message to register a counterparty on a client +message MsgRegisterCounterparty { + option (cosmos.msg.v1.signer) = "signer"; + + option (gogoproto.goproto_getters) = false; + + // client identifier + string client_id = 1; + // counterparty messaging key + repeated bytes counterparty_messaging_key = 2; + // signer address + string signer = 3; +} + +// MsgRegisterCounterpartyResponse defines the Msg/RegisterCounterparty response type. +message MsgRegisterCounterpartyResponse {} \ No newline at end of file