From e67939efd569f885e1917950327ee92bf6732c88 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Tue, 18 Aug 2026 13:36:59 +0100 Subject: [PATCH 1/5] Deprecate IBC write handlers Now that IBC in/outbound is disabled as part of SIP-3: - reject all IBC client, connection, and channel messages - reject IBC transfer messages - reject IBC client governance proposals - return stable module deprecation errors - add coverage for every deprecated write handler --- .../apps/transfer/keeper/msg_server.go | 39 +- .../apps/transfer/keeper/msg_server_test.go | 17 + .../modules/apps/transfer/types/errors.go | 2 + .../core/02-client/proposal_handler.go | 11 +- .../core/02-client/proposal_handler_test.go | 25 + .../modules/core/02-client/types/errors.go | 2 + sei-ibc-go/modules/core/keeper/msg_server.go | 701 ++---------------- .../modules/core/keeper/msg_server_test.go | 38 + sei-ibc-go/modules/core/types/errors.go | 2 + 9 files changed, 147 insertions(+), 690 deletions(-) create mode 100644 sei-ibc-go/modules/apps/transfer/keeper/msg_server_test.go create mode 100644 sei-ibc-go/modules/core/02-client/proposal_handler_test.go create mode 100644 sei-ibc-go/modules/core/keeper/msg_server_test.go diff --git a/sei-ibc-go/modules/apps/transfer/keeper/msg_server.go b/sei-ibc-go/modules/apps/transfer/keeper/msg_server.go index be0da16973..893a1381c6 100644 --- a/sei-ibc-go/modules/apps/transfer/keeper/msg_server.go +++ b/sei-ibc-go/modules/apps/transfer/keeper/msg_server.go @@ -3,45 +3,12 @@ package keeper import ( "context" - sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" - "github.com/sei-protocol/seilog" - "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/apps/transfer/types" ) -var logger = seilog.NewLogger("ibc-go", "modules", "apps", "transfer", "keeper") - var _ types.MsgServer = Keeper{} -// Transfer defines a rpc handler method for MsgTransfer. -func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - sender, err := sdk.AccAddressFromBech32(msg.Sender) - if err != nil { - return nil, err - } - - sequence, err := k.sendTransfer( - ctx, msg.SourcePort, msg.SourceChannel, msg.Token, sender, msg.Receiver, msg.TimeoutHeight, msg.TimeoutTimestamp, - msg.Memo) - if err != nil { - return nil, err - } - - logger.Info("IBC fungible token transfer", "token", msg.Token.Denom, "amount", msg.Token.Amount, "sender", msg.Sender, "receiver", msg.Receiver) - - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeTransfer, - sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), - sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), - ), - }) - - return &types.MsgTransferResponse{Sequence: sequence}, nil +// Transfer defines an RPC handler for MsgTransfer. +func (Keeper) Transfer(context.Context, *types.MsgTransfer) (*types.MsgTransferResponse, error) { + return nil, types.ErrTransferDeprecated } diff --git a/sei-ibc-go/modules/apps/transfer/keeper/msg_server_test.go b/sei-ibc-go/modules/apps/transfer/keeper/msg_server_test.go new file mode 100644 index 0000000000..8fd5c25ea9 --- /dev/null +++ b/sei-ibc-go/modules/apps/transfer/keeper/msg_server_test.go @@ -0,0 +1,17 @@ +package keeper + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/apps/transfer/types" +) + +func TestDeprecatedMessages(t *testing.T) { + response, err := (Keeper{}).Transfer(context.Background(), &types.MsgTransfer{}) + + require.Nil(t, response) + require.ErrorIs(t, err, types.ErrTransferDeprecated) +} diff --git a/sei-ibc-go/modules/apps/transfer/types/errors.go b/sei-ibc-go/modules/apps/transfer/types/errors.go index 13f12d862a..51e23d8045 100644 --- a/sei-ibc-go/modules/apps/transfer/types/errors.go +++ b/sei-ibc-go/modules/apps/transfer/types/errors.go @@ -15,4 +15,6 @@ var ( ErrReceiveDisabled = sdkerrors.Register(ModuleName, 8, "fungible token transfers to this chain are disabled") ErrMaxTransferChannels = sdkerrors.Register(ModuleName, 9, "max transfer channels") ErrInvalidMemo = sdkerrors.Register(ModuleName, 10, "invalid memo") + // ErrTransferDeprecated is returned by every transfer message handler. + ErrTransferDeprecated = sdkerrors.Register(ModuleName, 11, "transfer module is deprecated") ) diff --git a/sei-ibc-go/modules/core/02-client/proposal_handler.go b/sei-ibc-go/modules/core/02-client/proposal_handler.go index 913cccacf4..2b789c113b 100644 --- a/sei-ibc-go/modules/core/02-client/proposal_handler.go +++ b/sei-ibc-go/modules/core/02-client/proposal_handler.go @@ -10,14 +10,11 @@ import ( ) // NewClientProposalHandler defines the 02-client proposal handler -func NewClientProposalHandler(k keeper.Keeper) govtypes.Handler { - return func(ctx sdk.Context, content govtypes.Content) error { +func NewClientProposalHandler(_ keeper.Keeper) govtypes.Handler { + return func(_ sdk.Context, content govtypes.Content) error { switch c := content.(type) { - case *types.ClientUpdateProposal: - return k.ClientUpdateProposal(ctx, c) - case *types.UpgradeProposal: - return k.HandleUpgradeProposal(ctx, c) - + case *types.ClientUpdateProposal, *types.UpgradeProposal: + return types.ErrClientDeprecated default: return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized ibc proposal content type: %T", c) } diff --git a/sei-ibc-go/modules/core/02-client/proposal_handler_test.go b/sei-ibc-go/modules/core/02-client/proposal_handler_test.go new file mode 100644 index 0000000000..6b0567c52e --- /dev/null +++ b/sei-ibc-go/modules/core/02-client/proposal_handler_test.go @@ -0,0 +1,25 @@ +package client + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" + govtypes "github.com/sei-protocol/sei-chain/sei-cosmos/x/gov/types" + + "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/keeper" + "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/types" +) + +func TestDeprecatedClientProposals(t *testing.T) { + handler := NewClientProposalHandler(keeper.Keeper{}) + proposals := []govtypes.Content{ + &types.ClientUpdateProposal{}, + &types.UpgradeProposal{}, + } + + for _, proposal := range proposals { + require.ErrorIs(t, handler(sdk.Context{}, proposal), types.ErrClientDeprecated) + } +} diff --git a/sei-ibc-go/modules/core/02-client/types/errors.go b/sei-ibc-go/modules/core/02-client/types/errors.go index 82dc8344d6..19588eef0f 100644 --- a/sei-ibc-go/modules/core/02-client/types/errors.go +++ b/sei-ibc-go/modules/core/02-client/types/errors.go @@ -34,4 +34,6 @@ var ( ErrInvalidSubstitute = sdkerrors.Register(SubModuleName, 27, "invalid client state substitute") ErrInvalidUpgradeProposal = sdkerrors.Register(SubModuleName, 28, "invalid upgrade proposal") ErrClientNotActive = sdkerrors.Register(SubModuleName, 29, "client is not active") + // ErrClientDeprecated is returned by IBC client proposal handlers. + ErrClientDeprecated = sdkerrors.Register(SubModuleName, 30, "ibc client module is deprecated") ) diff --git a/sei-ibc-go/modules/core/keeper/msg_server.go b/sei-ibc-go/modules/core/keeper/msg_server.go index 35e580cf2b..b3b9691608 100644 --- a/sei-ibc-go/modules/core/keeper/msg_server.go +++ b/sei-ibc-go/modules/core/keeper/msg_server.go @@ -3,18 +3,9 @@ package keeper import ( "context" - metrics "github.com/armon/go-metrics" - - "github.com/sei-protocol/sei-chain/sei-cosmos/telemetry" - sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" - sdkerrors "github.com/sei-protocol/sei-chain/sei-cosmos/types/errors" - "go.opentelemetry.io/otel/attribute" - otelmetric "go.opentelemetry.io/otel/metric" - clienttypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/types" connectiontypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/03-connection/types" channeltypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/04-channel/types" - porttypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/05-port/types" coretypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/types" ) @@ -24,676 +15,92 @@ var ( _ channeltypes.MsgServer = Keeper{} ) -// CreateClient defines a rpc handler method for MsgCreateClient. -func (k Keeper) CreateClient(goCtx context.Context, msg *clienttypes.MsgCreateClient) (*clienttypes.MsgCreateClientResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - clientState, err := clienttypes.UnpackClientState(msg.ClientState) - if err != nil { - return nil, err - } - - consensusState, err := clienttypes.UnpackConsensusState(msg.ConsensusState) - if err != nil { - return nil, err - } - - if _, err = k.ClientKeeper.CreateClient(ctx, clientState, consensusState); err != nil { - return nil, err - } - - return &clienttypes.MsgCreateClientResponse{}, nil +// CreateClient defines an RPC handler for MsgCreateClient. +func (Keeper) CreateClient(context.Context, *clienttypes.MsgCreateClient) (*clienttypes.MsgCreateClientResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// UpdateClient defines a rpc handler method for MsgUpdateClient. -func (k Keeper) UpdateClient(goCtx context.Context, msg *clienttypes.MsgUpdateClient) (*clienttypes.MsgUpdateClientResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - header, err := clienttypes.UnpackHeader(msg.Header) - if err != nil { - return nil, err - } - - if err = k.ClientKeeper.UpdateClient(ctx, msg.ClientId, header); err != nil { - return nil, err - } - - return &clienttypes.MsgUpdateClientResponse{}, nil +// UpdateClient defines an RPC handler for MsgUpdateClient. +func (Keeper) UpdateClient(context.Context, *clienttypes.MsgUpdateClient) (*clienttypes.MsgUpdateClientResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// UpgradeClient defines a rpc handler method for MsgUpgradeClient. -func (k Keeper) UpgradeClient(goCtx context.Context, msg *clienttypes.MsgUpgradeClient) (*clienttypes.MsgUpgradeClientResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - upgradedClient, err := clienttypes.UnpackClientState(msg.ClientState) - if err != nil { - return nil, err - } - upgradedConsState, err := clienttypes.UnpackConsensusState(msg.ConsensusState) - if err != nil { - return nil, err - } - - if err = k.ClientKeeper.UpgradeClient(ctx, msg.ClientId, upgradedClient, upgradedConsState, - msg.ProofUpgradeClient, msg.ProofUpgradeConsensusState); err != nil { - return nil, err - } - - return &clienttypes.MsgUpgradeClientResponse{}, nil +// UpgradeClient defines an RPC handler for MsgUpgradeClient. +func (Keeper) UpgradeClient(context.Context, *clienttypes.MsgUpgradeClient) (*clienttypes.MsgUpgradeClientResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour. -func (k Keeper) SubmitMisbehaviour(goCtx context.Context, msg *clienttypes.MsgSubmitMisbehaviour) (*clienttypes.MsgSubmitMisbehaviourResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - misbehaviour, err := clienttypes.UnpackMisbehaviour(msg.Misbehaviour) - if err != nil { - return nil, err - } - - if err := k.ClientKeeper.CheckMisbehaviourAndUpdateState(ctx, misbehaviour); err != nil { - return nil, sdkerrors.Wrap(err, "failed to process misbehaviour for IBC client") - } - - return &clienttypes.MsgSubmitMisbehaviourResponse{}, nil +// SubmitMisbehaviour defines an RPC handler for MsgSubmitMisbehaviour. +func (Keeper) SubmitMisbehaviour(context.Context, *clienttypes.MsgSubmitMisbehaviour) (*clienttypes.MsgSubmitMisbehaviourResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// ConnectionOpenInit defines a rpc handler method for MsgConnectionOpenInit. -func (k Keeper) ConnectionOpenInit(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenInit) (*connectiontypes.MsgConnectionOpenInitResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - // outbound gating: disallow outbound connection inits when outbound disabled - if !k.IsOutboundEnabled(ctx) { - return nil, sdkerrors.Wrap(coretypes.ErrOutboundDisabled, "connection outbound disabled") - } - - if _, err := k.ConnectionKeeper.ConnOpenInit(ctx, msg.ClientId, msg.Counterparty, msg.Version, msg.DelayPeriod); err != nil { - return nil, sdkerrors.Wrap(err, "connection handshake open init failed") - } - - return &connectiontypes.MsgConnectionOpenInitResponse{}, nil +// ConnectionOpenInit defines an RPC handler for MsgConnectionOpenInit. +func (Keeper) ConnectionOpenInit(context.Context, *connectiontypes.MsgConnectionOpenInit) (*connectiontypes.MsgConnectionOpenInitResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// ConnectionOpenTry defines a rpc handler method for MsgConnectionOpenTry. -func (k Keeper) ConnectionOpenTry(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenTry) (*connectiontypes.MsgConnectionOpenTryResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - if !k.IsInboundEnabled(ctx) { - return nil, sdkerrors.Wrap(coretypes.ErrInboundDisabled, "connection inbound disabled") - } - - targetClient, err := clienttypes.UnpackClientState(msg.ClientState) - if err != nil { - return nil, err - } - - if _, err := k.ConnectionKeeper.ConnOpenTry( - ctx, msg.PreviousConnectionId, msg.Counterparty, msg.DelayPeriod, msg.ClientId, targetClient, - connectiontypes.ProtoVersionsToExported(msg.CounterpartyVersions), msg.ProofInit, msg.ProofClient, msg.ProofConsensus, - msg.ProofHeight, msg.ConsensusHeight, - ); err != nil { - return nil, sdkerrors.Wrap(err, "connection handshake open try failed") - } - - return &connectiontypes.MsgConnectionOpenTryResponse{}, nil +// ConnectionOpenTry defines an RPC handler for MsgConnectionOpenTry. +func (Keeper) ConnectionOpenTry(context.Context, *connectiontypes.MsgConnectionOpenTry) (*connectiontypes.MsgConnectionOpenTryResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// ConnectionOpenAck defines a rpc handler method for MsgConnectionOpenAck. -func (k Keeper) ConnectionOpenAck(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenAck) (*connectiontypes.MsgConnectionOpenAckResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - targetClient, err := clienttypes.UnpackClientState(msg.ClientState) - if err != nil { - return nil, err - } - - if err := k.ConnectionKeeper.ConnOpenAck( - ctx, msg.ConnectionId, targetClient, msg.Version, msg.CounterpartyConnectionId, - msg.ProofTry, msg.ProofClient, msg.ProofConsensus, - msg.ProofHeight, msg.ConsensusHeight, - ); err != nil { - return nil, sdkerrors.Wrap(err, "connection handshake open ack failed") - } - - return &connectiontypes.MsgConnectionOpenAckResponse{}, nil +// ConnectionOpenAck defines an RPC handler for MsgConnectionOpenAck. +func (Keeper) ConnectionOpenAck(context.Context, *connectiontypes.MsgConnectionOpenAck) (*connectiontypes.MsgConnectionOpenAckResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// ConnectionOpenConfirm defines a rpc handler method for MsgConnectionOpenConfirm. -func (k Keeper) ConnectionOpenConfirm(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenConfirm) (*connectiontypes.MsgConnectionOpenConfirmResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - if err := k.ConnectionKeeper.ConnOpenConfirm( - ctx, msg.ConnectionId, msg.ProofAck, msg.ProofHeight, - ); err != nil { - return nil, sdkerrors.Wrap(err, "connection handshake open confirm failed") - } - - return &connectiontypes.MsgConnectionOpenConfirmResponse{}, nil +// ConnectionOpenConfirm defines an RPC handler for MsgConnectionOpenConfirm. +func (Keeper) ConnectionOpenConfirm(context.Context, *connectiontypes.MsgConnectionOpenConfirm) (*connectiontypes.MsgConnectionOpenConfirmResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// ChannelOpenInit defines a rpc handler method for MsgChannelOpenInit. -// ChannelOpenInit will perform 04-channel checks, route to the application -// callback, and write an OpenInit channel into state upon successful execution. -func (k Keeper) ChannelOpenInit(goCtx context.Context, msg *channeltypes.MsgChannelOpenInit) (*channeltypes.MsgChannelOpenInitResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - // outbound gating: disallow outbound channel inits when outbound disabled - if !k.IsOutboundEnabled(ctx) { - return nil, sdkerrors.Wrap(coretypes.ErrOutboundDisabled, "channel outbound disabled") - } - - // Lookup module by port capability - module, portCap, err := k.PortKeeper.LookupModuleByPort(ctx, msg.PortId) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve application callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - // Perform 04-channel verification - channelID, cap, err := k.ChannelKeeper.ChanOpenInit( - ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, - portCap, msg.Channel.Counterparty, msg.Channel.Version, - ) - if err != nil { - return nil, sdkerrors.Wrap(err, "channel handshake open init failed") - } - - // Perform application logic callback - if err = cbs.OnChanOpenInit(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, channelID, cap, msg.Channel.Counterparty, msg.Channel.Version); err != nil { - return nil, sdkerrors.Wrap(err, "channel open init callback failed") - } - - // Write channel into state - k.ChannelKeeper.WriteOpenInitChannel(ctx, msg.PortId, channelID, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.Channel.Counterparty, msg.Channel.Version) - - return &channeltypes.MsgChannelOpenInitResponse{ - ChannelId: channelID, - Version: msg.Channel.Version, - }, nil +// ChannelOpenInit defines an RPC handler for MsgChannelOpenInit. +func (Keeper) ChannelOpenInit(context.Context, *channeltypes.MsgChannelOpenInit) (*channeltypes.MsgChannelOpenInitResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// ChannelOpenTry defines a rpc handler method for MsgChannelOpenTry. -// ChannelOpenTry will perform 04-channel checks, route to the application -// callback, and write an OpenTry channel into state upon successful execution. -func (k Keeper) ChannelOpenTry(goCtx context.Context, msg *channeltypes.MsgChannelOpenTry) (*channeltypes.MsgChannelOpenTryResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - if !k.IsInboundEnabled(ctx) { - return nil, sdkerrors.Wrap(coretypes.ErrInboundDisabled, "channel inbound disabled") - } - - // Lookup module by port capability - module, portCap, err := k.PortKeeper.LookupModuleByPort(ctx, msg.PortId) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve application callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - // Perform 04-channel verification - channelID, cap, err := k.ChannelKeeper.ChanOpenTry(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, msg.PreviousChannelId, - portCap, msg.Channel.Counterparty, msg.CounterpartyVersion, msg.ProofInit, msg.ProofHeight, - ) - if err != nil { - return nil, sdkerrors.Wrap(err, "channel handshake open try failed") - } - - // Perform application logic callback - version, err := cbs.OnChanOpenTry(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, channelID, cap, msg.Channel.Counterparty, msg.CounterpartyVersion) - if err != nil { - return nil, sdkerrors.Wrap(err, "channel open try callback failed") - } - - // Write channel into state - k.ChannelKeeper.WriteOpenTryChannel(ctx, msg.PortId, channelID, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.Channel.Counterparty, version) - - return &channeltypes.MsgChannelOpenTryResponse{ - Version: version, - }, nil +// ChannelOpenTry defines an RPC handler for MsgChannelOpenTry. +func (Keeper) ChannelOpenTry(context.Context, *channeltypes.MsgChannelOpenTry) (*channeltypes.MsgChannelOpenTryResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// ChannelOpenAck defines a rpc handler method for MsgChannelOpenAck. -// ChannelOpenAck will perform 04-channel checks, route to the application -// callback, and write an OpenAck channel into state upon successful execution. -func (k Keeper) ChannelOpenAck(goCtx context.Context, msg *channeltypes.MsgChannelOpenAck) (*channeltypes.MsgChannelOpenAckResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - // Lookup module by channel capability - module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve application callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - // Perform 04-channel verification - if err = k.ChannelKeeper.ChanOpenAck( - ctx, msg.PortId, msg.ChannelId, cap, msg.CounterpartyVersion, msg.CounterpartyChannelId, msg.ProofTry, msg.ProofHeight, - ); err != nil { - return nil, sdkerrors.Wrap(err, "channel handshake open ack failed") - } - - // Perform application logic callback - if err = cbs.OnChanOpenAck(ctx, msg.PortId, msg.ChannelId, msg.CounterpartyChannelId, msg.CounterpartyVersion); err != nil { - return nil, sdkerrors.Wrap(err, "channel open ack callback failed") - } - - // Write channel into state - k.ChannelKeeper.WriteOpenAckChannel(ctx, msg.PortId, msg.ChannelId, msg.CounterpartyVersion, msg.CounterpartyChannelId) - - return &channeltypes.MsgChannelOpenAckResponse{}, nil +// ChannelOpenAck defines an RPC handler for MsgChannelOpenAck. +func (Keeper) ChannelOpenAck(context.Context, *channeltypes.MsgChannelOpenAck) (*channeltypes.MsgChannelOpenAckResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// ChannelOpenConfirm defines a rpc handler method for MsgChannelOpenConfirm. -// ChannelOpenConfirm will perform 04-channel checks, route to the application -// callback, and write an OpenConfirm channel into state upon successful execution. -func (k Keeper) ChannelOpenConfirm(goCtx context.Context, msg *channeltypes.MsgChannelOpenConfirm) (*channeltypes.MsgChannelOpenConfirmResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - // Lookup module by channel capability - module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve application callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - // Perform 04-channel verification - if err = k.ChannelKeeper.ChanOpenConfirm(ctx, msg.PortId, msg.ChannelId, cap, msg.ProofAck, msg.ProofHeight); err != nil { - return nil, sdkerrors.Wrap(err, "channel handshake open confirm failed") - } - - // Perform application logic callback - if err = cbs.OnChanOpenConfirm(ctx, msg.PortId, msg.ChannelId); err != nil { - return nil, sdkerrors.Wrap(err, "channel open confirm callback failed") - } - - // Write channel into state - k.ChannelKeeper.WriteOpenConfirmChannel(ctx, msg.PortId, msg.ChannelId) - - return &channeltypes.MsgChannelOpenConfirmResponse{}, nil +// ChannelOpenConfirm defines an RPC handler for MsgChannelOpenConfirm. +func (Keeper) ChannelOpenConfirm(context.Context, *channeltypes.MsgChannelOpenConfirm) (*channeltypes.MsgChannelOpenConfirmResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// ChannelCloseInit defines a rpc handler method for MsgChannelCloseInit. -func (k Keeper) ChannelCloseInit(goCtx context.Context, msg *channeltypes.MsgChannelCloseInit) (*channeltypes.MsgChannelCloseInitResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - // Lookup module by channel capability - module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - if err = cbs.OnChanCloseInit(ctx, msg.PortId, msg.ChannelId); err != nil { - return nil, sdkerrors.Wrap(err, "channel close init callback failed") - } - - err = k.ChannelKeeper.ChanCloseInit(ctx, msg.PortId, msg.ChannelId, cap) - if err != nil { - return nil, sdkerrors.Wrap(err, "channel handshake close init failed") - } - - return &channeltypes.MsgChannelCloseInitResponse{}, nil +// ChannelCloseInit defines an RPC handler for MsgChannelCloseInit. +func (Keeper) ChannelCloseInit(context.Context, *channeltypes.MsgChannelCloseInit) (*channeltypes.MsgChannelCloseInitResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// ChannelCloseConfirm defines a rpc handler method for MsgChannelCloseConfirm. -func (k Keeper) ChannelCloseConfirm(goCtx context.Context, msg *channeltypes.MsgChannelCloseConfirm) (*channeltypes.MsgChannelCloseConfirmResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - // Lookup module by channel capability - module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - if err = cbs.OnChanCloseConfirm(ctx, msg.PortId, msg.ChannelId); err != nil { - return nil, sdkerrors.Wrap(err, "channel close confirm callback failed") - } - - err = k.ChannelKeeper.ChanCloseConfirm(ctx, msg.PortId, msg.ChannelId, cap, msg.ProofInit, msg.ProofHeight) - if err != nil { - return nil, sdkerrors.Wrap(err, "channel handshake close confirm failed") - } - - return &channeltypes.MsgChannelCloseConfirmResponse{}, nil +// ChannelCloseConfirm defines an RPC handler for MsgChannelCloseConfirm. +func (Keeper) ChannelCloseConfirm(context.Context, *channeltypes.MsgChannelCloseConfirm) (*channeltypes.MsgChannelCloseConfirmResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// RecvPacket defines a rpc handler method for MsgRecvPacket. -func (k Keeper) RecvPacket(goCtx context.Context, msg *channeltypes.MsgRecvPacket) (*channeltypes.MsgRecvPacketResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - if !k.IsInboundEnabled(ctx) { - return nil, sdkerrors.Wrap(coretypes.ErrInboundDisabled, "recv packet disabled") - } - - relayer, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return nil, sdkerrors.Wrap(err, "Invalid address for msg Signer") - } - - // Lookup module by channel capability - module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.DestinationPort, msg.Packet.DestinationChannel) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - // Perform TAO verification - // - // If the packet was already received, perform a no-op - // Use a cached context to prevent accidental state changes - cacheCtx, writeFn := ctx.CacheContext() - err = k.ChannelKeeper.RecvPacket(cacheCtx, cap, msg.Packet, msg.ProofCommitment, msg.ProofHeight) - - // NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context. - ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events()) - - switch err { - case nil: - writeFn() - case channeltypes.ErrNoOpMsg: - return &channeltypes.MsgRecvPacketResponse{Result: channeltypes.NOOP}, nil - default: - return nil, sdkerrors.Wrap(err, "receive packet verification failed") - } - - // Perform application logic callback - // - // Cache context so that we may discard state changes from callback if the acknowledgement is unsuccessful. - cacheCtx, writeFn = ctx.CacheContext() - ack := cbs.OnRecvPacket(cacheCtx, msg.Packet, relayer) - if ack == nil || ack.Success() { - // write application state changes for asynchronous and successful acknowledgements - writeFn() - // NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context. - // Events from callback are emitted regardless of acknowledgement success - ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events()) - } - - // Set packet acknowledgement only if the acknowledgement is not nil. - // NOTE: IBC applications modules may call the WriteAcknowledgement asynchronously if the - // acknowledgement is nil. - if ack != nil { - if err := k.ChannelKeeper.WriteAcknowledgement(ctx, cap, msg.Packet, ack); err != nil { - return nil, err - } - } - - defer func() { - ibcCoreMetrics.txMsgIbcRecvPacket.Add(ctx.Context(), 1, otelmetric.WithAttributes( - attribute.String(coretypes.LabelSourcePort, msg.Packet.SourcePort), - attribute.String(coretypes.LabelSourceChannel, msg.Packet.SourceChannel), - attribute.String(coretypes.LabelDestinationPort, msg.Packet.DestinationPort), - attribute.String(coretypes.LabelDestinationChannel, msg.Packet.DestinationChannel), - )) - // TODO(PLT-428): remove once tx_msg_ibc_recv_packet verified - telemetry.IncrCounterWithLabels( - []string{"tx", "msg", "ibc", channeltypes.EventTypeRecvPacket}, - 1, - []metrics.Label{ - telemetry.NewLabel(coretypes.LabelSourcePort, msg.Packet.SourcePort), - telemetry.NewLabel(coretypes.LabelSourceChannel, msg.Packet.SourceChannel), - telemetry.NewLabel(coretypes.LabelDestinationPort, msg.Packet.DestinationPort), - telemetry.NewLabel(coretypes.LabelDestinationChannel, msg.Packet.DestinationChannel), - }, - ) - }() - - return &channeltypes.MsgRecvPacketResponse{Result: channeltypes.SUCCESS}, nil +// RecvPacket defines an RPC handler for MsgRecvPacket. +func (Keeper) RecvPacket(context.Context, *channeltypes.MsgRecvPacket) (*channeltypes.MsgRecvPacketResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// Timeout defines a rpc handler method for MsgTimeout. -func (k Keeper) Timeout(goCtx context.Context, msg *channeltypes.MsgTimeout) (*channeltypes.MsgTimeoutResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - relayer, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return nil, sdkerrors.Wrap(err, "Invalid address for msg Signer") - } - - // Lookup module by channel capability - module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - // Perform TAO verification - // - // If the timeout was already received, perform a no-op - // Use a cached context to prevent accidental state changes - cacheCtx, writeFn := ctx.CacheContext() - err = k.ChannelKeeper.TimeoutPacket(cacheCtx, msg.Packet, msg.ProofUnreceived, msg.ProofHeight, msg.NextSequenceRecv) - - // NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context. - ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events()) - - switch err { - case nil: - writeFn() - case channeltypes.ErrNoOpMsg: - return &channeltypes.MsgTimeoutResponse{Result: channeltypes.NOOP}, nil - default: - return nil, sdkerrors.Wrap(err, "timeout packet verification failed") - } - - // Perform application logic callback - err = cbs.OnTimeoutPacket(ctx, msg.Packet, relayer) - if err != nil { - return nil, sdkerrors.Wrap(err, "timeout packet callback failed") - } - - // Delete packet commitment - if err = k.ChannelKeeper.TimeoutExecuted(ctx, cap, msg.Packet); err != nil { - return nil, err - } - - defer func() { - ibcCoreMetrics.ibcTimeoutPacket.Add(ctx.Context(), 1, otelmetric.WithAttributes( - attribute.String(coretypes.LabelSourcePort, msg.Packet.SourcePort), - attribute.String(coretypes.LabelSourceChannel, msg.Packet.SourceChannel), - attribute.String(coretypes.LabelDestinationPort, msg.Packet.DestinationPort), - attribute.String(coretypes.LabelDestinationChannel, msg.Packet.DestinationChannel), - attribute.String(coretypes.LabelTimeoutType, "height"), - )) - // TODO(PLT-428): remove once ibc_timeout_packet verified - telemetry.IncrCounterWithLabels( - []string{"ibc", "timeout", "packet"}, - 1, - []metrics.Label{ - telemetry.NewLabel(coretypes.LabelSourcePort, msg.Packet.SourcePort), - telemetry.NewLabel(coretypes.LabelSourceChannel, msg.Packet.SourceChannel), - telemetry.NewLabel(coretypes.LabelDestinationPort, msg.Packet.DestinationPort), - telemetry.NewLabel(coretypes.LabelDestinationChannel, msg.Packet.DestinationChannel), - telemetry.NewLabel(coretypes.LabelTimeoutType, "height"), - }, - ) - }() - - return &channeltypes.MsgTimeoutResponse{Result: channeltypes.SUCCESS}, nil +// Timeout defines an RPC handler for MsgTimeout. +func (Keeper) Timeout(context.Context, *channeltypes.MsgTimeout) (*channeltypes.MsgTimeoutResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// TimeoutOnClose defines a rpc handler method for MsgTimeoutOnClose. -func (k Keeper) TimeoutOnClose(goCtx context.Context, msg *channeltypes.MsgTimeoutOnClose) (*channeltypes.MsgTimeoutOnCloseResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - relayer, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return nil, sdkerrors.Wrap(err, "Invalid address for msg Signer") - } - - // Lookup module by channel capability - module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - // Perform TAO verification - // - // If the timeout was already received, perform a no-op - // Use a cached context to prevent accidental state changes - cacheCtx, writeFn := ctx.CacheContext() - err = k.ChannelKeeper.TimeoutOnClose(cacheCtx, cap, msg.Packet, msg.ProofUnreceived, msg.ProofClose, msg.ProofHeight, msg.NextSequenceRecv) - - // NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context. - ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events()) - - switch err { - case nil: - writeFn() - case channeltypes.ErrNoOpMsg: - return &channeltypes.MsgTimeoutOnCloseResponse{Result: channeltypes.NOOP}, nil - default: - return nil, sdkerrors.Wrap(err, "timeout on close packet verification failed") - } - - // Perform application logic callback - // - // NOTE: MsgTimeout and MsgTimeoutOnClose use the same "OnTimeoutPacket" - // application logic callback. - err = cbs.OnTimeoutPacket(ctx, msg.Packet, relayer) - if err != nil { - return nil, sdkerrors.Wrap(err, "timeout packet callback failed") - } - - // Delete packet commitment - if err = k.ChannelKeeper.TimeoutExecuted(ctx, cap, msg.Packet); err != nil { - return nil, err - } - - defer func() { - ibcCoreMetrics.ibcTimeoutPacket.Add(ctx.Context(), 1, otelmetric.WithAttributes( - attribute.String(coretypes.LabelSourcePort, msg.Packet.SourcePort), - attribute.String(coretypes.LabelSourceChannel, msg.Packet.SourceChannel), - attribute.String(coretypes.LabelDestinationPort, msg.Packet.DestinationPort), - attribute.String(coretypes.LabelDestinationChannel, msg.Packet.DestinationChannel), - attribute.String(coretypes.LabelTimeoutType, "channel-closed"), - )) - // TODO(PLT-428): remove once ibc_timeout_packet verified - telemetry.IncrCounterWithLabels( - []string{"ibc", "timeout", "packet"}, - 1, - []metrics.Label{ - telemetry.NewLabel(coretypes.LabelSourcePort, msg.Packet.SourcePort), - telemetry.NewLabel(coretypes.LabelSourceChannel, msg.Packet.SourceChannel), - telemetry.NewLabel(coretypes.LabelDestinationPort, msg.Packet.DestinationPort), - telemetry.NewLabel(coretypes.LabelDestinationChannel, msg.Packet.DestinationChannel), - telemetry.NewLabel(coretypes.LabelTimeoutType, "channel-closed"), - }, - ) - }() - - return &channeltypes.MsgTimeoutOnCloseResponse{Result: channeltypes.SUCCESS}, nil +// TimeoutOnClose defines an RPC handler for MsgTimeoutOnClose. +func (Keeper) TimeoutOnClose(context.Context, *channeltypes.MsgTimeoutOnClose) (*channeltypes.MsgTimeoutOnCloseResponse, error) { + return nil, coretypes.ErrIBCDeprecated } -// Acknowledgement defines a rpc handler method for MsgAcknowledgement. -func (k Keeper) Acknowledgement(goCtx context.Context, msg *channeltypes.MsgAcknowledgement) (*channeltypes.MsgAcknowledgementResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - relayer, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return nil, sdkerrors.Wrap(err, "Invalid address for msg Signer") - } - - // Lookup module by channel capability - module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - // Perform TAO verification - // - // If the acknowledgement was already received, perform a no-op - // Use a cached context to prevent accidental state changes - cacheCtx, writeFn := ctx.CacheContext() - err = k.ChannelKeeper.AcknowledgePacket(cacheCtx, cap, msg.Packet, msg.Acknowledgement, msg.ProofAcked, msg.ProofHeight) - - // NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context. - ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events()) - - switch err { - case nil: - writeFn() - case channeltypes.ErrNoOpMsg: - return &channeltypes.MsgAcknowledgementResponse{Result: channeltypes.NOOP}, nil - default: - return nil, sdkerrors.Wrap(err, "acknowledge packet verification failed") - } - - // Perform application logic callback - err = cbs.OnAcknowledgementPacket(ctx, msg.Packet, msg.Acknowledgement, relayer) - if err != nil { - return nil, sdkerrors.Wrap(err, "acknowledge packet callback failed") - } - - defer func() { - ibcCoreMetrics.txMsgIbcAcknowledgePacket.Add(ctx.Context(), 1, otelmetric.WithAttributes( - attribute.String(coretypes.LabelSourcePort, msg.Packet.SourcePort), - attribute.String(coretypes.LabelSourceChannel, msg.Packet.SourceChannel), - attribute.String(coretypes.LabelDestinationPort, msg.Packet.DestinationPort), - attribute.String(coretypes.LabelDestinationChannel, msg.Packet.DestinationChannel), - )) - // TODO(PLT-428): remove once tx_msg_ibc_acknowledge_packet verified - telemetry.IncrCounterWithLabels( - []string{"tx", "msg", "ibc", channeltypes.EventTypeAcknowledgePacket}, - 1, - []metrics.Label{ - telemetry.NewLabel(coretypes.LabelSourcePort, msg.Packet.SourcePort), - telemetry.NewLabel(coretypes.LabelSourceChannel, msg.Packet.SourceChannel), - telemetry.NewLabel(coretypes.LabelDestinationPort, msg.Packet.DestinationPort), - telemetry.NewLabel(coretypes.LabelDestinationChannel, msg.Packet.DestinationChannel), - }, - ) - }() - - return &channeltypes.MsgAcknowledgementResponse{Result: channeltypes.SUCCESS}, nil +// Acknowledgement defines an RPC handler for MsgAcknowledgement. +func (Keeper) Acknowledgement(context.Context, *channeltypes.MsgAcknowledgement) (*channeltypes.MsgAcknowledgementResponse, error) { + return nil, coretypes.ErrIBCDeprecated } diff --git a/sei-ibc-go/modules/core/keeper/msg_server_test.go b/sei-ibc-go/modules/core/keeper/msg_server_test.go new file mode 100644 index 0000000000..cff52c2d66 --- /dev/null +++ b/sei-ibc-go/modules/core/keeper/msg_server_test.go @@ -0,0 +1,38 @@ +package keeper + +import ( + "context" + "reflect" + "testing" + + "github.com/stretchr/testify/require" + + clienttypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/types" + connectiontypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/03-connection/types" + channeltypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/04-channel/types" + coretypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/types" +) + +func TestDeprecatedMessages(t *testing.T) { + server := reflect.ValueOf(Keeper{}) + serverTypes := []reflect.Type{ + reflect.TypeOf((*clienttypes.MsgServer)(nil)).Elem(), + reflect.TypeOf((*connectiontypes.MsgServer)(nil)).Elem(), + reflect.TypeOf((*channeltypes.MsgServer)(nil)).Elem(), + } + + for _, serverType := range serverTypes { + for i := 0; i < serverType.NumMethod(); i++ { + method := serverType.Method(i) + t.Run(method.Name, func(t *testing.T) { + results := server.MethodByName(method.Name).Call([]reflect.Value{ + reflect.ValueOf(context.Background()), + reflect.Zero(method.Type.In(1)), + }) + + require.Nil(t, results[0].Interface()) + require.ErrorIs(t, results[1].Interface().(error), coretypes.ErrIBCDeprecated) + }) + } + } +} diff --git a/sei-ibc-go/modules/core/types/errors.go b/sei-ibc-go/modules/core/types/errors.go index 9c390930ff..21e5cbe3fc 100644 --- a/sei-ibc-go/modules/core/types/errors.go +++ b/sei-ibc-go/modules/core/types/errors.go @@ -8,4 +8,6 @@ var ( // ErrInboundDisabled / ErrOutboundDisabled ErrInboundDisabled = sdkerrors.Register("ibc", 101, "ibc inbound disabled") ErrOutboundDisabled = sdkerrors.Register("ibc", 102, "ibc outbound disabled") + // ErrIBCDeprecated is returned by IBC write handlers. + ErrIBCDeprecated = sdkerrors.Register("ibc", 103, "ibc module is deprecated") ) From b66084cdc85ac8e99b06c4171c4686e8ee9b16ab Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Tue, 18 Aug 2026 15:18:25 +0100 Subject: [PATCH 2/5] Remove more of IBC and redirect legacy versions to legacy transfer --- app/app.go | 6 - precompiles/ibc/ibc_test.go | 12 + precompiles/ibc/legacy/v555/ibc.go | 4 +- precompiles/ibc/legacy/v562/ibc.go | 4 +- precompiles/ibc/legacy/v580/ibc.go | 4 +- precompiles/ibc/legacy/v601/ibc.go | 4 +- precompiles/ibc/legacy/v603/ibc.go | 4 +- precompiles/ibc/legacy/v605/ibc.go | 4 +- precompiles/ibc/legacy/v606/ibc.go | 4 +- precompiles/ibc/legacy/v610/ibc.go | 4 +- precompiles/ibc/legacy/v614/ibc.go | 4 +- precompiles/ibc/legacy/v620/ibc.go | 4 +- precompiles/ibc/legacy/v630/ibc.go | 4 +- precompiles/ibc/legacy/v640/ibc.go | 4 +- precompiles/ibc/legacy/v65/ibc.go | 4 +- precompiles/ibc/legacy/v66/ibc.go | 4 +- precompiles/utils/expected_keepers.go | 1 + .../apps/transfer/keeper/legacy_transfer.go | 40 ++ .../modules/apps/transfer/types/errors.go | 2 +- .../modules/core/02-client/keeper/client.go | 152 ---- .../modules/core/02-client/keeper/keeper.go | 20 - .../modules/core/02-client/keeper/proposal.go | 117 --- .../core/02-client/proposal_handler.go | 22 - .../core/02-client/proposal_handler_test.go | 25 - .../modules/core/02-client/types/errors.go | 2 - sei-ibc-go/modules/core/keeper/metrics.go | 39 - sei-ibc-go/modules/core/keeper/params.go | 30 - sei-ibc-go/modules/core/types/errors.go | 9 +- sei-wasmd/app/app.go | 7 +- sei-wasmd/x/wasm/ibc_reflect_test.go | 123 ---- sei-wasmd/x/wasm/ibctesting/app.go | 31 - sei-wasmd/x/wasm/ibctesting/chain.go | 675 ------------------ sei-wasmd/x/wasm/ibctesting/config.go | 64 -- sei-wasmd/x/wasm/ibctesting/coordinator.go | 371 ---------- sei-wasmd/x/wasm/ibctesting/endpoint.go | 544 -------------- sei-wasmd/x/wasm/ibctesting/event_utils.go | 91 --- sei-wasmd/x/wasm/ibctesting/events.go | 203 ------ sei-wasmd/x/wasm/ibctesting/path.go | 99 --- sei-wasmd/x/wasm/ibctesting/values.go | 57 -- sei-wasmd/x/wasm/ibctesting/wasm.go | 142 ---- sei-wasmd/x/wasm/relay_pingpong_test.go | 400 ----------- sei-wasmd/x/wasm/relay_test.go | 646 ----------------- 42 files changed, 85 insertions(+), 3901 deletions(-) create mode 100644 sei-ibc-go/modules/apps/transfer/keeper/legacy_transfer.go delete mode 100644 sei-ibc-go/modules/core/02-client/keeper/proposal.go delete mode 100644 sei-ibc-go/modules/core/02-client/proposal_handler.go delete mode 100644 sei-ibc-go/modules/core/02-client/proposal_handler_test.go delete mode 100644 sei-ibc-go/modules/core/keeper/metrics.go delete mode 100644 sei-wasmd/x/wasm/ibc_reflect_test.go delete mode 100644 sei-wasmd/x/wasm/ibctesting/app.go delete mode 100644 sei-wasmd/x/wasm/ibctesting/chain.go delete mode 100644 sei-wasmd/x/wasm/ibctesting/config.go delete mode 100644 sei-wasmd/x/wasm/ibctesting/coordinator.go delete mode 100644 sei-wasmd/x/wasm/ibctesting/endpoint.go delete mode 100644 sei-wasmd/x/wasm/ibctesting/event_utils.go delete mode 100644 sei-wasmd/x/wasm/ibctesting/events.go delete mode 100644 sei-wasmd/x/wasm/ibctesting/path.go delete mode 100644 sei-wasmd/x/wasm/ibctesting/values.go delete mode 100644 sei-wasmd/x/wasm/ibctesting/wasm.go delete mode 100644 sei-wasmd/x/wasm/relay_pingpong_test.go delete mode 100644 sei-wasmd/x/wasm/relay_test.go diff --git a/app/app.go b/app/app.go index ecab0bc8f1..3d428b45d4 100644 --- a/app/app.go +++ b/app/app.go @@ -126,9 +126,6 @@ import ( ibctransferkeeper "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/apps/transfer/keeper" ibctransfertypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/apps/transfer/types" ibc "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core" - ibcclient "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client" - ibcclientclient "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/client" - ibcclienttypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/types" ibcporttypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/05-port/types" ibchost "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/24-host" ibckeeper "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/keeper" @@ -193,8 +190,6 @@ func getGovProposalHandlers() []govclient.ProposalHandler { distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler, - ibcclientclient.UpdateClientProposalHandler, - ibcclientclient.UpgradeProposalHandler, mintclient.UpdateMinterHandler, // this line is used by starport scaffolding # stargate/app/govProposalHandler ) @@ -847,7 +842,6 @@ func New( AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)). AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)). AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)). - AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)). AddRoute(minttypes.RouterKey, mint.NewProposalHandler(app.MintKeeper)). AddRoute(tokenfactorytypes.RouterKey, tokenfactorymodule.NewProposalHandler(app.TokenFactoryKeeper)). AddRoute(evmtypes.RouterKey, evm.NewProposalHandler(app.EvmKeeper)) diff --git a/precompiles/ibc/ibc_test.go b/precompiles/ibc/ibc_test.go index 25136a2c9e..9b4241cee5 100644 --- a/precompiles/ibc/ibc_test.go +++ b/precompiles/ibc/ibc_test.go @@ -29,6 +29,10 @@ func (tk *MockTransferKeeper) Transfer(goCtx context.Context, msg *types.MsgTran return nil, nil } +func (tk *MockTransferKeeper) LegacyTransfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { + return tk.Transfer(goCtx, msg) +} + func (tk *MockTransferKeeper) SendTransfer( ctx sdk.Context, sourcePort, @@ -52,6 +56,10 @@ func (tk *MockMemoTransferKeeper) Transfer(goCtx context.Context, msg *types.Msg return nil, nil } +func (tk *MockMemoTransferKeeper) LegacyTransfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { + return tk.Transfer(goCtx, msg) +} + func (tk *MockMemoTransferKeeper) SendTransfer( ctx sdk.Context, sourcePort, @@ -71,6 +79,10 @@ func (tk *MockFailedTransferTransferKeeper) Transfer(goCtx context.Context, msg return nil, errors.New("failed to send transfer") } +func (tk *MockFailedTransferTransferKeeper) LegacyTransfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { + return tk.Transfer(goCtx, msg) +} + func (tk *MockFailedTransferTransferKeeper) SendTransfer( ctx sdk.Context, sourcePort, diff --git a/precompiles/ibc/legacy/v555/ibc.go b/precompiles/ibc/legacy/v555/ibc.go index 696a3ff6dc..902a2390eb 100644 --- a/precompiles/ibc/legacy/v555/ibc.go +++ b/precompiles/ibc/legacy/v555/ibc.go @@ -219,7 +219,7 @@ func (p Precompile) transfer(ctx sdk.Context, method *abi.Method, args []interfa return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -305,7 +305,7 @@ func (p Precompile) transferWithDefaultTimeout(ctx sdk.Context, method *abi.Meth return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v562/ibc.go b/precompiles/ibc/legacy/v562/ibc.go index 698059cb7b..8c201e885c 100644 --- a/precompiles/ibc/legacy/v562/ibc.go +++ b/precompiles/ibc/legacy/v562/ibc.go @@ -177,7 +177,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -263,7 +263,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v580/ibc.go b/precompiles/ibc/legacy/v580/ibc.go index 2c57648404..b707666c67 100644 --- a/precompiles/ibc/legacy/v580/ibc.go +++ b/precompiles/ibc/legacy/v580/ibc.go @@ -163,7 +163,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -249,7 +249,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v601/ibc.go b/precompiles/ibc/legacy/v601/ibc.go index 2409bed68b..50ec38e725 100644 --- a/precompiles/ibc/legacy/v601/ibc.go +++ b/precompiles/ibc/legacy/v601/ibc.go @@ -163,7 +163,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -249,7 +249,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v603/ibc.go b/precompiles/ibc/legacy/v603/ibc.go index 4bf2d17e52..c82e4a99d7 100644 --- a/precompiles/ibc/legacy/v603/ibc.go +++ b/precompiles/ibc/legacy/v603/ibc.go @@ -162,7 +162,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -248,7 +248,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v605/ibc.go b/precompiles/ibc/legacy/v605/ibc.go index 8fdfe973d0..64365f6138 100644 --- a/precompiles/ibc/legacy/v605/ibc.go +++ b/precompiles/ibc/legacy/v605/ibc.go @@ -166,7 +166,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -252,7 +252,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v606/ibc.go b/precompiles/ibc/legacy/v606/ibc.go index b76057374b..62fa5e21e5 100644 --- a/precompiles/ibc/legacy/v606/ibc.go +++ b/precompiles/ibc/legacy/v606/ibc.go @@ -166,7 +166,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -252,7 +252,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v610/ibc.go b/precompiles/ibc/legacy/v610/ibc.go index d0e571f8e7..627aad0d1c 100644 --- a/precompiles/ibc/legacy/v610/ibc.go +++ b/precompiles/ibc/legacy/v610/ibc.go @@ -166,7 +166,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -252,7 +252,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v614/ibc.go b/precompiles/ibc/legacy/v614/ibc.go index 97e76b3719..d922d29ce3 100644 --- a/precompiles/ibc/legacy/v614/ibc.go +++ b/precompiles/ibc/legacy/v614/ibc.go @@ -166,7 +166,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -252,7 +252,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v620/ibc.go b/precompiles/ibc/legacy/v620/ibc.go index 830b15c57e..1755af75ed 100644 --- a/precompiles/ibc/legacy/v620/ibc.go +++ b/precompiles/ibc/legacy/v620/ibc.go @@ -166,7 +166,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -252,7 +252,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v630/ibc.go b/precompiles/ibc/legacy/v630/ibc.go index 33cee9208a..560b3bb6d2 100644 --- a/precompiles/ibc/legacy/v630/ibc.go +++ b/precompiles/ibc/legacy/v630/ibc.go @@ -166,7 +166,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -252,7 +252,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v640/ibc.go b/precompiles/ibc/legacy/v640/ibc.go index 77597bd1e1..cdd786022f 100644 --- a/precompiles/ibc/legacy/v640/ibc.go +++ b/precompiles/ibc/legacy/v640/ibc.go @@ -166,7 +166,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -252,7 +252,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v65/ibc.go b/precompiles/ibc/legacy/v65/ibc.go index a2db1705b5..f5870349e0 100644 --- a/precompiles/ibc/legacy/v65/ibc.go +++ b/precompiles/ibc/legacy/v65/ibc.go @@ -166,7 +166,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -252,7 +252,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v66/ibc.go b/precompiles/ibc/legacy/v66/ibc.go index 2d705225ce..9e6dc24f9f 100644 --- a/precompiles/ibc/legacy/v66/ibc.go +++ b/precompiles/ibc/legacy/v66/ibc.go @@ -168,7 +168,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -254,7 +254,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/utils/expected_keepers.go b/precompiles/utils/expected_keepers.go index ab0581c70e..83fb8779b8 100644 --- a/precompiles/utils/expected_keepers.go +++ b/precompiles/utils/expected_keepers.go @@ -234,6 +234,7 @@ type DistributionKeeper interface { type TransferKeeper interface { Transfer(goCtx context.Context, msg *ibctypes.MsgTransfer) (*ibctypes.MsgTransferResponse, error) + LegacyTransfer(goCtx context.Context, msg *ibctypes.MsgTransfer) (*ibctypes.MsgTransferResponse, error) SendTransfer( ctx sdk.Context, sourcePort, diff --git a/sei-ibc-go/modules/apps/transfer/keeper/legacy_transfer.go b/sei-ibc-go/modules/apps/transfer/keeper/legacy_transfer.go new file mode 100644 index 0000000000..537880a9d4 --- /dev/null +++ b/sei-ibc-go/modules/apps/transfer/keeper/legacy_transfer.go @@ -0,0 +1,40 @@ +package keeper + +import ( + "context" + + sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" + + "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/apps/transfer/types" +) + +// LegacyTransfer executes a transfer for versioned historical EVM precompiles. +func (k Keeper) LegacyTransfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return nil, err + } + + sequence, err := k.sendTransfer( + ctx, msg.SourcePort, msg.SourceChannel, msg.Token, sender, msg.Receiver, msg.TimeoutHeight, msg.TimeoutTimestamp, + msg.Memo) + if err != nil { + return nil, err + } + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + types.EventTypeTransfer, + sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), + sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver), + ), + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + ), + }) + + return &types.MsgTransferResponse{Sequence: sequence}, nil +} diff --git a/sei-ibc-go/modules/apps/transfer/types/errors.go b/sei-ibc-go/modules/apps/transfer/types/errors.go index 51e23d8045..38c5574929 100644 --- a/sei-ibc-go/modules/apps/transfer/types/errors.go +++ b/sei-ibc-go/modules/apps/transfer/types/errors.go @@ -15,6 +15,6 @@ var ( ErrReceiveDisabled = sdkerrors.Register(ModuleName, 8, "fungible token transfers to this chain are disabled") ErrMaxTransferChannels = sdkerrors.Register(ModuleName, 9, "max transfer channels") ErrInvalidMemo = sdkerrors.Register(ModuleName, 10, "invalid memo") - // ErrTransferDeprecated is returned by every transfer message handler. + // ErrTransferDeprecated indicates that the transfer module is deprecated. ErrTransferDeprecated = sdkerrors.Register(ModuleName, 11, "transfer module is deprecated") ) diff --git a/sei-ibc-go/modules/core/02-client/keeper/client.go b/sei-ibc-go/modules/core/02-client/keeper/client.go index bd1bdbe205..d527b442f0 100644 --- a/sei-ibc-go/modules/core/02-client/keeper/client.go +++ b/sei-ibc-go/modules/core/02-client/keeper/client.go @@ -17,60 +17,6 @@ import ( var logger = seilog.NewLogger("ibc-go", "modules", "core", "02-client", "keeper") -// ErrInboundDisabled is the error for when inbound is disabled -var ErrInboundDisabled = sdkerrors.Register("ibc-client", 101, "ibc inbound disabled") - -// CreateClient creates a new client state and populates it with a given consensus -// state as defined in https://github.com/cosmos/ibc/tree/master/spec/core/ics-002-client-semantics#create -func (k Keeper) CreateClient( - ctx sdk.Context, clientState exported.ClientState, consensusState exported.ConsensusState, -) (string, error) { - // inbound gating: disallow client creation as part of inbound handshakes when inbound disabled - if !k.IsInboundEnabled(ctx) { - return "", sdkerrors.Wrap(ErrInboundDisabled, "client creation inbound disabled") - } - - params := k.GetParams(ctx) - if !params.IsAllowedClient(clientState.ClientType()) { - return "", sdkerrors.Wrapf( - types.ErrInvalidClientType, - "client state type %s is not registered in the allowlist", clientState.ClientType(), - ) - } - - clientID := k.GenerateClientIdentifier(ctx, clientState.ClientType()) - - k.SetClientState(ctx, clientID, clientState) - logger.Info("client created at height", "client-id", clientID, "height", clientState.GetLatestHeight().String()) - - // verifies initial consensus state against client state and initializes client store with any client-specific metadata - // e.g. set ProcessedTime in Tendermint clients - if err := clientState.Initialize(ctx, k.cdc, k.ClientStore(ctx, clientID), consensusState); err != nil { - return "", err - } - - // check if consensus state is nil in case the created client is Localhost - if consensusState != nil { - k.SetClientConsensusState(ctx, clientID, clientState.GetLatestHeight(), consensusState) - } - - logger.Info("client created at height", "client-id", clientID, "height", clientState.GetLatestHeight().String()) - - defer func() { - ibcClientMetrics.ibcClientCreate.Add(ctx.Context(), 1, otelmetric.WithAttributes(attribute.String(types.LabelClientType, clientState.ClientType()))) - // TODO(PLT-428): remove once ibc_client_create verified - telemetry.IncrCounterWithLabels( - []string{"ibc", "client", "create"}, - 1, - []metrics.Label{telemetry.NewLabel(types.LabelClientType, clientState.ClientType())}, - ) - }() - - EmitCreateClientEvent(ctx, clientID, clientState) - - return clientID, nil -} - // UpdateClient updates the consensus state and the state root from a provided header. func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.Header) error { clientState, found := k.GetClientState(ctx, clientID) @@ -103,7 +49,6 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H headerStr = hex.EncodeToString(types.MustMarshalHeader(k.cdc, header)) // set default consensus height with header height consensusHeight = header.GetHeight() - } // set new client state regardless of if update is valid update or misbehaviour @@ -143,7 +88,6 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H // emitting events in the keeper emits for both begin block and handler client updates EmitUpdateClientEvent(ctx, clientID, newClientState, consensusHeight, headerStr) } else { - logger.Info("client frozen due to misbehaviour", "client-id", clientID) defer func() { @@ -169,99 +113,3 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H return nil } - -// UpgradeClient upgrades the client to a new client state if this new client was committed to -// by the old client at the specified upgrade height -func (k Keeper) UpgradeClient(ctx sdk.Context, clientID string, upgradedClient exported.ClientState, upgradedConsState exported.ConsensusState, - proofUpgradeClient, proofUpgradeConsState []byte, -) error { - clientState, found := k.GetClientState(ctx, clientID) - if !found { - return sdkerrors.Wrapf(types.ErrClientNotFound, "cannot update client with ID %s", clientID) - } - - clientStore := k.ClientStore(ctx, clientID) - - if status := clientState.Status(ctx, clientStore, k.cdc); status != exported.Active { - return sdkerrors.Wrapf(types.ErrClientNotActive, "cannot upgrade client (%s) with status %s", clientID, status) - } - - updatedClientState, updatedConsState, err := clientState.VerifyUpgradeAndUpdateState(ctx, k.cdc, clientStore, - upgradedClient, upgradedConsState, proofUpgradeClient, proofUpgradeConsState) - if err != nil { - return sdkerrors.Wrapf(err, "cannot upgrade client with ID %s", clientID) - } - - k.SetClientState(ctx, clientID, updatedClientState) - k.SetClientConsensusState(ctx, clientID, updatedClientState.GetLatestHeight(), updatedConsState) - - logger.Info("client state upgraded", "client-id", clientID, "height", updatedClientState.GetLatestHeight().String()) - - defer func() { - ibcClientMetrics.ibcClientUpgrade.Add(ctx.Context(), 1, otelmetric.WithAttributes( - attribute.String(types.LabelClientType, updatedClientState.ClientType()), - attribute.String(types.LabelClientID, clientID), - )) - // TODO(PLT-428): remove once ibc_client_upgrade verified - telemetry.IncrCounterWithLabels( - []string{"ibc", "client", "upgrade"}, - 1, - []metrics.Label{ - telemetry.NewLabel(types.LabelClientType, updatedClientState.ClientType()), - telemetry.NewLabel(types.LabelClientID, clientID), - }, - ) - }() - - // emitting events in the keeper emits for client upgrades - EmitUpgradeClientEvent(ctx, clientID, updatedClientState) - - return nil -} - -// CheckMisbehaviourAndUpdateState checks for client misbehaviour and freezes the -// client if so. -func (k Keeper) CheckMisbehaviourAndUpdateState(ctx sdk.Context, misbehaviour exported.Misbehaviour) error { - clientState, found := k.GetClientState(ctx, misbehaviour.GetClientID()) - if !found { - return sdkerrors.Wrapf(types.ErrClientNotFound, "cannot check misbehaviour for client with ID %s", misbehaviour.GetClientID()) - } - - clientStore := k.ClientStore(ctx, misbehaviour.GetClientID()) - - if status := clientState.Status(ctx, clientStore, k.cdc); status != exported.Active { - return sdkerrors.Wrapf(types.ErrClientNotActive, "cannot process misbehaviour for client (%s) with status %s", misbehaviour.GetClientID(), status) - } - - if err := misbehaviour.ValidateBasic(); err != nil { - return err - } - - clientState, err := clientState.CheckMisbehaviourAndUpdateState(ctx, k.cdc, clientStore, misbehaviour) - if err != nil { - return err - } - - k.SetClientState(ctx, misbehaviour.GetClientID(), clientState) - logger.Info("client frozen due to misbehaviour", "client-id", misbehaviour.GetClientID()) - - defer func() { - ibcClientMetrics.ibcClientMisbehaviour.Add(ctx.Context(), 1, otelmetric.WithAttributes( - attribute.String(types.LabelClientType, misbehaviour.ClientType()), - attribute.String(types.LabelClientID, misbehaviour.GetClientID()), - )) - // TODO(PLT-428): remove once ibc_client_misbehaviour verified - telemetry.IncrCounterWithLabels( - []string{"ibc", "client", "misbehaviour"}, - 1, - []metrics.Label{ - telemetry.NewLabel(types.LabelClientType, misbehaviour.ClientType()), - telemetry.NewLabel(types.LabelClientID, misbehaviour.GetClientID()), - }, - ) - }() - - EmitSubmitMisbehaviourEvent(ctx, misbehaviour.GetClientID(), clientState) - - return nil -} diff --git a/sei-ibc-go/modules/core/02-client/keeper/keeper.go b/sei-ibc-go/modules/core/02-client/keeper/keeper.go index f9cd80ad41..8135680a31 100644 --- a/sei-ibc-go/modules/core/02-client/keeper/keeper.go +++ b/sei-ibc-go/modules/core/02-client/keeper/keeper.go @@ -21,9 +21,6 @@ import ( ibctmtypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/light-clients/07-tendermint/types" ) -// KeyInboundEnabled is the param key for inbound enabled -var KeyInboundEnabled = []byte("InboundEnabled") - // Keeper represents a type that grants read and write permissions to any client // state information type Keeper struct { @@ -50,23 +47,6 @@ func NewKeeper(cdc codec.BinaryCodec, key sdk.StoreKey, paramSpace paramtypes.Su } } -// IsInboundEnabled returns true if inbound IBC is enabled. -func (k Keeper) IsInboundEnabled(ctx sdk.Context) bool { - var inbound bool - k.paramSpace.Get(ctx, KeyInboundEnabled, &inbound) - return inbound -} - -// GenerateClientIdentifier returns the next client identifier. -func (k Keeper) GenerateClientIdentifier(ctx sdk.Context, clientType string) string { - nextClientSeq := k.GetNextClientSequence(ctx) - clientID := types.FormatClientIdentifier(clientType, nextClientSeq) - - nextClientSeq++ - k.SetNextClientSequence(ctx, nextClientSeq) - return clientID -} - // GetClientState gets a particular client from the store func (k Keeper) GetClientState(ctx sdk.Context, clientID string) (exported.ClientState, bool) { store := k.ClientStore(ctx, clientID) diff --git a/sei-ibc-go/modules/core/02-client/keeper/proposal.go b/sei-ibc-go/modules/core/02-client/keeper/proposal.go deleted file mode 100644 index 1f3159b0c0..0000000000 --- a/sei-ibc-go/modules/core/02-client/keeper/proposal.go +++ /dev/null @@ -1,117 +0,0 @@ -package keeper - -import ( - "github.com/armon/go-metrics" - "github.com/sei-protocol/sei-chain/sei-cosmos/telemetry" - sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" - sdkerrors "github.com/sei-protocol/sei-chain/sei-cosmos/types/errors" - "go.opentelemetry.io/otel/attribute" - otelmetric "go.opentelemetry.io/otel/metric" - - "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/types" - "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/exported" -) - -// ClientUpdateProposal will retrieve the subject and substitute client. -// A callback will occur to the subject client state with the client -// prefixed store being provided for both the subject and the substitute client. -// The localhost client is not allowed to be modified with a proposal. The IBC -// client implementations are responsible for validating the parameters of the -// subtitute (enusring they match the subject's parameters) as well as copying -// the necessary consensus states from the subtitute to the subject client -// store. The substitute must be Active and the subject must not be Active. -func (k Keeper) ClientUpdateProposal(ctx sdk.Context, p *types.ClientUpdateProposal) error { - if p.SubjectClientId == exported.Localhost || p.SubstituteClientId == exported.Localhost { - return sdkerrors.Wrap(types.ErrInvalidUpdateClientProposal, "cannot update localhost client with proposal") - } - - subjectClientState, found := k.GetClientState(ctx, p.SubjectClientId) - if !found { - return sdkerrors.Wrapf(types.ErrClientNotFound, "subject client with ID %s", p.SubjectClientId) - } - - subjectClientStore := k.ClientStore(ctx, p.SubjectClientId) - - if status := subjectClientState.Status(ctx, subjectClientStore, k.cdc); status == exported.Active { - return sdkerrors.Wrap(types.ErrInvalidUpdateClientProposal, "cannot update Active subject client") - } - - substituteClientState, found := k.GetClientState(ctx, p.SubstituteClientId) - if !found { - return sdkerrors.Wrapf(types.ErrClientNotFound, "substitute client with ID %s", p.SubstituteClientId) - } - - if subjectClientState.GetLatestHeight().GTE(substituteClientState.GetLatestHeight()) { - return sdkerrors.Wrapf(types.ErrInvalidHeight, "subject client state latest height is greater or equal to substitute client state latest height (%s >= %s)", subjectClientState.GetLatestHeight(), substituteClientState.GetLatestHeight()) - } - - substituteClientStore := k.ClientStore(ctx, p.SubstituteClientId) - - if status := substituteClientState.Status(ctx, substituteClientStore, k.cdc); status != exported.Active { - return sdkerrors.Wrapf(types.ErrClientNotActive, "substitute client is not Active, status is %s", status) - } - - clientState, err := subjectClientState.CheckSubstituteAndUpdateState(ctx, k.cdc, subjectClientStore, substituteClientStore, substituteClientState) - if err != nil { - return err - } - k.SetClientState(ctx, p.SubjectClientId, clientState) - - logger.Info("client updated after governance proposal passed", "client-id", p.SubjectClientId, "height", clientState.GetLatestHeight().String()) - - defer func() { - ibcClientMetrics.ibcClientUpdate.Add(ctx.Context(), 1, otelmetric.WithAttributes( - attribute.String(types.LabelClientType, clientState.ClientType()), - attribute.String(types.LabelClientID, p.SubjectClientId), - attribute.String(types.LabelUpdateType, "proposal"), - )) - // TODO(PLT-428): remove once ibc_client_update verified - telemetry.IncrCounterWithLabels( - []string{"ibc", "client", "update"}, - 1, - []metrics.Label{ - telemetry.NewLabel(types.LabelClientType, clientState.ClientType()), - telemetry.NewLabel(types.LabelClientID, p.SubjectClientId), - telemetry.NewLabel(types.LabelUpdateType, "proposal"), - }, - ) - }() - - // emitting events in the keeper for proposal updates to clients - EmitUpdateClientProposalEvent(ctx, p.SubjectClientId, clientState) - - return nil -} - -// HandleUpgradeProposal sets the upgraded client state in the upgrade store. It clears -// an IBC client state and consensus state if a previous plan was set. Then it -// will schedule an upgrade and finally set the upgraded client state in upgrade -// store. -func (k Keeper) HandleUpgradeProposal(ctx sdk.Context, p *types.UpgradeProposal) error { - clientState, err := types.UnpackClientState(p.UpgradedClientState) - if err != nil { - return sdkerrors.Wrap(err, "could not unpack UpgradedClientState") - } - - // zero out any custom fields before setting - cs := clientState.ZeroCustomFields() - bz, err := types.MarshalClientState(k.cdc, cs) - if err != nil { - return sdkerrors.Wrap(err, "could not marshal UpgradedClientState") - } - - if err := k.upgradeKeeper.ScheduleUpgrade(ctx, p.Plan); err != nil { - return err - } - - // sets the new upgraded client in last height committed on this chain is at plan.Height, - // since the chain will panic at plan.Height and new chain will resume at plan.Height - if err = k.upgradeKeeper.SetUpgradedClient(ctx, p.Plan.Height, bz); err != nil { - return err - } - - // emitting an event for handling client upgrade proposal - EmitUpgradeClientProposalEvent(ctx, p.Title, p.Plan.Height) - - return nil -} diff --git a/sei-ibc-go/modules/core/02-client/proposal_handler.go b/sei-ibc-go/modules/core/02-client/proposal_handler.go deleted file mode 100644 index 2b789c113b..0000000000 --- a/sei-ibc-go/modules/core/02-client/proposal_handler.go +++ /dev/null @@ -1,22 +0,0 @@ -package client - -import ( - sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" - sdkerrors "github.com/sei-protocol/sei-chain/sei-cosmos/types/errors" - govtypes "github.com/sei-protocol/sei-chain/sei-cosmos/x/gov/types" - - "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/keeper" - "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/types" -) - -// NewClientProposalHandler defines the 02-client proposal handler -func NewClientProposalHandler(_ keeper.Keeper) govtypes.Handler { - return func(_ sdk.Context, content govtypes.Content) error { - switch c := content.(type) { - case *types.ClientUpdateProposal, *types.UpgradeProposal: - return types.ErrClientDeprecated - default: - return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized ibc proposal content type: %T", c) - } - } -} diff --git a/sei-ibc-go/modules/core/02-client/proposal_handler_test.go b/sei-ibc-go/modules/core/02-client/proposal_handler_test.go deleted file mode 100644 index 6b0567c52e..0000000000 --- a/sei-ibc-go/modules/core/02-client/proposal_handler_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package client - -import ( - "testing" - - "github.com/stretchr/testify/require" - - sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" - govtypes "github.com/sei-protocol/sei-chain/sei-cosmos/x/gov/types" - - "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/keeper" - "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/types" -) - -func TestDeprecatedClientProposals(t *testing.T) { - handler := NewClientProposalHandler(keeper.Keeper{}) - proposals := []govtypes.Content{ - &types.ClientUpdateProposal{}, - &types.UpgradeProposal{}, - } - - for _, proposal := range proposals { - require.ErrorIs(t, handler(sdk.Context{}, proposal), types.ErrClientDeprecated) - } -} diff --git a/sei-ibc-go/modules/core/02-client/types/errors.go b/sei-ibc-go/modules/core/02-client/types/errors.go index 19588eef0f..82dc8344d6 100644 --- a/sei-ibc-go/modules/core/02-client/types/errors.go +++ b/sei-ibc-go/modules/core/02-client/types/errors.go @@ -34,6 +34,4 @@ var ( ErrInvalidSubstitute = sdkerrors.Register(SubModuleName, 27, "invalid client state substitute") ErrInvalidUpgradeProposal = sdkerrors.Register(SubModuleName, 28, "invalid upgrade proposal") ErrClientNotActive = sdkerrors.Register(SubModuleName, 29, "client is not active") - // ErrClientDeprecated is returned by IBC client proposal handlers. - ErrClientDeprecated = sdkerrors.Register(SubModuleName, 30, "ibc client module is deprecated") ) diff --git a/sei-ibc-go/modules/core/keeper/metrics.go b/sei-ibc-go/modules/core/keeper/metrics.go deleted file mode 100644 index 8dca0e02c1..0000000000 --- a/sei-ibc-go/modules/core/keeper/metrics.go +++ /dev/null @@ -1,39 +0,0 @@ -package keeper - -import ( - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/metric" -) - -var ( - meter = otel.Meter("ibc_core") - - ibcCoreMetrics = struct { - txMsgIbcRecvPacket metric.Int64Counter - ibcTimeoutPacket metric.Int64Counter - txMsgIbcAcknowledgePacket metric.Int64Counter - }{ - txMsgIbcRecvPacket: must(meter.Int64Counter( - "ibc_core_tx_msg_recv_packet", - metric.WithDescription("Total number of IBC recv packet messages"), - metric.WithUnit("{count}"), - )), - ibcTimeoutPacket: must(meter.Int64Counter( - "ibc_core_timeout_packet", - metric.WithDescription("Total number of IBC timeout packets"), - metric.WithUnit("{count}"), - )), - txMsgIbcAcknowledgePacket: must(meter.Int64Counter( - "ibc_core_tx_msg_acknowledge_packet", - metric.WithDescription("Total number of IBC acknowledge packet messages"), - metric.WithUnit("{count}"), - )), - } -) - -func must[V any](v V, err error) V { - if err != nil { - panic(err) - } - return v -} diff --git a/sei-ibc-go/modules/core/keeper/params.go b/sei-ibc-go/modules/core/keeper/params.go index f6b2613a56..d6b2570fe1 100644 --- a/sei-ibc-go/modules/core/keeper/params.go +++ b/sei-ibc-go/modules/core/keeper/params.go @@ -2,7 +2,6 @@ package keeper import ( sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" - paramtypes "github.com/sei-protocol/sei-chain/sei-cosmos/x/params/types" "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/types" ) @@ -18,32 +17,3 @@ func (k *Keeper) GetParams(ctx sdk.Context) types.Params { func (k *Keeper) SetParams(ctx sdk.Context, p types.Params) { k.paramSpace.SetParamSet(ctx, &p) } - -// IsInboundEnabled returns true if inbound IBC is enabled. -func (k *Keeper) IsInboundEnabled(ctx sdk.Context) bool { - return k.GetParams(ctx).InboundEnabled -} - -// IsOutboundEnabled returns true if outbound IBC is enabled. -func (k *Keeper) IsOutboundEnabled(ctx sdk.Context) bool { - return k.GetParams(ctx).OutboundEnabled -} - -// SetInboundEnabled sets inbound enabled flag. -func (k *Keeper) SetInboundEnabled(ctx sdk.Context, enabled bool) { - p := k.GetParams(ctx) - p.InboundEnabled = enabled - k.SetParams(ctx, p) -} - -// SetOutboundEnabled sets outbound enabled flag. -func (k *Keeper) SetOutboundEnabled(ctx sdk.Context, enabled bool) { - p := k.GetParams(ctx) - p.OutboundEnabled = enabled - k.SetParams(ctx, p) -} - -// GetParamSpace returns the keeper's paramSpace (for other packages if needed). -func (k *Keeper) GetParamSpace() paramtypes.Subspace { - return k.paramSpace -} diff --git a/sei-ibc-go/modules/core/types/errors.go b/sei-ibc-go/modules/core/types/errors.go index 21e5cbe3fc..32744df0ff 100644 --- a/sei-ibc-go/modules/core/types/errors.go +++ b/sei-ibc-go/modules/core/types/errors.go @@ -4,10 +4,5 @@ import ( sdkerrors "github.com/sei-protocol/sei-chain/sei-cosmos/types/errors" ) -var ( - // ErrInboundDisabled / ErrOutboundDisabled - ErrInboundDisabled = sdkerrors.Register("ibc", 101, "ibc inbound disabled") - ErrOutboundDisabled = sdkerrors.Register("ibc", 102, "ibc outbound disabled") - // ErrIBCDeprecated is returned by IBC write handlers. - ErrIBCDeprecated = sdkerrors.Register("ibc", 103, "ibc module is deprecated") -) +// ErrIBCDeprecated indicates that the IBC module is deprecated. +var ErrIBCDeprecated = sdkerrors.Register("ibc", 103, "ibc module is deprecated") diff --git a/sei-wasmd/app/app.go b/sei-wasmd/app/app.go index 7f67e928bd..7f59781754 100644 --- a/sei-wasmd/app/app.go +++ b/sei-wasmd/app/app.go @@ -75,8 +75,6 @@ import ( ibctransfertypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/apps/transfer/types" ibc "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core" ibcclient "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client" - ibcclientclient "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/client" - ibcclienttypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/types" porttypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/05-port/types" ibchost "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/24-host" ibckeeper "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/keeper" @@ -178,8 +176,6 @@ var ( distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler, - ibcclientclient.UpdateClientProposalHandler, - ibcclientclient.UpgradeProposalHandler, )..., ), params.AppModuleBasic{}, @@ -400,8 +396,7 @@ func NewWasmApp( AddRoute(govtypes.RouterKey, govtypes.ProposalHandler). AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.paramsKeeper)). AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.distrKeeper)). - AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.upgradeKeeper)). - AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.ibcKeeper.ClientKeeper)) + AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.upgradeKeeper)) // Create Transfer Keepers app.transferKeeper = ibctransferkeeper.NewKeeper( diff --git a/sei-wasmd/x/wasm/ibc_reflect_test.go b/sei-wasmd/x/wasm/ibc_reflect_test.go deleted file mode 100644 index 35d5f5fd5c..0000000000 --- a/sei-wasmd/x/wasm/ibc_reflect_test.go +++ /dev/null @@ -1,123 +0,0 @@ -package wasm_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - channeltypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/04-channel/types" - - wasmvmtypes "github.com/sei-protocol/sei-chain/sei-wasmvm/types" - "github.com/stretchr/testify/require" - - wasmibctesting "github.com/sei-protocol/sei-chain/sei-wasmd/x/wasm/ibctesting" - wasmkeeper "github.com/sei-protocol/sei-chain/sei-wasmd/x/wasm/keeper" -) - -func TestIBCReflectContract(t *testing.T) { - // scenario: - // chain A: ibc_reflect_send.wasm - // chain B: reflect.wasm + ibc_reflect.wasm - // - // Chain A "ibc_reflect_send" sends a IBC packet "on channel connect" event to chain B "ibc_reflect" - // "ibc_reflect" sends a submessage to "reflect" which is returned as submessage. - - var ( - coordinator = wasmibctesting.NewCoordinator(t, 2) - chainA = coordinator.GetChain(wasmibctesting.GetChainID(0)) - chainB = coordinator.GetChain(wasmibctesting.GetChainID(1)) - ) - coordinator.CommitBlock(chainA, chainB) - - initMsg := []byte(`{}`) - codeID := chainA.StoreCodeFile("./keeper/testdata/ibc_reflect_send.wasm").CodeID - sendContractAddr := chainA.InstantiateContract(codeID, initMsg) - - reflectID := chainB.StoreCodeFile("./keeper/testdata/reflect.wasm").CodeID - initMsg = wasmkeeper.IBCReflectInitMsg{ - ReflectCodeID: reflectID, - }.GetBytes(t) - codeID = chainB.StoreCodeFile("./keeper/testdata/ibc_reflect.wasm").CodeID - - reflectContractAddr := chainB.InstantiateContract(codeID, initMsg) - var ( - sourcePortID = chainA.ContractInfo(sendContractAddr).IBCPortID - counterpartPortID = chainB.ContractInfo(reflectContractAddr).IBCPortID - ) - coordinator.CommitBlock(chainA, chainB) - coordinator.UpdateTime() - - require.Equal(t, chainA.CurrentHeader.Time, chainB.CurrentHeader.Time) - path := wasmibctesting.NewPath(chainA, chainB) - path.EndpointA.ChannelConfig = &wasmibctesting.ChannelConfig{ - PortID: sourcePortID, - Version: "ibc-reflect-v1", - Order: channeltypes.ORDERED, - } - path.EndpointB.ChannelConfig = &wasmibctesting.ChannelConfig{ - PortID: counterpartPortID, - Version: "ibc-reflect-v1", - Order: channeltypes.ORDERED, - } - - coordinator.SetupConnections(path) - coordinator.CreateChannels(path) - - // TODO: query both contracts directly to ensure they have registered the proper connection - // (and the chainB has created a reflect contract) - - // there should be one packet to relay back and forth (whoami) - // TODO: how do I find the packet that was previously sent by the smart contract? - // Coordinator.RecvPacket requires channeltypes.Packet as input? - // Given the source (portID, channelID), we should be able to count how many packets are pending, query the data - // and submit them to the other side (same with acks). This is what the real relayer does. I guess the test framework doesn't? - - // Update: I dug through the code, especially channel.Keeper.SendPacket, and it only writes a commitment - // only writes I see: https://github.com/cosmos/cosmos-sdk/blob/31fdee0228bd6f3e787489c8e4434aabc8facb7d/x/ibc/core/04-channel/keeper/packet.go#L115-L116 - // commitment is hashed packet: https://github.com/cosmos/cosmos-sdk/blob/31fdee0228bd6f3e787489c8e4434aabc8facb7d/x/ibc/core/04-channel/types/packet.go#L14-L34 - // how is the relayer supposed to get the original packet data?? - // eg. ibctransfer doesn't store the packet either: https://github.com/cosmos/cosmos-sdk/blob/master/x/ibc/applications/transfer/keeper/relay.go#L145-L162 - // ... or I guess the original packet data is only available in the event logs???? - // https://github.com/cosmos/cosmos-sdk/blob/31fdee0228bd6f3e787489c8e4434aabc8facb7d/x/ibc/core/04-channel/keeper/packet.go#L121-L132 - - // ensure the expected packet was prepared, and relay it - require.Equal(t, 1, len(chainA.PendingSendPackets)) - require.Equal(t, 0, len(chainB.PendingSendPackets)) - err := coordinator.RelayAndAckPendingPackets(path) - require.NoError(t, err) - require.Equal(t, 0, len(chainA.PendingSendPackets)) - require.Equal(t, 0, len(chainB.PendingSendPackets)) - - // let's query the source contract and make sure it registered an address - query := ReflectSendQueryMsg{Account: &AccountQuery{ChannelID: path.EndpointA.ChannelID}} - var account AccountResponse - err = chainA.SmartQuery(sendContractAddr.String(), query, &account) - require.NoError(t, err) - require.NotEmpty(t, account.RemoteAddr) - require.Empty(t, account.RemoteBalance) - - // close channel - coordinator.CloseChannel(path) - - // let's query the source contract and make sure it registered an address - account = AccountResponse{} - err = chainA.SmartQuery(sendContractAddr.String(), query, &account) - require.Error(t, err) - assert.Contains(t, err.Error(), "not found") -} - -type ReflectSendQueryMsg struct { - Admin *struct{} `json:"admin,omitempty"` - ListAccounts *struct{} `json:"list_accounts,omitempty"` - Account *AccountQuery `json:"account,omitempty"` -} - -type AccountQuery struct { - ChannelID string `json:"channel_id"` -} - -type AccountResponse struct { - LastUpdateTime uint64 `json:"last_update_time,string"` - RemoteAddr string `json:"remote_addr"` - RemoteBalance wasmvmtypes.Coins `json:"remote_balance"` -} diff --git a/sei-wasmd/x/wasm/ibctesting/app.go b/sei-wasmd/x/wasm/ibctesting/app.go deleted file mode 100644 index 7f21d3791f..0000000000 --- a/sei-wasmd/x/wasm/ibctesting/app.go +++ /dev/null @@ -1,31 +0,0 @@ -package ibctesting - -import ( - "github.com/sei-protocol/sei-chain/sei-cosmos/baseapp" - "github.com/sei-protocol/sei-chain/sei-cosmos/client" - sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" - capabilitykeeper "github.com/sei-protocol/sei-chain/sei-cosmos/x/capability/keeper" - stakingkeeper "github.com/sei-protocol/sei-chain/sei-cosmos/x/staking/keeper" - "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/keeper" - - "github.com/sei-protocol/sei-chain/sei-cosmos/codec" - abci "github.com/sei-protocol/sei-chain/sei-tendermint/abci/types" -) - -type TestingApp interface { - abci.Application - - // ibc-go additions - GetBaseApp() *baseapp.BaseApp - GetStakingKeeper() stakingkeeper.Keeper - GetIBCKeeper() *keeper.Keeper - GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper - GetTxConfig() client.TxConfig - - // Implemented by SimApp - AppCodec() codec.Codec - - // Implemented by BaseApp - LastCommitID() sdk.CommitID - LastBlockHeight() int64 -} diff --git a/sei-wasmd/x/wasm/ibctesting/chain.go b/sei-wasmd/x/wasm/ibctesting/chain.go deleted file mode 100644 index 5004f69ba8..0000000000 --- a/sei-wasmd/x/wasm/ibctesting/chain.go +++ /dev/null @@ -1,675 +0,0 @@ -package ibctesting - -import ( - "bytes" - "context" - "fmt" - "math" - "testing" - "time" - - "github.com/sei-protocol/sei-chain/sei-cosmos/baseapp" - "github.com/sei-protocol/sei-chain/sei-cosmos/client" - "github.com/sei-protocol/sei-chain/sei-cosmos/codec" - cryptocodec "github.com/sei-protocol/sei-chain/sei-cosmos/crypto/codec" - "github.com/sei-protocol/sei-chain/sei-cosmos/crypto/keys/ed25519" - "github.com/sei-protocol/sei-chain/sei-cosmos/crypto/keys/secp256k1" - cryptotypes "github.com/sei-protocol/sei-chain/sei-cosmos/crypto/types" - sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" - sdkerrors "github.com/sei-protocol/sei-chain/sei-cosmos/types/errors" - authtypes "github.com/sei-protocol/sei-chain/sei-cosmos/x/auth/types" - banktypes "github.com/sei-protocol/sei-chain/sei-cosmos/x/bank/types" - capabilitykeeper "github.com/sei-protocol/sei-chain/sei-cosmos/x/capability/keeper" - capabilitytypes "github.com/sei-protocol/sei-chain/sei-cosmos/x/capability/types" - stakingkeeper "github.com/sei-protocol/sei-chain/sei-cosmos/x/staking/keeper" - "github.com/sei-protocol/sei-chain/sei-cosmos/x/staking/teststaking" - stakingtypes "github.com/sei-protocol/sei-chain/sei-cosmos/x/staking/types" - clienttypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/types" - channeltypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/04-channel/types" - commitmenttypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/23-commitment/types" - host "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/24-host" - "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/exported" - ibckeeper "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/keeper" - "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/types" - ibctmtypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/light-clients/07-tendermint/types" - abci "github.com/sei-protocol/sei-chain/sei-tendermint/abci/types" - "github.com/sei-protocol/sei-chain/sei-tendermint/crypto" - "github.com/sei-protocol/sei-chain/sei-tendermint/crypto/tmhash" - "github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils" - tmproto "github.com/sei-protocol/sei-chain/sei-tendermint/proto/tendermint/types" - tmtypes "github.com/sei-protocol/sei-chain/sei-tendermint/types" - tmversion "github.com/sei-protocol/sei-chain/sei-tendermint/version" - "github.com/stretchr/testify/require" - - wasmd "github.com/sei-protocol/sei-chain/sei-wasmd/app" - "github.com/sei-protocol/sei-chain/sei-wasmd/x/wasm" -) - -// TestChain is a testing struct that wraps a simapp with the last TM Header, the current ABCI -// header and the validators of the TestChain. It also contains a field called ChainID. This -// is the clientID that *other* chains use to refer to this TestChain. The SenderAccount -// is used for delivering transactions through the application state. -// NOTE: the actual application uses an empty chain-id for ease of testing. -type TestChain struct { - t *testing.T - - Coordinator *Coordinator - App TestingApp - ChainID string - LastHeader *ibctmtypes.Header // header for last block height committed - CurrentHeader tmproto.Header // header for current block height - QueryServer types.QueryServer - TxConfig client.TxConfig - Codec codec.BinaryCodec - - Vals *tmtypes.ValidatorSet - Signers []tmtypes.PrivValidator - - senderPrivKey cryptotypes.PrivKey - SenderAccount authtypes.AccountI - - PendingSendPackets []channeltypes.Packet - PendingAckPackets []PacketAck -} - -type PacketAck struct { - Packet channeltypes.Packet - Ack []byte -} - -type PV struct { - PrivKey cryptotypes.PrivKey -} - -func NewPV() PV { - return PV{ed25519.GenPrivKey()} -} - -// GetPubKey implements PrivValidator interface -func (pv PV) GetPubKey(context.Context) (crypto.PubKey, error) { - return cryptocodec.ToTmPubKeyInterface(pv.PrivKey.PubKey()) -} - -// SignVote implements PrivValidator interface -func (pv PV) SignVote(_ context.Context, chainID string, vote *tmproto.Vote) error { - signBytes := tmtypes.VoteSignBytes(chainID, vote) - sig, err := pv.PrivKey.Sign(signBytes) - if err != nil { - return err - } - vote.Signature = sig - return nil -} - -// SignProposal implements PrivValidator interface -func (pv PV) SignProposal(_ context.Context, chainID string, proposal *tmproto.Proposal) error { - signBytes := tmtypes.ProposalSignBytes(chainID, proposal) - sig, err := pv.PrivKey.Sign(signBytes) - if err != nil { - return err - } - proposal.Signature = sig - return nil -} - -// NewTestChain initializes a new TestChain instance with a single validator set using a -// generated private key. It also creates a sender account to be used for delivering transactions. -// -// The first block height is committed to state in order to allow for client creations on -// counterparty chains. The TestChain will return with a block height starting at 2. -// -// Time management is handled by the Coordinator in order to ensure synchrony between chains. -// Each update of any chain increments the block header time for all chains by 5 seconds. -func NewTestChain(t *testing.T, coord *Coordinator, chainID string, opts ...wasm.Option) *TestChain { - // generate validator private/public key - privVal := NewPV() - pubKey, err := privVal.GetPubKey(context.Background()) - require.NoError(t, err) - - // create validator set with single validator - validator := tmtypes.NewValidator(pubKey, 1) - valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}) - signers := []tmtypes.PrivValidator{privVal} - - // generate genesis account - senderPrivKey := secp256k1.GenPrivKey() - acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0) - amount, ok := sdk.NewIntFromString("10000000000000000000") - require.True(t, ok) - - balance := banktypes.Balance{ - Address: acc.GetAddress().String(), - Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, amount)), - } - - app := NewTestingAppDecorator(t, wasmd.SetupWithGenesisValSet(t, chainID, valSet, []authtypes.GenesisAccount{acc}, opts, balance)) - - // create current header and call begin block - header := tmproto.Header{ - ChainID: chainID, - Height: 1, - Time: coord.CurrentTime.UTC(), - } - - txConfig := app.GetTxConfig() - - // create an account to send transactions from - chain := &TestChain{ - t: t, - Coordinator: coord, - ChainID: chainID, - App: app, - CurrentHeader: header, - QueryServer: app.GetIBCKeeper(), - TxConfig: txConfig, - Codec: app.AppCodec(), - Vals: valSet, - Signers: signers, - senderPrivKey: senderPrivKey, - SenderAccount: acc, - } - - coord.CommitBlock(chain) - - return chain -} - -// GetContext returns the current context for the application. -func (chain *TestChain) GetContext() sdk.Context { - return chain.App.GetBaseApp().NewContext(false, chain.CurrentHeader) -} - -// QueryProof performs an abci query with the given key and returns the proto encoded merkle proof -// for the query and the height at which the proof will succeed on a tendermint verifier. -func (chain *TestChain) QueryProof(key []byte) ([]byte, clienttypes.Height) { - return chain.QueryProofAtHeight(key, chain.App.LastBlockHeight()) -} - -// QueryProof performs an abci query with the given key and returns the proto encoded merkle proof -// for the query and the height at which the proof will succeed on a tendermint verifier. -func (chain *TestChain) QueryProofAtHeight(key []byte, height int64) ([]byte, clienttypes.Height) { - res, _ := chain.App.Query(context.Background(), &abci.RequestQuery{ - Path: fmt.Sprintf("store/%s/key", host.StoreKey), - Height: height - 1, - Data: key, - Prove: true, - }) - - merkleProof, err := commitmenttypes.ConvertProofs(res.ProofOps) - require.NoError(chain.t, err) - - proof, err := chain.App.AppCodec().Marshal(&merkleProof) - require.NoError(chain.t, err) - - revision := clienttypes.ParseChainID(chain.ChainID) - - // proof height + 1 is returned as the proof created corresponds to the height the proof - // was created in the IAVL tree. Tendermint and subsequently the clients that rely on it - // have heights 1 above the IAVL tree. Thus we return proof height + 1 - require.Greater(chain.t, res.Height, int64(0)) - // #nosec G115 -- checked above. - return proof, clienttypes.NewHeight(revision, uint64(res.Height)+1) -} - -// QueryUpgradeProof performs an abci query with the given key and returns the proto encoded merkle proof -// for the query and the height at which the proof will succeed on a tendermint verifier. -func (chain *TestChain) QueryUpgradeProof(key []byte, height uint64) ([]byte, clienttypes.Height) { - require.Less(chain.t, height, math.MaxInt64) - res, _ := chain.App.Query(context.Background(), &abci.RequestQuery{ - Path: "store/upgrade/key", - Height: int64(height - 1), // #nosec G115 -- checked above. - Data: key, - Prove: true, - }) - - merkleProof, err := commitmenttypes.ConvertProofs(res.ProofOps) - require.NoError(chain.t, err) - - proof, err := chain.App.AppCodec().Marshal(&merkleProof) - require.NoError(chain.t, err) - - revision := clienttypes.ParseChainID(chain.ChainID) - - // proof height + 1 is returned as the proof created corresponds to the height the proof - // was created in the IAVL tree. Tendermint and subsequently the clients that rely on it - // have heights 1 above the IAVL tree. Thus we return proof height + 1 - require.Greater(chain.t, res.Height, int64(0)) - // #nosec G115 -- checked above. - return proof, clienttypes.NewHeight(revision, uint64(res.Height+1)) -} - -// QueryConsensusStateProof performs an abci query for a consensus state -// stored on the given clientID. The proof and consensusHeight are returned. -func (chain *TestChain) QueryConsensusStateProof(clientID string) ([]byte, clienttypes.Height) { - clientState := chain.GetClientState(clientID) - - consensusHeight := clientState.GetLatestHeight().(clienttypes.Height) - consensusKey := host.FullConsensusStateKey(clientID, consensusHeight) - proofConsensus, _ := chain.QueryProof(consensusKey) - - return proofConsensus, consensusHeight -} - -// NextBlock sets the last header to the current header and increments the current header to be -// at the next block height. It does not update the time as that is handled by the Coordinator. -// -// CONTRACT: this function must only be called after app.Commit() occurs -func (chain *TestChain) NextBlock() { - // set the last header to the current header - // use nil trusted fields - chain.LastHeader = chain.CurrentTMClientHeader() - - // increment the current header - chain.CurrentHeader = tmproto.Header{ - ChainID: chain.ChainID, - Height: chain.App.LastBlockHeight() + 1, - AppHash: chain.App.LastCommitID().Hash, - // NOTE: the time is increased by the coordinator to maintain time synchrony amongst - // chains. - Time: chain.CurrentHeader.Time, - ValidatorsHash: chain.Vals.Hash(), - NextValidatorsHash: chain.Vals.Hash(), - } - - wasmApp := chain.App.(*TestingAppDecorator).WasmApp - _, err := wasmApp.FinalizeBlock(context.Background(), &abci.RequestFinalizeBlock{ - Header: &tmproto.Header{ - ChainID: chain.ChainID, - Height: chain.App.LastBlockHeight() + 1, - Time: chain.CurrentHeader.Time, - AppHash: chain.CurrentHeader.AppHash, - - ValidatorsHash: chain.Vals.Hash(), - NextValidatorsHash: chain.Vals.Hash(), - }, - }) - require.NoError(chain.t, err) - // wasmApp.BeginBlock(wasmApp.GetContextForDeliverTx([]byte{}), abci.RequestBeginBlock{Header: chain.CurrentHeader}) -} - -// sendMsgs delivers a transaction through the application without returning the result. -func (chain *TestChain) sendMsgs(msgs ...sdk.Msg) error { - _, err := chain.SendMsgs(msgs...) - return err -} - -// SendMsgs delivers a transaction through the application. It updates the senders sequence -// number and updates the TestChain's headers. It returns the result and error if one -// occurred. -func (chain *TestChain) SendMsgs(msgs ...sdk.Msg) (*sdk.Result, error) { - // ensure the chain has the latest time - chain.Coordinator.UpdateTimeForChain(chain) - - _, r, err := wasmd.SignAndDeliver( - chain.t, - chain.TxConfig, - chain.App.GetBaseApp(), - chain.App.GetIBCKeeper(), - chain.App.GetStakingKeeper(), - chain.App.(*TestingAppDecorator).GetCapabilityKeeper(), - chain.App.(*TestingAppDecorator).GetDistrKeeper(), - chain.App.(*TestingAppDecorator).GetSlashingKeeper(), - chain.App.(*TestingAppDecorator).GetEvidenceKeeper(), - chain.GetContext().BlockHeader(), - msgs, - chain.ChainID, - []uint64{chain.SenderAccount.GetAccountNumber()}, - []uint64{chain.SenderAccount.GetSequence()}, - true, true, chain.senderPrivKey, - ) - if err != nil { - return nil, err - } - - // SignAndDeliver calls app.Commit() - chain.NextBlock() - - // increment sequence for successful transaction execution - err = chain.SenderAccount.SetSequence(chain.SenderAccount.GetSequence() + 1) - if err != nil { - return nil, err - } - - chain.captureIBCEvents(r) - - return r, nil -} - -func (chain *TestChain) captureIBCEvents(r *sdk.Result) { - toSend := getSendPackets(r.Events) - if len(toSend) > 0 { - // Keep a queue on the chain that we can relay in tests - chain.PendingSendPackets = append(chain.PendingSendPackets, toSend...) - } - toAck := getAckPackets(r.Events) - if len(toAck) > 0 { - // Keep a queue on the chain that we can relay in tests - chain.PendingAckPackets = append(chain.PendingAckPackets, toAck...) - } -} - -// GetClientState retrieves the client state for the provided clientID. The client is -// expected to exist otherwise testing will fail. -func (chain *TestChain) GetClientState(clientID string) exported.ClientState { - clientState, found := chain.App.GetIBCKeeper().ClientKeeper.GetClientState(chain.GetContext(), clientID) - require.True(chain.t, found) - - return clientState -} - -// GetConsensusState retrieves the consensus state for the provided clientID and height. -// It will return a success boolean depending on if consensus state exists or not. -func (chain *TestChain) GetConsensusState(clientID string, height exported.Height) (exported.ConsensusState, bool) { - return chain.App.GetIBCKeeper().ClientKeeper.GetClientConsensusState(chain.GetContext(), clientID, height) -} - -// GetValsAtHeight will return the validator set of the chain at a given height. It will return -// a success boolean depending on if the validator set exists or not at that height. -func (chain *TestChain) GetValsAtHeight(height int64) (*tmtypes.ValidatorSet, bool) { - histInfo, ok := chain.App.GetStakingKeeper().GetHistoricalInfo(chain.GetContext(), height) - if !ok { - return nil, false - } - - valSet := stakingtypes.Validators(histInfo.Valset) - - tmValidators, err := teststaking.ToTmValidators(valSet, sdk.DefaultPowerReduction) - if err != nil { - panic(err) - } - return tmtypes.NewValidatorSet(tmValidators), true -} - -// GetAcknowledgement retrieves an acknowledgement for the provided packet. If the -// acknowledgement does not exist then testing will fail. -func (chain *TestChain) GetAcknowledgement(packet exported.PacketI) []byte { - ack, found := chain.App.GetIBCKeeper().ChannelKeeper.GetPacketAcknowledgement(chain.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - require.True(chain.t, found) - - return ack -} - -// GetPrefix returns the prefix for used by a chain in connection creation -func (chain *TestChain) GetPrefix() commitmenttypes.MerklePrefix { - return commitmenttypes.NewMerklePrefix(chain.App.GetIBCKeeper().ConnectionKeeper.GetCommitmentPrefix().Bytes()) -} - -// ConstructUpdateTMClientHeader will construct a valid 07-tendermint Header to update the -// light client on the source chain. -func (chain *TestChain) ConstructUpdateTMClientHeader(counterparty *TestChain, clientID string) (*ibctmtypes.Header, error) { - return chain.ConstructUpdateTMClientHeaderWithTrustedHeight(counterparty, clientID, clienttypes.ZeroHeight()) -} - -// ConstructUpdateTMClientHeader will construct a valid 07-tendermint Header to update the -// light client on the source chain. -func (chain *TestChain) ConstructUpdateTMClientHeaderWithTrustedHeight(counterparty *TestChain, clientID string, trustedHeight clienttypes.Height) (*ibctmtypes.Header, error) { - header := counterparty.LastHeader - // Relayer must query for LatestHeight on client to get TrustedHeight if the trusted height is not set - if trustedHeight.IsZero() { - trustedHeight = chain.GetClientState(clientID).GetLatestHeight().(clienttypes.Height) - } - var ( - tmTrustedVals *tmtypes.ValidatorSet - ok bool - ) - // Once we get TrustedHeight from client, we must query the validators from the counterparty chain - // If the LatestHeight == LastHeader.Height, then TrustedValidators are current validators - // If LatestHeight < LastHeader.Height, we can query the historical validator set from HistoricalInfo - if trustedHeight == counterparty.LastHeader.GetHeight() { - tmTrustedVals = counterparty.Vals - } else { - // NOTE: We need to get validators from counterparty at height: trustedHeight+1 - // since the last trusted validators for a header at height h - // is the NextValidators at h+1 committed to in header h by - // NextValidatorsHash - require.Less(chain.t, trustedHeight.RevisionHeight+1, uint64(math.MaxInt64)) - // #nosec G115 -- checked above - tmTrustedVals, ok = counterparty.GetValsAtHeight(int64(trustedHeight.RevisionHeight + 1)) - if !ok { - return nil, sdkerrors.Wrapf(ibctmtypes.ErrInvalidHeaderHeight, "could not retrieve trusted validators at trustedHeight: %d", trustedHeight) - } - } - // inject trusted fields into last header - // for now assume revision number is 0 - header.TrustedHeight = trustedHeight - - trustedVals, err := tmTrustedVals.ToProto() - if err != nil { - return nil, err - } - header.TrustedValidators = trustedVals - - return header, nil -} - -// ExpireClient fast forwards the chain's block time by the provided amount of time which will -// expire any clients with a trusting period less than or equal to this amount of time. -func (chain *TestChain) ExpireClient(amount time.Duration) { - chain.Coordinator.IncrementTimeBy(amount) -} - -// CurrentTMClientHeader creates a TM header using the current header parameters -// on the chain. The trusted fields in the header are set to nil. -func (chain *TestChain) CurrentTMClientHeader() *ibctmtypes.Header { - return chain.CreateTMClientHeader(chain.ChainID, chain.CurrentHeader.Height, clienttypes.Height{}, chain.CurrentHeader.Time, chain.Vals, nil, chain.Signers) -} - -// CreateTMClientHeader creates a TM header to update the TM client. Args are passed in to allow -// caller flexibility to use params that differ from the chain. -func (chain *TestChain) CreateTMClientHeader(chainID string, blockHeight int64, trustedHeight clienttypes.Height, timestamp time.Time, tmValSet, tmTrustedVals *tmtypes.ValidatorSet, signers []tmtypes.PrivValidator) *ibctmtypes.Header { - var ( - valSet *tmproto.ValidatorSet - trustedVals *tmproto.ValidatorSet - ) - require.NotNil(chain.t, tmValSet) - - vsetHash := tmValSet.Hash() - - tmHeader := tmtypes.Header{ - Version: tmversion.Consensus{Block: tmversion.BlockProtocol, App: 2}, - ChainID: chainID, - Height: blockHeight, - Time: timestamp, - LastBlockID: MakeBlockID(make([]byte, tmhash.Size), tmtypes.MaxBlockPartsCount, make([]byte, tmhash.Size)), - LastCommitHash: chain.App.LastCommitID().Hash, - DataHash: tmhash.Sum([]byte("data_hash")), - ValidatorsHash: vsetHash, - NextValidatorsHash: vsetHash, - ConsensusHash: tmhash.Sum([]byte("consensus_hash")), - AppHash: chain.CurrentHeader.AppHash, - LastResultsHash: tmhash.Sum([]byte("last_results_hash")), - EvidenceHash: tmhash.Sum([]byte("evidence_hash")), - ProposerAddress: tmValSet.Proposer.Address, //nolint:staticcheck - } - hhash := tmHeader.Hash() - blockID := MakeBlockID(hhash, 3, tmhash.Sum([]byte("part_set"))) - voteSet := tmtypes.NewVoteSet(chainID, blockHeight, 1, tmproto.PrecommitType, tmValSet) - require.LessOrEqual(chain.t, len(tmValSet.Validators), math.MaxInt32, "validator set size exceeds max int32") - for i, val := range tmValSet.Validators { - privVal := signers[i] - vote := &tmtypes.Vote{ - Type: tmproto.PrecommitType, - Height: blockHeight, - Round: 1, - BlockID: blockID, - Timestamp: timestamp, - ValidatorAddress: val.Address, - ValidatorIndex: int32(i), // #nosec G115 -- validator set size is checked above - } - v := vote.ToProto() - err := privVal.SignVote(context.Background(), chainID, v) - require.NoError(chain.t, err) - vote.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(v.Signature))) - _, err = voteSet.AddVote(vote) - require.NoError(chain.t, err) - } - - commit := voteSet.MakeCommit() - - signedHeader := &tmproto.SignedHeader{ - Header: tmHeader.ToProto(), - Commit: commit.ToProto(), - } - - valSet, err := tmValSet.ToProto() - require.NoError(chain.t, err) - - if tmTrustedVals != nil { - trustedVals, err = tmTrustedVals.ToProto() - require.NoError(chain.t, err) - } - - // The trusted fields may be nil. They may be filled before relaying messages to a client. - // The relayer is responsible for querying client and injecting appropriate trusted fields. - return &ibctmtypes.Header{ - SignedHeader: signedHeader, - ValidatorSet: valSet, - TrustedHeight: trustedHeight, - TrustedValidators: trustedVals, - } -} - -// MakeBlockID copied unimported test functions from tmtypes to use them here -func MakeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) tmtypes.BlockID { - return tmtypes.BlockID{ - Hash: hash, - PartSetHeader: tmtypes.PartSetHeader{ - Total: partSetSize, - Hash: partSetHash, - }, - } -} - -// CreateSortedSignerArray takes two PrivValidators, and the corresponding Validator structs -// (including voting power). It returns a signer array of PrivValidators that matches the -// sorting of ValidatorSet. -// The sorting is first by .VotingPower (descending), with secondary index of .Address (ascending). -func CreateSortedSignerArray(altPrivVal, suitePrivVal tmtypes.PrivValidator, - altVal, suiteVal *tmtypes.Validator, -) []tmtypes.PrivValidator { - switch { - case altVal.VotingPower > suiteVal.VotingPower: - return []tmtypes.PrivValidator{altPrivVal, suitePrivVal} - case altVal.VotingPower < suiteVal.VotingPower: - return []tmtypes.PrivValidator{suitePrivVal, altPrivVal} - default: - if bytes.Compare(altVal.Address, suiteVal.Address) == -1 { - return []tmtypes.PrivValidator{altPrivVal, suitePrivVal} - } - return []tmtypes.PrivValidator{suitePrivVal, altPrivVal} - } -} - -// CreatePortCapability binds and claims a capability for the given portID if it does not -// already exist. This function will fail testing on any resulting error. -// NOTE: only creation of a capbility for a transfer or mock port is supported -// Other applications must bind to the port in InitGenesis or modify this code. -func (chain *TestChain) CreatePortCapability(scopedKeeper capabilitykeeper.ScopedKeeper, portID string) { - // ensure the chain has the latest time - // check if the portId is already binded, if not bind it - _, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), host.PortPath(portID)) - if !ok { - // create capability using the IBC capability keeper - cap, err := chain.App.GetScopedIBCKeeper().NewCapability(chain.GetContext(), host.PortPath(portID)) - require.NoError(chain.t, err) - - // claim capability using the scopedKeeper - err = scopedKeeper.ClaimCapability(chain.GetContext(), cap, host.PortPath(portID)) - require.NoError(chain.t, err) - } - - wasmApp := chain.App.(*TestingAppDecorator).WasmApp - wasmApp.SetDeliverStateToCommit() - _, err := chain.App.Commit(context.Background()) - require.NoError(chain.t, err) - - chain.NextBlock() -} - -// GetPortCapability returns the port capability for the given portID. The capability must -// exist, otherwise testing will fail. -func (chain *TestChain) GetPortCapability(portID string) *capabilitytypes.Capability { - cap, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), host.PortPath(portID)) - require.True(chain.t, ok) - - return cap -} - -// CreateChannelCapability binds and claims a capability for the given portID and channelID -// if it does not already exist. This function will fail testing on any resulting error. The -// scoped keeper passed in will claim the new capability. -func (chain *TestChain) CreateChannelCapability(scopedKeeper capabilitykeeper.ScopedKeeper, portID, channelID string) { - // ensure the chain has the latest time - capName := host.ChannelCapabilityPath(portID, channelID) - // check if the portId is already binded, if not bind it - _, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), capName) - if !ok { - cap, err := chain.App.GetScopedIBCKeeper().NewCapability(chain.GetContext(), capName) - require.NoError(chain.t, err) - err = scopedKeeper.ClaimCapability(chain.GetContext(), cap, capName) - require.NoError(chain.t, err) - } - - wasmApp := chain.App.(*TestingAppDecorator).WasmApp - wasmApp.SetDeliverStateToCommit() - _, err := chain.App.Commit(context.Background()) - require.NoError(chain.t, err) - - chain.NextBlock() -} - -// GetChannelCapability returns the channel capability for the given portID and channelID. -// The capability must exist, otherwise testing will fail. -func (chain *TestChain) GetChannelCapability(portID, channelID string) *capabilitytypes.Capability { - cap, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), host.ChannelCapabilityPath(portID, channelID)) - require.True(chain.t, ok) - - return cap -} - -func (chain *TestChain) Balance(acc sdk.AccAddress, denom string) sdk.Coin { - return chain.GetTestSupport().BankKeeper().GetBalance(chain.GetContext(), acc, denom) -} - -func (chain *TestChain) AllBalances(acc sdk.AccAddress) sdk.Coins { - return chain.GetTestSupport().BankKeeper().GetAllBalances(chain.GetContext(), acc) -} - -func (chain TestChain) GetTestSupport() *wasmd.TestSupport { - return chain.App.(*TestingAppDecorator).TestSupport() -} - -var _ TestingApp = TestingAppDecorator{} - -type TestingAppDecorator struct { - *wasmd.WasmApp - t *testing.T -} - -func NewTestingAppDecorator(t *testing.T, wasmApp *wasmd.WasmApp) *TestingAppDecorator { - return &TestingAppDecorator{WasmApp: wasmApp, t: t} -} - -func (a TestingAppDecorator) GetBaseApp() *baseapp.BaseApp { - return a.TestSupport().GetBaseApp() -} - -func (a TestingAppDecorator) GetStakingKeeper() stakingkeeper.Keeper { - return a.TestSupport().StakingKeeper() -} - -func (a TestingAppDecorator) GetIBCKeeper() *ibckeeper.Keeper { - return a.TestSupport().IBCKeeper() -} - -func (a TestingAppDecorator) GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper { - return a.TestSupport().ScopeIBCKeeper() -} - -func (a TestingAppDecorator) GetTxConfig() client.TxConfig { - return a.TestSupport().GetTxConfig() -} - -func (a TestingAppDecorator) TestSupport() *wasmd.TestSupport { - return wasmd.NewTestSupport(a.t, a.WasmApp) -} diff --git a/sei-wasmd/x/wasm/ibctesting/config.go b/sei-wasmd/x/wasm/ibctesting/config.go deleted file mode 100644 index 3151d57c9c..0000000000 --- a/sei-wasmd/x/wasm/ibctesting/config.go +++ /dev/null @@ -1,64 +0,0 @@ -package ibctesting - -import ( - "time" - - connectiontypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/03-connection/types" - channeltypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/04-channel/types" - "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/exported" - ibctmtypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/light-clients/07-tendermint/types" -) - -type ClientConfig interface { - GetClientType() string -} - -type TendermintConfig struct { - TrustLevel ibctmtypes.Fraction - TrustingPeriod time.Duration - UnbondingPeriod time.Duration - MaxClockDrift time.Duration - AllowUpdateAfterExpiry bool - AllowUpdateAfterMisbehaviour bool -} - -func NewTendermintConfig() *TendermintConfig { - return &TendermintConfig{ - TrustLevel: DefaultTrustLevel, - TrustingPeriod: TrustingPeriod, - UnbondingPeriod: UnbondingPeriod, - MaxClockDrift: MaxClockDrift, - AllowUpdateAfterExpiry: false, - AllowUpdateAfterMisbehaviour: false, - } -} - -func (tmcfg *TendermintConfig) GetClientType() string { - return exported.Tendermint -} - -type ConnectionConfig struct { - DelayPeriod uint64 - Version *connectiontypes.Version -} - -func NewConnectionConfig() *ConnectionConfig { - return &ConnectionConfig{ - DelayPeriod: DefaultDelayPeriod, - Version: ConnectionVersion, - } -} - -type ChannelConfig struct { - PortID string - Version string - Order channeltypes.Order -} - -func NewChannelConfig() *ChannelConfig { - return &ChannelConfig{ - PortID: MockPort, - Version: DefaultChannelVersion, - Order: channeltypes.UNORDERED, - } -} diff --git a/sei-wasmd/x/wasm/ibctesting/coordinator.go b/sei-wasmd/x/wasm/ibctesting/coordinator.go deleted file mode 100644 index a71715bfd6..0000000000 --- a/sei-wasmd/x/wasm/ibctesting/coordinator.go +++ /dev/null @@ -1,371 +0,0 @@ -package ibctesting - -import ( - "context" - "fmt" - "strconv" - "testing" - "time" - - channeltypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/04-channel/types" - host "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/24-host" - - abci "github.com/sei-protocol/sei-chain/sei-tendermint/abci/types" - tmproto "github.com/sei-protocol/sei-chain/sei-tendermint/proto/tendermint/types" - "github.com/stretchr/testify/require" - - wasmkeeper "github.com/sei-protocol/sei-chain/sei-wasmd/x/wasm/keeper" -) - -const ChainIDPrefix = "testchain" - -var ( - globalStartTime = time.Date(2020, 12, 4, 10, 30, 0, 0, time.UTC) - TimeIncrement = time.Second * 5 -) - -// Coordinator is a testing struct which contains N TestChain's. It handles keeping all chains -// in sync with regards to time. -type Coordinator struct { - t *testing.T - - CurrentTime time.Time - Chains map[string]*TestChain -} - -// NewCoordinator initializes Coordinator with N TestChain's -func NewCoordinator(t *testing.T, n int, opts ...[]wasmkeeper.Option) *Coordinator { - chains := make(map[string]*TestChain) - coord := &Coordinator{ - t: t, - CurrentTime: globalStartTime, - } - - for i := 0; i < n; i++ { - chainID := GetChainID(i) - var x []wasmkeeper.Option - if len(opts) > i { - x = opts[i] - } - chains[chainID] = NewTestChain(t, coord, chainID, x...) - } - coord.Chains = chains - - return coord -} - -// IncrementTime iterates through all the TestChain's and increments their current header time -// by 5 seconds. -// -// CONTRACT: this function must be called after every Commit on any TestChain. -func (coord *Coordinator) IncrementTime() { - coord.IncrementTimeBy(TimeIncrement) -} - -// IncrementTimeBy iterates through all the TestChain's and increments their current header time -// by specified time. -func (coord *Coordinator) IncrementTimeBy(increment time.Duration) { - coord.CurrentTime = coord.CurrentTime.Add(increment).UTC() - coord.UpdateTime() -} - -// UpdateTime updates all clocks for the TestChains to the current global time. -func (coord *Coordinator) UpdateTime() { - for _, chain := range coord.Chains { - coord.UpdateTimeForChain(chain) - } -} - -// UpdateTimeForChain updates the clock for a specific chain. -func (coord *Coordinator) UpdateTimeForChain(chain *TestChain) { - chain.CurrentHeader.Time = coord.CurrentTime.UTC() - wasmApp := chain.App.(*TestingAppDecorator).WasmApp - _, err := wasmApp.FinalizeBlock(context.Background(), &abci.RequestFinalizeBlock{ - Header: &tmproto.Header{ - ChainID: chain.ChainID, - Height: chain.App.LastBlockHeight() + 1, - Time: chain.CurrentHeader.Time, - AppHash: chain.CurrentHeader.AppHash, - - ValidatorsHash: chain.Vals.Hash(), - NextValidatorsHash: chain.Vals.Hash(), - }, - }) - require.NoError(coord.t, err) -} - -// Setup constructs a TM client, connection, and channel on both chains provided. It will -// fail if any error occurs. The clientID's, TestConnections, and TestChannels are returned -// for both chains. The channels created are connected to the ibc-transfer application. -func (coord *Coordinator) Setup(path *Path) { - coord.SetupConnections(path) - - // channels can also be referenced through the returned connections - coord.CreateChannels(path) -} - -// SetupClients is a helper function to create clients on both chains. It assumes the -// caller does not anticipate any errors. -func (coord *Coordinator) SetupClients(path *Path) { - err := path.EndpointA.CreateClient() - require.NoError(coord.t, err) - - err = path.EndpointB.CreateClient() - require.NoError(coord.t, err) -} - -// SetupClientConnections is a helper function to create clients and the appropriate -// connections on both the source and counterparty chain. It assumes the caller does not -// anticipate any errors. -func (coord *Coordinator) SetupConnections(path *Path) { - coord.SetupClients(path) - - coord.CreateConnections(path) -} - -// CreateConnection constructs and executes connection handshake messages in order to create -// OPEN channels on chainA and chainB. The connection information of for chainA and chainB -// are returned within a TestConnection struct. The function expects the connections to be -// successfully opened otherwise testing will fail. -func (coord *Coordinator) CreateConnections(path *Path) { - err := path.EndpointA.ConnOpenInit() - require.NoError(coord.t, err) - - err = path.EndpointB.ConnOpenTry() - require.NoError(coord.t, err) - - err = path.EndpointA.ConnOpenAck() - require.NoError(coord.t, err) - - err = path.EndpointB.ConnOpenConfirm() - require.NoError(coord.t, err) - - // ensure counterparty is up to date - err = path.EndpointA.UpdateClient() - require.NoError(coord.t, err) -} - -// CreateMockChannels constructs and executes channel handshake messages to create OPEN -// channels that use a mock application module that returns nil on all callbacks. This -// function is expects the channels to be successfully opened otherwise testing will -// fail. -func (coord *Coordinator) CreateMockChannels(path *Path) { - path.EndpointA.ChannelConfig.PortID = MockPort - path.EndpointB.ChannelConfig.PortID = MockPort - - coord.CreateChannels(path) -} - -// CreateTransferChannels constructs and executes channel handshake messages to create OPEN -// ibc-transfer channels on chainA and chainB. The function expects the channels to be -// successfully opened otherwise testing will fail. -func (coord *Coordinator) CreateTransferChannels(path *Path) { - path.EndpointA.ChannelConfig.PortID = TransferPort - path.EndpointB.ChannelConfig.PortID = TransferPort - - coord.CreateChannels(path) -} - -// CreateChannel constructs and executes channel handshake messages in order to create -// OPEN channels on chainA and chainB. The function expects the channels to be successfully -// opened otherwise testing will fail. -func (coord *Coordinator) CreateChannels(path *Path) { - err := path.EndpointA.ChanOpenInit() - require.NoError(coord.t, err) - - err = path.EndpointB.ChanOpenTry() - require.NoError(coord.t, err) - - err = path.EndpointA.ChanOpenAck() - require.NoError(coord.t, err) - - err = path.EndpointB.ChanOpenConfirm() - require.NoError(coord.t, err) - - // ensure counterparty is up to date - err = path.EndpointA.UpdateClient() - require.NoError(coord.t, err) -} - -// GetChain returns the TestChain using the given chainID and returns an error if it does -// not exist. -func (coord *Coordinator) GetChain(chainID string) *TestChain { - chain, found := coord.Chains[chainID] - require.True(coord.t, found, fmt.Sprintf("%s chain does not exist", chainID)) - return chain -} - -// GetChainID returns the chainID used for the provided index. -func GetChainID(index int) string { - return ChainIDPrefix + strconv.Itoa(index) -} - -// CommitBlock commits a block on the provided indexes and then increments the global time. -// -// CONTRACT: the passed in list of indexes must not contain duplicates -func (coord *Coordinator) CommitBlock(chains ...*TestChain) { - for _, chain := range chains { - wasmApp := chain.App.(*TestingAppDecorator).WasmApp - wasmApp.SetDeliverStateToCommit() - _, err := wasmApp.Commit(context.Background()) - require.NoError(coord.t, err) - chain.NextBlock() - } - coord.IncrementTime() -} - -// CommitNBlocks commits n blocks to state and updates the block height by 1 for each commit. -func (coord *Coordinator) CommitNBlocks(chain *TestChain, n uint64) { - for i := uint64(0); i < n; i++ { - wasmApp := chain.App.(*TestingAppDecorator).WasmApp - _, err := wasmApp.FinalizeBlock(context.Background(), &abci.RequestFinalizeBlock{ - Header: &tmproto.Header{ - Height: chain.App.LastBlockHeight() + 1, - Time: chain.CurrentHeader.Time, - AppHash: chain.CurrentHeader.AppHash, - - ValidatorsHash: chain.Vals.Hash(), - NextValidatorsHash: chain.Vals.Hash(), - }, - }) - require.NoError(coord.t, err) - wasmApp.SetDeliverStateToCommit() - _, err = chain.App.Commit(context.Background()) - require.NoError(coord.t, err) - chain.NextBlock() - coord.IncrementTime() - } -} - -// ConnOpenInitOnBothChains initializes a connection on both endpoints with the state INIT -// using the OpenInit handshake call. -func (coord *Coordinator) ConnOpenInitOnBothChains(path *Path) error { - if err := path.EndpointA.ConnOpenInit(); err != nil { - return err - } - - if err := path.EndpointB.ConnOpenInit(); err != nil { - return err - } - - if err := path.EndpointA.UpdateClient(); err != nil { - return err - } - - if err := path.EndpointB.UpdateClient(); err != nil { - return err - } - - return nil -} - -// ChanOpenInitOnBothChains initializes a channel on the source chain and counterparty chain -// with the state INIT using the OpenInit handshake call. -func (coord *Coordinator) ChanOpenInitOnBothChains(path *Path) error { - // NOTE: only creation of a capability for a transfer or mock port is supported - // Other applications must bind to the port in InitGenesis or modify this code. - - if err := path.EndpointA.ChanOpenInit(); err != nil { - return err - } - - if err := path.EndpointB.ChanOpenInit(); err != nil { - return err - } - - if err := path.EndpointA.UpdateClient(); err != nil { - return err - } - - if err := path.EndpointB.UpdateClient(); err != nil { - return err - } - - return nil -} - -// from A to B -func (coord *Coordinator) RelayAndAckPendingPackets(path *Path) error { - // get all the packet to relay src->dest - src := path.EndpointA - dest := path.EndpointB - toSend := src.Chain.PendingSendPackets - coord.t.Logf("Relay %d Packets A->B\n", len(toSend)) - - // send this to the other side - coord.IncrementTime() - coord.CommitBlock(src.Chain) - err := dest.UpdateClient() - if err != nil { - return err - } - for _, packet := range toSend { - err = dest.RecvPacket(packet) - if err != nil { - return err - } - } - src.Chain.PendingSendPackets = nil - - // get all the acks to relay dest->src - toAck := dest.Chain.PendingAckPackets - // TODO: assert >= len(toSend)? - coord.t.Logf("Ack %d Packets B->A\n", len(toAck)) - - // send the ack back from dest -> src - coord.IncrementTime() - coord.CommitBlock(dest.Chain) - err = src.UpdateClient() - if err != nil { - return err - } - for _, ack := range toAck { - err = src.AcknowledgePacket(ack.Packet, ack.Ack) - if err != nil { - return err - } - } - dest.Chain.PendingAckPackets = nil - return nil -} - -// TimeoutPendingPackets returns the package to source chain to let the IBC app revert any operation. -// from A to A -func (coord *Coordinator) TimeoutPendingPackets(path *Path) error { - src := path.EndpointA - dest := path.EndpointB - - toSend := src.Chain.PendingSendPackets - coord.t.Logf("Timeout %d Packets A->A\n", len(toSend)) - - if err := src.UpdateClient(); err != nil { - return err - } - // Increment time and commit block so that 5 second delay period passes between send and receive - coord.IncrementTime() - coord.CommitBlock(src.Chain, dest.Chain) - for _, packet := range toSend { - // get proof of packet unreceived on dest - packetKey := host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - proofUnreceived, proofHeight := dest.QueryProof(packetKey) - timeoutMsg := channeltypes.NewMsgTimeout(packet, packet.Sequence, proofUnreceived, proofHeight, src.Chain.SenderAccount.GetAddress().String()) - err := src.Chain.sendMsgs(timeoutMsg) - if err != nil { - return err - } - } - src.Chain.PendingSendPackets = nil - dest.Chain.PendingAckPackets = nil - return nil -} - -// CloseChannel close channel on both sides -func (coord *Coordinator) CloseChannel(path *Path) { - err := path.EndpointA.ChanCloseInit() - require.NoError(coord.t, err) - coord.IncrementTime() - err = path.EndpointB.UpdateClient() - require.NoError(coord.t, err) - err = path.EndpointB.ChanCloseConfirm() - require.NoError(coord.t, err) -} diff --git a/sei-wasmd/x/wasm/ibctesting/endpoint.go b/sei-wasmd/x/wasm/ibctesting/endpoint.go deleted file mode 100644 index fafbf70b53..0000000000 --- a/sei-wasmd/x/wasm/ibctesting/endpoint.go +++ /dev/null @@ -1,544 +0,0 @@ -package ibctesting - -import ( - "fmt" - "math" - - // sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" - "github.com/stretchr/testify/require" - - clienttypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/types" - connectiontypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/03-connection/types" - channeltypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/04-channel/types" - commitmenttypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/23-commitment/types" - host "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/24-host" - "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/exported" - ibctmtypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/light-clients/07-tendermint/types" -) - -// Endpoint is a which represents a channel endpoint and its associated -// client and connections. It contains client, connection, and channel -// configuration parameters. Endpoint functions will utilize the parameters -// set in the configuration structs when executing IBC messages. -type Endpoint struct { - Chain *TestChain - Counterparty *Endpoint - ClientID string - ConnectionID string - ChannelID string - - ClientConfig ClientConfig - ConnectionConfig *ConnectionConfig - ChannelConfig *ChannelConfig -} - -// NewEndpoint constructs a new endpoint without the counterparty. -// CONTRACT: the counterparty endpoint must be set by the caller. -func NewEndpoint( - chain *TestChain, clientConfig ClientConfig, - connectionConfig *ConnectionConfig, channelConfig *ChannelConfig, -) *Endpoint { - return &Endpoint{ - Chain: chain, - ClientConfig: clientConfig, - ConnectionConfig: connectionConfig, - ChannelConfig: channelConfig, - } -} - -// NewDefaultEndpoint constructs a new endpoint using default values. -// CONTRACT: the counterparty endpoitn must be set by the caller. -func NewDefaultEndpoint(chain *TestChain) *Endpoint { - return &Endpoint{ - Chain: chain, - ClientConfig: NewTendermintConfig(), - ConnectionConfig: NewConnectionConfig(), - ChannelConfig: NewChannelConfig(), - } -} - -// QueryProof queries proof associated with this endpoint using the lastest client state -// height on the counterparty chain. -func (endpoint *Endpoint) QueryProof(key []byte) ([]byte, clienttypes.Height) { - // obtain the counterparty client representing the chain associated with the endpoint - clientState := endpoint.Counterparty.Chain.GetClientState(endpoint.Counterparty.ClientID) - - // query proof on the counterparty using the latest height of the IBC client - return endpoint.QueryProofAtHeight(key, clientState.GetLatestHeight().GetRevisionHeight()) -} - -// QueryProofAtHeight queries proof associated with this endpoint using the proof height -// providied -func (endpoint *Endpoint) QueryProofAtHeight(key []byte, height uint64) ([]byte, clienttypes.Height) { - // query proof on the counterparty using the latest height of the IBC client - if height > math.MaxInt64 { - panic("height exceeds max int64") - } - // #nosec G115 -- height is bounds checked above - return endpoint.Chain.QueryProofAtHeight(key, int64(height)) -} - -// CreateClient creates an IBC client on the endpoint. It will update the -// clientID for the endpoint if the message is successfully executed. -// NOTE: a solo machine client will be created with an empty diversifier. -func (endpoint *Endpoint) CreateClient() (err error) { - // ensure counterparty has committed state - endpoint.Chain.Coordinator.CommitBlock(endpoint.Counterparty.Chain) - - var ( - clientState exported.ClientState - consensusState exported.ConsensusState - ) - - switch endpoint.ClientConfig.GetClientType() { - case exported.Tendermint: - tmConfig, ok := endpoint.ClientConfig.(*TendermintConfig) - require.True(endpoint.Chain.t, ok) - - height := endpoint.Counterparty.Chain.LastHeader.GetHeight().(clienttypes.Height) - clientState = ibctmtypes.NewClientState( - endpoint.Counterparty.Chain.ChainID, tmConfig.TrustLevel, tmConfig.TrustingPeriod, tmConfig.UnbondingPeriod, tmConfig.MaxClockDrift, - height, commitmenttypes.GetSDKSpecs(), UpgradePath, tmConfig.AllowUpdateAfterExpiry, tmConfig.AllowUpdateAfterMisbehaviour, - ) - consensusState = endpoint.Counterparty.Chain.LastHeader.ConsensusState() - case exported.Solomachine: - // TODO - // solo := NewSolomachine(chain.t, endpoint.Chain.Codec, clientID, "", 1) - // clientState = solo.ClientState() - // consensusState = solo.ConsensusState() - - default: - err = fmt.Errorf("client type %s is not supported", endpoint.ClientConfig.GetClientType()) - } - - if err != nil { - return err - } - - msg, err := clienttypes.NewMsgCreateClient( - clientState, consensusState, endpoint.Chain.SenderAccount.GetAddress().String(), - ) - require.NoError(endpoint.Chain.t, err) - - res, err := endpoint.Chain.SendMsgs(msg) - if err != nil { - return err - } - - endpoint.ClientID, err = ParseClientIDFromEvents(res.GetEvents()) - require.NoError(endpoint.Chain.t, err) - - return nil -} - -// UpdateClient updates the IBC client associated with the endpoint. -func (endpoint *Endpoint) UpdateClient() (err error) { - // ensure counterparty has committed state - endpoint.Chain.Coordinator.CommitBlock(endpoint.Counterparty.Chain) - - var header exported.Header - - switch endpoint.ClientConfig.GetClientType() { - case exported.Tendermint: - header, err = endpoint.Chain.ConstructUpdateTMClientHeader(endpoint.Counterparty.Chain, endpoint.ClientID) - - default: - err = fmt.Errorf("client type %s is not supported", endpoint.ClientConfig.GetClientType()) - } - - if err != nil { - return err - } - - msg, err := clienttypes.NewMsgUpdateClient( - endpoint.ClientID, header, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - require.NoError(endpoint.Chain.t, err) - - return endpoint.Chain.sendMsgs(msg) -} - -// ConnOpenInit will construct and execute a MsgConnectionOpenInit on the associated endpoint. -func (endpoint *Endpoint) ConnOpenInit() error { - msg := connectiontypes.NewMsgConnectionOpenInit( - endpoint.ClientID, - endpoint.Counterparty.ClientID, - endpoint.Counterparty.Chain.GetPrefix(), DefaultOpenInitVersion, endpoint.ConnectionConfig.DelayPeriod, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - res, err := endpoint.Chain.SendMsgs(msg) - if err != nil { - return err - } - - endpoint.ConnectionID, err = ParseConnectionIDFromEvents(res.GetEvents()) - require.NoError(endpoint.Chain.t, err) - - return nil -} - -// ConnOpenTry will construct and execute a MsgConnectionOpenTry on the associated endpoint. -func (endpoint *Endpoint) ConnOpenTry() error { - if err := endpoint.UpdateClient(); err != nil { - return err - } - - counterpartyClient, proofClient, proofConsensus, consensusHeight, proofInit, proofHeight := endpoint.QueryConnectionHandshakeProof() - - msg := connectiontypes.NewMsgConnectionOpenTry( - "", endpoint.ClientID, // does not support handshake continuation - endpoint.Counterparty.ConnectionID, endpoint.Counterparty.ClientID, - counterpartyClient, endpoint.Counterparty.Chain.GetPrefix(), []*connectiontypes.Version{ConnectionVersion}, endpoint.ConnectionConfig.DelayPeriod, - proofInit, proofClient, proofConsensus, - proofHeight, consensusHeight, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - res, err := endpoint.Chain.SendMsgs(msg) - if err != nil { - return err - } - - if endpoint.ConnectionID == "" { - endpoint.ConnectionID, err = ParseConnectionIDFromEvents(res.GetEvents()) - require.NoError(endpoint.Chain.t, err) - } - - return nil -} - -// ConnOpenAck will construct and execute a MsgConnectionOpenAck on the associated endpoint. -func (endpoint *Endpoint) ConnOpenAck() error { - if err := endpoint.UpdateClient(); err != nil { - return err - } - - counterpartyClient, proofClient, proofConsensus, consensusHeight, proofTry, proofHeight := endpoint.QueryConnectionHandshakeProof() - - msg := connectiontypes.NewMsgConnectionOpenAck( - endpoint.ConnectionID, endpoint.Counterparty.ConnectionID, counterpartyClient, // testing doesn't use flexible selection - proofTry, proofClient, proofConsensus, - proofHeight, consensusHeight, - ConnectionVersion, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - return endpoint.Chain.sendMsgs(msg) -} - -// ConnOpenConfirm will construct and execute a MsgConnectionOpenConfirm on the associated endpoint. -func (endpoint *Endpoint) ConnOpenConfirm() error { - if err := endpoint.UpdateClient(); err != nil { - return err - } - - connectionKey := host.ConnectionKey(endpoint.Counterparty.ConnectionID) - proof, height := endpoint.Counterparty.Chain.QueryProof(connectionKey) - - msg := connectiontypes.NewMsgConnectionOpenConfirm( - endpoint.ConnectionID, - proof, height, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - return endpoint.Chain.sendMsgs(msg) -} - -// QueryConnectionHandshakeProof returns all the proofs necessary to execute OpenTry or Open Ack of -// the connection handshakes. It returns the counterparty client state, proof of the counterparty -// client state, proof of the counterparty consensus state, the consensus state height, proof of -// the counterparty connection, and the proof height for all the proofs returned. -func (endpoint *Endpoint) QueryConnectionHandshakeProof() ( - clientState exported.ClientState, proofClient, - proofConsensus []byte, consensusHeight clienttypes.Height, - proofConnection []byte, proofHeight clienttypes.Height, -) { - // obtain the client state on the counterparty chain - clientState = endpoint.Counterparty.Chain.GetClientState(endpoint.Counterparty.ClientID) - - // query proof for the client state on the counterparty - clientKey := host.FullClientStateKey(endpoint.Counterparty.ClientID) - proofClient, proofHeight = endpoint.Counterparty.QueryProof(clientKey) - - consensusHeight = clientState.GetLatestHeight().(clienttypes.Height) - - // query proof for the consensus state on the counterparty - consensusKey := host.FullConsensusStateKey(endpoint.Counterparty.ClientID, consensusHeight) - proofConsensus, _ = endpoint.Counterparty.QueryProofAtHeight(consensusKey, proofHeight.GetRevisionHeight()) - - // query proof for the connection on the counterparty - connectionKey := host.ConnectionKey(endpoint.Counterparty.ConnectionID) - proofConnection, _ = endpoint.Counterparty.QueryProofAtHeight(connectionKey, proofHeight.GetRevisionHeight()) - - return -} - -// ChanOpenInit will construct and execute a MsgChannelOpenInit on the associated endpoint. -func (endpoint *Endpoint) ChanOpenInit() error { - msg := channeltypes.NewMsgChannelOpenInit( - endpoint.ChannelConfig.PortID, - endpoint.ChannelConfig.Version, endpoint.ChannelConfig.Order, []string{endpoint.ConnectionID}, - endpoint.Counterparty.ChannelConfig.PortID, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - res, err := endpoint.Chain.SendMsgs(msg) - if err != nil { - return err - } - - endpoint.ChannelID, err = ParseChannelIDFromEvents(res.GetEvents()) - require.NoError(endpoint.Chain.t, err) - - return nil -} - -// ChanOpenTry will construct and execute a MsgChannelOpenTry on the associated endpoint. -func (endpoint *Endpoint) ChanOpenTry() error { - if err := endpoint.UpdateClient(); err != nil { - return err - } - - channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID) - proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey) - - msg := channeltypes.NewMsgChannelOpenTry( - endpoint.ChannelConfig.PortID, "", // does not support handshake continuation - endpoint.ChannelConfig.Version, endpoint.ChannelConfig.Order, []string{endpoint.ConnectionID}, - endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID, endpoint.Counterparty.ChannelConfig.Version, - proof, height, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - res, err := endpoint.Chain.SendMsgs(msg) - if err != nil { - return err - } - - if endpoint.ChannelID == "" { - endpoint.ChannelID, err = ParseChannelIDFromEvents(res.GetEvents()) - require.NoError(endpoint.Chain.t, err) - } - - return nil -} - -// ChanOpenAck will construct and execute a MsgChannelOpenAck on the associated endpoint. -func (endpoint *Endpoint) ChanOpenAck() error { - if err := endpoint.UpdateClient(); err != nil { - return err - } - - channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID) - proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey) - - msg := channeltypes.NewMsgChannelOpenAck( - endpoint.ChannelConfig.PortID, endpoint.ChannelID, - endpoint.Counterparty.ChannelID, endpoint.Counterparty.ChannelConfig.Version, // testing doesn't use flexible selection - proof, height, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - return endpoint.Chain.sendMsgs(msg) -} - -// ChanOpenConfirm will construct and execute a MsgChannelOpenConfirm on the associated endpoint. -func (endpoint *Endpoint) ChanOpenConfirm() error { - if err := endpoint.UpdateClient(); err != nil { - return err - } - - channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID) - proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey) - - msg := channeltypes.NewMsgChannelOpenConfirm( - endpoint.ChannelConfig.PortID, endpoint.ChannelID, - proof, height, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - return endpoint.Chain.sendMsgs(msg) -} - -// ChanCloseInit will construct and execute a MsgChannelCloseInit on the associated endpoint. -// -// NOTE: does not work with ibc-transfer module -func (endpoint *Endpoint) ChanCloseInit() error { - msg := channeltypes.NewMsgChannelCloseInit( - endpoint.ChannelConfig.PortID, endpoint.ChannelID, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - return endpoint.Chain.sendMsgs(msg) -} - -// ChanCloseConfirm will construct and execute a NewMsgChannelCloseConfirm on the associated endpoint. -func (endpoint *Endpoint) ChanCloseConfirm() error { - channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID) - proof, proofHeight := endpoint.Counterparty.QueryProof(channelKey) - - msg := channeltypes.NewMsgChannelCloseConfirm( - endpoint.ChannelConfig.PortID, endpoint.ChannelID, - proof, proofHeight, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - return endpoint.Chain.sendMsgs(msg) -} - -// SendPacket sends a packet through the channel keeper using the associated endpoint -// The counterparty client is updated so proofs can be sent to the counterparty chain. -func (endpoint *Endpoint) SendPacket(packet exported.PacketI) error { - channelCap := endpoint.Chain.GetChannelCapability(packet.GetSourcePort(), packet.GetSourceChannel()) - - // no need to send message, acting as a module - err := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.SendPacket(endpoint.Chain.GetContext(), channelCap, packet) - if err != nil { - return err - } - - // commit changes since no message was sent - endpoint.Chain.Coordinator.CommitBlock(endpoint.Chain) - - return endpoint.Counterparty.UpdateClient() -} - -// RecvPacket receives a packet on the associated endpoint. -// The counterparty client is updated. -func (endpoint *Endpoint) RecvPacket(packet channeltypes.Packet) error { - // get proof of packet commitment on source - packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - proof, proofHeight := endpoint.Counterparty.Chain.QueryProof(packetKey) - - recvMsg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String()) - - // receive on counterparty and update source client - if err := endpoint.Chain.sendMsgs(recvMsg); err != nil { - return err - } - - return endpoint.Counterparty.UpdateClient() -} - -// WriteAcknowledgement writes an acknowledgement on the channel associated with the endpoint. -// The counterparty client is updated. -func (endpoint *Endpoint) WriteAcknowledgement(ack exported.Acknowledgement, packet exported.PacketI) error { - channelCap := endpoint.Chain.GetChannelCapability(packet.GetDestPort(), packet.GetDestChannel()) - - // no need to send message, acting as a handler - err := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.WriteAcknowledgement(endpoint.Chain.GetContext(), channelCap, packet, ack) - if err != nil { - return err - } - - // commit changes since no message was sent - endpoint.Chain.Coordinator.CommitBlock(endpoint.Chain) - - return endpoint.Counterparty.UpdateClient() -} - -// AcknowledgePacket sends a MsgAcknowledgement to the channel associated with the endpoint. -func (endpoint *Endpoint) AcknowledgePacket(packet channeltypes.Packet, ack []byte) error { - // get proof of acknowledgement on counterparty - packetKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - proof, proofHeight := endpoint.Counterparty.QueryProof(packetKey) - - ackMsg := channeltypes.NewMsgAcknowledgement(packet, ack, proof, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String()) - - return endpoint.Chain.sendMsgs(ackMsg) -} - -// TimeoutPacket sends a MsgTimeout to the channel associated with the endpoint. -func (endpoint *Endpoint) TimeoutPacket(packet channeltypes.Packet) error { - // get proof for timeout based on channel order - var packetKey []byte - - switch endpoint.ChannelConfig.Order { - case channeltypes.ORDERED: - packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel()) - case channeltypes.UNORDERED: - packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - default: - return fmt.Errorf("unsupported order type %s", endpoint.ChannelConfig.Order) - } - - proof, proofHeight := endpoint.Counterparty.QueryProof(packetKey) - nextSeqRecv, found := endpoint.Counterparty.Chain.App.GetIBCKeeper().ChannelKeeper.GetNextSequenceRecv(endpoint.Counterparty.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID) - require.True(endpoint.Chain.t, found) - - timeoutMsg := channeltypes.NewMsgTimeout( - packet, nextSeqRecv, - proof, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String(), - ) - - return endpoint.Chain.sendMsgs(timeoutMsg) -} - -// SetChannelClosed sets a channel state to CLOSED. -func (endpoint *Endpoint) SetChannelClosed() error { - channel := endpoint.GetChannel() - - channel.State = channeltypes.CLOSED - endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.SetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID, channel) - - endpoint.Chain.Coordinator.CommitBlock(endpoint.Chain) - - return endpoint.Counterparty.UpdateClient() -} - -// GetClientState retrieves the Client State for this endpoint. The -// client state is expected to exist otherwise testing will fail. -func (endpoint *Endpoint) GetClientState() exported.ClientState { - return endpoint.Chain.GetClientState(endpoint.ClientID) -} - -// SetClientState sets the client state for this endpoint. -func (endpoint *Endpoint) SetClientState(clientState exported.ClientState) { - endpoint.Chain.App.GetIBCKeeper().ClientKeeper.SetClientState(endpoint.Chain.GetContext(), endpoint.ClientID, clientState) -} - -// GetConsensusState retrieves the Consensus State for this endpoint at the provided height. -// The consensus state is expected to exist otherwise testing will fail. -func (endpoint *Endpoint) GetConsensusState(height exported.Height) exported.ConsensusState { - consensusState, found := endpoint.Chain.GetConsensusState(endpoint.ClientID, height) - require.True(endpoint.Chain.t, found) - - return consensusState -} - -// SetConsensusState sets the consensus state for this endpoint. -func (endpoint *Endpoint) SetConsensusState(consensusState exported.ConsensusState, height exported.Height) { - endpoint.Chain.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(endpoint.Chain.GetContext(), endpoint.ClientID, height, consensusState) -} - -// GetConnection retrieves an IBC Connection for the endpoint. The -// connection is expected to exist otherwise testing will fail. -func (endpoint *Endpoint) GetConnection() connectiontypes.ConnectionEnd { - connection, found := endpoint.Chain.App.GetIBCKeeper().ConnectionKeeper.GetConnection(endpoint.Chain.GetContext(), endpoint.ConnectionID) - require.True(endpoint.Chain.t, found) - - return connection -} - -// SetConnection sets the connection for this endpoint. -func (endpoint *Endpoint) SetConnection(connection connectiontypes.ConnectionEnd) { - endpoint.Chain.App.GetIBCKeeper().ConnectionKeeper.SetConnection(endpoint.Chain.GetContext(), endpoint.ConnectionID, connection) -} - -// GetChannel retrieves an IBC Channel for the endpoint. The channel -// is expected to exist otherwise testing will fail. -func (endpoint *Endpoint) GetChannel() channeltypes.Channel { - channel, found := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.GetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID) - require.True(endpoint.Chain.t, found) - - return channel -} - -// SetChannel sets the channel for this endpoint. -func (endpoint *Endpoint) SetChannel(channel channeltypes.Channel) { - endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.SetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID, channel) -} - -// QueryClientStateProof performs and abci query for a client stat associated -// with this endpoint and returns the ClientState along with the proof. -func (endpoint *Endpoint) QueryClientStateProof() (exported.ClientState, []byte) { - // retrieve client state to provide proof for - clientState := endpoint.GetClientState() - - clientKey := host.FullClientStateKey(endpoint.ClientID) - proofClient, _ := endpoint.QueryProof(clientKey) - - return clientState, proofClient -} diff --git a/sei-wasmd/x/wasm/ibctesting/event_utils.go b/sei-wasmd/x/wasm/ibctesting/event_utils.go deleted file mode 100644 index aacb649393..0000000000 --- a/sei-wasmd/x/wasm/ibctesting/event_utils.go +++ /dev/null @@ -1,91 +0,0 @@ -package ibctesting - -import ( - "strconv" - "strings" - - clienttypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/types" - channeltypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/04-channel/types" - abci "github.com/sei-protocol/sei-chain/sei-tendermint/abci/types" -) - -func getSendPackets(evts []abci.Event) []channeltypes.Packet { - var res []channeltypes.Packet - for _, evt := range evts { - if evt.Type == "send_packet" { - packet := parsePacketFromEvent(evt) - res = append(res, packet) - } - } - return res -} - -func getAckPackets(evts []abci.Event) []PacketAck { - var res []PacketAck - for _, evt := range evts { - if evt.Type == "write_acknowledgement" { - packet := parsePacketFromEvent(evt) - ack := PacketAck{ - Packet: packet, - Ack: []byte(getField(evt, "packet_ack")), - } - res = append(res, ack) - } - } - return res -} - -// Used for various debug statements above when needed... do not remove -// func showEvent(evt abci.Event) { -// fmt.Printf("evt.Type: %s\n", evt.Type) -// for _, attr := range evt.Attributes { -// fmt.Printf(" %s = %s\n", string(attr.Key), string(attr.Value)) -// } -//} - -func parsePacketFromEvent(evt abci.Event) channeltypes.Packet { - return channeltypes.Packet{ - Sequence: getUintField(evt, "packet_sequence"), - SourcePort: getField(evt, "packet_src_port"), - SourceChannel: getField(evt, "packet_src_channel"), - DestinationPort: getField(evt, "packet_dst_port"), - DestinationChannel: getField(evt, "packet_dst_channel"), - Data: []byte(getField(evt, "packet_data")), - TimeoutHeight: parseTimeoutHeight(getField(evt, "packet_timeout_height")), - TimeoutTimestamp: getUintField(evt, "packet_timeout_timestamp"), - } -} - -// return the value for the attribute with the given name -func getField(evt abci.Event, key string) string { - for _, attr := range evt.Attributes { - if string(attr.Key) == key { - return string(attr.Value) - } - } - return "" -} - -func getUintField(evt abci.Event, key string) uint64 { - raw := getField(evt, key) - return toUint64(raw) -} - -func toUint64(raw string) uint64 { - if raw == "" { - return 0 - } - i, err := strconv.ParseUint(raw, 10, 64) - if err != nil { - panic(err) - } - return i -} - -func parseTimeoutHeight(raw string) clienttypes.Height { - chunks := strings.Split(raw, "-") - return clienttypes.Height{ - RevisionNumber: toUint64(chunks[0]), - RevisionHeight: toUint64(chunks[1]), - } -} diff --git a/sei-wasmd/x/wasm/ibctesting/events.go b/sei-wasmd/x/wasm/ibctesting/events.go deleted file mode 100644 index c1d97e2620..0000000000 --- a/sei-wasmd/x/wasm/ibctesting/events.go +++ /dev/null @@ -1,203 +0,0 @@ -package ibctesting - -import ( - "fmt" - "slices" - "strconv" - - abci "github.com/sei-protocol/sei-chain/sei-tendermint/abci/types" - "github.com/stretchr/testify/assert" - - sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" - - clienttypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/types" - connectiontypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/03-connection/types" - channeltypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/04-channel/types" -) - -// ParseClientIDFromEvents parses events emitted from a MsgCreateClient and returns the -// client identifier. -func ParseClientIDFromEvents(events sdk.Events) (string, error) { - for _, ev := range events { - if ev.Type == clienttypes.EventTypeCreateClient { - for _, attr := range ev.Attributes { - if string(attr.Key) == clienttypes.AttributeKeyClientID { - return string(attr.Value), nil - } - } - } - } - return "", fmt.Errorf("client identifier event attribute not found") -} - -// ParseConnectionIDFromEvents parses events emitted from a MsgConnectionOpenInit or -// MsgConnectionOpenTry and returns the connection identifier. -func ParseConnectionIDFromEvents(events sdk.Events) (string, error) { - for _, ev := range events { - if ev.Type == connectiontypes.EventTypeConnectionOpenInit || - ev.Type == connectiontypes.EventTypeConnectionOpenTry { - for _, attr := range ev.Attributes { - if string(attr.Key) == connectiontypes.AttributeKeyConnectionID { - return string(attr.Value), nil - } - } - } - } - return "", fmt.Errorf("connection identifier event attribute not found") -} - -// ParseChannelIDFromEvents parses events emitted from a MsgChannelOpenInit or -// MsgChannelOpenTry and returns the channel identifier. -func ParseChannelIDFromEvents(events sdk.Events) (string, error) { - for _, ev := range events { - if ev.Type == channeltypes.EventTypeChannelOpenInit || ev.Type == channeltypes.EventTypeChannelOpenTry { - for _, attr := range ev.Attributes { - if string(attr.Key) == channeltypes.AttributeKeyChannelID { - return string(attr.Value), nil - } - } - } - } - return "", fmt.Errorf("channel identifier event attribute not found") -} - -// ParsePacketFromEvents parses events emitted from a MsgRecvPacket and returns the -// acknowledgement. -func ParsePacketFromEvents(events sdk.Events) (channeltypes.Packet, error) { - for _, ev := range events { - if ev.Type == channeltypes.EventTypeSendPacket { - packet := channeltypes.Packet{} - for _, attr := range ev.Attributes { - switch string(attr.Key) { - case channeltypes.AttributeKeyData: - packet.Data = attr.Value - - case channeltypes.AttributeKeySequence: - seq, err := strconv.ParseUint(string(attr.Value), 10, 64) - if err != nil { - return channeltypes.Packet{}, err - } - - packet.Sequence = seq - - case channeltypes.AttributeKeySrcPort: - packet.SourcePort = string(attr.Value) - - case channeltypes.AttributeKeySrcChannel: - packet.SourceChannel = string(attr.Value) - - case channeltypes.AttributeKeyDstPort: - packet.DestinationPort = string(attr.Value) - - case channeltypes.AttributeKeyDstChannel: - packet.DestinationChannel = string(attr.Value) - - case channeltypes.AttributeKeyTimeoutHeight: - height, err := clienttypes.ParseHeight(string(attr.Value)) - if err != nil { - return channeltypes.Packet{}, err - } - - packet.TimeoutHeight = height - - case channeltypes.AttributeKeyTimeoutTimestamp: - timestamp, err := strconv.ParseUint(string(attr.Value), 10, 64) - if err != nil { - return channeltypes.Packet{}, err - } - - packet.TimeoutTimestamp = timestamp - - default: - continue - } - } - - return packet, nil - } - } - return channeltypes.Packet{}, fmt.Errorf("acknowledgement event attribute not found") -} - -// ParseAckFromEvents parses events emitted from a MsgRecvPacket and returns the -// acknowledgement. -func ParseAckFromEvents(events sdk.Events) ([]byte, error) { - for _, ev := range events { - if ev.Type == channeltypes.EventTypeWriteAck { - for _, attr := range ev.Attributes { - if string(attr.Key) == channeltypes.AttributeKeyAck { - return attr.Value, nil - } - } - } - } - return nil, fmt.Errorf("acknowledgement event attribute not found") -} - -// AssertEvents asserts that expected events are present in the actual events. -func AssertEvents( - t assert.TestingT, - expected []abci.Event, - actual []abci.Event, -) { - foundEvents := make(map[int]bool) - - for i, expectedEvent := range expected { - for _, actualEvent := range actual { - if shouldProcessEvent(expectedEvent, actualEvent) { - attributeMatch := true - for _, expectedAttr := range expectedEvent.Attributes { - // any expected attributes that are not contained in the actual events will cause this event - // not to match - attributeMatch = attributeMatch && containsAttribute(actualEvent.Attributes, string(expectedAttr.Key), string(expectedAttr.Value)) - } - - if attributeMatch { - foundEvents[i] = true - } - } - } - } - - for i, expectedEvent := range expected { - assert.True(t, foundEvents[i], "event: %s was not found in events", expectedEvent.Type) - } -} - -// shouldProcessEvent returns true if the given expected event should be processed based on event type. -func shouldProcessEvent(expectedEvent abci.Event, actualEvent abci.Event) bool { - if expectedEvent.Type != actualEvent.Type { - return false - } - // the actual event will have an extra attribute added automatically - // by Cosmos SDK since v0.50, that's why we subtract 1 when comparing - // with the number of attributes in the expected event. - if containsAttributeKey(actualEvent.Attributes, "msg_index") { - return len(expectedEvent.Attributes) == len(actualEvent.Attributes)-1 - } - - return len(expectedEvent.Attributes) == len(actualEvent.Attributes) -} - -// containsAttribute returns true if the given key/value pair is contained in the given attributes. -// NOTE: this ignores the indexed field, which can be set or unset depending on how the events are retrieved. -func containsAttribute(attrs []abci.EventAttribute, key, value string) bool { - return slices.ContainsFunc(attrs, func(attr abci.EventAttribute) bool { - return string(attr.Key) == key && string(attr.Value) == value - }) -} - -// containsAttributeKey returns true if the given key is contained in the given attributes. -func containsAttributeKey(attrs []abci.EventAttribute, key string) bool { - _, found := attributeByKey(attrs, key) - return found -} - -// attributeByKey returns the event attribute's value keyed by the given key and a boolean indicating its presence in the given attributes. -func attributeByKey(attributes []abci.EventAttribute, key string) (abci.EventAttribute, bool) { - idx := slices.IndexFunc(attributes, func(a abci.EventAttribute) bool { return string(a.Key) == key }) - if idx == -1 { - return abci.EventAttribute{}, false - } - return attributes[idx], true -} diff --git a/sei-wasmd/x/wasm/ibctesting/path.go b/sei-wasmd/x/wasm/ibctesting/path.go deleted file mode 100644 index ca2ac61436..0000000000 --- a/sei-wasmd/x/wasm/ibctesting/path.go +++ /dev/null @@ -1,99 +0,0 @@ -package ibctesting - -import ( - "bytes" - "fmt" - - sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" - channeltypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/04-channel/types" -) - -// Path contains two endpoints representing two chains connected over IBC -type Path struct { - EndpointA *Endpoint - EndpointB *Endpoint -} - -// NewPath constructs an endpoint for each chain using the default values -// for the endpoints. Each endpoint is updated to have a pointer to the -// counterparty endpoint. -func NewPath(chainA, chainB *TestChain) *Path { - endpointA := NewDefaultEndpoint(chainA) - endpointB := NewDefaultEndpoint(chainB) - - endpointA.Counterparty = endpointB - endpointB.Counterparty = endpointA - - return &Path{ - EndpointA: endpointA, - EndpointB: endpointB, - } -} - -// SetChannelOrdered sets the channel order for both endpoints to ORDERED. -func (path *Path) SetChannelOrdered() { - path.EndpointA.ChannelConfig.Order = channeltypes.ORDERED - path.EndpointB.ChannelConfig.Order = channeltypes.ORDERED -} - -// RelayPacket attempts to relay the packet first on EndpointA and then on EndpointB -// if EndpointA does not contain a packet commitment for that packet. An error is returned -// if a relay step fails or the packet commitment does not exist on either endpoint. -func (path *Path) RelayPacket(packet channeltypes.Packet, ack []byte) error { - pc := path.EndpointA.Chain.App.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(path.EndpointA.Chain.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - if bytes.Equal(pc, channeltypes.CommitPacket(path.EndpointA.Chain.App.AppCodec(), packet)) { - - // packet found, relay from A to B - if err := path.EndpointB.UpdateClient(); err != nil { - return err - } - - if err := path.EndpointB.RecvPacket(packet); err != nil { - return err - } - - if err := path.EndpointA.AcknowledgePacket(packet, ack); err != nil { - return err - } - return nil - - } - - pc = path.EndpointB.Chain.App.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(path.EndpointB.Chain.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - if bytes.Equal(pc, channeltypes.CommitPacket(path.EndpointB.Chain.App.AppCodec(), packet)) { - - // packet found, relay B to A - if err := path.EndpointA.UpdateClient(); err != nil { - return err - } - - if err := path.EndpointA.RecvPacket(packet); err != nil { - return err - } - if err := path.EndpointB.AcknowledgePacket(packet, ack); err != nil { - return err - } - return nil - } - - return fmt.Errorf("packet commitment does not exist on either endpoint for provided packet") -} - -// SendMsg delivers the provided messages to the chain. The counterparty -// client is updated with the new source consensus state. -func (path *Path) SendMsg(msgs ...sdk.Msg) error { - if err := path.EndpointA.Chain.sendMsgs(msgs...); err != nil { - return err - } - if err := path.EndpointA.UpdateClient(); err != nil { - return err - } - return path.EndpointB.UpdateClient() -} - -func (path *Path) Invert() *Path { - return &Path{ - EndpointA: path.EndpointB, - EndpointB: path.EndpointA, - } -} diff --git a/sei-wasmd/x/wasm/ibctesting/values.go b/sei-wasmd/x/wasm/ibctesting/values.go deleted file mode 100644 index e7eb0c2bd8..0000000000 --- a/sei-wasmd/x/wasm/ibctesting/values.go +++ /dev/null @@ -1,57 +0,0 @@ -/* -This file contains the variables, constants, and default values -used in the testing package and commonly defined in tests. -*/ -package ibctesting - -import ( - "time" - - sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" - - ibctransfertypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/apps/transfer/types" - connectiontypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/03-connection/types" - commitmenttypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/23-commitment/types" - ibctmtypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/light-clients/07-tendermint/types" -) - -const ( - FirstClientID = "07-tendermint-0" - FirstChannelID = "channel-0" - FirstConnectionID = "connection-0" - - // Default params constants used to create a TM client - TrustingPeriod time.Duration = time.Hour * 24 * 7 * 2 - UnbondingPeriod time.Duration = time.Hour * 24 * 7 * 3 - MaxClockDrift time.Duration = time.Second * 10 - DefaultDelayPeriod uint64 = 0 - - DefaultChannelVersion = "mock-version" - InvalidID = "IDisInvalid" - - // Application Ports - TransferPort = ibctransfertypes.ModuleName - MockPort = "mock" - - // used for testing proposals - Title = "title" - Description = "description" - - LongString = "LoremipsumdolorsitameconsecteturadipiscingeliseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquUtenimadminimveniamquisnostrudexercitationullamcolaborisnisiutaliquipexeacommodoconsequDuisauteiruredolorinreprehenderitinvoluptateelitsseillumoloreufugiatnullaariaturEcepteurintoccaectupidatatonroidentuntnulpauifficiaeseruntmollitanimidestlaborum" -) - -var ( - DefaultOpenInitVersion *connectiontypes.Version - - // Default params variables used to create a TM client - DefaultTrustLevel ibctmtypes.Fraction = ibctmtypes.DefaultTrustLevel - - TestAccAddress = "cosmos17dtl0mjt3t77kpuhg2edqzjpszulwhgzuj9ljs" - TestCoin = sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) - - UpgradePath = []string{"upgrade", "upgradedIBCState"} - - ConnectionVersion = connectiontypes.ExportedVersionsToProto(connectiontypes.GetCompatibleVersions())[0] - - prefix = commitmenttypes.NewMerklePrefix([]byte("ibc")) -) diff --git a/sei-wasmd/x/wasm/ibctesting/wasm.go b/sei-wasmd/x/wasm/ibctesting/wasm.go deleted file mode 100644 index e44a063303..0000000000 --- a/sei-wasmd/x/wasm/ibctesting/wasm.go +++ /dev/null @@ -1,142 +0,0 @@ -package ibctesting - -import ( - "bytes" - "compress/gzip" - "context" - "encoding/json" - "fmt" - "os" - "path/filepath" - "strings" - - wasmd "github.com/sei-protocol/sei-chain/sei-wasmd/app" - - "github.com/golang/protobuf/proto" //nolint - sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" - abci "github.com/sei-protocol/sei-chain/sei-tendermint/abci/types" - "github.com/sei-protocol/sei-chain/sei-tendermint/libs/rand" - "github.com/stretchr/testify/require" - - "github.com/sei-protocol/sei-chain/sei-wasmd/x/wasm/types" -) - -var wasmIdent = []byte("\x00\x61\x73\x6D") - -// SeedNewContractInstance stores some wasm code and instantiates a new contract on this chain. -// This method can be called to prepare the store with some valid CodeInfo and ContractInfo. The returned -// Address is the contract address for this instance. Test should make use of this data and/or use NewIBCContractMockWasmer -// for using a contract mock in Go. -func (chain *TestChain) SeedNewContractInstance() sdk.AccAddress { - pInstResp := chain.StoreCode(append(wasmIdent, rand.Bytes(10)...)) - codeID := pInstResp.CodeID - - anyAddressStr := chain.SenderAccount.GetAddress().String() - initMsg := []byte(fmt.Sprintf(`{"verifier": %q, "beneficiary": %q}`, anyAddressStr, anyAddressStr)) - return chain.InstantiateContract(codeID, initMsg) -} - -func (chain *TestChain) StoreCodeFile(filename string) types.MsgStoreCodeResponse { - wasmCode, err := os.ReadFile(filepath.Clean(filename)) - require.NoError(chain.t, err) - if strings.HasSuffix(filename, "wasm") { // compress for gas limit - var buf bytes.Buffer - gz := gzip.NewWriter(&buf) - _, err := gz.Write(wasmCode) - require.NoError(chain.t, err) - err = gz.Close() - require.NoError(chain.t, err) - wasmCode = buf.Bytes() - } - return chain.StoreCode(wasmCode) -} - -func (chain *TestChain) StoreCode(byteCode []byte) types.MsgStoreCodeResponse { - storeMsg := &types.MsgStoreCode{ - Sender: chain.SenderAccount.GetAddress().String(), - WASMByteCode: byteCode, - } - r, err := chain.SendMsgs(storeMsg) - require.NoError(chain.t, err) - protoResult := chain.parseSDKResultData(r) - require.Len(chain.t, protoResult.Data, 1) - // unmarshal protobuf response from data - var pInstResp types.MsgStoreCodeResponse - require.NoError(chain.t, pInstResp.Unmarshal(protoResult.Data[0].Data)) - require.NotEmpty(chain.t, pInstResp.CodeID) - return pInstResp -} - -func (chain *TestChain) InstantiateContract(codeID uint64, initMsg []byte) sdk.AccAddress { - instantiateMsg := &types.MsgInstantiateContract{ - Sender: chain.SenderAccount.GetAddress().String(), - Admin: chain.SenderAccount.GetAddress().String(), - CodeID: codeID, - Label: "ibc-test", - Msg: initMsg, - Funds: sdk.Coins{TestCoin}, - } - - r, err := chain.SendMsgs(instantiateMsg) - require.NoError(chain.t, err) - protoResult := chain.parseSDKResultData(r) - require.Len(chain.t, protoResult.Data, 1) - - var pExecResp types.MsgInstantiateContractResponse - require.NoError(chain.t, pExecResp.Unmarshal(protoResult.Data[0].Data)) - a, err := sdk.AccAddressFromBech32(pExecResp.Address) - require.NoError(chain.t, err) - return a -} - -// SmartQuery This will serialize the query message and submit it to the contract. -// The response is parsed into the provided interface. -// Usage: SmartQuery(addr, QueryMsg{Foo: 1}, &response) -func (chain *TestChain) SmartQuery(contractAddr string, queryMsg interface{}, response interface{}) error { - msg, err := json.Marshal(queryMsg) - if err != nil { - return err - } - - req := types.QuerySmartContractStateRequest{ - Address: contractAddr, - QueryData: msg, - } - reqBin, err := proto.Marshal(&req) - if err != nil { - return err - } - - // TODO: what is the query? - res, _ := chain.App.Query(context.Background(), &abci.RequestQuery{ - Path: "/cosmwasm.wasm.v1.Query/SmartContractState", - Data: reqBin, - }) - - if res.Code != 0 { - return fmt.Errorf("query failed: (%d) %s", res.Code, res.Log) - } - - // unpack protobuf - var resp types.QuerySmartContractStateResponse - err = proto.Unmarshal(res.Value, &resp) - if err != nil { - return err - } - // unpack json content - return json.Unmarshal(resp.Data, response) -} - -func (chain *TestChain) parseSDKResultData(r *sdk.Result) sdk.TxMsgData { - var protoResult sdk.TxMsgData - require.NoError(chain.t, proto.Unmarshal(r.Data, &protoResult)) - return protoResult -} - -// ContractInfo is a helper function to returns the ContractInfo for the given contract address -func (chain *TestChain) ContractInfo(contractAddr sdk.AccAddress) *types.ContractInfo { - type testSupporter interface { - TestSupport() *wasmd.TestSupport - } - return chain.App.(testSupporter).TestSupport().WasmKeeper().GetContractInfo(chain.GetContext(), contractAddr) -} diff --git a/sei-wasmd/x/wasm/relay_pingpong_test.go b/sei-wasmd/x/wasm/relay_pingpong_test.go deleted file mode 100644 index e0d756b75f..0000000000 --- a/sei-wasmd/x/wasm/relay_pingpong_test.go +++ /dev/null @@ -1,400 +0,0 @@ -package wasm_test - -import ( - "encoding/json" - "fmt" - "testing" - - ibctransfertypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/apps/transfer/types" - - "github.com/sei-protocol/sei-chain/sei-cosmos/store/prefix" - sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" - clienttypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/types" - channeltypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/04-channel/types" - wasmvm "github.com/sei-protocol/sei-chain/sei-wasmvm" - wasmvmtypes "github.com/sei-protocol/sei-chain/sei-wasmvm/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - wasmibctesting "github.com/sei-protocol/sei-chain/sei-wasmd/x/wasm/ibctesting" - wasmkeeper "github.com/sei-protocol/sei-chain/sei-wasmd/x/wasm/keeper" - "github.com/sei-protocol/sei-chain/sei-wasmd/x/wasm/keeper/wasmtesting" - wasmtypes "github.com/sei-protocol/sei-chain/sei-wasmd/x/wasm/types" -) - -const ( - ping = "ping" - pong = "pong" -) - -var doNotTimeout = clienttypes.NewHeight(1, 1111111) - -func TestPinPong(t *testing.T) { - // custom IBC protocol example - // scenario: given two chains, - // with a contract on chain A and chain B - // when a ibc packet comes in, the contract responds with a new packet containing - // either ping or pong - - pingContract := &player{t: t, actor: ping} - pongContract := &player{t: t, actor: pong} - - var ( - chainAOpts = []wasmkeeper.Option{ - wasmkeeper.WithWasmEngine( - wasmtesting.NewIBCContractMockWasmer(pingContract)), - } - chainBOpts = []wasmkeeper.Option{wasmkeeper.WithWasmEngine( - wasmtesting.NewIBCContractMockWasmer(pongContract), - )} - coordinator = wasmibctesting.NewCoordinator(t, 2, chainAOpts, chainBOpts) - chainA = coordinator.GetChain(wasmibctesting.GetChainID(0)) - chainB = coordinator.GetChain(wasmibctesting.GetChainID(1)) - ) - _ = chainB.SeedNewContractInstance() // skip 1 instance so that addresses are not the same - var ( - pingContractAddr = chainA.SeedNewContractInstance() - pongContractAddr = chainB.SeedNewContractInstance() - ) - require.NotEqual(t, pingContractAddr, pongContractAddr) - coordinator.CommitBlock(chainA, chainB) - - pingContract.chain = chainA - pingContract.contractAddr = pingContractAddr - - pongContract.chain = chainB - pongContract.contractAddr = pongContractAddr - - var ( - sourcePortID = wasmkeeper.PortIDForContract(pingContractAddr) - counterpartyPortID = wasmkeeper.PortIDForContract(pongContractAddr) - ) - - path := wasmibctesting.NewPath(chainA, chainB) - path.EndpointA.ChannelConfig = &wasmibctesting.ChannelConfig{ - PortID: sourcePortID, - Version: ibctransfertypes.Version, - Order: channeltypes.ORDERED, - } - path.EndpointB.ChannelConfig = &wasmibctesting.ChannelConfig{ - PortID: counterpartyPortID, - Version: ibctransfertypes.Version, - Order: channeltypes.ORDERED, - } - coordinator.SetupConnections(path) - coordinator.CreateChannels(path) - - // trigger start game via execute - const startValue uint64 = 100 - const rounds = 3 - s := startGame{ - ChannelID: path.EndpointA.ChannelID, - Value: startValue, - } - startMsg := &wasmtypes.MsgExecuteContract{ - Sender: chainA.SenderAccount.GetAddress().String(), - Contract: pingContractAddr.String(), - Msg: s.GetBytes(), - } - // on chain A - _, err := path.EndpointA.Chain.SendMsgs(startMsg) - require.NoError(t, err) - - // when some rounds are played - for i := 1; i <= rounds; i++ { - t.Logf("++ round: %d\n", i) - - require.Len(t, chainA.PendingSendPackets, 1) - err := coordinator.RelayAndAckPendingPackets(path) - require.NoError(t, err) - - // switch side - require.Len(t, chainB.PendingSendPackets, 1) - err = coordinator.RelayAndAckPendingPackets(path.Invert()) - require.NoError(t, err) - } - - // then receive/response state is as expected - assert.Equal(t, startValue+rounds, pingContract.QueryState(lastBallSentKey)) - assert.Equal(t, uint64(rounds), pingContract.QueryState(lastBallReceivedKey)) - assert.Equal(t, uint64(rounds+1), pingContract.QueryState(sentBallsCountKey)) - assert.Equal(t, uint64(rounds), pingContract.QueryState(receivedBallsCountKey)) - assert.Equal(t, uint64(rounds), pingContract.QueryState(confirmedBallsCountKey)) - - assert.Equal(t, uint64(rounds), pongContract.QueryState(lastBallSentKey)) - assert.Equal(t, startValue+rounds-1, pongContract.QueryState(lastBallReceivedKey)) - assert.Equal(t, uint64(rounds), pongContract.QueryState(sentBallsCountKey)) - assert.Equal(t, uint64(rounds), pongContract.QueryState(receivedBallsCountKey)) - assert.Equal(t, uint64(rounds), pongContract.QueryState(confirmedBallsCountKey)) -} - -var _ wasmtesting.IBCContractCallbacks = &player{} - -// player is a (mock) contract that sends and receives ibc packages -type player struct { - t *testing.T - chain *wasmibctesting.TestChain - contractAddr sdk.AccAddress - actor string // either ping or pong - execCalls int // number of calls to Execute method (checkTx + deliverTx) -} - -// Execute starts the ping pong game -// Contracts finds all connected channels and broadcasts a ping message -func (p *player) Execute(code wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { - p.execCalls++ - // start game - var start startGame - if err := json.Unmarshal(executeMsg, &start); err != nil { - return nil, 0, err - } - - if start.MaxValue != 0 { - store.Set(maxValueKey, sdk.Uint64ToBigEndian(start.MaxValue)) - } - service := NewHit(p.actor, start.Value) - p.t.Logf("[%s] starting game with: %d: %v\n", p.actor, start.Value, service) - - p.incrementCounter(sentBallsCountKey, store) - store.Set(lastBallSentKey, sdk.Uint64ToBigEndian(start.Value)) - return &wasmvmtypes.Response{ - Messages: []wasmvmtypes.SubMsg{ - { - Msg: wasmvmtypes.CosmosMsg{ - IBC: &wasmvmtypes.IBCMsg{ - SendPacket: &wasmvmtypes.SendPacketMsg{ - ChannelID: start.ChannelID, - Data: service.GetBytes(), - Timeout: wasmvmtypes.IBCTimeout{Block: &wasmvmtypes.IBCTimeoutBlock{ - Revision: doNotTimeout.RevisionNumber, - Height: doNotTimeout.RevisionHeight, - }}, - }, - }, - }, - ReplyOn: wasmvmtypes.ReplyNever, - }, - }, - }, 0, nil -} - -// OnIBCChannelOpen ensures to accept only configured version -func (p player) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBC3ChannelOpenResponse, uint64, error) { - if msg.GetChannel().Version != p.actor { - return &wasmvmtypes.IBC3ChannelOpenResponse{}, 0, nil - } - return &wasmvmtypes.IBC3ChannelOpenResponse{}, 0, nil -} - -// OnIBCChannelConnect persists connection endpoints -func (p player) IBCChannelConnect(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelConnectMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { - p.storeEndpoint(store, msg.GetChannel()) - return &wasmvmtypes.IBCBasicResponse{}, 0, nil -} - -// connectedChannelsModel is a simple persistence model to store endpoint addresses within the contract's store -type connectedChannelsModel struct { - Our wasmvmtypes.IBCEndpoint - Their wasmvmtypes.IBCEndpoint -} - -var ( // store keys - ibcEndpointsKey = []byte("ibc-endpoints") - maxValueKey = []byte("max-value") -) - -func (p player) loadEndpoints(store prefix.Store, channelID string) *connectedChannelsModel { - var counterparties []connectedChannelsModel - if bz := store.Get(ibcEndpointsKey); bz != nil { - require.NoError(p.t, json.Unmarshal(bz, &counterparties)) - } - for _, v := range counterparties { - if v.Our.ChannelID == channelID { - return &v - } - } - p.t.Fatalf("no counterparty found for channel %q", channelID) - return nil -} - -func (p player) storeEndpoint(store wasmvm.KVStore, channel wasmvmtypes.IBCChannel) { - var counterparties []connectedChannelsModel - if b := store.Get(ibcEndpointsKey); b != nil { - require.NoError(p.t, json.Unmarshal(b, &counterparties)) - } - counterparties = append(counterparties, connectedChannelsModel{Our: channel.Endpoint, Their: channel.CounterpartyEndpoint}) - bz, err := json.Marshal(&counterparties) - require.NoError(p.t, err) - store.Set(ibcEndpointsKey, bz) -} - -func (p player) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelCloseMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { - panic("implement me") -} - -var ( // store keys - lastBallSentKey = []byte("lastBallSent") - lastBallReceivedKey = []byte("lastBallReceived") - sentBallsCountKey = []byte("sentBalls") - receivedBallsCountKey = []byte("recvBalls") - confirmedBallsCountKey = []byte("confBalls") -) - -// IBCPacketReceive receives the hit and serves a response hit via `wasmvmtypes.IBCPacket` -func (p player) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResult, uint64, error) { - // parse received data and store - packet := msg.Packet - var receivedBall hit - if err := json.Unmarshal(packet.Data, &receivedBall); err != nil { - return &wasmvmtypes.IBCReceiveResult{ - Ok: &wasmvmtypes.IBCReceiveResponse{ - Acknowledgement: hitAcknowledgement{Error: err.Error()}.GetBytes(), - }, - // no hit msg, we stop the game - }, 0, nil - } - p.incrementCounter(receivedBallsCountKey, store) - - otherCount := receivedBall[counterParty(p.actor)] - store.Set(lastBallReceivedKey, sdk.Uint64ToBigEndian(otherCount)) - - if maxVal := store.Get(maxValueKey); maxVal != nil && otherCount > sdk.BigEndianToUint64(maxVal) { - errMsg := fmt.Sprintf("max value exceeded: %d got %d", sdk.BigEndianToUint64(maxVal), otherCount) - return &wasmvmtypes.IBCReceiveResult{Ok: &wasmvmtypes.IBCReceiveResponse{ - Acknowledgement: receivedBall.BuildError(errMsg).GetBytes(), - }}, 0, nil - } - - nextValue := p.incrementCounter(lastBallSentKey, store) - newHit := NewHit(p.actor, nextValue) - respHit := &wasmvmtypes.IBCMsg{SendPacket: &wasmvmtypes.SendPacketMsg{ - ChannelID: packet.Src.ChannelID, - Data: newHit.GetBytes(), - Timeout: wasmvmtypes.IBCTimeout{Block: &wasmvmtypes.IBCTimeoutBlock{ - Revision: doNotTimeout.RevisionNumber, - Height: doNotTimeout.RevisionHeight, - }}, - }} - p.incrementCounter(sentBallsCountKey, store) - p.t.Logf("[%s] received %d, returning %d: %v\n", p.actor, otherCount, nextValue, newHit) - - return &wasmvmtypes.IBCReceiveResult{ - Ok: &wasmvmtypes.IBCReceiveResponse{ - Acknowledgement: receivedBall.BuildAck().GetBytes(), - Messages: []wasmvmtypes.SubMsg{{Msg: wasmvmtypes.CosmosMsg{IBC: respHit}, ReplyOn: wasmvmtypes.ReplyNever}}, - }, - }, 0, nil -} - -// OnIBCPacketAcknowledgement handles the packet acknowledgment frame. Stops the game on an any error -func (p player) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketAckMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { - // parse received data and store - var sentBall hit - if err := json.Unmarshal(msg.OriginalPacket.Data, &sentBall); err != nil { - return nil, 0, err - } - - var ack hitAcknowledgement - if err := json.Unmarshal(msg.Acknowledgement.Data, &ack); err != nil { - return nil, 0, err - } - if ack.Success != nil { - confirmedCount := sentBall[p.actor] - p.t.Logf("[%s] acknowledged %d: %v\n", p.actor, confirmedCount, sentBall) - } else { - p.t.Logf("[%s] received app layer error: %s\n", p.actor, ack.Error) - } - - p.incrementCounter(confirmedBallsCountKey, store) - return &wasmvmtypes.IBCBasicResponse{}, 0, nil -} - -func (p player) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacketTimeoutMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { - panic("implement me") -} - -func (p player) incrementCounter(key []byte, store wasmvm.KVStore) uint64 { - var count uint64 - bz := store.Get(key) - if bz != nil { - count = sdk.BigEndianToUint64(bz) - } - count++ - store.Set(key, sdk.Uint64ToBigEndian(count)) - return count -} - -func (p player) QueryState(key []byte) uint64 { - raw := p.chain.GetTestSupport().WasmKeeper().QueryRaw(p.chain.GetContext(), p.contractAddr, key) - return sdk.BigEndianToUint64(raw) -} - -func counterParty(s string) string { - switch s { - case ping: - return pong - case pong: - return ping - default: - panic(fmt.Sprintf("unsupported: %q", s)) - } -} - -// hit is ibc packet payload -type hit map[string]uint64 - -func NewHit(player string, count uint64) hit { - return map[string]uint64{ - player: count, - } -} - -func (h hit) GetBytes() []byte { - b, err := json.Marshal(h) - if err != nil { - panic(err) - } - return b -} - -func (h hit) String() string { - return fmt.Sprintf("Ball %s", string(h.GetBytes())) -} - -func (h hit) BuildAck() hitAcknowledgement { - return hitAcknowledgement{Success: &h} -} - -func (h hit) BuildError(errMsg string) hitAcknowledgement { - return hitAcknowledgement{Error: errMsg} -} - -// hitAcknowledgement is ibc acknowledgment payload -type hitAcknowledgement struct { - Error string `json:"error,omitempty"` - Success *hit `json:"success,omitempty"` -} - -func (a hitAcknowledgement) GetBytes() []byte { - b, err := json.Marshal(a) - if err != nil { - panic(err) - } - return b -} - -// startGame is an execute message payload -type startGame struct { - ChannelID string - Value uint64 - // limit above the game is aborted - MaxValue uint64 `json:"max_value,omitempty"` -} - -func (g startGame) GetBytes() wasmtypes.RawContractMessage { - b, err := json.Marshal(g) - if err != nil { - panic(err) - } - return b -} diff --git a/sei-wasmd/x/wasm/relay_test.go b/sei-wasmd/x/wasm/relay_test.go deleted file mode 100644 index 6c80cf0225..0000000000 --- a/sei-wasmd/x/wasm/relay_test.go +++ /dev/null @@ -1,646 +0,0 @@ -package wasm_test - -import ( - "encoding/json" - "errors" - "testing" - "time" - - sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" - sdkerrors "github.com/sei-protocol/sei-chain/sei-cosmos/types/errors" - ibctransfertypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/apps/transfer/types" - clienttypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/types" - channeltypes "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/04-channel/types" - wasmvm "github.com/sei-protocol/sei-chain/sei-wasmvm" - wasmvmtypes "github.com/sei-protocol/sei-chain/sei-wasmvm/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - wasmibctesting "github.com/sei-protocol/sei-chain/sei-wasmd/x/wasm/ibctesting" - wasmkeeper "github.com/sei-protocol/sei-chain/sei-wasmd/x/wasm/keeper" - wasmtesting "github.com/sei-protocol/sei-chain/sei-wasmd/x/wasm/keeper/wasmtesting" - "github.com/sei-protocol/sei-chain/sei-wasmd/x/wasm/types" -) - -func TestFromIBCTransferToContract(t *testing.T) { - // scenario: given two chains, - // with a contract on chain B - // then the contract can handle the receiving side of an ics20 transfer - // that was started on chain A via ibc transfer module - - transferAmount := sdk.NewInt(1) - specs := map[string]struct { - contract wasmtesting.IBCContractCallbacks - setupContract func(t *testing.T, contract wasmtesting.IBCContractCallbacks, chain *wasmibctesting.TestChain) - expChainABalanceDiff sdk.Int - expChainBBalanceDiff sdk.Int - }{ - "ack": { - contract: &ackReceiverContract{}, - setupContract: func(t *testing.T, contract wasmtesting.IBCContractCallbacks, chain *wasmibctesting.TestChain) { - c := contract.(*ackReceiverContract) - c.t = t - c.chain = chain - }, - expChainABalanceDiff: transferAmount.Neg(), - expChainBBalanceDiff: transferAmount, - }, - "nack": { - contract: &nackReceiverContract{}, - setupContract: func(t *testing.T, contract wasmtesting.IBCContractCallbacks, chain *wasmibctesting.TestChain) { - c := contract.(*nackReceiverContract) - c.t = t - }, - expChainABalanceDiff: sdk.ZeroInt(), - expChainBBalanceDiff: sdk.ZeroInt(), - }, - "error": { - contract: &errorReceiverContract{}, - setupContract: func(t *testing.T, contract wasmtesting.IBCContractCallbacks, chain *wasmibctesting.TestChain) { - c := contract.(*errorReceiverContract) - c.t = t - }, - expChainABalanceDiff: sdk.ZeroInt(), - expChainBBalanceDiff: sdk.ZeroInt(), - }, - } - for name, spec := range specs { - t.Run(name, func(t *testing.T) { - var ( - chainAOpts = []wasmkeeper.Option{wasmkeeper.WithWasmEngine( - wasmtesting.NewIBCContractMockWasmer(spec.contract), - )} - coordinator = wasmibctesting.NewCoordinator(t, 2, []wasmkeeper.Option{}, chainAOpts) - chainA = coordinator.GetChain(wasmibctesting.GetChainID(0)) - chainB = coordinator.GetChain(wasmibctesting.GetChainID(1)) - ) - coordinator.CommitBlock(chainA, chainB) - myContractAddr := chainB.SeedNewContractInstance() - contractBPortID := chainB.ContractInfo(myContractAddr).IBCPortID - - spec.setupContract(t, spec.contract, chainB) - - path := wasmibctesting.NewPath(chainA, chainB) - path.EndpointA.ChannelConfig = &wasmibctesting.ChannelConfig{ - PortID: "transfer", - Version: ibctransfertypes.Version, - Order: channeltypes.UNORDERED, - } - path.EndpointB.ChannelConfig = &wasmibctesting.ChannelConfig{ - PortID: contractBPortID, - Version: ibctransfertypes.Version, - Order: channeltypes.UNORDERED, - } - - coordinator.SetupConnections(path) - coordinator.CreateChannels(path) - - originalChainABalance := chainA.Balance(chainA.SenderAccount.GetAddress(), sdk.DefaultBondDenom) - // when transfer via sdk transfer from A (module) -> B (contract) - coinToSendToB := sdk.NewCoin(sdk.DefaultBondDenom, transferAmount) - timeoutHeight := clienttypes.NewHeight(1, 110) - msg := ibctransfertypes.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, coinToSendToB, chainA.SenderAccount.GetAddress().String(), chainB.SenderAccount.GetAddress().String(), timeoutHeight, 0) - _, err := chainA.SendMsgs(msg) - require.NoError(t, err) - require.NoError(t, path.EndpointB.UpdateClient()) - - // then - require.Equal(t, 1, len(chainA.PendingSendPackets)) - require.Equal(t, 0, len(chainB.PendingSendPackets)) - - // and when relay to chain B and handle Ack on chain A - err = coordinator.RelayAndAckPendingPackets(path) - require.NoError(t, err) - - // then - require.Equal(t, 0, len(chainA.PendingSendPackets)) - require.Equal(t, 0, len(chainB.PendingSendPackets)) - - // and source chain balance was decreased - newChainABalance := chainA.Balance(chainA.SenderAccount.GetAddress(), sdk.DefaultBondDenom) - assert.Equal(t, originalChainABalance.Amount.Add(spec.expChainABalanceDiff), newChainABalance.Amount) - - // and dest chain balance contains voucher - expBalance := ibctransfertypes.GetTransferCoin(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, coinToSendToB.Denom, spec.expChainBBalanceDiff) - gotBalance := chainB.Balance(chainB.SenderAccount.GetAddress(), expBalance.Denom) - assert.Equal(t, expBalance, gotBalance, "got total balance: %s", chainB.AllBalances(chainB.SenderAccount.GetAddress())) - }) - } -} - -func TestContractCanInitiateIBCTransferMsg(t *testing.T) { - // scenario: given two chains, - // with a contract on chain A - // then the contract can start an ibc transfer via ibctransfertypes.NewMsgTransfer - // that is handled on chain A by the ibc transfer module and - // received on chain B via ibc transfer module as well - - myContract := &sendViaIBCTransferContract{t: t} - var ( - chainAOpts = []wasmkeeper.Option{ - wasmkeeper.WithWasmEngine( - wasmtesting.NewIBCContractMockWasmer(myContract)), - } - coordinator = wasmibctesting.NewCoordinator(t, 2, chainAOpts) - chainA = coordinator.GetChain(wasmibctesting.GetChainID(0)) - chainB = coordinator.GetChain(wasmibctesting.GetChainID(1)) - ) - myContractAddr := chainA.SeedNewContractInstance() - coordinator.CommitBlock(chainA, chainB) - - path := wasmibctesting.NewPath(chainA, chainB) - path.EndpointA.ChannelConfig = &wasmibctesting.ChannelConfig{ - PortID: ibctransfertypes.PortID, - Version: ibctransfertypes.Version, - Order: channeltypes.UNORDERED, - } - path.EndpointB.ChannelConfig = &wasmibctesting.ChannelConfig{ - PortID: ibctransfertypes.PortID, - Version: ibctransfertypes.Version, - Order: channeltypes.UNORDERED, - } - coordinator.SetupConnections(path) - coordinator.CreateChannels(path) - - // when contract is triggered to send IBCTransferMsg - receiverAddress := chainB.SenderAccount.GetAddress() - coinToSendToB := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) - - // start transfer from chainA to chainB - startMsg := &types.MsgExecuteContract{ - Sender: chainA.SenderAccount.GetAddress().String(), - Contract: myContractAddr.String(), - Msg: startTransfer{ - ChannelID: path.EndpointA.ChannelID, - CoinsToSend: coinToSendToB, - ReceiverAddr: receiverAddress.String(), - }.GetBytes(), - } - _, err := chainA.SendMsgs(startMsg) - require.NoError(t, err) - - // then - require.Equal(t, 1, len(chainA.PendingSendPackets)) - require.Equal(t, 0, len(chainB.PendingSendPackets)) - - // and when relay to chain B and handle Ack on chain A - err = coordinator.RelayAndAckPendingPackets(path) - require.NoError(t, err) - - // then - require.Equal(t, 0, len(chainA.PendingSendPackets)) - require.Equal(t, 0, len(chainB.PendingSendPackets)) - - // and dest chain balance contains voucher - bankKeeperB := chainB.GetTestSupport().BankKeeper() - expBalance := ibctransfertypes.GetTransferCoin(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, coinToSendToB.Denom, coinToSendToB.Amount) - gotBalance := chainB.Balance(chainB.SenderAccount.GetAddress(), expBalance.Denom) - assert.Equal(t, expBalance, gotBalance, "got total balance: %s", bankKeeperB.GetAllBalances(chainB.GetContext(), chainB.SenderAccount.GetAddress())) -} - -func TestContractCanEmulateIBCTransferMessage(t *testing.T) { - // scenario: given two chains, - // with a contract on chain A - // then the contract can emulate the ibc transfer module in the contract to send an ibc packet - // which is received on chain B via ibc transfer module - - myContract := &sendEmulatedIBCTransferContract{t: t} - - var ( - chainAOpts = []wasmkeeper.Option{ - wasmkeeper.WithWasmEngine( - wasmtesting.NewIBCContractMockWasmer(myContract)), - } - coordinator = wasmibctesting.NewCoordinator(t, 2, chainAOpts) - - chainA = coordinator.GetChain(wasmibctesting.GetChainID(0)) - chainB = coordinator.GetChain(wasmibctesting.GetChainID(1)) - ) - myContractAddr := chainA.SeedNewContractInstance() - myContract.contractAddr = myContractAddr.String() - - path := wasmibctesting.NewPath(chainA, chainB) - path.EndpointA.ChannelConfig = &wasmibctesting.ChannelConfig{ - PortID: chainA.ContractInfo(myContractAddr).IBCPortID, - Version: ibctransfertypes.Version, - Order: channeltypes.UNORDERED, - } - path.EndpointB.ChannelConfig = &wasmibctesting.ChannelConfig{ - PortID: ibctransfertypes.PortID, - Version: ibctransfertypes.Version, - Order: channeltypes.UNORDERED, - } - coordinator.SetupConnections(path) - coordinator.CreateChannels(path) - - // when contract is triggered to send the ibc package to chain B - timeout := uint64(chainB.LastHeader.Header.Time.Add(time.Hour).UnixNano()) // enough time to not timeout - receiverAddress := chainB.SenderAccount.GetAddress() - coinToSendToB := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) - - // start transfer from chainA to chainB - startMsg := &types.MsgExecuteContract{ - Sender: chainA.SenderAccount.GetAddress().String(), - Contract: myContractAddr.String(), - Msg: startTransfer{ - ChannelID: path.EndpointA.ChannelID, - CoinsToSend: coinToSendToB, - ReceiverAddr: receiverAddress.String(), - ContractIBCPort: chainA.ContractInfo(myContractAddr).IBCPortID, - Timeout: timeout, - }.GetBytes(), - Funds: sdk.NewCoins(coinToSendToB), - } - _, err := chainA.SendMsgs(startMsg) - require.NoError(t, err) - - // then - require.Equal(t, 1, len(chainA.PendingSendPackets)) - require.Equal(t, 0, len(chainB.PendingSendPackets)) - - // and when relay to chain B and handle Ack on chain A - err = coordinator.RelayAndAckPendingPackets(path) - require.NoError(t, err) - - // then - require.Equal(t, 0, len(chainA.PendingSendPackets)) - require.Equal(t, 0, len(chainB.PendingSendPackets)) - - // and dest chain balance contains voucher - bankKeeperB := chainB.GetTestSupport().BankKeeper() - expBalance := ibctransfertypes.GetTransferCoin(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, coinToSendToB.Denom, coinToSendToB.Amount) - gotBalance := chainB.Balance(chainB.SenderAccount.GetAddress(), expBalance.Denom) - assert.Equal(t, expBalance, gotBalance, "got total balance: %s", bankKeeperB.GetAllBalances(chainB.GetContext(), chainB.SenderAccount.GetAddress())) -} - -func TestContractCanEmulateIBCTransferMessageWithTimeout(t *testing.T) { - // scenario: given two chains, - // with a contract on chain A - // then the contract can emulate the ibc transfer module in the contract to send an ibc packet - // which is not received on chain B and times out - - myContract := &sendEmulatedIBCTransferContract{t: t} - - var ( - chainAOpts = []wasmkeeper.Option{ - wasmkeeper.WithWasmEngine( - wasmtesting.NewIBCContractMockWasmer(myContract)), - } - coordinator = wasmibctesting.NewCoordinator(t, 2, chainAOpts) - - chainA = coordinator.GetChain(wasmibctesting.GetChainID(0)) - chainB = coordinator.GetChain(wasmibctesting.GetChainID(1)) - ) - coordinator.CommitBlock(chainA, chainB) - myContractAddr := chainA.SeedNewContractInstance() - myContract.contractAddr = myContractAddr.String() - - path := wasmibctesting.NewPath(chainA, chainB) - path.EndpointA.ChannelConfig = &wasmibctesting.ChannelConfig{ - PortID: chainA.ContractInfo(myContractAddr).IBCPortID, - Version: ibctransfertypes.Version, - Order: channeltypes.UNORDERED, - } - path.EndpointB.ChannelConfig = &wasmibctesting.ChannelConfig{ - PortID: ibctransfertypes.PortID, - Version: ibctransfertypes.Version, - Order: channeltypes.UNORDERED, - } - coordinator.SetupConnections(path) - coordinator.CreateChannels(path) - coordinator.UpdateTime() - - // when contract is triggered to send the ibc package to chain B - timeout := uint64(chainB.LastHeader.Header.Time.Add(time.Nanosecond).UnixNano()) // will timeout - receiverAddress := chainB.SenderAccount.GetAddress() - coinToSendToB := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) - initialContractBalance := chainA.Balance(myContractAddr, sdk.DefaultBondDenom) - initialSenderBalance := chainA.Balance(chainA.SenderAccount.GetAddress(), sdk.DefaultBondDenom) - - // custom payload data to be transferred into a proper ICS20 ibc packet - startMsg := &types.MsgExecuteContract{ - Sender: chainA.SenderAccount.GetAddress().String(), - Contract: myContractAddr.String(), - Msg: startTransfer{ - ChannelID: path.EndpointA.ChannelID, - CoinsToSend: coinToSendToB, - ReceiverAddr: receiverAddress.String(), - ContractIBCPort: chainA.ContractInfo(myContractAddr).IBCPortID, - Timeout: timeout, - }.GetBytes(), - Funds: sdk.NewCoins(coinToSendToB), - } - _, err := chainA.SendMsgs(startMsg) - require.NoError(t, err) - coordinator.CommitBlock(chainA, chainB) - // then - require.Equal(t, 1, len(chainA.PendingSendPackets)) - require.Equal(t, 0, len(chainB.PendingSendPackets)) - newContractBalance := chainA.Balance(myContractAddr, sdk.DefaultBondDenom) - assert.Equal(t, initialContractBalance.Add(coinToSendToB), newContractBalance) // hold in escrow - - // when timeout packet send (by the relayer) - err = coordinator.TimeoutPendingPackets(path) - require.NoError(t, err) - coordinator.CommitBlock(chainA) - - // then - require.Equal(t, 0, len(chainA.PendingSendPackets)) - require.Equal(t, 0, len(chainB.PendingSendPackets)) - - // and then verify account balances restored - newContractBalance = chainA.Balance(myContractAddr, sdk.DefaultBondDenom) - assert.Equal(t, initialContractBalance.String(), newContractBalance.String()) - newSenderBalance := chainA.Balance(chainA.SenderAccount.GetAddress(), sdk.DefaultBondDenom) - assert.Equal(t, initialSenderBalance.String(), newSenderBalance.String()) -} - -func TestContractHandlesChannelClose(t *testing.T) { - // scenario: a contract is the sending side of an ics20 transfer but the packet was not received - // on the destination chain within the timeout boundaries - myContractA := &captureCloseContract{} - myContractB := &captureCloseContract{} - - var ( - chainAOpts = []wasmkeeper.Option{ - wasmkeeper.WithWasmEngine( - wasmtesting.NewIBCContractMockWasmer(myContractA)), - } - chainBOpts = []wasmkeeper.Option{ - wasmkeeper.WithWasmEngine( - wasmtesting.NewIBCContractMockWasmer(myContractB)), - } - coordinator = wasmibctesting.NewCoordinator(t, 2, chainAOpts, chainBOpts) - - chainA = coordinator.GetChain(wasmibctesting.GetChainID(0)) - chainB = coordinator.GetChain(wasmibctesting.GetChainID(1)) - ) - - coordinator.CommitBlock(chainA, chainB) - myContractAddrA := chainA.SeedNewContractInstance() - _ = chainB.SeedNewContractInstance() // skip one instance - myContractAddrB := chainB.SeedNewContractInstance() - - path := wasmibctesting.NewPath(chainA, chainB) - path.EndpointA.ChannelConfig = &wasmibctesting.ChannelConfig{ - PortID: chainA.ContractInfo(myContractAddrA).IBCPortID, - Version: ibctransfertypes.Version, - Order: channeltypes.UNORDERED, - } - path.EndpointB.ChannelConfig = &wasmibctesting.ChannelConfig{ - PortID: chainB.ContractInfo(myContractAddrB).IBCPortID, - Version: ibctransfertypes.Version, - Order: channeltypes.UNORDERED, - } - coordinator.SetupConnections(path) - coordinator.CreateChannels(path) - coordinator.CloseChannel(path) - assert.True(t, myContractB.closeCalled) -} - -var _ wasmtesting.IBCContractCallbacks = &captureCloseContract{} - -// contract that sets a flag on IBC channel close only. -type captureCloseContract struct { - contractStub - closeCalled bool -} - -func (c *captureCloseContract) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelCloseMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { - c.closeCalled = true - return &wasmvmtypes.IBCBasicResponse{}, 1, nil -} - -var _ wasmtesting.IBCContractCallbacks = &sendViaIBCTransferContract{} - -// contract that initiates an ics-20 transfer on execute via sdk message -type sendViaIBCTransferContract struct { - contractStub - t *testing.T -} - -func (s *sendViaIBCTransferContract) Execute(code wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { - var in startTransfer - if err := json.Unmarshal(executeMsg, &in); err != nil { - return nil, 0, err - } - ibcMsg := &wasmvmtypes.IBCMsg{ - Transfer: &wasmvmtypes.TransferMsg{ - ToAddress: in.ReceiverAddr, - Amount: wasmvmtypes.NewCoin(in.CoinsToSend.Amount.Uint64(), in.CoinsToSend.Denom), - ChannelID: in.ChannelID, - Timeout: wasmvmtypes.IBCTimeout{Block: &wasmvmtypes.IBCTimeoutBlock{ - Revision: 0, - Height: 110, - }}, - }, - } - - return &wasmvmtypes.Response{Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{IBC: ibcMsg}}}}, 0, nil -} - -var _ wasmtesting.IBCContractCallbacks = &sendEmulatedIBCTransferContract{} - -// contract that interacts as an ics20 sending side via IBC packets -// It can also handle the timeout. -type sendEmulatedIBCTransferContract struct { - contractStub - t *testing.T - contractAddr string -} - -func (s *sendEmulatedIBCTransferContract) Execute(code wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { - var in startTransfer - if err := json.Unmarshal(executeMsg, &in); err != nil { - return nil, 0, err - } - require.Len(s.t, info.Funds, 1) - require.Equal(s.t, in.CoinsToSend.Amount.String(), info.Funds[0].Amount) - require.Equal(s.t, in.CoinsToSend.Denom, info.Funds[0].Denom) - dataPacket := ibctransfertypes.NewFungibleTokenPacketData( - in.CoinsToSend.Denom, in.CoinsToSend.Amount.String(), info.Sender, in.ReceiverAddr, - ) - if err := dataPacket.ValidateBasic(); err != nil { - return nil, 0, err - } - - ibcMsg := &wasmvmtypes.IBCMsg{ - SendPacket: &wasmvmtypes.SendPacketMsg{ - ChannelID: in.ChannelID, - Data: dataPacket.GetBytes(), - Timeout: wasmvmtypes.IBCTimeout{Timestamp: in.Timeout}, - }, - } - return &wasmvmtypes.Response{Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{IBC: ibcMsg}}}}, 0, nil -} - -func (c *sendEmulatedIBCTransferContract) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketTimeoutMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { - packet := msg.Packet - - var data ibctransfertypes.FungibleTokenPacketData - if err := ibctransfertypes.ModuleCdc.UnmarshalAsJSON(packet.Data, &data); err != nil { - return nil, 0, err - } - if err := data.ValidateBasic(); err != nil { - return nil, 0, err - } - amount, _ := sdk.NewIntFromString(data.Amount) - - returnTokens := &wasmvmtypes.BankMsg{ - Send: &wasmvmtypes.SendMsg{ - ToAddress: data.Sender, - Amount: wasmvmtypes.Coins{wasmvmtypes.NewCoin(amount.Uint64(), data.Denom)}, - }, - } - - return &wasmvmtypes.IBCBasicResponse{Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: returnTokens}}}}, 0, nil -} - -// custom contract execute payload -type startTransfer struct { - ChannelID string - CoinsToSend sdk.Coin - ReceiverAddr string - ContractIBCPort string - Timeout uint64 -} - -func (g startTransfer) GetBytes() types.RawContractMessage { - b, err := json.Marshal(g) - if err != nil { - panic(err) - } - return b -} - -var _ wasmtesting.IBCContractCallbacks = &ackReceiverContract{} - -// contract that acts as the receiving side for an ics-20 transfer. -type ackReceiverContract struct { - contractStub - t *testing.T - chain *wasmibctesting.TestChain -} - -func (c *ackReceiverContract) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResult, uint64, error) { - packet := msg.Packet - - var src ibctransfertypes.FungibleTokenPacketData - if err := ibctransfertypes.ModuleCdc.UnmarshalAsJSON(packet.Data, &src); err != nil { - return nil, 0, err - } - require.NoError(c.t, src.ValidateBasic()) - - // call original ibctransfer keeper to not copy all code into this - ibcPacket := toIBCPacket(packet) - ctx := c.chain.GetContext() // HACK: please note that this is not reverted after checkTX - err := c.chain.GetTestSupport().TransferKeeper().OnRecvPacket(ctx, ibcPacket, src) - if err != nil { - return nil, 0, sdkerrors.Wrap(err, "within our smart contract") - } - - var log []wasmvmtypes.EventAttribute // note: all events are under `wasm` event type - ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}).Acknowledgement() - return &wasmvmtypes.IBCReceiveResult{Ok: &wasmvmtypes.IBCReceiveResponse{Acknowledgement: ack, Attributes: log}}, 0, nil -} - -func (c *ackReceiverContract) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketAckMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { - var data ibctransfertypes.FungibleTokenPacketData - if err := ibctransfertypes.ModuleCdc.UnmarshalAsJSON(msg.OriginalPacket.Data, &data); err != nil { - return nil, 0, err - } - // call original ibctransfer keeper to not copy all code into this - - var ack channeltypes.Acknowledgement - if err := ibctransfertypes.ModuleCdc.UnmarshalAsJSON(msg.Acknowledgement.Data, &ack); err != nil { - return nil, 0, err - } - - // call original ibctransfer keeper to not copy all code into this - ctx := c.chain.GetContext() // HACK: please note that this is not reverted after checkTX - ibcPacket := toIBCPacket(msg.OriginalPacket) - err := c.chain.GetTestSupport().TransferKeeper().OnAcknowledgementPacket(ctx, ibcPacket, data, ack) - if err != nil { - return nil, 0, sdkerrors.Wrap(err, "within our smart contract") - } - - return &wasmvmtypes.IBCBasicResponse{}, 0, nil -} - -// contract that acts as the receiving side for an ics-20 transfer and always returns a nack. -type nackReceiverContract struct { - contractStub - t *testing.T -} - -func (c *nackReceiverContract) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResult, uint64, error) { - packet := msg.Packet - - var src ibctransfertypes.FungibleTokenPacketData - if err := ibctransfertypes.ModuleCdc.UnmarshalAsJSON(packet.Data, &src); err != nil { - return nil, 0, err - } - require.NoError(c.t, src.ValidateBasic()) - return &wasmvmtypes.IBCReceiveResult{Err: "nack-testing"}, 0, nil -} - -// contract that acts as the receiving side for an ics-20 transfer and always returns an error. -type errorReceiverContract struct { - contractStub - t *testing.T -} - -func (c *errorReceiverContract) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResult, uint64, error) { - packet := msg.Packet - - var src ibctransfertypes.FungibleTokenPacketData - if err := ibctransfertypes.ModuleCdc.UnmarshalAsJSON(packet.Data, &src); err != nil { - return nil, 0, err - } - require.NoError(c.t, src.ValidateBasic()) - return nil, 0, errors.New("error-testing") -} - -// simple helper struct that implements connection setup methods. -type contractStub struct{} - -func (s *contractStub) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBC3ChannelOpenResponse, uint64, error) { - return &wasmvmtypes.IBC3ChannelOpenResponse{}, 0, nil -} - -func (s *contractStub) IBCChannelConnect(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelConnectMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { - return &wasmvmtypes.IBCBasicResponse{}, 0, nil -} - -func (s *contractStub) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelCloseMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { - panic("implement me") -} - -func (s *contractStub) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResult, uint64, error) { - panic("implement me") -} - -func (s *contractStub) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketAckMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { - return &wasmvmtypes.IBCBasicResponse{}, 0, nil -} - -func (s *contractStub) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketTimeoutMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { - panic("implement me") -} - -func toIBCPacket(p wasmvmtypes.IBCPacket) channeltypes.Packet { - var height clienttypes.Height - if p.Timeout.Block != nil { - height = clienttypes.NewHeight(p.Timeout.Block.Revision, p.Timeout.Block.Height) - } - return channeltypes.Packet{ - Sequence: p.Sequence, - SourcePort: p.Src.PortID, - SourceChannel: p.Src.ChannelID, - DestinationPort: p.Dest.PortID, - DestinationChannel: p.Dest.ChannelID, - Data: p.Data, - TimeoutHeight: height, - TimeoutTimestamp: p.Timeout.Timestamp, - } -} From 6aeead8bb2b7a1b45042f5910a88ab513654c57e Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Tue, 18 Aug 2026 15:43:00 +0100 Subject: [PATCH 3/5] Avoid modifying old precompiles while cleaning up IBC --- precompiles/ibc/legacy/v65/ibc.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/precompiles/ibc/legacy/v65/ibc.go b/precompiles/ibc/legacy/v65/ibc.go index f5870349e0..a2db1705b5 100644 --- a/precompiles/ibc/legacy/v65/ibc.go +++ b/precompiles/ibc/legacy/v65/ibc.go @@ -166,7 +166,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -252,7 +252,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err From 3b59bdd69ccf9d542aeacf8118a69a8b0b5e75c9 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Tue, 18 Aug 2026 15:43:00 +0100 Subject: [PATCH 4/5] Avoid modifying old precompiles while cleaning up IBC --- precompiles/ibc/ibc_test.go | 12 ------ precompiles/ibc/legacy/v555/ibc.go | 4 +- precompiles/ibc/legacy/v562/ibc.go | 4 +- precompiles/ibc/legacy/v580/ibc.go | 4 +- precompiles/ibc/legacy/v601/ibc.go | 4 +- precompiles/ibc/legacy/v603/ibc.go | 4 +- precompiles/ibc/legacy/v605/ibc.go | 4 +- precompiles/ibc/legacy/v606/ibc.go | 4 +- precompiles/ibc/legacy/v610/ibc.go | 4 +- precompiles/ibc/legacy/v614/ibc.go | 4 +- precompiles/ibc/legacy/v620/ibc.go | 4 +- precompiles/ibc/legacy/v630/ibc.go | 4 +- precompiles/ibc/legacy/v640/ibc.go | 4 +- precompiles/ibc/legacy/v66/ibc.go | 4 +- precompiles/utils/expected_keepers.go | 1 - .../transfer/keeper/deprecated_msg_server.go | 22 ++++++++++ ..._test.go => deprecated_msg_server_test.go} | 2 +- .../apps/transfer/keeper/legacy_transfer.go | 40 ------------------- .../apps/transfer/keeper/msg_server.go | 39 ++++++++++++++++-- sei-ibc-go/modules/apps/transfer/module.go | 4 +- 20 files changed, 88 insertions(+), 84 deletions(-) create mode 100644 sei-ibc-go/modules/apps/transfer/keeper/deprecated_msg_server.go rename sei-ibc-go/modules/apps/transfer/keeper/{msg_server_test.go => deprecated_msg_server_test.go} (75%) delete mode 100644 sei-ibc-go/modules/apps/transfer/keeper/legacy_transfer.go diff --git a/precompiles/ibc/ibc_test.go b/precompiles/ibc/ibc_test.go index 9b4241cee5..25136a2c9e 100644 --- a/precompiles/ibc/ibc_test.go +++ b/precompiles/ibc/ibc_test.go @@ -29,10 +29,6 @@ func (tk *MockTransferKeeper) Transfer(goCtx context.Context, msg *types.MsgTran return nil, nil } -func (tk *MockTransferKeeper) LegacyTransfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { - return tk.Transfer(goCtx, msg) -} - func (tk *MockTransferKeeper) SendTransfer( ctx sdk.Context, sourcePort, @@ -56,10 +52,6 @@ func (tk *MockMemoTransferKeeper) Transfer(goCtx context.Context, msg *types.Msg return nil, nil } -func (tk *MockMemoTransferKeeper) LegacyTransfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { - return tk.Transfer(goCtx, msg) -} - func (tk *MockMemoTransferKeeper) SendTransfer( ctx sdk.Context, sourcePort, @@ -79,10 +71,6 @@ func (tk *MockFailedTransferTransferKeeper) Transfer(goCtx context.Context, msg return nil, errors.New("failed to send transfer") } -func (tk *MockFailedTransferTransferKeeper) LegacyTransfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { - return tk.Transfer(goCtx, msg) -} - func (tk *MockFailedTransferTransferKeeper) SendTransfer( ctx sdk.Context, sourcePort, diff --git a/precompiles/ibc/legacy/v555/ibc.go b/precompiles/ibc/legacy/v555/ibc.go index 902a2390eb..696a3ff6dc 100644 --- a/precompiles/ibc/legacy/v555/ibc.go +++ b/precompiles/ibc/legacy/v555/ibc.go @@ -219,7 +219,7 @@ func (p Precompile) transfer(ctx sdk.Context, method *abi.Method, args []interfa return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -305,7 +305,7 @@ func (p Precompile) transferWithDefaultTimeout(ctx sdk.Context, method *abi.Meth return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v562/ibc.go b/precompiles/ibc/legacy/v562/ibc.go index 8c201e885c..698059cb7b 100644 --- a/precompiles/ibc/legacy/v562/ibc.go +++ b/precompiles/ibc/legacy/v562/ibc.go @@ -177,7 +177,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -263,7 +263,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v580/ibc.go b/precompiles/ibc/legacy/v580/ibc.go index b707666c67..2c57648404 100644 --- a/precompiles/ibc/legacy/v580/ibc.go +++ b/precompiles/ibc/legacy/v580/ibc.go @@ -163,7 +163,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -249,7 +249,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v601/ibc.go b/precompiles/ibc/legacy/v601/ibc.go index 50ec38e725..2409bed68b 100644 --- a/precompiles/ibc/legacy/v601/ibc.go +++ b/precompiles/ibc/legacy/v601/ibc.go @@ -163,7 +163,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -249,7 +249,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v603/ibc.go b/precompiles/ibc/legacy/v603/ibc.go index c82e4a99d7..4bf2d17e52 100644 --- a/precompiles/ibc/legacy/v603/ibc.go +++ b/precompiles/ibc/legacy/v603/ibc.go @@ -162,7 +162,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -248,7 +248,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v605/ibc.go b/precompiles/ibc/legacy/v605/ibc.go index 64365f6138..8fdfe973d0 100644 --- a/precompiles/ibc/legacy/v605/ibc.go +++ b/precompiles/ibc/legacy/v605/ibc.go @@ -166,7 +166,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -252,7 +252,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v606/ibc.go b/precompiles/ibc/legacy/v606/ibc.go index 62fa5e21e5..b76057374b 100644 --- a/precompiles/ibc/legacy/v606/ibc.go +++ b/precompiles/ibc/legacy/v606/ibc.go @@ -166,7 +166,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -252,7 +252,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v610/ibc.go b/precompiles/ibc/legacy/v610/ibc.go index 627aad0d1c..d0e571f8e7 100644 --- a/precompiles/ibc/legacy/v610/ibc.go +++ b/precompiles/ibc/legacy/v610/ibc.go @@ -166,7 +166,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -252,7 +252,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v614/ibc.go b/precompiles/ibc/legacy/v614/ibc.go index d922d29ce3..97e76b3719 100644 --- a/precompiles/ibc/legacy/v614/ibc.go +++ b/precompiles/ibc/legacy/v614/ibc.go @@ -166,7 +166,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -252,7 +252,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v620/ibc.go b/precompiles/ibc/legacy/v620/ibc.go index 1755af75ed..830b15c57e 100644 --- a/precompiles/ibc/legacy/v620/ibc.go +++ b/precompiles/ibc/legacy/v620/ibc.go @@ -166,7 +166,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -252,7 +252,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v630/ibc.go b/precompiles/ibc/legacy/v630/ibc.go index 560b3bb6d2..33cee9208a 100644 --- a/precompiles/ibc/legacy/v630/ibc.go +++ b/precompiles/ibc/legacy/v630/ibc.go @@ -166,7 +166,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -252,7 +252,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v640/ibc.go b/precompiles/ibc/legacy/v640/ibc.go index cdd786022f..77597bd1e1 100644 --- a/precompiles/ibc/legacy/v640/ibc.go +++ b/precompiles/ibc/legacy/v640/ibc.go @@ -166,7 +166,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -252,7 +252,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/ibc/legacy/v66/ibc.go b/precompiles/ibc/legacy/v66/ibc.go index 9e6dc24f9f..2d705225ce 100644 --- a/precompiles/ibc/legacy/v66/ibc.go +++ b/precompiles/ibc/legacy/v66/ibc.go @@ -168,7 +168,7 @@ func (p PrecompileExecutor) transfer(ctx sdk.Context, method *abi.Method, args [ return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err @@ -254,7 +254,7 @@ func (p PrecompileExecutor) transferWithDefaultTimeout(ctx sdk.Context, method * return } - _, err = p.transferKeeper.LegacyTransfer(sdk.WrapSDKContext(ctx), &msg) + _, err = p.transferKeeper.Transfer(sdk.WrapSDKContext(ctx), &msg) if err != nil { rerr = err diff --git a/precompiles/utils/expected_keepers.go b/precompiles/utils/expected_keepers.go index 83fb8779b8..ab0581c70e 100644 --- a/precompiles/utils/expected_keepers.go +++ b/precompiles/utils/expected_keepers.go @@ -234,7 +234,6 @@ type DistributionKeeper interface { type TransferKeeper interface { Transfer(goCtx context.Context, msg *ibctypes.MsgTransfer) (*ibctypes.MsgTransferResponse, error) - LegacyTransfer(goCtx context.Context, msg *ibctypes.MsgTransfer) (*ibctypes.MsgTransferResponse, error) SendTransfer( ctx sdk.Context, sourcePort, diff --git a/sei-ibc-go/modules/apps/transfer/keeper/deprecated_msg_server.go b/sei-ibc-go/modules/apps/transfer/keeper/deprecated_msg_server.go new file mode 100644 index 0000000000..593ee23abd --- /dev/null +++ b/sei-ibc-go/modules/apps/transfer/keeper/deprecated_msg_server.go @@ -0,0 +1,22 @@ +package keeper + +import ( + "context" + + "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/apps/transfer/types" +) + +// DeprecatedMsgServer is a types.MsgServer that rejects every message with +// types.ErrTransferDeprecated. +// +// It is registered as the transfer module's message server so that submitted +// transactions are rejected, while Keeper retains the executable transfer +// logic for the versioned EVM precompiles that replay historical blocks. +type DeprecatedMsgServer struct{} + +var _ types.MsgServer = DeprecatedMsgServer{} + +// Transfer defines an RPC handler for MsgTransfer. +func (DeprecatedMsgServer) Transfer(context.Context, *types.MsgTransfer) (*types.MsgTransferResponse, error) { + return nil, types.ErrTransferDeprecated +} diff --git a/sei-ibc-go/modules/apps/transfer/keeper/msg_server_test.go b/sei-ibc-go/modules/apps/transfer/keeper/deprecated_msg_server_test.go similarity index 75% rename from sei-ibc-go/modules/apps/transfer/keeper/msg_server_test.go rename to sei-ibc-go/modules/apps/transfer/keeper/deprecated_msg_server_test.go index 8fd5c25ea9..34fe4ce871 100644 --- a/sei-ibc-go/modules/apps/transfer/keeper/msg_server_test.go +++ b/sei-ibc-go/modules/apps/transfer/keeper/deprecated_msg_server_test.go @@ -10,7 +10,7 @@ import ( ) func TestDeprecatedMessages(t *testing.T) { - response, err := (Keeper{}).Transfer(context.Background(), &types.MsgTransfer{}) + response, err := DeprecatedMsgServer{}.Transfer(context.Background(), &types.MsgTransfer{}) require.Nil(t, response) require.ErrorIs(t, err, types.ErrTransferDeprecated) diff --git a/sei-ibc-go/modules/apps/transfer/keeper/legacy_transfer.go b/sei-ibc-go/modules/apps/transfer/keeper/legacy_transfer.go deleted file mode 100644 index 537880a9d4..0000000000 --- a/sei-ibc-go/modules/apps/transfer/keeper/legacy_transfer.go +++ /dev/null @@ -1,40 +0,0 @@ -package keeper - -import ( - "context" - - sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" - - "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/apps/transfer/types" -) - -// LegacyTransfer executes a transfer for versioned historical EVM precompiles. -func (k Keeper) LegacyTransfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - sender, err := sdk.AccAddressFromBech32(msg.Sender) - if err != nil { - return nil, err - } - - sequence, err := k.sendTransfer( - ctx, msg.SourcePort, msg.SourceChannel, msg.Token, sender, msg.Receiver, msg.TimeoutHeight, msg.TimeoutTimestamp, - msg.Memo) - if err != nil { - return nil, err - } - - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeTransfer, - sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), - sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), - ), - }) - - return &types.MsgTransferResponse{Sequence: sequence}, nil -} diff --git a/sei-ibc-go/modules/apps/transfer/keeper/msg_server.go b/sei-ibc-go/modules/apps/transfer/keeper/msg_server.go index 893a1381c6..be0da16973 100644 --- a/sei-ibc-go/modules/apps/transfer/keeper/msg_server.go +++ b/sei-ibc-go/modules/apps/transfer/keeper/msg_server.go @@ -3,12 +3,45 @@ package keeper import ( "context" + sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" + "github.com/sei-protocol/seilog" + "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/apps/transfer/types" ) +var logger = seilog.NewLogger("ibc-go", "modules", "apps", "transfer", "keeper") + var _ types.MsgServer = Keeper{} -// Transfer defines an RPC handler for MsgTransfer. -func (Keeper) Transfer(context.Context, *types.MsgTransfer) (*types.MsgTransferResponse, error) { - return nil, types.ErrTransferDeprecated +// Transfer defines a rpc handler method for MsgTransfer. +func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return nil, err + } + + sequence, err := k.sendTransfer( + ctx, msg.SourcePort, msg.SourceChannel, msg.Token, sender, msg.Receiver, msg.TimeoutHeight, msg.TimeoutTimestamp, + msg.Memo) + if err != nil { + return nil, err + } + + logger.Info("IBC fungible token transfer", "token", msg.Token.Denom, "amount", msg.Token.Amount, "sender", msg.Sender, "receiver", msg.Receiver) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + types.EventTypeTransfer, + sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), + sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver), + ), + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + ), + }) + + return &types.MsgTransferResponse{Sequence: sequence}, nil } diff --git a/sei-ibc-go/modules/apps/transfer/module.go b/sei-ibc-go/modules/apps/transfer/module.go index 7fcb407f1a..07929261c2 100644 --- a/sei-ibc-go/modules/apps/transfer/module.go +++ b/sei-ibc-go/modules/apps/transfer/module.go @@ -131,7 +131,9 @@ func (am AppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Querier { // RegisterServices registers module services. func (am AppModule) RegisterServices(cfg module.Configurator) { - types.RegisterMsgServer(cfg.MsgServer(), am.keeper) + // Transactions are rejected as deprecated; Keeper.Transfer stays executable + // for the versioned EVM precompiles that replay historical blocks. + types.RegisterMsgServer(cfg.MsgServer(), keeper.DeprecatedMsgServer{}) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) m := keeper.NewMigrator(am.keeper) From 8d9d9b5ac0165b2dc47082c3649879ba64d16066 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Tue, 18 Aug 2026 15:56:55 +0100 Subject: [PATCH 5/5] Clean up CLI dependencies --- .../modules/core/02-client/client/cli/tx.go | 165 ------------------ .../core/02-client/client/proposal_handler.go | 26 --- .../modules/core/02-client/keeper/events.go | 68 -------- .../modules/core/02-client/keeper/metrics.go | 12 -- 4 files changed, 271 deletions(-) delete mode 100644 sei-ibc-go/modules/core/02-client/client/proposal_handler.go diff --git a/sei-ibc-go/modules/core/02-client/client/cli/tx.go b/sei-ibc-go/modules/core/02-client/client/cli/tx.go index 482178b971..6b2313dd7b 100644 --- a/sei-ibc-go/modules/core/02-client/client/cli/tx.go +++ b/sei-ibc-go/modules/core/02-client/client/cli/tx.go @@ -4,17 +4,12 @@ import ( "fmt" "os" "path/filepath" - "strconv" "github.com/sei-protocol/sei-chain/sei-cosmos/client" "github.com/sei-protocol/sei-chain/sei-cosmos/client/flags" "github.com/sei-protocol/sei-chain/sei-cosmos/client/tx" "github.com/sei-protocol/sei-chain/sei-cosmos/codec" - sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" "github.com/sei-protocol/sei-chain/sei-cosmos/version" - govcli "github.com/sei-protocol/sei-chain/sei-cosmos/x/gov/client/cli" - govtypes "github.com/sei-protocol/sei-chain/sei-cosmos/x/gov/types" - upgradetypes "github.com/sei-protocol/sei-chain/sei-cosmos/x/upgrade/types" "github.com/spf13/cobra" "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/types" @@ -233,163 +228,3 @@ func NewUpgradeClientCmd() *cobra.Command { return cmd } - -// NewCmdSubmitUpdateClientProposal implements a command handler for submitting an update IBC client proposal transaction. -func NewCmdSubmitUpdateClientProposal() *cobra.Command { - cmd := &cobra.Command{ - Use: "update-client [subject-client-id] [substitute-client-id]", - Args: cobra.ExactArgs(2), - Short: "Submit an update IBC client proposal", - Long: "Submit an update IBC client proposal along with an initial deposit.\n" + - "Please specify a subject client identifier you want to update..\n" + - "Please specify the substitute client the subject client will be updated to.", - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - - title, err := cmd.Flags().GetString(govcli.FlagTitle) - if err != nil { - return err - } - - description, err := cmd.Flags().GetString(govcli.FlagDescription) - if err != nil { - return err - } - - subjectClientID := args[0] - substituteClientID := args[1] - - content := types.NewClientUpdateProposal(title, description, subjectClientID, substituteClientID) - - from := clientCtx.GetFromAddress() - - depositStr, err := cmd.Flags().GetString(govcli.FlagDeposit) - if err != nil { - return err - } - deposit, err := sdk.ParseCoinsNormalized(depositStr) - if err != nil { - return err - } - - msg, err := govtypes.NewMsgSubmitProposal(content, deposit, from) - if err != nil { - return err - } - - if err = msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(cmd.Context(), clientCtx, cmd.Flags(), msg) - }, - } - - cmd.Flags().String(govcli.FlagTitle, "", "title of proposal") - cmd.Flags().String(govcli.FlagDescription, "", "description of proposal") - cmd.Flags().String(govcli.FlagDeposit, "", "deposit of proposal") - - return cmd -} - -// NewCmdSubmitUpgradeProposal implements a command handler for submitting an upgrade IBC client proposal transaction. -func NewCmdSubmitUpgradeProposal() *cobra.Command { - cmd := &cobra.Command{ - Use: "ibc-upgrade [name] [height] [path/to/upgraded_client_state.json] [flags]", - Args: cobra.ExactArgs(3), - Short: "Submit an IBC upgrade proposal", - Long: "Submit an IBC client breaking upgrade proposal along with an initial deposit.\n" + - "The client state specified is the upgraded client state representing the upgraded chain\n" + - `Example Upgraded Client State JSON: -{ - "@type":"/ibc.lightclients.tendermint.v1.ClientState", - "chain_id":"testchain1", - "unbonding_period":"1814400s", - "latest_height":{"revision_number":"0","revision_height":"2"}, - "proof_specs":[{"leaf_spec":{"hash":"SHA256","prehash_key":"NO_HASH","prehash_value":"SHA256","length":"VAR_PROTO","prefix":"AA=="},"inner_spec":{"child_order":[0,1],"child_size":33,"min_prefix_length":4,"max_prefix_length":12,"empty_child":null,"hash":"SHA256"},"max_depth":0,"min_depth":0},{"leaf_spec":{"hash":"SHA256","prehash_key":"NO_HASH","prehash_value":"SHA256","length":"VAR_PROTO","prefix":"AA=="},"inner_spec":{"child_order":[0,1],"child_size":32,"min_prefix_length":1,"max_prefix_length":1,"empty_child":null,"hash":"SHA256"},"max_depth":0,"min_depth":0}], - "upgrade_path":["upgrade","upgradedIBCState"], -} - `, - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - title, err := cmd.Flags().GetString(govcli.FlagTitle) - if err != nil { - return err - } - - description, err := cmd.Flags().GetString(govcli.FlagDescription) - if err != nil { - return err - } - - name := args[0] - - height, err := strconv.ParseInt(args[1], 10, 64) - if err != nil { - return err - } - - plan := upgradetypes.Plan{ - Name: name, - Height: height, - } - - // attempt to unmarshal client state argument - var clientState exported.ClientState - clientContentOrFileName := args[2] - if err := cdc.UnmarshalInterfaceJSON([]byte(clientContentOrFileName), &clientState); err != nil { - - // check for file path if JSON input is not provided - contents, err := os.ReadFile(filepath.Clean(clientContentOrFileName)) - if err != nil { - return fmt.Errorf("neither JSON input nor path to .json file for client state were provided: %w", err) - } - - if err := cdc.UnmarshalInterfaceJSON(contents, &clientState); err != nil { - return fmt.Errorf("error unmarshalling client state file: %w", err) - } - } - - content, err := types.NewUpgradeProposal(title, description, plan, clientState) - if err != nil { - return err - } - - from := clientCtx.GetFromAddress() - - depositStr, err := cmd.Flags().GetString(govcli.FlagDeposit) - if err != nil { - return err - } - deposit, err := sdk.ParseCoinsNormalized(depositStr) - if err != nil { - return err - } - - msg, err := govtypes.NewMsgSubmitProposal(content, deposit, from) - if err != nil { - return err - } - - if err = msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(cmd.Context(), clientCtx, cmd.Flags(), msg) - }, - } - - cmd.Flags().String(govcli.FlagTitle, "", "title of proposal") - cmd.Flags().String(govcli.FlagDescription, "", "description of proposal") - cmd.Flags().String(govcli.FlagDeposit, "", "deposit of proposal") - - return cmd -} diff --git a/sei-ibc-go/modules/core/02-client/client/proposal_handler.go b/sei-ibc-go/modules/core/02-client/client/proposal_handler.go deleted file mode 100644 index a455de9ccb..0000000000 --- a/sei-ibc-go/modules/core/02-client/client/proposal_handler.go +++ /dev/null @@ -1,26 +0,0 @@ -package client - -import ( - "net/http" - - "github.com/sei-protocol/sei-chain/sei-cosmos/client" - "github.com/sei-protocol/sei-chain/sei-cosmos/types/rest" - govclient "github.com/sei-protocol/sei-chain/sei-cosmos/x/gov/client" - govrest "github.com/sei-protocol/sei-chain/sei-cosmos/x/gov/client/rest" - - "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/client/cli" -) - -var ( - UpdateClientProposalHandler = govclient.NewProposalHandler(cli.NewCmdSubmitUpdateClientProposal, emptyRestHandler) - UpgradeProposalHandler = govclient.NewProposalHandler(cli.NewCmdSubmitUpgradeProposal, emptyRestHandler) -) - -func emptyRestHandler(client.Context) govrest.ProposalRESTHandler { - return govrest.ProposalRESTHandler{ - SubRoute: "unsupported-ibc-client", - Handler: func(w http.ResponseWriter, r *http.Request) { - rest.WriteErrorResponse(w, http.StatusBadRequest, "Legacy REST Routes are not supported for IBC proposals") - }, - } -} diff --git a/sei-ibc-go/modules/core/02-client/keeper/events.go b/sei-ibc-go/modules/core/02-client/keeper/events.go index a80941a5a4..e356b29140 100644 --- a/sei-ibc-go/modules/core/02-client/keeper/events.go +++ b/sei-ibc-go/modules/core/02-client/keeper/events.go @@ -1,30 +1,12 @@ package keeper import ( - "fmt" - sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/02-client/types" "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/exported" ) -// EmitCreateClientEvent emits a create client event -func EmitCreateClientEvent(ctx sdk.Context, clientID string, clientState exported.ClientState) { - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeCreateClient, - sdk.NewAttribute(types.AttributeKeyClientID, clientID), - sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()), - sdk.NewAttribute(types.AttributeKeyConsensusHeight, clientState.GetLatestHeight().String()), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), - ), - }) -} - // EmitUpdateClientEvent emits an update client event func EmitUpdateClientEvent(ctx sdk.Context, clientID string, clientState exported.ClientState, consensusHeight exported.Height, headerStr string) { ctx.EventManager().EmitEvents(sdk.Events{ @@ -42,56 +24,6 @@ func EmitUpdateClientEvent(ctx sdk.Context, clientID string, clientState exporte }) } -// EmitUpdateClientEvent emits an upgrade client event -func EmitUpgradeClientEvent(ctx sdk.Context, clientID string, clientState exported.ClientState) { - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeUpgradeClient, - sdk.NewAttribute(types.AttributeKeyClientID, clientID), - sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()), - sdk.NewAttribute(types.AttributeKeyConsensusHeight, clientState.GetLatestHeight().String()), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), - ), - }) -} - -// EmitUpdateClientProposalEvent emits an update client proposal event -func EmitUpdateClientProposalEvent(ctx sdk.Context, clientID string, clientState exported.ClientState) { - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypeUpdateClientProposal, - sdk.NewAttribute(types.AttributeKeySubjectClientID, clientID), - sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()), - sdk.NewAttribute(types.AttributeKeyConsensusHeight, clientState.GetLatestHeight().String()), - ), - ) -} - -// EmitUpgradeClientProposalEvent emits an upgrade client proposal event -func EmitUpgradeClientProposalEvent(ctx sdk.Context, title string, height int64) { - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypeUpgradeClientProposal, - sdk.NewAttribute(types.AttributeKeyUpgradePlanTitle, title), - sdk.NewAttribute(types.AttributeKeyUpgradePlanHeight, fmt.Sprintf("%d", height)), - ), - ) -} - -// EmitSubmitMisbehaviourEvent emits a client misbehaviour event -func EmitSubmitMisbehaviourEvent(ctx sdk.Context, clientID string, clientState exported.ClientState) { - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypeSubmitMisbehaviour, - sdk.NewAttribute(types.AttributeKeyClientID, clientID), - sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()), - ), - ) -} - // EmitSubmitMisbehaviourEventOnUpdate emits a client misbehaviour event on a client update event func EmitSubmitMisbehaviourEventOnUpdate(ctx sdk.Context, clientID string, clientState exported.ClientState, consensusHeight exported.Height, headerStr string) { ctx.EventManager().EmitEvent( diff --git a/sei-ibc-go/modules/core/02-client/keeper/metrics.go b/sei-ibc-go/modules/core/02-client/keeper/metrics.go index fc9febaafa..3f316523c4 100644 --- a/sei-ibc-go/modules/core/02-client/keeper/metrics.go +++ b/sei-ibc-go/modules/core/02-client/keeper/metrics.go @@ -9,26 +9,14 @@ var ( meter = otel.Meter("ibc_core_client_keeper") ibcClientMetrics = struct { - ibcClientCreate metric.Int64Counter ibcClientUpdate metric.Int64Counter - ibcClientUpgrade metric.Int64Counter ibcClientMisbehaviour metric.Int64Counter }{ - ibcClientCreate: must(meter.Int64Counter( - "ibc_client_create", - metric.WithDescription("Total number of IBC client creates"), - metric.WithUnit("{count}"), - )), ibcClientUpdate: must(meter.Int64Counter( "ibc_client_update", metric.WithDescription("Total number of IBC client updates"), metric.WithUnit("{count}"), )), - ibcClientUpgrade: must(meter.Int64Counter( - "ibc_client_upgrade", - metric.WithDescription("Total number of IBC client upgrades"), - metric.WithUnit("{count}"), - )), ibcClientMisbehaviour: must(meter.Int64Counter( "ibc_client_misbehaviour", metric.WithDescription("Total number of IBC client misbehaviour events"),