Refactor x/ibc to ADR 031 (#7576)

* WIP: Refactor x/ibc to ADR 031

* updated handler

* removed unsued

* fix

* Add proto service for ibc/transfer

* lint

* remove old upgrade handler

* added doc

* review changes

* fix tests

* formatter

* Add MsgServer wiring in RegisterServices

Co-authored-by: Aaron Craelius <aaronc@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
atheeshp 2020-10-19 23:51:53 +05:30 committed by GitHub
parent eba4c8a264
commit 155a6ad7fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 6018 additions and 2471 deletions

View File

@ -7,6 +7,12 @@ import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";
import "ibc/core/client/v1/client.proto";
// Msg defines the ibc/transfer Msg service.
service Msg {
// Transfer defines a rpc handler method for MsgTransfer.
rpc Transfer(MsgTransfer) returns (MsgTransferResponse);
}
// MsgTransfer defines a msg to transfer fungible tokens (i.e Coins) between
// ICS20 enabled chains. See ICS Spec here:
// https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures
@ -33,6 +39,9 @@ message MsgTransfer {
uint64 timeout_timestamp = 7 [(gogoproto.moretags) = "yaml:\"timeout_timestamp\""];
}
// MsgTransferResponse defines the Msg/Transfer response type.
message MsgTransferResponse { }
// FungibleTokenPacketData defines a struct for the packet payload
// See FungibleTokenPacketData spec:
// https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures

View File

@ -6,6 +6,39 @@ option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types";
import "gogoproto/gogo.proto";
import "ibc/core/client/v1/client.proto";
// Msg defines the ibc/channel Msg service.
service Msg {
// ChannelOpenInit defines a rpc handler method for MsgChannelOpenInit.
rpc ChannelOpenInit(MsgChannelOpenInit) returns (MsgChannelOpenInitResponse);
// ChannelOpenTry defines a rpc handler method for MsgChannelOpenTry.
rpc ChannelOpenTry(MsgChannelOpenTry) returns (MsgChannelOpenTryResponse);
// ChannelOpenAck defines a rpc handler method for MsgChannelOpenAck.
rpc ChannelOpenAck(MsgChannelOpenAck) returns (MsgChannelOpenAckResponse);
// ChannelOpenConfirm defines a rpc handler method for MsgChannelOpenConfirm.
rpc ChannelOpenConfirm(MsgChannelOpenConfirm) returns (MsgChannelOpenConfirmResponse);
// ChannelCloseInit defines a rpc handler method for MsgChannelCloseInit.
rpc ChannelCloseInit(MsgChannelCloseInit) returns (MsgChannelCloseInitResponse);
// ChannelCloseConfirm defines a rpc handler method for MsgChannelCloseConfirm.
rpc ChannelCloseConfirm(MsgChannelCloseConfirm) returns (MsgChannelCloseConfirmResponse);
// RecvPacket defines a rpc handler method for MsgRecvPacket.
rpc RecvPacket(MsgRecvPacket) returns (MsgRecvPacketResponse);
// Timeout defines a rpc handler method for MsgTimeout.
rpc Timeout(MsgTimeout) returns (MsgTimeoutResponse);
// TimeoutOnClose defines a rpc handler method for MsgTimeoutOnClose.
rpc TimeoutOnClose(MsgTimeoutOnClose) returns (MsgTimeoutOnCloseResponse);
// Acknowledgement defines a rpc handler method for MsgAcknowledgement.
rpc Acknowledgement(MsgAcknowledgement) returns (MsgAcknowledgementResponse);
}
// MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It
// is called by a relayer on Chain A.
message MsgChannelOpenInit {
@ -18,7 +51,10 @@ message MsgChannelOpenInit {
string signer = 4;
}
// MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel
// MsgChannelOpenInitResponse defines the Msg/ChannelOpenInit response type.
message MsgChannelOpenInitResponse {}
// MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel
// on Chain B.
message MsgChannelOpenTry {
option (gogoproto.equal) = false;
@ -35,6 +71,9 @@ message MsgChannelOpenTry {
string signer = 8;
}
// MsgChannelOpenTryResponse defines the Msg/ChannelOpenTry response type.
message MsgChannelOpenTryResponse {}
// MsgChannelOpenAck defines a msg sent by a Relayer to Chain A to acknowledge
// the change of channel state to TRYOPEN on Chain B.
message MsgChannelOpenAck {
@ -51,6 +90,9 @@ message MsgChannelOpenAck {
string signer = 7;
}
// MsgChannelOpenAckResponse defines the Msg/ChannelOpenAck response type.
message MsgChannelOpenAckResponse {}
// MsgChannelOpenConfirm defines a msg sent by a Relayer to Chain B to
// acknowledge the change of channel state to OPEN on Chain A.
message MsgChannelOpenConfirm {
@ -65,6 +107,9 @@ message MsgChannelOpenConfirm {
string signer = 5;
}
// MsgChannelOpenConfirmResponse defines the Msg/ChannelOpenConfirm response type.
message MsgChannelOpenConfirmResponse {}
// MsgChannelCloseInit defines a msg sent by a Relayer to Chain A
// to close a channel with Chain B.
message MsgChannelCloseInit {
@ -76,6 +121,9 @@ message MsgChannelCloseInit {
string signer = 3;
}
// MsgChannelCloseInitResponse defines the Msg/ChannelCloseInit response type.
message MsgChannelCloseInitResponse {}
// MsgChannelCloseConfirm defines a msg sent by a Relayer to Chain B
// to acknowledge the change of channel state to CLOSED on Chain A.
message MsgChannelCloseConfirm {
@ -90,6 +138,9 @@ message MsgChannelCloseConfirm {
string signer = 5;
}
// MsgChannelCloseConfirmResponse defines the Msg/ChannelCloseConfirm response type.
message MsgChannelCloseConfirmResponse {}
// MsgRecvPacket receives incoming IBC packet
message MsgRecvPacket {
option (gogoproto.equal) = false;
@ -102,6 +153,9 @@ message MsgRecvPacket {
string signer = 4;
}
// MsgRecvPacketResponse defines the Msg/RecvPacket response type.
message MsgRecvPacketResponse {}
// MsgTimeout receives timed-out packet
message MsgTimeout {
option (gogoproto.equal) = false;
@ -115,6 +169,9 @@ message MsgTimeout {
string signer = 5;
}
// MsgTimeoutResponse defines the Msg/Timeout response type.
message MsgTimeoutResponse {}
// MsgTimeoutOnClose timed-out packet upon counterparty channel closure.
message MsgTimeoutOnClose {
option (gogoproto.equal) = false;
@ -129,6 +186,9 @@ message MsgTimeoutOnClose {
string signer = 6;
}
// MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type.
message MsgTimeoutOnCloseResponse {}
// MsgAcknowledgement receives incoming IBC acknowledgement
message MsgAcknowledgement {
option (gogoproto.equal) = false;
@ -142,6 +202,9 @@ message MsgAcknowledgement {
string signer = 5;
}
// MsgAcknowledgementResponse defines the Msg/Acknowledgement response type.
message MsgAcknowledgementResponse {}
// Channel defines pipeline for exactly-once packet delivery between specific
// modules on separate blockchains, which has at least one end capable of
// sending packets and one end capable of receiving packets.

View File

@ -6,6 +6,91 @@ option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types";
import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
// Msg defines the ibc/client Msg service.
service Msg {
// CreateClient defines a rpc handler method for MsgCreateClient.
rpc CreateClient(MsgCreateClient) returns (MsgCreateClientResponse);
// UpdateClient defines a rpc handler method for MsgUpdateClient.
rpc UpdateClient(MsgUpdateClient) returns (MsgUpdateClientResponse);
// UpgradeClient defines a rpc handler method for MsgUpgradeClient.
rpc UpgradeClient(MsgUpgradeClient) returns (MsgUpgradeClientResponse);
// SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour.
rpc SubmitMisbehaviour(MsgSubmitMisbehaviour) returns (MsgSubmitMisbehaviourResponse);
}
// MsgCreateClient defines a message to create an IBC client
message MsgCreateClient {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
// client unique identifier
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
// light client state
google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""];
// consensus state associated with the client that corresponds to a given
// height.
google.protobuf.Any consensus_state = 3 [(gogoproto.moretags) = "yaml:\"consensus_state\""];
// signer address
string signer = 4;
}
// MsgCreateClientResponse defines the Msg/CreateClient response type.
message MsgCreateClientResponse { }
// MsgUpdateClient defines an sdk.Msg to update a IBC client state using
// the given header.
message MsgUpdateClient {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
// client unique identifier
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
// header to update the light client
google.protobuf.Any header = 2;
// signer address
string signer = 3;
}
// MsgUpdateClientResponse defines the Msg/UpdateClient response type.
message MsgUpdateClientResponse { }
// MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state
message MsgUpgradeClient {
// client unique identifier
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
// upgraded client state
google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""];
// height at which old chain halts and upgrades (i.e last block executed)
Height upgrade_height = 3 [(gogoproto.moretags) = "yaml:\"upgrade_height\""];
// proof that old chain committed to new client
bytes proof_upgrade = 4 [(gogoproto.moretags) = "yaml:\"proof_upgrade\""];
// signer address
string signer = 5;
}
// MsgUpgradeClientResponse defines the Msg/UpgradeClient response type.
message MsgUpgradeClientResponse { }
// MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for
// light client misbehaviour.
message MsgSubmitMisbehaviour {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
// client unique identifier
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
// misbehaviour used for freezing the light client
google.protobuf.Any misbehaviour = 2;
// signer address
string signer = 3;
}
// MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type.
message MsgSubmitMisbehaviourResponse { }
// IdentifiedClientState defines a client state with an additional client
// identifier field.
message IdentifiedClientState {
@ -48,64 +133,6 @@ message ClientUpdateProposal {
google.protobuf.Any header = 4;
}
// MsgCreateClient defines a message to create an IBC client
message MsgCreateClient {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
// client unique identifier
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
// light client state
google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""];
// consensus state associated with the client that corresponds to a given
// height.
google.protobuf.Any consensus_state = 3 [(gogoproto.moretags) = "yaml:\"consensus_state\""];
// signer address
string signer = 4;
}
// MsgUpdateClient defines an sdk.Msg to update a IBC client state using
// the given header.
message MsgUpdateClient {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
// client unique identifier
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
// header to update the light client
google.protobuf.Any header = 2;
// signer address
string signer = 3;
}
// MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state
message MsgUpgradeClient {
// client unique identifier
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
// upgraded client state
google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""];
// height at which old chain halts and upgrades (i.e last block executed)
Height upgrade_height = 3 [(gogoproto.moretags) = "yaml:\"upgrade_height\""];
// proof that old chain committed to new client
bytes proof_upgrade = 4 [(gogoproto.moretags) = "yaml:\"proof_upgrade\""];
// signer address
string signer = 5;
}
// MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for
// light client misbehaviour.
message MsgSubmitMisbehaviour {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
// client unique identifier
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
// misbehaviour used for freezing the light client
google.protobuf.Any misbehaviour = 2;
// signer address
string signer = 3;
}
// Height is a monotonically increasing data type
// that can be compared against another Height for the purposes of updating and
// freezing clients

View File

@ -8,6 +8,21 @@ import "google/protobuf/any.proto";
import "ibc/core/commitment/v1/commitment.proto";
import "ibc/core/client/v1/client.proto";
// Msg defines the ibc/connection Msg service.
service Msg {
// ConnectionOpenInit defines a rpc handler method for MsgConnectionOpenInit.
rpc ConnectionOpenInit(MsgConnectionOpenInit) returns (MsgConnectionOpenInitResponse);
// ConnectionOpenTry defines a rpc handler method for MsgConnectionOpenTry.
rpc ConnectionOpenTry(MsgConnectionOpenTry) returns (MsgConnectionOpenTryResponse);
// ConnectionOpenAck defines a rpc handler method for MsgConnectionOpenAck.
rpc ConnectionOpenAck(MsgConnectionOpenAck) returns (MsgConnectionOpenAckResponse);
// ConnectionOpenConfirm defines a rpc handler method for MsgConnectionOpenConfirm.
rpc ConnectionOpenConfirm(MsgConnectionOpenConfirm) returns (MsgConnectionOpenConfirmResponse);
}
// MsgConnectionOpenInit defines the msg sent by an account on Chain A to
// initialize a connection with Chain B.
message MsgConnectionOpenInit {
@ -21,6 +36,9 @@ message MsgConnectionOpenInit {
string signer = 5;
}
// MsgConnectionOpenInitResponse defines the Msg/ConnectionOpenInit response type.
message MsgConnectionOpenInitResponse { }
// MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a
// connection on Chain B.
message MsgConnectionOpenTry {
@ -47,6 +65,9 @@ message MsgConnectionOpenTry {
string signer = 12;
}
// MsgConnectionOpenTryResponse defines the Msg/ConnectionOpenTry response type.
message MsgConnectionOpenTryResponse { }
// MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to
// acknowledge the change of connection state to TRYOPEN on Chain B.
message MsgConnectionOpenAck {
@ -71,6 +92,9 @@ message MsgConnectionOpenAck {
string signer = 10;
}
// MsgConnectionOpenAckResponse defines the Msg/ConnectionOpenAck response type.
message MsgConnectionOpenAckResponse { }
// MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to
// acknowledge the change of connection state to OPEN on Chain A.
message MsgConnectionOpenConfirm {
@ -85,6 +109,9 @@ message MsgConnectionOpenConfirm {
string signer = 4;
}
// MsgConnectionOpenConfirmResponse defines the Msg/ConnectionOpenConfirm response type.
message MsgConnectionOpenConfirmResponse { }
// ICS03 - Connection Data Structures as defined in
// https://github.com/cosmos/ics/tree/master/spec/ics-003-connection-semantics#data-structures

View File

@ -3,51 +3,21 @@ package transfer
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/keeper"
"github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types"
)
// NewHandler returns sdk.Handler for IBC token transfer module messages
func NewHandler(k keeper.Keeper) sdk.Handler {
func NewHandler(k types.MsgServer) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
ctx = ctx.WithEventManager(sdk.NewEventManager())
switch msg := msg.(type) {
case *types.MsgTransfer:
return handleMsgTransfer(ctx, k, msg)
res, err := k.Transfer(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
default:
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized ICS-20 transfer message type: %T", msg)
}
}
}
// See createOutgoingPacket in spec:https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#packet-relay
func handleMsgTransfer(ctx sdk.Context, k keeper.Keeper, msg *types.MsgTransfer) (*sdk.Result, error) {
sender, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
return nil, err
}
if err := k.SendTransfer(
ctx, msg.SourcePort, msg.SourceChannel, msg.Token, sender, msg.Receiver, msg.TimeoutHeight, msg.TimeoutTimestamp,
); err != nil {
return nil, err
}
k.Logger(ctx).Info("IBC fungible token transfer", "token", msg.Token.Denom, "amount", msg.Token.Amount.String(), "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 &sdk.Result{
Events: ctx.EventManager().Events().ToABCIEvents(),
}, nil
}

View File

@ -0,0 +1,43 @@
package keeper
import (
"context"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types"
)
var _ types.MsgServer = Keeper{}
// See createOutgoingPacket in spec:https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#packet-relay
// 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
}
if err := k.SendTransfer(
ctx, msg.SourcePort, msg.SourceChannel, msg.Token, sender, msg.Receiver, msg.TimeoutHeight, msg.TimeoutTimestamp,
); err != nil {
return nil, err
}
k.Logger(ctx).Info("IBC fungible token transfer", "token", msg.Token.Denom, "amount", msg.Token.Amount.String(), "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{}, nil
}

View File

@ -120,9 +120,9 @@ func (am AppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Querier {
return nil
}
// RegisterQueryService registers a GRPC query service to respond to the
// module-specific GRPC queries.
// RegisterServices registers module services.
func (am AppModule) RegisterServices(cfg module.Configurator) {
types.RegisterMsgServer(cfg.MsgServer(), am.keeper)
types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
}

View File

@ -4,11 +4,16 @@
package types
import (
context "context"
fmt "fmt"
types "github.com/cosmos/cosmos-sdk/types"
grpc1 "github.com/gogo/protobuf/grpc"
types1 "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
io "io"
math "math"
math_bits "math/bits"
@ -80,6 +85,43 @@ func (m *MsgTransfer) XXX_DiscardUnknown() {
var xxx_messageInfo_MsgTransfer proto.InternalMessageInfo
// MsgTransferResponse defines the Msg/Transfer response type.
type MsgTransferResponse struct {
}
func (m *MsgTransferResponse) Reset() { *m = MsgTransferResponse{} }
func (m *MsgTransferResponse) String() string { return proto.CompactTextString(m) }
func (*MsgTransferResponse) ProtoMessage() {}
func (*MsgTransferResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_5041673e96e97901, []int{1}
}
func (m *MsgTransferResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *MsgTransferResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_MsgTransferResponse.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *MsgTransferResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_MsgTransferResponse.Merge(m, src)
}
func (m *MsgTransferResponse) XXX_Size() int {
return m.Size()
}
func (m *MsgTransferResponse) XXX_DiscardUnknown() {
xxx_messageInfo_MsgTransferResponse.DiscardUnknown(m)
}
var xxx_messageInfo_MsgTransferResponse proto.InternalMessageInfo
// FungibleTokenPacketData defines a struct for the packet payload
// See FungibleTokenPacketData spec:
// https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures
@ -98,7 +140,7 @@ func (m *FungibleTokenPacketData) Reset() { *m = FungibleTokenPacketData
func (m *FungibleTokenPacketData) String() string { return proto.CompactTextString(m) }
func (*FungibleTokenPacketData) ProtoMessage() {}
func (*FungibleTokenPacketData) Descriptor() ([]byte, []int) {
return fileDescriptor_5041673e96e97901, []int{1}
return fileDescriptor_5041673e96e97901, []int{2}
}
func (m *FungibleTokenPacketData) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -169,7 +211,7 @@ func (m *DenomTrace) Reset() { *m = DenomTrace{} }
func (m *DenomTrace) String() string { return proto.CompactTextString(m) }
func (*DenomTrace) ProtoMessage() {}
func (*DenomTrace) Descriptor() ([]byte, []int) {
return fileDescriptor_5041673e96e97901, []int{2}
return fileDescriptor_5041673e96e97901, []int{3}
}
func (m *DenomTrace) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -229,7 +271,7 @@ func (m *Params) Reset() { *m = Params{} }
func (m *Params) String() string { return proto.CompactTextString(m) }
func (*Params) ProtoMessage() {}
func (*Params) Descriptor() ([]byte, []int) {
return fileDescriptor_5041673e96e97901, []int{3}
return fileDescriptor_5041673e96e97901, []int{4}
}
func (m *Params) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -274,6 +316,7 @@ func (m *Params) GetReceiveEnabled() bool {
func init() {
proto.RegisterType((*MsgTransfer)(nil), "ibc.applications.transfer.v1.MsgTransfer")
proto.RegisterType((*MsgTransferResponse)(nil), "ibc.applications.transfer.v1.MsgTransferResponse")
proto.RegisterType((*FungibleTokenPacketData)(nil), "ibc.applications.transfer.v1.FungibleTokenPacketData")
proto.RegisterType((*DenomTrace)(nil), "ibc.applications.transfer.v1.DenomTrace")
proto.RegisterType((*Params)(nil), "ibc.applications.transfer.v1.Params")
@ -284,45 +327,129 @@ func init() {
}
var fileDescriptor_5041673e96e97901 = []byte{
// 601 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x53, 0xcd, 0x6e, 0xd3, 0x4c,
0x14, 0x8d, 0xdb, 0x34, 0x5f, 0x3b, 0xf9, 0x5a, 0x60, 0x28, 0xad, 0x1b, 0xb5, 0x76, 0xe5, 0x55,
0x25, 0x84, 0xad, 0x80, 0x10, 0x52, 0x17, 0x80, 0xd2, 0x82, 0x60, 0x81, 0x54, 0x59, 0x59, 0x20,
0x36, 0x61, 0x3c, 0x19, 0x9c, 0x51, 0xed, 0x19, 0x6b, 0x66, 0x12, 0x51, 0xf1, 0x02, 0xb0, 0xe3,
0x11, 0xba, 0xe6, 0x49, 0xba, 0xec, 0x92, 0x95, 0x85, 0xda, 0x0d, 0xeb, 0x3c, 0x01, 0x9a, 0x9f,
0x86, 0x04, 0xa9, 0x2b, 0xcf, 0xb9, 0xf7, 0x9c, 0x7b, 0xe6, 0xde, 0xeb, 0x01, 0x0f, 0x69, 0x86,
0x13, 0x54, 0x55, 0x05, 0xc5, 0x48, 0x51, 0xce, 0x64, 0xa2, 0x04, 0x62, 0xf2, 0x13, 0x11, 0xc9,
0xa4, 0x3b, 0x3b, 0xc7, 0x95, 0xe0, 0x8a, 0xc3, 0x5d, 0x9a, 0xe1, 0x78, 0x9e, 0x1c, 0xcf, 0x08,
0x93, 0x6e, 0x67, 0x33, 0xe7, 0x39, 0x37, 0xc4, 0x44, 0x9f, 0xac, 0xa6, 0x13, 0x60, 0x2e, 0x4b,
0x2e, 0x93, 0x0c, 0x49, 0x92, 0x4c, 0xba, 0x19, 0x51, 0xa8, 0x9b, 0x60, 0x4e, 0x99, 0xcb, 0x87,
0xfa, 0x02, 0x98, 0x0b, 0x92, 0xe0, 0x82, 0x12, 0xa6, 0xb4, 0xad, 0x3d, 0x59, 0x42, 0xf4, 0x63,
0x19, 0xb4, 0xdf, 0xc9, 0xbc, 0xef, 0x9c, 0xe0, 0x33, 0xd0, 0x96, 0x7c, 0x2c, 0x30, 0x19, 0x54,
0x5c, 0x28, 0xdf, 0xdb, 0xf7, 0x0e, 0xd6, 0x7a, 0x5b, 0xd3, 0x3a, 0x84, 0x67, 0xa8, 0x2c, 0x0e,
0xa3, 0xb9, 0x64, 0x94, 0x02, 0x8b, 0x4e, 0xb8, 0x50, 0xf0, 0x25, 0xd8, 0x70, 0x39, 0x3c, 0x42,
0x8c, 0x91, 0xc2, 0x5f, 0x32, 0xda, 0x9d, 0x69, 0x1d, 0x3e, 0x58, 0xd0, 0xba, 0x7c, 0x94, 0xae,
0xdb, 0xc0, 0x91, 0xc5, 0xf0, 0x29, 0x58, 0x51, 0xfc, 0x94, 0x30, 0x7f, 0x79, 0xdf, 0x3b, 0x68,
0x3f, 0xde, 0x89, 0x6d, 0x6f, 0xb1, 0xee, 0x2d, 0x76, 0xbd, 0xc5, 0x47, 0x9c, 0xb2, 0x5e, 0xf3,
0xa2, 0x0e, 0x1b, 0xa9, 0x65, 0xc3, 0x2d, 0xd0, 0x92, 0x84, 0x0d, 0x89, 0xf0, 0x9b, 0xda, 0x30,
0x75, 0x08, 0x76, 0xc0, 0xaa, 0x20, 0x98, 0xd0, 0x09, 0x11, 0xfe, 0x8a, 0xc9, 0xcc, 0x30, 0xfc,
0x08, 0x36, 0x14, 0x2d, 0x09, 0x1f, 0xab, 0xc1, 0x88, 0xd0, 0x7c, 0xa4, 0xfc, 0x96, 0xf1, 0xec,
0xc4, 0x7a, 0x07, 0x7a, 0x5e, 0xb1, 0x9b, 0xd2, 0xa4, 0x1b, 0xbf, 0x31, 0x8c, 0xde, 0x9e, 0x36,
0xfd, 0xdb, 0xcc, 0xa2, 0x3e, 0x4a, 0xd7, 0x5d, 0xc0, 0xb2, 0xe1, 0x5b, 0x70, 0xef, 0x86, 0xa1,
0xbf, 0x52, 0xa1, 0xb2, 0xf2, 0xff, 0xdb, 0xf7, 0x0e, 0x9a, 0xbd, 0xdd, 0x69, 0x1d, 0xfa, 0x8b,
0x45, 0x66, 0x94, 0x28, 0xbd, 0xeb, 0x62, 0xfd, 0x9b, 0xd0, 0xe1, 0xea, 0xd7, 0xf3, 0xb0, 0xf1,
0xfb, 0x3c, 0x6c, 0x44, 0x5f, 0xc0, 0xf6, 0xeb, 0x31, 0xcb, 0x69, 0x56, 0x90, 0xbe, 0xee, 0xfd,
0x04, 0xe1, 0x53, 0xa2, 0x8e, 0x91, 0x42, 0x70, 0x13, 0xac, 0x0c, 0x09, 0xe3, 0xa5, 0xdd, 0x58,
0x6a, 0x81, 0x9e, 0x0d, 0x2a, 0xf9, 0x98, 0x29, 0xb3, 0x8c, 0x66, 0xea, 0xd0, 0xdc, 0xcc, 0x96,
0x6f, 0x9d, 0x59, 0x73, 0x71, 0x66, 0xd1, 0x0b, 0x00, 0x8e, 0x75, 0xd1, 0xbe, 0x40, 0x98, 0x40,
0x08, 0x9a, 0x15, 0x52, 0x23, 0x67, 0x67, 0xce, 0x70, 0x0f, 0x00, 0xbd, 0xab, 0x81, 0xbd, 0x88,
0x59, 0x7f, 0xba, 0xa6, 0x23, 0x46, 0x17, 0x7d, 0xf3, 0x40, 0xeb, 0x04, 0x09, 0x54, 0x4a, 0x78,
0x08, 0xfe, 0xd7, 0x8e, 0x03, 0xc2, 0x50, 0x56, 0x90, 0xa1, 0xa9, 0xb2, 0xda, 0xdb, 0x9e, 0xd6,
0xe1, 0x7d, 0xf7, 0xab, 0xcc, 0x65, 0xa3, 0xb4, 0xad, 0xe1, 0x2b, 0x8b, 0xe0, 0x11, 0xb8, 0xe3,
0xee, 0x34, 0x93, 0x2f, 0x19, 0x79, 0x67, 0x5a, 0x87, 0x5b, 0x56, 0xfe, 0x0f, 0x21, 0x4a, 0x37,
0x5c, 0xc4, 0x15, 0xe9, 0xbd, 0xbf, 0xb8, 0x0a, 0xbc, 0xcb, 0xab, 0xc0, 0xfb, 0x75, 0x15, 0x78,
0xdf, 0xaf, 0x83, 0xc6, 0xe5, 0x75, 0xd0, 0xf8, 0x79, 0x1d, 0x34, 0x3e, 0x3c, 0xcf, 0xa9, 0x1a,
0x8d, 0xb3, 0x18, 0xf3, 0x32, 0x71, 0x8f, 0xcb, 0x7e, 0x1e, 0xc9, 0xe1, 0x69, 0xf2, 0x39, 0xb9,
0xfd, 0x45, 0xab, 0xb3, 0x8a, 0xc8, 0xac, 0x65, 0xde, 0xd5, 0x93, 0x3f, 0x01, 0x00, 0x00, 0xff,
0xff, 0xed, 0xa5, 0xb5, 0x3a, 0xfb, 0x03, 0x00, 0x00,
// 638 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xcd, 0x6e, 0xd3, 0x40,
0x10, 0x8e, 0x9b, 0x34, 0xa4, 0x1b, 0x5a, 0x60, 0xfb, 0xe7, 0x46, 0xad, 0x5d, 0xf9, 0x54, 0x84,
0x58, 0x2b, 0x45, 0x08, 0xa9, 0x07, 0x40, 0x69, 0x41, 0x70, 0xa8, 0x54, 0x59, 0x39, 0x20, 0x2e,
0x61, 0xbd, 0x59, 0x1c, 0xab, 0xf1, 0xae, 0xe5, 0xdd, 0x44, 0x54, 0xbc, 0x00, 0xdc, 0x78, 0x84,
0x9e, 0x79, 0x92, 0x1e, 0x7b, 0xe4, 0x14, 0xa1, 0xf6, 0xc2, 0x39, 0x4f, 0x80, 0xf6, 0xa7, 0xc1,
0x41, 0x2a, 0xe2, 0xe4, 0xfd, 0x66, 0xbe, 0x6f, 0x66, 0x67, 0x66, 0xc7, 0xe0, 0x51, 0x1a, 0x93,
0x10, 0xe7, 0xf9, 0x30, 0x25, 0x58, 0xa6, 0x9c, 0x89, 0x50, 0x16, 0x98, 0x89, 0x8f, 0xb4, 0x08,
0xc7, 0xed, 0xd9, 0x19, 0xe5, 0x05, 0x97, 0x1c, 0x6e, 0xa7, 0x31, 0x41, 0x65, 0x32, 0x9a, 0x11,
0xc6, 0xed, 0xd6, 0x5a, 0xc2, 0x13, 0xae, 0x89, 0xa1, 0x3a, 0x19, 0x4d, 0xcb, 0x23, 0x5c, 0x64,
0x5c, 0x84, 0x31, 0x16, 0x34, 0x1c, 0xb7, 0x63, 0x2a, 0x71, 0x3b, 0x24, 0x3c, 0x65, 0xd6, 0xef,
0xab, 0x0b, 0x10, 0x5e, 0xd0, 0x90, 0x0c, 0x53, 0xca, 0xa4, 0x4a, 0x6b, 0x4e, 0x86, 0x10, 0x7c,
0xaf, 0x82, 0xe6, 0xb1, 0x48, 0xba, 0x36, 0x13, 0x7c, 0x06, 0x9a, 0x82, 0x8f, 0x0a, 0x42, 0x7b,
0x39, 0x2f, 0xa4, 0xeb, 0xec, 0x3a, 0x7b, 0x4b, 0x9d, 0x8d, 0xe9, 0xc4, 0x87, 0x67, 0x38, 0x1b,
0x1e, 0x04, 0x25, 0x67, 0x10, 0x01, 0x83, 0x4e, 0x78, 0x21, 0xe1, 0x4b, 0xb0, 0x62, 0x7d, 0x64,
0x80, 0x19, 0xa3, 0x43, 0x77, 0x41, 0x6b, 0xb7, 0xa6, 0x13, 0x7f, 0x7d, 0x4e, 0x6b, 0xfd, 0x41,
0xb4, 0x6c, 0x0c, 0x87, 0x06, 0xc3, 0xa7, 0x60, 0x51, 0xf2, 0x53, 0xca, 0xdc, 0xea, 0xae, 0xb3,
0xd7, 0xdc, 0xdf, 0x42, 0xa6, 0x36, 0xa4, 0x6a, 0x43, 0xb6, 0x36, 0x74, 0xc8, 0x53, 0xd6, 0xa9,
0x5d, 0x4c, 0xfc, 0x4a, 0x64, 0xd8, 0x70, 0x03, 0xd4, 0x05, 0x65, 0x7d, 0x5a, 0xb8, 0x35, 0x95,
0x30, 0xb2, 0x08, 0xb6, 0x40, 0xa3, 0xa0, 0x84, 0xa6, 0x63, 0x5a, 0xb8, 0x8b, 0xda, 0x33, 0xc3,
0xf0, 0x03, 0x58, 0x91, 0x69, 0x46, 0xf9, 0x48, 0xf6, 0x06, 0x34, 0x4d, 0x06, 0xd2, 0xad, 0xeb,
0x9c, 0x2d, 0xa4, 0x66, 0xa0, 0xfa, 0x85, 0x6c, 0x97, 0xc6, 0x6d, 0xf4, 0x46, 0x33, 0x3a, 0x3b,
0x2a, 0xe9, 0x9f, 0x62, 0xe6, 0xf5, 0x41, 0xb4, 0x6c, 0x0d, 0x86, 0x0d, 0xdf, 0x82, 0x07, 0x37,
0x0c, 0xf5, 0x15, 0x12, 0x67, 0xb9, 0x7b, 0x67, 0xd7, 0xd9, 0xab, 0x75, 0xb6, 0xa7, 0x13, 0xdf,
0x9d, 0x0f, 0x32, 0xa3, 0x04, 0xd1, 0x7d, 0x6b, 0xeb, 0xde, 0x98, 0x0e, 0x1a, 0x5f, 0xce, 0xfd,
0xca, 0xaf, 0x73, 0xbf, 0x12, 0xac, 0x83, 0xd5, 0xd2, 0xac, 0x22, 0x2a, 0x72, 0xce, 0x04, 0x0d,
0x3e, 0x83, 0xcd, 0xd7, 0x23, 0x96, 0xa4, 0xf1, 0x90, 0x76, 0x55, 0x4b, 0x4e, 0x30, 0x39, 0xa5,
0xf2, 0x08, 0x4b, 0x0c, 0xd7, 0xc0, 0x62, 0x9f, 0x32, 0x9e, 0x99, 0x41, 0x46, 0x06, 0xa8, 0x96,
0xe1, 0x8c, 0x8f, 0x98, 0xd4, 0x33, 0xaa, 0x45, 0x16, 0x95, 0x5a, 0x59, 0xbd, 0xb5, 0x95, 0xb5,
0xf9, 0x56, 0x06, 0x2f, 0x00, 0x38, 0x52, 0x41, 0xbb, 0x05, 0x26, 0x14, 0x42, 0x50, 0xcb, 0xb1,
0x1c, 0xd8, 0x74, 0xfa, 0x0c, 0x77, 0x00, 0x50, 0x23, 0xec, 0x99, 0x8b, 0xe8, 0x57, 0x11, 0x2d,
0x29, 0x8b, 0xd6, 0x05, 0x5f, 0x1d, 0x50, 0x3f, 0xc1, 0x05, 0xce, 0x04, 0x3c, 0x00, 0x77, 0x55,
0xc6, 0x1e, 0x65, 0x38, 0x1e, 0xd2, 0xbe, 0x8e, 0xd2, 0xe8, 0x6c, 0x4e, 0x27, 0xfe, 0xaa, 0x7d,
0x41, 0x25, 0x6f, 0x10, 0x35, 0x15, 0x7c, 0x65, 0x10, 0x3c, 0x04, 0xf7, 0xec, 0x9d, 0x66, 0xf2,
0x05, 0x2d, 0x6f, 0x4d, 0x27, 0xfe, 0x86, 0x91, 0xff, 0x45, 0x08, 0xa2, 0x15, 0x6b, 0xb1, 0x41,
0xf6, 0x39, 0xa8, 0x1e, 0x8b, 0x04, 0x0e, 0x40, 0x63, 0xb6, 0x10, 0x0f, 0xd1, 0xbf, 0xd6, 0x12,
0x95, 0xe6, 0xd1, 0x6a, 0xff, 0x37, 0xf5, 0x66, 0x74, 0x9d, 0x77, 0x17, 0x57, 0x9e, 0x73, 0x79,
0xe5, 0x39, 0x3f, 0xaf, 0x3c, 0xe7, 0xdb, 0xb5, 0x57, 0xb9, 0xbc, 0xf6, 0x2a, 0x3f, 0xae, 0xbd,
0xca, 0xfb, 0xe7, 0x49, 0x2a, 0x07, 0xa3, 0x18, 0x11, 0x9e, 0x85, 0x76, 0xc9, 0xcd, 0xe7, 0xb1,
0xe8, 0x9f, 0x86, 0x9f, 0xc2, 0xdb, 0xff, 0x2c, 0xf2, 0x2c, 0xa7, 0x22, 0xae, 0xeb, 0xfd, 0x7e,
0xf2, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x34, 0x4e, 0x38, 0x40, 0x83, 0x04, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// MsgClient is the client API for Msg service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type MsgClient interface {
// Transfer defines a rpc handler method for MsgTransfer.
Transfer(ctx context.Context, in *MsgTransfer, opts ...grpc.CallOption) (*MsgTransferResponse, error)
}
type msgClient struct {
cc grpc1.ClientConn
}
func NewMsgClient(cc grpc1.ClientConn) MsgClient {
return &msgClient{cc}
}
func (c *msgClient) Transfer(ctx context.Context, in *MsgTransfer, opts ...grpc.CallOption) (*MsgTransferResponse, error) {
out := new(MsgTransferResponse)
err := c.cc.Invoke(ctx, "/ibc.applications.transfer.v1.Msg/Transfer", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// MsgServer is the server API for Msg service.
type MsgServer interface {
// Transfer defines a rpc handler method for MsgTransfer.
Transfer(context.Context, *MsgTransfer) (*MsgTransferResponse, error)
}
// UnimplementedMsgServer can be embedded to have forward compatible implementations.
type UnimplementedMsgServer struct {
}
func (*UnimplementedMsgServer) Transfer(ctx context.Context, req *MsgTransfer) (*MsgTransferResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Transfer not implemented")
}
func RegisterMsgServer(s grpc1.Server, srv MsgServer) {
s.RegisterService(&_Msg_serviceDesc, srv)
}
func _Msg_Transfer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(MsgTransfer)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(MsgServer).Transfer(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/ibc.applications.transfer.v1.Msg/Transfer",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MsgServer).Transfer(ctx, req.(*MsgTransfer))
}
return interceptor(ctx, in, info, handler)
}
var _Msg_serviceDesc = grpc.ServiceDesc{
ServiceName: "ibc.applications.transfer.v1.Msg",
HandlerType: (*MsgServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Transfer",
Handler: _Msg_Transfer_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "ibc/applications/transfer/v1/transfer.proto",
}
func (m *MsgTransfer) Marshal() (dAtA []byte, err error) {
@ -401,6 +528,29 @@ func (m *MsgTransfer) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *MsgTransferResponse) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *MsgTransferResponse) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *MsgTransferResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
return len(dAtA) - i, nil
}
func (m *FungibleTokenPacketData) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@ -573,6 +723,15 @@ func (m *MsgTransfer) Size() (n int) {
return n
}
func (m *MsgTransferResponse) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
return n
}
func (m *FungibleTokenPacketData) Size() (n int) {
if m == nil {
return 0
@ -901,6 +1060,59 @@ func (m *MsgTransfer) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *MsgTransferResponse) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTransfer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: MsgTransferResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: MsgTransferResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
default:
iNdEx = preIndex
skippy, err := skipTransfer(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthTransfer
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthTransfer
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *FungibleTokenPacketData) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0

View File

@ -1,132 +0,0 @@
package client
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/keeper"
"github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
)
// HandleMsgCreateClient defines the sdk.Handler for MsgCreateClient
func HandleMsgCreateClient(ctx sdk.Context, k keeper.Keeper, msg *types.MsgCreateClient) (*sdk.Result, error) {
clientState, err := types.UnpackClientState(msg.ClientState)
if err != nil {
return nil, err
}
consensusState, err := types.UnpackConsensusState(msg.ConsensusState)
if err != nil {
return nil, err
}
if err = k.CreateClient(ctx, msg.ClientId, clientState, consensusState); err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeCreateClient,
sdk.NewAttribute(types.AttributeKeyClientID, msg.ClientId),
sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()),
sdk.NewAttribute(types.AttributeKeyConsensusHeight, clientState.GetLatestHeight().String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
})
return &sdk.Result{
Events: ctx.EventManager().Events().ToABCIEvents(),
}, nil
}
// HandleMsgUpdateClient defines the sdk.Handler for MsgUpdateClient
func HandleMsgUpdateClient(ctx sdk.Context, k keeper.Keeper, msg *types.MsgUpdateClient) (*sdk.Result, error) {
header, err := types.UnpackHeader(msg.Header)
if err != nil {
return nil, err
}
if err = k.UpdateClient(ctx, msg.ClientId, header); err != nil {
return nil, err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
)
return &sdk.Result{
Events: ctx.EventManager().Events().ToABCIEvents(),
}, nil
}
// HandleMsgUpgradeClient defines the sdk.Handler for MsgUpgradeClient
func HandleMsgUpgradeClient(ctx sdk.Context, k keeper.Keeper, msg *types.MsgUpgradeClient) (*sdk.Result, error) {
upgradedClient, err := types.UnpackClientState(msg.ClientState)
if err != nil {
return nil, err
}
if err := upgradedClient.Validate(); err != nil {
return nil, err
}
if err = k.UpgradeClient(ctx, msg.ClientId, upgradedClient, msg.UpgradeHeight, msg.ProofUpgrade); err != nil {
return nil, err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
)
return &sdk.Result{
Events: ctx.EventManager().Events().ToABCIEvents(),
}, nil
}
// HandleMsgSubmitMisbehaviour defines the Evidence module handler for submitting a
// light client misbehaviour.
func HandleMsgSubmitMisbehaviour(ctx sdk.Context, k keeper.Keeper, msg *types.MsgSubmitMisbehaviour) (*sdk.Result, error) {
misbehaviour, err := types.UnpackMisbehaviour(msg.Misbehaviour)
if err != nil {
return nil, err
}
if err := k.CheckMisbehaviourAndUpdateState(ctx, misbehaviour); err != nil {
return nil, sdkerrors.Wrap(err, "failed to process misbehaviour for IBC client")
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeSubmitMisbehaviour,
sdk.NewAttribute(types.AttributeKeyClientID, msg.ClientId),
sdk.NewAttribute(types.AttributeKeyClientType, misbehaviour.ClientType()),
sdk.NewAttribute(types.AttributeKeyConsensusHeight, misbehaviour.GetHeight().String()),
),
)
return &sdk.Result{
Events: ctx.EventManager().Events().ToABCIEvents(),
}, nil
}
// NewClientUpdateProposalHandler defines the client update proposal handler
func NewClientUpdateProposalHandler(k keeper.Keeper) govtypes.Handler {
return func(ctx sdk.Context, content govtypes.Content) error {
switch c := content.(type) {
case *types.ClientUpdateProposal:
return k.ClientUpdateProposal(ctx, c)
default:
return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized ibc proposal content type: %T", c)
}
}
}

View File

@ -1,220 +0,0 @@
package client_test
import (
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
client "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client"
"github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types"
"github.com/cosmos/cosmos-sdk/x/ibc/core/exported"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types"
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
)
func (suite *ClientTestSuite) TestNewClientUpdateProposalHandler() {
var (
content govtypes.Content
err error
)
testCases := []struct {
name string
malleate func()
expPass bool
}{
{
"valid update client proposal", func() {
clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint)
clientState := suite.chainA.GetClientState(clientA)
tmClientState, ok := clientState.(*ibctmtypes.ClientState)
suite.Require().True(ok)
tmClientState.AllowUpdateAfterMisbehaviour = true
tmClientState.FrozenHeight = tmClientState.LatestHeight
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clientA, tmClientState)
// use next header for chainB to update the client on chainA
header, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientA)
suite.Require().NoError(err)
content, err = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, clientA, header)
suite.Require().NoError(err)
}, true,
},
{
"nil proposal", func() {
content = nil
}, false,
},
{
"unsupported proposal type", func() {
content = distributiontypes.NewCommunityPoolSpendProposal(ibctesting.Title, ibctesting.Description, suite.chainA.SenderAccount.GetAddress(), sdk.NewCoins(sdk.NewCoin("communityfunds", sdk.NewInt(10))))
}, false,
},
}
for _, tc := range testCases {
tc := tc
suite.Run(tc.name, func() {
suite.SetupTest() // reset
tc.malleate()
proposalHandler := client.NewClientUpdateProposalHandler(suite.chainA.App.IBCKeeper.ClientKeeper)
err = proposalHandler(suite.chainA.GetContext(), content)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *ClientTestSuite) TestUpgradeClient() {
var (
clientA string
upgradedClient exported.ClientState
upgradeHeight exported.Height
msg *clienttypes.MsgUpgradeClient
)
newClientHeight := clienttypes.NewHeight(1, 1)
cases := []struct {
name string
setup func()
expPass bool
}{
{
name: "successful upgrade",
setup: func() {
upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, ibctesting.DefaultConsensusParams, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
// upgrade Height is at next block
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
// zero custom fields and store in upgrade store
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
// commit upgrade store changes and update clients
suite.coordinator.CommitBlock(suite.chainB)
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint)
suite.Require().NoError(err)
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
suite.Require().True(found)
proofUpgrade, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradeHeight, proofUpgrade, suite.chainA.SenderAccount.GetAddress())
suite.Require().NoError(err)
},
expPass: true,
},
{
name: "invalid upgrade: msg.ClientState does not contain valid clientstate",
setup: func() {
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
suite.Require().True(found)
// upgrade Height is at next block
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
proofUpgrade, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
consState := ibctmtypes.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("app_hash")), []byte("next_vals_hash"))
consAny, err := clienttypes.PackConsensusState(consState)
suite.Require().NoError(err)
height, _ := upgradeHeight.(types.Height)
msg = &types.MsgUpgradeClient{ClientId: clientA, ClientState: consAny, UpgradeHeight: &height, ProofUpgrade: proofUpgrade, Signer: suite.chainA.SenderAccount.GetAddress().String()}
},
expPass: false,
},
{
name: "invalid clientstate",
setup: func() {
upgradedClient = ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, ibctesting.DefaultConsensusParams, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
// upgrade Height is at next block
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
// zero custom fields and store in upgrade store
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
// commit upgrade store changes and update clients
suite.coordinator.CommitBlock(suite.chainB)
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint)
suite.Require().NoError(err)
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
suite.Require().True(found)
proofUpgrade, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradeHeight, proofUpgrade, suite.chainA.SenderAccount.GetAddress())
suite.Require().NoError(err)
},
expPass: false,
},
{
name: "VerifyUpgrade fails",
setup: func() {
upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, ibctesting.DefaultConsensusParams, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
// upgrade Height is at next block
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
// zero custom fields and store in upgrade store
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
// commit upgrade store changes and update clients
suite.coordinator.CommitBlock(suite.chainB)
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint)
suite.Require().NoError(err)
msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradeHeight, nil, suite.chainA.SenderAccount.GetAddress())
suite.Require().NoError(err)
},
expPass: false,
},
}
for _, tc := range cases {
tc := tc
clientA, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint)
tc.setup()
_, err := client.HandleMsgUpgradeClient(
suite.chainA.GetContext(), suite.chainA.App.IBCKeeper.ClientKeeper, msg,
)
if tc.expPass {
suite.Require().NoError(err, "upgrade handler failed on valid case: %s", tc.name)
newClient, ok := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
suite.Require().True(ok)
suite.Require().Equal(upgradedClient, newClient)
} else {
suite.Require().Error(err, "upgrade handler passed on invalid case: %s", tc.name)
}
}
}

View File

@ -0,0 +1,22 @@
package client
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/keeper"
"github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
)
// NewClientUpdateProposalHandler defines the client update proposal handler
func NewClientUpdateProposalHandler(k keeper.Keeper) govtypes.Handler {
return func(ctx sdk.Context, content govtypes.Content) error {
switch c := content.(type) {
case *types.ClientUpdateProposal:
return k.ClientUpdateProposal(ctx, c)
default:
return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized ibc proposal content type: %T", c)
}
}
}

