diff --git a/go.mod b/go.mod index 0ede7fe5b08..5d3579580e4 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ replace github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.2021 require ( cosmossdk.io/api v0.9.2 + cosmossdk.io/collections v1.3.1 cosmossdk.io/core v0.11.3 cosmossdk.io/errors v1.0.2 cosmossdk.io/log v1.6.0 @@ -41,7 +42,6 @@ require ( cloud.google.com/go/iam v1.2.2 // indirect cloud.google.com/go/monitoring v1.21.2 // indirect cloud.google.com/go/storage v1.49.0 // indirect - cosmossdk.io/collections v1.3.1 // indirect cosmossdk.io/depinject v1.2.1 // indirect cosmossdk.io/schema v1.1.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect @@ -66,7 +66,6 @@ require ( github.com/chzyer/readline v1.5.1 // indirect github.com/cloudwego/base64x v0.1.5 // indirect github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f // indirect - github.com/cockroachdb/apd/v2 v2.0.2 // indirect github.com/cockroachdb/errors v1.12.0 // indirect github.com/cockroachdb/fifo v0.0.0-20240616162244-4768e80dfb9a // indirect github.com/cockroachdb/logtags v0.0.0-20241215232642-bb51bb14a506 // indirect diff --git a/modules/apps/27-gmp/PICKUP.md b/modules/apps/27-gmp/PICKUP.md new file mode 100644 index 00000000000..d997f6fb1c1 --- /dev/null +++ b/modules/apps/27-gmp/PICKUP.md @@ -0,0 +1,8 @@ +# GMP pickup document + +`27-gmp` application is feature complete, however, it is not yet production ready. This document outlines the remaining tasks to make it production ready. + +- `BuildAddressPredictable` should be audited and tested for security. Specifcally, what happens if the address was created by sending the address some coins first? +- `DeserializeCosmosTx` supports both protobuf encoding and protojson encoding. However, the support for this is hacky since it tries to decode the tx using both methods and returns the one that works. It would be better to have a more robust way to determine the encoding of the tx. +- Add unit tests and integration tests for the `27-gmp` module. Right now, there are no tests for this module. +- End to end tests should be added to ensure the entire flow works as expected. End to end tests should be added to this repository if Cosmos to Cosmos calls are to be supported, otherwise, the end to end tests in the `solidity-ibc-go` repository should be sufficient. diff --git a/modules/apps/27-gmp/ibc_module.go b/modules/apps/27-gmp/ibc_module.go new file mode 100644 index 00000000000..941e265b739 --- /dev/null +++ b/modules/apps/27-gmp/ibc_module.go @@ -0,0 +1,130 @@ +package gmp + +import ( + "fmt" + + errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/keeper" + "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types" + clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" + channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types" + "github.com/cosmos/ibc-go/v10/modules/core/api" + ibcerrors "github.com/cosmos/ibc-go/v10/modules/core/errors" +) + +var _ api.IBCModule = (*IBCModule)(nil) + +// IBCModule implements the ICS26 interface for transfer given the transfer keeper. +type IBCModule struct { + keeper *keeper.Keeper +} + +// NewIBCModule creates a new IBCModule given the keeper +func NewIBCModule(k *keeper.Keeper) *IBCModule { + return &IBCModule{ + keeper: k, + } +} + +func (*IBCModule) OnSendPacket(ctx sdk.Context, sourceChannel string, destinationChannel string, sequence uint64, payload channeltypesv2.Payload, signer sdk.AccAddress) error { + if payload.SourcePort != types.PortID || payload.DestinationPort != types.PortID { + return errorsmod.Wrapf(channeltypesv2.ErrInvalidPacket, "payload port ID is invalid: expected %s, got sourcePort: %s destPort: %s", types.PortID, payload.SourcePort, payload.DestinationPort) + } + if !clienttypes.IsValidClientID(sourceChannel) || !clienttypes.IsValidClientID(destinationChannel) { + return errorsmod.Wrapf(channeltypesv2.ErrInvalidPacket, "client IDs must be in valid format: {string}-{number}") + } + + data, err := types.UnmarshalPacketData(payload.Value, payload.Version, payload.Encoding) + if err != nil { + return err + } + + if err := data.ValidateBasic(); err != nil { + return errorsmod.Wrapf(err, "failed to validate %s packet data", types.Version) + } + + sender, err := sdk.AccAddressFromBech32(data.Sender) + if err != nil { + return err + } + + if !signer.Equals(sender) { + return errorsmod.Wrapf(ibcerrors.ErrUnauthorized, "sender %s is different from signer %s", sender, signer) + } + + // TODO: emit event and telemetry + + return nil +} + +func (im *IBCModule) OnRecvPacket(ctx sdk.Context, sourceChannel, destinationChannel string, sequence uint64, payload channeltypesv2.Payload, relayer sdk.AccAddress) channeltypesv2.RecvPacketResult { + if payload.SourcePort != types.PortID || payload.DestinationPort != types.PortID { + return channeltypesv2.RecvPacketResult{ + Status: channeltypesv2.PacketStatus_Failure, + } + } + if payload.Version != types.Version { + return channeltypesv2.RecvPacketResult{ + Status: channeltypesv2.PacketStatus_Failure, + } + } + + packetData, ackErr := types.UnmarshalPacketData(payload.Value, payload.Version, payload.Encoding) + if ackErr != nil { + im.keeper.Logger(ctx).Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), sequence)) + return channeltypesv2.RecvPacketResult{ + Status: channeltypesv2.PacketStatus_Failure, + } + } + + if ackErr := packetData.ValidateBasic(); ackErr != nil { + im.keeper.Logger(ctx).Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), sequence)) + return channeltypesv2.RecvPacketResult{ + Status: channeltypesv2.PacketStatus_Failure, + } + } + + result, ackErr := im.keeper.OnRecvPacket( + ctx, + packetData, + payload.SourcePort, + sourceChannel, + payload.DestinationPort, + destinationChannel, + ) + if ackErr != nil { + im.keeper.Logger(ctx).Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), sequence)) + return channeltypesv2.RecvPacketResult{ + Status: channeltypesv2.PacketStatus_Failure, + } + } + + ack := types.NewAcknowledgement(result) + ackBz, ackErr := types.MarshalAcknowledgement(&ack, types.Version, payload.Encoding) + if ackErr != nil { + im.keeper.Logger(ctx).Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), sequence)) + return channeltypesv2.RecvPacketResult{ + Status: channeltypesv2.PacketStatus_Failure, + } + } + + im.keeper.Logger(ctx).Info("successfully handled ICS-27 GMP packet", "sequence", sequence) + + // TODO: implement telemetry + + return channeltypesv2.RecvPacketResult{ + Status: channeltypesv2.PacketStatus_Success, + Acknowledgement: ackBz, + } +} + +func (*IBCModule) OnTimeoutPacket(_ sdk.Context, _, _ string, _ uint64, _ channeltypesv2.Payload, _ sdk.AccAddress) error { + return nil +} + +func (*IBCModule) OnAcknowledgementPacket(_ sdk.Context, _, _ string, _ uint64, _ []byte, _ channeltypesv2.Payload, _ sdk.AccAddress) error { + return nil +} diff --git a/modules/apps/27-gmp/keeper/account.go b/modules/apps/27-gmp/keeper/account.go new file mode 100644 index 00000000000..f8d497fd594 --- /dev/null +++ b/modules/apps/27-gmp/keeper/account.go @@ -0,0 +1,66 @@ +package keeper + +import ( + "context" + + "cosmossdk.io/collections" + errorsmod "cosmossdk.io/errors" + + "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types" +) + +// getOrCreateICS27Account retrieves an existing ICS27 account or creates a new one if it doesn't exist. +func (k *Keeper) getOrCreateICS27Account(ctx context.Context, accountID *types.AccountIdentifier) (*types.ICS27Account, error) { + existingIcs27Account, err := k.Accounts.Get(ctx, collections.Join3(accountID.ClientId, accountID.Sender, accountID.Salt)) + if err == nil { + return &existingIcs27Account, nil + } else if !errorsmod.IsOf(err, collections.ErrNotFound) { + return nil, err + } + + // Create a new account + newAddr, err := types.BuildAddressPredictable(accountID) + if err != nil { + return nil, err + } + + existingAcc := k.accountKeeper.GetAccount(ctx, newAddr) + if existingAcc != nil { + // TODO: ensure this cannot be abused (refactor after this is resolved) + ics27Account := types.NewICS27Account(existingAcc.GetAddress().String(), accountID) + if err := k.Accounts.Set(ctx, collections.Join3(accountID.ClientId, accountID.Sender, accountID.Salt), ics27Account); err != nil { + return nil, errorsmod.Wrapf(err, "failed to set account %s in store", ics27Account) + } + + return &ics27Account, nil + } + + newAcc := k.accountKeeper.NewAccountWithAddress(ctx, newAddr) + k.accountKeeper.SetAccount(ctx, newAcc) + + ics27Account := types.NewICS27Account(newAcc.GetAddress().String(), accountID) + if err := k.Accounts.Set(ctx, collections.Join3(accountID.ClientId, accountID.Sender, accountID.Salt), ics27Account); err != nil { + return nil, errorsmod.Wrapf(err, "failed to set account %s in store", ics27Account) + } + + k.Logger(ctx).Info("Created new ICS27 account", "account", ics27Account) + return &ics27Account, nil +} + +// getOrComputeICS27Adderss retrieves an existing ICS27 account address or computes it if it doesn't exist. This doesn't modify the store. +func (k *Keeper) getOrComputeICS27Address(ctx context.Context, accountID *types.AccountIdentifier) (string, error) { + existingIcs27Account, err := k.Accounts.Get(ctx, collections.Join3(accountID.ClientId, accountID.Sender, accountID.Salt)) + if err == nil { + return existingIcs27Account.Address, nil + } else if !errorsmod.IsOf(err, collections.ErrNotFound) { + return "", err + } + + // Compute a new address + newAddr, err := types.BuildAddressPredictable(accountID) + if err != nil { + return "", err + } + + return newAddr.String(), nil +} diff --git a/modules/apps/27-gmp/keeper/genesis.go b/modules/apps/27-gmp/keeper/genesis.go new file mode 100644 index 00000000000..c45447f4ca3 --- /dev/null +++ b/modules/apps/27-gmp/keeper/genesis.go @@ -0,0 +1,53 @@ +package keeper + +import ( + "context" + + "cosmossdk.io/collections" + errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types" + ibcerrors "github.com/cosmos/ibc-go/v10/modules/core/errors" +) + +// InitGenesis initializes the module state from a genesis state. +func (k *Keeper) InitGenesis(ctx context.Context, data *types.GenesisState) error { + for _, account := range data.Ics27Accounts { + if _, err := sdk.AccAddressFromBech32(account.AccountAddress); err != nil { + return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) + } + if _, err := sdk.AccAddressFromBech32(account.AccountId.Sender); err != nil { + return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) + } + + if err := k.Accounts.Set(ctx, collections.Join3(account.AccountId.ClientId, account.AccountId.Sender, account.AccountId.Salt), types.ICS27Account{ + Address: account.AccountAddress, + AccountId: &account.AccountId, + }); err != nil { + return err + } + } + + return nil +} + +// ExportGenesis exports the module state to a genesis state. +func (k *Keeper) ExportGenesis(ctx context.Context) (*types.GenesisState, error) { + var accounts []types.RegisteredICS27Account + if err := k.Accounts.Walk(ctx, nil, func(key collections.Triple[string, string, []byte], value types.ICS27Account) (bool, error) { + accounts = append(accounts, types.RegisteredICS27Account{ + AccountAddress: value.Address, + AccountId: *value.AccountId, + }) + + return false, nil + }); err != nil { + return nil, err + } + + return &types.GenesisState{ + Ics27Accounts: accounts, + }, nil +} diff --git a/modules/apps/27-gmp/keeper/keeper.go b/modules/apps/27-gmp/keeper/keeper.go new file mode 100644 index 00000000000..ab8e5f4fe5e --- /dev/null +++ b/modules/apps/27-gmp/keeper/keeper.go @@ -0,0 +1,74 @@ +package keeper + +import ( + "context" + "errors" + "strings" + + "cosmossdk.io/collections" + storetypes "cosmossdk.io/core/store" + "cosmossdk.io/log" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types" + "github.com/cosmos/ibc-go/v10/modules/core/exported" +) + +// Keeper defines the IBC fungible transfer keeper +type Keeper struct { + cdc codec.Codec + + msgRouter types.MessageRouter + + accountKeeper types.AccountKeeper + + // the address capable of executing a MsgUpdateParams message. Typically, this + // should be the x/gov module account. + authority string + + // state management + Schema collections.Schema + // Accounts is a map of (ClientID, Sender, Salt) to ICS27Account + Accounts collections.Map[collections.Triple[string, string, []byte], types.ICS27Account] +} + +// NewKeeper creates a new Keeper instance +func NewKeeper( + cdc codec.Codec, storeService storetypes.KVStoreService, + accountKeeper types.AccountKeeper, msgRouter types.MessageRouter, + authority string, +) *Keeper { + if strings.TrimSpace(authority) == "" { + panic(errors.New("authority must be non-empty")) + } + + sb := collections.NewSchemaBuilder(storeService) + k := Keeper{ + cdc: cdc, + msgRouter: msgRouter, + accountKeeper: accountKeeper, + authority: authority, + Accounts: collections.NewMap(sb, types.AccountsKey, "accounts", collections.TripleKeyCodec(collections.StringKey, collections.StringKey, collections.BytesKey), codec.CollValue[types.ICS27Account](cdc)), + } + + schema, err := sb.Build() + if err != nil { + panic(err) + } + + k.Schema = schema + + return &k +} + +// GetAuthority returns the module's authority. +func (k *Keeper) GetAuthority() string { + return k.authority +} + +// Logger returns a module-specific logger. +func (*Keeper) Logger(goCtx context.Context) log.Logger { + return sdk.UnwrapSDKContext(goCtx).Logger().With("module", "x/"+exported.ModuleName+"-"+types.ModuleName) +} diff --git a/modules/apps/27-gmp/keeper/msg_server.go b/modules/apps/27-gmp/keeper/msg_server.go new file mode 100644 index 00000000000..6972140e06e --- /dev/null +++ b/modules/apps/27-gmp/keeper/msg_server.go @@ -0,0 +1,83 @@ +package keeper + +import ( + "context" + + "github.com/cosmos/gogoproto/proto" + + errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types" + channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types" + ibcerrors "github.com/cosmos/ibc-go/v10/modules/core/errors" +) + +var _ types.MsgServer = (*Keeper)(nil) + +// SendCall defines the handler for the MsgSendCall message. +func (k *Keeper) SendCall(goCtx context.Context, msg *types.MsgSendCall) (*types.MsgSendCallResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + _, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return nil, err + } + + packetData := types.NewGMPPacketData(msg.Sender, msg.Receiver, msg.Salt, msg.Payload, msg.Memo) + if err := packetData.ValidateBasic(); err != nil { + return nil, errorsmod.Wrapf(err, "failed to validate %s packet data", types.Version) + } + + sequence, err := k.sendPacket(ctx, msg.Encoding, msg.SourceClient, msg.TimeoutTimestamp, packetData) + if err != nil { + return nil, err + } + + k.Logger(ctx).Info("IBC send GMP packet", "sender", msg.Sender, "receiver", msg.Receiver) + + return &types.MsgSendCallResponse{Sequence: sequence}, nil +} + +func (k *Keeper) sendPacket(ctx sdk.Context, encoding, sourceClient string, timeoutTimestamp uint64, packetData types.GMPPacketData) (uint64, error) { + if encoding == "" { + encoding = types.EncodingABI + } + + data, err := types.MarshalPacketData(&packetData, types.Version, encoding) + if err != nil { + return 0, err + } + + payload := channeltypesv2.NewPayload(types.PortID, types.PortID, types.Version, encoding, data) + msg := channeltypesv2.NewMsgSendPacket( + sourceClient, timeoutTimestamp, + packetData.Sender, payload, + ) + + handler := k.msgRouter.Handler(msg) + if handler == nil { + return 0, errorsmod.Wrapf(ibcerrors.ErrInvalidRequest, "unrecognized packet type: %T", msg) + } + res, err := handler(ctx, msg) + if err != nil { + return 0, err + } + + // NOTE: The sdk msg handler creates a new EventManager, so events must be correctly propagated back to the current context + ctx.EventManager().EmitEvents(res.GetEvents()) + + // Each individual sdk.Result has exactly one Msg response. We aggregate here. + msgResponse := res.MsgResponses[0] + if msgResponse == nil { + return 0, errorsmod.Wrapf(ibcerrors.ErrLogic, "got nil Msg response for msg %s", sdk.MsgTypeURL(msg)) + } + var sendResponse channeltypesv2.MsgSendPacketResponse + err = proto.Unmarshal(msgResponse.Value, &sendResponse) + if err != nil { + return 0, err + } + + return sendResponse.Sequence, nil +} diff --git a/modules/apps/27-gmp/keeper/query_server.go b/modules/apps/27-gmp/keeper/query_server.go new file mode 100644 index 00000000000..6ff2fac084b --- /dev/null +++ b/modules/apps/27-gmp/keeper/query_server.go @@ -0,0 +1,28 @@ +package keeper + +import ( + "context" + "encoding/hex" + + "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types" +) + +var _ types.QueryServer = (*Keeper)(nil) + +// AccountAddress defines the handler for the Query/AccountAddress RPC method. +func (k *Keeper) AccountAddress(ctx context.Context, req *types.QueryAccountAddressRequest) (*types.QueryAccountAddressResponse, error) { + salt, err := hex.DecodeString(req.Salt) + if err != nil { + return nil, err + } + + accountID := types.NewAccountIdentifier(req.ClientId, req.Sender, salt) + address, err := k.getOrComputeICS27Address(ctx, &accountID) + if err != nil { + return nil, err + } + + return &types.QueryAccountAddressResponse{ + AccountAddress: address, + }, nil +} diff --git a/modules/apps/27-gmp/keeper/relay.go b/modules/apps/27-gmp/keeper/relay.go new file mode 100644 index 00000000000..91a605cbb1b --- /dev/null +++ b/modules/apps/27-gmp/keeper/relay.go @@ -0,0 +1,152 @@ +package keeper + +import ( + "bytes" + + "github.com/cosmos/gogoproto/proto" + + errorsmod "cosmossdk.io/errors" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types" + ibcerrors "github.com/cosmos/ibc-go/v10/modules/core/errors" +) + +// OnRecvPacket processes a GMP packet. +// Returns the data result of the execution if successful. +func (k *Keeper) OnRecvPacket( + ctx sdk.Context, + data *types.GMPPacketData, + sourcePort, + sourceClient, + destPort, + destClient string, +) ([]byte, error) { + accountID := types.NewAccountIdentifier(destClient, data.Sender, data.Salt) + + ics27Acc, err := k.getOrCreateICS27Account(ctx, &accountID) + if err != nil { + return nil, err + } + + ics27Addr, err := sdk.AccAddressFromBech32(ics27Acc.Address) + if err != nil { + return nil, err + } + + ics27SdkAcc := k.accountKeeper.GetAccount(ctx, ics27Addr) + if ics27SdkAcc == nil { + return nil, errorsmod.Wrapf(types.ErrAccountNotFound, "account %s not found", ics27Addr) + } + + txResponse, err := k.executeTx(ctx, ics27SdkAcc, data.Payload) + if err != nil { + return nil, errorsmod.Wrapf(err, "failed to execute ICS27 account transaction") + } + + return txResponse, nil +} + +// executeTx attempts to execute the provided transaction. It begins by authenticating the transaction signer. +// If authentication succeeds, it does basic validation of the messages before attempting to deliver each message +// into state. The state changes will only be committed if all messages in the transaction succeed. Thus the +// execution of the transaction is atomic, all state changes are reverted if a single message fails. +func (k *Keeper) executeTx(ctx sdk.Context, account sdk.AccountI, payload []byte) ([]byte, error) { + msgs, err := types.DeserializeCosmosTx(k.cdc, payload) + if err != nil { + return nil, errorsmod.Wrapf(err, "failed to deserialize ICS27 CosmosTx") + } + + if err := k.authenticateTx(ctx, account, msgs); err != nil { + return nil, err + } + + txMsgData := &sdk.TxMsgData{ + MsgResponses: make([]*codectypes.Any, len(msgs)), + } + + // CacheContext returns a new context with the multi-store branched into a cached storage object + // writeCache is called only if all msgs succeed, performing state transitions atomically + cacheCtx, writeCache := ctx.CacheContext() + for i, msg := range msgs { + if m, ok := msg.(sdk.HasValidateBasic); ok { + if err := m.ValidateBasic(); err != nil { + return nil, err + } + } + + protoAny, err := k.executeMsg(cacheCtx, msg) + if err != nil { + ctx.Logger().Error("failed to execute 27-gmp message", "msg", msg, "error", err) + return nil, err + } + + txMsgData.MsgResponses[i] = protoAny + } + + writeCache() + + ctx.Logger().Info("executed 27-gmp transaction", "account", account.GetAddress(), "msgs", msgs) + + txResponse, err := proto.Marshal(txMsgData) + if err != nil { + return nil, errorsmod.Wrap(err, "failed to marshal tx data") + } + + return txResponse, nil +} + +// authenticateTx checks that the transaction is signed by the expected signer. +func (k *Keeper) authenticateTx(_ sdk.Context, account sdk.AccountI, msgs []sdk.Msg) error { + if len(msgs) == 0 { + return errorsmod.Wrapf(types.ErrInvalidPayload, "empty message list") + } + + accountAddr := account.GetAddress() + for _, msg := range msgs { + // obtain the message signers using the proto signer annotations + // the msgv2 return value is discarded as it is not used + signers, _, err := k.cdc.GetMsgV1Signers(msg) + if err != nil { + return errorsmod.Wrapf(err, "failed to obtain message signers for message type %s", sdk.MsgTypeURL(msg)) + } + + for _, signer := range signers { + // the interchain account address is stored as the string value of the sdk.AccAddress type + // thus we must cast the signer to a sdk.AccAddress to obtain the comparison value + // the stored interchain account address must match the signer for every message to be executed + if !bytes.Equal(signer, accountAddr.Bytes()) { + return errorsmod.Wrapf(ibcerrors.ErrUnauthorized, "unexpected signer address: expected %s, got %s", accountAddr, sdk.AccAddress(signer)) + } + } + } + + return nil +} + +// Attempts to get the message handler from the router and if found will then execute the message. +// If the message execution is successful, the proto marshaled message response will be returned. +func (k *Keeper) executeMsg(ctx sdk.Context, msg sdk.Msg) (*codectypes.Any, error) { + handler := k.msgRouter.Handler(msg) + if handler == nil { + return nil, types.ErrInvalidMsgRoute + } + + res, err := handler(ctx, msg) + if err != nil { + return nil, err + } + + // NOTE: The sdk msg handler creates a new EventManager, so events must be correctly propagated back to the current context + ctx.EventManager().EmitEvents(res.GetEvents()) + + // Each individual sdk.Result has exactly one Msg response. We aggregate here. + msgResponse := res.MsgResponses[0] + if msgResponse == nil { + return nil, errorsmod.Wrapf(ibcerrors.ErrLogic, "got nil Msg response for msg %s", sdk.MsgTypeURL(msg)) + } + + return msgResponse, nil +} diff --git a/modules/apps/27-gmp/module.go b/modules/apps/27-gmp/module.go new file mode 100644 index 00000000000..bdcc60a7ef2 --- /dev/null +++ b/modules/apps/27-gmp/module.go @@ -0,0 +1,149 @@ +package gmp + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/grpc-ecosystem/grpc-gateway/runtime" + + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" + "cosmossdk.io/core/appmodule" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + + "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/keeper" + "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types" +) + +var ( + _ module.AppModule = (*AppModule)(nil) + _ module.AppModuleBasic = (*AppModule)(nil) + // _ module.AppModuleSimulation = (*AppModule)(nil) + _ module.HasGenesis = (*AppModule)(nil) + _ module.HasName = (*AppModule)(nil) + _ module.HasConsensusVersion = (*AppModule)(nil) + _ module.HasServices = (*AppModule)(nil) + // _ module.HasProposalMsgs = (*AppModule)(nil) + _ appmodule.AppModule = (*AppModule)(nil) +) + +// AppModule represents the AppModule for this module +type AppModule struct { + keeper *keeper.Keeper +} + +// NewAppModule creates a new 27-gmp module +func NewAppModule(k *keeper.Keeper) AppModule { + return AppModule{ + keeper: k, + } +} + +func NewAppModuleBasic(m AppModule) module.AppModuleBasic { + return module.CoreAppModuleBasicAdaptor(m.Name(), m) +} + +// Name implements AppModuleBasic interface +func (AppModule) Name() string { return types.ModuleName } + +// IsOnePerModuleType implements the depinject.OnePerModuleType interface. +func (AppModule) IsOnePerModuleType() {} + +// IsAppModule implements the appmodule.AppModule interface. +func (AppModule) IsAppModule() {} + +// RegisterLegacyAminoCodec implements AppModuleBasic interface +func (AppModule) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the ics27 module. +func (AppModule) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + if err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)); err != nil { + panic(err) + } +} + +// RegisterInterfaces registers module concrete types into protobuf Any. +func (AppModule) RegisterInterfaces(registry codectypes.InterfaceRegistry) { + types.RegisterInterfaces(registry) +} + +// ConsensusVersion implements AppModule/ConsensusVersion defining the current version of transfer. +func (AppModule) ConsensusVersion() uint64 { return 1 } + +// DefaultGenesis returns default genesis state as raw bytes for the ibc +// transfer module. +func (AppModule) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesisState()) +} + +// RegisterServices registers module services. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), am.keeper) + types.RegisterQueryServer(cfg.QueryServer(), am.keeper) +} + +// ValidateGenesis performs genesis state validation for the ibc transfer module. +func (AppModule) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { + var gs types.GenesisState + if err := cdc.UnmarshalJSON(bz, &gs); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + } + + return gs.Validate() +} + +// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface. +func (AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { + return types.AutoCLIOptions() +} + +// InitGenesis performs genesis initialization for the ibc-transfer module. It returns +// no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) { + var genesisState types.GenesisState + cdc.MustUnmarshalJSON(data, &genesisState) + err := am.keeper.InitGenesis(ctx, &genesisState) + if err != nil { + panic(fmt.Errorf("failed to initialize %s genesis state: %w", types.ModuleName, err)) + } +} + +// ExportGenesis returns the exported genesis state as raw bytes for the ibc-transfer +// module. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + gs, err := am.keeper.ExportGenesis(ctx) + if err != nil { + panic(fmt.Errorf("failed to export %s genesis state: %w", types.ModuleName, err)) + } + + return cdc.MustMarshalJSON(gs) +} + +/* +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of the transfer module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + simulation.RandomizedGenState(simState) +} + +// ProposalMsgs returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { + return simulation.ProposalMsgs() +} + +// RegisterStoreDecoder registers a decoder for transfer module's types +func (AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { + sdr[types.StoreKey] = simulation.NewDecodeStore() +} + +// WeightedOperations returns the all the transfer module operations with their respective weights. +func (AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { + return nil +} +*/ diff --git a/modules/apps/27-gmp/types/account.go b/modules/apps/27-gmp/types/account.go new file mode 100644 index 00000000000..1c4c2aff55c --- /dev/null +++ b/modules/apps/27-gmp/types/account.go @@ -0,0 +1,126 @@ +package types + +import ( + "strings" + + "github.com/cosmos/gogoproto/proto" + + errorsmod "cosmossdk.io/errors" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + + host "github.com/cosmos/ibc-go/v10/modules/core/24-host" + ibcerrors "github.com/cosmos/ibc-go/v10/modules/core/errors" +) + +// NewAccountIdentifier creates a new AccountIdentifier with the given clientId, sender, and salt. +func NewAccountIdentifier(clientID, sender string, salt []byte) AccountIdentifier { + return AccountIdentifier{ + ClientId: clientID, + Sender: sender, + Salt: salt, + } +} + +// NewICS27Account creates a new ICS27Account with the given address and accountId. +func NewICS27Account(addr string, accountID *AccountIdentifier) ICS27Account { + return ICS27Account{ + Address: addr, + AccountId: accountID, + } +} + +// BuildAddressPredictable generates an account address for the gmp module with len = types.AccountAddrLen using the +// Cosmos SDK address.Module function. +// Internally a key is built containing: +// (len(clientId) | clientId | len(sender) | sender | len(salt) | salt). +// +// All method parameter values must be valid and not nil. +// +// This function was copied from wasmd and modified. +// +func BuildAddressPredictable(accountID *AccountIdentifier) (sdk.AccAddress, error) { + if err := host.ClientIdentifierValidator(accountID.ClientId); err != nil { + return nil, errorsmod.Wrapf(err, "invalid client ID %s", accountID.ClientId) + } + if strings.TrimSpace(accountID.Sender) == "" { + return nil, errorsmod.Wrap(ibcerrors.ErrInvalidAddress, "missing sender address") + } + + clientIDBz := uint64LengthPrefix([]byte(accountID.ClientId)) + senderBz := uint64LengthPrefix([]byte(accountID.Sender)) + saltBz := uint64LengthPrefix(accountID.Salt) + key := make([]byte, len(clientIDBz)+len(senderBz)+len(saltBz)) + copy(key[0:], clientIDBz) + copy(key[len(clientIDBz):], senderBz) + copy(key[len(clientIDBz)+len(senderBz):], saltBz) + return address.Module(accountsKey, key)[:AccountAddrLen], nil +} + +// uint64LengthPrefix prepend big endian encoded byte length +func uint64LengthPrefix(bz []byte) []byte { + return append(sdk.Uint64ToBigEndian(uint64(len(bz))), bz...) +} + +// DeserializeCosmosTx unmarshals and unpacks a slice of transaction bytes into a slice of sdk.Msg's. +// The transaction bytes are unmarshaled depending on the encoding type passed in. The sdk.Msg's are +// unpacked from Any's and returned. +func DeserializeCosmosTx(cdc codec.Codec, data []byte) ([]sdk.Msg, error) { + // this is a defensive check to ensure only the ProtoCodec is used for message deserialization + if _, ok := cdc.(*codec.ProtoCodec); !ok { + return nil, errorsmod.Wrap(ErrInvalidCodec, "only the ProtoCodec may be used for receiving messages on the host chain") + } + + var cosmosTx CosmosTx + err := cdc.Unmarshal(data, &cosmosTx) + if err != nil { + // TODO: clean up after the demo + if err := cdc.UnmarshalJSON(data, &cosmosTx); err != nil { + return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "cannot unmarshal CosmosTx with protobuf or protojson: %v", err) + } + } + + msgs := make([]sdk.Msg, len(cosmosTx.Messages)) + + for i, protoAny := range cosmosTx.Messages { + var msg sdk.Msg + err := cdc.UnpackAny(protoAny, &msg) + if err != nil { + return nil, err + } + msgs[i] = msg + } + + return msgs, nil +} + +// SerializeCosmosTx serializes a slice of sdk.Msg's using the CosmosTx type. The sdk.Msg's are +// packed into Any's and inserted into the Messages field of a CosmosTx. The CosmosTx is marshaled +// depending on the encoding type passed in. The marshaled bytes are returned. +func SerializeCosmosTx(cdc codec.BinaryCodec, msgs []proto.Message) ([]byte, error) { + var ( + bz []byte + err error + ) + msgAnys := make([]*codectypes.Any, len(msgs)) + for i, msg := range msgs { + msgAnys[i], err = codectypes.NewAnyWithValue(msg) + if err != nil { + return nil, err + } + } + + cosmosTx := &CosmosTx{ + Messages: msgAnys, + } + + bz, err = cdc.Marshal(cosmosTx) + if err != nil { + return nil, errorsmod.Wrapf(err, "cannot marshal CosmosTx with protobuf") + } + + return bz, nil +} diff --git a/modules/apps/27-gmp/types/account.pb.go b/modules/apps/27-gmp/types/account.pb.go new file mode 100644 index 00000000000..22288175f99 --- /dev/null +++ b/modules/apps/27-gmp/types/account.pb.go @@ -0,0 +1,853 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: ibc/applications/gmp/v1/account.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + types "github.com/cosmos/cosmos-sdk/codec/types" + proto "github.com/cosmos/gogoproto/proto" + 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 + +// AccountIdentifier is used to identify a ICS27 account. +type AccountIdentifier struct { + // The (local) client identifier + ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + // The sender of the packet + Sender string `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` + // The salt of the packet + Salt []byte `protobuf:"bytes,3,opt,name=salt,proto3" json:"salt,omitempty"` +} + +func (m *AccountIdentifier) Reset() { *m = AccountIdentifier{} } +func (m *AccountIdentifier) String() string { return proto.CompactTextString(m) } +func (*AccountIdentifier) ProtoMessage() {} +func (*AccountIdentifier) Descriptor() ([]byte, []int) { + return fileDescriptor_5d5b886ccdedc1db, []int{0} +} +func (m *AccountIdentifier) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AccountIdentifier) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AccountIdentifier.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 *AccountIdentifier) XXX_Merge(src proto.Message) { + xxx_messageInfo_AccountIdentifier.Merge(m, src) +} +func (m *AccountIdentifier) XXX_Size() int { + return m.Size() +} +func (m *AccountIdentifier) XXX_DiscardUnknown() { + xxx_messageInfo_AccountIdentifier.DiscardUnknown(m) +} + +var xxx_messageInfo_AccountIdentifier proto.InternalMessageInfo + +func (m *AccountIdentifier) GetClientId() string { + if m != nil { + return m.ClientId + } + return "" +} + +func (m *AccountIdentifier) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *AccountIdentifier) GetSalt() []byte { + if m != nil { + return m.Salt + } + return nil +} + +// An ICS27Account is defined as a BaseAccount & the account identifier +type ICS27Account struct { + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + AccountId *AccountIdentifier `protobuf:"bytes,2,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"` +} + +func (m *ICS27Account) Reset() { *m = ICS27Account{} } +func (m *ICS27Account) String() string { return proto.CompactTextString(m) } +func (*ICS27Account) ProtoMessage() {} +func (*ICS27Account) Descriptor() ([]byte, []int) { + return fileDescriptor_5d5b886ccdedc1db, []int{1} +} +func (m *ICS27Account) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ICS27Account) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ICS27Account.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 *ICS27Account) XXX_Merge(src proto.Message) { + xxx_messageInfo_ICS27Account.Merge(m, src) +} +func (m *ICS27Account) XXX_Size() int { + return m.Size() +} +func (m *ICS27Account) XXX_DiscardUnknown() { + xxx_messageInfo_ICS27Account.DiscardUnknown(m) +} + +var xxx_messageInfo_ICS27Account proto.InternalMessageInfo + +func (m *ICS27Account) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *ICS27Account) GetAccountId() *AccountIdentifier { + if m != nil { + return m.AccountId + } + return nil +} + +// CosmosTx contains a list of sdk.Msg's. It should be used when sending transactions to an SDK host chain. +type CosmosTx struct { + Messages []*types.Any `protobuf:"bytes,1,rep,name=messages,proto3" json:"messages,omitempty"` +} + +func (m *CosmosTx) Reset() { *m = CosmosTx{} } +func (m *CosmosTx) String() string { return proto.CompactTextString(m) } +func (*CosmosTx) ProtoMessage() {} +func (*CosmosTx) Descriptor() ([]byte, []int) { + return fileDescriptor_5d5b886ccdedc1db, []int{2} +} +func (m *CosmosTx) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CosmosTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CosmosTx.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 *CosmosTx) XXX_Merge(src proto.Message) { + xxx_messageInfo_CosmosTx.Merge(m, src) +} +func (m *CosmosTx) XXX_Size() int { + return m.Size() +} +func (m *CosmosTx) XXX_DiscardUnknown() { + xxx_messageInfo_CosmosTx.DiscardUnknown(m) +} + +var xxx_messageInfo_CosmosTx proto.InternalMessageInfo + +func (m *CosmosTx) GetMessages() []*types.Any { + if m != nil { + return m.Messages + } + return nil +} + +func init() { + proto.RegisterType((*AccountIdentifier)(nil), "ibc.applications.gmp.v1.AccountIdentifier") + proto.RegisterType((*ICS27Account)(nil), "ibc.applications.gmp.v1.ICS27Account") + proto.RegisterType((*CosmosTx)(nil), "ibc.applications.gmp.v1.CosmosTx") +} + +func init() { + proto.RegisterFile("ibc/applications/gmp/v1/account.proto", fileDescriptor_5d5b886ccdedc1db) +} + +var fileDescriptor_5d5b886ccdedc1db = []byte{ + // 370 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x51, 0x41, 0x8b, 0xda, 0x40, + 0x18, 0x35, 0xb5, 0x58, 0x1d, 0xbd, 0x74, 0x90, 0x36, 0x5a, 0x08, 0x22, 0x14, 0xa4, 0xe0, 0x8c, + 0xa6, 0x50, 0x2f, 0xbd, 0xa8, 0xa7, 0xdc, 0x4a, 0xec, 0xa9, 0x14, 0x64, 0x32, 0x19, 0x67, 0x07, + 0x92, 0x99, 0x90, 0x99, 0xc8, 0xfa, 0x23, 0x16, 0xf6, 0xc7, 0xec, 0x8f, 0xd8, 0xa3, 0xec, 0x69, + 0x8f, 0x8b, 0xfe, 0x91, 0x25, 0x99, 0xb8, 0x2c, 0x2c, 0x7b, 0xcb, 0xfb, 0xde, 0xcb, 0xf7, 0xde, + 0xbc, 0x0f, 0x7c, 0x17, 0x11, 0xc5, 0x24, 0xcb, 0x12, 0x41, 0x89, 0x11, 0x4a, 0x6a, 0xcc, 0xd3, + 0x0c, 0xef, 0xe7, 0x98, 0x50, 0xaa, 0x0a, 0x69, 0x50, 0x96, 0x2b, 0xa3, 0xe0, 0x57, 0x11, 0x51, + 0xf4, 0x5a, 0x86, 0x78, 0x9a, 0xa1, 0xfd, 0x7c, 0x38, 0xe0, 0x4a, 0xf1, 0x84, 0xe1, 0x4a, 0x16, + 0x15, 0x3b, 0x4c, 0xe4, 0xc1, 0xfe, 0x33, 0x1c, 0x50, 0xa5, 0x53, 0xa5, 0xb7, 0x15, 0xc2, 0x16, + 0x58, 0x6a, 0xfc, 0x1f, 0x7c, 0x5e, 0xda, 0xfd, 0x41, 0xcc, 0xa4, 0x11, 0x3b, 0xc1, 0x72, 0xf8, + 0x0d, 0x74, 0x68, 0x22, 0x98, 0x34, 0x5b, 0x11, 0xbb, 0xce, 0xc8, 0x99, 0x74, 0xc2, 0xb6, 0x1d, + 0x04, 0x31, 0xfc, 0x02, 0x5a, 0x9a, 0xc9, 0x98, 0xe5, 0xee, 0x87, 0x8a, 0xa9, 0x11, 0x84, 0xe0, + 0xa3, 0x26, 0x89, 0x71, 0x9b, 0x23, 0x67, 0xd2, 0x0b, 0xab, 0xef, 0xf1, 0x8d, 0x03, 0x7a, 0xc1, + 0x7a, 0xe3, 0x2f, 0x6a, 0x0f, 0xe8, 0x83, 0x4f, 0x24, 0x8e, 0x73, 0xa6, 0xb5, 0xdd, 0xbb, 0x72, + 0x1f, 0xee, 0xa6, 0xfd, 0x3a, 0xd1, 0xd2, 0x32, 0x1b, 0x93, 0x0b, 0xc9, 0xc3, 0x8b, 0x10, 0x06, + 0x00, 0xd4, 0x15, 0x94, 0x71, 0x4a, 0xd3, 0xae, 0xff, 0x03, 0xbd, 0x53, 0x03, 0x7a, 0xf3, 0x9a, + 0xb0, 0x43, 0x2e, 0xa3, 0xf1, 0x6f, 0xd0, 0x5e, 0x57, 0x5e, 0x7f, 0xaf, 0xe1, 0x0c, 0xb4, 0x53, + 0xa6, 0x35, 0xe1, 0xac, 0xcc, 0xd2, 0x9c, 0x74, 0xfd, 0x3e, 0xb2, 0x15, 0xa2, 0x4b, 0x85, 0x68, + 0x29, 0x0f, 0xe1, 0x8b, 0x6a, 0xf5, 0xe7, 0xfe, 0xe4, 0x39, 0xc7, 0x93, 0xe7, 0x3c, 0x9d, 0x3c, + 0xe7, 0xf6, 0xec, 0x35, 0x8e, 0x67, 0xaf, 0xf1, 0x78, 0xf6, 0x1a, 0xff, 0x7e, 0x71, 0x61, 0xae, + 0x8a, 0x08, 0x51, 0x95, 0xd6, 0xf5, 0x62, 0x11, 0xd1, 0x29, 0x57, 0x78, 0x3f, 0x9f, 0xe1, 0x54, + 0xc5, 0x45, 0xc2, 0x74, 0x79, 0x5c, 0x8d, 0xfd, 0xc5, 0xb4, 0xbc, 0xab, 0x39, 0x64, 0x4c, 0x47, + 0xad, 0xca, 0xe9, 0xe7, 0x73, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7c, 0x58, 0xaf, 0x6b, 0xfc, 0x01, + 0x00, 0x00, +} + +func (m *AccountIdentifier) 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 *AccountIdentifier) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AccountIdentifier) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Salt) > 0 { + i -= len(m.Salt) + copy(dAtA[i:], m.Salt) + i = encodeVarintAccount(dAtA, i, uint64(len(m.Salt))) + i-- + dAtA[i] = 0x1a + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintAccount(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x12 + } + if len(m.ClientId) > 0 { + i -= len(m.ClientId) + copy(dAtA[i:], m.ClientId) + i = encodeVarintAccount(dAtA, i, uint64(len(m.ClientId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ICS27Account) 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 *ICS27Account) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ICS27Account) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.AccountId != nil { + { + size, err := m.AccountId.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAccount(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintAccount(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *CosmosTx) 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 *CosmosTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CosmosTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Messages) > 0 { + for iNdEx := len(m.Messages) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Messages[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAccount(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintAccount(dAtA []byte, offset int, v uint64) int { + offset -= sovAccount(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *AccountIdentifier) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ClientId) + if l > 0 { + n += 1 + l + sovAccount(uint64(l)) + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovAccount(uint64(l)) + } + l = len(m.Salt) + if l > 0 { + n += 1 + l + sovAccount(uint64(l)) + } + return n +} + +func (m *ICS27Account) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovAccount(uint64(l)) + } + if m.AccountId != nil { + l = m.AccountId.Size() + n += 1 + l + sovAccount(uint64(l)) + } + return n +} + +func (m *CosmosTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Messages) > 0 { + for _, e := range m.Messages { + l = e.Size() + n += 1 + l + sovAccount(uint64(l)) + } + } + return n +} + +func sovAccount(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozAccount(x uint64) (n int) { + return sovAccount(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *AccountIdentifier) 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 ErrIntOverflowAccount + } + 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: AccountIdentifier: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AccountIdentifier: 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 ErrIntOverflowAccount + } + 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 ErrInvalidLengthAccount + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthAccount + } + 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 Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAccount + } + 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 ErrInvalidLengthAccount + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthAccount + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Salt", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAccount + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthAccount + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthAccount + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Salt = append(m.Salt[:0], dAtA[iNdEx:postIndex]...) + if m.Salt == nil { + m.Salt = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAccount(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAccount + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ICS27Account) 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 ErrIntOverflowAccount + } + 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: ICS27Account: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ICS27Account: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAccount + } + 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 ErrInvalidLengthAccount + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthAccount + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AccountId", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAccount + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAccount + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAccount + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.AccountId == nil { + m.AccountId = &AccountIdentifier{} + } + if err := m.AccountId.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAccount(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAccount + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CosmosTx) 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 ErrIntOverflowAccount + } + 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: CosmosTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CosmosTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Messages", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAccount + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAccount + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAccount + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Messages = append(m.Messages, &types.Any{}) + if err := m.Messages[len(m.Messages)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAccount(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAccount + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipAccount(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, ErrIntOverflowAccount + } + 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, ErrIntOverflowAccount + } + 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, ErrIntOverflowAccount + } + 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, ErrInvalidLengthAccount + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupAccount + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthAccount + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthAccount = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowAccount = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupAccount = fmt.Errorf("proto: unexpected end of group") +) diff --git a/modules/apps/27-gmp/types/ack.go b/modules/apps/27-gmp/types/ack.go new file mode 100644 index 00000000000..6f67c6da196 --- /dev/null +++ b/modules/apps/27-gmp/types/ack.go @@ -0,0 +1,74 @@ +package types + +import ( + "encoding/json" + + "github.com/cosmos/gogoproto/proto" + + errorsmod "cosmossdk.io/errors" + + "github.com/cosmos/cosmos-sdk/codec/unknownproto" + + ibcerrors "github.com/cosmos/ibc-go/v10/modules/core/errors" +) + +// NewAcknowledgement creates a new Acknowledgement +func NewAcknowledgement(result []byte) Acknowledgement { + return Acknowledgement{ + Result: result, + } +} + +// ValidateBasic performs basic validation on the Acknowledgement +func (Acknowledgement) ValidateBasic() error { + return nil +} + +func MarshalAcknowledgement(data *Acknowledgement, ics27Version string, encoding string) ([]byte, error) { + if ics27Version != Version { + panic("unsupported ics27 version") + } + + switch encoding { + case EncodingJSON: + return json.Marshal(data) + case EncodingProtobuf: + return proto.Marshal(data) + case EncodingABI: + return EncodeABIAcknowledgement(data) + default: + return nil, errorsmod.Wrapf(ErrInvalidEncoding, "invalid encoding provided, must be either empty or one of [%q, %q, %q], got %s", EncodingJSON, EncodingProtobuf, EncodingABI, encoding) + } +} + +func UnmarshalAcknowledgement(bz []byte, ics27Version string, encoding string) (*Acknowledgement, error) { + if ics27Version != Version { + panic("unsupported ics27 version") + } + + var data *Acknowledgement + switch encoding { + case EncodingJSON: + if err := json.Unmarshal(bz, &data); err != nil { + return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "failed to unmarshal json packet data: %s", err) + } + case EncodingProtobuf: + if err := unknownproto.RejectUnknownFieldsStrict(bz, data, unknownproto.DefaultAnyResolver{}); err != nil { + return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "failed to unmarshal protobuf packet data: %s", err) + } + + if err := proto.Unmarshal(bz, data); err != nil { + return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "failed to unmarshal protobuf packet data: %s", err) + } + case EncodingABI: + var err error + data, err = DecodeABIAcknowledgement(bz) + if err != nil { + return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "failed to unmarshal ABI packet data: %s", err) + } + default: + return nil, errorsmod.Wrapf(ErrInvalidEncoding, "invalid encoding provided, must be either empty or one of [%q, %q, %q], got %s", EncodingJSON, EncodingProtobuf, EncodingABI, encoding) + } + + return data, nil +} diff --git a/modules/apps/27-gmp/types/autocli.go b/modules/apps/27-gmp/types/autocli.go new file mode 100644 index 00000000000..ddddf306067 --- /dev/null +++ b/modules/apps/27-gmp/types/autocli.go @@ -0,0 +1,46 @@ +package types + +import ( + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" +) + +// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface. +func AutoCLIOptions() *autocliv1.ModuleOptions { + return &autocliv1.ModuleOptions{ + Query: &autocliv1.ServiceCommandDescriptor{ + Service: _Query_serviceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "AccountAddress", + Use: "get-address [client_id] [sender] [salt]", + Short: "Get or pre-compute the address of an ICS27 GMP account", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "client_id"}, + {ProtoField: "sender"}, + {ProtoField: "salt"}, + }, + }, + }, + }, + Tx: &autocliv1.ServiceCommandDescriptor{ + Service: _Msg_serviceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "SendCall", + Use: "send-call [source_client] [sender] [receiver] [salt] [payload] [timeout_timestamp] [memo] [encoding]", + Short: "Send a call to an ICS27 GMP account", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "source_client"}, + {ProtoField: "sender"}, + {ProtoField: "receiver"}, + {ProtoField: "salt"}, + {ProtoField: "payload"}, + {ProtoField: "timeout_timestamp"}, + {ProtoField: "memo"}, + {ProtoField: "encoding", Optional: true}, + }, + }, + }, + }, + } +} diff --git a/modules/apps/27-gmp/types/codec.go b/modules/apps/27-gmp/types/codec.go new file mode 100644 index 00000000000..7ec8fae40ae --- /dev/null +++ b/modules/apps/27-gmp/types/codec.go @@ -0,0 +1,20 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// ModuleCdc references the global gmp module codec. Note, the codec +// should ONLY be used in certain instances of tests and for JSON encoding. +// +// The actual codec used for serialization should be provided to interchain accounts and +// defined at the application level. +var ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) + +// RegisterInterfaces registers the gmp types and the concrete ICS27Account implementation +// against the associated x/auth AccountI and GenesisAccount interfaces. +func RegisterInterfaces(registry codectypes.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.Msg)(nil), &MsgSendCall{}) +} diff --git a/modules/apps/27-gmp/types/errors.go b/modules/apps/27-gmp/types/errors.go new file mode 100644 index 00000000000..af78cee63de --- /dev/null +++ b/modules/apps/27-gmp/types/errors.go @@ -0,0 +1,17 @@ +package types + +import errorsmod "cosmossdk.io/errors" + +var ( + ErrInvalidCodec = errorsmod.Register(ModuleName, 1, "codec is not supported") + ErrInvalidMemo = errorsmod.Register(ModuleName, 2, "invalid memo") + ErrInvalidSalt = errorsmod.Register(ModuleName, 3, "invalid salt") + ErrInvalidPayload = errorsmod.Register(ModuleName, 4, "invalid payload") + ErrInvalidTimeoutTimestamp = errorsmod.Register(ModuleName, 5, "invalid timeout timestamp") + ErrInvalidEncoding = errorsmod.Register(ModuleName, 6, "invalid encoding") + ErrAbiDecoding = errorsmod.Register(ModuleName, 7, "abi decoding error") + ErrAbiEncoding = errorsmod.Register(ModuleName, 8, "abi encoding error") + ErrAccountAlreadyExists = errorsmod.Register(ModuleName, 9, "account already exists") + ErrAccountNotFound = errorsmod.Register(ModuleName, 10, "account not found") + ErrInvalidMsgRoute = errorsmod.Register(ModuleName, 11, "invalid msg route") +) diff --git a/modules/apps/27-gmp/types/expected_keepers.go b/modules/apps/27-gmp/types/expected_keepers.go new file mode 100644 index 00000000000..3b04f77b43c --- /dev/null +++ b/modules/apps/27-gmp/types/expected_keepers.go @@ -0,0 +1,17 @@ +package types + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// AccountKeeper defines a subset of methods implemented by the cosmos-sdk account keeper +type AccountKeeper interface { + // Return a new account with the next account number and the specified address. Does not save the new account to the store. + NewAccountWithAddress(ctx context.Context, addr sdk.AccAddress) sdk.AccountI + // Retrieve an account from the store. + GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI + // Set an account in the store. + SetAccount(ctx context.Context, acc sdk.AccountI) +} diff --git a/modules/apps/27-gmp/types/genesis.go b/modules/apps/27-gmp/types/genesis.go new file mode 100644 index 00000000000..193c6cf4d01 --- /dev/null +++ b/modules/apps/27-gmp/types/genesis.go @@ -0,0 +1,38 @@ +package types + +import ( + errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + + host "github.com/cosmos/ibc-go/v10/modules/core/24-host" + ibcerrors "github.com/cosmos/ibc-go/v10/modules/core/errors" +) + +// DefaultGenesisState returns the default GenesisState. +func DefaultGenesisState() *GenesisState { + return &GenesisState{ + Ics27Accounts: []RegisteredICS27Account{}, + } +} + +// Validate performs basic genesis state validation returning an error upon any +// failure. +func (gs GenesisState) Validate() error { + for _, account := range gs.Ics27Accounts { + if _, err := sdk.AccAddressFromBech32(account.AccountAddress); err != nil { + return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) + } + if _, err := sdk.AccAddressFromBech32(account.AccountId.Sender); err != nil { + return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) + } + if err := host.ClientIdentifierValidator(account.AccountId.ClientId); err != nil { + return errorsmod.Wrapf(err, "invalid source client ID %s", account.AccountId.ClientId) + } + if len(account.AccountId.Salt) > MaximumSaltLength { + return errorsmod.Wrapf(ErrInvalidSalt, "salt must not exceed %d bytes", MaximumSaltLength) + } + } + + return nil +} diff --git a/modules/apps/27-gmp/types/genesis.pb.go b/modules/apps/27-gmp/types/genesis.pb.go new file mode 100644 index 00000000000..0fd1913b2ee --- /dev/null +++ b/modules/apps/27-gmp/types/genesis.pb.go @@ -0,0 +1,566 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: ibc/applications/gmp/v1/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + 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 + +// GenesisState defines the 27-gmp genesis state +type GenesisState struct { + // The list of registered ICS27 accounts + Ics27Accounts []RegisteredICS27Account `protobuf:"bytes,2,rep,name=ics27_accounts,json=ics27Accounts,proto3" json:"ics27_accounts"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_7cccbdb788964d3f, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.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 *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetIcs27Accounts() []RegisteredICS27Account { + if m != nil { + return m.Ics27Accounts + } + return nil +} + +// RegisteredICS27Account contains an account identifier and associated interchain account address +type RegisteredICS27Account struct { + /// The address of the ics27 account + AccountAddress string `protobuf:"bytes,1,opt,name=account_address,json=accountAddress,proto3" json:"account_address,omitempty"` + /// The account identifier + AccountId AccountIdentifier `protobuf:"bytes,2,opt,name=account_id,json=accountId,proto3" json:"account_id"` +} + +func (m *RegisteredICS27Account) Reset() { *m = RegisteredICS27Account{} } +func (m *RegisteredICS27Account) String() string { return proto.CompactTextString(m) } +func (*RegisteredICS27Account) ProtoMessage() {} +func (*RegisteredICS27Account) Descriptor() ([]byte, []int) { + return fileDescriptor_7cccbdb788964d3f, []int{1} +} +func (m *RegisteredICS27Account) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RegisteredICS27Account) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RegisteredICS27Account.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 *RegisteredICS27Account) XXX_Merge(src proto.Message) { + xxx_messageInfo_RegisteredICS27Account.Merge(m, src) +} +func (m *RegisteredICS27Account) XXX_Size() int { + return m.Size() +} +func (m *RegisteredICS27Account) XXX_DiscardUnknown() { + xxx_messageInfo_RegisteredICS27Account.DiscardUnknown(m) +} + +var xxx_messageInfo_RegisteredICS27Account proto.InternalMessageInfo + +func (m *RegisteredICS27Account) GetAccountAddress() string { + if m != nil { + return m.AccountAddress + } + return "" +} + +func (m *RegisteredICS27Account) GetAccountId() AccountIdentifier { + if m != nil { + return m.AccountId + } + return AccountIdentifier{} +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "ibc.applications.gmp.v1.GenesisState") + proto.RegisterType((*RegisteredICS27Account)(nil), "ibc.applications.gmp.v1.RegisteredICS27Account") +} + +func init() { + proto.RegisterFile("ibc/applications/gmp/v1/genesis.proto", fileDescriptor_7cccbdb788964d3f) +} + +var fileDescriptor_7cccbdb788964d3f = []byte{ + // 320 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x90, 0x41, 0x4b, 0x3a, 0x41, + 0x18, 0xc6, 0x77, 0xfc, 0xff, 0x09, 0x1c, 0xcb, 0x60, 0x89, 0x12, 0x0f, 0x9b, 0x08, 0x91, 0x04, + 0xce, 0xe4, 0x06, 0x79, 0xd6, 0x0e, 0xe1, 0xa9, 0xd0, 0x5b, 0x04, 0xb2, 0x3b, 0x3b, 0x4d, 0x2f, + 0xb8, 0x3b, 0xc3, 0xbe, 0xa3, 0xd0, 0xb7, 0x88, 0x3e, 0x95, 0x47, 0x8f, 0x9d, 0x22, 0xf4, 0x8b, + 0x84, 0xee, 0x08, 0x1d, 0xda, 0xdb, 0xcb, 0xf3, 0x3e, 0xbf, 0xf7, 0x79, 0x79, 0xe8, 0x05, 0xc4, + 0x82, 0x47, 0xc6, 0xcc, 0x40, 0x44, 0x16, 0x74, 0x86, 0x5c, 0xa5, 0x86, 0x2f, 0x7a, 0x5c, 0xc9, + 0x4c, 0x22, 0x20, 0x33, 0xb9, 0xb6, 0xda, 0x3f, 0x83, 0x58, 0xb0, 0xdf, 0x36, 0xa6, 0x52, 0xc3, + 0x16, 0xbd, 0x66, 0x29, 0x1f, 0x09, 0xa1, 0xe7, 0x99, 0x2d, 0xf8, 0xe6, 0x89, 0xd2, 0x4a, 0xef, + 0x46, 0xbe, 0x9d, 0x0a, 0xb5, 0x3d, 0xa3, 0x87, 0xf7, 0x45, 0xcc, 0xc4, 0x46, 0x56, 0xfa, 0xcf, + 0xb4, 0x0e, 0x02, 0xc3, 0xfe, 0xd4, 0xc1, 0xd8, 0xa8, 0xb4, 0xfe, 0x75, 0x6a, 0x21, 0x67, 0x25, + 0xf1, 0x6c, 0x2c, 0x15, 0xa0, 0x95, 0xb9, 0x4c, 0x46, 0x77, 0x93, 0xb0, 0x3f, 0x28, 0xb8, 0xe1, + 0xff, 0xe5, 0xd7, 0xb9, 0x37, 0x3e, 0xda, 0x1d, 0x73, 0x1a, 0xb6, 0x3f, 0x08, 0x3d, 0xfd, 0xdb, + 0xef, 0x5f, 0xd2, 0x63, 0x17, 0x39, 0x8d, 0x92, 0x24, 0x97, 0x88, 0x0d, 0xd2, 0x22, 0x9d, 0xea, + 0xb8, 0xee, 0xe4, 0x41, 0xa1, 0xfa, 0x0f, 0x94, 0xee, 0x8d, 0x90, 0x34, 0x2a, 0x2d, 0xd2, 0xa9, + 0x85, 0x57, 0xa5, 0xdf, 0xb9, 0xf3, 0xa3, 0x44, 0x66, 0x16, 0x5e, 0x40, 0xe6, 0xee, 0xb1, 0x6a, + 0xb4, 0x5f, 0x0c, 0x1f, 0x97, 0xeb, 0x80, 0xac, 0xd6, 0x01, 0xf9, 0x5e, 0x07, 0xe4, 0x7d, 0x13, + 0x78, 0xab, 0x4d, 0xe0, 0x7d, 0x6e, 0x02, 0xef, 0xe9, 0x56, 0x81, 0x7d, 0x9d, 0xc7, 0x4c, 0xe8, + 0x94, 0x0b, 0x8d, 0xa9, 0x46, 0x0e, 0xb1, 0xe8, 0x2a, 0xcd, 0x17, 0xbd, 0x6b, 0x9e, 0xea, 0x64, + 0x3e, 0x93, 0xb8, 0xad, 0x1e, 0x79, 0xd8, 0xef, 0x6e, 0x5b, 0xb7, 0x6f, 0x46, 0x62, 0x7c, 0xb0, + 0xeb, 0xf6, 0xe6, 0x27, 0x00, 0x00, 0xff, 0xff, 0xf5, 0x8a, 0x64, 0xe8, 0xda, 0x01, 0x00, 0x00, +} + +func (m *GenesisState) 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 *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Ics27Accounts) > 0 { + for iNdEx := len(m.Ics27Accounts) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Ics27Accounts[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + return len(dAtA) - i, nil +} + +func (m *RegisteredICS27Account) 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 *RegisteredICS27Account) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RegisteredICS27Account) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.AccountId.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.AccountAddress) > 0 { + i -= len(m.AccountAddress) + copy(dAtA[i:], m.AccountAddress) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.AccountAddress))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Ics27Accounts) > 0 { + for _, e := range m.Ics27Accounts { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func (m *RegisteredICS27Account) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.AccountAddress) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + l = m.AccountId.Size() + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) 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 ErrIntOverflowGenesis + } + 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: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ics27Accounts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Ics27Accounts = append(m.Ics27Accounts, RegisteredICS27Account{}) + if err := m.Ics27Accounts[len(m.Ics27Accounts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RegisteredICS27Account) 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 ErrIntOverflowGenesis + } + 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: RegisteredICS27Account: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RegisteredICS27Account: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AccountAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + 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 ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AccountAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AccountId", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.AccountId.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(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, ErrIntOverflowGenesis + } + 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, ErrIntOverflowGenesis + } + 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, ErrIntOverflowGenesis + } + 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, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/modules/apps/27-gmp/types/keys.go b/modules/apps/27-gmp/types/keys.go new file mode 100644 index 00000000000..c511cad377e --- /dev/null +++ b/modules/apps/27-gmp/types/keys.go @@ -0,0 +1,32 @@ +package types + +import "cosmossdk.io/collections" + +const ( + // ModuleName defines the gmp module name + ModuleName = "gmp" + + // StoreKey is the primary storage key for the gmp module + StoreKey = ModuleName + + // PortID is the default IBC port id that the gmp module + PortID = "gmpport" + + // Version defines the current version for gmp + Version = "ics27-2" + + // RouterKey is the message route for gmp + RouterKey = ModuleName + + // QuerierRoute is the querier route for gmp + QuerierRoute = ModuleName + + // accountsKey is the key used when generating a module address for the gmp module + accountsKey = "gmp-accounts" + + // AccountAddrLen is the length of the ICS27 account address + AccountAddrLen = 32 +) + +// AccountsKey is the key used to store the accounts in the keeper +var AccountsKey = collections.NewPrefix(0) diff --git a/modules/apps/27-gmp/types/msgs.go b/modules/apps/27-gmp/types/msgs.go new file mode 100644 index 00000000000..d43c6f5c6ca --- /dev/null +++ b/modules/apps/27-gmp/types/msgs.go @@ -0,0 +1,85 @@ +package types + +import ( + errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + + host "github.com/cosmos/ibc-go/v10/modules/core/24-host" + ibcerrors "github.com/cosmos/ibc-go/v10/modules/core/errors" +) + +const ( + MaximumReceiverLength = 2048 // maximum length of the receiver address in bytes (value chosen arbitrarily) + MaximumMemoLength = 32768 // maximum length of the memo in bytes (value chosen arbitrarily) + MaximumSaltLength = 32 // maximum length of the salt in bytes (value chosen arbitrarily) + MaximumPayloadLength = 32768 // maximum length of the payload in bytes (value chosen arbitrarily) +) + +var ( + _ sdk.Msg = (*MsgSendCall)(nil) + _ sdk.HasValidateBasic = (*MsgSendCall)(nil) +) + +// NewMsgSendCall creates a new MsgSendCall instance +func NewMsgSendCall(sourceClient, sender, receiver string, payload, salt []byte, timeoutTimestamp uint64, encoding, memo string) *MsgSendCall { + return &MsgSendCall{ + SourceClient: sourceClient, + Sender: sender, + Receiver: receiver, + Payload: payload, + Salt: salt, + Memo: memo, + TimeoutTimestamp: timeoutTimestamp, + Encoding: encoding, + } +} + +// ValidateBasic performs a basic check of the MsgSendCall fields. +// NOTE: The recipient addresses format is not validated as the format defined by +// the chain is not known to IBC. +func (msg MsgSendCall) ValidateBasic() error { + if err := msg.validateIdentifiers(); err != nil { + return err + } + + if _, err := sdk.AccAddressFromBech32(msg.Sender); err != nil { + return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) + } + // receiver is allowed to be empty + if len(msg.Receiver) > MaximumReceiverLength { + return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "recipient address must not exceed %d bytes", MaximumReceiverLength) + } + if len(msg.Payload) > MaximumPayloadLength { + return errorsmod.Wrapf(ErrInvalidPayload, "payload must not exceed %d bytes", MaximumPayloadLength) + } + if len(msg.Salt) > MaximumSaltLength { + return errorsmod.Wrapf(ErrInvalidSalt, "salt must not exceed %d bytes", MaximumSaltLength) + } + if len(msg.Memo) > MaximumMemoLength { + return errorsmod.Wrapf(ErrInvalidMemo, "memo must not exceed %d bytes", MaximumMemoLength) + } + if msg.TimeoutTimestamp == 0 { + return errorsmod.Wrap(ErrInvalidTimeoutTimestamp, "timeout timestamp must be greater than 0") + } + return validateEncoding(msg.Encoding) +} + +// validateIdentifiers checks if the IBC identifiers are valid +func (msg MsgSendCall) validateIdentifiers() error { + if err := host.ClientIdentifierValidator(msg.SourceClient); err != nil { + return errorsmod.Wrapf(err, "invalid source client ID %s", msg.SourceClient) + } + + return nil +} + +// validateEncoding checks if the encoding is valid +func validateEncoding(encoding string) error { + switch encoding { + case "", EncodingProtobuf, EncodingJSON, EncodingABI: + return nil + default: + return errorsmod.Wrapf(ErrInvalidEncoding, "unsupported encoding format %s", encoding) + } +} diff --git a/modules/apps/27-gmp/types/packet.go b/modules/apps/27-gmp/types/packet.go new file mode 100644 index 00000000000..35126cd290d --- /dev/null +++ b/modules/apps/27-gmp/types/packet.go @@ -0,0 +1,105 @@ +package types + +import ( + "encoding/json" + "strings" + + "github.com/cosmos/gogoproto/proto" + + errorsmod "cosmossdk.io/errors" + + "github.com/cosmos/cosmos-sdk/codec/unknownproto" + + ibcerrors "github.com/cosmos/ibc-go/v10/modules/core/errors" +) + +const ( + EncodingJSON = "application/json" + EncodingProtobuf = "application/x-protobuf" + EncodingABI = "application/x-solidity-abi" +) + +// NewGMPPacketData creates a new GMPPacketData instance with the provided parameters. +func NewGMPPacketData( + sender, receiver string, salt, payload []byte, memo string, +) GMPPacketData { + return GMPPacketData{ + Sender: sender, + Receiver: receiver, + Salt: salt, + Payload: payload, + Memo: memo, + } +} + +func (p GMPPacketData) ValidateBasic() error { + if strings.TrimSpace(p.Sender) == "" { + return errorsmod.Wrap(ibcerrors.ErrInvalidAddress, "missing sender address") + } + // receiver is allowed to be empty + if len(p.Receiver) > MaximumReceiverLength { + return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "recipient address must not exceed %d bytes", MaximumReceiverLength) + } + if len(p.Payload) > MaximumPayloadLength { + return errorsmod.Wrapf(ErrInvalidPayload, "payload must not exceed %d bytes", MaximumPayloadLength) + } + if len(p.Salt) > MaximumSaltLength { + return errorsmod.Wrapf(ErrInvalidSalt, "salt must not exceed %d bytes", MaximumSaltLength) + } + if len(p.Memo) > MaximumMemoLength { + return errorsmod.Wrapf(ErrInvalidMemo, "memo must not exceed %d bytes", MaximumMemoLength) + } + + return nil +} + +// MarshalPacketData attempts to marshal the provided GMPPacketData into bytes with the provided encoding. +func MarshalPacketData(data *GMPPacketData, ics27Version string, encoding string) ([]byte, error) { + if ics27Version != Version { + panic("unsupported ics27 version") + } + + switch encoding { + case EncodingJSON: + return json.Marshal(data) + case EncodingProtobuf: + return proto.Marshal(data) + case EncodingABI: + return EncodeABIGMPPacketData(data) + default: + return nil, errorsmod.Wrapf(ErrInvalidEncoding, "invalid encoding provided, must be either empty or one of [%q, %q, %q], got %s", EncodingJSON, EncodingProtobuf, EncodingABI, encoding) + } +} + +// UnmarshalPacketData attempts to unmarshal the provided bytes into a GMPPacketData with the provided encoding. +func UnmarshalPacketData(bz []byte, ics27Version string, encoding string) (*GMPPacketData, error) { + if ics27Version != Version { + panic("unsupported ics27 version") + } + + var data *GMPPacketData + switch encoding { + case EncodingJSON: + if err := json.Unmarshal(bz, &data); err != nil { + return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "failed to unmarshal json packet data: %s", err) + } + case EncodingProtobuf: + if err := unknownproto.RejectUnknownFieldsStrict(bz, data, unknownproto.DefaultAnyResolver{}); err != nil { + return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "failed to unmarshal protobuf packet data: %s", err) + } + + if err := proto.Unmarshal(bz, data); err != nil { + return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "failed to unmarshal protobuf packet data: %s", err) + } + case EncodingABI: + var err error + data, err = DecodeABIGMPPacketData(bz) + if err != nil { + return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "failed to unmarshal ABI packet data: %s", err) + } + default: + return nil, errorsmod.Wrapf(ErrInvalidEncoding, "invalid encoding provided, must be either empty or one of [%q, %q, %q], got %s", EncodingJSON, EncodingProtobuf, EncodingABI, encoding) + } + + return data, nil +} diff --git a/modules/apps/27-gmp/types/packet.pb.go b/modules/apps/27-gmp/types/packet.pb.go new file mode 100644 index 00000000000..c7204389840 --- /dev/null +++ b/modules/apps/27-gmp/types/packet.pb.go @@ -0,0 +1,712 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: ibc/applications/gmp/v1/packet.proto + +package types + +import ( + fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" + 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 + +// GMPPacketData defines a struct for the packet payload +type GMPPacketData struct { + // the sender address + Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` + // the recipient address on the destination chain + Receiver string `protobuf:"bytes,2,opt,name=receiver,proto3" json:"receiver,omitempty"` + // The salt used to generate the caller account address + Salt []byte `protobuf:"bytes,3,opt,name=salt,proto3" json:"salt,omitempty"` + // The payload of the call + Payload []byte `protobuf:"bytes,4,opt,name=payload,proto3" json:"payload,omitempty"` + // optional memo + Memo string `protobuf:"bytes,5,opt,name=memo,proto3" json:"memo,omitempty"` +} + +func (m *GMPPacketData) Reset() { *m = GMPPacketData{} } +func (m *GMPPacketData) String() string { return proto.CompactTextString(m) } +func (*GMPPacketData) ProtoMessage() {} +func (*GMPPacketData) Descriptor() ([]byte, []int) { + return fileDescriptor_2a0b0887619370c4, []int{0} +} +func (m *GMPPacketData) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GMPPacketData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GMPPacketData.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 *GMPPacketData) XXX_Merge(src proto.Message) { + xxx_messageInfo_GMPPacketData.Merge(m, src) +} +func (m *GMPPacketData) XXX_Size() int { + return m.Size() +} +func (m *GMPPacketData) XXX_DiscardUnknown() { + xxx_messageInfo_GMPPacketData.DiscardUnknown(m) +} + +var xxx_messageInfo_GMPPacketData proto.InternalMessageInfo + +func (m *GMPPacketData) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *GMPPacketData) GetReceiver() string { + if m != nil { + return m.Receiver + } + return "" +} + +func (m *GMPPacketData) GetSalt() []byte { + if m != nil { + return m.Salt + } + return nil +} + +func (m *GMPPacketData) GetPayload() []byte { + if m != nil { + return m.Payload + } + return nil +} + +func (m *GMPPacketData) GetMemo() string { + if m != nil { + return m.Memo + } + return "" +} + +// Acknowledgement defines a struct for the ICS27-2 acknowledgement +type Acknowledgement struct { + // The result of the call + Result []byte `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` +} + +func (m *Acknowledgement) Reset() { *m = Acknowledgement{} } +func (m *Acknowledgement) String() string { return proto.CompactTextString(m) } +func (*Acknowledgement) ProtoMessage() {} +func (*Acknowledgement) Descriptor() ([]byte, []int) { + return fileDescriptor_2a0b0887619370c4, []int{1} +} +func (m *Acknowledgement) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Acknowledgement) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Acknowledgement.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 *Acknowledgement) XXX_Merge(src proto.Message) { + xxx_messageInfo_Acknowledgement.Merge(m, src) +} +func (m *Acknowledgement) XXX_Size() int { + return m.Size() +} +func (m *Acknowledgement) XXX_DiscardUnknown() { + xxx_messageInfo_Acknowledgement.DiscardUnknown(m) +} + +var xxx_messageInfo_Acknowledgement proto.InternalMessageInfo + +func (m *Acknowledgement) GetResult() []byte { + if m != nil { + return m.Result + } + return nil +} + +func init() { + proto.RegisterType((*GMPPacketData)(nil), "ibc.applications.gmp.v1.GMPPacketData") + proto.RegisterType((*Acknowledgement)(nil), "ibc.applications.gmp.v1.Acknowledgement") +} + +func init() { + proto.RegisterFile("ibc/applications/gmp/v1/packet.proto", fileDescriptor_2a0b0887619370c4) +} + +var fileDescriptor_2a0b0887619370c4 = []byte{ + // 283 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x90, 0x31, 0x4b, 0x33, 0x31, + 0x1c, 0xc6, 0x9b, 0xf7, 0xad, 0x55, 0x43, 0x45, 0xc8, 0xa0, 0xc1, 0x21, 0x94, 0xe2, 0x50, 0x87, + 0x5e, 0xac, 0x82, 0xce, 0x8a, 0xe0, 0x24, 0x1c, 0x37, 0xba, 0xe5, 0x72, 0x7f, 0xce, 0xd0, 0xe4, + 0x12, 0x2e, 0xb9, 0x93, 0x7e, 0x00, 0x77, 0x3f, 0x96, 0x63, 0x47, 0x47, 0xb9, 0xfb, 0x22, 0x72, + 0xa1, 0x8a, 0xdb, 0xf3, 0x4b, 0x1e, 0xfe, 0x3c, 0xfc, 0xf0, 0xb9, 0xca, 0x25, 0x17, 0xce, 0x69, + 0x25, 0x45, 0x50, 0xb6, 0xf2, 0xbc, 0x34, 0x8e, 0xb7, 0x2b, 0xee, 0x84, 0x5c, 0x43, 0x48, 0x5c, + 0x6d, 0x83, 0x25, 0xa7, 0x2a, 0x97, 0xc9, 0xdf, 0x56, 0x52, 0x1a, 0x97, 0xb4, 0xab, 0xf9, 0x1b, + 0xc2, 0x47, 0x8f, 0x4f, 0x69, 0x1a, 0xcb, 0x0f, 0x22, 0x08, 0x72, 0x82, 0x27, 0x1e, 0xaa, 0x02, + 0x6a, 0x8a, 0x66, 0x68, 0x71, 0x98, 0xed, 0x88, 0x9c, 0xe1, 0x83, 0x1a, 0x24, 0xa8, 0x16, 0x6a, + 0xfa, 0x2f, 0xfe, 0xfc, 0x32, 0x21, 0x78, 0xec, 0x85, 0x0e, 0xf4, 0xff, 0x0c, 0x2d, 0xa6, 0x59, + 0xcc, 0x84, 0xe2, 0x7d, 0x27, 0x36, 0xda, 0x8a, 0x82, 0x8e, 0xe3, 0xf3, 0x0f, 0x0e, 0x6d, 0x03, + 0xc6, 0xd2, 0xbd, 0x78, 0x25, 0xe6, 0xf9, 0x05, 0x3e, 0xbe, 0x93, 0xeb, 0xca, 0xbe, 0x6a, 0x28, + 0x4a, 0x30, 0x50, 0x85, 0x61, 0x48, 0x0d, 0xbe, 0xd1, 0x21, 0x0e, 0x99, 0x66, 0x3b, 0xba, 0x4f, + 0x3f, 0x3a, 0x86, 0xb6, 0x1d, 0x43, 0x5f, 0x1d, 0x43, 0xef, 0x3d, 0x1b, 0x6d, 0x7b, 0x36, 0xfa, + 0xec, 0xd9, 0xe8, 0xf9, 0xa6, 0x54, 0xe1, 0xa5, 0xc9, 0x13, 0x69, 0x0d, 0x97, 0xd6, 0x1b, 0xeb, + 0xb9, 0xca, 0xe5, 0xb2, 0xb4, 0xbc, 0x5d, 0x5d, 0x72, 0x63, 0x8b, 0x46, 0x83, 0x1f, 0x64, 0x79, + 0x7e, 0x75, 0xbb, 0x1c, 0x3c, 0x85, 0x8d, 0x03, 0x9f, 0x4f, 0xa2, 0xa4, 0xeb, 0xef, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x3e, 0xa9, 0x52, 0x9d, 0x4c, 0x01, 0x00, 0x00, +} + +func (m *GMPPacketData) 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 *GMPPacketData) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GMPPacketData) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Memo) > 0 { + i -= len(m.Memo) + copy(dAtA[i:], m.Memo) + i = encodeVarintPacket(dAtA, i, uint64(len(m.Memo))) + i-- + dAtA[i] = 0x2a + } + if len(m.Payload) > 0 { + i -= len(m.Payload) + copy(dAtA[i:], m.Payload) + i = encodeVarintPacket(dAtA, i, uint64(len(m.Payload))) + i-- + dAtA[i] = 0x22 + } + if len(m.Salt) > 0 { + i -= len(m.Salt) + copy(dAtA[i:], m.Salt) + i = encodeVarintPacket(dAtA, i, uint64(len(m.Salt))) + i-- + dAtA[i] = 0x1a + } + if len(m.Receiver) > 0 { + i -= len(m.Receiver) + copy(dAtA[i:], m.Receiver) + i = encodeVarintPacket(dAtA, i, uint64(len(m.Receiver))) + i-- + dAtA[i] = 0x12 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintPacket(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Acknowledgement) 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 *Acknowledgement) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Acknowledgement) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Result) > 0 { + i -= len(m.Result) + copy(dAtA[i:], m.Result) + i = encodeVarintPacket(dAtA, i, uint64(len(m.Result))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintPacket(dAtA []byte, offset int, v uint64) int { + offset -= sovPacket(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GMPPacketData) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovPacket(uint64(l)) + } + l = len(m.Receiver) + if l > 0 { + n += 1 + l + sovPacket(uint64(l)) + } + l = len(m.Salt) + if l > 0 { + n += 1 + l + sovPacket(uint64(l)) + } + l = len(m.Payload) + if l > 0 { + n += 1 + l + sovPacket(uint64(l)) + } + l = len(m.Memo) + if l > 0 { + n += 1 + l + sovPacket(uint64(l)) + } + return n +} + +func (m *Acknowledgement) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Result) + if l > 0 { + n += 1 + l + sovPacket(uint64(l)) + } + return n +} + +func sovPacket(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozPacket(x uint64) (n int) { + return sovPacket(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GMPPacketData) 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 ErrIntOverflowPacket + } + 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: GMPPacketData: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GMPPacketData: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPacket + } + 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 ErrInvalidLengthPacket + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPacket + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Receiver", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPacket + } + 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 ErrInvalidLengthPacket + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPacket + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Receiver = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Salt", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPacket + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthPacket + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthPacket + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Salt = append(m.Salt[:0], dAtA[iNdEx:postIndex]...) + if m.Salt == nil { + m.Salt = []byte{} + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Payload", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPacket + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthPacket + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthPacket + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Payload = append(m.Payload[:0], dAtA[iNdEx:postIndex]...) + if m.Payload == nil { + m.Payload = []byte{} + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Memo", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPacket + } + 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 ErrInvalidLengthPacket + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPacket + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Memo = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPacket(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPacket + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Acknowledgement) 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 ErrIntOverflowPacket + } + 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: Acknowledgement: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Acknowledgement: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPacket + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthPacket + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthPacket + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Result = append(m.Result[:0], dAtA[iNdEx:postIndex]...) + if m.Result == nil { + m.Result = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPacket(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPacket + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipPacket(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, ErrIntOverflowPacket + } + 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, ErrIntOverflowPacket + } + 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, ErrIntOverflowPacket + } + 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, ErrInvalidLengthPacket + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupPacket + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthPacket + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthPacket = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowPacket = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupPacket = fmt.Errorf("proto: unexpected end of group") +) diff --git a/modules/apps/27-gmp/types/query.pb.go b/modules/apps/27-gmp/types/query.pb.go new file mode 100644 index 00000000000..97809332d9d --- /dev/null +++ b/modules/apps/27-gmp/types/query.pb.go @@ -0,0 +1,697 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: ibc/applications/gmp/v1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + 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 + +// QueryAccountAddressRequest is the request type for the Query/AccountAddress RPC method. +type QueryAccountAddressRequest struct { + // The (local) client identifier + ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + // The sender of the packet + Sender string `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` + // The salt of the packet (in hex format) + Salt string `protobuf:"bytes,3,opt,name=salt,proto3" json:"salt,omitempty"` +} + +func (m *QueryAccountAddressRequest) Reset() { *m = QueryAccountAddressRequest{} } +func (m *QueryAccountAddressRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAccountAddressRequest) ProtoMessage() {} +func (*QueryAccountAddressRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_0d55aa1ab285a918, []int{0} +} +func (m *QueryAccountAddressRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAccountAddressRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAccountAddressRequest.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 *QueryAccountAddressRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAccountAddressRequest.Merge(m, src) +} +func (m *QueryAccountAddressRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAccountAddressRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAccountAddressRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAccountAddressRequest proto.InternalMessageInfo + +func (m *QueryAccountAddressRequest) GetClientId() string { + if m != nil { + return m.ClientId + } + return "" +} + +func (m *QueryAccountAddressRequest) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *QueryAccountAddressRequest) GetSalt() string { + if m != nil { + return m.Salt + } + return "" +} + +// QueryAccountAddressResponse is the response type for the Query/AccountAddress RPC method. +type QueryAccountAddressResponse struct { + // The interchain account address + AccountAddress string `protobuf:"bytes,1,opt,name=account_address,json=accountAddress,proto3" json:"account_address,omitempty"` +} + +func (m *QueryAccountAddressResponse) Reset() { *m = QueryAccountAddressResponse{} } +func (m *QueryAccountAddressResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAccountAddressResponse) ProtoMessage() {} +func (*QueryAccountAddressResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_0d55aa1ab285a918, []int{1} +} +func (m *QueryAccountAddressResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAccountAddressResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAccountAddressResponse.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 *QueryAccountAddressResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAccountAddressResponse.Merge(m, src) +} +func (m *QueryAccountAddressResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAccountAddressResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAccountAddressResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAccountAddressResponse proto.InternalMessageInfo + +func (m *QueryAccountAddressResponse) GetAccountAddress() string { + if m != nil { + return m.AccountAddress + } + return "" +} + +func init() { + proto.RegisterType((*QueryAccountAddressRequest)(nil), "ibc.applications.gmp.v1.QueryAccountAddressRequest") + proto.RegisterType((*QueryAccountAddressResponse)(nil), "ibc.applications.gmp.v1.QueryAccountAddressResponse") +} + +func init() { + proto.RegisterFile("ibc/applications/gmp/v1/query.proto", fileDescriptor_0d55aa1ab285a918) +} + +var fileDescriptor_0d55aa1ab285a918 = []byte{ + // 358 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x51, 0x41, 0x4b, 0x3a, 0x41, + 0x1c, 0x75, 0xfd, 0xff, 0x93, 0x9c, 0x83, 0xc1, 0x1c, 0x4a, 0x34, 0x96, 0xb0, 0x43, 0x21, 0xb8, + 0x93, 0x1a, 0x75, 0x0a, 0xd2, 0x43, 0xd4, 0xad, 0x3c, 0x76, 0x91, 0xd9, 0xd9, 0x61, 0x1b, 0xd8, + 0xdd, 0x19, 0xf7, 0x37, 0x2b, 0x88, 0x78, 0xe9, 0x13, 0x04, 0x7d, 0xa6, 0xa0, 0x5b, 0x42, 0x97, + 0x8e, 0xa1, 0x7d, 0x90, 0xd8, 0x9d, 0x45, 0x12, 0xf2, 0xd0, 0x6d, 0xe6, 0xf7, 0xe6, 0xbd, 0x37, + 0xbf, 0xf7, 0xd0, 0xa1, 0x70, 0x19, 0xa1, 0x4a, 0x05, 0x82, 0x51, 0x2d, 0x64, 0x04, 0xc4, 0x0f, + 0x15, 0x19, 0xb7, 0xc9, 0x28, 0xe1, 0xf1, 0xc4, 0x51, 0xb1, 0xd4, 0x12, 0xef, 0x09, 0x97, 0x39, + 0x3f, 0x1f, 0x39, 0x7e, 0xa8, 0x9c, 0x71, 0xbb, 0xb6, 0xef, 0x4b, 0xe9, 0x07, 0x9c, 0x50, 0x25, + 0x08, 0x8d, 0x22, 0xa9, 0x73, 0x38, 0xa3, 0x35, 0x38, 0xaa, 0xdd, 0xa5, 0x2a, 0x3d, 0xc6, 0x64, + 0x12, 0xe9, 0x9e, 0xe7, 0xc5, 0x1c, 0x60, 0xc0, 0x47, 0x09, 0x07, 0x8d, 0xeb, 0xa8, 0xcc, 0x02, + 0xc1, 0x23, 0x3d, 0x14, 0x5e, 0xd5, 0x3a, 0xb0, 0x8e, 0xcb, 0x83, 0x6d, 0x33, 0xb8, 0xf1, 0xf0, + 0x2e, 0x2a, 0x01, 0x8f, 0x3c, 0x1e, 0x57, 0x8b, 0x19, 0x92, 0xdf, 0x30, 0x46, 0xff, 0x81, 0x06, + 0xba, 0xfa, 0x2f, 0x9b, 0x66, 0xe7, 0xc6, 0x15, 0xaa, 0xff, 0x6a, 0x03, 0x4a, 0x46, 0xc0, 0xf1, + 0x11, 0xda, 0xa1, 0x06, 0x19, 0x52, 0x03, 0xe5, 0x6e, 0x15, 0xba, 0x46, 0xe8, 0xbc, 0x59, 0x68, + 0x2b, 0x13, 0xc2, 0x2f, 0x16, 0xaa, 0xac, 0xab, 0xe1, 0xae, 0xb3, 0x21, 0x03, 0x67, 0xf3, 0x8a, + 0xb5, 0xd3, 0xbf, 0x91, 0xcc, 0x87, 0x1b, 0xd7, 0x8f, 0xef, 0x5f, 0xcf, 0xc5, 0x3e, 0xbe, 0x24, + 0x79, 0x37, 0xab, 0x4e, 0x4c, 0x3c, 0x40, 0xa6, 0xab, 0xe0, 0x66, 0x24, 0x5f, 0x02, 0xc8, 0xd4, + 0x44, 0x34, 0x23, 0xd3, 0x34, 0x95, 0x8b, 0x66, 0x73, 0xd6, 0xbf, 0x7d, 0x5d, 0xd8, 0xd6, 0x7c, + 0x61, 0x5b, 0x9f, 0x0b, 0xdb, 0x7a, 0x5a, 0xda, 0x85, 0xf9, 0xd2, 0x2e, 0x7c, 0x2c, 0xed, 0xc2, + 0xfd, 0x99, 0x2f, 0xf4, 0x43, 0xe2, 0x3a, 0x4c, 0x86, 0x84, 0x49, 0x08, 0x25, 0xa4, 0x66, 0x2d, + 0x5f, 0x92, 0x71, 0xfb, 0x84, 0x84, 0xd2, 0x4b, 0x02, 0x0e, 0xc6, 0xbb, 0x73, 0xde, 0x4a, 0xed, + 0xf5, 0x44, 0x71, 0x70, 0x4b, 0x59, 0xb3, 0xdd, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x08, 0xbf, + 0x5a, 0x74, 0x37, 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 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // AccountAddress queries the interchain account address for a given client_id, sender, and salt. + // If the account is not registered, the address is computed deterministically + AccountAddress(ctx context.Context, in *QueryAccountAddressRequest, opts ...grpc.CallOption) (*QueryAccountAddressResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) AccountAddress(ctx context.Context, in *QueryAccountAddressRequest, opts ...grpc.CallOption) (*QueryAccountAddressResponse, error) { + out := new(QueryAccountAddressResponse) + err := c.cc.Invoke(ctx, "/ibc.applications.gmp.v1.Query/AccountAddress", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // AccountAddress queries the interchain account address for a given client_id, sender, and salt. + // If the account is not registered, the address is computed deterministically + AccountAddress(context.Context, *QueryAccountAddressRequest) (*QueryAccountAddressResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) AccountAddress(ctx context.Context, req *QueryAccountAddressRequest) (*QueryAccountAddressResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AccountAddress not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_AccountAddress_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAccountAddressRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).AccountAddress(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ibc.applications.gmp.v1.Query/AccountAddress", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).AccountAddress(ctx, req.(*QueryAccountAddressRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "ibc.applications.gmp.v1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "AccountAddress", + Handler: _Query_AccountAddress_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "ibc/applications/gmp/v1/query.proto", +} + +func (m *QueryAccountAddressRequest) 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 *QueryAccountAddressRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAccountAddressRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Salt) > 0 { + i -= len(m.Salt) + copy(dAtA[i:], m.Salt) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Salt))) + i-- + dAtA[i] = 0x1a + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x12 + } + if len(m.ClientId) > 0 { + i -= len(m.ClientId) + copy(dAtA[i:], m.ClientId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ClientId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryAccountAddressResponse) 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 *QueryAccountAddressResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAccountAddressResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AccountAddress) > 0 { + i -= len(m.AccountAddress) + copy(dAtA[i:], m.AccountAddress) + i = encodeVarintQuery(dAtA, i, uint64(len(m.AccountAddress))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryAccountAddressRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ClientId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Salt) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAccountAddressResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.AccountAddress) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryAccountAddressRequest) 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 ErrIntOverflowQuery + } + 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: QueryAccountAddressRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAccountAddressRequest: 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 ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + 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 Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Salt", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Salt = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAccountAddressResponse) 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 ErrIntOverflowQuery + } + 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: QueryAccountAddressResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAccountAddressResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AccountAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AccountAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(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, ErrIntOverflowQuery + } + 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, ErrIntOverflowQuery + } + 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, ErrIntOverflowQuery + } + 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, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/modules/apps/27-gmp/types/query.pb.gw.go b/modules/apps/27-gmp/types/query.pb.gw.go new file mode 100644 index 00000000000..0fa9f5f2299 --- /dev/null +++ b/modules/apps/27-gmp/types/query.pb.gw.go @@ -0,0 +1,233 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: ibc/applications/gmp/v1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_AccountAddress_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAccountAddressRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["client_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "client_id") + } + + protoReq.ClientId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "client_id", err) + } + + val, ok = pathParams["sender"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sender") + } + + protoReq.Sender, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sender", err) + } + + val, ok = pathParams["salt"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "salt") + } + + protoReq.Salt, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "salt", err) + } + + msg, err := client.AccountAddress(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_AccountAddress_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAccountAddressRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["client_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "client_id") + } + + protoReq.ClientId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "client_id", err) + } + + val, ok = pathParams["sender"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sender") + } + + protoReq.Sender, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sender", err) + } + + val, ok = pathParams["salt"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "salt") + } + + protoReq.Salt, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "salt", err) + } + + msg, err := server.AccountAddress(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_AccountAddress_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_AccountAddress_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AccountAddress_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_AccountAddress_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_AccountAddress_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AccountAddress_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_AccountAddress_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 3, 0, 4, 1, 5, 8}, []string{"ibc", "apps", "gmp", "v1", "clients", "client_id", "accounts", "sender", "salt"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_AccountAddress_0 = runtime.ForwardResponseMessage +) diff --git a/modules/apps/27-gmp/types/router.go b/modules/apps/27-gmp/types/router.go new file mode 100644 index 00000000000..dd1cfb4d3cf --- /dev/null +++ b/modules/apps/27-gmp/types/router.go @@ -0,0 +1,12 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// MessageRouter ADR 031 request type routing +// https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-031-msg-service.md +type MessageRouter interface { + Handler(msg sdk.Msg) baseapp.MsgServiceHandler +} diff --git a/modules/apps/27-gmp/types/solidity_abi.go b/modules/apps/27-gmp/types/solidity_abi.go new file mode 100644 index 00000000000..7a78e27b6bb --- /dev/null +++ b/modules/apps/27-gmp/types/solidity_abi.go @@ -0,0 +1,168 @@ +package types + +import ( + "github.com/ethereum/go-ethereum/accounts/abi" + + errorsmod "cosmossdk.io/errors" +) + +// getICS27PacketABI returns an abi.Arguments slice describing the Solidity types of the struct. +func getICS27PacketABI() abi.Arguments { + // Create the ABI types for each field. + // The Solidity types used are: + // - string for Sender, Receiver and Memo. + // - bytes for Salt and Payload. + tupleType, err := abi.NewType("tuple", "", []abi.ArgumentMarshaling{ + { + Name: "sender", + Type: "string", + }, + { + Name: "receiver", + Type: "string", + }, + { + Name: "salt", + Type: "bytes", + }, + { + Name: "payload", + Type: "bytes", + }, + { + Name: "memo", + Type: "string", + }, + }) + if err != nil { + panic(err) + } + + // Create an ABI argument representing our struct as a single tuple argument. + arguments := abi.Arguments{ + { + Type: tupleType, + }, + } + + return arguments +} + +// getICS27AckABI returns an abi.Arguments slice describing the Solidity types of the struct. +func getICS27AckABI() abi.Arguments { + // Create the ABI types for each field. + // The Solidity types used are: + // - bytes for Result. + tupleType, err := abi.NewType("tuple", "", []abi.ArgumentMarshaling{ + { + Name: "result", + Type: "bytes", + }, + }) + if err != nil { + panic(err) + } + + // Create an ABI argument representing our struct as a single tuple argument. + arguments := abi.Arguments{ + { + Type: tupleType, + }, + } + + return arguments +} + +// DecodeABIGMPPacketData decodes a solidity ABI encoded ics27lib.GMPPacketData and converts it into an ibc-go GMPPacketData. +func DecodeABIGMPPacketData(data []byte) (*GMPPacketData, error) { + arguments := getICS27PacketABI() + + packetDataI, err := arguments.Unpack(data) + if err != nil { + return nil, errorsmod.Wrapf(ErrAbiDecoding, "failed to unpack data: %s", err) + } + + packetData, ok := packetDataI[0].(struct { + Sender string `json:"sender"` + Receiver string `json:"receiver"` + Salt []byte `json:"salt"` + Payload []byte `json:"payload"` + Memo string `json:"memo"` + }) + if !ok { + return nil, errorsmod.Wrapf(ErrAbiDecoding, "failed to parse packet data") + } + + return &GMPPacketData{ + Sender: packetData.Sender, + Receiver: packetData.Receiver, + Salt: packetData.Salt, + Payload: packetData.Payload, + Memo: packetData.Memo, + }, nil +} + +// EncodeABIGMPPacketData encodes a GMPPacketData into a solidity ABI encoded byte array. +func EncodeABIGMPPacketData(data *GMPPacketData) ([]byte, error) { + packetData := struct { + Sender string `json:"sender"` + Receiver string `json:"receiver"` + Salt []byte `json:"salt"` + Payload []byte `json:"payload"` + Memo string `json:"memo"` + }{ + data.Sender, + data.Receiver, + data.Salt, + data.Payload, + data.Memo, + } + + arguments := getICS27PacketABI() + // Pack the values in the order defined in the ABI. + encodedData, err := arguments.Pack(packetData) + if err != nil { + return nil, errorsmod.Wrapf(ErrAbiEncoding, "failed to pack data: %s", err) + } + + return encodedData, nil +} + +// DecodeABIAcknowledgement decodes a solidity ABI encoded ics27lib.Acknowledgement and converts it into an ibc-go Acknowledgement +func DecodeABIAcknowledgement(data []byte) (*Acknowledgement, error) { + arguments := getICS27AckABI() + + packetDataI, err := arguments.Unpack(data) + if err != nil { + return nil, errorsmod.Wrapf(ErrAbiDecoding, "failed to unpack data: %s", err) + } + + packetData, ok := packetDataI[0].(struct { + Result []byte `json:"result"` + }) + if !ok { + return nil, errorsmod.Wrapf(ErrAbiDecoding, "failed to parse packet data") + } + + return &Acknowledgement{ + Result: packetData.Result, + }, nil +} + +// EncodeABIAcknowledgement encodes an Acknowledgement into a solidity ABI encoded byte array +func EncodeABIAcknowledgement(data *Acknowledgement) ([]byte, error) { + ack := struct { + Result []byte `json:"result"` + }{ + Result: data.Result, + } + + arguments := getICS27AckABI() + // Pack the values in the order defined in the ABI. + encodedData, err := arguments.Pack(ack) + if err != nil { + return nil, errorsmod.Wrapf(ErrAbiEncoding, "failed to pack data: %s", err) + } + + return encodedData, nil +} diff --git a/modules/apps/27-gmp/types/tx.pb.go b/modules/apps/27-gmp/types/tx.pb.go new file mode 100644 index 00000000000..63af1d98ca5 --- /dev/null +++ b/modules/apps/27-gmp/types/tx.pb.go @@ -0,0 +1,867 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: ibc/applications/gmp/v1/tx.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 + +// MsgSendCall defines a msg to send a call to a contract/receiver on a ICS27-2 enabled chain. +type MsgSendCall struct { + // the client by which the packet will be sent + SourceClient string `protobuf:"bytes,1,opt,name=source_client,json=sourceClient,proto3" json:"source_client,omitempty"` + // the sender address + Sender string `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` + // the recipient address on the destination chain + Receiver string `protobuf:"bytes,3,opt,name=receiver,proto3" json:"receiver,omitempty"` + // The salt used to generate the caller account address + Salt []byte `protobuf:"bytes,4,opt,name=salt,proto3" json:"salt,omitempty"` + // The payload of the call + Payload []byte `protobuf:"bytes,5,opt,name=payload,proto3" json:"payload,omitempty"` + // Timeout timestamp in absolute nanoseconds since unix epoch. + TimeoutTimestamp uint64 `protobuf:"varint,6,opt,name=timeout_timestamp,json=timeoutTimestamp,proto3" json:"timeout_timestamp,omitempty"` + // optional memo + Memo string `protobuf:"bytes,7,opt,name=memo,proto3" json:"memo,omitempty"` + // optional encoding + Encoding string `protobuf:"bytes,8,opt,name=encoding,proto3" json:"encoding,omitempty"` +} + +func (m *MsgSendCall) Reset() { *m = MsgSendCall{} } +func (m *MsgSendCall) String() string { return proto.CompactTextString(m) } +func (*MsgSendCall) ProtoMessage() {} +func (*MsgSendCall) Descriptor() ([]byte, []int) { + return fileDescriptor_32bfd6a386d18ce5, []int{0} +} +func (m *MsgSendCall) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSendCall) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSendCall.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 *MsgSendCall) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSendCall.Merge(m, src) +} +func (m *MsgSendCall) XXX_Size() int { + return m.Size() +} +func (m *MsgSendCall) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSendCall.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSendCall proto.InternalMessageInfo + +// MsgSendCallResponse defines the Msg/SendCall response type. +type MsgSendCallResponse struct { + // sequence number of the GMP packet sent + Sequence uint64 `protobuf:"varint,1,opt,name=sequence,proto3" json:"sequence,omitempty"` +} + +func (m *MsgSendCallResponse) Reset() { *m = MsgSendCallResponse{} } +func (m *MsgSendCallResponse) String() string { return proto.CompactTextString(m) } +func (*MsgSendCallResponse) ProtoMessage() {} +func (*MsgSendCallResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_32bfd6a386d18ce5, []int{1} +} +func (m *MsgSendCallResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSendCallResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSendCallResponse.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 *MsgSendCallResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSendCallResponse.Merge(m, src) +} +func (m *MsgSendCallResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgSendCallResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSendCallResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSendCallResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgSendCall)(nil), "ibc.applications.gmp.v1.MsgSendCall") + proto.RegisterType((*MsgSendCallResponse)(nil), "ibc.applications.gmp.v1.MsgSendCallResponse") +} + +func init() { proto.RegisterFile("ibc/applications/gmp/v1/tx.proto", fileDescriptor_32bfd6a386d18ce5) } + +var fileDescriptor_32bfd6a386d18ce5 = []byte{ + // 422 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0xb1, 0x6e, 0x14, 0x31, + 0x10, 0xbd, 0x4d, 0x36, 0x97, 0xc3, 0x04, 0x01, 0x06, 0x11, 0x6b, 0x8b, 0xe5, 0x14, 0x28, 0x4e, + 0x81, 0xac, 0xb9, 0x20, 0x11, 0x29, 0x25, 0xa9, 0x23, 0xa1, 0x85, 0x8a, 0x82, 0x68, 0xd7, 0x3b, + 0x32, 0x96, 0xd6, 0x6b, 0xb3, 0xe3, 0x3d, 0x91, 0x0e, 0xa5, 0xa2, 0xe4, 0x13, 0xf8, 0x84, 0x7c, + 0x06, 0x65, 0x4a, 0x4a, 0x74, 0x57, 0xe4, 0x37, 0x90, 0x7d, 0xb7, 0xa7, 0x6b, 0x90, 0xa8, 0x3c, + 0x6f, 0xde, 0xd3, 0xf3, 0xd3, 0xcc, 0x90, 0xb1, 0x2a, 0x05, 0x2f, 0xac, 0xad, 0x95, 0x28, 0x9c, + 0x32, 0x0d, 0x72, 0xa9, 0x2d, 0x9f, 0x4d, 0xb9, 0xfb, 0x9a, 0xd9, 0xd6, 0x38, 0x43, 0xf7, 0x55, + 0x29, 0xb2, 0x4d, 0x45, 0x26, 0xb5, 0xcd, 0x66, 0xd3, 0xe4, 0xb1, 0x34, 0xd2, 0x04, 0x0d, 0xf7, + 0xd5, 0x52, 0x9e, 0xec, 0x0b, 0x83, 0xda, 0x20, 0xd7, 0x28, 0xbd, 0x8d, 0x46, 0xb9, 0x24, 0x0e, + 0xae, 0xb6, 0xc8, 0xdd, 0x73, 0x94, 0xef, 0xa1, 0xa9, 0xce, 0x8a, 0xba, 0xa6, 0xcf, 0xc8, 0x3d, + 0x34, 0x5d, 0x2b, 0xe0, 0x42, 0xd4, 0x0a, 0x1a, 0xc7, 0xa2, 0x71, 0x34, 0xb9, 0x93, 0xef, 0x2d, + 0x9b, 0x67, 0xa1, 0x47, 0x9f, 0x90, 0x21, 0x42, 0x53, 0x41, 0xcb, 0xb6, 0x02, 0xbb, 0x42, 0x34, + 0x21, 0xa3, 0x16, 0x04, 0xa8, 0x19, 0xb4, 0x6c, 0x3b, 0x30, 0x6b, 0x4c, 0x29, 0x89, 0xb1, 0xa8, + 0x1d, 0x8b, 0xc7, 0xd1, 0x64, 0x2f, 0x0f, 0x35, 0x65, 0x64, 0xd7, 0x16, 0x97, 0xb5, 0x29, 0x2a, + 0xb6, 0x13, 0xda, 0x3d, 0xa4, 0x2f, 0xc8, 0x43, 0xa7, 0x34, 0x98, 0xce, 0x5d, 0xf8, 0x17, 0x5d, + 0xa1, 0x2d, 0x1b, 0x8e, 0xa3, 0x49, 0x9c, 0x3f, 0x58, 0x11, 0x1f, 0xfa, 0xbe, 0xb7, 0xd6, 0xa0, + 0x0d, 0xdb, 0x0d, 0x5f, 0x86, 0xda, 0x47, 0x81, 0x46, 0x98, 0x4a, 0x35, 0x92, 0x8d, 0x96, 0x51, + 0x7a, 0x7c, 0x7a, 0xff, 0xfb, 0xcf, 0xa7, 0x83, 0xab, 0xdb, 0xeb, 0xc3, 0x55, 0xee, 0x83, 0x13, + 0xf2, 0x68, 0x63, 0x06, 0x39, 0xa0, 0x35, 0x0d, 0x82, 0xf7, 0x40, 0xf8, 0xd2, 0x41, 0x23, 0x20, + 0x8c, 0x21, 0xce, 0xd7, 0xf8, 0x34, 0xf6, 0x1e, 0xc7, 0x35, 0xd9, 0x3e, 0x47, 0x49, 0x3f, 0x91, + 0xd1, 0x7a, 0x80, 0xcf, 0xb3, 0x7f, 0x6c, 0x26, 0xdb, 0xf8, 0x22, 0x79, 0xf9, 0x3f, 0xaa, 0x3e, + 0x48, 0xb2, 0xf3, 0xed, 0xf6, 0xfa, 0x30, 0x7a, 0xfb, 0xee, 0xd7, 0x3c, 0x8d, 0x6e, 0xe6, 0x69, + 0xf4, 0x67, 0x9e, 0x46, 0x3f, 0x16, 0xe9, 0xe0, 0x66, 0x91, 0x0e, 0x7e, 0x2f, 0xd2, 0xc1, 0xc7, + 0x37, 0x52, 0xb9, 0xcf, 0x5d, 0x99, 0x09, 0xa3, 0xf9, 0x6a, 0xd3, 0xaa, 0x14, 0x47, 0xd2, 0xf0, + 0xd9, 0xf4, 0x15, 0xd7, 0xa6, 0xea, 0x6a, 0x40, 0x7f, 0x50, 0xc8, 0x8f, 0x4f, 0x8e, 0xfc, 0x2d, + 0xb9, 0x4b, 0x0b, 0x58, 0x0e, 0xc3, 0x11, 0xbc, 0xfe, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x54, 0x14, + 0xab, 0xb4, 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 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // SendCall defines a rpc handler method for MsgSendCall. + SendCall(ctx context.Context, in *MsgSendCall, opts ...grpc.CallOption) (*MsgSendCallResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) SendCall(ctx context.Context, in *MsgSendCall, opts ...grpc.CallOption) (*MsgSendCallResponse, error) { + out := new(MsgSendCallResponse) + err := c.cc.Invoke(ctx, "/ibc.applications.gmp.v1.Msg/SendCall", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // SendCall defines a rpc handler method for MsgSendCall. + SendCall(context.Context, *MsgSendCall) (*MsgSendCallResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) SendCall(ctx context.Context, req *MsgSendCall) (*MsgSendCallResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SendCall not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_SendCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgSendCall) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).SendCall(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ibc.applications.gmp.v1.Msg/SendCall", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).SendCall(ctx, req.(*MsgSendCall)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "ibc.applications.gmp.v1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SendCall", + Handler: _Msg_SendCall_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "ibc/applications/gmp/v1/tx.proto", +} + +func (m *MsgSendCall) 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 *MsgSendCall) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSendCall) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Encoding) > 0 { + i -= len(m.Encoding) + copy(dAtA[i:], m.Encoding) + i = encodeVarintTx(dAtA, i, uint64(len(m.Encoding))) + i-- + dAtA[i] = 0x42 + } + if len(m.Memo) > 0 { + i -= len(m.Memo) + copy(dAtA[i:], m.Memo) + i = encodeVarintTx(dAtA, i, uint64(len(m.Memo))) + i-- + dAtA[i] = 0x3a + } + if m.TimeoutTimestamp != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.TimeoutTimestamp)) + i-- + dAtA[i] = 0x30 + } + if len(m.Payload) > 0 { + i -= len(m.Payload) + copy(dAtA[i:], m.Payload) + i = encodeVarintTx(dAtA, i, uint64(len(m.Payload))) + i-- + dAtA[i] = 0x2a + } + if len(m.Salt) > 0 { + i -= len(m.Salt) + copy(dAtA[i:], m.Salt) + i = encodeVarintTx(dAtA, i, uint64(len(m.Salt))) + i-- + dAtA[i] = 0x22 + } + if len(m.Receiver) > 0 { + i -= len(m.Receiver) + copy(dAtA[i:], m.Receiver) + i = encodeVarintTx(dAtA, i, uint64(len(m.Receiver))) + i-- + dAtA[i] = 0x1a + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x12 + } + if len(m.SourceClient) > 0 { + i -= len(m.SourceClient) + copy(dAtA[i:], m.SourceClient) + i = encodeVarintTx(dAtA, i, uint64(len(m.SourceClient))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgSendCallResponse) 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 *MsgSendCallResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSendCallResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Sequence != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Sequence)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgSendCall) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.SourceClient) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Receiver) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Salt) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Payload) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.TimeoutTimestamp != 0 { + n += 1 + sovTx(uint64(m.TimeoutTimestamp)) + } + l = len(m.Memo) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Encoding) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgSendCallResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Sequence != 0 { + n += 1 + sovTx(uint64(m.Sequence)) + } + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgSendCall) 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: MsgSendCall: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSendCall: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SourceClient", 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.SourceClient = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", 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.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Receiver", 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.Receiver = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Salt", 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.Salt = append(m.Salt[:0], dAtA[iNdEx:postIndex]...) + if m.Salt == nil { + m.Salt = []byte{} + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Payload", 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.Payload = append(m.Payload[:0], dAtA[iNdEx:postIndex]...) + if m.Payload == nil { + m.Payload = []byte{} + } + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TimeoutTimestamp", wireType) + } + m.TimeoutTimestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TimeoutTimestamp |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Memo", 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.Memo = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Encoding", 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.Encoding = string(dAtA[iNdEx:postIndex]) + 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 *MsgSendCallResponse) 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: MsgSendCallResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSendCallResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType) + } + m.Sequence = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Sequence |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + 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, ErrIntOverflowTx + } + 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, ErrIntOverflowTx + } + 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, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/modules/apps/transfer/types/msgs_test.go b/modules/apps/transfer/types/msgs_test.go index ad81198047e..33619e4ad8c 100644 --- a/modules/apps/transfer/types/msgs_test.go +++ b/modules/apps/transfer/types/msgs_test.go @@ -32,8 +32,6 @@ const ( invalidChannel = "(invalidchannel1)" invalidShortChannel = "invalid" invalidLongChannel = "invalidlongchannelinvalidlongchannelinvalidlongchannelinvalidlongchannel" - - invalidAddress = "invalid" ) var ( diff --git a/modules/light-clients/08-wasm/testing/simapp/app.go b/modules/light-clients/08-wasm/testing/simapp/app.go index af3134dd446..1baa11ead44 100644 --- a/modules/light-clients/08-wasm/testing/simapp/app.go +++ b/modules/light-clients/08-wasm/testing/simapp/app.go @@ -101,6 +101,9 @@ import ( "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/v10/blsverifier" ibcwasmkeeper "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/v10/keeper" ibcwasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/v10/types" + gmp "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp" + gmpkeeper "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/keeper" + gmptypes "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types" ica "github.com/cosmos/ibc-go/v10/modules/apps/27-interchain-accounts" icacontroller "github.com/cosmos/ibc-go/v10/modules/apps/27-interchain-accounts/controller" icacontrollerkeeper "github.com/cosmos/ibc-go/v10/modules/apps/27-interchain-accounts/controller/keeper" @@ -139,6 +142,7 @@ var ( govtypes.ModuleName: {authtypes.Burner}, ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, icatypes.ModuleName: nil, + gmptypes.ModuleName: nil, ibcmock.ModuleName: nil, } ) @@ -174,6 +178,7 @@ type SimApp struct { IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly ICAControllerKeeper *icacontrollerkeeper.Keeper ICAHostKeeper *icahostkeeper.Keeper + GMPKeeper *gmpkeeper.Keeper EvidenceKeeper evidencekeeper.Keeper TransferKeeper *ibctransferkeeper.Keeper WasmClientKeeper ibcwasmkeeper.Keeper @@ -295,7 +300,7 @@ func newSimApp( keys := storetypes.NewKVStoreKeys( authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, - govtypes.StoreKey, ibcexported.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, + govtypes.StoreKey, ibcexported.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, gmptypes.StoreKey, evidencetypes.StoreKey, ibctransfertypes.StoreKey, icacontrollertypes.StoreKey, icahosttypes.StoreKey, authzkeeper.StoreKey, consensusparamtypes.StoreKey, circuittypes.StoreKey, ibcwasmtypes.StoreKey, ) @@ -452,6 +457,15 @@ func newSimApp( app.GRPCQueryRouter(), authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) + // ICS-27 GMP keeper + app.GMPKeeper = gmpkeeper.NewKeeper( + appCodec, + runtime.NewKVStoreService(keys[gmptypes.ModuleName]), + app.AccountKeeper, + app.MsgServiceRouter(), + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + ) + // Create IBC Router ibcRouter := porttypes.NewRouter() ibcRouterV2 := ibcapi.NewRouter() @@ -524,6 +538,9 @@ func newSimApp( // register the transfer v2 module. ibcRouterV2.AddRoute(ibctransfertypes.PortID, transferv2.NewIBCModule(app.TransferKeeper)) + // Register the ICS-27 GMP module + ibcRouterV2.AddRoute(gmptypes.PortID, gmp.NewIBCModule(app.GMPKeeper)) + // Seal the IBC Routers. app.IBCKeeper.SetRouter(ibcRouter) app.IBCKeeper.SetRouterV2(ibcRouterV2) @@ -575,6 +592,7 @@ func newSimApp( ibc.NewAppModule(app.IBCKeeper), transfer.NewAppModule(app.TransferKeeper), ica.NewAppModule(app.ICAControllerKeeper, app.ICAHostKeeper), + gmp.NewAppModule(app.GMPKeeper), mockModule, // IBC light clients @@ -617,6 +635,7 @@ func newSimApp( genutiltypes.ModuleName, authz.ModuleName, icatypes.ModuleName, + gmptypes.ModuleName, ibcwasmtypes.ModuleName, ibcmock.ModuleName, ) @@ -628,6 +647,7 @@ func newSimApp( genutiltypes.ModuleName, feegrant.ModuleName, icatypes.ModuleName, + gmptypes.ModuleName, ibcwasmtypes.ModuleName, ibcmock.ModuleName, ) @@ -640,7 +660,7 @@ func newSimApp( banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName, slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, ibcexported.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName, ibctransfertypes.ModuleName, - icatypes.ModuleName, ibcmock.ModuleName, feegrant.ModuleName, upgradetypes.ModuleName, + icatypes.ModuleName, ibcmock.ModuleName, feegrant.ModuleName, upgradetypes.ModuleName, gmptypes.ModuleName, vestingtypes.ModuleName, consensusparamtypes.ModuleName, circuittypes.ModuleName, ibcwasmtypes.ModuleName, } app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...) diff --git a/proto/ibc/applications/gmp/v1/account.proto b/proto/ibc/applications/gmp/v1/account.proto new file mode 100644 index 00000000000..ce1680f3d24 --- /dev/null +++ b/proto/ibc/applications/gmp/v1/account.proto @@ -0,0 +1,29 @@ +syntax = "proto3"; + +package ibc.applications.gmp.v1; + +option go_package = "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types"; + +import "google/protobuf/any.proto"; +import "cosmos_proto/cosmos.proto"; + +// AccountIdentifier is used to identify a ICS27 account. +message AccountIdentifier { + // The (local) client identifier + string client_id = 1; + // The sender of the packet + string sender = 2; + // The salt of the packet + bytes salt = 3; +} + +// An ICS27Account is defined as a BaseAccount & the account identifier +message ICS27Account { + string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + AccountIdentifier account_id = 2; +} + +// CosmosTx contains a list of sdk.Msg's. It should be used when sending transactions to an SDK host chain. +message CosmosTx { + repeated google.protobuf.Any messages = 1; +} diff --git a/proto/ibc/applications/gmp/v1/genesis.proto b/proto/ibc/applications/gmp/v1/genesis.proto new file mode 100644 index 00000000000..8a0e2d04601 --- /dev/null +++ b/proto/ibc/applications/gmp/v1/genesis.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; + +package ibc.applications.gmp.v1; + +option go_package = "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types"; + +import "ibc/applications/gmp/v1/account.proto"; +import "gogoproto/gogo.proto"; + +// GenesisState defines the 27-gmp genesis state +message GenesisState { + // The list of registered ICS27 accounts + repeated RegisteredICS27Account ics27_accounts = 2 [(gogoproto.nullable) = false]; +} + +// RegisteredICS27Account contains an account identifier and associated interchain account address +message RegisteredICS27Account { + /// The address of the ics27 account + string account_address = 1; + /// The account identifier + AccountIdentifier account_id = 2 [(gogoproto.nullable) = false]; +} diff --git a/proto/ibc/applications/gmp/v1/packet.proto b/proto/ibc/applications/gmp/v1/packet.proto new file mode 100644 index 00000000000..43ede2a576f --- /dev/null +++ b/proto/ibc/applications/gmp/v1/packet.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; + +package ibc.applications.gmp.v1; + +option go_package = "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types"; + +// GMPPacketData defines a struct for the packet payload +message GMPPacketData { + // the sender address + string sender = 1; + // the recipient address on the destination chain + string receiver = 2; + // The salt used to generate the caller account address + bytes salt = 3; + // The payload of the call + bytes payload = 4; + // optional memo + string memo = 5; +} + +// Acknowledgement defines a struct for the ICS27-2 acknowledgement +message Acknowledgement { + // The result of the call + bytes result = 1; +} diff --git a/proto/ibc/applications/gmp/v1/query.proto b/proto/ibc/applications/gmp/v1/query.proto new file mode 100644 index 00000000000..3532e8ecaad --- /dev/null +++ b/proto/ibc/applications/gmp/v1/query.proto @@ -0,0 +1,32 @@ +syntax = "proto3"; + +package ibc.applications.gmp.v1; + +import "google/api/annotations.proto"; + +option go_package = "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types"; + +// Query provides defines the gRPC querier service. +service Query { + // AccountAddress queries the interchain account address for a given client_id, sender, and salt. + // If the account is not registered, the address is computed deterministically + rpc AccountAddress(QueryAccountAddressRequest) returns (QueryAccountAddressResponse) { + option (google.api.http).get = "/ibc/apps/gmp/v1/clients/{client_id}/accounts/{sender}/{salt=**}"; + } +} + +// QueryAccountAddressRequest is the request type for the Query/AccountAddress RPC method. +message QueryAccountAddressRequest { + // The (local) client identifier + string client_id = 1; + // The sender of the packet + string sender = 2; + // The salt of the packet (in hex format) + string salt = 3; +} + +// QueryAccountAddressResponse is the response type for the Query/AccountAddress RPC method. +message QueryAccountAddressResponse { + // The interchain account address + string account_address = 1; +} diff --git a/proto/ibc/applications/gmp/v1/tx.proto b/proto/ibc/applications/gmp/v1/tx.proto new file mode 100644 index 00000000000..d3942230f51 --- /dev/null +++ b/proto/ibc/applications/gmp/v1/tx.proto @@ -0,0 +1,48 @@ +syntax = "proto3"; + +package ibc.applications.gmp.v1; + +option go_package = "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types"; + +import "gogoproto/gogo.proto"; +import "cosmos/msg/v1/msg.proto"; + +// Msg defines the ibc/gmp Msg service. +service Msg { + option (cosmos.msg.v1.service) = true; + + // SendCall defines a rpc handler method for MsgSendCall. + rpc SendCall(MsgSendCall) returns (MsgSendCallResponse); +} + +// MsgSendCall defines a msg to send a call to a contract/receiver on a ICS27-2 enabled chain. +message MsgSendCall { + option (cosmos.msg.v1.signer) = "sender"; + + option (gogoproto.goproto_getters) = false; + + // the client by which the packet will be sent + string source_client = 1; + // the sender address + string sender = 2; + // the recipient address on the destination chain + string receiver = 3; + // The salt used to generate the caller account address + bytes salt = 4; + // The payload of the call + bytes payload = 5; + // Timeout timestamp in absolute nanoseconds since unix epoch. + uint64 timeout_timestamp = 6; + // optional memo + string memo = 7; + // optional encoding + string encoding = 8; +} + +// MsgSendCallResponse defines the Msg/SendCall response type. +message MsgSendCallResponse { + option (gogoproto.goproto_getters) = false; + + // sequence number of the GMP packet sent + uint64 sequence = 1; +} diff --git a/testing/simapp/app.go b/testing/simapp/app.go index c65d894a895..c9807a847f3 100644 --- a/testing/simapp/app.go +++ b/testing/simapp/app.go @@ -78,6 +78,9 @@ import ( abci "github.com/cometbft/cometbft/abci/types" + gmp "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp" + gmpkeeper "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/keeper" + gmptypes "github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types" ica "github.com/cosmos/ibc-go/v10/modules/apps/27-interchain-accounts" icacontroller "github.com/cosmos/ibc-go/v10/modules/apps/27-interchain-accounts/controller" icacontrollerkeeper "github.com/cosmos/ibc-go/v10/modules/apps/27-interchain-accounts/controller/keeper" @@ -123,6 +126,7 @@ var ( govtypes.ModuleName: {authtypes.Burner}, ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, icatypes.ModuleName: nil, + gmptypes.ModuleName: nil, ibcmock.ModuleName: nil, } ) @@ -155,6 +159,7 @@ type SimApp struct { IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly ICAControllerKeeper *icacontrollerkeeper.Keeper ICAHostKeeper *icahostkeeper.Keeper + GMPKeeper *gmpkeeper.Keeper TransferKeeper *ibctransferkeeper.Keeper ConsensusParamsKeeper consensusparamkeeper.Keeper PFMKeeper *packetforwardkeeper.Keeper @@ -250,7 +255,7 @@ func NewSimApp( keys := storetypes.NewKVStoreKeys( authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, - govtypes.StoreKey, ibcexported.StoreKey, upgradetypes.StoreKey, + govtypes.StoreKey, ibcexported.StoreKey, upgradetypes.StoreKey, gmptypes.StoreKey, packetforwardtypes.StoreKey, ibctransfertypes.StoreKey, icacontrollertypes.StoreKey, icahosttypes.StoreKey, authzkeeper.StoreKey, consensusparamtypes.StoreKey, ratelimittypes.StoreKey, @@ -354,6 +359,15 @@ func NewSimApp( authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) + // ICS-27 GMP keeper + app.GMPKeeper = gmpkeeper.NewKeeper( + appCodec, + runtime.NewKVStoreService(keys[gmptypes.ModuleName]), + app.AccountKeeper, + app.MsgServiceRouter(), + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + ) + // Create IBC Router ibcRouter := porttypes.NewRouter() ibcRouterV2 := ibcapi.NewRouter() @@ -449,6 +463,9 @@ func NewSimApp( // register the transfer v2 module. ibcRouterV2.AddRoute(ibctransfertypes.PortID, transferv2.NewIBCModule(app.TransferKeeper)) + // Register the ICS-27 GMP module + ibcRouterV2.AddRoute(gmptypes.PortID, gmp.NewIBCModule(app.GMPKeeper)) + // Seal the IBC Router app.IBCKeeper.SetRouter(ibcRouter) app.IBCKeeper.SetRouterV2(ibcRouterV2) @@ -488,6 +505,7 @@ func NewSimApp( transfer.NewAppModule(app.TransferKeeper), ratelimiting.NewAppModule(app.RateLimitKeeper), ica.NewAppModule(app.ICAControllerKeeper, app.ICAHostKeeper), + gmp.NewAppModule(app.GMPKeeper), mockModule, packetforward.NewAppModule(app.PFMKeeper), @@ -530,6 +548,7 @@ func NewSimApp( genutiltypes.ModuleName, authz.ModuleName, icatypes.ModuleName, + gmptypes.ModuleName, ratelimittypes.ModuleName, ibcmock.ModuleName, ) @@ -541,6 +560,7 @@ func NewSimApp( packetforwardtypes.ModuleName, genutiltypes.ModuleName, icatypes.ModuleName, + gmptypes.ModuleName, ibcmock.ModuleName, ) @@ -552,7 +572,7 @@ func NewSimApp( banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName, slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, ibcexported.ModuleName, genutiltypes.ModuleName, authz.ModuleName, ibctransfertypes.ModuleName, ratelimittypes.ModuleName, - packetforwardtypes.ModuleName, icatypes.ModuleName, ibcmock.ModuleName, upgradetypes.ModuleName, + packetforwardtypes.ModuleName, icatypes.ModuleName, ibcmock.ModuleName, upgradetypes.ModuleName, gmptypes.ModuleName, vestingtypes.ModuleName, consensusparamtypes.ModuleName, } app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...)