diff --git a/contracts/javascore/ibc/src/main/java/ibc/ics04/channel/IBCPacket.java b/contracts/javascore/ibc/src/main/java/ibc/ics04/channel/IBCPacket.java index 3853c845e..903ad776f 100644 --- a/contracts/javascore/ibc/src/main/java/ibc/ics04/channel/IBCPacket.java +++ b/contracts/javascore/ibc/src/main/java/ibc/ics04/channel/IBCPacket.java @@ -230,9 +230,10 @@ public void _requestTimeout(MsgRequestTimeoutPacket msg) { boolean heightTimeout = revisionHeight.compareTo(BigInteger.ZERO) > 0 && BigInteger.valueOf(Context.getBlockHeight()) .compareTo(revisionHeight) >= 0; - boolean timeTimeout = packet.getTimeoutTimestamp().compareTo(BigInteger.ZERO) > 0 + BigInteger timeoutTimestamp = packet.getTimeoutTimestamp(); + boolean timeTimeout = timeoutTimestamp.compareTo(BigInteger.ZERO) > 0 && BigInteger.valueOf(Context.getBlockTimestamp()) - .compareTo(packet.getTimeoutTimestamp()) < 0; + .compareTo(timeoutTimestamp) >= 0; Context.require(heightTimeout || timeTimeout, "Packet has not yet timed out"); byte[] commitmentPath = IBCCommitment.packetCommitmentPath(packet.getSourcePort(), diff --git a/contracts/javascore/ibc/src/test/java/ibc/ics04/channel/PacketTest.java b/contracts/javascore/ibc/src/test/java/ibc/ics04/channel/PacketTest.java index a40a30f11..9c8d20efa 100644 --- a/contracts/javascore/ibc/src/test/java/ibc/ics04/channel/PacketTest.java +++ b/contracts/javascore/ibc/src/test/java/ibc/ics04/channel/PacketTest.java @@ -541,7 +541,7 @@ void requestTimeout_UnOrdered() { packet.invoke(owner, "setChannel", portId, channelId, baseChannel); Height timeoutHeight = new Height(); timeoutHeight.setRevisionHeight(BigInteger.valueOf(sm.getBlock().getHeight())); - MsgRequestTimeoutPacket timeoutPacket=new MsgRequestTimeoutPacket(); + MsgRequestTimeoutPacket timeoutPacket = new MsgRequestTimeoutPacket(); basePacket.setTimeoutHeight(timeoutHeight); basePacket.setTimeoutTimestamp(BigInteger.valueOf(sm.getBlock().getTimestamp())); byte[] commitmentPath = IBCCommitment.packetReceiptCommitmentKey(basePacket.getSourcePort(), @@ -563,7 +563,7 @@ void requestTimeout_Ordered() { packet.invoke(owner, "setChannel", portId, channelId, baseChannel); Height timeoutHeight = new Height(); timeoutHeight.setRevisionHeight(BigInteger.valueOf(sm.getBlock().getHeight())); - MsgRequestTimeoutPacket timeoutPacket=new MsgRequestTimeoutPacket(); + MsgRequestTimeoutPacket timeoutPacket = new MsgRequestTimeoutPacket(); basePacket.setTimeoutHeight(timeoutHeight); basePacket.setTimeoutTimestamp(BigInteger.valueOf(sm.getBlock().getTimestamp())); byte[] commitmentPath = IBCCommitment.nextSequenceRecvCommitmentKey(basePacket.getSourcePort(), @@ -579,6 +579,67 @@ void requestTimeout_Ordered() { ByteUtil.join(commitmentPath, Proto.encodeFixed64(basePacket.getSequence(), false))); } + @Test + void requestTimeout_timestamp() { + // Arrange + baseChannel.setOrdering(Channel.Order.ORDER_UNORDERED); + packet.invoke(owner, "setChannel", portId, channelId, baseChannel); + MsgRequestTimeoutPacket timeoutPacket = new MsgRequestTimeoutPacket(); + basePacket.setTimeoutTimestamp(BigInteger.valueOf(sm.getBlock().getTimestamp())); + byte[] commitmentPath = IBCCommitment.packetReceiptCommitmentKey(basePacket.getSourcePort(), + basePacket.getSourceChannel(), basePacket.getSequence()); + timeoutPacket.setPacket(basePacket.encode()); + timeoutPacket.setProofHeight(new byte[0]); + timeoutPacket.setProof(new byte[0]); + // Act + packet.invoke(owner, "_requestTimeout", timeoutPacket); + + // Assert + verify(packetSpy).sendBTPMessage(clientId, commitmentPath); + } + + @Test + void requestTimeout_NotYetTimedOut_Timestamp() { + // Arrange + baseChannel.setOrdering(Channel.Order.ORDER_UNORDERED); + packet.invoke(owner, "setChannel", portId, channelId, baseChannel); + MsgRequestTimeoutPacket timeoutPacket = new MsgRequestTimeoutPacket(); + basePacket.setTimeoutTimestamp(BigInteger.valueOf(sm.getBlock().getTimestamp()).multiply(BigInteger.TWO)); + byte[] commitmentPath = IBCCommitment.packetReceiptCommitmentKey(basePacket.getSourcePort(), + basePacket.getSourceChannel(), basePacket.getSequence()); + timeoutPacket.setPacket(basePacket.encode()); + timeoutPacket.setProofHeight(new byte[0]); + timeoutPacket.setProof(new byte[0]); + String expectedErrorMessage = "Packet has not yet timed out"; + + // Act + Executable beforeTimeout = () -> packet.invoke(owner, "_requestTimeout", timeoutPacket); + AssertionError e = assertThrows(AssertionError.class, beforeTimeout); + assertTrue(e.getMessage().contains(expectedErrorMessage)); + } + + @Test + void requestTimeout_NotYetTimedOut_Height() { + // Arrange + baseChannel.setOrdering(Channel.Order.ORDER_UNORDERED); + packet.invoke(owner, "setChannel", portId, channelId, baseChannel); + Height timeoutHeight = new Height(); + timeoutHeight.setRevisionHeight(BigInteger.valueOf(sm.getBlock().getHeight()).multiply(BigInteger.TWO)); + MsgRequestTimeoutPacket timeoutPacket = new MsgRequestTimeoutPacket(); + basePacket.setTimeoutHeight(timeoutHeight); + byte[] commitmentPath = IBCCommitment.packetReceiptCommitmentKey(basePacket.getSourcePort(), + basePacket.getSourceChannel(), basePacket.getSequence()); + timeoutPacket.setPacket(basePacket.encode()); + timeoutPacket.setProofHeight(new byte[0]); + timeoutPacket.setProof(new byte[0]); + String expectedErrorMessage = "Packet has not yet timed out"; + + // Act + Executable beforeTimeout = () -> packet.invoke(owner, "_requestTimeout", timeoutPacket); + AssertionError e = assertThrows(AssertionError.class, beforeTimeout); + assertTrue(e.getMessage().contains(expectedErrorMessage)); + } + @Test void timeoutPacket_unOrdered() { // Arrange