View File

@ -0,0 +1,75 @@
package client_test
import (
sdk "github.com/cosmos/cosmos-sdk/types"
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
client "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types"
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
)
func (suite *ClientTestSuite) TestNewClientUpdateProposalHandler() {
var (
content govtypes.Content
err error
)
testCases := []struct {
name string
malleate func()
expPass bool
}{
{
"valid update client proposal", func() {
clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint)
clientState := suite.chainA.GetClientState(clientA)
tmClientState, ok := clientState.(*ibctmtypes.ClientState)
suite.Require().True(ok)
tmClientState.AllowUpdateAfterMisbehaviour = true
tmClientState.FrozenHeight = tmClientState.LatestHeight
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clientA, tmClientState)
// use next header for chainB to update the client on chainA
header, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientA)
suite.Require().NoError(err)
content, err = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, clientA, header)
suite.Require().NoError(err)
}, true,
},
{
"nil proposal", func() {
content = nil
}, false,
},
{
"unsupported proposal type", func() {
content = distributiontypes.NewCommunityPoolSpendProposal(ibctesting.Title, ibctesting.Description, suite.chainA.SenderAccount.GetAddress(), sdk.NewCoins(sdk.NewCoin("communityfunds", sdk.NewInt(10))))
}, false,
},
}
for _, tc := range testCases {
tc := tc
suite.Run(tc.name, func() {
suite.SetupTest() // reset
tc.malleate()
proposalHandler := client.NewClientUpdateProposalHandler(suite.chainA.App.IBCKeeper.ClientKeeper)
err = proposalHandler(suite.chainA.GetContext(), content)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,135 +0,0 @@
package connection
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
"github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/keeper"
"github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types"
)
// HandleMsgConnectionOpenInit defines the sdk.Handler for MsgConnectionOpenInit
func HandleMsgConnectionOpenInit(ctx sdk.Context, k keeper.Keeper, msg *types.MsgConnectionOpenInit) (*sdk.Result, error) {
if err := k.ConnOpenInit(
ctx, msg.ConnectionId, msg.ClientId, msg.Counterparty, msg.Version,
); err != nil {
return nil, sdkerrors.Wrap(err, "connection handshake open init failed")
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeConnectionOpenInit,
sdk.NewAttribute(types.AttributeKeyConnectionID, msg.ConnectionId),
sdk.NewAttribute(types.AttributeKeyClientID, msg.ClientId),
sdk.NewAttribute(types.AttributeKeyCounterpartyClientID, msg.Counterparty.ClientId),
sdk.NewAttribute(types.AttributeKeyCounterpartyConnectionID, msg.Counterparty.ConnectionId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
})
return &sdk.Result{
Events: ctx.EventManager().Events().ToABCIEvents(),
}, nil
}
// HandleMsgConnectionOpenTry defines the sdk.Handler for MsgConnectionOpenTry
func HandleMsgConnectionOpenTry(ctx sdk.Context, k keeper.Keeper, msg *types.MsgConnectionOpenTry) (*sdk.Result, error) {
targetClient, err := clienttypes.UnpackClientState(msg.ClientState)
if err != nil {
return nil, sdkerrors.Wrapf(err, "client in msg is not exported.ClientState. invalid client: %v.", targetClient)
}
if err := k.ConnOpenTry(
ctx, msg.DesiredConnectionId, msg.CounterpartyChosenConnectionId, msg.Counterparty, msg.ClientId, targetClient,
msg.CounterpartyVersions, msg.ProofInit, msg.ProofClient, msg.ProofConsensus,
msg.ProofHeight, msg.ConsensusHeight,
); err != nil {
return nil, sdkerrors.Wrap(err, "connection handshake open try failed")
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeConnectionOpenTry,
sdk.NewAttribute(types.AttributeKeyConnectionID, msg.DesiredConnectionId),
sdk.NewAttribute(types.AttributeKeyClientID, msg.ClientId),
sdk.NewAttribute(types.AttributeKeyCounterpartyClientID, msg.Counterparty.ClientId),
sdk.NewAttribute(types.AttributeKeyCounterpartyConnectionID, msg.Counterparty.ConnectionId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
})
return &sdk.Result{
Events: ctx.EventManager().Events().ToABCIEvents(),
}, nil
}
// HandleMsgConnectionOpenAck defines the sdk.Handler for MsgConnectionOpenAck
func HandleMsgConnectionOpenAck(ctx sdk.Context, k keeper.Keeper, msg *types.MsgConnectionOpenAck) (*sdk.Result, error) {
targetClient, err := clienttypes.UnpackClientState(msg.ClientState)
if err != nil {
return nil, sdkerrors.Wrapf(err, "client in msg is not exported.ClientState. invalid client: %v", targetClient)
}
if err := k.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")
}
connectionEnd, _ := k.GetConnection(ctx, msg.ConnectionId)
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeConnectionOpenAck,
sdk.NewAttribute(types.AttributeKeyConnectionID, msg.ConnectionId),
sdk.NewAttribute(types.AttributeKeyClientID, connectionEnd.ClientId),
sdk.NewAttribute(types.AttributeKeyCounterpartyClientID, connectionEnd.Counterparty.ClientId),
sdk.NewAttribute(types.AttributeKeyCounterpartyConnectionID, connectionEnd.Counterparty.ConnectionId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
})
return &sdk.Result{
Events: ctx.EventManager().Events().ToABCIEvents(),
}, nil
}
// HandleMsgConnectionOpenConfirm defines the sdk.Handler for MsgConnectionOpenConfirm
func HandleMsgConnectionOpenConfirm(ctx sdk.Context, k keeper.Keeper, msg *types.MsgConnectionOpenConfirm) (*sdk.Result, error) {
if err := k.ConnOpenConfirm(
ctx, msg.ConnectionId, msg.ProofAck, msg.ProofHeight,
); err != nil {
return nil, sdkerrors.Wrap(err, "connection handshake open confirm failed")
}
connectionEnd, _ := k.GetConnection(ctx, msg.ConnectionId)
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeConnectionOpenConfirm,
sdk.NewAttribute(types.AttributeKeyConnectionID, msg.ConnectionId),
sdk.NewAttribute(types.AttributeKeyClientID, connectionEnd.ClientId),
sdk.NewAttribute(types.AttributeKeyCounterpartyClientID, connectionEnd.Counterparty.ClientId),
sdk.NewAttribute(types.AttributeKeyCounterpartyConnectionID, connectionEnd.Counterparty.ConnectionId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
})
return &sdk.Result{
Events: ctx.EventManager().Events().ToABCIEvents(),
}, nil
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,9 @@ package ibc_test
import (
"fmt"
"testing"
"github.com/stretchr/testify/suite"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/codec"
@ -20,6 +22,42 @@ import (
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
)
const (
connectionID = "connectionidone"
clientID = "clientidone"
connectionID2 = "connectionidtwo"
clientID2 = "clientidtwo"
port1 = "firstport"
port2 = "secondport"
channel1 = "firstchannel"
channel2 = "secondchannel"
)
var clientHeight = clienttypes.NewHeight(0, 10)
type IBCTestSuite struct {
suite.Suite
coordinator *ibctesting.Coordinator
chainA *ibctesting.TestChain
chainB *ibctesting.TestChain
}
// SetupTest creates a coordinator with 2 test chains.
func (suite *IBCTestSuite) SetupTest() {
suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2)
suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0))
suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1))
}
func TestIBCTestSuite(t *testing.T) {
suite.Run(t, new(IBCTestSuite))
}
func (suite *IBCTestSuite) TestValidateGenesis() {
header := suite.chainA.CreateTMClientHeader(suite.chainA.ChainID, suite.chainA.CurrentHeader.Height, clienttypes.NewHeight(0, uint64(suite.chainA.CurrentHeader.Height-1)), suite.chainA.CurrentHeader.Time, suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers)

View File

@ -1,18 +1,11 @@
package ibc
import (
"github.com/armon/go-metrics"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
client "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
connection "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection"
connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types"
channel "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel"
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"
porttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/types"
"github.com/cosmos/cosmos-sdk/x/ibc/core/keeper"
)
@ -24,340 +17,75 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
switch msg := msg.(type) {
// IBC client msg interface types
case *clienttypes.MsgCreateClient:
return client.HandleMsgCreateClient(ctx, k.ClientKeeper, msg)
res, err := k.CreateClient(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *clienttypes.MsgUpdateClient:
return client.HandleMsgUpdateClient(ctx, k.ClientKeeper, msg)
res, err := k.UpdateClient(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *clienttypes.MsgSubmitMisbehaviour:
return client.HandleMsgSubmitMisbehaviour(ctx, k.ClientKeeper, msg)
res, err := k.SubmitMisbehaviour(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
// IBC connection msgs
case *connectiontypes.MsgConnectionOpenInit:
return connection.HandleMsgConnectionOpenInit(ctx, k.ConnectionKeeper, msg)
res, err := k.ConnectionOpenInit(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *connectiontypes.MsgConnectionOpenTry:
return connection.HandleMsgConnectionOpenTry(ctx, k.ConnectionKeeper, msg)
res, err := k.ConnectionOpenTry(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *connectiontypes.MsgConnectionOpenAck:
return connection.HandleMsgConnectionOpenAck(ctx, k.ConnectionKeeper, msg)
res, err := k.ConnectionOpenAck(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *connectiontypes.MsgConnectionOpenConfirm:
return connection.HandleMsgConnectionOpenConfirm(ctx, k.ConnectionKeeper, msg)
res, err := k.ConnectionOpenConfirm(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
// IBC channel msgs
case *channeltypes.MsgChannelOpenInit:
// 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")
}
res, cap, err := channel.HandleMsgChannelOpenInit(ctx, k.ChannelKeeper, portCap, msg)
if err != nil {
return nil, err
}
// 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.OnChanOpenInit(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, msg.ChannelId, cap, msg.Channel.Counterparty, msg.Channel.Version); err != nil {
return nil, sdkerrors.Wrap(err, "channel open init callback failed")
}
return res, nil
res, err := k.ChannelOpenInit(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *channeltypes.MsgChannelOpenTry:
// 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")
}
res, cap, err := channel.HandleMsgChannelOpenTry(ctx, k.ChannelKeeper, portCap, msg)
if err != nil {
return nil, err
}
// 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.OnChanOpenTry(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, msg.DesiredChannelId, cap, msg.Channel.Counterparty, msg.Channel.Version, msg.CounterpartyVersion); err != nil {
return nil, sdkerrors.Wrap(err, "channel open try callback failed")
}
return res, nil
res, err := k.ChannelOpenTry(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *channeltypes.MsgChannelOpenAck:
// 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.OnChanOpenAck(ctx, msg.PortId, msg.ChannelId, msg.CounterpartyVersion); err != nil {
return nil, sdkerrors.Wrap(err, "channel open ack callback failed")
}
return channel.HandleMsgChannelOpenAck(ctx, k.ChannelKeeper, cap, msg)
res, err := k.ChannelOpenAck(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *channeltypes.MsgChannelOpenConfirm:
// 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.OnChanOpenConfirm(ctx, msg.PortId, msg.ChannelId); err != nil {
return nil, sdkerrors.Wrap(err, "channel open confirm callback failed")
}
return channel.HandleMsgChannelOpenConfirm(ctx, k.ChannelKeeper, cap, msg)
res, err := k.ChannelOpenConfirm(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *channeltypes.MsgChannelCloseInit:
// 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")
}
return channel.HandleMsgChannelCloseInit(ctx, k.ChannelKeeper, cap, msg)
res, err := k.ChannelCloseInit(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *channeltypes.MsgChannelCloseConfirm:
// 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")
}
return channel.HandleMsgChannelCloseConfirm(ctx, k.ChannelKeeper, cap, msg)
res, err := k.ChannelCloseConfirm(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
// IBC packet msgs get routed to the appropriate module callback
case *channeltypes.MsgRecvPacket:
// 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 err := k.ChannelKeeper.RecvPacket(ctx, msg.Packet, msg.Proof, msg.ProofHeight); err != nil {
return nil, sdkerrors.Wrap(err, "receive packet verification failed")
}
// Perform application logic callback
res, ack, err := cbs.OnRecvPacket(ctx, msg.Packet)
if err != nil {
return nil, sdkerrors.Wrap(err, "receive packet callback failed")
}
if err := k.ChannelKeeper.WriteReceipt(ctx, cap, msg.Packet); err != nil {
return nil, err
}
// 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, msg.Packet, ack); err != nil {
return nil, err
}
}
defer func() {
telemetry.IncrCounterWithLabels(
[]string{"tx", "msg", "ibc", msg.Type()},
1,
[]metrics.Label{
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
},
)
}()
return res, nil
res, err := k.RecvPacket(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *channeltypes.MsgAcknowledgement:
// 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 err := k.ChannelKeeper.AcknowledgePacket(ctx, msg.Packet, msg.Acknowledgement, msg.Proof, msg.ProofHeight); err != nil {
return nil, sdkerrors.Wrap(err, "acknowledge packet verification failed")
}
// Perform application logic callback
res, err := cbs.OnAcknowledgementPacket(ctx, msg.Packet, msg.Acknowledgement)
if err != nil {
return nil, sdkerrors.Wrap(err, "acknowledge packet callback failed")
}
// Delete packet commitment
if err = k.ChannelKeeper.AcknowledgementExecuted(ctx, cap, msg.Packet); err != nil {
return nil, err
}
defer func() {
telemetry.IncrCounterWithLabels(
[]string{"tx", "msg", "ibc", msg.Type()},
1,
[]metrics.Label{
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
},
)
}()
return res, nil
res, err := k.Acknowledgement(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *channeltypes.MsgTimeout:
// 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 err := k.ChannelKeeper.TimeoutPacket(ctx, msg.Packet, msg.Proof, msg.ProofHeight, msg.NextSequenceRecv); err != nil {
return nil, sdkerrors.Wrap(err, "timeout packet verification failed")
}
// Perform application logic callback
res, err := cbs.OnTimeoutPacket(ctx, msg.Packet)
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() {
telemetry.IncrCounterWithLabels(
[]string{"ibc", "timeout", "packet"},
1,
[]metrics.Label{
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
telemetry.NewLabel("timeout-type", "height"),
},
)
}()
return res, nil
res, err := k.Timeout(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *channeltypes.MsgTimeoutOnClose:
// 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 err := k.ChannelKeeper.TimeoutOnClose(ctx, cap, msg.Packet, msg.Proof, msg.ProofClose, msg.ProofHeight, msg.NextSequenceRecv); err != nil {
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.
res, err := cbs.OnTimeoutPacket(ctx, msg.Packet)
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() {
telemetry.IncrCounterWithLabels(
[]string{"ibc", "timeout", "packet"},
1,
[]metrics.Label{
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
telemetry.NewLabel("timeout-type", "channel-closed"),
},
)
}()
return res, nil
res, err := k.TimeoutOnClose(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
default:
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized IBC message type: %T", msg)

View File

@ -0,0 +1,622 @@
package keeper
import (
"context"
"github.com/armon/go-metrics"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types"
channel "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel"
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"
porttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/types"
)
var _ clienttypes.MsgServer = Keeper{}
var _ connectiontypes.MsgServer = Keeper{}
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, msg.ClientId, clientState, consensusState); err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
clienttypes.EventTypeCreateClient,
sdk.NewAttribute(clienttypes.AttributeKeyClientID, msg.ClientId),
sdk.NewAttribute(clienttypes.AttributeKeyClientType, clientState.ClientType()),
sdk.NewAttribute(clienttypes.AttributeKeyConsensusHeight, clientState.GetLatestHeight().String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, clienttypes.AttributeValueCategory),
),
})
return &clienttypes.MsgCreateClientResponse{}, nil
}
// 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
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, clienttypes.AttributeValueCategory),
),
)
return &clienttypes.MsgUpdateClientResponse{}, nil
}
// 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
}
if err := upgradedClient.Validate(); err != nil {
return nil, err
}
if err = k.ClientKeeper.UpgradeClient(ctx, msg.ClientId, upgradedClient, msg.UpgradeHeight, msg.ProofUpgrade); err != nil {
return nil, err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, clienttypes.AttributeValueCategory),
),
)
return &clienttypes.MsgUpgradeClientResponse{}, nil
}
// 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")
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
clienttypes.EventTypeSubmitMisbehaviour,
sdk.NewAttribute(clienttypes.AttributeKeyClientID, msg.ClientId),
sdk.NewAttribute(clienttypes.AttributeKeyClientType, misbehaviour.ClientType()),
sdk.NewAttribute(clienttypes.AttributeKeyConsensusHeight, misbehaviour.GetHeight().String()),
),
)
return &clienttypes.MsgSubmitMisbehaviourResponse{}, nil
}
// 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)
if err := k.ConnectionKeeper.ConnOpenInit(
ctx, msg.ConnectionId, msg.ClientId, msg.Counterparty, msg.Version,
); err != nil {
return nil, sdkerrors.Wrap(err, "connection handshake open init failed")
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
connectiontypes.EventTypeConnectionOpenInit,
sdk.NewAttribute(connectiontypes.AttributeKeyConnectionID, msg.ConnectionId),
sdk.NewAttribute(connectiontypes.AttributeKeyClientID, msg.ClientId),
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyClientID, msg.Counterparty.ClientId),
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyConnectionID, msg.Counterparty.ConnectionId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, connectiontypes.AttributeValueCategory),
),
})
return &connectiontypes.MsgConnectionOpenInitResponse{}, nil
}
// 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)
targetClient, err := clienttypes.UnpackClientState(msg.ClientState)
if err != nil {
return nil, sdkerrors.Wrapf(err, "client in msg is not exported.ClientState. invalid client: %v.", targetClient)
}
if err := k.ConnectionKeeper.ConnOpenTry(
ctx, msg.DesiredConnectionId, msg.CounterpartyChosenConnectionId, msg.Counterparty, msg.ClientId, targetClient,
msg.CounterpartyVersions, msg.ProofInit, msg.ProofClient, msg.ProofConsensus,
msg.ProofHeight, msg.ConsensusHeight,
); err != nil {
return nil, sdkerrors.Wrap(err, "connection handshake open try failed")
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
connectiontypes.EventTypeConnectionOpenTry,
sdk.NewAttribute(connectiontypes.AttributeKeyConnectionID, msg.DesiredConnectionId),
sdk.NewAttribute(connectiontypes.AttributeKeyClientID, msg.ClientId),
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyClientID, msg.Counterparty.ClientId),
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyConnectionID, msg.Counterparty.ConnectionId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, connectiontypes.AttributeValueCategory),
),
})
return &connectiontypes.MsgConnectionOpenTryResponse{}, nil
}
// 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, sdkerrors.Wrapf(err, "client in msg is not exported.ClientState. invalid client: %v", targetClient)
}
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")
}
connectionEnd, _ := k.ConnectionKeeper.GetConnection(ctx, msg.ConnectionId)
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
connectiontypes.EventTypeConnectionOpenAck,
sdk.NewAttribute(connectiontypes.AttributeKeyConnectionID, msg.ConnectionId),
sdk.NewAttribute(connectiontypes.AttributeKeyClientID, connectionEnd.ClientId),
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyClientID, connectionEnd.Counterparty.ClientId),
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyConnectionID, connectionEnd.Counterparty.ConnectionId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, connectiontypes.AttributeValueCategory),
),
})
return &connectiontypes.MsgConnectionOpenAckResponse{}, nil
}
// 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")
}
connectionEnd, _ := k.ConnectionKeeper.GetConnection(ctx, msg.ConnectionId)
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
connectiontypes.EventTypeConnectionOpenConfirm,
sdk.NewAttribute(connectiontypes.AttributeKeyConnectionID, msg.ConnectionId),
sdk.NewAttribute(connectiontypes.AttributeKeyClientID, connectionEnd.ClientId),
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyClientID, connectionEnd.Counterparty.ClientId),
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyConnectionID, connectionEnd.Counterparty.ConnectionId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, connectiontypes.AttributeValueCategory),
),
})
return &connectiontypes.MsgConnectionOpenConfirmResponse{}, nil
}
// ChannelOpenInit defines a rpc handler method for MsgChannelOpenInit.
func (k Keeper) ChannelOpenInit(goCtx context.Context, msg *channeltypes.MsgChannelOpenInit) (*channeltypes.MsgChannelOpenInitResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// 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")
}
_, cap, err := channel.HandleMsgChannelOpenInit(ctx, k.ChannelKeeper, portCap, msg)
if err != nil {
return nil, err
}
// 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.OnChanOpenInit(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, msg.ChannelId, cap, msg.Channel.Counterparty, msg.Channel.Version); err != nil {
return nil, sdkerrors.Wrap(err, "channel open init callback failed")
}
return &channeltypes.MsgChannelOpenInitResponse{}, nil
}
// ChannelOpenTry defines a rpc handler method for MsgChannelOpenTry.
func (k Keeper) ChannelOpenTry(goCtx context.Context, msg *channeltypes.MsgChannelOpenTry) (*channeltypes.MsgChannelOpenTryResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// 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")
}
_, cap, err := channel.HandleMsgChannelOpenTry(ctx, k.ChannelKeeper, portCap, msg)
if err != nil {
return nil, err
}
// 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.OnChanOpenTry(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, msg.DesiredChannelId, cap, msg.Channel.Counterparty, msg.Channel.Version, msg.CounterpartyVersion); err != nil {
return nil, sdkerrors.Wrap(err, "channel open try callback failed")
}
return &channeltypes.MsgChannelOpenTryResponse{}, nil
}
// ChannelOpenAck defines a rpc handler method for MsgChannelOpenAck.
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 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.OnChanOpenAck(ctx, msg.PortId, msg.ChannelId, msg.CounterpartyVersion); err != nil {
return nil, sdkerrors.Wrap(err, "channel open ack callback failed")
}
_, err = channel.HandleMsgChannelOpenAck(ctx, k.ChannelKeeper, cap, msg)
if err != nil {
return nil, err
}
return &channeltypes.MsgChannelOpenAckResponse{}, nil
}
// ChannelOpenConfirm defines a rpc handler method for MsgChannelOpenConfirm.
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 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.OnChanOpenConfirm(ctx, msg.PortId, msg.ChannelId); err != nil {
return nil, sdkerrors.Wrap(err, "channel open confirm callback failed")
}
_, err = channel.HandleMsgChannelOpenConfirm(ctx, k.ChannelKeeper, cap, msg)
if err != nil {
return nil, err
}
return &channeltypes.MsgChannelOpenConfirmResponse{}, nil
}
// 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 = channel.HandleMsgChannelCloseInit(ctx, k.ChannelKeeper, cap, msg)
if err != nil {
return nil, err
}
return &channeltypes.MsgChannelCloseInitResponse{}, nil
}
// 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 = channel.HandleMsgChannelCloseConfirm(ctx, k.ChannelKeeper, cap, msg)
if err != nil {
return nil, err
}
return &channeltypes.MsgChannelCloseConfirmResponse{}, nil
}
// 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)
// 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 err := k.ChannelKeeper.RecvPacket(ctx, msg.Packet, msg.Proof, msg.ProofHeight); err != nil {
return nil, sdkerrors.Wrap(err, "receive packet verification failed")
}
// Perform application logic callback
_, ack, err := cbs.OnRecvPacket(ctx, msg.Packet)
if err != nil {
return nil, sdkerrors.Wrap(err, "receive packet callback failed")
}
if err := k.ChannelKeeper.WriteReceipt(ctx, cap, msg.Packet); err != nil {
return nil, err
}
// 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, msg.Packet, ack); err != nil {
return nil, err
}
}
defer func() {
telemetry.IncrCounterWithLabels(
[]string{"tx", "msg", "ibc", msg.Type()},
1,
[]metrics.Label{
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
},
)
}()
return &channeltypes.MsgRecvPacketResponse{}, nil
}
// 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)
// 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 err := k.ChannelKeeper.TimeoutPacket(ctx, msg.Packet, msg.Proof, msg.ProofHeight, msg.NextSequenceRecv); err != nil {
return nil, sdkerrors.Wrap(err, "timeout packet verification failed")
}
// Perform application logic callback
_, err = cbs.OnTimeoutPacket(ctx, msg.Packet)
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() {
telemetry.IncrCounterWithLabels(
[]string{"ibc", "timeout", "packet"},
1,
[]metrics.Label{
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
telemetry.NewLabel("timeout-type", "height"),
},
)
}()
return &channeltypes.MsgTimeoutResponse{}, nil
}
// 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)
// 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 err := k.ChannelKeeper.TimeoutOnClose(ctx, cap, msg.Packet, msg.Proof, msg.ProofClose, msg.ProofHeight, msg.NextSequenceRecv); err != nil {
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)
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() {
telemetry.IncrCounterWithLabels(
[]string{"ibc", "timeout", "packet"},
1,
[]metrics.Label{
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
telemetry.NewLabel("timeout-type", "channel-closed"),
},
)
}()
return &channeltypes.MsgTimeoutOnCloseResponse{}, nil
}
// 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)
// 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 err := k.ChannelKeeper.AcknowledgePacket(ctx, msg.Packet, msg.Acknowledgement, msg.Proof, msg.ProofHeight); err != nil {
return nil, sdkerrors.Wrap(err, "acknowledge packet verification failed")
}
// Perform application logic callback
_, err = cbs.OnAcknowledgementPacket(ctx, msg.Packet, msg.Acknowledgement)
if err != nil {
return nil, sdkerrors.Wrap(err, "acknowledge packet callback failed")
}
// Delete packet commitment
if err = k.ChannelKeeper.AcknowledgementExecuted(ctx, cap, msg.Packet); err != nil {
return nil, err
}
defer func() {
telemetry.IncrCounterWithLabels(
[]string{"tx", "msg", "ibc", msg.Type()},
1,
[]metrics.Label{
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
},
)
}()
return &channeltypes.MsgAcknowledgementResponse{}, nil
}

