From e2e48784193145e32e16f67d913f092d6e4097d3 Mon Sep 17 00:00:00 2001 From: Colin Axner Date: Fri, 17 Apr 2020 12:53:01 -0700 Subject: [PATCH 01/12] add timeout timestamp to packet and timestamp to consensus state --- x/ibc/02-client/exported/exported.go | 3 +++ x/ibc/03-connection/keeper/keeper.go | 22 ++++++++++++++++++++ x/ibc/04-channel/exported/exported.go | 1 + x/ibc/04-channel/keeper/packet.go | 17 +++++++++++---- x/ibc/04-channel/types/expected_keepers.go | 5 +++++ x/ibc/04-channel/types/msgs_test.go | 8 ++++--- x/ibc/04-channel/types/packet.go | 11 +++++++--- x/ibc/07-tendermint/types/consensus_state.go | 4 ++-- 8 files changed, 59 insertions(+), 12 deletions(-) diff --git a/x/ibc/02-client/exported/exported.go b/x/ibc/02-client/exported/exported.go index 83ca5be502c0..9072e0c88a3d 100644 --- a/x/ibc/02-client/exported/exported.go +++ b/x/ibc/02-client/exported/exported.go @@ -103,6 +103,9 @@ type ConsensusState interface { // which is used for key-value pair verification. GetRoot() commitmentexported.Root + // GetTimestamp returns the timestamp of the consensus state + GetTimestamp() uint64 + ValidateBasic() error } diff --git a/x/ibc/03-connection/keeper/keeper.go b/x/ibc/03-connection/keeper/keeper.go index 9b2d5d7d48df..a89dae7c2e19 100644 --- a/x/ibc/03-connection/keeper/keeper.go +++ b/x/ibc/03-connection/keeper/keeper.go @@ -63,6 +63,28 @@ func (k Keeper) SetConnection(ctx sdk.Context, connectionID string, connection t store.Set(ibctypes.KeyConnection(connectionID), bz) } +// GetTimestampAtHeight returns the timestamp of the consensus state at the +// given height. +func (k Keeper) GetTimestampAtHeight(ctx sdk.Context, connection types.ConnectionEnd, height uint64) uint64 { + clientState, found := k.clientKeeper.GetClientState(ctx, connection.GetClientID()) + if !found { + return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID()) + } + + consensusState, found := k.clientKeeper.GetClientConsensusState( + ctx, connection.GetClientID(), height, + ) + + if !found { + return sdkerrors.Wrapf( + clienttypes.ErrConsensusStateNotFound, + "clientID (%s), height (%d)", connection.GetClientID(), height, + ) + } + + return consensusState.GetTimestamp() +} + // GetClientConnectionPaths returns all the connection paths stored under a // particular client func (k Keeper) GetClientConnectionPaths(ctx sdk.Context, clientID string) ([]string, bool) { diff --git a/x/ibc/04-channel/exported/exported.go b/x/ibc/04-channel/exported/exported.go index 850b13d7dc3e..7ba92b5c9172 100644 --- a/x/ibc/04-channel/exported/exported.go +++ b/x/ibc/04-channel/exported/exported.go @@ -27,6 +27,7 @@ type CounterpartyI interface { type PacketI interface { GetSequence() uint64 GetTimeoutHeight() uint64 + GetTimeoutTimestamp() uint64 GetSourcePort() string GetSourceChannel() string GetDestPort() string diff --git a/x/ibc/04-channel/keeper/packet.go b/x/ibc/04-channel/keeper/packet.go index 18cff6324cbf..b39ca9807c98 100644 --- a/x/ibc/04-channel/keeper/packet.go +++ b/x/ibc/04-channel/keeper/packet.go @@ -16,7 +16,7 @@ import ( ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" ) -// SendPacket is called by a module in order to send an IBC packet on a channel +// SendPacket is called by a module in order to send an IBC packet on a channel // end owned by the calling module to the corresponding module on the counterparty // chain. func (k Keeper) SendPacket( @@ -77,8 +77,13 @@ func (k Keeper) SendPacket( } // check if packet timeouted on the receiving chain - if clientState.GetLatestHeight() >= packet.GetTimeoutHeight() { - return sdkerrors.Wrap(types.ErrPacketTimeout, "timeout already passed ond the receiving chain") + latestHeight := clientState.GetLatestHeight() + if packet.GetTimeoutHeight() != 0 && latestHeight >= packet.GetTimeoutHeight() { + return sdkerrors.Wrap(types.ErrPacketTimeout, "timeout height already passed on the receiving chain") + } + + if packet.GetTimeoutTimestamp() != 0 && k.connectionKeeper.GetTimeoutAtHeight(ctx, connectionEnd, latestHeight) >= packet.GetTimeoutTimestamp() { + return sdkerrors.Wrap(types.ErrPacketTimeout, "timeout timestamp already passed on the receiving chain") } nextSequenceSend, found := k.GetNextSequenceSend(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) @@ -167,7 +172,11 @@ func (k Keeper) RecvPacket( } // check if packet timeouted by comparing it with the latest height of the chain - if uint64(ctx.BlockHeight()) >= packet.GetTimeoutHeight() { + if packet.GetTimeoutHeight() != 0 && uint64(ctx.BlockHeight()) >= packet.GetTimeoutHeight() { + return nil, types.ErrPacketTimeout + } + + if packet.GetTimeoutTimestamp() != 0 && ctx.BlockTime().UnixNano() >= packet.GetTimeoutTimestamp() { return nil, types.ErrPacketTimeout } diff --git a/x/ibc/04-channel/types/expected_keepers.go b/x/ibc/04-channel/types/expected_keepers.go index cbc663528198..a5dddf08c83b 100644 --- a/x/ibc/04-channel/types/expected_keepers.go +++ b/x/ibc/04-channel/types/expected_keepers.go @@ -18,6 +18,11 @@ type ClientKeeper interface { // ConnectionKeeper expected account IBC connection keeper type ConnectionKeeper interface { GetConnection(ctx sdk.Context, connectionID string) (connectiontypes.ConnectionEnd, bool) + GetTimestampAtHeight( + ctx sdk.Context, + connection connectionexported.ConnectionI, + height uint64, + ) uint64 VerifyChannelState( ctx sdk.Context, connection connectionexported.ConnectionI, diff --git a/x/ibc/04-channel/types/msgs_test.go b/x/ibc/04-channel/types/msgs_test.go index 81237978f9ea..7db59f80a832 100644 --- a/x/ibc/04-channel/types/msgs_test.go +++ b/x/ibc/04-channel/types/msgs_test.go @@ -3,6 +3,7 @@ package types import ( "fmt" "testing" + "time" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" @@ -354,13 +355,14 @@ func (suite *MsgTestSuite) TestMsgChannelCloseConfirm() { // define variables used for testing var ( - timeout = uint64(100) + timeoutHeight = uint64(100) + timeoutTimestamp = uint64(100) validPacketData = []byte("testdata") unknownPacketData = []byte("unknown") invalidAckData = []byte("123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890") - packet = NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, 100) - unknownPacket = NewPacket(unknownPacketData, 0, portid, chanid, cpportid, cpchanid, 100) + packet = NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp) + unknownPacket = NewPacket(unknownPacketData, 0, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp) invalidAck = invalidAckData emptyProof = commitmenttypes.MerkleProof{Proof: nil} diff --git a/x/ibc/04-channel/types/packet.go b/x/ibc/04-channel/types/packet.go index d302f3414511..c12ba033eee2 100644 --- a/x/ibc/04-channel/types/packet.go +++ b/x/ibc/04-channel/types/packet.go @@ -35,6 +35,7 @@ type Packet struct { DestinationPort string `json:"destination_port" yaml:"destination_port"` // identifies the port on the receiving chain. DestinationChannel string `json:"destination_channel" yaml:"destination_channel"` // identifies the channel end on the receiving chain. TimeoutHeight uint64 `json:"timeout_height" yaml:"timeout_height"` // block height after which the packet times out + TimeoutTimestamp uint64 `json:"timeout_timestamp" yaml:"timeout_timestamp"` // block timestamp after which the packet times out } // NewPacket creates a new Packet instance @@ -42,7 +43,7 @@ func NewPacket( data []byte, sequence uint64, sourcePort, sourceChannel, destinationPort, destinationChannel string, - timeoutHeight uint64, + timeoutHeight uint64, timeoutTimestamp uint64, ) Packet { return Packet{ Data: data, @@ -52,6 +53,7 @@ func NewPacket( DestinationPort: destinationPort, DestinationChannel: destinationChannel, TimeoutHeight: timeoutHeight, + TimeoutTimestamp: timeoutTimestamp, } } @@ -76,6 +78,9 @@ func (p Packet) GetData() []byte { return p.Data } // GetTimeoutHeight implements PacketI interface func (p Packet) GetTimeoutHeight() uint64 { return p.TimeoutHeight } +// GetTimeoutTimestamp implements PacketI interface +func (p Packet) GetTimeoutTimestamp() uint64 { return p.TimeoutTimestamp } + // ValidateBasic implements PacketI interface func (p Packet) ValidateBasic() error { if err := host.DefaultPortIdentifierValidator(p.SourcePort); err != nil { @@ -105,8 +110,8 @@ func (p Packet) ValidateBasic() error { if p.Sequence == 0 { return sdkerrors.Wrap(ErrInvalidPacket, "packet sequence cannot be 0") } - if p.TimeoutHeight == 0 { - return sdkerrors.Wrap(ErrInvalidPacket, "packet timeout cannot be 0") + if p.TimeoutHeight == 0 && p.TimeoutTimestamp == 0 { + return sdkerrors.Wrap(ErrInvalidPacket, "packet timeout height and packet timeout timestamp cannot both be 0") } if len(p.Data) == 0 { return sdkerrors.Wrap(ErrInvalidPacket, "packet data bytes cannot be empty") diff --git a/x/ibc/07-tendermint/types/consensus_state.go b/x/ibc/07-tendermint/types/consensus_state.go index 801fc768f181..be0cc9af3387 100644 --- a/x/ibc/07-tendermint/types/consensus_state.go +++ b/x/ibc/07-tendermint/types/consensus_state.go @@ -35,8 +35,8 @@ func (cs ConsensusState) GetHeight() uint64 { } // GetTimestamp returns block time at which the consensus state was stored -func (cs ConsensusState) GetTimestamp() time.Time { - return cs.Timestamp +func (cs ConsensusState) GetTimestamp() uint64 { + return cs.Timestamp.UnixNano() } // ValidateBasic defines a basic validation for the tendermint consensus state. From 004abac0f71f4dd8bb6ad2bb7d204f130ca71a02 Mon Sep 17 00:00:00 2001 From: Colin Axner Date: Mon, 20 Apr 2020 11:11:28 -0700 Subject: [PATCH 02/12] add timeout timestamp event attribute --- x/ibc/04-channel/keeper/packet.go | 14 +++++++++----- x/ibc/04-channel/keeper/timeout.go | 12 +++++++++--- x/ibc/04-channel/types/events.go | 15 ++++++++------- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/x/ibc/04-channel/keeper/packet.go b/x/ibc/04-channel/keeper/packet.go index b39ca9807c98..78a7a370517d 100644 --- a/x/ibc/04-channel/keeper/packet.go +++ b/x/ibc/04-channel/keeper/packet.go @@ -82,7 +82,7 @@ func (k Keeper) SendPacket( return sdkerrors.Wrap(types.ErrPacketTimeout, "timeout height already passed on the receiving chain") } - if packet.GetTimeoutTimestamp() != 0 && k.connectionKeeper.GetTimeoutAtHeight(ctx, connectionEnd, latestHeight) >= packet.GetTimeoutTimestamp() { + if packet.GetTimeoutTimestamp() != 0 && k.connectionKeeper.GetTimestampAtHeight(ctx, connectionEnd, latestHeight) >= packet.GetTimeoutTimestamp() { return sdkerrors.Wrap(types.ErrPacketTimeout, "timeout timestamp already passed on the receiving chain") } @@ -108,7 +108,8 @@ func (k Keeper) SendPacket( sdk.NewEvent( types.EventTypeSendPacket, sdk.NewAttribute(types.AttributeKeyData, string(packet.GetData())), - sdk.NewAttribute(types.AttributeKeyTimeout, fmt.Sprintf("%d", packet.GetTimeoutHeight())), + 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()), @@ -251,7 +252,8 @@ func (k Keeper) PacketExecuted( sdk.NewEvent( types.EventTypeRecvPacket, sdk.NewAttribute(types.AttributeKeyData, string(acknowledgement)), - sdk.NewAttribute(types.AttributeKeyTimeout, fmt.Sprintf("%d", packet.GetTimeoutHeight())), + 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()), @@ -338,7 +340,8 @@ func (k Keeper) AcknowledgePacket( ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( types.EventTypeAcknowledgePacket, - sdk.NewAttribute(types.AttributeKeyTimeout, fmt.Sprintf("%d", packet.GetTimeoutHeight())), + 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()), @@ -453,7 +456,8 @@ func (k Keeper) CleanupPacket( ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( types.EventTypeCleanupPacket, - sdk.NewAttribute(types.AttributeKeyTimeout, fmt.Sprintf("%d", packet.GetTimeoutHeight())), + 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()), diff --git a/x/ibc/04-channel/keeper/timeout.go b/x/ibc/04-channel/keeper/timeout.go index 8ca20555ff30..3606834ef24c 100644 --- a/x/ibc/04-channel/keeper/timeout.go +++ b/x/ibc/04-channel/keeper/timeout.go @@ -67,7 +67,11 @@ func (k Keeper) TimeoutPacket( } // check that timeout height has passed on the other end - if proofHeight < packet.GetTimeoutHeight() { + if packet.GetTimeoutHeight() != 0 && proofHeight < packet.GetTimeoutHeight() { + return nil, types.ErrPacketTimeout + } + + if packet.GetTimeoutTimestamp() != 0 && proofHeight < packet.GetTimeoutTimestamp() { return nil, types.ErrPacketTimeout } @@ -110,7 +114,8 @@ func (k Keeper) TimeoutPacket( ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( types.EventTypeTimeoutPacket, - sdk.NewAttribute(types.AttributeKeyTimeout, fmt.Sprintf("%d", packet.GetTimeoutHeight())), + 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()), @@ -247,7 +252,8 @@ func (k Keeper) TimeoutOnClose( ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( types.EventTypeTimeoutPacket, - sdk.NewAttribute(types.AttributeKeyTimeout, fmt.Sprintf("%d", packet.GetTimeoutHeight())), + 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()), diff --git a/x/ibc/04-channel/types/events.go b/x/ibc/04-channel/types/events.go index 6896b225b142..ac9407d71202 100644 --- a/x/ibc/04-channel/types/events.go +++ b/x/ibc/04-channel/types/events.go @@ -20,13 +20,14 @@ const ( EventTypeCleanupPacket = "cleanup_packet" EventTypeTimeoutPacket = "timeout_packet" - AttributeKeyData = "packet_data" - AttributeKeyTimeout = "packet_timeout" - AttributeKeySequence = "packet_sequence" - AttributeKeySrcPort = "packet_src_port" - AttributeKeySrcChannel = "packet_src_channel" - AttributeKeyDstPort = "packet_dst_port" - AttributeKeyDstChannel = "packet_dst_channel" + AttributeKeyData = "packet_data" + AttributeKeyTimeoutHeight = "packet_timeout_height" + AttributeKeyTimeoutTimestamp = "packet_timeout_timestamp" + AttributeKeySequence = "packet_sequence" + AttributeKeySrcPort = "packet_src_port" + AttributeKeySrcChannel = "packet_src_channel" + AttributeKeyDstPort = "packet_dst_port" + AttributeKeyDstChannel = "packet_dst_channel" ) // IBC channel events vars From af8fa3fd96507c793f920001fc70ec7b77fe848e Mon Sep 17 00:00:00 2001 From: Colin Axner Date: Mon, 20 Apr 2020 13:52:18 -0700 Subject: [PATCH 03/12] update various issues with adding timestamp --- x/ibc/03-connection/keeper/keeper.go | 11 +++-------- x/ibc/04-channel/client/utils/utils.go | 5 +++-- x/ibc/04-channel/keeper/packet.go | 14 ++++++++++---- x/ibc/04-channel/keeper/timeout.go | 13 +++++++------ x/ibc/04-channel/types/expected_keepers.go | 4 ++-- x/ibc/04-channel/types/msgs_test.go | 4 ++-- x/ibc/04-channel/types/packet_test.go | 17 ++++++++++------- x/ibc/07-tendermint/types/consensus_state.go | 5 ++++- 8 files changed, 41 insertions(+), 32 deletions(-) diff --git a/x/ibc/03-connection/keeper/keeper.go b/x/ibc/03-connection/keeper/keeper.go index a89dae7c2e19..5d939ca06f18 100644 --- a/x/ibc/03-connection/keeper/keeper.go +++ b/x/ibc/03-connection/keeper/keeper.go @@ -65,24 +65,19 @@ func (k Keeper) SetConnection(ctx sdk.Context, connectionID string, connection t // GetTimestampAtHeight returns the timestamp of the consensus state at the // given height. -func (k Keeper) GetTimestampAtHeight(ctx sdk.Context, connection types.ConnectionEnd, height uint64) uint64 { - clientState, found := k.clientKeeper.GetClientState(ctx, connection.GetClientID()) - if !found { - return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID()) - } - +func (k Keeper) GetTimestampAtHeight(ctx sdk.Context, connection types.ConnectionEnd, height uint64) (timestamp uint64, err error) { consensusState, found := k.clientKeeper.GetClientConsensusState( ctx, connection.GetClientID(), height, ) if !found { - return sdkerrors.Wrapf( + return timestamp, sdkerrors.Wrapf( clienttypes.ErrConsensusStateNotFound, "clientID (%s), height (%d)", connection.GetClientID(), height, ) } - return consensusState.GetTimestamp() + return consensusState.GetTimestamp(), err } // GetClientConnectionPaths returns all the connection paths stored under a diff --git a/x/ibc/04-channel/client/utils/utils.go b/x/ibc/04-channel/client/utils/utils.go index 729fad9d1d2e..70d6b530240e 100644 --- a/x/ibc/04-channel/client/utils/utils.go +++ b/x/ibc/04-channel/client/utils/utils.go @@ -11,7 +11,7 @@ import ( // QueryPacket returns a packet from the store func QueryPacket( ctx context.CLIContext, portID, channelID string, - sequence, timeout uint64, prove bool, + sequence, timeoutHeight, timeoutTimestamp uint64, prove bool, ) (types.PacketResponse, error) { req := abci.RequestQuery{ Path: "store/ibc/key", @@ -39,7 +39,8 @@ func QueryPacket( channelID, destPortID, destChannelID, - timeout, + timeoutHeight, + timeoutTimestamp, ) // FIXME: res.Height+1 is hack, fix later diff --git a/x/ibc/04-channel/keeper/packet.go b/x/ibc/04-channel/keeper/packet.go index 78a7a370517d..a4ebcb31cd3b 100644 --- a/x/ibc/04-channel/keeper/packet.go +++ b/x/ibc/04-channel/keeper/packet.go @@ -82,7 +82,12 @@ func (k Keeper) SendPacket( return sdkerrors.Wrap(types.ErrPacketTimeout, "timeout height already passed on the receiving chain") } - if packet.GetTimeoutTimestamp() != 0 && k.connectionKeeper.GetTimestampAtHeight(ctx, connectionEnd, latestHeight) >= packet.GetTimeoutTimestamp() { + latestTimestamp, err := k.connectionKeeper.GetTimestampAtHeight(ctx, connectionEnd, latestHeight) + if err != nil { + return err + } + + if packet.GetTimeoutTimestamp() != 0 && latestTimestamp >= packet.GetTimeoutTimestamp() { return sdkerrors.Wrap(types.ErrPacketTimeout, "timeout timestamp already passed on the receiving chain") } @@ -174,11 +179,12 @@ func (k Keeper) RecvPacket( // check if packet timeouted by comparing it with the latest height of the chain if packet.GetTimeoutHeight() != 0 && uint64(ctx.BlockHeight()) >= packet.GetTimeoutHeight() { - return nil, types.ErrPacketTimeout + return nil, sdkerrors.Wrapf(types.ErrPacketTimeout, "packet timeout height (%d) has been passed by the current block height (%d)", packet.GetTimeoutHeight(), uint64(ctx.BlockHeight())) } - if packet.GetTimeoutTimestamp() != 0 && ctx.BlockTime().UnixNano() >= packet.GetTimeoutTimestamp() { - return nil, types.ErrPacketTimeout + // check if packet timeouted by comparing it with the latest timestamp of the chain + if packet.GetTimeoutTimestamp() != 0 && uint64(ctx.BlockTime().UnixNano()) >= packet.GetTimeoutTimestamp() { + return nil, sdkerrors.Wrapf(types.ErrPacketTimeout, "packet timeout timestamp (%d) has been passed by the current block timestamp (%d)", packet.GetTimeoutTimestamp(), uint64(ctx.BlockTime().UnixNano())) } if err := k.connectionKeeper.VerifyPacketCommitment( diff --git a/x/ibc/04-channel/keeper/timeout.go b/x/ibc/04-channel/keeper/timeout.go index 3606834ef24c..ca7161077cf4 100644 --- a/x/ibc/04-channel/keeper/timeout.go +++ b/x/ibc/04-channel/keeper/timeout.go @@ -66,13 +66,15 @@ func (k Keeper) TimeoutPacket( ) } - // check that timeout height has passed on the other end - if packet.GetTimeoutHeight() != 0 && proofHeight < packet.GetTimeoutHeight() { - return nil, types.ErrPacketTimeout + // check that timeout height or timeout timestamp has passed on the other end + proofTimestamp, err := k.connectionKeeper.GetTimestampAtHeight(ctx, connectionEnd, proofHeight) + if err != nil { + return nil, err } - if packet.GetTimeoutTimestamp() != 0 && proofHeight < packet.GetTimeoutTimestamp() { - return nil, types.ErrPacketTimeout + if (packet.GetTimeoutHeight() == 0 || proofHeight < packet.GetTimeoutHeight()) && + (packet.GetTimeoutTimestamp() == 0 || proofTimestamp < packet.GetTimeoutTimestamp()) { + return nil, sdkerrors.Wrap(types.ErrPacketTimeout, "packet timeout has not been reached for height or timestamp") } // check that packet has not been received @@ -87,7 +89,6 @@ func (k Keeper) TimeoutPacket( return nil, sdkerrors.Wrap(types.ErrInvalidPacket, "packet hasn't been sent") } - var err error switch channel.Ordering { case exported.ORDERED: // check that the recv sequence is as claimed diff --git a/x/ibc/04-channel/types/expected_keepers.go b/x/ibc/04-channel/types/expected_keepers.go index a5dddf08c83b..e2599b80d23e 100644 --- a/x/ibc/04-channel/types/expected_keepers.go +++ b/x/ibc/04-channel/types/expected_keepers.go @@ -20,9 +20,9 @@ type ConnectionKeeper interface { GetConnection(ctx sdk.Context, connectionID string) (connectiontypes.ConnectionEnd, bool) GetTimestampAtHeight( ctx sdk.Context, - connection connectionexported.ConnectionI, + connection connectiontypes.ConnectionEnd, height uint64, - ) uint64 + ) (uint64, error) VerifyChannelState( ctx sdk.Context, connection connectionexported.ConnectionI, diff --git a/x/ibc/04-channel/types/msgs_test.go b/x/ibc/04-channel/types/msgs_test.go index 7db59f80a832..ddc5fdef82ae 100644 --- a/x/ibc/04-channel/types/msgs_test.go +++ b/x/ibc/04-channel/types/msgs_test.go @@ -3,7 +3,6 @@ package types import ( "fmt" "testing" - "time" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" @@ -357,6 +356,7 @@ func (suite *MsgTestSuite) TestMsgChannelCloseConfirm() { var ( timeoutHeight = uint64(100) timeoutTimestamp = uint64(100) + invalidTimeout = uint64(0) validPacketData = []byte("testdata") unknownPacketData = []byte("unknown") invalidAckData = []byte("123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890") @@ -427,7 +427,7 @@ func TestMsgPacketGetSignBytes(t *testing.T) { res := msg.GetSignBytes() expected := fmt.Sprintf( - `{"type":"ibc/channel/MsgPacket","value":{"packet":{"data":%s,"destination_channel":"testcpchannel","destination_port":"testcpport","sequence":"1","source_channel":"testchannel","source_port":"testportid","timeout_height":"100"},"proof":{"type":"ibc/commitment/MerkleProof","value":{"proof":{"ops":[]}}},"proof_height":"1","signer":"cosmos1w3jhxarpv3j8yvg4ufs4x"}}`, + `{"type":"ibc/channel/MsgPacket","value":{"packet":{"data":%s,"destination_channel":"testcpchannel","destination_port":"testcpport","sequence":"1","source_channel":"testchannel","source_port":"testportid","timeout_height":"100","timeout_timestamp":"100"},"proof":{"type":"ibc/commitment/MerkleProof","value":{"proof":{"ops":[]}}},"proof_height":"1","signer":"cosmos1w3jhxarpv3j8yvg4ufs4x"}}`, string(msg.GetDataSignBytes()), ) require.Equal(t, expected, string(res)) diff --git a/x/ibc/04-channel/types/packet_test.go b/x/ibc/04-channel/types/packet_test.go index 3efc7158db87..5c08a26470d4 100644 --- a/x/ibc/04-channel/types/packet_test.go +++ b/x/ibc/04-channel/types/packet_test.go @@ -12,13 +12,16 @@ func TestPacketValidateBasic(t *testing.T) { expPass bool errMsg string }{ - {NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, timeout), true, ""}, - {NewPacket(validPacketData, 0, portid, chanid, cpportid, cpchanid, timeout), false, "invalid sequence"}, - {NewPacket(validPacketData, 1, invalidPort, chanid, cpportid, cpchanid, timeout), false, "invalid source port"}, - {NewPacket(validPacketData, 1, portid, invalidChannel, cpportid, cpchanid, timeout), false, "invalid source channel"}, - {NewPacket(validPacketData, 1, portid, chanid, invalidPort, cpchanid, timeout), false, "invalid destination port"}, - {NewPacket(validPacketData, 1, portid, chanid, cpportid, invalidChannel, timeout), false, "invalid destination channel"}, - {NewPacket(unknownPacketData, 1, portid, chanid, cpportid, cpchanid, timeout), true, ""}, + {NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp), true, ""}, + {NewPacket(validPacketData, 0, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp), false, "invalid sequence"}, + {NewPacket(validPacketData, 1, invalidPort, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp), false, "invalid source port"}, + {NewPacket(validPacketData, 1, portid, invalidChannel, cpportid, cpchanid, timeoutHeight, timeoutTimestamp), false, "invalid source channel"}, + {NewPacket(validPacketData, 1, portid, chanid, invalidPort, cpchanid, timeoutHeight, timeoutTimestamp), false, "invalid destination port"}, + {NewPacket(validPacketData, 1, portid, chanid, cpportid, invalidChannel, timeoutHeight, timeoutTimestamp), false, "invalid destination channel"}, + {NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, invalidTimeout, invalidTimeout), false, "invalid timeout"}, + {NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, invalidTimeout, timeoutTimestamp), true, "timeout height 0 with valid timeout timestamp"}, + {NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, timeoutHeight, invalidTimeout), true, "timeout timestamp 0 with valid timeout height"}, + {NewPacket(unknownPacketData, 1, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp), true, ""}, } for i, tc := range testCases { diff --git a/x/ibc/07-tendermint/types/consensus_state.go b/x/ibc/07-tendermint/types/consensus_state.go index be0cc9af3387..f570e0575565 100644 --- a/x/ibc/07-tendermint/types/consensus_state.go +++ b/x/ibc/07-tendermint/types/consensus_state.go @@ -36,7 +36,7 @@ func (cs ConsensusState) GetHeight() uint64 { // GetTimestamp returns block time at which the consensus state was stored func (cs ConsensusState) GetTimestamp() uint64 { - return cs.Timestamp.UnixNano() + return uint64(cs.Timestamp.UnixNano()) } // ValidateBasic defines a basic validation for the tendermint consensus state. @@ -53,5 +53,8 @@ func (cs ConsensusState) ValidateBasic() error { if cs.Timestamp.IsZero() { return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "timestamp cannot be zero Unix time") } + if cs.Timestamp.UnixNano() < 0 { + return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "timestamp cannot be negative Unix time") + } return nil } From 2a3fbd750a41a2f801552eaad2d4685ed5c56649 Mon Sep 17 00:00:00 2001 From: Colin Axner Date: Mon, 20 Apr 2020 14:59:09 -0700 Subject: [PATCH 04/12] fix tests, add default timeout timestamp --- x/ibc/04-channel/keeper/keeper_test.go | 11 +++ x/ibc/04-channel/keeper/packet_test.go | 105 +++++++++++++----------- x/ibc/04-channel/keeper/timeout_test.go | 40 ++++----- x/ibc/20-transfer/alias.go | 29 +++---- x/ibc/20-transfer/keeper/keeper.go | 7 +- x/ibc/20-transfer/keeper/relay.go | 3 +- x/ibc/20-transfer/keeper/relay_test.go | 6 +- 7 files changed, 115 insertions(+), 86 deletions(-) diff --git a/x/ibc/04-channel/keeper/keeper_test.go b/x/ibc/04-channel/keeper/keeper_test.go index 1f8bcb5c5cbd..46a43d87a24e 100644 --- a/x/ibc/04-channel/keeper/keeper_test.go +++ b/x/ibc/04-channel/keeper/keeper_test.go @@ -46,6 +46,11 @@ const ( trustingPeriod time.Duration = time.Hour * 24 * 7 * 2 ubdPeriod time.Duration = time.Hour * 24 * 7 * 3 + + timeoutHeight = 100 + timeoutTimestamp = 100 + disabledTimeoutTimestamp = 0 + disabledTimeoutHeight = 0 ) type KeeperTestSuite struct { @@ -193,6 +198,12 @@ func commitNBlocks(chain *TestChain, n int) { } } +// commit current block and start the next block with the provided time +func commitBlockWithNewTimestamp(chain *TestChain, timestamp int64) { + chain.App.Commit() + chain.App.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: chain.App.LastBlockHeight() + 1, Time: time.Unix(timestamp, 0)}}) +} + // nolint: unused func queryProof(chain *TestChain, key []byte) (commitmenttypes.MerkleProof, uint64) { res := chain.App.Query(abci.RequestQuery{ diff --git a/x/ibc/04-channel/keeper/packet_test.go b/x/ibc/04-channel/keeper/packet_test.go index 2dc79bb19674..6efb99dffcdb 100644 --- a/x/ibc/04-channel/keeper/packet_test.go +++ b/x/ibc/04-channel/keeper/packet_test.go @@ -19,66 +19,73 @@ func (suite *KeeperTestSuite) TestSendPacket() { var channelCap *capability.Capability testCases := []testCase{ {"success", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.CreateClient(suite.chainA) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) suite.chainB.App.IBCKeeper.ChannelKeeper.SetNextSequenceSend(suite.chainB.GetContext(), testPort1, testChannel1, 1) }, true}, {"packet basic validation failed", func() { - packet = types.NewPacket(mockFailPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockFailPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) }, false}, {"channel not found", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) }, false}, {"channel closed", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.CLOSED, exported.ORDERED, testConnectionIDA) }, false}, {"packet dest port ≠ channel counterparty port", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, testPort3, counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, testPort3, counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"packet dest channel ID ≠ channel counterparty channel ID", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), testChannel3, 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), testChannel3, timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"connection not found", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"connection is UNINITIALIZED", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.UNINITIALIZED) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"client state not found", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"timeout height passed", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) commitNBlocks(suite.chainB, 10) suite.chainB.CreateClient(suite.chainA) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, + {"timeout timestamp passed", func() { + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), disabledTimeoutHeight, timeoutTimestamp) + commitBlockWithNewTimestamp(suite.chainB, timeoutTimestamp) + suite.chainB.CreateClient(suite.chainA) + suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) + suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) + }, false}, {"next sequence send not found", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.CreateClient(suite.chainA) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"next sequence wrong", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.CreateClient(suite.chainA) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) suite.chainB.App.IBCKeeper.ChannelKeeper.SetNextSequenceSend(suite.chainB.GetContext(), testPort1, testChannel1, 5) }, false}, {"channel capability not found", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.CreateClient(suite.chainA) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) @@ -125,40 +132,46 @@ func (suite *KeeperTestSuite) TestRecvPacket() { suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) suite.chainA.createChannel(testPort2, testChannel2, testPort1, testChannel1, exported.OPEN, exported.ORDERED, testConnectionIDB) suite.chainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceSend(suite.chainA.GetContext(), testPort2, testChannel2, 1) - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort2, testChannel2, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort2, testChannel2, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainA.GetContext(), testPort2, testChannel2, 1, types.CommitPacket(packet)) }, true}, {"channel not found", func() {}, false}, {"channel not open", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort2, testChannel2, testPort1, testChannel1, exported.INIT, exported.ORDERED, testConnectionIDA) }, false}, {"packet source port ≠ channel counterparty port", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort2, testChannel2, testPort3, testChannel1, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"packet source channel ID ≠ channel counterparty channel ID", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort2, testChannel2, testPort1, testChannel3, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"connection not found", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort2, testChannel2, testPort1, testChannel1, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"connection not OPEN", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.INIT) suite.chainB.createChannel(testPort2, testChannel2, testPort1, testChannel1, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, - {"timeout passed", func() { + {"timeout height passed", func() { commitNBlocks(suite.chainB, 10) - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) + suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) + suite.chainB.createChannel(testPort2, testChannel2, testPort1, testChannel1, exported.OPEN, exported.ORDERED, testConnectionIDA) + }, false}, + {"timeout timestamp passed", func() { + commitBlockWithNewTimestamp(suite.chainB, timeoutTimestamp) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), disabledTimeoutHeight, timeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort2, testChannel2, testPort1, testChannel1, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"validation failed", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort2, testChannel2, testPort1, testChannel1, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, @@ -196,31 +209,31 @@ func (suite *KeeperTestSuite) TestPacketExecuted() { var channelCap *capability.Capability testCases := []testCase{ {"success: UNORDERED", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainA.createChannel(testPort2, testChannel2, testPort1, testChannel1, exported.OPEN, exported.UNORDERED, testConnectionIDA) suite.chainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(suite.chainA.GetContext(), testPort2, testChannel2, 1) }, true}, {"success: ORDERED", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainA.createChannel(testPort2, testChannel2, testPort1, testChannel1, exported.OPEN, exported.ORDERED, testConnectionIDA) suite.chainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(suite.chainA.GetContext(), testPort2, testChannel2, 1) }, true}, {"channel not found", func() {}, false}, {"channel not OPEN", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainA.createChannel(testPort2, testChannel2, testPort1, testChannel1, exported.CLOSED, exported.ORDERED, testConnectionIDA) }, false}, {"next sequence receive not found", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainA.createChannel(testPort2, testChannel2, testPort1, testChannel1, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"packet sequence ≠ next sequence receive", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainA.createChannel(testPort2, testChannel2, testPort1, testChannel1, exported.OPEN, exported.ORDERED, testConnectionIDA) suite.chainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(suite.chainA.GetContext(), testPort2, testChannel2, 5) }, false}, {"capability not found", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainA.createChannel(testPort2, testChannel2, testPort1, testChannel1, exported.OPEN, exported.UNORDERED, testConnectionIDA) suite.chainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(suite.chainA.GetContext(), testPort2, testChannel2, 1) channelCap = capability.NewCapability(3) @@ -260,7 +273,7 @@ func (suite *KeeperTestSuite) TestAcknowledgePacket() { testCases := []testCase{ {"success", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.CreateClient(suite.chainA) suite.chainA.CreateClient(suite.chainB) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) @@ -272,33 +285,33 @@ func (suite *KeeperTestSuite) TestAcknowledgePacket() { }, true}, {"channel not found", func() {}, false}, {"channel not open", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.CLOSED, exported.ORDERED, testConnectionIDA) }, false}, {"packet source port ≠ channel counterparty port", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort3, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"packet source channel ID ≠ channel counterparty channel ID", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel3, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"connection not found", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"connection not OPEN", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.INIT) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"packet hasn't been sent", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"packet ack verification failed", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) suite.chainB.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainB.GetContext(), testPort1, testChannel1, 1, types.CommitPacket(packet)) @@ -342,7 +355,7 @@ func (suite *KeeperTestSuite) TestCleanupPacket() { testCases := []testCase{ {"success", func() { nextSeqRecv = 10 - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainA.CreateClient(suite.chainB) suite.chainB.CreateClient(suite.chainA) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) @@ -354,47 +367,47 @@ func (suite *KeeperTestSuite) TestCleanupPacket() { }, true}, {"channel not found", func() {}, false}, {"channel not open", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.CLOSED, exported.ORDERED, testConnectionIDA) }, false}, {"packet source port ≠ channel counterparty port", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort3, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"packet source channel ID ≠ channel counterparty channel ID", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel3, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"connection not found", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"connection not OPEN", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.INIT) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"packet already received ", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 10, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 10, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"packet hasn't been sent", func() { nextSeqRecv = 10 - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"next seq receive verification failed", func() { nextSeqRecv = 10 - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) suite.chainB.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainB.GetContext(), testPort1, testChannel1, 1, types.CommitPacket(packet)) }, false}, {"packet ack verification failed", func() { nextSeqRecv = 10 - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.UNORDERED, testConnectionIDA) suite.chainB.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainB.GetContext(), testPort1, testChannel1, 1, types.CommitPacket(packet)) diff --git a/x/ibc/04-channel/keeper/timeout_test.go b/x/ibc/04-channel/keeper/timeout_test.go index 9d60a0ce148e..61ab13f218fd 100644 --- a/x/ibc/04-channel/keeper/timeout_test.go +++ b/x/ibc/04-channel/keeper/timeout_test.go @@ -21,7 +21,7 @@ func (suite *KeeperTestSuite) TestTimeoutPacket() { testCases := []testCase{ {"success", func() { nextSeqRecv = 1 - packet = types.NewPacket(newMockTimeoutPacket().GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 1) + packet = types.NewPacket(newMockTimeoutPacket().GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 1, disabledTimeoutTimestamp) suite.chainB.CreateClient(suite.chainA) suite.chainA.CreateClient(suite.chainB) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) @@ -32,48 +32,48 @@ func (suite *KeeperTestSuite) TestTimeoutPacket() { }, true}, {"channel not found", func() {}, false}, {"channel not open", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.CLOSED, exported.ORDERED, testConnectionIDA) }, false}, {"packet source port ≠ channel counterparty port", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort3, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"packet source channel ID ≠ channel counterparty channel ID", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel3, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"connection not found", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"timeout", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 10, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 10, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"packet already received ", func() { nextSeqRecv = 2 - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"packet hasn't been sent", func() { nextSeqRecv = 1 - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"next seq receive verification failed", func() { nextSeqRecv = 1 - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) suite.chainB.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainB.GetContext(), testPort1, testChannel1, 2, types.CommitPacket(packet)) }, false}, {"packet ack verification failed", func() { nextSeqRecv = 1 - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.UNORDERED, testConnectionIDA) suite.chainB.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainB.GetContext(), testPort1, testChannel1, 2, types.CommitPacket(packet)) @@ -111,12 +111,12 @@ func (suite *KeeperTestSuite) TestTimeoutExecuted() { var chanCap *capability.Capability testCases := []testCase{ {"success ORDERED", func() { - packet = types.NewPacket(newMockTimeoutPacket().GetBytes(), 1, testPort1, testChannel1, testPort2, testChannel2, 3) + packet = types.NewPacket(newMockTimeoutPacket().GetBytes(), 1, testPort1, testChannel1, testPort2, testChannel2, 3, disabledTimeoutTimestamp) suite.chainA.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, true}, {"channel not found", func() {}, false}, {"incorrect capability", func() { - packet = types.NewPacket(newMockTimeoutPacket().GetBytes(), 1, testPort1, testChannel1, testPort2, testChannel2, 3) + packet = types.NewPacket(newMockTimeoutPacket().GetBytes(), 1, testPort1, testChannel1, testPort2, testChannel2, 3, disabledTimeoutTimestamp) suite.chainA.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) chanCap = capability.NewCapability(1) }, false}, @@ -157,7 +157,7 @@ func (suite *KeeperTestSuite) TestTimeoutOnClose() { testCases := []testCase{ {"success", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.CreateClient(suite.chainA) suite.chainA.CreateClient(suite.chainB) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) @@ -169,24 +169,24 @@ func (suite *KeeperTestSuite) TestTimeoutOnClose() { }, true}, {"channel not found", func() {}, false}, {"packet dest port ≠ channel counterparty port", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort3, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"packet dest channel ID ≠ channel counterparty channel ID", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel3, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"connection not found", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"packet hasn't been sent", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) }, false}, {"channel verification failed", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.CreateClient(suite.chainA) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.UNORDERED, testConnectionIDA) @@ -194,7 +194,7 @@ func (suite *KeeperTestSuite) TestTimeoutOnClose() { suite.chainB.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(suite.chainB.GetContext(), testPort1, testChannel1, nextSeqRecv) }, false}, {"next seq receive verification failed", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.CreateClient(suite.chainA) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.ORDERED, testConnectionIDA) @@ -202,7 +202,7 @@ func (suite *KeeperTestSuite) TestTimeoutOnClose() { suite.chainB.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(suite.chainB.GetContext(), testPort1, testChannel1, nextSeqRecv) }, false}, {"packet ack verification failed", func() { - packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), 100) + packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp) suite.chainB.CreateClient(suite.chainA) suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connectionexported.OPEN) suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, exported.OPEN, exported.UNORDERED, testConnectionIDA) diff --git a/x/ibc/20-transfer/alias.go b/x/ibc/20-transfer/alias.go index 2999371ce3c7..ce6e26404978 100644 --- a/x/ibc/20-transfer/alias.go +++ b/x/ibc/20-transfer/alias.go @@ -12,20 +12,21 @@ import ( ) const ( - DefaultPacketTimeout = keeper.DefaultPacketTimeout - EventTypeTimeout = types.EventTypeTimeout - EventTypePacket = types.EventTypePacket - EventTypeChannelClose = types.EventTypeChannelClose - AttributeKeyReceiver = types.AttributeKeyReceiver - AttributeKeyValue = types.AttributeKeyValue - AttributeKeyRefundReceiver = types.AttributeKeyRefundReceiver - AttributeKeyRefundValue = types.AttributeKeyRefundValue - AttributeKeyAckSuccess = types.AttributeKeyAckSuccess - AttributeKeyAckError = types.AttributeKeyAckError - ModuleName = types.ModuleName - StoreKey = types.StoreKey - RouterKey = types.RouterKey - QuerierRoute = types.QuerierRoute + DefaultPacketTimeoutHeight = keeper.DefaultPacketTimeoutHeight + DefaultPacketTimeoutTimestamp = keeper.DefaultPacketTimeoutTimestamp + EventTypeTimeout = types.EventTypeTimeout + EventTypePacket = types.EventTypePacket + EventTypeChannelClose = types.EventTypeChannelClose + AttributeKeyReceiver = types.AttributeKeyReceiver + AttributeKeyValue = types.AttributeKeyValue + AttributeKeyRefundReceiver = types.AttributeKeyRefundReceiver + AttributeKeyRefundValue = types.AttributeKeyRefundValue + AttributeKeyAckSuccess = types.AttributeKeyAckSuccess + AttributeKeyAckError = types.AttributeKeyAckError + ModuleName = types.ModuleName + StoreKey = types.StoreKey + RouterKey = types.RouterKey + QuerierRoute = types.QuerierRoute ) var ( diff --git a/x/ibc/20-transfer/keeper/keeper.go b/x/ibc/20-transfer/keeper/keeper.go index 2fe9324736be..aa48454f8ca8 100644 --- a/x/ibc/20-transfer/keeper/keeper.go +++ b/x/ibc/20-transfer/keeper/keeper.go @@ -17,9 +17,12 @@ import ( supplyexported "github.com/cosmos/cosmos-sdk/x/supply/exported" ) -// DefaultPacketTimeout is the default packet timeout relative to the current block height const ( - DefaultPacketTimeout = 1000 // NOTE: in blocks + // DefaultPacketTimeoutHeight is the default packet timeout relative to the current block height + DefaultPacketTimeoutHeight = 1000 // NOTE: in blocks. Timeout disabled when set to 0. + + // DefaultPacketTimeoutTimestamp is the default packet timeout relative to the current block timestamp + DefaultPacketTimeoutTimestamp = 0 // NOTE: in nanoseconds. Timeout disabled when set to 0. ) // Keeper defines the IBC transfer keeper diff --git a/x/ibc/20-transfer/keeper/relay.go b/x/ibc/20-transfer/keeper/relay.go index 4dd57d9e496e..97f5682ac12b 100644 --- a/x/ibc/20-transfer/keeper/relay.go +++ b/x/ibc/20-transfer/keeper/relay.go @@ -134,7 +134,8 @@ func (k Keeper) createOutgoingPacket( sourceChannel, destinationPort, destinationChannel, - destHeight+DefaultPacketTimeout, + destHeight+DefaultPacketTimeoutHeight, + DefaultPacketTimeoutTimestamp, ) return k.channelKeeper.SendPacket(ctx, channelCap, packet) diff --git a/x/ibc/20-transfer/keeper/relay_test.go b/x/ibc/20-transfer/keeper/relay_test.go index 3102b553a301..58f9373ef2d4 100644 --- a/x/ibc/20-transfer/keeper/relay_test.go +++ b/x/ibc/20-transfer/keeper/relay_test.go @@ -141,7 +141,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() { }, true}, } - packet := channeltypes.NewPacket(data.GetBytes(), 1, testPort1, testChannel1, testPort2, testChannel2, 100) + packet := channeltypes.NewPacket(data.GetBytes(), 1, testPort1, testChannel1, testPort2, testChannel2, 100, 0) for i, tc := range testCases { tc := tc @@ -196,7 +196,7 @@ func (suite *KeeperTestSuite) TestOnAcknowledgementPacket() { }, false, false}, } - packet := channeltypes.NewPacket(data.GetBytes(), 1, testPort1, testChannel1, testPort2, testChannel2, 100) + packet := channeltypes.NewPacket(data.GetBytes(), 1, testPort1, testChannel1, testPort2, testChannel2, 100, 0) for i, tc := range testCases { tc := tc @@ -266,7 +266,7 @@ func (suite *KeeperTestSuite) TestOnTimeoutPacket() { }, true, false}, } - packet := channeltypes.NewPacket(data.GetBytes(), 1, testPort1, testChannel1, testPort2, testChannel2, 100) + packet := channeltypes.NewPacket(data.GetBytes(), 1, testPort1, testChannel1, testPort2, testChannel2, 100, 0) for i, tc := range testCases { tc := tc From 9ebd1c0f72b1b8372fe231ce05507eff733d9ae2 Mon Sep 17 00:00:00 2001 From: Colin Axner Date: Tue, 21 Apr 2020 16:12:31 -0700 Subject: [PATCH 05/12] add unit test and minor fixes --- x/ibc/03-connection/keeper/keeper_test.go | 49 +++++++++++++++++++++-- x/ibc/04-channel/keeper/packet.go | 20 +++++++-- x/ibc/04-channel/types/msgs_test.go | 2 +- x/ibc/04-channel/types/packet_test.go | 6 +-- x/ibc/20-transfer/keeper/keeper.go | 10 +++-- x/ibc/ante/ante_test.go | 6 +-- 6 files changed, 75 insertions(+), 18 deletions(-) diff --git a/x/ibc/03-connection/keeper/keeper_test.go b/x/ibc/03-connection/keeper/keeper_test.go index 13c03d1bf1fc..0e3ceffced69 100644 --- a/x/ibc/03-connection/keeper/keeper_test.go +++ b/x/ibc/03-connection/keeper/keeper_test.go @@ -36,6 +36,12 @@ const ( trustingPeriod time.Duration = time.Hour * 24 * 7 * 2 ubdPeriod time.Duration = time.Hour * 24 * 7 * 3 + + nextTimestamp = 10 // increment used for the next header's timestamp +) + +var ( + timestamp = time.Now() // starting timestamp for the client test chain ) type KeeperTestSuite struct { @@ -123,6 +129,44 @@ func (suite KeeperTestSuite) TestGetAllConnections() { suite.Require().ElementsMatch(expConnections, connections) } +// TestGetTimestampAtHeight verifies if the clients on each chain return the correct timestamp +// for the other chain. +func (suite *KeeperTestSuite) TestGetTimestampAtHeight() { + cases := []struct { + msg string + malleate func() + expPass bool + }{ + {"verification success", func() { + suite.chainA.CreateClient(suite.chainB) + // suite.chainB.CreateClient(suite.chainA) + }, true}, + {"client state not found", func() {}, false}, + } + + for i, tc := range cases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + // create and store a connection to chainB on chainA + connection := suite.chainA.createConnection(testConnectionIDA, testConnectionIDB, testClientIDB, testClientIDA, exported.OPEN) + suite.chainA.updateClient(suite.chainB) + + actualTimestamp, err := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetTimestampAtHeight( + suite.chainA.GetContext(), connection, uint64(suite.chainB.Header.Height), + ) + + if tc.expPass { + suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg) + suite.Require().EqualValues(uint64(suite.chainB.Header.Time.UnixNano()), actualTimestamp) + } else { + suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg) + } + }) + } +} + // TestChain is a testing struct that wraps a simapp with the latest Header, Vals and Signers // It also contains a field called ClientID. This is the clientID that *other* chains use // to refer to this TestChain. For simplicity's sake it is also the chainID on the TestChain Header @@ -139,9 +183,8 @@ func NewTestChain(clientID string) *TestChain { validator := tmtypes.NewValidator(privVal.GetPubKey(), 1) valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}) signers := []tmtypes.PrivValidator{privVal} - now := time.Now() - header := ibctmtypes.CreateTestHeader(clientID, 1, now, valSet, signers) + header := ibctmtypes.CreateTestHeader(clientID, 1, timestamp, valSet, signers) return &TestChain{ ClientID: clientID, @@ -314,7 +357,7 @@ func (chain *TestChain) createChannel( func nextHeader(chain *TestChain) ibctmtypes.Header { return ibctmtypes.CreateTestHeader(chain.Header.ChainID, chain.Header.Height+1, - time.Now(), chain.Vals, chain.Signers) + chain.Header.Time.Add(nextTimestamp), chain.Vals, chain.Signers) } func prefixedClientKey(clientID string, key []byte) []byte { diff --git a/x/ibc/04-channel/keeper/packet.go b/x/ibc/04-channel/keeper/packet.go index a4ebcb31cd3b..020a2c8d4797 100644 --- a/x/ibc/04-channel/keeper/packet.go +++ b/x/ibc/04-channel/keeper/packet.go @@ -79,7 +79,10 @@ func (k Keeper) SendPacket( // check if packet timeouted on the receiving chain latestHeight := clientState.GetLatestHeight() if packet.GetTimeoutHeight() != 0 && latestHeight >= packet.GetTimeoutHeight() { - return sdkerrors.Wrap(types.ErrPacketTimeout, "timeout height already passed on the receiving chain") + return sdkerrors.Wrapf( + types.ErrPacketTimeout, + "receiving chain block height >= packet timeout height (%d >= %d)", latestHeight, packet.GetTimeoutHeight(), + ) } latestTimestamp, err := k.connectionKeeper.GetTimestampAtHeight(ctx, connectionEnd, latestHeight) @@ -88,7 +91,10 @@ func (k Keeper) SendPacket( } if packet.GetTimeoutTimestamp() != 0 && latestTimestamp >= packet.GetTimeoutTimestamp() { - return sdkerrors.Wrap(types.ErrPacketTimeout, "timeout timestamp already passed on the receiving chain") + return sdkerrors.Wrapf( + types.ErrPacketTimeout, + "receiving chain block timestamp >= packet timeout timestamp (%d >= %d)", latestTimestamp, packet.GetTimeoutTimestamp(), + ) } nextSequenceSend, found := k.GetNextSequenceSend(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) @@ -179,12 +185,18 @@ func (k Keeper) RecvPacket( // check if packet timeouted by comparing it with the latest height of the chain if packet.GetTimeoutHeight() != 0 && uint64(ctx.BlockHeight()) >= packet.GetTimeoutHeight() { - return nil, sdkerrors.Wrapf(types.ErrPacketTimeout, "packet timeout height (%d) has been passed by the current block height (%d)", packet.GetTimeoutHeight(), uint64(ctx.BlockHeight())) + return nil, sdkerrors.Wrapf( + types.ErrPacketTimeout, + "block height >= packet timeout height (%d >= %d)", uint64(ctx.BlockHeight()), packet.GetTimeoutHeight(), + ) } // check if packet timeouted by comparing it with the latest timestamp of the chain if packet.GetTimeoutTimestamp() != 0 && uint64(ctx.BlockTime().UnixNano()) >= packet.GetTimeoutTimestamp() { - return nil, sdkerrors.Wrapf(types.ErrPacketTimeout, "packet timeout timestamp (%d) has been passed by the current block timestamp (%d)", packet.GetTimeoutTimestamp(), uint64(ctx.BlockTime().UnixNano())) + return nil, sdkerrors.Wrapf( + types.ErrPacketTimeout, + "block timestamp >= packet timeout timestamp (%d >= %d)", uint64(ctx.BlockTime().UnixNano()), packet.GetTimeoutTimestamp(), + ) } if err := k.connectionKeeper.VerifyPacketCommitment( diff --git a/x/ibc/04-channel/types/msgs_test.go b/x/ibc/04-channel/types/msgs_test.go index ddc5fdef82ae..87687c27d468 100644 --- a/x/ibc/04-channel/types/msgs_test.go +++ b/x/ibc/04-channel/types/msgs_test.go @@ -356,7 +356,7 @@ func (suite *MsgTestSuite) TestMsgChannelCloseConfirm() { var ( timeoutHeight = uint64(100) timeoutTimestamp = uint64(100) - invalidTimeout = uint64(0) + disabledTimeout = uint64(0) validPacketData = []byte("testdata") unknownPacketData = []byte("unknown") invalidAckData = []byte("123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890") diff --git a/x/ibc/04-channel/types/packet_test.go b/x/ibc/04-channel/types/packet_test.go index 5c08a26470d4..12c2e16a7a7f 100644 --- a/x/ibc/04-channel/types/packet_test.go +++ b/x/ibc/04-channel/types/packet_test.go @@ -18,9 +18,9 @@ func TestPacketValidateBasic(t *testing.T) { {NewPacket(validPacketData, 1, portid, invalidChannel, cpportid, cpchanid, timeoutHeight, timeoutTimestamp), false, "invalid source channel"}, {NewPacket(validPacketData, 1, portid, chanid, invalidPort, cpchanid, timeoutHeight, timeoutTimestamp), false, "invalid destination port"}, {NewPacket(validPacketData, 1, portid, chanid, cpportid, invalidChannel, timeoutHeight, timeoutTimestamp), false, "invalid destination channel"}, - {NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, invalidTimeout, invalidTimeout), false, "invalid timeout"}, - {NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, invalidTimeout, timeoutTimestamp), true, "timeout height 0 with valid timeout timestamp"}, - {NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, timeoutHeight, invalidTimeout), true, "timeout timestamp 0 with valid timeout height"}, + {NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, disabledTimeout, disabledTimeout), false, "disabled both timeout height and timestamp"}, + {NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, disabledTimeout, timeoutTimestamp), true, "disabled timeout height, valid timeout timestamp"}, + {NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, timeoutHeight, disabledTimeout), true, "disabled timeout timestamp, valid timeout height"}, {NewPacket(unknownPacketData, 1, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp), true, ""}, } diff --git a/x/ibc/20-transfer/keeper/keeper.go b/x/ibc/20-transfer/keeper/keeper.go index aa48454f8ca8..41a73503258b 100644 --- a/x/ibc/20-transfer/keeper/keeper.go +++ b/x/ibc/20-transfer/keeper/keeper.go @@ -18,11 +18,13 @@ import ( ) const ( - // DefaultPacketTimeoutHeight is the default packet timeout relative to the current block height - DefaultPacketTimeoutHeight = 1000 // NOTE: in blocks. Timeout disabled when set to 0. + // DefaultPacketTimeoutHeight is the default packet timeout height relative + // to the current block height. The timeout is disabled when set to 0. + DefaultPacketTimeoutHeight = 1000 // NOTE: in blocks - // DefaultPacketTimeoutTimestamp is the default packet timeout relative to the current block timestamp - DefaultPacketTimeoutTimestamp = 0 // NOTE: in nanoseconds. Timeout disabled when set to 0. + // DefaultPacketTimeoutTimestamp is the default packet timeout timestamp relative + // to the current block timestamp. The timeout is disabled when set to 0. + DefaultPacketTimeoutTimestamp = 0 // NOTE: in nanoseconds ) // Keeper defines the IBC transfer keeper diff --git a/x/ibc/ante/ante_test.go b/x/ibc/ante/ante_test.go index 72e20f398b4d..b323d68a82e0 100644 --- a/x/ibc/ante/ante_test.go +++ b/x/ibc/ante/ante_test.go @@ -86,7 +86,7 @@ func (suite *HandlerTestSuite) TestHandleMsgPacketOrdered() { suite.chainA.App.IBCKeeper.ChannelKeeper, )) - packet := channel.NewPacket(newPacket(12345).GetData(), 1, portid, chanid, cpportid, cpchanid, 100) + packet := channel.NewPacket(newPacket(12345).GetData(), 1, portid, chanid, cpportid, cpchanid, 100, 0) ctx := suite.chainA.GetContext() cctx, _ := ctx.CacheContext() @@ -145,7 +145,7 @@ func (suite *HandlerTestSuite) TestHandleMsgPacketUnordered() { var packet channeltypes.Packet for i := 0; i < 5; i++ { - packet = channel.NewPacket(newPacket(uint64(i)).GetData(), uint64(i), portid, chanid, cpportid, cpchanid, 100) + packet = channel.NewPacket(newPacket(uint64(i)).GetData(), uint64(i), portid, chanid, cpportid, cpchanid, 100, 0) suite.chainB.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainB.GetContext(), packet.SourcePort, packet.SourceChannel, uint64(i), channeltypes.CommitPacket(packet)) } @@ -157,7 +157,7 @@ func (suite *HandlerTestSuite) TestHandleMsgPacketUnordered() { for i := 10; i >= 0; i-- { cctx, write := suite.chainA.GetContext().CacheContext() - packet = channel.NewPacket(newPacket(uint64(i)).GetData(), uint64(i), portid, chanid, cpportid, cpchanid, 100) + packet = channel.NewPacket(newPacket(uint64(i)).GetData(), uint64(i), portid, chanid, cpportid, cpchanid, 100, 0) packetCommitmentPath := ibctypes.PacketCommitmentPath(packet.SourcePort, packet.SourceChannel, uint64(i)) proof, proofHeight := queryProof(suite.chainB, packetCommitmentPath) msg := channel.NewMsgPacket(packet, proof, uint64(proofHeight), addr1) From 20706ae522fc292fe432c5bc04aaea7a2b3709b4 Mon Sep 17 00:00:00 2001 From: Colin Axner Date: Tue, 21 Apr 2020 16:16:30 -0700 Subject: [PATCH 06/12] remove unnecessary code --- x/ibc/03-connection/keeper/keeper_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/x/ibc/03-connection/keeper/keeper_test.go b/x/ibc/03-connection/keeper/keeper_test.go index 0e3ceffced69..47c6505bbe42 100644 --- a/x/ibc/03-connection/keeper/keeper_test.go +++ b/x/ibc/03-connection/keeper/keeper_test.go @@ -139,7 +139,6 @@ func (suite *KeeperTestSuite) TestGetTimestampAtHeight() { }{ {"verification success", func() { suite.chainA.CreateClient(suite.chainB) - // suite.chainB.CreateClient(suite.chainA) }, true}, {"client state not found", func() {}, false}, } @@ -151,7 +150,6 @@ func (suite *KeeperTestSuite) TestGetTimestampAtHeight() { tc.malleate() // create and store a connection to chainB on chainA connection := suite.chainA.createConnection(testConnectionIDA, testConnectionIDB, testClientIDB, testClientIDA, exported.OPEN) - suite.chainA.updateClient(suite.chainB) actualTimestamp, err := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetTimestampAtHeight( suite.chainA.GetContext(), connection, uint64(suite.chainB.Header.Height), From dc5a13eba5c23fa0056c9213e7f20a71aa09d446 Mon Sep 17 00:00:00 2001 From: Colin Axner Date: Tue, 21 Apr 2020 16:40:00 -0700 Subject: [PATCH 07/12] code review fix --- x/ibc/03-connection/keeper/keeper.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x/ibc/03-connection/keeper/keeper.go b/x/ibc/03-connection/keeper/keeper.go index dc78fb4ee909..aa5eb5a8a133 100644 --- a/x/ibc/03-connection/keeper/keeper.go +++ b/x/ibc/03-connection/keeper/keeper.go @@ -65,19 +65,19 @@ func (k Keeper) SetConnection(ctx sdk.Context, connectionID string, connection t // GetTimestampAtHeight returns the timestamp of the consensus state at the // given height. -func (k Keeper) GetTimestampAtHeight(ctx sdk.Context, connection types.ConnectionEnd, height uint64) (timestamp uint64, err error) { +func (k Keeper) GetTimestampAtHeight(ctx sdk.Context, connection types.ConnectionEnd, height uint64) (uint64, error) { consensusState, found := k.clientKeeper.GetClientConsensusState( ctx, connection.GetClientID(), height, ) if !found { - return timestamp, sdkerrors.Wrapf( + return 0, sdkerrors.Wrapf( clienttypes.ErrConsensusStateNotFound, "clientID (%s), height (%d)", connection.GetClientID(), height, ) } - return consensusState.GetTimestamp(), err + return consensusState.GetTimestamp(), nil } // GetClientConnectionPaths returns all the connection paths stored under a From 3699e1ebe10685ed24437efc8796e3e1cc7b5f23 Mon Sep 17 00:00:00 2001 From: colin axner Date: Tue, 21 Apr 2020 16:40:36 -0700 Subject: [PATCH 08/12] Update x/ibc/03-connection/keeper/keeper.go Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- x/ibc/03-connection/keeper/keeper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/ibc/03-connection/keeper/keeper.go b/x/ibc/03-connection/keeper/keeper.go index aa5eb5a8a133..205019c9f4f3 100644 --- a/x/ibc/03-connection/keeper/keeper.go +++ b/x/ibc/03-connection/keeper/keeper.go @@ -63,7 +63,7 @@ func (k Keeper) SetConnection(ctx sdk.Context, connectionID string, connection t store.Set(ibctypes.KeyConnection(connectionID), bz) } -// GetTimestampAtHeight returns the timestamp of the consensus state at the +// GetTimestampAtHeight returns the timestamp in nanoseconds of the consensus state at the // given height. func (k Keeper) GetTimestampAtHeight(ctx sdk.Context, connection types.ConnectionEnd, height uint64) (uint64, error) { consensusState, found := k.clientKeeper.GetClientConsensusState( From e69c0ffdee792b7f410b2077662e7c03e00546ef Mon Sep 17 00:00:00 2001 From: colin axner Date: Wed, 22 Apr 2020 10:35:52 -0700 Subject: [PATCH 09/12] Update x/ibc/02-client/exported/exported.go Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- x/ibc/02-client/exported/exported.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/ibc/02-client/exported/exported.go b/x/ibc/02-client/exported/exported.go index e96c8f19a9ef..a071d94a02f4 100644 --- a/x/ibc/02-client/exported/exported.go +++ b/x/ibc/02-client/exported/exported.go @@ -103,7 +103,7 @@ type ConsensusState interface { // which is used for key-value pair verification. GetRoot() commitmentexported.Root - // GetTimestamp returns the timestamp of the consensus state + // GetTimestamp returns the timestamp (in nanoseconds) of the consensus state GetTimestamp() uint64 ValidateBasic() error From 28e4a4d1e886d026e972c24cf01ebbcc490605d4 Mon Sep 17 00:00:00 2001 From: colin axner Date: Wed, 22 Apr 2020 10:36:28 -0700 Subject: [PATCH 10/12] Update x/ibc/04-channel/types/packet.go Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- x/ibc/04-channel/types/packet.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/ibc/04-channel/types/packet.go b/x/ibc/04-channel/types/packet.go index c12ba033eee2..16c397ef38b0 100644 --- a/x/ibc/04-channel/types/packet.go +++ b/x/ibc/04-channel/types/packet.go @@ -35,7 +35,7 @@ type Packet struct { DestinationPort string `json:"destination_port" yaml:"destination_port"` // identifies the port on the receiving chain. DestinationChannel string `json:"destination_channel" yaml:"destination_channel"` // identifies the channel end on the receiving chain. TimeoutHeight uint64 `json:"timeout_height" yaml:"timeout_height"` // block height after which the packet times out - TimeoutTimestamp uint64 `json:"timeout_timestamp" yaml:"timeout_timestamp"` // block timestamp after which the packet times out + TimeoutTimestamp uint64 `json:"timeout_timestamp" yaml:"timeout_timestamp"` // block timestamp (in nanoseconds) after which the packet times out } // NewPacket creates a new Packet instance From 38cc9d29c97144cdd22e94a7a6cec52f5422892d Mon Sep 17 00:00:00 2001 From: colin axner Date: Wed, 22 Apr 2020 10:37:09 -0700 Subject: [PATCH 11/12] Update x/ibc/07-tendermint/types/consensus_state.go Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- x/ibc/07-tendermint/types/consensus_state.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/ibc/07-tendermint/types/consensus_state.go b/x/ibc/07-tendermint/types/consensus_state.go index f570e0575565..aecc7c981a8c 100644 --- a/x/ibc/07-tendermint/types/consensus_state.go +++ b/x/ibc/07-tendermint/types/consensus_state.go @@ -34,7 +34,7 @@ func (cs ConsensusState) GetHeight() uint64 { return cs.Height } -// GetTimestamp returns block time at which the consensus state was stored +// GetTimestamp returns block time in nanoseconds at which the consensus state was stored func (cs ConsensusState) GetTimestamp() uint64 { return uint64(cs.Timestamp.UnixNano()) } From 93efa8254f2d0ca516a2fcaff57199ca6231428a Mon Sep 17 00:00:00 2001 From: Colin Axner Date: Wed, 22 Apr 2020 10:51:25 -0700 Subject: [PATCH 12/12] return time.Time in error message --- x/ibc/04-channel/keeper/packet.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/x/ibc/04-channel/keeper/packet.go b/x/ibc/04-channel/keeper/packet.go index bf040fb534ed..4a35e8039460 100644 --- a/x/ibc/04-channel/keeper/packet.go +++ b/x/ibc/04-channel/keeper/packet.go @@ -3,6 +3,7 @@ package keeper import ( "bytes" "fmt" + "time" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -93,7 +94,7 @@ func (k Keeper) SendPacket( if packet.GetTimeoutTimestamp() != 0 && latestTimestamp >= packet.GetTimeoutTimestamp() { return sdkerrors.Wrapf( types.ErrPacketTimeout, - "receiving chain block timestamp >= packet timeout timestamp (%d >= %d)", latestTimestamp, packet.GetTimeoutTimestamp(), + "receiving chain block timestamp >= packet timeout timestamp (%s >= %s)", time.Unix(0, int64(latestTimestamp)), time.Unix(0, int64(packet.GetTimeoutTimestamp())), ) } @@ -195,7 +196,7 @@ func (k Keeper) RecvPacket( if packet.GetTimeoutTimestamp() != 0 && uint64(ctx.BlockTime().UnixNano()) >= packet.GetTimeoutTimestamp() { return nil, sdkerrors.Wrapf( types.ErrPacketTimeout, - "block timestamp >= packet timeout timestamp (%d >= %d)", uint64(ctx.BlockTime().UnixNano()), packet.GetTimeoutTimestamp(), + "block timestamp >= packet timeout timestamp (%s >= %s)", ctx.BlockTime(), time.Unix(0, int64(packet.GetTimeoutTimestamp())), ) }