Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ICS 04: fix timeout conditions for ordered (without/with allow timeout) channels #977

Conversation

crodriguezvega
Copy link
Contributor

closes: #965

@@ -964,7 +964,7 @@ function timeoutPacket(
// ordered channel: check that packet has not been received
// only allow timeout on next sequence so all sequences before the timed out packet are processed (received/timed out)
// before this packet times out
abortTransactionUnless(nextSequenceRecv == packet.sequence)
abortTransactionUnless(nextSequenceRecv <= packet.sequence)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See ibc-go.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think its clearer to write

abortTransactionUnless(packet.Sequence >= nextSequenceRecv)

switch channel.order {
case ORDERED:
// ordered channel: check that packet has not been received
abortTransactionUnless(nextSequenceRecv <= packet.sequence)
Copy link
Contributor Author

@crodriguezvega crodriguezvega May 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the ordered to match what the implementation does and what the spec also does for regular packet timeouts.


// NOTE: For ORDERED_ALLOW_TIMEOUT, the relayer must first attempt the receive on the destination chain
// before the timeout receipt can be written and subsequently proven on the sender chain in timeoutPacket
case ORDERED_ALLOW_TIMEOUT:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I split ORDERED and ORDERED_ALLOW_TIMEOUT because conditions are different.

// only allow timeout on next sequence so all sequences before the timed out packet are processed (received/timed out)
// before this packet times out
abortTransactionUnless(nextSequenceRecv == packet.sequence)
abortTransactionUnless(nextSequenceRecv > packet.sequence)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For both packet timeouts and for timeout on close the nextSequenceRecv on the counterparty would have been incremented by one before the timeout receipt is written.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this was correct as it was

Copy link
Contributor Author

@crodriguezvega crodriguezvega Jun 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for changing it is that in line 709 inside recvPacket the nextSequenceRecv is incremented by 1 before the timeout receipt is written:

nextSequenceRecv = nextSequenceRecv + 1
provableStore.set(nextSequenceRecvPath(packet.destPort, packet.destChannel), nextSequenceRecv)

So if I relayer tries to timeout the packet, the nextSequenceRecv in the timeout message will be > than packet.sequence, won't it?

Same thing for the condition checked in timeoutOnClose.

Is this reasoning correct, @AdityaSripal?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AdityaSripal for timing out a packet if the channel is open, should the condition still be that the relayer must attempt to receive the packet (as the comment above this line says)? If that's the case, then I guess it's ok to not support the situation where packet.sequence is >= nextSequenceRecv.

@@ -964,7 +964,7 @@ function timeoutPacket(
// ordered channel: check that packet has not been received
// only allow timeout on next sequence so all sequences before the timed out packet are processed (received/timed out)
// before this packet times out
abortTransactionUnless(nextSequenceRecv == packet.sequence)
abortTransactionUnless(nextSequenceRecv <= packet.sequence)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think its clearer to write

abortTransactionUnless(packet.Sequence >= nextSequenceRecv)

// only allow timeout on next sequence so all sequences before the timed out packet are processed (received/timed out)
// before this packet times out
abortTransactionUnless(nextSequenceRecv == packet.sequence)
abortTransactionUnless(nextSequenceRecv > packet.sequence)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this was correct as it was

// NOTE: For ORDERED_ALLOW_TIMEOUT, the relayer must first attempt the receive on the destination chain
// before the timeout receipt can be written and subsequently proven on the sender chain in timeoutPacket
case ORDERED_ALLOW_TIMEOUT:
abortTransactionUnless(nextSequenceRecv > packet.sequence)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be an equals

// only allow timeout on next sequence so all sequences before the timed out packet are processed (received/timed out)
// before this packet times out
abortTransactionUnless(nextSequenceRecv == packet.sequence)
abortTransactionUnless(nextSequenceRecv > packet.sequence)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AdityaSripal for timing out a packet if the channel is open, should the condition still be that the relayer must attempt to receive the packet (as the comment above this line says)? If that's the case, then I guess it's ok to not support the situation where packet.sequence is >= nextSequenceRecv.

// Otherwise, if packet.sequence < nextSequenceRecv, then the relayer has attempted
// to receive the packet on the destination chain, and nextSequenceRecv has been incremented.
// In this situation, verify the presence of timeout receipt.
if packet.sequence < nextSequenceRecv {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If packet.sequence >= nextSequenceRecv, then timeout, otherwise verify there is a timeout receipt.

// only allow timeout on next sequence so all sequences before the timed out packet are processed (received/timed out)
// before this packet times out
abortTransactionUnless(nextSequenceRecv == packet.sequence)
abortTransactionUnless(packet.sequence < nextSequenceRecv)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AdityaSripal if a channel is open and the relayer must first attempt to receive the packet on destination chain, I guess it is ok to assume that nextSequenceRecv will have been incremented and therefore is > packet.sequence?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No we will actually want the equals here because I think it makes sense to enforce that timeout happens in order as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the condition be then abortTransactionUnless(packet.sequence == nextSequenceRecv - 1) since nextSequenceRecv will have been incremented when attempting to receive packet with packet.sequence?

Copy link
Member

@AdityaSripal AdityaSripal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Carlos, I think its still important to ensure ordering in the timeout logic. Perhaps we should even add this to timeoutOnClose. Also I believe the else clause in the ordered_allow_timeout case is missing.

// only allow timeout on next sequence so all sequences before the timed out packet are processed (received/timed out)
// before this packet times out
abortTransactionUnless(nextSequenceRecv == packet.sequence)
abortTransactionUnless(packet.sequence < nextSequenceRecv)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No we will actually want the equals here because I think it makes sense to enforce that timeout happens in order as well.

@@ -1190,8 +1190,7 @@ function timeoutPacket(
// ordered channel: check that packet has not been received
// only allow timeout on next sequence so all sequences before the timed out packet are processed (received/timed out)
// before this packet times out
abortTransactionUnless(nextSequenceRecv == packet.sequence)

abortTransactionUnless(packet.sequence >= nextSequenceRecv)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again I think this should remain as is. It would enforce that the only packet that gets timed out is the first in line

Copy link
Member

@AdityaSripal AdityaSripal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @crodriguezvega !

@AdityaSripal AdityaSripal merged commit cd6ae64 into main Nov 1, 2023
2 checks passed
@AdityaSripal AdityaSripal deleted the carlos/965-ics04-something-confusing-about-function-timeoutpacket-and-timeoutonclose branch November 1, 2023 15:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Backlog
Development

Successfully merging this pull request may close these issues.

ICS04: Something confusing about function timeoutPacket and timeoutOnClose
2 participants