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

TLA+ spec for packet delay #835

Merged
merged 10 commits into from
Apr 20, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ GetLatestHeight(chain) ==
chain.height

(***************************************************************************
Initial values of a channel end, chain store, accounts for ICS02
Initial values of a channel end, chain store, accounts for ICS20
***************************************************************************)
\* Initial value of a channel end:
\* - state is "OPEN" (we assume channel handshake has successfully finished)
Expand Down
4 changes: 2 additions & 2 deletions docs/spec/tla/ibc-core/ICS04PacketHandlers.tla
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ HandlePacketAck(chainID, chain, packetDatagram, log) ==
IF \* if the channel and connection ends are open for packet transmission
/\ channelEnd.state = "OPEN"
/\ connectionEnd.state = "OPEN"
\* if the packet committment exists in the chain store
/\ packetCommitment \in chain.packetCommittments
\* if the packet commitment exists in the chain store
/\ packetCommitment \in chain.packetCommitments
\* if the "PacketRecv" datagram has valid port and channel IDs
/\ packet.srcPortID = channelEnd.portID
/\ packet.srcChannelID = channelEnd.channelID
Expand Down
159 changes: 159 additions & 0 deletions docs/spec/tla/packet-delay/Chain.tla
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
------------------------------- MODULE Chain -------------------------------

EXTENDS Integers, FiniteSets, Sequences, ICS04PacketHandlers, IBCPacketDelayDefinitions

CONSTANTS
MaxHeight, \* maximal chain height
ChannelOrdering, \* indicate whether the channels are ordered or unordered
MaxPacketSeq, \* maximal packet sequence number
MaxDelay, \* maximal packet delay
ChainID \* a chain ID

VARIABLES
chainStore, \* chain store, containing client heights and a channel end
incomingPacketDatagrams, \* sequence of incoming packet datagrams
appPacketSeq, \* packet sequence number from the application on the chain
packetLog, \* packet log
packetDatagramTimestamp \* history variable that tracks when packet datagrams were processed

vars == <<chainStore, incomingPacketDatagrams, appPacketSeq, packetLog, packetDatagramTimestamp>>
Heights == 1..MaxHeight \* set of possible heights of the chains in the system

(***************************************************************************
Packet update operators
***************************************************************************)
\* Update the chain store and packet log with packet datagrams
(* @type: (Str, DATAGRAM, Seq(LOGENTRY)) =>
[chainStore: CHAINSTORE, packetLog: Seq(LOGENTRY), datagramTimestamp: <<Str, Int>> -> Int];
*)
PacketUpdate(chainID, packetDatagram, log) ==

LET packet == packetDatagram.packet IN
\* get the new updated store, packet log
LET packetUpdate ==
IF packetDatagram.type = "PacketRecv"
THEN HandlePacketRecv(chainID, chainStore, packetDatagram, MaxDelay, log, packetDatagramTimestamp)
ELSE IF packetDatagram.type = "PacketAck"
THEN HandlePacketAck(chainID, chainStore, packetDatagram, MaxDelay, log, packetDatagramTimestamp)
ELSE [chainStore |-> chainStore,
packetLog |-> log,
datagramTimestamp |-> packetDatagramTimestamp]
IN

LET packetUpdateStore == packetUpdate.chainStore IN

\* update height and timestamp
LET updatedStore ==
IF packetUpdateStore.height + 1 \in Heights
THEN [packetUpdateStore EXCEPT
!.height = packetUpdateStore.height + 1,
!.timestamp = packetUpdateStore.timestamp + 1]
ELSE [packetUpdateStore EXCEPT
!.timestamp = packetUpdateStore.timestamp + 1]
IN

[chainStore |-> updatedStore,
packetLog |-> packetUpdate.packetLog,
datagramTimestamp |-> packetUpdate.datagramTimestamp]

(***************************************************************************
Chain actions
***************************************************************************)
\* Advance the height of the chain until MaxHeight is reached
AdvanceChain ==
/\ chainStore.height + 1 \in Heights
/\ chainStore' = [chainStore EXCEPT
!.height = chainStore.height + 1,
!.timestamp = chainStore.timestamp + 1]
/\ UNCHANGED <<incomingPacketDatagrams, appPacketSeq, packetLog, packetDatagramTimestamp>>

