From 16435a0f4d320e3554c3aecd10a62d2dedeca69a Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Thu, 20 Aug 2020 13:19:57 +0200 Subject: [PATCH] ibc: TimeoutOnClose support (#7066) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ibc: TimeoutOnClose support * revert added callback * update proto * update spec and add msg test * update handler and add test * apply self-review changes * apply @fedekunze review suggestion Co-authored-by: Colin Axner Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> --- docs/ibc/custom.md | 5 +- proto/ibc/channel/channel.proto | 112 +++-- x/ibc-transfer/handler_test.go | 4 +- x/ibc-transfer/module.go | 10 +- x/ibc/04-channel/keeper/timeout.go | 26 +- x/ibc/04-channel/types/channel.pb.go | 602 ++++++++++++++++++++++----- x/ibc/04-channel/types/codec.go | 1 + x/ibc/04-channel/types/msgs.go | 54 +++ x/ibc/04-channel/types/msgs_test.go | 38 +- x/ibc/handler.go | 33 ++ x/ibc/handler_test.go | 248 ++++++++++- x/ibc/spec/04_messages.md | 99 +++++ x/ibc/spec/06_events.md | 6 +- x/ibc/testing/coordinator.go | 12 +- 14 files changed, 1056 insertions(+), 194 deletions(-) diff --git a/docs/ibc/custom.md b/docs/ibc/custom.md index 0a66a13be2..24decd4fc0 100644 --- a/docs/ibc/custom.md +++ b/docs/ibc/custom.md @@ -371,8 +371,9 @@ OnAcknowledgementPacket( #### Timeout Packets -If the timout for a packet is reached before the packet is successfully received, the receiving -chain can no longer process it. Thus, the sending chain must process the timout using +If the timeout for a packet is reached before the packet is successfully received or the +counterparty channel end is closed before the packet is successfully received, then the receiving +chain can no longer process it. Thus, the sending chain must process the timeout using `OnTimeoutPacket` to handle this situation. Again the IBC module will verify that the timeout is indeed valid, so our module only needs to implement the state machine logic for what to do once a timeout is reached and the packet can no longer be received. diff --git a/proto/ibc/channel/channel.proto b/proto/ibc/channel/channel.proto index e7cef886ea..3d603942c2 100644 --- a/proto/ibc/channel/channel.proto +++ b/proto/ibc/channel/channel.proto @@ -5,46 +5,52 @@ option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"; import "gogoproto/gogo.proto"; -// MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It is -// called by a relayer on Chain A. +// MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It +// is called by a relayer on Chain A. message MsgChannelOpenInit { string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""]; Channel channel = 3 [(gogoproto.nullable) = false]; - bytes signer = 4 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; + bytes signer = 4 + [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; } // MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel // on Chain B. message MsgChannelOpenTry { - string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; - string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""]; - Channel channel = 3 [(gogoproto.nullable) = false]; - string counterparty_version = 4 [(gogoproto.moretags) = "yaml:\"counterparty_version\""]; - bytes proof_init = 5 [(gogoproto.moretags) = "yaml:\"proof_init\""]; - uint64 proof_height = 6 [(gogoproto.moretags) = "yaml:\"proof_height\""]; - bytes signer = 7 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; + string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; + string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""]; + Channel channel = 3 [(gogoproto.nullable) = false]; + string counterparty_version = 4 + [(gogoproto.moretags) = "yaml:\"counterparty_version\""]; + bytes proof_init = 5 [(gogoproto.moretags) = "yaml:\"proof_init\""]; + uint64 proof_height = 6 [(gogoproto.moretags) = "yaml:\"proof_height\""]; + bytes signer = 7 + [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; } // 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 { - string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; - string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""]; - string counterparty_version = 3 [(gogoproto.moretags) = "yaml:\"counterparty_version\""]; - bytes proof_try = 4 [(gogoproto.moretags) = "yaml:\"proof_try\""]; - uint64 proof_height = 5 [(gogoproto.moretags) = "yaml:\"proof_height\""]; - bytes signer = 6 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; + string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; + string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""]; + string counterparty_version = 3 + [(gogoproto.moretags) = "yaml:\"counterparty_version\""]; + bytes proof_try = 4 [(gogoproto.moretags) = "yaml:\"proof_try\""]; + uint64 proof_height = 5 [(gogoproto.moretags) = "yaml:\"proof_height\""]; + bytes signer = 6 + [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; } -// MsgChannelOpenConfirm defines a msg sent by a Relayer to Chain B to acknowledge -// the change of channel state to OPEN on Chain A. +// 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 { string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""]; bytes proof_ack = 3 [(gogoproto.moretags) = "yaml:\"proof_ack\""]; uint64 proof_height = 4 [(gogoproto.moretags) = "yaml:\"proof_height\""]; - bytes signer = 5 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; + bytes signer = 5 + [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; } // MsgChannelOpenConfirm defines a msg sent by a Relayer to Chain A @@ -52,7 +58,8 @@ message MsgChannelOpenConfirm { message MsgChannelCloseInit { string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""]; - bytes signer = 3 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; + bytes signer = 3 + [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; } // MsgChannelCloseConfirm defines a msg sent by a Relayer to Chain B @@ -62,7 +69,8 @@ message MsgChannelCloseConfirm { string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""]; bytes proof_init = 3 [(gogoproto.moretags) = "yaml:\"proof_init\""]; uint64 proof_height = 4 [(gogoproto.moretags) = "yaml:\"proof_height\""]; - bytes signer = 5 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; + bytes signer = 5 + [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; } // MsgRecvPacket receives incoming IBC packet @@ -70,16 +78,31 @@ message MsgRecvPacket { Packet packet = 1 [(gogoproto.nullable) = false]; bytes proof = 2; uint64 proof_height = 3 [(gogoproto.moretags) = "yaml:\"proof_height\""]; - bytes signer = 4 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; + bytes signer = 4 + [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; } // MsgTimeout receives timed-out packet message MsgTimeout { - Packet packet = 1 [(gogoproto.nullable) = false]; - bytes proof = 2; - uint64 proof_height = 3 [(gogoproto.moretags) = "yaml:\"proof_height\""]; - uint64 next_sequence_recv = 4 [(gogoproto.moretags) = "yaml:\"next_sequence_recv\""]; - bytes signer = 5 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; + Packet packet = 1 [(gogoproto.nullable) = false]; + bytes proof = 2; + uint64 proof_height = 3 [(gogoproto.moretags) = "yaml:\"proof_height\""]; + uint64 next_sequence_recv = 4 + [(gogoproto.moretags) = "yaml:\"next_sequence_recv\""]; + bytes signer = 5 + [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; +} + +// MsgTimeoutOnClose timed-out packet upon counterparty channel closure. +message MsgTimeoutOnClose { + Packet packet = 1 [(gogoproto.nullable) = false]; + bytes proof = 2; + bytes proof_close = 3 [(gogoproto.moretags) = "yaml:\"proof_close\""]; + uint64 proof_height = 4 [(gogoproto.moretags) = "yaml:\"proof_height\""]; + uint64 next_sequence_recv = 5 + [(gogoproto.moretags) = "yaml:\"next_sequence_recv\""]; + bytes signer = 6 + [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; } // MsgAcknowledgement receives incoming IBC acknowledgement @@ -88,12 +111,13 @@ message MsgAcknowledgement { bytes acknowledgement = 2; bytes proof = 3; uint64 proof_height = 4 [(gogoproto.moretags) = "yaml:\"proof_height\""]; - bytes signer = 5 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; + bytes signer = 5 + [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; } // 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. +// modules on separate blockchains, which has at least one end capable of +// sending packets and one end capable of receiving packets. message Channel { option (gogoproto.goproto_getters) = false; @@ -105,13 +129,14 @@ message Channel { Counterparty counterparty = 3 [(gogoproto.nullable) = false]; // list of connection identifiers, in order, along which packets sent on this // channel will travel - repeated string connection_hops = 4 [(gogoproto.moretags) = "yaml:\"connection_hops\""]; + repeated string connection_hops = 4 + [(gogoproto.moretags) = "yaml:\"connection_hops\""]; // opaque channel version, which is agreed upon during the handshake string version = 5; } -// IdentifiedChannel defines a channel with additional port and channel identifier -// fields. +// IdentifiedChannel defines a channel with additional port and channel +// identifier fields. message IdentifiedChannel { option (gogoproto.goproto_getters) = false; @@ -123,7 +148,8 @@ message IdentifiedChannel { Counterparty counterparty = 3 [(gogoproto.nullable) = false]; // list of connection identifiers, in order, along which packets sent on this // channel will travel - repeated string connection_hops = 4 [(gogoproto.moretags) = "yaml:\"connection_hops\""]; + repeated string connection_hops = 4 + [(gogoproto.moretags) = "yaml:\"connection_hops\""]; // opaque channel version, which is agreed upon during the handshake string version = 5; // port identifier @@ -138,7 +164,8 @@ enum State { option (gogoproto.goproto_enum_prefix) = false; // Default State - STATE_UNINITIALIZED_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "UNINITIALIZED"]; + STATE_UNINITIALIZED_UNSPECIFIED = 0 + [(gogoproto.enumvalue_customname) = "UNINITIALIZED"]; // A channel has just started the opening handshake. STATE_INIT = 1 [(gogoproto.enumvalue_customname) = "INIT"]; // A channel has acknowledged the handshake step on the counterparty chain. @@ -146,7 +173,8 @@ enum State { // A channel has completed the handshake. Open channels are // ready to send and receive packets. STATE_OPEN = 3 [(gogoproto.enumvalue_customname) = "OPEN"]; - // A channel has been closed and can no longer be used to send or receive packets. + // A channel has been closed and can no longer be used to send or receive + // packets. STATE_CLOSED = 4 [(gogoproto.enumvalue_customname) = "CLOSED"]; } @@ -156,7 +184,8 @@ enum Order { // zero-value for channel ordering ORDER_NONE_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "NONE"]; - // packets can be delivered in any order, which may differ from the order in which they were sent. + // packets can be delivered in any order, which may differ from the order in + // which they were sent. ORDER_UNORDERED = 1 [(gogoproto.enumvalue_customname) = "UNORDERED"]; // packets are delivered exactly in the order which they were sent ORDER_ORDERED = 2 [(gogoproto.enumvalue_customname) = "ORDERED"]; @@ -185,15 +214,18 @@ message Packet { // identifies the channel end on the sending chain. string source_channel = 3 [(gogoproto.moretags) = "yaml:\"source_channel\""]; // identifies the port on the receiving chain. - string destination_port = 4 [(gogoproto.moretags) = "yaml:\"destination_port\""]; + string destination_port = 4 + [(gogoproto.moretags) = "yaml:\"destination_port\""]; // identifies the channel end on the receiving chain. - string destination_channel = 5 [(gogoproto.moretags) = "yaml:\"destination_channel\""]; + string destination_channel = 5 + [(gogoproto.moretags) = "yaml:\"destination_channel\""]; // actual opaque bytes transferred directly to the application module bytes data = 6; // block height after which the packet times out uint64 timeout_height = 7 [(gogoproto.moretags) = "yaml:\"timeout_height\""]; // block timestamp (in nanoseconds) after which the packet times out - uint64 timeout_timestamp = 8 [(gogoproto.moretags) = "yaml:\"timeout_timestamp\""]; + uint64 timeout_timestamp = 8 + [(gogoproto.moretags) = "yaml:\"timeout_timestamp\""]; } // PacketAckCommitment defines the genesis type necessary to retrieve and store diff --git a/x/ibc-transfer/handler_test.go b/x/ibc-transfer/handler_test.go index 344080cb17..49d83a69ab 100644 --- a/x/ibc-transfer/handler_test.go +++ b/x/ibc-transfer/handler_test.go @@ -38,7 +38,7 @@ func (suite *HandlerTestSuite) TestHandleMsgTransfer() { // send from chainA to chainB msg := types.NewMsgTransfer(channelA.PortID, channelA.ID, coinToSendToB, suite.chainA.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), 110, 0) - err := suite.coordinator.SendMsgs(suite.chainA, suite.chainB, clientB, msg) + err := suite.coordinator.SendMsg(suite.chainA, suite.chainB, clientB, msg) suite.Require().NoError(err) // message committed // relay send @@ -58,7 +58,7 @@ func (suite *HandlerTestSuite) TestHandleMsgTransfer() { // send from chainB back to chainA msg = types.NewMsgTransfer(channelB.PortID, channelB.ID, coinToSendBackToA, suite.chainB.SenderAccount.GetAddress(), suite.chainA.SenderAccount.GetAddress().String(), 110, 0) - err = suite.coordinator.SendMsgs(suite.chainB, suite.chainA, clientA, msg) + err = suite.coordinator.SendMsg(suite.chainB, suite.chainA, clientA, msg) suite.Require().NoError(err) // message committed // relay send diff --git a/x/ibc-transfer/module.go b/x/ibc-transfer/module.go index 4d5656e46b..b67ba787f4 100644 --- a/x/ibc-transfer/module.go +++ b/x/ibc-transfer/module.go @@ -175,7 +175,7 @@ func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.Weig //____________________________________________________________________________ -// Implement IBCModule callbacks +// OnChanOpenInit implements the IBCModule interface func (am AppModule) OnChanOpenInit( ctx sdk.Context, order channeltypes.Order, @@ -207,6 +207,7 @@ func (am AppModule) OnChanOpenInit( return nil } +// OnChanOpenTry implements the IBCModule interface func (am AppModule) OnChanOpenTry( ctx sdk.Context, order channeltypes.Order, @@ -243,6 +244,7 @@ func (am AppModule) OnChanOpenTry( return nil } +// OnChanOpenAck implements the IBCModule interface func (am AppModule) OnChanOpenAck( ctx sdk.Context, portID, @@ -255,6 +257,7 @@ func (am AppModule) OnChanOpenAck( return nil } +// OnChanOpenConfirm implements the IBCModule interface func (am AppModule) OnChanOpenConfirm( ctx sdk.Context, portID, @@ -263,6 +266,7 @@ func (am AppModule) OnChanOpenConfirm( return nil } +// OnChanCloseInit implements the IBCModule interface func (am AppModule) OnChanCloseInit( ctx sdk.Context, portID, @@ -272,6 +276,7 @@ func (am AppModule) OnChanCloseInit( return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "user cannot close channel") } +// OnChanCloseConfirm implements the IBCModule interface func (am AppModule) OnChanCloseConfirm( ctx sdk.Context, portID, @@ -280,6 +285,7 @@ func (am AppModule) OnChanCloseConfirm( return nil } +// OnRecvPacket implements the IBCModule interface func (am AppModule) OnRecvPacket( ctx sdk.Context, packet channeltypes.Packet, @@ -316,6 +322,7 @@ func (am AppModule) OnRecvPacket( }, acknowledgement.GetBytes(), nil } +// OnAcknowledgementPacket implements the IBCModule interface func (am AppModule) OnAcknowledgementPacket( ctx sdk.Context, packet channeltypes.Packet, @@ -359,6 +366,7 @@ func (am AppModule) OnAcknowledgementPacket( }, nil } +// OnTimeoutPacket implements the IBCModule interface func (am AppModule) OnTimeoutPacket( ctx sdk.Context, packet channeltypes.Packet, diff --git a/x/ibc/04-channel/keeper/timeout.go b/x/ibc/04-channel/keeper/timeout.go index e4687bd031..687e3d1b86 100644 --- a/x/ibc/04-channel/keeper/timeout.go +++ b/x/ibc/04-channel/keeper/timeout.go @@ -145,7 +145,7 @@ func (k Keeper) TimeoutExecuted( k.SetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), channel) } - k.Logger(ctx).Info(fmt.Sprintf("packet timed-out: %v", packet)) + k.Logger(ctx).Info("packet timed-out", "packet", packet) // emit an event marking that we have processed the timeout ctx.EventManager().EmitEvents(sdk.Events{ @@ -266,28 +266,6 @@ func (k Keeper) TimeoutOnClose( return err } - k.deletePacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - - k.Logger(ctx).Info(fmt.Sprintf("packet timed-out on close: %v", packet)) - - // emit an event marking that we have processed the timeout - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeTimeoutPacket, - sdk.NewAttribute(types.AttributeKeyTimeoutHeight, fmt.Sprintf("%d", packet.GetTimeoutHeight())), - sdk.NewAttribute(types.AttributeKeyTimeoutTimestamp, fmt.Sprintf("%d", packet.GetTimeoutTimestamp())), - sdk.NewAttribute(types.AttributeKeySequence, fmt.Sprintf("%d", packet.GetSequence())), - sdk.NewAttribute(types.AttributeKeySrcPort, packet.GetSourcePort()), - sdk.NewAttribute(types.AttributeKeySrcChannel, packet.GetSourceChannel()), - sdk.NewAttribute(types.AttributeKeyDstPort, packet.GetDestPort()), - sdk.NewAttribute(types.AttributeKeyDstChannel, packet.GetDestChannel()), - sdk.NewAttribute(types.AttributeKeyChannelOrdering, channel.Ordering.String()), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), - ), - }) - + // NOTE: the remaining code is located in the TimeoutExecuted function return nil } diff --git a/x/ibc/04-channel/types/channel.pb.go b/x/ibc/04-channel/types/channel.pb.go index 7654beebb2..eb32530a5f 100644 --- a/x/ibc/04-channel/types/channel.pb.go +++ b/x/ibc/04-channel/types/channel.pb.go @@ -38,7 +38,8 @@ const ( // A channel has completed the handshake. Open channels are // ready to send and receive packets. OPEN State = 3 - // A channel has been closed and can no longer be used to send or receive packets. + // A channel has been closed and can no longer be used to send or receive + // packets. CLOSED State = 4 ) @@ -72,7 +73,8 @@ type Order int32 const ( // zero-value for channel ordering NONE Order = 0 - // packets can be delivered in any order, which may differ from the order in which they were sent. + // packets can be delivered in any order, which may differ from the order in + // which they were sent. UNORDERED Order = 1 // packets are delivered exactly in the order which they were sent ORDERED Order = 2 @@ -98,8 +100,8 @@ func (Order) EnumDescriptor() ([]byte, []int) { return fileDescriptor_9277922ccfb7f043, []int{1} } -// MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It is -// called by a relayer on Chain A. +// MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It +// is called by a relayer on Chain A. type MsgChannelOpenInit struct { PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty" yaml:"port_id"` ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty" yaml:"channel_id"` @@ -348,8 +350,8 @@ func (m *MsgChannelOpenAck) GetSigner() github_com_cosmos_cosmos_sdk_types.AccAd return nil } -// MsgChannelOpenConfirm defines a msg sent by a Relayer to Chain B to acknowledge -// the change of channel state to OPEN on Chain A. +// MsgChannelOpenConfirm defines a msg sent by a Relayer to Chain B to +// acknowledge the change of channel state to OPEN on Chain A. type MsgChannelOpenConfirm struct { PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty" yaml:"port_id"` ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty" yaml:"channel_id"` @@ -712,6 +714,91 @@ func (m *MsgTimeout) GetSigner() github_com_cosmos_cosmos_sdk_types.AccAddress { return nil } +// MsgTimeoutOnClose timed-out packet upon counterparty channel closure. +type MsgTimeoutOnClose struct { + Packet Packet `protobuf:"bytes,1,opt,name=packet,proto3" json:"packet"` + Proof []byte `protobuf:"bytes,2,opt,name=proof,proto3" json:"proof,omitempty"` + ProofClose []byte `protobuf:"bytes,3,opt,name=proof_close,json=proofClose,proto3" json:"proof_close,omitempty" yaml:"proof_close"` + ProofHeight uint64 `protobuf:"varint,4,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height,omitempty" yaml:"proof_height"` + NextSequenceRecv uint64 `protobuf:"varint,5,opt,name=next_sequence_recv,json=nextSequenceRecv,proto3" json:"next_sequence_recv,omitempty" yaml:"next_sequence_recv"` + Signer github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,6,opt,name=signer,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"signer,omitempty"` +} + +func (m *MsgTimeoutOnClose) Reset() { *m = MsgTimeoutOnClose{} } +func (m *MsgTimeoutOnClose) String() string { return proto.CompactTextString(m) } +func (*MsgTimeoutOnClose) ProtoMessage() {} +func (*MsgTimeoutOnClose) Descriptor() ([]byte, []int) { + return fileDescriptor_9277922ccfb7f043, []int{8} +} +func (m *MsgTimeoutOnClose) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgTimeoutOnClose) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgTimeoutOnClose.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 *MsgTimeoutOnClose) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgTimeoutOnClose.Merge(m, src) +} +func (m *MsgTimeoutOnClose) XXX_Size() int { + return m.Size() +} +func (m *MsgTimeoutOnClose) XXX_DiscardUnknown() { + xxx_messageInfo_MsgTimeoutOnClose.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgTimeoutOnClose proto.InternalMessageInfo + +func (m *MsgTimeoutOnClose) GetPacket() Packet { + if m != nil { + return m.Packet + } + return Packet{} +} + +func (m *MsgTimeoutOnClose) GetProof() []byte { + if m != nil { + return m.Proof + } + return nil +} + +func (m *MsgTimeoutOnClose) GetProofClose() []byte { + if m != nil { + return m.ProofClose + } + return nil +} + +func (m *MsgTimeoutOnClose) GetProofHeight() uint64 { + if m != nil { + return m.ProofHeight + } + return 0 +} + +func (m *MsgTimeoutOnClose) GetNextSequenceRecv() uint64 { + if m != nil { + return m.NextSequenceRecv + } + return 0 +} + +func (m *MsgTimeoutOnClose) GetSigner() github_com_cosmos_cosmos_sdk_types.AccAddress { + if m != nil { + return m.Signer + } + return nil +} + // MsgAcknowledgement receives incoming IBC acknowledgement type MsgAcknowledgement struct { Packet Packet `protobuf:"bytes,1,opt,name=packet,proto3" json:"packet"` @@ -725,7 +812,7 @@ func (m *MsgAcknowledgement) Reset() { *m = MsgAcknowledgement{} } func (m *MsgAcknowledgement) String() string { return proto.CompactTextString(m) } func (*MsgAcknowledgement) ProtoMessage() {} func (*MsgAcknowledgement) Descriptor() ([]byte, []int) { - return fileDescriptor_9277922ccfb7f043, []int{8} + return fileDescriptor_9277922ccfb7f043, []int{9} } func (m *MsgAcknowledgement) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -790,8 +877,8 @@ func (m *MsgAcknowledgement) GetSigner() github_com_cosmos_cosmos_sdk_types.AccA } // 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. +// modules on separate blockchains, which has at least one end capable of +// sending packets and one end capable of receiving packets. type Channel struct { // current state of the channel end State State `protobuf:"varint,1,opt,name=state,proto3,enum=ibc.channel.State" json:"state,omitempty"` @@ -810,7 +897,7 @@ func (m *Channel) Reset() { *m = Channel{} } func (m *Channel) String() string { return proto.CompactTextString(m) } func (*Channel) ProtoMessage() {} func (*Channel) Descriptor() ([]byte, []int) { - return fileDescriptor_9277922ccfb7f043, []int{9} + return fileDescriptor_9277922ccfb7f043, []int{10} } func (m *Channel) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -839,8 +926,8 @@ func (m *Channel) XXX_DiscardUnknown() { var xxx_messageInfo_Channel proto.InternalMessageInfo -// IdentifiedChannel defines a channel with additional port and channel identifier -// fields. +// IdentifiedChannel defines a channel with additional port and channel +// identifier fields. type IdentifiedChannel struct { // current state of the channel end State State `protobuf:"varint,1,opt,name=state,proto3,enum=ibc.channel.State" json:"state,omitempty"` @@ -863,7 +950,7 @@ func (m *IdentifiedChannel) Reset() { *m = IdentifiedChannel{} } func (m *IdentifiedChannel) String() string { return proto.CompactTextString(m) } func (*IdentifiedChannel) ProtoMessage() {} func (*IdentifiedChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_9277922ccfb7f043, []int{10} + return fileDescriptor_9277922ccfb7f043, []int{11} } func (m *IdentifiedChannel) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -904,7 +991,7 @@ func (m *Counterparty) Reset() { *m = Counterparty{} } func (m *Counterparty) String() string { return proto.CompactTextString(m) } func (*Counterparty) ProtoMessage() {} func (*Counterparty) Descriptor() ([]byte, []int) { - return fileDescriptor_9277922ccfb7f043, []int{11} + return fileDescriptor_9277922ccfb7f043, []int{12} } func (m *Counterparty) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -959,7 +1046,7 @@ func (m *Packet) Reset() { *m = Packet{} } func (m *Packet) String() string { return proto.CompactTextString(m) } func (*Packet) ProtoMessage() {} func (*Packet) Descriptor() ([]byte, []int) { - return fileDescriptor_9277922ccfb7f043, []int{12} + return fileDescriptor_9277922ccfb7f043, []int{13} } func (m *Packet) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1005,7 +1092,7 @@ func (m *PacketAckCommitment) Reset() { *m = PacketAckCommitment{} } func (m *PacketAckCommitment) String() string { return proto.CompactTextString(m) } func (*PacketAckCommitment) ProtoMessage() {} func (*PacketAckCommitment) Descriptor() ([]byte, []int) { - return fileDescriptor_9277922ccfb7f043, []int{13} + return fileDescriptor_9277922ccfb7f043, []int{14} } func (m *PacketAckCommitment) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1045,6 +1132,7 @@ func init() { proto.RegisterType((*MsgChannelCloseConfirm)(nil), "ibc.channel.MsgChannelCloseConfirm") proto.RegisterType((*MsgRecvPacket)(nil), "ibc.channel.MsgRecvPacket") proto.RegisterType((*MsgTimeout)(nil), "ibc.channel.MsgTimeout") + proto.RegisterType((*MsgTimeoutOnClose)(nil), "ibc.channel.MsgTimeoutOnClose") proto.RegisterType((*MsgAcknowledgement)(nil), "ibc.channel.MsgAcknowledgement") proto.RegisterType((*Channel)(nil), "ibc.channel.Channel") proto.RegisterType((*IdentifiedChannel)(nil), "ibc.channel.IdentifiedChannel") @@ -1056,86 +1144,89 @@ func init() { func init() { proto.RegisterFile("ibc/channel/channel.proto", fileDescriptor_9277922ccfb7f043) } var fileDescriptor_9277922ccfb7f043 = []byte{ - // 1259 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x58, 0x3f, 0x6f, 0xdb, 0x46, - 0x14, 0x17, 0x25, 0x4a, 0xb2, 0x9e, 0xff, 0xc9, 0x67, 0xc7, 0x91, 0x95, 0x44, 0x14, 0x88, 0x0e, - 0x42, 0x8a, 0xc8, 0xcd, 0x1f, 0xb4, 0x40, 0xa6, 0x4a, 0xb2, 0x82, 0x08, 0x8d, 0x25, 0xe3, 0xac, - 0x14, 0x68, 0x16, 0x81, 0xa6, 0x2e, 0x12, 0x21, 0x8b, 0xa7, 0x92, 0x74, 0x12, 0xef, 0x1d, 0x02, - 0x03, 0x2d, 0xfa, 0x05, 0x0c, 0x14, 0xe8, 0xd4, 0xa5, 0x53, 0x81, 0x76, 0xe9, 0xd4, 0x25, 0x5b, - 0x33, 0x76, 0x62, 0x8a, 0xf8, 0x1b, 0x70, 0x2a, 0x3a, 0x15, 0xbc, 0x3b, 0x4a, 0xa4, 0x9c, 0x66, - 0xb0, 0x0a, 0x25, 0x43, 0x27, 0xde, 0x7b, 0xef, 0x77, 0x77, 0xef, 0xfd, 0xde, 0xf3, 0x7b, 0x67, - 0xc1, 0x96, 0x71, 0xa0, 0x6f, 0xeb, 0x7d, 0xcd, 0x34, 0xc9, 0x61, 0xf0, 0x2d, 0x8f, 0x2c, 0xea, - 0x50, 0xb4, 0x68, 0x1c, 0xe8, 0x65, 0xa1, 0xca, 0x6f, 0xf4, 0x68, 0x8f, 0x32, 0xfd, 0xb6, 0xbf, - 0xe2, 0x10, 0xf5, 0x2f, 0x09, 0xd0, 0xae, 0xdd, 0xab, 0x71, 0x50, 0x6b, 0x44, 0xcc, 0x86, 0x69, - 0x38, 0xe8, 0x43, 0x48, 0x8f, 0xa8, 0xe5, 0x74, 0x8c, 0x6e, 0x4e, 0x2a, 0x4a, 0xa5, 0x4c, 0x15, - 0x79, 0xae, 0xb2, 0x72, 0xac, 0x0d, 0x0f, 0xef, 0xaa, 0xc2, 0xa0, 0xe2, 0x94, 0xbf, 0x6a, 0x74, - 0xd1, 0x1d, 0x00, 0x71, 0x89, 0x8f, 0x8f, 0x33, 0xfc, 0x25, 0xcf, 0x55, 0xd6, 0x38, 0x7e, 0x62, - 0x53, 0x71, 0x46, 0x08, 0x6c, 0x57, 0x5a, 0x08, 0xb9, 0x44, 0x51, 0x2a, 0x2d, 0xde, 0xda, 0x28, - 0x87, 0xdc, 0x2d, 0x0b, 0x8f, 0xaa, 0xf2, 0x0b, 0x57, 0x89, 0xe1, 0x00, 0x8a, 0x1a, 0x90, 0xb2, - 0x8d, 0x9e, 0x49, 0xac, 0x9c, 0x5c, 0x94, 0x4a, 0x4b, 0xd5, 0x9b, 0x7f, 0xbb, 0xca, 0x8d, 0x9e, - 0xe1, 0xf4, 0x8f, 0x0e, 0xca, 0x3a, 0x1d, 0x6e, 0xeb, 0xd4, 0x1e, 0x52, 0x5b, 0x7c, 0x6e, 0xd8, - 0xdd, 0xc1, 0xb6, 0x73, 0x3c, 0x22, 0x76, 0xb9, 0xa2, 0xeb, 0x95, 0x6e, 0xd7, 0x22, 0xb6, 0x8d, - 0xc5, 0x01, 0xea, 0xaf, 0x09, 0x58, 0x8b, 0x86, 0xde, 0xb6, 0x8e, 0xdf, 0xdf, 0xc8, 0x31, 0x6c, - 0xe8, 0xf4, 0xc8, 0x74, 0x88, 0x35, 0xd2, 0x2c, 0xe7, 0xb8, 0xf3, 0x84, 0x58, 0xb6, 0x41, 0x4d, - 0xc6, 0x43, 0xa6, 0xaa, 0x78, 0xae, 0x72, 0x45, 0xdc, 0xfa, 0x06, 0x94, 0x8a, 0xd7, 0xc3, 0xea, - 0xcf, 0xb9, 0xd6, 0xf7, 0x7f, 0x64, 0x51, 0xfa, 0xb8, 0x63, 0x98, 0x86, 0x93, 0x4b, 0x32, 0x46, - 0x43, 0xfe, 0x4f, 0x6c, 0x2a, 0xce, 0x30, 0x81, 0x15, 0xc7, 0x5d, 0x58, 0xe2, 0x96, 0x3e, 0x31, - 0x7a, 0x7d, 0x27, 0x97, 0x2a, 0x4a, 0x25, 0xb9, 0x7a, 0xd9, 0x73, 0x95, 0xf5, 0xf0, 0x3e, 0x6e, - 0x55, 0xf1, 0x22, 0x13, 0xef, 0x33, 0x29, 0x94, 0xbf, 0xf4, 0xac, 0xf9, 0xfb, 0xea, 0x5c, 0xfe, - 0x2a, 0xfa, 0x60, 0x1e, 0xf9, 0xfb, 0xb7, 0x4c, 0x24, 0x66, 0xc8, 0xc4, 0x4d, 0xe0, 0x04, 0x77, - 0x1c, 0xeb, 0x58, 0x94, 0xf6, 0x86, 0xe7, 0x2a, 0xd9, 0x30, 0xa1, 0x8e, 0x75, 0xac, 0xe2, 0x05, - 0xb6, 0xf6, 0x2b, 0x75, 0x3a, 0x0d, 0xc9, 0x0b, 0xa5, 0x21, 0x35, 0x6b, 0x1a, 0x7e, 0x8a, 0xc3, - 0xa5, 0x68, 0x1a, 0x6a, 0xd4, 0x7c, 0x6c, 0x58, 0xc3, 0x79, 0xa4, 0x62, 0x4c, 0x9b, 0xa6, 0x0f, - 0x18, 0xff, 0x6f, 0xa0, 0x4d, 0xd3, 0x07, 0x01, 0x6d, 0x7e, 0x81, 0x4c, 0xd3, 0x26, 0x5f, 0x88, - 0xb6, 0xe4, 0xac, 0xb4, 0xfd, 0x26, 0xc1, 0xfa, 0x84, 0xb6, 0xda, 0x21, 0xb5, 0xc9, 0xbc, 0x3a, - 0xef, 0x24, 0x8a, 0xc4, 0xac, 0x51, 0xfc, 0x12, 0x87, 0xcd, 0xa9, 0x28, 0xe6, 0x98, 0xfd, 0x68, - 0xfb, 0x4a, 0x5c, 0xb0, 0x7d, 0xbd, 0xa3, 0x02, 0x78, 0x25, 0xc1, 0xf2, 0xae, 0xdd, 0xc3, 0x44, - 0x7f, 0xb2, 0xa7, 0xe9, 0x03, 0xe2, 0xa0, 0x9b, 0x90, 0x1a, 0xb1, 0x15, 0x23, 0x6c, 0xf1, 0xd6, - 0x7a, 0x64, 0x2c, 0x70, 0x90, 0x98, 0x0a, 0x02, 0x88, 0x36, 0x20, 0xc9, 0xdc, 0x63, 0x94, 0x2d, - 0x61, 0x2e, 0x9c, 0x8b, 0x30, 0x71, 0xa1, 0x08, 0x67, 0x1e, 0xb0, 0x3f, 0xc4, 0x01, 0x76, 0xed, - 0x5e, 0xdb, 0x18, 0x12, 0x7a, 0xf4, 0x9e, 0x84, 0xf7, 0x19, 0x20, 0x93, 0x3c, 0x73, 0x3a, 0x36, - 0xf9, 0xf2, 0x88, 0x98, 0x3a, 0xe9, 0x58, 0x44, 0x7f, 0x22, 0x4a, 0xe0, 0x9a, 0xe7, 0x2a, 0x5b, - 0xfc, 0x84, 0xf3, 0x18, 0x15, 0x67, 0x7d, 0xe5, 0xbe, 0xd0, 0xf9, 0x69, 0xfb, 0x2f, 0xab, 0xe1, - 0x9b, 0x38, 0x7b, 0x87, 0x55, 0xf4, 0x81, 0x49, 0x9f, 0x1e, 0x92, 0x6e, 0x8f, 0x0c, 0x89, 0x79, - 0x21, 0xce, 0x4a, 0xb0, 0xaa, 0x45, 0x4f, 0x11, 0xec, 0x4d, 0xab, 0x27, 0xec, 0x26, 0xde, 0xc6, - 0xee, 0x3b, 0xfa, 0xf3, 0xf8, 0x3a, 0x0e, 0x69, 0xd1, 0x56, 0x50, 0x09, 0x92, 0xb6, 0xa3, 0x39, - 0x84, 0x91, 0xb0, 0x72, 0x0b, 0x45, 0x48, 0xd8, 0xf7, 0x2d, 0x98, 0x03, 0x50, 0x19, 0x16, 0xa8, - 0xd5, 0x25, 0x96, 0x61, 0xf6, 0x58, 0xd4, 0xd3, 0xe0, 0x96, 0x6f, 0xc4, 0x63, 0x0c, 0xaa, 0xc1, - 0x52, 0x78, 0x1a, 0x8b, 0xf7, 0xd8, 0x56, 0xf4, 0x3d, 0x16, 0x02, 0x08, 0xae, 0x23, 0x9b, 0x50, - 0x0d, 0x56, 0x75, 0x6a, 0x9a, 0x44, 0x77, 0x0c, 0x6a, 0x76, 0xfa, 0x74, 0x64, 0xe7, 0xe4, 0x62, - 0xa2, 0x94, 0xa9, 0xe6, 0x3d, 0x57, 0xd9, 0x0c, 0x9e, 0x02, 0x11, 0x80, 0x8a, 0x57, 0x26, 0x9a, - 0xfb, 0x74, 0x64, 0xa3, 0x1c, 0xa4, 0x83, 0x77, 0x84, 0xcf, 0x5d, 0x06, 0x07, 0xe2, 0x5d, 0xf9, - 0xf9, 0x77, 0x4a, 0x4c, 0xfd, 0x3d, 0x0e, 0x6b, 0x8d, 0x2e, 0x31, 0x1d, 0xe3, 0xb1, 0x41, 0xba, - 0xff, 0x33, 0xe3, 0x3f, 0x9a, 0x2e, 0x4f, 0x46, 0x4c, 0x8a, 0x59, 0x82, 0x71, 0x72, 0x2d, 0x32, - 0x4e, 0xd2, 0xcc, 0x36, 0x99, 0x1b, 0x82, 0xd1, 0xa7, 0xb0, 0x14, 0x0e, 0x60, 0x0e, 0x03, 0x4b, - 0x5c, 0xfc, 0x2a, 0x01, 0x29, 0xd1, 0xf2, 0xf3, 0xb0, 0x10, 0x74, 0x19, 0x76, 0xa9, 0x8c, 0xc7, - 0x32, 0xfa, 0x04, 0x16, 0x6d, 0x7a, 0x64, 0xe9, 0xa4, 0xe3, 0xdf, 0x29, 0xee, 0xd8, 0xf4, 0x5c, - 0x05, 0xf1, 0x3b, 0x42, 0x46, 0x15, 0x03, 0x97, 0xf6, 0xa8, 0xe5, 0xa0, 0x4f, 0x61, 0x45, 0xd8, - 0xc2, 0xff, 0x66, 0x64, 0xaa, 0x5b, 0x9e, 0xab, 0x5c, 0x8a, 0xec, 0x15, 0x76, 0x15, 0x2f, 0x73, - 0x45, 0x50, 0x56, 0xf7, 0x20, 0xdb, 0x25, 0xb6, 0x63, 0x98, 0x1a, 0xcb, 0x0b, 0xbb, 0x9f, 0xff, - 0x9f, 0x71, 0xc5, 0x73, 0x95, 0xcb, 0xfc, 0x8c, 0x69, 0x84, 0x8a, 0x57, 0x43, 0x2a, 0xe6, 0x49, - 0x0b, 0xd6, 0xc3, 0xa8, 0xc0, 0x1d, 0x96, 0xc6, 0x6a, 0xc1, 0x73, 0x95, 0xfc, 0xf9, 0xa3, 0xc6, - 0x3e, 0xa1, 0x90, 0x36, 0x70, 0x0c, 0x81, 0xdc, 0xd5, 0x1c, 0x8d, 0xbf, 0x5a, 0x31, 0x5b, 0xfb, - 0xe1, 0x3a, 0x7c, 0xc4, 0x04, 0x2d, 0x2b, 0xcd, 0x5a, 0x56, 0x28, 0xdc, 0xa8, 0x5d, 0xc5, 0xcb, - 0x42, 0x31, 0x6e, 0x5b, 0x6b, 0x01, 0xc2, 0xff, 0xda, 0x8e, 0x36, 0x1c, 0xe5, 0x16, 0xd8, 0x21, - 0x57, 0x3d, 0x57, 0xc9, 0x45, 0x0f, 0x19, 0x43, 0x54, 0x9c, 0x15, 0xba, 0x76, 0xa0, 0x12, 0x19, - 0xfe, 0x51, 0x82, 0x75, 0x9e, 0xe1, 0x8a, 0x3e, 0xa8, 0xd1, 0xe1, 0xd0, 0x70, 0x58, 0xc7, 0x9d, - 0xc3, 0x9b, 0x28, 0x5c, 0x51, 0x89, 0xa9, 0x8a, 0x42, 0x20, 0xf7, 0x35, 0xbb, 0xcf, 0x27, 0x3b, - 0x66, 0x6b, 0xee, 0xf0, 0xf5, 0x9f, 0x25, 0x48, 0xb2, 0x76, 0x81, 0x3e, 0x06, 0x65, 0xbf, 0x5d, - 0x69, 0xd7, 0x3b, 0x0f, 0x9b, 0x8d, 0x66, 0xa3, 0xdd, 0xa8, 0x3c, 0x68, 0x3c, 0xaa, 0xef, 0x74, - 0x1e, 0x36, 0xf7, 0xf7, 0xea, 0xb5, 0xc6, 0xbd, 0x46, 0x7d, 0x27, 0x1b, 0xcb, 0xaf, 0x9d, 0x9c, - 0x16, 0x97, 0x23, 0x00, 0x94, 0x03, 0xe0, 0xfb, 0x7c, 0x65, 0x56, 0xca, 0x2f, 0x9c, 0x9c, 0x16, - 0x65, 0x7f, 0x8d, 0x0a, 0xb0, 0xcc, 0x2d, 0x6d, 0xfc, 0x45, 0x6b, 0xaf, 0xde, 0xcc, 0xc6, 0xf3, - 0x8b, 0x27, 0xa7, 0xc5, 0xb4, 0x10, 0x27, 0x3b, 0x99, 0x31, 0xc1, 0x77, 0x32, 0xcb, 0x55, 0x58, - 0xe2, 0x96, 0xda, 0x83, 0xd6, 0x7e, 0x7d, 0x27, 0x2b, 0xe7, 0xe1, 0xe4, 0xb4, 0x98, 0xe2, 0x52, - 0x5e, 0x7e, 0xfe, 0x7d, 0x21, 0x76, 0xfd, 0x29, 0x24, 0x59, 0xeb, 0x42, 0x1f, 0xc0, 0x66, 0x0b, - 0xef, 0xd4, 0x71, 0xa7, 0xd9, 0x6a, 0xd6, 0xa7, 0xfc, 0x65, 0x47, 0xfa, 0x7a, 0xa4, 0xc2, 0x2a, - 0x47, 0x3d, 0x6c, 0xb2, 0x6f, 0x7d, 0x27, 0x2b, 0xe5, 0x97, 0x4f, 0x4e, 0x8b, 0x99, 0xb1, 0xc2, - 0x77, 0x98, 0x63, 0x02, 0x84, 0x70, 0x58, 0x88, 0xfc, 0xe2, 0xea, 0xee, 0x8b, 0xd7, 0x05, 0xe9, - 0xe5, 0xeb, 0x82, 0xf4, 0xe7, 0xeb, 0x82, 0xf4, 0xed, 0x59, 0x21, 0xf6, 0xf2, 0xac, 0x10, 0xfb, - 0xe3, 0xac, 0x10, 0x7b, 0x74, 0xfb, 0xad, 0x13, 0xef, 0xd9, 0xb6, 0x71, 0xa0, 0x6f, 0x7f, 0x74, - 0xe7, 0x46, 0xf0, 0x9b, 0x0d, 0x1b, 0x81, 0x07, 0x29, 0xf6, 0x7b, 0xcc, 0xed, 0x7f, 0x02, 0x00, - 0x00, 0xff, 0xff, 0xa9, 0x83, 0xf0, 0x66, 0xcf, 0x11, 0x00, 0x00, + // 1303 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x58, 0xbd, 0x6f, 0xdb, 0x46, + 0x14, 0x17, 0xf5, 0x69, 0x3d, 0x7f, 0xc9, 0x67, 0xc7, 0x91, 0x95, 0x44, 0x14, 0x88, 0x0e, 0x42, + 0x8a, 0xc8, 0xcd, 0x07, 0x5a, 0x20, 0x53, 0x25, 0x59, 0x41, 0x84, 0xc6, 0x92, 0x71, 0x56, 0x0a, + 0x34, 0x0b, 0x41, 0x53, 0x17, 0x89, 0x90, 0xc5, 0x53, 0x49, 0x3a, 0x89, 0xf7, 0x0e, 0x81, 0x81, + 0x16, 0xfd, 0x07, 0x0c, 0x14, 0xe8, 0xd4, 0xa5, 0x53, 0x81, 0x76, 0xe9, 0xd4, 0x25, 0x5b, 0x33, + 0x76, 0x62, 0x8a, 0x64, 0xea, 0xca, 0xa9, 0xe8, 0x54, 0xf0, 0xee, 0x28, 0x91, 0x72, 0x9a, 0xc1, + 0x0a, 0x94, 0x0c, 0x9d, 0xc8, 0xf7, 0xde, 0xef, 0xee, 0xde, 0xfb, 0xbd, 0xc7, 0xf7, 0x4e, 0x82, + 0x2d, 0xe3, 0x40, 0xdf, 0xd6, 0xfb, 0x9a, 0x69, 0x92, 0xc3, 0xe0, 0x59, 0x19, 0x59, 0xd4, 0xa1, + 0x68, 0xd1, 0x38, 0xd0, 0x2b, 0x42, 0x55, 0xd8, 0xe8, 0xd1, 0x1e, 0x65, 0xfa, 0x6d, 0xff, 0x8d, + 0x43, 0x94, 0xbf, 0x25, 0x40, 0xbb, 0x76, 0xaf, 0xce, 0x41, 0xed, 0x11, 0x31, 0x9b, 0xa6, 0xe1, + 0xa0, 0x0f, 0x21, 0x33, 0xa2, 0x96, 0xa3, 0x1a, 0xdd, 0xbc, 0x54, 0x92, 0xca, 0xd9, 0x1a, 0xf2, + 0x5c, 0x79, 0xe5, 0x58, 0x1b, 0x1e, 0xde, 0x56, 0x84, 0x41, 0xc1, 0x69, 0xff, 0xad, 0xd9, 0x45, + 0xb7, 0x00, 0xc4, 0x21, 0x3e, 0x3e, 0xce, 0xf0, 0x17, 0x3c, 0x57, 0x5e, 0xe3, 0xf8, 0x89, 0x4d, + 0xc1, 0x59, 0x21, 0xb0, 0x55, 0x19, 0x21, 0xe4, 0x13, 0x25, 0xa9, 0xbc, 0x78, 0x63, 0xa3, 0x12, + 0x72, 0xb7, 0x22, 0x3c, 0xaa, 0x25, 0x9f, 0xb9, 0x72, 0x0c, 0x07, 0x50, 0xd4, 0x84, 0xb4, 0x6d, + 0xf4, 0x4c, 0x62, 0xe5, 0x93, 0x25, 0xa9, 0xbc, 0x54, 0xbb, 0xfe, 0x8f, 0x2b, 0x5f, 0xeb, 0x19, + 0x4e, 0xff, 0xe8, 0xa0, 0xa2, 0xd3, 0xe1, 0xb6, 0x4e, 0xed, 0x21, 0xb5, 0xc5, 0xe3, 0x9a, 0xdd, + 0x1d, 0x6c, 0x3b, 0xc7, 0x23, 0x62, 0x57, 0xaa, 0xba, 0x5e, 0xed, 0x76, 0x2d, 0x62, 0xdb, 0x58, + 0x6c, 0xa0, 0xfc, 0x9a, 0x80, 0xb5, 0x68, 0xe8, 0x1d, 0xeb, 0xf8, 0xfd, 0x8d, 0x1c, 0xc3, 0x86, + 0x4e, 0x8f, 0x4c, 0x87, 0x58, 0x23, 0xcd, 0x72, 0x8e, 0xd5, 0x47, 0xc4, 0xb2, 0x0d, 0x6a, 0x32, + 0x1e, 0xb2, 0x35, 0xd9, 0x73, 0xe5, 0x4b, 0xe2, 0xd4, 0xd7, 0xa0, 0x14, 0xbc, 0x1e, 0x56, 0x7f, + 0xce, 0xb5, 0xbe, 0xff, 0x23, 0x8b, 0xd2, 0x87, 0xaa, 0x61, 0x1a, 0x4e, 0x3e, 0xc5, 0x18, 0x0d, + 0xf9, 0x3f, 0xb1, 0x29, 0x38, 0xcb, 0x04, 0x56, 0x1c, 0xb7, 0x61, 0x89, 0x5b, 0xfa, 0xc4, 0xe8, + 0xf5, 0x9d, 0x7c, 0xba, 0x24, 0x95, 0x93, 0xb5, 0x8b, 0x9e, 0x2b, 0xaf, 0x87, 0xd7, 0x71, 0xab, + 0x82, 0x17, 0x99, 0x78, 0x97, 0x49, 0xa1, 0xfc, 0x65, 0x66, 0xcd, 0xdf, 0x57, 0x67, 0xf2, 0x57, + 0xd5, 0x07, 0xf3, 0xc8, 0xdf, 0x7f, 0x65, 0x22, 0x31, 0x43, 0x26, 0xae, 0x03, 0x27, 0x58, 0x75, + 0xac, 0x63, 0x51, 0xda, 0x1b, 0x9e, 0x2b, 0xe7, 0xc2, 0x84, 0x3a, 0xd6, 0xb1, 0x82, 0x17, 0xd8, + 0xbb, 0x5f, 0xa9, 0xd3, 0x69, 0x48, 0x9d, 0x2b, 0x0d, 0xe9, 0x59, 0xd3, 0xf0, 0x53, 0x1c, 0x2e, + 0x44, 0xd3, 0x50, 0xa7, 0xe6, 0x43, 0xc3, 0x1a, 0xce, 0x23, 0x15, 0x63, 0xda, 0x34, 0x7d, 0xc0, + 0xf8, 0x7f, 0x0d, 0x6d, 0x9a, 0x3e, 0x08, 0x68, 0xf3, 0x0b, 0x64, 0x9a, 0xb6, 0xe4, 0xb9, 0x68, + 0x4b, 0xcd, 0x4a, 0xdb, 0x6f, 0x12, 0xac, 0x4f, 0x68, 0xab, 0x1f, 0x52, 0x9b, 0xcc, 0xab, 0xf3, + 0x4e, 0xa2, 0x48, 0xcc, 0x1a, 0xc5, 0x2f, 0x71, 0xd8, 0x9c, 0x8a, 0x62, 0x8e, 0xd9, 0x8f, 0xb6, + 0xaf, 0xc4, 0x39, 0xdb, 0xd7, 0x3b, 0x2a, 0x80, 0x17, 0x12, 0x2c, 0xef, 0xda, 0x3d, 0x4c, 0xf4, + 0x47, 0x7b, 0x9a, 0x3e, 0x20, 0x0e, 0xba, 0x0e, 0xe9, 0x11, 0x7b, 0x63, 0x84, 0x2d, 0xde, 0x58, + 0x8f, 0x8c, 0x05, 0x0e, 0x12, 0x53, 0x41, 0x00, 0xd1, 0x06, 0xa4, 0x98, 0x7b, 0x8c, 0xb2, 0x25, + 0xcc, 0x85, 0x33, 0x11, 0x26, 0xce, 0x15, 0xe1, 0xcc, 0x03, 0xf6, 0x87, 0x38, 0xc0, 0xae, 0xdd, + 0xeb, 0x18, 0x43, 0x42, 0x8f, 0xde, 0x93, 0xf0, 0x3e, 0x03, 0x64, 0x92, 0x27, 0x8e, 0x6a, 0x93, + 0x2f, 0x8f, 0x88, 0xa9, 0x13, 0xd5, 0x22, 0xfa, 0x23, 0x51, 0x02, 0x57, 0x3c, 0x57, 0xde, 0xe2, + 0x3b, 0x9c, 0xc5, 0x28, 0x38, 0xe7, 0x2b, 0xf7, 0x85, 0xce, 0x4f, 0xdb, 0xdb, 0xac, 0x86, 0xbf, + 0xe2, 0x6c, 0x98, 0x09, 0xae, 0xda, 0x26, 0xfb, 0x94, 0xde, 0x1e, 0x65, 0x9f, 0x00, 0x67, 0x41, + 0xd5, 0xfd, 0x7d, 0xc5, 0xa7, 0xb2, 0xe9, 0xb9, 0x32, 0x0a, 0x33, 0xc6, 0x8c, 0x0a, 0xe6, 0x1f, + 0x15, 0xf7, 0x60, 0x96, 0x8f, 0xe5, 0xf5, 0x5c, 0xa7, 0x66, 0xe5, 0x7a, 0xe6, 0x89, 0xf5, 0x4d, + 0x9c, 0xdd, 0x79, 0xab, 0xfa, 0xc0, 0xa4, 0x8f, 0x0f, 0x49, 0xb7, 0x47, 0x86, 0xc4, 0x3c, 0x57, + 0x7d, 0x96, 0x61, 0x55, 0x8b, 0xee, 0x22, 0x68, 0x9f, 0x56, 0x4f, 0xd2, 0x92, 0x78, 0x53, 0x25, + 0xbf, 0xa3, 0x56, 0xf4, 0x75, 0x1c, 0x32, 0xa2, 0x85, 0xa3, 0x32, 0xa4, 0x6c, 0x47, 0x73, 0x08, + 0x23, 0x61, 0xe5, 0x06, 0x8a, 0x90, 0xb0, 0xef, 0x5b, 0x30, 0x07, 0xa0, 0x0a, 0x2c, 0x50, 0xab, + 0x4b, 0x2c, 0xc3, 0xec, 0xb1, 0xa8, 0xa7, 0xc1, 0x6d, 0xdf, 0x88, 0xc7, 0x18, 0x54, 0x87, 0xa5, + 0xf0, 0xcd, 0x47, 0xdc, 0x7d, 0xb7, 0xa2, 0x77, 0xdf, 0x10, 0x40, 0x70, 0x1d, 0x59, 0x84, 0xea, + 0xb0, 0xaa, 0x53, 0xd3, 0x24, 0xba, 0x63, 0x50, 0x53, 0xed, 0xd3, 0x91, 0x9d, 0x4f, 0x96, 0x12, + 0xe5, 0x6c, 0xad, 0xe0, 0xb9, 0xf2, 0x66, 0x70, 0xed, 0x8a, 0x00, 0x14, 0xbc, 0x32, 0xd1, 0xdc, + 0xa5, 0x23, 0x1b, 0xe5, 0x21, 0x13, 0xdc, 0xd9, 0x7c, 0xee, 0xb2, 0x38, 0x10, 0x6f, 0x27, 0x9f, + 0x7e, 0x27, 0xc7, 0x94, 0xdf, 0xe3, 0xb0, 0xd6, 0xec, 0x12, 0xd3, 0x31, 0x1e, 0x1a, 0xa4, 0xfb, + 0x3f, 0x33, 0xfe, 0x05, 0xf5, 0xe2, 0x64, 0x9c, 0xa7, 0x99, 0x25, 0x18, 0xdd, 0x57, 0x22, 0xa3, + 0x3b, 0xc3, 0x6c, 0x93, 0x19, 0x2d, 0x18, 0x7d, 0x0c, 0x4b, 0xe1, 0x00, 0xe6, 0x70, 0x39, 0x10, + 0x07, 0xbf, 0x48, 0x40, 0x5a, 0x8c, 0xd7, 0x02, 0x2c, 0x04, 0x5d, 0x86, 0x1d, 0x9a, 0xc4, 0x63, + 0xd9, 0xef, 0x8f, 0x36, 0x3d, 0xb2, 0x74, 0xa2, 0xfa, 0x67, 0x8a, 0x33, 0x42, 0xfd, 0x31, 0x64, + 0x54, 0x30, 0x70, 0x69, 0x8f, 0x5a, 0x0e, 0xfa, 0x14, 0x56, 0x84, 0x2d, 0xfc, 0x93, 0x2e, 0x5b, + 0xdb, 0xf2, 0x5c, 0xf9, 0x42, 0x64, 0xad, 0xb0, 0x2b, 0x78, 0x99, 0x2b, 0x82, 0xb2, 0xba, 0x03, + 0xb9, 0x2e, 0xb1, 0x1d, 0xc3, 0xd4, 0x58, 0x5e, 0xd8, 0xf9, 0xfc, 0x37, 0xdd, 0x25, 0xcf, 0x95, + 0x2f, 0xf2, 0x3d, 0xa6, 0x11, 0x0a, 0x5e, 0x0d, 0xa9, 0x98, 0x27, 0x6d, 0x58, 0x0f, 0xa3, 0x02, + 0x77, 0x58, 0x1a, 0x6b, 0x45, 0xcf, 0x95, 0x0b, 0x67, 0xb7, 0x1a, 0xfb, 0x84, 0x42, 0xda, 0xc0, + 0x31, 0x04, 0xc9, 0xae, 0xe6, 0x68, 0xbc, 0xdf, 0x62, 0xf6, 0xee, 0x87, 0xeb, 0xf0, 0x11, 0x15, + 0xb4, 0xac, 0x0c, 0x6b, 0x59, 0xa1, 0x70, 0xa3, 0x76, 0x05, 0x2f, 0x0b, 0xc5, 0xb8, 0x6d, 0xad, + 0x05, 0x08, 0xff, 0x69, 0x3b, 0xda, 0x70, 0x94, 0x5f, 0x60, 0x9b, 0x5c, 0xf6, 0x5c, 0x39, 0x1f, + 0xdd, 0x64, 0x0c, 0x51, 0x70, 0x4e, 0xe8, 0x3a, 0x81, 0x4a, 0x64, 0xf8, 0x47, 0x09, 0xd6, 0x79, + 0x86, 0xab, 0xfa, 0xa0, 0x4e, 0x87, 0x43, 0xc3, 0x61, 0x1d, 0x77, 0x0e, 0xf7, 0xcf, 0x70, 0x45, + 0x25, 0xa6, 0x2a, 0x0a, 0x41, 0xb2, 0xaf, 0xd9, 0x7d, 0x7e, 0x8b, 0xc2, 0xec, 0x9d, 0x3b, 0x7c, + 0xf5, 0x67, 0x09, 0x52, 0xac, 0x5d, 0xa0, 0x8f, 0x41, 0xde, 0xef, 0x54, 0x3b, 0x0d, 0xf5, 0x7e, + 0xab, 0xd9, 0x6a, 0x76, 0x9a, 0xd5, 0x7b, 0xcd, 0x07, 0x8d, 0x1d, 0xf5, 0x7e, 0x6b, 0x7f, 0xaf, + 0x51, 0x6f, 0xde, 0x69, 0x36, 0x76, 0x72, 0xb1, 0xc2, 0xda, 0xc9, 0x69, 0x69, 0x39, 0x02, 0x40, + 0x79, 0x00, 0xbe, 0xce, 0x57, 0xe6, 0xa4, 0xc2, 0xc2, 0xc9, 0x69, 0x29, 0xe9, 0xbf, 0xa3, 0x22, + 0x2c, 0x73, 0x4b, 0x07, 0x7f, 0xd1, 0xde, 0x6b, 0xb4, 0x72, 0xf1, 0xc2, 0xe2, 0xc9, 0x69, 0x29, + 0x23, 0xc4, 0xc9, 0x4a, 0x66, 0x4c, 0xf0, 0x95, 0xcc, 0x72, 0x19, 0x96, 0xb8, 0xa5, 0x7e, 0xaf, + 0xbd, 0xdf, 0xd8, 0xc9, 0x25, 0x0b, 0x70, 0x72, 0x5a, 0x4a, 0x73, 0xa9, 0x90, 0x7c, 0xfa, 0x7d, + 0x31, 0x76, 0xf5, 0x31, 0xa4, 0x58, 0xeb, 0x42, 0x1f, 0xc0, 0x66, 0x1b, 0xef, 0x34, 0xb0, 0xda, + 0x6a, 0xb7, 0x1a, 0x53, 0xfe, 0xb2, 0x2d, 0x7d, 0x3d, 0x52, 0x60, 0x95, 0xa3, 0xee, 0xb7, 0xd8, + 0xb3, 0xb1, 0x93, 0x93, 0x0a, 0xcb, 0x27, 0xa7, 0xa5, 0xec, 0x58, 0xe1, 0x3b, 0xcc, 0x31, 0x01, + 0x42, 0x38, 0x2c, 0x44, 0x7e, 0x70, 0x6d, 0xf7, 0xd9, 0xcb, 0xa2, 0xf4, 0xfc, 0x65, 0x51, 0xfa, + 0xf3, 0x65, 0x51, 0xfa, 0xf6, 0x55, 0x31, 0xf6, 0xfc, 0x55, 0x31, 0xf6, 0xc7, 0xab, 0x62, 0xec, + 0xc1, 0xcd, 0x37, 0x4e, 0xbc, 0x27, 0xdb, 0xc6, 0x81, 0xbe, 0xfd, 0xd1, 0xad, 0x6b, 0xc1, 0xff, + 0x63, 0x6c, 0x04, 0x1e, 0xa4, 0xd9, 0x7f, 0x5f, 0x37, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xbc, + 0xba, 0x59, 0x74, 0x3b, 0x13, 0x00, 0x00, } func (m *MsgChannelOpenInit) Marshal() (dAtA []byte, err error) { @@ -1593,6 +1684,70 @@ func (m *MsgTimeout) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *MsgTimeoutOnClose) 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 *MsgTimeoutOnClose) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgTimeoutOnClose) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintChannel(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0x32 + } + if m.NextSequenceRecv != 0 { + i = encodeVarintChannel(dAtA, i, uint64(m.NextSequenceRecv)) + i-- + dAtA[i] = 0x28 + } + if m.ProofHeight != 0 { + i = encodeVarintChannel(dAtA, i, uint64(m.ProofHeight)) + i-- + dAtA[i] = 0x20 + } + if len(m.ProofClose) > 0 { + i -= len(m.ProofClose) + copy(dAtA[i:], m.ProofClose) + i = encodeVarintChannel(dAtA, i, uint64(len(m.ProofClose))) + i-- + dAtA[i] = 0x1a + } + if len(m.Proof) > 0 { + i -= len(m.Proof) + copy(dAtA[i:], m.Proof) + i = encodeVarintChannel(dAtA, i, uint64(len(m.Proof))) + i-- + dAtA[i] = 0x12 + } + { + size, err := m.Packet.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintChannel(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func (m *MsgAcknowledgement) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -2167,6 +2322,35 @@ func (m *MsgTimeout) Size() (n int) { return n } +func (m *MsgTimeoutOnClose) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Packet.Size() + n += 1 + l + sovChannel(uint64(l)) + l = len(m.Proof) + if l > 0 { + n += 1 + l + sovChannel(uint64(l)) + } + l = len(m.ProofClose) + if l > 0 { + n += 1 + l + sovChannel(uint64(l)) + } + if m.ProofHeight != 0 { + n += 1 + sovChannel(uint64(m.ProofHeight)) + } + if m.NextSequenceRecv != 0 { + n += 1 + sovChannel(uint64(m.NextSequenceRecv)) + } + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovChannel(uint64(l)) + } + return n +} + func (m *MsgAcknowledgement) Size() (n int) { if m == nil { return 0 @@ -3953,6 +4137,232 @@ func (m *MsgTimeout) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgTimeoutOnClose) 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 ErrIntOverflowChannel + } + 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: MsgTimeoutOnClose: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgTimeoutOnClose: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Packet", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChannel + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthChannel + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthChannel + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Packet.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChannel + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthChannel + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthChannel + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Proof = append(m.Proof[:0], dAtA[iNdEx:postIndex]...) + if m.Proof == nil { + m.Proof = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProofClose", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChannel + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthChannel + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthChannel + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProofClose = append(m.ProofClose[:0], dAtA[iNdEx:postIndex]...) + if m.ProofClose == nil { + m.ProofClose = []byte{} + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", wireType) + } + m.ProofHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChannel + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProofHeight |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NextSequenceRecv", wireType) + } + m.NextSequenceRecv = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChannel + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.NextSequenceRecv |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChannel + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthChannel + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthChannel + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = append(m.Signer[:0], dAtA[iNdEx:postIndex]...) + if m.Signer == nil { + m.Signer = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipChannel(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthChannel + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthChannel + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *MsgAcknowledgement) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/ibc/04-channel/types/codec.go b/x/ibc/04-channel/types/codec.go index 22348bd6a2..3f4e62b0a2 100644 --- a/x/ibc/04-channel/types/codec.go +++ b/x/ibc/04-channel/types/codec.go @@ -20,6 +20,7 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { &MsgRecvPacket{}, &MsgAcknowledgement{}, &MsgTimeout{}, + &MsgTimeoutOnClose{}, ) } diff --git a/x/ibc/04-channel/types/msgs.go b/x/ibc/04-channel/types/msgs.go index 8264329832..73d4114d7f 100644 --- a/x/ibc/04-channel/types/msgs.go +++ b/x/ibc/04-channel/types/msgs.go @@ -433,6 +433,60 @@ func (msg MsgTimeout) Type() string { return "timeout_packet" } +// NewMsgTimeoutOnClose constructs new MsgTimeoutOnClose +func NewMsgTimeoutOnClose( + packet Packet, nextSequenceRecv uint64, + proof, proofClose []byte, + proofHeight uint64, signer sdk.AccAddress, +) *MsgTimeoutOnClose { + return &MsgTimeoutOnClose{ + Packet: packet, + NextSequenceRecv: nextSequenceRecv, + Proof: proof, + ProofClose: proofClose, + ProofHeight: proofHeight, + Signer: signer, + } +} + +// Route implements sdk.Msg +func (msg MsgTimeoutOnClose) Route() string { + return host.RouterKey +} + +// ValidateBasic implements sdk.Msg +func (msg MsgTimeoutOnClose) ValidateBasic() error { + if len(msg.Proof) == 0 { + return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof") + } + if len(msg.ProofClose) == 0 { + return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof of closed counterparty channel end") + } + if msg.ProofHeight == 0 { + return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be > 0") + } + if msg.Signer.Empty() { + return sdkerrors.ErrInvalidAddress + } + + return msg.Packet.ValidateBasic() +} + +// GetSignBytes implements sdk.Msg +func (msg MsgTimeoutOnClose) GetSignBytes() []byte { + return sdk.MustSortJSON(SubModuleCdc.MustMarshalJSON(&msg)) +} + +// GetSigners implements sdk.Msg +func (msg MsgTimeoutOnClose) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Signer} +} + +// Type implements sdk.Msg +func (msg MsgTimeoutOnClose) Type() string { + return "timeout_on_close_packet" +} + var _ sdk.Msg = &MsgAcknowledgement{} // NewMsgAcknowledgement constructs a new MsgAcknowledgement diff --git a/x/ibc/04-channel/types/msgs_test.go b/x/ibc/04-channel/types/msgs_test.go index d886213b3e..b6c9c47743 100644 --- a/x/ibc/04-channel/types/msgs_test.go +++ b/x/ibc/04-channel/types/msgs_test.go @@ -43,7 +43,7 @@ var ( unknownPacketData = []byte("unknown") packet = types.NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp) - unknownPacket = types.NewPacket(unknownPacketData, 0, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp) + invalidPacket = types.NewPacket(unknownPacketData, 0, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp) emptyProof = []byte{} invalidProofs1 = commitmentexported.Proof(nil) @@ -383,7 +383,7 @@ func (suite *MsgTestSuite) TestMsgRecvPacketValidation() { types.NewMsgRecvPacket(packet, suite.proof, 0, addr1), // proof height is zero types.NewMsgRecvPacket(packet, emptyProof, 1, addr1), // empty proof types.NewMsgRecvPacket(packet, suite.proof, 1, emptyAddr), // missing signer address - types.NewMsgRecvPacket(unknownPacket, suite.proof, 1, addr1), // unknown packet + types.NewMsgRecvPacket(invalidPacket, suite.proof, 1, addr1), // unknown packet } testCases := []struct { @@ -436,7 +436,7 @@ func (suite *MsgTestSuite) TestMsgTimeout() { types.NewMsgTimeout(packet, 1, suite.proof, 0, addr), types.NewMsgTimeout(packet, 1, suite.proof, 1, emptyAddr), types.NewMsgTimeout(packet, 1, emptyProof, 1, addr), - types.NewMsgTimeout(unknownPacket, 1, suite.proof, 1, addr), + types.NewMsgTimeout(invalidPacket, 1, suite.proof, 1, addr), } testCases := []struct { @@ -461,6 +461,36 @@ func (suite *MsgTestSuite) TestMsgTimeout() { } } +// TestMsgTimeoutOnClose tests ValidateBasic for MsgTimeoutOnClose +func (suite *MsgTestSuite) TestMsgTimeoutOnClose() { + testCases := []struct { + name string + msg sdk.Msg + expPass bool + }{ + {"success", types.NewMsgTimeoutOnClose(packet, 1, suite.proof, suite.proof, 1, addr), true}, + {"empty proof", types.NewMsgTimeoutOnClose(packet, 1, emptyProof, suite.proof, 1, addr), false}, + {"empty proof close", types.NewMsgTimeoutOnClose(packet, 1, suite.proof, emptyProof, 1, addr), false}, + {"proof height is zero", types.NewMsgTimeoutOnClose(packet, 1, suite.proof, suite.proof, 0, addr), false}, + {"signer address is empty", types.NewMsgTimeoutOnClose(packet, 1, suite.proof, suite.proof, 1, emptyAddr), false}, + {"invalid packet", types.NewMsgTimeoutOnClose(invalidPacket, 1, suite.proof, suite.proof, 1, addr), false}, + } + + for _, tc := range testCases { + tc := tc + + suite.Run(tc.name, func() { + err := tc.msg.ValidateBasic() + + if tc.expPass { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + } + }) + } +} + // TestMsgAcknowledgement tests ValidateBasic for MsgAcknowledgement func (suite *MsgTestSuite) TestMsgAcknowledgement() { testMsgs := []*types.MsgAcknowledgement{ @@ -468,7 +498,7 @@ func (suite *MsgTestSuite) TestMsgAcknowledgement() { types.NewMsgAcknowledgement(packet, packet.GetData(), suite.proof, 0, addr), types.NewMsgAcknowledgement(packet, packet.GetData(), suite.proof, 1, emptyAddr), types.NewMsgAcknowledgement(packet, packet.GetData(), emptyProof, 1, addr), - types.NewMsgAcknowledgement(unknownPacket, packet.GetData(), suite.proof, 1, addr), + types.NewMsgAcknowledgement(invalidPacket, packet.GetData(), suite.proof, 1, addr), } testCases := []struct { diff --git a/x/ibc/handler.go b/x/ibc/handler.go index b4f3c328ad..9e370c3380 100644 --- a/x/ibc/handler.go +++ b/x/ibc/handler.go @@ -260,6 +260,39 @@ func NewHandler(k keeper.Keeper) sdk.Handler { return res, nil + 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 + } + + return res, nil + default: return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized IBC message type: %T", msg) } diff --git a/x/ibc/handler_test.go b/x/ibc/handler_test.go index 8db8cd829e..7cf08d6dc1 100644 --- a/x/ibc/handler_test.go +++ b/x/ibc/handler_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/suite" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc" ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc-transfer/types" clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" @@ -13,8 +14,9 @@ import ( ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" ) -var ( +const ( timeoutHeight = uint64(10000) + totalPackets = uint64(10) ) type HandlerTestSuite struct { @@ -329,7 +331,7 @@ func (suite *HandlerTestSuite) TestHandleTimeoutPacket() { // send from chainA to chainB msg := ibctransfertypes.NewMsgTransfer(channelA.PortID, channelA.ID, ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), packet.GetTimeoutHeight(), packet.GetTimeoutTimestamp()) - err := suite.coordinator.SendMsgs(suite.chainA, suite.chainB, clientB, msg) + err := suite.coordinator.SendMsg(suite.chainA, suite.chainB, clientB, msg) suite.Require().NoError(err) // message committed // need to update chainA client to prove missing ack @@ -343,7 +345,7 @@ func (suite *HandlerTestSuite) TestHandleTimeoutPacket() { // send from chainA to chainB msg := ibctransfertypes.NewMsgTransfer(channelA.PortID, channelA.ID, ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), packet.GetTimeoutHeight(), packet.GetTimeoutTimestamp()) - err := suite.coordinator.SendMsgs(suite.chainA, suite.chainB, clientB, msg) + err := suite.coordinator.SendMsg(suite.chainA, suite.chainB, clientB, msg) suite.Require().NoError(err) // message committed // need to update chainA client to prove missing ack @@ -355,15 +357,18 @@ func (suite *HandlerTestSuite) TestHandleTimeoutPacket() { // setup uses an UNORDERED channel clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB) - // attempts to timeout packet with sequence 10 without timing out packet with sequence 1 - for i := uint64(1); i < 10; i++ { - packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, uint64(suite.chainB.GetContext().BlockHeight()), 0) - - // send from chainA to chainB - msg := ibctransfertypes.NewMsgTransfer(channelA.PortID, channelA.ID, ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), packet.GetTimeoutHeight(), packet.GetTimeoutTimestamp()) - err := suite.coordinator.SendMsgs(suite.chainA, suite.chainB, clientB, msg) - suite.Require().NoError(err) // message committed + msgs := make([]sdk.Msg, totalPackets) + // attempts to timeout the last packet sent without timing out the first packet + // packet sequences begin at 1 + for i := uint64(0); i < totalPackets; i++ { + packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), i+1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, uint64(suite.chainB.GetContext().BlockHeight()), 0) + msgs[i] = ibctransfertypes.NewMsgTransfer(channelA.PortID, channelA.ID, ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), packet.GetTimeoutHeight(), packet.GetTimeoutTimestamp()) } + + // send from chainA to chainB + err := suite.coordinator.SendMsgs(suite.chainA, suite.chainB, clientB, msgs) + suite.Require().NoError(err) // message committed + // need to update chainA client to prove missing ack suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, clientexported.Tendermint) packetKey = host.KeyPacketAcknowledgement(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) @@ -373,15 +378,18 @@ func (suite *HandlerTestSuite) TestHandleTimeoutPacket() { clientA, clientB, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, clientexported.Tendermint) channelA, channelB := suite.coordinator.CreateChannel(suite.chainA, suite.chainB, connA, connB, channeltypes.ORDERED) - // attempts to timeout packet with sequence 10 without timing out packet with sequence 1 - for i := uint64(1); i < 10; i++ { - packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, uint64(suite.chainB.GetContext().BlockHeight()), 0) - - // send from chainA to chainB - msg := ibctransfertypes.NewMsgTransfer(channelA.PortID, channelA.ID, ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), packet.GetTimeoutHeight(), packet.GetTimeoutTimestamp()) - err := suite.coordinator.SendMsgs(suite.chainA, suite.chainB, clientB, msg) - suite.Require().NoError(err) // message committed + msgs := make([]sdk.Msg, totalPackets) + // attempts to timeout the last packet sent without timing out the first packet + // packet sequences begin at 1 + for i := uint64(0); i < totalPackets; i++ { + packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), i+1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, uint64(suite.chainB.GetContext().BlockHeight()), 0) + msgs[i] = ibctransfertypes.NewMsgTransfer(channelA.PortID, channelA.ID, ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), packet.GetTimeoutHeight(), packet.GetTimeoutTimestamp()) } + + // send from chainA to chainB + err := suite.coordinator.SendMsgs(suite.chainA, suite.chainB, clientB, msgs) + suite.Require().NoError(err) // message committed + // need to update chainA client to prove missing ack suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, clientexported.Tendermint) packetKey = host.KeyNextSequenceRecv(packet.GetDestPort(), packet.GetDestChannel()) @@ -433,3 +441,205 @@ func (suite *HandlerTestSuite) TestHandleTimeoutPacket() { }) } } + +// tests the IBC handler timing out a packet via channel closure on ordered +// and unordered channels. It verifies that the deletion of a packet +// 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 *HandlerTestSuite) TestHandleTimeoutOnClosePacket() { + var ( + packet channeltypes.Packet + packetKey []byte + counterpartyChannel ibctesting.TestChannel + ) + + testCases := []struct { + name string + malleate func() + expPass bool + }{ + {"success: ORDERED", func() { + clientA, clientB, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, clientexported.Tendermint) + channelA, channelB := suite.coordinator.CreateChannel(suite.chainA, suite.chainB, connA, connB, channeltypes.ORDERED) + packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) + counterpartyChannel = ibctesting.TestChannel{ + PortID: channelB.PortID, + ID: channelB.ID, + CounterpartyClientID: clientA, + } + + // send from chainA to chainB + msg := ibctransfertypes.NewMsgTransfer(channelA.PortID, channelA.ID, ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), packet.GetTimeoutHeight(), packet.GetTimeoutTimestamp()) + err := suite.coordinator.SendMsg(suite.chainA, suite.chainB, clientB, msg) + suite.Require().NoError(err) // message committed + + // need to update chainA client to prove missing ack + suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, clientexported.Tendermint) + + packetKey = host.KeyNextSequenceRecv(packet.GetDestPort(), packet.GetDestChannel()) + + // close counterparty channel + suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, counterpartyChannel) + + }, true}, + {"success: UNORDERED", func() { + clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB) + packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) + counterpartyChannel = ibctesting.TestChannel{ + PortID: channelB.PortID, + ID: channelB.ID, + CounterpartyClientID: clientA, + } + + // send from chainA to chainB + msg := ibctransfertypes.NewMsgTransfer(channelA.PortID, channelA.ID, ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), packet.GetTimeoutHeight(), packet.GetTimeoutTimestamp()) + err := suite.coordinator.SendMsg(suite.chainA, suite.chainB, clientB, msg) + suite.Require().NoError(err) // message committed + + // need to update chainA client to prove missing ack + suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, clientexported.Tendermint) + + packetKey = host.KeyPacketAcknowledgement(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) + + // close counterparty channel + suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, counterpartyChannel) + + }, true}, + {"success: UNORDERED timeout out of order packet", func() { + // setup uses an UNORDERED channel + clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB) + counterpartyChannel = ibctesting.TestChannel{ + PortID: channelB.PortID, + ID: channelB.ID, + CounterpartyClientID: clientA, + } + + msgs := make([]sdk.Msg, totalPackets) + // attempts to timeout the last packet sent without timing out the first packet + // packet sequences begin at 1 + for i := uint64(0); i < totalPackets; i++ { + packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), i+1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) + msgs[i] = ibctransfertypes.NewMsgTransfer(channelA.PortID, channelA.ID, ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), packet.GetTimeoutHeight(), packet.GetTimeoutTimestamp()) + } + + // send from chainA to chainB + err := suite.coordinator.SendMsgs(suite.chainA, suite.chainB, clientB, msgs) + suite.Require().NoError(err) // message committed + + // need to update chainA client to prove missing ack + suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, clientexported.Tendermint) + packetKey = host.KeyPacketAcknowledgement(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) + + // close counterparty channel + suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, counterpartyChannel) + + }, true}, + {"success: ORDERED timeout out of order packet", func() { + clientA, clientB, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, clientexported.Tendermint) + channelA, channelB := suite.coordinator.CreateChannel(suite.chainA, suite.chainB, connA, connB, channeltypes.ORDERED) + counterpartyChannel = ibctesting.TestChannel{ + PortID: channelB.PortID, + ID: channelB.ID, + CounterpartyClientID: clientA, + } + + msgs := make([]sdk.Msg, totalPackets) + // attempts to timeout the last packet sent without timing out the first packet + // packet sequences begin at 1 + for i := uint64(0); i < totalPackets; i++ { + packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), i+1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) + msgs[i] = ibctransfertypes.NewMsgTransfer(channelA.PortID, channelA.ID, ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), packet.GetTimeoutHeight(), packet.GetTimeoutTimestamp()) + } + + // send from chainA to chainB + err := suite.coordinator.SendMsgs(suite.chainA, suite.chainB, clientB, msgs) + suite.Require().NoError(err) // message committed + + // need to update chainA client to prove missing ack + suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, clientexported.Tendermint) + packetKey = host.KeyNextSequenceRecv(packet.GetDestPort(), packet.GetDestChannel()) + + // close counterparty channel + suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, counterpartyChannel) + + }, true}, + {"channel does not exist", func() { + // any non-nil value of packet is valid + suite.Require().NotNil(packet) + + packetKey = host.KeyNextSequenceRecv(packet.GetDestPort(), packet.GetDestChannel()) + }, false}, + {"UNORDERED: packet not sent", func() { + clientA, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB) + packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) + packetKey = host.KeyPacketAcknowledgement(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) + counterpartyChannel = ibctesting.TestChannel{ + PortID: channelB.PortID, + ID: channelB.ID, + CounterpartyClientID: clientA, + } + + // close counterparty channel + suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, counterpartyChannel) + + }, false}, + {"ORDERED: channel not closed", func() { + clientA, clientB, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, clientexported.Tendermint) + channelA, channelB := suite.coordinator.CreateChannel(suite.chainA, suite.chainB, connA, connB, channeltypes.ORDERED) + packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) + counterpartyChannel = ibctesting.TestChannel{ + PortID: channelB.PortID, + ID: channelB.ID, + CounterpartyClientID: clientA, + } + + // send from chainA to chainB + msg := ibctransfertypes.NewMsgTransfer(channelA.PortID, channelA.ID, ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), packet.GetTimeoutHeight(), packet.GetTimeoutTimestamp()) + err := suite.coordinator.SendMsg(suite.chainA, suite.chainB, clientB, msg) + suite.Require().NoError(err) // message committed + + // need to update chainA client to prove missing ack + suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, clientexported.Tendermint) + + packetKey = host.KeyNextSequenceRecv(packet.GetDestPort(), packet.GetDestChannel()) + + }, false}, + } + + for _, tc := range testCases { + tc := tc + + suite.Run(tc.name, func() { + suite.SetupTest() // reset + + handler := ibc.NewHandler(*suite.chainA.App.IBCKeeper) + + tc.malleate() + + proof, proofHeight := suite.chainB.QueryProof(packetKey) + + channelKey := host.KeyChannel(counterpartyChannel.PortID, counterpartyChannel.ID) + proofClosed, _ := suite.chainB.QueryProof(channelKey) + + msg := channeltypes.NewMsgTimeoutOnClose(packet, 1, proof, proofClosed, proofHeight, suite.chainA.SenderAccount.GetAddress()) + + _, err := handler(suite.chainA.GetContext(), msg) + + if tc.expPass { + suite.Require().NoError(err) + + // replay should return an error + _, err := handler(suite.chainA.GetContext(), msg) + suite.Require().Error(err) + + // verify packet commitment was deleted + has := suite.chainA.App.IBCKeeper.ChannelKeeper.HasPacketCommitment(suite.chainA.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) + suite.Require().False(has) + + } else { + suite.Require().Error(err) + } + }) + } +} diff --git a/x/ibc/spec/04_messages.md b/x/ibc/spec/04_messages.md index b4dc503859..945488a027 100644 --- a/x/ibc/spec/04_messages.md +++ b/x/ibc/spec/04_messages.md @@ -324,3 +324,102 @@ This message is expected to fail if: - `ProofInit` does not prove that the counterparty set its channel to state CLOSED The message closes a channel on chain B for the given Port ID and Channel ID. + +### MsgRecvPacket + +A packet is received on chain B using the `MsgRecvPacket`. + +```go +type MsgRecvPacket struct { + Packet Packet + Proof []byte + ProofHeight uint64 + Signer sdk.AccAddress +} +``` + +This message is expected to fail if: +- `Proof` is empty +- `ProofHeight` is zero +- `Signer` is empty +- `Packet` fails basic validation +- `Proof` does not prove that the counterparty sent the `Packet`. + +The message receives a packet on chain B. + +### MsgTimeout + +A packet is timed out on chain A using the `MsgTimeout`. + +```go +type MsgTimeout struct { + Packet Packet + Proof []byte + ProofHeight uint64 + NextSequenceRecv uint64 + Signer sdk.AccAddress +} +``` + +This message is expected to fail if: +- `Proof` is empty +- `ProofHeight` is zero +- `NextSequenceRecv` is zero +- `Signer` is empty +- `Packet` fails basic validation +- `Proof` does not prove that the packet has not been received on the counterparty chain. + +The message times out a packet on chain B. + +### MsgTimeoutOnClose + +A packet is timed out on chain A due to the closure of the channel end on chain B using +the `MsgTimeoutOnClose`. + +```go +type MsgTimeoutOnClose struct { + Packet Packet + Proof []byte + ProofClose []byte + ProofHeight uint64 + NextSequenceRecv uint64 + Signer sdk.AccAddress +} +``` + +This message is expected to fail if: +- `Proof` is empty +- `ProofClose` is empty +- `ProofHeight` is zero +- `NextSequenceRecv` is zero +- `Signer` is empty +- `Packet` fails basic validation +- `Proof` does not prove that the packet has not been received on the counterparty chain. +- `ProofClose` does not prove that the counterparty channel end has been closed. + +The message times out a packet on chain B. + +### MsgAcknowledgement + +A packet is acknowledged on chain A using the `MsgAcknowledgement`. + +```go +type MsgAcknowledgement struct { + Packet Packet + Acknowledgement []byte + Proof []byte + ProofHeight uint64 + Signer sdk.AccAddress +} +``` + +This message is expected to fail if: +- `Proof` is empty +- `ProofHeight` is zero +- `Signer` is empty +- `Packet` fails basic validation +- `Acknowledgement` is empty +- `Proof` does not prove that the counterparty received the `Packet`. + +The message receives a packet on chain A. + diff --git a/x/ibc/spec/06_events.md b/x/ibc/spec/06_events.md index 09e4823ec8..466a8bd2c7 100644 --- a/x/ibc/spec/06_events.md +++ b/x/ibc/spec/06_events.md @@ -183,7 +183,7 @@ callbacks to IBC applications. | message | action | application-module-defined-field | | message | module | ibc-channel | -### RecvPacket +### MsgRecvPacket | Type | Attribute Key | Attribute Value | |-------------|--------------------------|----------------------| @@ -200,7 +200,7 @@ callbacks to IBC applications. | message | action | recv_packet | | message | module | ibc-channel | -### AcknowledgePacket +### MsgAcknowledgePacket | Type | Attribute Key | Attribute Value | |--------------------|--------------------------|----------------------| @@ -215,7 +215,7 @@ callbacks to IBC applications. | message | action | acknowledge_packet | | message | module | ibc-channel | -### TimeoutPacket & TimeoutOnClose +### MsgTimeoutPacket & MsgTimeoutOnClose | Type | Attribute Key | Attribute Value | |----------------|--------------------------|----------------------| diff --git a/x/ibc/testing/coordinator.go b/x/ibc/testing/coordinator.go index 713fb581a0..43a2c8f776 100644 --- a/x/ibc/testing/coordinator.go +++ b/x/ibc/testing/coordinator.go @@ -259,7 +259,7 @@ func (coord *Coordinator) RecvPacket( recvMsg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, counterparty.SenderAccount.GetAddress()) // receive on counterparty and update source client - return coord.SendMsgs(counterparty, source, sourceClient, recvMsg) + return coord.SendMsgs(counterparty, source, sourceClient, []sdk.Msg{recvMsg}) } // AcknowledgePacket acknowledges on the source chain the packet received on @@ -277,7 +277,7 @@ func (coord *Coordinator) AcknowledgePacket( proof, proofHeight := counterparty.QueryProof(packetKey) ackMsg := channeltypes.NewMsgAcknowledgement(packet, ack, proof, proofHeight, source.SenderAccount.GetAddress()) - return coord.SendMsgs(source, counterparty, counterpartyClient, ackMsg) + return coord.SendMsgs(source, counterparty, counterpartyClient, []sdk.Msg{ackMsg}) } // RelayPacket receives a channel packet on counterparty, queries the ack @@ -305,9 +305,15 @@ func (coord *Coordinator) IncrementTime() { } } +// SendMsg delivers a single provided message to the chain. The counterparty +// client is update with the new source consensus state. +func (coord *Coordinator) SendMsg(source, counterparty *TestChain, counterpartyClientID string, msg sdk.Msg) error { + return coord.SendMsgs(source, counterparty, counterpartyClientID, []sdk.Msg{msg}) +} + // SendMsgs delivers the provided messages to the chain. The counterparty // client is updated with the new source consensus state. -func (coord *Coordinator) SendMsgs(source, counterparty *TestChain, counterpartyClientID string, msgs ...sdk.Msg) error { +func (coord *Coordinator) SendMsgs(source, counterparty *TestChain, counterpartyClientID string, msgs []sdk.Msg) error { if err := source.SendMsgs(msgs...); err != nil { return err }