View File

@ -1,39 +1,31 @@
package ibc_test
package keeper_test
import (
"testing"
"time"
"github.com/stretchr/testify/suite"
ibc "github.com/cosmos/cosmos-sdk/x/ibc/core"
sdk "github.com/cosmos/cosmos-sdk/types"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types"
host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host"
"github.com/cosmos/cosmos-sdk/x/ibc/core/exported"
"github.com/cosmos/cosmos-sdk/x/ibc/core/keeper"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types"
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
)
const (
connectionID = "connectionidone"
clientID = "clientidone"
connectionID2 = "connectionidtwo"
clientID2 = "clientidtwo"
port1 = "firstport"
port2 = "secondport"
channel1 = "firstchannel"
channel2 = "secondchannel"
height = 10
)
const height = 10
var (
timeoutHeight = clienttypes.NewHeight(0, 10000)
maxSequence = uint64(10)
clientHeight = clienttypes.NewHeight(0, 10)
)
type IBCTestSuite struct {
type KeeperTestSuite struct {
suite.Suite
coordinator *ibctesting.Coordinator
@ -43,7 +35,7 @@ type IBCTestSuite struct {
}
// SetupTest creates a coordinator with 2 test chains.
func (suite *IBCTestSuite) SetupTest() {
func (suite *KeeperTestSuite) SetupTest() {
suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2)
suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0))
@ -51,7 +43,7 @@ func (suite *IBCTestSuite) SetupTest() {
}
func TestIBCTestSuite(t *testing.T) {
suite.Run(t, new(IBCTestSuite))
suite.Run(t, new(KeeperTestSuite))
}
// tests the IBC handler receiving a packet on ordered and unordered channels.
@ -59,7 +51,7 @@ func TestIBCTestSuite(t *testing.T) {
// tests high level properties like ordering and basic sanity checks. More
// rigorous testing of 'RecvPacket' and 'WriteReceipt' can be found in the
// 04-channel/keeper/packet_test.go.
func (suite *IBCTestSuite) TestHandleRecvPacket() {
func (suite *KeeperTestSuite) TestHandleRecvPacket() {
var (
packet channeltypes.Packet
)
@ -143,8 +135,6 @@ func (suite *IBCTestSuite) TestHandleRecvPacket() {
suite.Run(tc.name, func() {
suite.SetupTest() // reset
handler := ibc.NewHandler(*suite.chainB.App.IBCKeeper)
tc.malleate()
// get proof of packet commitment from chainA
@ -154,13 +144,13 @@ func (suite *IBCTestSuite) TestHandleRecvPacket() {
msg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, suite.chainB.SenderAccount.GetAddress())
// ante-handle RecvPacket
_, err := handler(suite.chainB.GetContext(), msg)
_, err := keeper.Keeper.RecvPacket(*suite.chainB.App.IBCKeeper, sdk.WrapSDKContext(suite.chainB.GetContext()), msg)
if tc.expPass {
suite.Require().NoError(err)
// replay should fail since state changes occur
_, err := handler(suite.chainB.GetContext(), msg)
_, err := keeper.Keeper.RecvPacket(*suite.chainB.App.IBCKeeper, sdk.WrapSDKContext(suite.chainB.GetContext()), msg)
suite.Require().Error(err)
// verify ack was written
@ -179,7 +169,7 @@ func (suite *IBCTestSuite) TestHandleRecvPacket() {
// occurs. It test high level properties like ordering and basic sanity
// checks. More rigorous testing of 'AcknowledgePacket' and 'AcknowledgementExecuted'
// can be found in the 04-channel/keeper/packet_test.go.
func (suite *IBCTestSuite) TestHandleAcknowledgePacket() {
func (suite *KeeperTestSuite) TestHandleAcknowledgePacket() {
var (
packet channeltypes.Packet
)
@ -303,8 +293,6 @@ func (suite *IBCTestSuite) TestHandleAcknowledgePacket() {
suite.SetupTest() // reset
ibctesting.TestHash = ibctesting.MockAcknowledgement
handler := ibc.NewHandler(*suite.chainA.App.IBCKeeper)
tc.malleate()
packetKey := host.KeyPacketAcknowledgement(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
@ -312,13 +300,13 @@ func (suite *IBCTestSuite) TestHandleAcknowledgePacket() {
msg := channeltypes.NewMsgAcknowledgement(packet, ibctesting.MockAcknowledgement, proof, proofHeight, suite.chainA.SenderAccount.GetAddress())
_, err := handler(suite.chainA.GetContext(), msg)
_, err := keeper.Keeper.Acknowledgement(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
if tc.expPass {
suite.Require().NoError(err)
// replay should an error
_, err := handler(suite.chainA.GetContext(), msg)
_, err := keeper.Keeper.Acknowledgement(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
suite.Require().Error(err)
// verify packet commitment was deleted on source chain
@ -337,7 +325,7 @@ func (suite *IBCTestSuite) TestHandleAcknowledgePacket() {
// high level properties like ordering and basic sanity checks. More
// rigorous testing of 'TimeoutPacket' and 'TimeoutExecuted' can be found in
// the 04-channel/keeper/timeout_test.go.
func (suite *IBCTestSuite) TestHandleTimeoutPacket() {
func (suite *KeeperTestSuite) TestHandleTimeoutPacket() {
var (
packet channeltypes.Packet
packetKey []byte
@ -427,21 +415,19 @@ func (suite *IBCTestSuite) TestHandleTimeoutPacket() {
suite.Run(tc.name, func() {
suite.SetupTest() // reset
handler := ibc.NewHandler(*suite.chainA.App.IBCKeeper)
tc.malleate()
proof, proofHeight := suite.chainB.QueryProof(packetKey)
msg := channeltypes.NewMsgTimeout(packet, 1, proof, proofHeight, suite.chainA.SenderAccount.GetAddress())
_, err := handler(suite.chainA.GetContext(), msg)
_, err := keeper.Keeper.Timeout(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
if tc.expPass {
suite.Require().NoError(err)
// replay should return an error
_, err := handler(suite.chainA.GetContext(), msg)
_, err := keeper.Keeper.Timeout(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
suite.Require().Error(err)
// verify packet commitment was deleted on source chain
@ -460,7 +446,7 @@ func (suite *IBCTestSuite) TestHandleTimeoutPacket() {
// commitment occurs. It tests high level properties like ordering and basic
// sanity checks. More rigorous testing of 'TimeoutOnClose' and
//'TimeoutExecuted' can be found in the 04-channel/keeper/timeout_test.go.
func (suite *IBCTestSuite) TestHandleTimeoutOnClosePacket() {
func (suite *KeeperTestSuite) TestHandleTimeoutOnClosePacket() {
var (
packet channeltypes.Packet
packetKey []byte
@ -608,8 +594,6 @@ func (suite *IBCTestSuite) TestHandleTimeoutOnClosePacket() {
suite.Run(tc.name, func() {
suite.SetupTest() // reset
handler := ibc.NewHandler(*suite.chainA.App.IBCKeeper)
tc.malleate()
proof, proofHeight := suite.chainB.QueryProof(packetKey)
@ -619,13 +603,13 @@ func (suite *IBCTestSuite) TestHandleTimeoutOnClosePacket() {
msg := channeltypes.NewMsgTimeoutOnClose(packet, 1, proof, proofClosed, proofHeight, suite.chainA.SenderAccount.GetAddress())
_, err := handler(suite.chainA.GetContext(), msg)
_, err := keeper.Keeper.TimeoutOnClose(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
if tc.expPass {
suite.Require().NoError(err)
// replay should return an error
_, err := handler(suite.chainA.GetContext(), msg)
_, err := keeper.Keeper.TimeoutOnClose(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
suite.Require().Error(err)
// verify packet commitment was deleted on source chain
@ -638,3 +622,140 @@ func (suite *IBCTestSuite) TestHandleTimeoutOnClosePacket() {
})
}
}
func (suite *KeeperTestSuite) TestUpgradeClient() {
var (
clientA string
upgradedClient exported.ClientState
upgradeHeight exported.Height
msg *clienttypes.MsgUpgradeClient
)
newClientHeight := clienttypes.NewHeight(1, 1)
cases := []struct {
name string
setup func()
expPass bool
}{
{
name: "successful upgrade",
setup: func() {
upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, ibctesting.DefaultConsensusParams, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
// upgrade Height is at next block
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
// zero custom fields and store in upgrade store
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
// commit upgrade store changes and update clients
suite.coordinator.CommitBlock(suite.chainB)
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint)
suite.Require().NoError(err)
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
suite.Require().True(found)
proofUpgrade, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradeHeight, proofUpgrade, suite.chainA.SenderAccount.GetAddress())
suite.Require().NoError(err)
},
expPass: true,
},
{
name: "invalid upgrade: msg.ClientState does not contain valid clientstate",
setup: func() {
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
suite.Require().True(found)
// upgrade Height is at next block
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
proofUpgrade, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
consState := ibctmtypes.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("app_hash")), []byte("next_vals_hash"))
consAny, err := clienttypes.PackConsensusState(consState)
suite.Require().NoError(err)
height, _ := upgradeHeight.(clienttypes.Height)
msg = &clienttypes.MsgUpgradeClient{ClientId: clientA, ClientState: consAny, UpgradeHeight: &height, ProofUpgrade: proofUpgrade, Signer: suite.chainA.SenderAccount.GetAddress().String()}
},
expPass: false,
},
{
name: "invalid clientstate",
setup: func() {
upgradedClient = ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, ibctesting.DefaultConsensusParams, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
// upgrade Height is at next block
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
// zero custom fields and store in upgrade store
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
// commit upgrade store changes and update clients
suite.coordinator.CommitBlock(suite.chainB)
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint)
suite.Require().NoError(err)
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
suite.Require().True(found)
proofUpgrade, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradeHeight, proofUpgrade, suite.chainA.SenderAccount.GetAddress())
suite.Require().NoError(err)
},
expPass: false,
},
{
name: "VerifyUpgrade fails",
setup: func() {
upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, ibctesting.DefaultConsensusParams, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
// upgrade Height is at next block
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
// zero custom fields and store in upgrade store
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
// commit upgrade store changes and update clients
suite.coordinator.CommitBlock(suite.chainB)
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint)
suite.Require().NoError(err)
msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradeHeight, nil, suite.chainA.SenderAccount.GetAddress())
suite.Require().NoError(err)
},
expPass: false,
},
}
for _, tc := range cases {
tc := tc
clientA, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint)
tc.setup()
_, err := keeper.Keeper.UpgradeClient(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
if tc.expPass {
suite.Require().NoError(err, "upgrade handler failed on valid case: %s", tc.name)
newClient, ok := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
suite.Require().True(ok)
suite.Require().Equal(upgradedClient, newClient)
} else {
suite.Require().Error(err, "upgrade handler passed on invalid case: %s", tc.name)
}
}
}

View File

@ -130,8 +130,11 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd
return nil
}
// RegisterQueryService registers the gRPC query service for the ibc module.
// RegisterServices registers module services.
func (am AppModule) RegisterServices(cfg module.Configurator) {
clienttypes.RegisterMsgServer(cfg.MsgServer(), am.keeper)
connectiontypes.RegisterMsgServer(cfg.MsgServer(), am.keeper)
channeltypes.RegisterMsgServer(cfg.MsgServer(), am.keeper)
types.RegisterQueryService(cfg.QueryServer(), am.keeper)
}