From b4253a5c0be4f2799fb0d0818297ae14f1b2e1ac Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Fri, 4 Aug 2023 15:13:01 -0300 Subject: [PATCH 1/5] Add update functionality for WASM code id The commit introduces the new rpc handler method, `UpdateWasmCodeId`, for updating the WASM code id within IBC light clients. This allows clients to change the existing code id for WASM contracts. The new function takes in three parameters, signer, client id, and code id and updates the existing code id for the given client. This functionality was necessary for providing flexibility in managing the contracts. The update can only be triggered by the authority. --- modules/core/02-client/types/events.go | 1 + .../light-clients/08-wasm/client/cli/cli.go | 1 + .../light-clients/08-wasm/client/cli/tx.go | 42 +- .../light-clients/08-wasm/keeper/keeper.go | 21 +- .../08-wasm/keeper/msg_server.go | 56 +- modules/light-clients/08-wasm/types/msgs.go | 46 ++ modules/light-clients/08-wasm/types/tx.pb.go | 579 +++++++++++++++++- proto/ibc/lightclients/wasm/v1/tx.proto | 18 +- testing/simapp/app.go | 2 +- 9 files changed, 733 insertions(+), 33 deletions(-) diff --git a/modules/core/02-client/types/events.go b/modules/core/02-client/types/events.go index f0b607536cc..f7a9e01e9d2 100644 --- a/modules/core/02-client/types/events.go +++ b/modules/core/02-client/types/events.go @@ -30,6 +30,7 @@ var ( EventTypeUpgradeChain = "upgrade_chain" EventTypeUpgradeClientProposal = "upgrade_client_proposal" EventTypePushWasmCode = "push_wasm_code" + EventTypeUpdateWasmCodeId = "update_wasm_code_id" AttributeValueCategory = fmt.Sprintf("%s_%s", ibcexported.ModuleName, SubModuleName) ) diff --git a/modules/light-clients/08-wasm/client/cli/cli.go b/modules/light-clients/08-wasm/client/cli/cli.go index bafceca11f0..11d03d7dfb0 100644 --- a/modules/light-clients/08-wasm/client/cli/cli.go +++ b/modules/light-clients/08-wasm/client/cli/cli.go @@ -38,6 +38,7 @@ func NewTxCmd() *cobra.Command { txCmd.AddCommand( newPushNewWasmCodeCmd(), + newUpdateWasmCodeId(), ) return txCmd diff --git a/modules/light-clients/08-wasm/client/cli/tx.go b/modules/light-clients/08-wasm/client/cli/tx.go index d94da2e823c..c8a2e71132b 100644 --- a/modules/light-clients/08-wasm/client/cli/tx.go +++ b/modules/light-clients/08-wasm/client/cli/tx.go @@ -6,9 +6,9 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" + transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + "github.com/cosmos/ibc-go/v7/modules/light-clients/08-wasm/types" "github.com/spf13/cobra" - - types "github.com/cosmos/ibc-go/v7/modules/light-clients/08-wasm/types" ) // newPushNewWasmCodeCmd returns the command to create a PushNewWasmCode transaction @@ -47,3 +47,41 @@ func newPushNewWasmCodeCmd() *cobra.Command { return cmd } + +// newUpdateWasmCodeId returns the command to create a UpdateWasmCodeId transaction +func newUpdateWasmCodeId() *cobra.Command { + cmd := &cobra.Command{ + Use: "update-wasm-code-id [client-id] [code-id]", + Short: "Updates wasm code id for a client", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + clientId := args[0] + codeId, err := transfertypes.ParseHexHash(args[1]) + + if err != nil { + return err + } + + msg := &types.MsgUpdateWasmCodeId{ + ClientId: clientId, + CodeId: codeId, + Signer: clientCtx.GetFromAddress().String(), + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/modules/light-clients/08-wasm/keeper/keeper.go b/modules/light-clients/08-wasm/keeper/keeper.go index 3843889eb04..17b0e5869f3 100644 --- a/modules/light-clients/08-wasm/keeper/keeper.go +++ b/modules/light-clients/08-wasm/keeper/keeper.go @@ -6,6 +6,7 @@ import ( "crypto/sha256" "encoding/hex" "fmt" + clientkeeper "github.com/cosmos/ibc-go/v7/modules/core/02-client/keeper" "math" "path/filepath" "strings" @@ -25,13 +26,14 @@ import ( ) type Keeper struct { - storeKey storetypes.StoreKey - cdc codec.BinaryCodec - wasmVM *cosmwasm.VM - authority string + storeKey storetypes.StoreKey + cdc codec.BinaryCodec + wasmVM *cosmwasm.VM + authority string + clientKeeper *clientkeeper.Keeper } -func NewKeeper(cdc codec.BinaryCodec, key storetypes.StoreKey, authority string, homeDir string) Keeper { +func NewKeeper(cdc codec.BinaryCodec, key storetypes.StoreKey, authority string, homeDir string, clientKeeper *clientkeeper.Keeper) Keeper { // Wasm VM wasmDataDir := filepath.Join(homeDir, "wasm_client_data") wasmSupportedFeatures := strings.Join([]string{"storage", "iterator"}, ",") @@ -48,10 +50,11 @@ func NewKeeper(cdc codec.BinaryCodec, key storetypes.StoreKey, authority string, // governance authority return Keeper{ - cdc: cdc, - storeKey: key, - wasmVM: vm, - authority: authority, + cdc: cdc, + storeKey: key, + wasmVM: vm, + authority: authority, + clientKeeper: clientKeeper, } } diff --git a/modules/light-clients/08-wasm/keeper/msg_server.go b/modules/light-clients/08-wasm/keeper/msg_server.go index b20368f16ae..ee508ccba06 100644 --- a/modules/light-clients/08-wasm/keeper/msg_server.go +++ b/modules/light-clients/08-wasm/keeper/msg_server.go @@ -3,11 +3,13 @@ package keeper import ( "context" "encoding/hex" - + "fmt" + "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" + host "github.com/cosmos/ibc-go/v7/modules/core/24-host" "github.com/cosmos/ibc-go/v7/modules/light-clients/08-wasm/types" ) @@ -41,3 +43,55 @@ func (k Keeper) PushNewWasmCode(goCtx context.Context, msg *types.MsgPushNewWasm CodeId: codeID, }, nil } + +func (k Keeper) ClientStore(ctx sdk.Context, clientID string) sdk.KVStore { + clientPrefix := []byte(fmt.Sprintf("%s/%s/", host.KeyClientStorePrefix, clientID)) + return prefix.NewStore(ctx.KVStore(k.storeKey), clientPrefix) +} + +// UpdateWasmCodeId defines a rpc handler method for MsgUpdateWasmCodeId +func (k Keeper) UpdateWasmCodeId(goCtx context.Context, msg *types.MsgUpdateWasmCodeId) (*types.MsgUpdateWasmCodeIdResponse, error) { + if k.authority != msg.Signer { + return nil, sdkerrors.Wrapf(govtypes.ErrInvalidSigner, "invalid authority: expected %s, got %s", k.authority, msg.Signer) + } + + ctx := sdk.UnwrapSDKContext(goCtx) + store := ctx.KVStore(k.storeKey) + + codeId := msg.CodeId + if !store.Has(types.CodeID(codeId)) { + return nil, sdkerrors.Wrapf(types.ErrInvalidCodeId, "code id %s does not exist", hex.EncodeToString(codeId)) + } + + clientId := msg.ClientId + unknownClientState, found := k.clientKeeper.GetClientState(ctx, clientId) + if !found { + return nil, sdkerrors.Wrapf(clienttypes.ErrClientNotFound, "cannot update client with ID %s", clientId) + } + + clientState, ok := unknownClientState.(*types.ClientState) + if !ok { + return nil, sdkerrors.Wrapf(types.ErrInvalid, "client state type %T, expected %T", unknownClientState, (*types.ClientState)(nil)) + } + + clientState.CodeId = codeId + + k.clientKeeper.SetClientState(ctx, clientId, clientState) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + clienttypes.EventTypeUpdateWasmCodeId, + sdk.NewAttribute(clienttypes.AttributeKeyClientID, clientId), + sdk.NewAttribute(clienttypes.AttributeKeyWasmCodeID, hex.EncodeToString(codeId)), + ), + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, clienttypes.AttributeValueCategory), + ), + }) + + return &types.MsgUpdateWasmCodeIdResponse{ + ClientId: clientId, + CodeId: codeId, + }, nil +} diff --git a/modules/light-clients/08-wasm/types/msgs.go b/modules/light-clients/08-wasm/types/msgs.go index 986e850f02b..0b1ada956bc 100644 --- a/modules/light-clients/08-wasm/types/msgs.go +++ b/modules/light-clients/08-wasm/types/msgs.go @@ -8,6 +8,9 @@ import ( var TypeMsgPushNewWasmCode = "push_wasm_code" var _ sdk.Msg = &MsgPushNewWasmCode{} +var TypeMsgUpdateWasmCodeId = "update_wasm_code_id" +var _ sdk.Msg = &MsgUpdateWasmCodeId{} + // NewMsgPushNewWasmCode creates a new MsgPushNewWasmCode instance // //nolint:interfacer @@ -47,3 +50,46 @@ func (m MsgPushNewWasmCode) GetSigners() []sdk.AccAddress { func (msg MsgPushNewWasmCode) GetSignBytes() []byte { return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg)) } + +// NewMsgUpdateWasmCodeId creates a new MsgUpdateWasmCodeId instance +// +//nolint:interfacer + +// Route Implements Msg. +func (msg MsgUpdateWasmCodeId) Route() string { return ModuleName } + +// Type Implements Msg. +func (msg MsgUpdateWasmCodeId) Type() string { return TypeMsgUpdateWasmCodeId } + +// TODO: add tests for MsgUpdateWasmCodeId + +func NewMsgUpdateWasmCodeId(signer string, codeId []byte, clientId string) *MsgUpdateWasmCodeId { + return &MsgUpdateWasmCodeId{ + Signer: signer, + CodeId: codeId, + ClientId: clientId, + } +} + +func (m MsgUpdateWasmCodeId) ValidateBasic() error { + if len(m.CodeId) != 32 { + return sdkerrors.Wrapf(ErrWasmEmptyCode, + "invalid code id length (expected 32, got %d)", len(m.CodeId), + ) + } + + return nil +} + +func (m MsgUpdateWasmCodeId) GetSigners() []sdk.AccAddress { + signer, err := sdk.AccAddressFromBech32(m.Signer) + if err != nil { + panic(err) + } + return []sdk.AccAddress{signer} +} + +// GetSignBytes implements the LegacyMsg interface. +func (msg MsgUpdateWasmCodeId) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg)) +} diff --git a/modules/light-clients/08-wasm/types/tx.pb.go b/modules/light-clients/08-wasm/types/tx.pb.go index dcbf69886e4..e13a443d4aa 100644 --- a/modules/light-clients/08-wasm/types/tx.pb.go +++ b/modules/light-clients/08-wasm/types/tx.pb.go @@ -125,33 +125,153 @@ func (m *MsgPushNewWasmCodeResponse) GetCodeId() []byte { return nil } +// Message type to update wasm code id +type MsgUpdateWasmCodeId struct { + Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` + ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + CodeId []byte `protobuf:"bytes,3,opt,name=code_id,json=codeId,proto3" json:"code_id,omitempty"` +} + +func (m *MsgUpdateWasmCodeId) Reset() { *m = MsgUpdateWasmCodeId{} } +func (m *MsgUpdateWasmCodeId) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateWasmCodeId) ProtoMessage() {} +func (*MsgUpdateWasmCodeId) Descriptor() ([]byte, []int) { + return fileDescriptor_1d9737363bf1e38d, []int{2} +} +func (m *MsgUpdateWasmCodeId) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateWasmCodeId) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateWasmCodeId.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 *MsgUpdateWasmCodeId) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateWasmCodeId.Merge(m, src) +} +func (m *MsgUpdateWasmCodeId) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateWasmCodeId) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateWasmCodeId.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateWasmCodeId proto.InternalMessageInfo + +func (m *MsgUpdateWasmCodeId) GetSigner() string { + if m != nil { + return m.Signer + } + return "" +} + +func (m *MsgUpdateWasmCodeId) GetClientId() string { + if m != nil { + return m.ClientId + } + return "" +} + +func (m *MsgUpdateWasmCodeId) GetCodeId() []byte { + if m != nil { + return m.CodeId + } + return nil +} + +// Response in case of successful handling +type MsgUpdateWasmCodeIdResponse struct { + ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + CodeId []byte `protobuf:"bytes,2,opt,name=code_id,json=codeId,proto3" json:"code_id,omitempty"` +} + +func (m *MsgUpdateWasmCodeIdResponse) Reset() { *m = MsgUpdateWasmCodeIdResponse{} } +func (m *MsgUpdateWasmCodeIdResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateWasmCodeIdResponse) ProtoMessage() {} +func (*MsgUpdateWasmCodeIdResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1d9737363bf1e38d, []int{3} +} +func (m *MsgUpdateWasmCodeIdResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateWasmCodeIdResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateWasmCodeIdResponse.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 *MsgUpdateWasmCodeIdResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateWasmCodeIdResponse.Merge(m, src) +} +func (m *MsgUpdateWasmCodeIdResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateWasmCodeIdResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateWasmCodeIdResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateWasmCodeIdResponse proto.InternalMessageInfo + +func (m *MsgUpdateWasmCodeIdResponse) GetClientId() string { + if m != nil { + return m.ClientId + } + return "" +} + +func (m *MsgUpdateWasmCodeIdResponse) GetCodeId() []byte { + if m != nil { + return m.CodeId + } + return nil +} + func init() { proto.RegisterType((*MsgPushNewWasmCode)(nil), "ibc.lightclients.wasm.v1.MsgPushNewWasmCode") proto.RegisterType((*MsgPushNewWasmCodeResponse)(nil), "ibc.lightclients.wasm.v1.MsgPushNewWasmCodeResponse") + proto.RegisterType((*MsgUpdateWasmCodeId)(nil), "ibc.lightclients.wasm.v1.MsgUpdateWasmCodeId") + proto.RegisterType((*MsgUpdateWasmCodeIdResponse)(nil), "ibc.lightclients.wasm.v1.MsgUpdateWasmCodeIdResponse") } func init() { proto.RegisterFile("ibc/lightclients/wasm/v1/tx.proto", fileDescriptor_1d9737363bf1e38d) } var fileDescriptor_1d9737363bf1e38d = []byte{ - // 276 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xcc, 0x4c, 0x4a, 0xd6, - 0xcf, 0xc9, 0x4c, 0xcf, 0x28, 0x49, 0xce, 0xc9, 0x4c, 0xcd, 0x2b, 0x29, 0xd6, 0x2f, 0x4f, 0x2c, - 0xce, 0xd5, 0x2f, 0x33, 0xd4, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0xc8, - 0x4c, 0x4a, 0xd6, 0x43, 0x56, 0xa2, 0x07, 0x52, 0xa2, 0x57, 0x66, 0xa8, 0xe4, 0xc0, 0x25, 0xe4, - 0x5b, 0x9c, 0x1e, 0x50, 0x5a, 0x9c, 0xe1, 0x97, 0x5a, 0x1e, 0x9e, 0x58, 0x9c, 0xeb, 0x9c, 0x9f, - 0x92, 0x2a, 0x24, 0xc6, 0xc5, 0x56, 0x9c, 0x99, 0x9e, 0x97, 0x5a, 0x24, 0xc1, 0xa8, 0xc0, 0xa8, - 0xc1, 0x19, 0x04, 0xe5, 0x09, 0x09, 0x71, 0xb1, 0x24, 0xe7, 0xa7, 0xa4, 0x4a, 0x30, 0x29, 0x30, - 0x6a, 0xf0, 0x04, 0x81, 0xd9, 0x4a, 0xa6, 0x5c, 0x52, 0x98, 0x26, 0x04, 0xa5, 0x16, 0x17, 0xe4, - 0xe7, 0x15, 0xa7, 0x0a, 0x89, 0x73, 0xb1, 0x83, 0x54, 0xc5, 0x67, 0xa6, 0x80, 0x8d, 0xe2, 0x09, - 0x62, 0x03, 0x71, 0x3d, 0x53, 0x8c, 0x6a, 0xb8, 0x98, 0x7d, 0x8b, 0xd3, 0x85, 0x4a, 0xb9, 0xf8, - 0xd1, 0x2d, 0xd7, 0xd1, 0xc3, 0xe5, 0x5a, 0x3d, 0x4c, 0x8b, 0xa4, 0x4c, 0x48, 0x51, 0x0d, 0x73, - 0x96, 0x53, 0xe4, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, - 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0xd9, 0xa7, 0x67, - 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x27, 0xe7, 0x17, 0xe7, 0xe6, 0x17, 0xeb, - 0x67, 0x26, 0x25, 0xeb, 0xa6, 0xe7, 0xeb, 0x97, 0x99, 0xeb, 0xe7, 0xe6, 0xa7, 0x94, 0xe6, 0xa4, - 0x16, 0x43, 0x42, 0x5b, 0x17, 0x16, 0xdc, 0x06, 0x16, 0xba, 0xe0, 0x10, 0x2f, 0xa9, 0x2c, 0x48, - 0x2d, 0x4e, 0x62, 0x03, 0x07, 0xb9, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x60, 0xe3, 0x92, 0xd7, - 0x97, 0x01, 0x00, 0x00, + // 351 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0xcf, 0x4e, 0x2a, 0x31, + 0x18, 0xc5, 0x29, 0xdc, 0x70, 0x2f, 0x0d, 0xc9, 0x35, 0x35, 0x51, 0x02, 0xc9, 0x04, 0x59, 0xb1, + 0x70, 0x5a, 0x51, 0x89, 0xee, 0x34, 0xba, 0x62, 0x81, 0x31, 0x63, 0x8c, 0xd1, 0x8d, 0x61, 0xda, + 0xa6, 0x34, 0x61, 0xe8, 0x84, 0xaf, 0x03, 0xf8, 0x16, 0x3e, 0x96, 0x4b, 0x96, 0x2e, 0x0d, 0xbc, + 0x83, 0x6b, 0x33, 0x83, 0x10, 0xfe, 0x88, 0x09, 0xbb, 0x7e, 0xed, 0xe9, 0xef, 0x7c, 0x39, 0x39, + 0xf8, 0x40, 0xfb, 0x9c, 0x75, 0xb4, 0x6a, 0x5b, 0xde, 0xd1, 0xb2, 0x6b, 0x81, 0x0d, 0x5a, 0x10, + 0xb0, 0x7e, 0x8d, 0xd9, 0x21, 0x0d, 0x7b, 0xc6, 0x1a, 0x52, 0xd0, 0x3e, 0xa7, 0x8b, 0x12, 0x1a, + 0x4b, 0x68, 0xbf, 0x56, 0xb9, 0xc4, 0xa4, 0x09, 0xea, 0x36, 0x82, 0xf6, 0x8d, 0x1c, 0x3c, 0xb4, + 0x20, 0xb8, 0x36, 0x42, 0x92, 0x3d, 0x9c, 0x05, 0xad, 0xba, 0xb2, 0x57, 0x40, 0x65, 0x54, 0xcd, + 0x79, 0xdf, 0x13, 0x21, 0xf8, 0x0f, 0x37, 0x42, 0x16, 0xd2, 0x65, 0x54, 0xcd, 0x7b, 0xc9, 0xb9, + 0x52, 0xc7, 0xc5, 0x75, 0x82, 0x27, 0x21, 0x34, 0x5d, 0x90, 0x64, 0x1f, 0xff, 0x8d, 0x55, 0xcf, + 0x5a, 0x24, 0xa8, 0xbc, 0x97, 0x8d, 0xc7, 0x86, 0xa8, 0x70, 0xbc, 0xdb, 0x04, 0x75, 0x1f, 0x8a, + 0x96, 0x95, 0xb3, 0x5f, 0x0d, 0xb1, 0xd1, 0xb9, 0x84, 0x73, 0xd3, 0xd5, 0x63, 0x52, 0x3a, 0x79, + 0xfa, 0x37, 0xbd, 0x68, 0x88, 0x45, 0x93, 0xcc, 0x92, 0xc9, 0x1d, 0x2e, 0xfd, 0x60, 0x32, 0x5f, + 0x6e, 0x09, 0x8a, 0x36, 0x43, 0xd3, 0x8b, 0xd0, 0xe3, 0x4f, 0x84, 0x33, 0x4d, 0x50, 0x24, 0xc2, + 0xff, 0x57, 0x73, 0x3b, 0xa4, 0x9b, 0x82, 0xa6, 0xeb, 0x19, 0x15, 0x4f, 0xb7, 0x51, 0xcf, 0x97, + 0x1e, 0xe2, 0x9d, 0xb5, 0xd4, 0xdc, 0x5f, 0x49, 0xab, 0xf2, 0x62, 0x7d, 0x2b, 0xf9, 0xcc, 0xf9, + 0xea, 0xf1, 0x6d, 0xec, 0xa0, 0xd1, 0xd8, 0x41, 0x1f, 0x63, 0x07, 0xbd, 0x4e, 0x9c, 0xd4, 0x68, + 0xe2, 0xa4, 0xde, 0x27, 0x4e, 0xea, 0xe9, 0x42, 0x69, 0xdb, 0x8e, 0x7c, 0xca, 0x4d, 0xc0, 0xb8, + 0x81, 0xc0, 0x00, 0xd3, 0x3e, 0x77, 0x95, 0x61, 0xfd, 0x33, 0x16, 0x18, 0x11, 0x75, 0x24, 0x4c, + 0x2b, 0xea, 0xce, 0x3a, 0x7a, 0x74, 0xee, 0x26, 0x35, 0xb5, 0x2f, 0xa1, 0x04, 0x3f, 0x9b, 0xf4, + 0xf4, 0xe4, 0x2b, 0x00, 0x00, 0xff, 0xff, 0xa3, 0x41, 0x45, 0x75, 0xcc, 0x02, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -168,6 +288,8 @@ const _ = grpc.SupportPackageIsVersion4 type MsgClient interface { // PushNewWasmCode defines a rpc handler method for PushNewWasmCode. PushNewWasmCode(ctx context.Context, in *MsgPushNewWasmCode, opts ...grpc.CallOption) (*MsgPushNewWasmCodeResponse, error) + // UpdateWasmCodeId defines a rpc handler method for UpdateWasmCodeId. + UpdateWasmCodeId(ctx context.Context, in *MsgUpdateWasmCodeId, opts ...grpc.CallOption) (*MsgUpdateWasmCodeIdResponse, error) } type msgClient struct { @@ -187,10 +309,21 @@ func (c *msgClient) PushNewWasmCode(ctx context.Context, in *MsgPushNewWasmCode, return out, nil } +func (c *msgClient) UpdateWasmCodeId(ctx context.Context, in *MsgUpdateWasmCodeId, opts ...grpc.CallOption) (*MsgUpdateWasmCodeIdResponse, error) { + out := new(MsgUpdateWasmCodeIdResponse) + err := c.cc.Invoke(ctx, "/ibc.lightclients.wasm.v1.Msg/UpdateWasmCodeId", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { // PushNewWasmCode defines a rpc handler method for PushNewWasmCode. PushNewWasmCode(context.Context, *MsgPushNewWasmCode) (*MsgPushNewWasmCodeResponse, error) + // UpdateWasmCodeId defines a rpc handler method for UpdateWasmCodeId. + UpdateWasmCodeId(context.Context, *MsgUpdateWasmCodeId) (*MsgUpdateWasmCodeIdResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -200,6 +333,9 @@ type UnimplementedMsgServer struct { func (*UnimplementedMsgServer) PushNewWasmCode(ctx context.Context, req *MsgPushNewWasmCode) (*MsgPushNewWasmCodeResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method PushNewWasmCode not implemented") } +func (*UnimplementedMsgServer) UpdateWasmCodeId(ctx context.Context, req *MsgUpdateWasmCodeId) (*MsgUpdateWasmCodeIdResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateWasmCodeId not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -223,6 +359,24 @@ func _Msg_PushNewWasmCode_Handler(srv interface{}, ctx context.Context, dec func return interceptor(ctx, in, info, handler) } +func _Msg_UpdateWasmCodeId_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateWasmCodeId) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateWasmCodeId(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ibc.lightclients.wasm.v1.Msg/UpdateWasmCodeId", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateWasmCodeId(ctx, req.(*MsgUpdateWasmCodeId)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "ibc.lightclients.wasm.v1.Msg", HandlerType: (*MsgServer)(nil), @@ -231,6 +385,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "PushNewWasmCode", Handler: _Msg_PushNewWasmCode_Handler, }, + { + MethodName: "UpdateWasmCodeId", + Handler: _Msg_UpdateWasmCodeId_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "ibc/lightclients/wasm/v1/tx.proto", @@ -303,6 +461,87 @@ func (m *MsgPushNewWasmCodeResponse) MarshalToSizedBuffer(dAtA []byte) (int, err return len(dAtA) - i, nil } +func (m *MsgUpdateWasmCodeId) 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 *MsgUpdateWasmCodeId) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateWasmCodeId) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.CodeId) > 0 { + i -= len(m.CodeId) + copy(dAtA[i:], m.CodeId) + i = encodeVarintTx(dAtA, i, uint64(len(m.CodeId))) + i-- + dAtA[i] = 0x1a + } + if len(m.ClientId) > 0 { + i -= len(m.ClientId) + copy(dAtA[i:], m.ClientId) + i = encodeVarintTx(dAtA, i, uint64(len(m.ClientId))) + i-- + dAtA[i] = 0x12 + } + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateWasmCodeIdResponse) 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 *MsgUpdateWasmCodeIdResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateWasmCodeIdResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.CodeId) > 0 { + i -= len(m.CodeId) + copy(dAtA[i:], m.CodeId) + i = encodeVarintTx(dAtA, i, uint64(len(m.CodeId))) + i-- + dAtA[i] = 0x12 + } + if len(m.ClientId) > 0 { + i -= len(m.ClientId) + copy(dAtA[i:], m.ClientId) + i = encodeVarintTx(dAtA, i, uint64(len(m.ClientId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -344,6 +583,44 @@ func (m *MsgPushNewWasmCodeResponse) Size() (n int) { return n } +func (m *MsgUpdateWasmCodeId) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ClientId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.CodeId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgUpdateWasmCodeIdResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ClientId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.CodeId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -550,6 +827,270 @@ func (m *MsgPushNewWasmCodeResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgUpdateWasmCodeId) 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 ErrIntOverflowTx + } + 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: MsgUpdateWasmCodeId: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateWasmCodeId: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + 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 ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClientId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CodeId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CodeId = append(m.CodeId[:0], dAtA[iNdEx:postIndex]...) + if m.CodeId == nil { + m.CodeId = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateWasmCodeIdResponse) 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 ErrIntOverflowTx + } + 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: MsgUpdateWasmCodeIdResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateWasmCodeIdResponse: 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 ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + 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 CodeId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CodeId = append(m.CodeId[:0], dAtA[iNdEx:postIndex]...) + if m.CodeId == nil { + m.CodeId = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/proto/ibc/lightclients/wasm/v1/tx.proto b/proto/ibc/lightclients/wasm/v1/tx.proto index cd6a95a35bc..5599e8d0c41 100644 --- a/proto/ibc/lightclients/wasm/v1/tx.proto +++ b/proto/ibc/lightclients/wasm/v1/tx.proto @@ -7,6 +7,9 @@ option go_package = "github.com/cosmos/ibc-go/v7/modules/light-clients/08-wasm/t service Msg { // PushNewWasmCode defines a rpc handler method for PushNewWasmCode. rpc PushNewWasmCode(MsgPushNewWasmCode) returns (MsgPushNewWasmCodeResponse); + + // UpdateWasmCodeId defines a rpc handler method for UpdateWasmCodeId. + rpc UpdateWasmCodeId(MsgUpdateWasmCodeId) returns (MsgUpdateWasmCodeIdResponse); } // Message type to push new wasm code @@ -18,4 +21,17 @@ message MsgPushNewWasmCode { // Response in case of successful handling message MsgPushNewWasmCodeResponse { bytes code_id = 1; -} \ No newline at end of file +} + +// Message type to update wasm code id +message MsgUpdateWasmCodeId { + string signer = 1; + string client_id = 2; + bytes code_id = 3; +} + +// Response in case of successful handling +message MsgUpdateWasmCodeIdResponse { + string client_id = 1; + bytes code_id = 2; +} diff --git a/testing/simapp/app.go b/testing/simapp/app.go index cd3c6488dcb..58a2d5ca9ff 100644 --- a/testing/simapp/app.go +++ b/testing/simapp/app.go @@ -411,7 +411,7 @@ func NewSimApp( */ app.GroupKeeper = groupkeeper.NewKeeper(keys[group.StoreKey], appCodec, app.MsgServiceRouter(), app.AccountKeeper, groupConfig) - app.WasmClientKeeper = ibcwasmkeeper.NewKeeper(appCodec, keys[ibcwasmtypes.StoreKey], authtypes.NewModuleAddress(govtypes.ModuleName).String(), homePath) + app.WasmClientKeeper = ibcwasmkeeper.NewKeeper(appCodec, keys[ibcwasmtypes.StoreKey], authtypes.NewModuleAddress(govtypes.ModuleName).String(), homePath, &app.IBCKeeper.ClientKeeper) // IBC Fee Module keeper app.IBCFeeKeeper = ibcfeekeeper.NewKeeper( From 489fa5d90840686a50ac5dfcb1f74bc9c37ea21d Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Sat, 23 Sep 2023 17:02:39 -0300 Subject: [PATCH 2/5] Refactor validation and cleanup unused code The `ValidateBasic()` method calls were removed from `tx.go` as validation is now handled directly within the message struct `MsgUpdateWasmCodeId`, in `msgs.go`. Additionally, unused code was removed from `msg_server.go` to simplify and clean up the codebase. --- modules/light-clients/08-wasm/client/cli/tx.go | 8 -------- modules/light-clients/08-wasm/keeper/msg_server.go | 8 -------- modules/light-clients/08-wasm/types/msgs.go | 9 ++++++++- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/modules/light-clients/08-wasm/client/cli/tx.go b/modules/light-clients/08-wasm/client/cli/tx.go index c8a2e71132b..bc352d94b30 100644 --- a/modules/light-clients/08-wasm/client/cli/tx.go +++ b/modules/light-clients/08-wasm/client/cli/tx.go @@ -35,10 +35,6 @@ func newPushNewWasmCodeCmd() *cobra.Command { Signer: clientCtx.GetFromAddress().String(), } - if err := msg.ValidateBasic(); err != nil { - return err - } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) }, } @@ -73,10 +69,6 @@ func newUpdateWasmCodeId() *cobra.Command { Signer: clientCtx.GetFromAddress().String(), } - if err := msg.ValidateBasic(); err != nil { - return err - } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) }, } diff --git a/modules/light-clients/08-wasm/keeper/msg_server.go b/modules/light-clients/08-wasm/keeper/msg_server.go index ee508ccba06..73fe3152c34 100644 --- a/modules/light-clients/08-wasm/keeper/msg_server.go +++ b/modules/light-clients/08-wasm/keeper/msg_server.go @@ -3,13 +3,10 @@ package keeper import ( "context" "encoding/hex" - "fmt" - "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" - host "github.com/cosmos/ibc-go/v7/modules/core/24-host" "github.com/cosmos/ibc-go/v7/modules/light-clients/08-wasm/types" ) @@ -44,11 +41,6 @@ func (k Keeper) PushNewWasmCode(goCtx context.Context, msg *types.MsgPushNewWasm }, nil } -func (k Keeper) ClientStore(ctx sdk.Context, clientID string) sdk.KVStore { - clientPrefix := []byte(fmt.Sprintf("%s/%s/", host.KeyClientStorePrefix, clientID)) - return prefix.NewStore(ctx.KVStore(k.storeKey), clientPrefix) -} - // UpdateWasmCodeId defines a rpc handler method for MsgUpdateWasmCodeId func (k Keeper) UpdateWasmCodeId(goCtx context.Context, msg *types.MsgUpdateWasmCodeId) (*types.MsgUpdateWasmCodeIdResponse, error) { if k.authority != msg.Signer { diff --git a/modules/light-clients/08-wasm/types/msgs.go b/modules/light-clients/08-wasm/types/msgs.go index 0b1ada956bc..17c3502295f 100644 --- a/modules/light-clients/08-wasm/types/msgs.go +++ b/modules/light-clients/08-wasm/types/msgs.go @@ -1,8 +1,10 @@ package types import ( + "github.com/cometbft/cometbft/crypto/tmhash" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + host "github.com/cosmos/ibc-go/v7/modules/core/24-host" ) var TypeMsgPushNewWasmCode = "push_wasm_code" @@ -72,12 +74,17 @@ func NewMsgUpdateWasmCodeId(signer string, codeId []byte, clientId string) *MsgU } func (m MsgUpdateWasmCodeId) ValidateBasic() error { - if len(m.CodeId) != 32 { + if len(m.CodeId) != tmhash.Size { return sdkerrors.Wrapf(ErrWasmEmptyCode, "invalid code id length (expected 32, got %d)", len(m.CodeId), ) } + err := host.ClientIdentifierValidator(m.ClientId) + if err != nil { + return err + } + return nil } From ed35119cd64fd0297879b19a777824252b7ed26c Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Sat, 23 Sep 2023 17:43:29 -0300 Subject: [PATCH 3/5] add tests --- .../light-clients/08-wasm/types/types_test.go | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/modules/light-clients/08-wasm/types/types_test.go b/modules/light-clients/08-wasm/types/types_test.go index 11ce7a44245..2548c1fb523 100644 --- a/modules/light-clients/08-wasm/types/types_test.go +++ b/modules/light-clients/08-wasm/types/types_test.go @@ -209,6 +209,55 @@ func (suite *WasmTestSuite) TestPushNewWasmCodeWithErrors() { suite.Require().Error(err) } +func (suite *WasmTestSuite) TestUpdateWasmCodeId() { + suite.SetupWithChannel() + signer := authtypes.NewModuleAddress(govtypes.ModuleName).String() + data, err := os.ReadFile("test_data/ics07_tendermint_cw.wasm.gz") + suite.Require().NoError(err) + + msg := wasmtypes.NewMsgPushNewWasmCode(signer, data) + response, err := suite.wasmKeeper.PushNewWasmCode(suite.ctx, msg) + suite.Require().NoError(err) + newCodeId := response.CodeId + + msgUpdate := wasmtypes.NewMsgUpdateWasmCodeId(signer, newCodeId, "08-wasm-0") + _, err = suite.wasmKeeper.UpdateWasmCodeId(suite.ctx, msgUpdate) + suite.Require().NoError(err) + + cs, ok := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientState(suite.ctx, "08-wasm-0") + suite.Require().True(ok) + wasmCs, ok := cs.(*wasmtypes.ClientState) + suite.Require().True(ok) + suite.Require().Equal(newCodeId, wasmCs.CodeId) +} + +func (suite *WasmTestSuite) TestUpdateWasmCodeIdWithErrors() { + suite.SetupWithEmptyClient() + signer := authtypes.NewModuleAddress(govtypes.ModuleName).String() + data, err := os.ReadFile("test_data/ics07_tendermint_cw.wasm.gz") + suite.Require().NoError(err) + + msg := wasmtypes.NewMsgPushNewWasmCode(signer, data) + response, err := suite.wasmKeeper.PushNewWasmCode(suite.ctx, msg) + suite.Require().NoError(err) + newCodeId := response.CodeId + + // test invalid signer + msgUpdate := wasmtypes.NewMsgUpdateWasmCodeId("invalid", newCodeId, "08-wasm-0") + _, err = suite.wasmKeeper.UpdateWasmCodeId(suite.ctx, msgUpdate) + suite.Require().Error(err) + + // test invalid code id + msgUpdate = wasmtypes.NewMsgUpdateWasmCodeId(signer, []byte{}, "08-wasm-0") + _, err = suite.wasmKeeper.UpdateWasmCodeId(suite.ctx, msgUpdate) + suite.Require().Error(err) + + // test invalid client id + msgUpdate = wasmtypes.NewMsgUpdateWasmCodeId(signer, newCodeId, "invalid") + _, err = suite.wasmKeeper.UpdateWasmCodeId(suite.ctx, msgUpdate) + suite.Require().Error(err) +} + func (suite *WasmTestSuite) TestQueryWasmCode() { // test invalid query request _, err := suite.wasmKeeper.WasmCode(suite.ctx, &wasmtypes.WasmCodeQuery{}) From 4247dce8c428b7fb96e6b1b18752cc266cd63c6e Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Sat, 23 Sep 2023 17:47:41 -0300 Subject: [PATCH 4/5] add more test cases --- modules/light-clients/08-wasm/types/types_test.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/modules/light-clients/08-wasm/types/types_test.go b/modules/light-clients/08-wasm/types/types_test.go index 2548c1fb523..2292a2e9378 100644 --- a/modules/light-clients/08-wasm/types/types_test.go +++ b/modules/light-clients/08-wasm/types/types_test.go @@ -252,8 +252,19 @@ func (suite *WasmTestSuite) TestUpdateWasmCodeIdWithErrors() { _, err = suite.wasmKeeper.UpdateWasmCodeId(suite.ctx, msgUpdate) suite.Require().Error(err) + // test non-existing code id + nonExistingCodeId := make([]byte, 32) + msgUpdate = wasmtypes.NewMsgUpdateWasmCodeId(signer, nonExistingCodeId, "08-wasm-0") + _, err = suite.wasmKeeper.UpdateWasmCodeId(suite.ctx, msgUpdate) + suite.Require().Error(err) + // test invalid client id - msgUpdate = wasmtypes.NewMsgUpdateWasmCodeId(signer, newCodeId, "invalid") + msgUpdate = wasmtypes.NewMsgUpdateWasmCodeId(signer, newCodeId, "invalid\n") + _, err = suite.wasmKeeper.UpdateWasmCodeId(suite.ctx, msgUpdate) + suite.Require().Error(err) + + // test non-existing client id + msgUpdate = wasmtypes.NewMsgUpdateWasmCodeId(signer, newCodeId, "00-nonexist") _, err = suite.wasmKeeper.UpdateWasmCodeId(suite.ctx, msgUpdate) suite.Require().Error(err) } From ce6f5efed19ec0e5e7ba9ca33d14c1ec08dc84dc Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Sun, 24 Sep 2023 17:10:27 -0300 Subject: [PATCH 5/5] remove TODO --- modules/light-clients/08-wasm/types/msgs.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/light-clients/08-wasm/types/msgs.go b/modules/light-clients/08-wasm/types/msgs.go index 17c3502295f..15607e180ce 100644 --- a/modules/light-clients/08-wasm/types/msgs.go +++ b/modules/light-clients/08-wasm/types/msgs.go @@ -63,8 +63,6 @@ func (msg MsgUpdateWasmCodeId) Route() string { return ModuleName } // Type Implements Msg. func (msg MsgUpdateWasmCodeId) Type() string { return TypeMsgUpdateWasmCodeId } -// TODO: add tests for MsgUpdateWasmCodeId - func NewMsgUpdateWasmCodeId(signer string, codeId []byte, clientId string) *MsgUpdateWasmCodeId { return &MsgUpdateWasmCodeId{ Signer: signer,