\* handle the incoming packet datagrams
HandlePacketDatagrams ==
\* enabled if incomingPacketDatagrams is not empty
/\ incomingPacketDatagrams /= <<>>
/\ LET packetUpdate == PacketUpdate(ChainID, Head(incomingPacketDatagrams), packetLog) IN
/\ chainStore' = packetUpdate.chainStore
/\ packetLog' = packetUpdate.packetLog
/\ incomingPacketDatagrams' = Tail(incomingPacketDatagrams)
/\ packetDatagramTimestamp' = packetUpdate.datagramTimestamp
/\ UNCHANGED appPacketSeq

\* Send a packet
SendPacket ==
\* enabled if appPacketSeq is not bigger than MaxPacketSeq
/\ appPacketSeq <= MaxPacketSeq
\* Create packet
/\ LET packet == [
sequence |-> appPacketSeq,
timeoutHeight |-> MaxHeight,
srcPortID |-> chainStore.channelEnd.portID,
srcChannelID |-> chainStore.channelEnd.channelID,
dstPortID |-> chainStore.channelEnd.counterpartyPortID,
dstChannelID |-> chainStore.channelEnd.counterpartyChannelID] IN
\* update chain store with packet committment
/\ chainStore' = WritePacketCommitment(chainStore, packet)
\* log sent packet
/\ packetLog' = Append(packetLog,
[type |-> "PacketSent",
srcChainID |-> ChainID,
sequence |-> packet.sequence,
timeoutHeight |-> packet.timeoutHeight]
)
\* increase application packet sequence
/\ appPacketSeq' = appPacketSeq + 1
/\ UNCHANGED <<incomingPacketDatagrams, packetDatagramTimestamp>>



\* Acknowledge a packet
AcknowledgePacket ==
/\ chainStore.packetsToAcknowledge /= <<>>
\* write acknowledgements to chain store
/\ chainStore' = WriteAcknowledgement(chainStore, Head(chainStore.packetsToAcknowledge))
\* log acknowledgement
/\ packetLog' = LogAcknowledgement(ChainID, chainStore, packetLog, Head(chainStore.packetsToAcknowledge))
/\ UNCHANGED <<incomingPacketDatagrams, appPacketSeq, packetDatagramTimestamp>>

(***************************************************************************
Specification
***************************************************************************)
\* Initial state predicate
\* Initially
\* - the chain store is initialized to
\* InitChainStore(ChainID, ChannelOrdering, MaxDelay)
\* (defined in IBCPacketDelayDefinitions.tla)
\* - incomingPacketDatagrams is an empty sequence
\* - the appPacketSeq is set to 1
Init ==
/\ chainStore = InitChainStore(ChainID, Heights, ChannelOrdering, MaxDelay)
/\ incomingPacketDatagrams = <<>>
/\ appPacketSeq = 1

\* Next state action
\* The chain either
\* - advances its height
\* - receives datagrams and updates its state
\* - sends a packet
\* - acknowledges a packet
Next ==
\/ AdvanceChain
\/ HandlePacketDatagrams
\/ SendPacket
\/ AcknowledgePacket
\/ UNCHANGED vars

(***************************************************************************
Invariants
***************************************************************************)

\* type invariant
TypeOK ==
/\ chainStore \in ChainStores(Heights, ChannelOrdering, MaxPacketSeq)
/\ incomingPacketDatagrams \in Seq(Datagrams(Heights, MaxPacketSeq))
/\ appPacketSeq \in Int
/\ packetLog \in Seq(PacketLogEntries(Heights, MaxPacketSeq))

=============================================================================
\* Modification History
\* Last modified Mon Apr 19 15:44:24 CEST 2021 by ilinastoilkovska
\* Created Thu Dec 10 13:52:13 CET 2020 by ilinastoilkovska
12 changes: 12 additions & 0 deletions docs/spec/tla/packet-delay/IBCPacketDelay.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
CONSTANTS
MaxHeight = 3
ChannelOrdering = "UNORDERED"
MaxPacketSeq = 1
MaxDelay = 1

INIT Init
NEXT Next

INVARIANTS
TypeOK
Inv
Loading