-
Notifications
You must be signed in to change notification settings - Fork 352
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
Basic packet flow in TLA+ #248
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice spec! I have a few comments after the first pass. Struggling with TLC, one relayer and minimal config, it still runs after almost 1hr.
\* Supports ICS2 (Clients), ICS3 (Connections), and ICS4 (Channels). | ||
UpdateChainStore(chainID, datagrams) == | ||
\* Supports ICS2 (Clients), ICS3 (Connections), and ICS4 (Channels & Packets). | ||
UpdateChainStoreAndPacketLog(chainID, datagrams, packetDatagrams, log) == |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should have a sequence of datagrams for everything. We can get handshake datagrams interleaved with packet datagrams and the order matters. And then in the function we should process them in order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I had the idea to transition to sequences of datagams completely. But doing so increases the state space that TLC enumerates. Will try to think about better handling, while still processing datagrams in order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with Anca that orders matter. We can have either sequence or handle only single datagram at the time.
Co-authored-by: Anca Zamfir <[email protected]>
Codecov Report
@@ Coverage Diff @@
## master #248 +/- ##
=========================================
+ Coverage 13.6% 34.1% +20.4%
=========================================
Files 69 106 +37
Lines 3752 7112 +3360
Branches 1374 2579 +1205
=========================================
+ Hits 513 2430 +1917
- Misses 2618 4318 +1700
+ Partials 621 364 -257
Continue to review full report at Codecov.
|
@@ -10,9 +10,12 @@ CONSTANTS MaxHeight, \* maximal chain height | |||
|
|||
VARIABLES chainStore, \* chain store, containing client heights, a connection end, a channel end | |||
incomingDatagrams, \* set of incoming datagrams | |||
history \* history variable | |||
incomingPacketDatagrams, \* sequence of incoming packet datagrams | |||
history, \* history variable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the purpose of history variable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use the history variable in the invariant we check with Apalache. The history variable is a record that stores flags about the state of the connection and channel ends. The flags are set once, when the state changes. The invariant checks that if a flag is set, the state of the connection or channel end does not go back to a previous state.
Example: a connection is open, and the flag history.connOpen
is set to TRUE
. The following invariant has to hold:
history.connOpen => /\ chainA.connectionEnd.state /= "UNINIT"
/\ chainA.connectionEnd.state /= "INIT"
/\ chainA.connectionEnd.state /= "TRYOPEN"
\* (Handler operators defined in PacketHandlers.tla) | ||
PacketUpdate(chainID, store, packetDatagrams, log) == | ||
\* if the sequence of packet datagrams is not empty | ||
IF packetDatagrams /= AsSeqPacketDatagrams(<<>>) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the structure is not the same as with others, i.e., it contains HandlePacketRecv
and HandlePacketAck
that internally check for the datagram type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is because the PacketUpdate
operator computes the update to the chain store with a single packet datagram, taken from the sequence of packet datagrams, while the other *Update
operators update the chain store with a set of datagrams, which is obtained by taking a subset of the incoming datagrams, containing datagrams of particular type.
docs/spec/relayer/Chain.tla
Outdated
Tail(chain.packetsToAcknowledge)] | ||
|
||
\* log acknowledgements to packet Log | ||
LogAcknowledgement(chain, log, packet) == |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if we need to model event log as it is not necessarily, i.e., current ICS18 is not using it. It might be useful as part of MBT, but in the initial version I would prefer having the minimal set of functionalities needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can have it merged like this for now, I will experiment to see if by removing it we can obtain some model checking results.
docs/spec/relayer/Chain.tla
Outdated
\* add a packet committment in the chain store, and increase nextSendSeq | ||
\/ /\ channelEnd.order = "ORDERED" | ||
/\ packet.sequence = channelEnd.nextSendSeq | ||
/\ packet.sequence <= MaxPacketSeq |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a model constraint, not the handler one; ideally they should not be mixed and model constraint can be a precondition at the higher level.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've refactored this action a bit.
@@ -156,6 +299,8 @@ Init == | |||
Next == | |||
\/ AdvanceChain | |||
\/ HandleIncomingDatagrams | |||
\/ SendPacket | |||
\/ AcknowledgePacket |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add timeout handling here? Then it seems complete.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, what about channel closing? Is it also triggered "externally"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
channel closing is triggered by the application so yes the trigger is "external"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We currently have a flag for each chain that triggers channel closing, which is non-deterministically set by the environment. When we add timeouts we would have channel closing that is triggered by a timeout.
docs/spec/relayer/PacketHandlers.tla
Outdated
\* Handle "PacketRecv" datagrams | ||
HandlePacketRecv(chainID, chain, packetDatagram, log) == | ||
\* get chainID's connection end | ||
LET connectionEnd == chain.connectionEnd IN |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering if we are missing important aspect here as we don't use chain and connection id from packetDatagram to fetch local connection and channel end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can check in lines 32-33
/\ packetDatagram.srcChannelID = channelEnd.channelID
/\ packetDatagram.dstChannelID = channelEnd.counterpartyChannelID
where channelEnd
is defined like in line 17. This should filter out packet datagrams that do not have the correct channelIDs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. There are few comments that could be addressed and few more general concerns that we can address later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Thanks Ilina!
* send packet action added, relayer packet creation * packet receive, ack * packet ack * readme updated * Apply suggestions from code review Co-authored-by: Anca Zamfir <[email protected]> * addressed comments * applied review comments * moved files around Co-authored-by: Anca Zamfir <[email protected]>
Closes: #124
Description
Added support for handling the basic packet flow in the Relayer TLA+ specification. Currently, the spec handles sending, receiving, and acknowledgements of packets.
The following basic packet flow is assumed:
ChainA
sends a packet by writing a sent packet log entry to the packet log and writing a packet commitmentPacketRecv
datagram forChainB
ChainB
processes thePacketRecv
datagram, and adds the received packet to its set of packets that should be acknowledged (asynchronous acknowledgements)ChainB
writes the acknowledgement by writing a log entry to the packet logPacketAck
datagram forChainA
ChainA
processes thePacketAck
datagram by deleting the packet commitment of the original sent packetThe packets and packet logs are sequences, rather than sets. This is to ensure that there is order in sending, receiving, and acknowledgements of packets.
For contributor use:
docs/
) and code commentsFiles changed
in the Github PR explorer