-
Notifications
You must be signed in to change notification settings - Fork 357
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
Add error handling logic to relayer spec #236
Conversation
Codecov Report
@@ Coverage Diff @@
## master #236 +/- ##
=========================================
+ Coverage 13.6% 37.6% +23.9%
=========================================
Files 69 79 +10
Lines 3752 5652 +1900
Branches 1374 1870 +496
=========================================
+ Hits 513 2127 +1614
- Misses 2618 3318 +700
+ Partials 621 207 -414
Continue to review full report at Codecov.
|
|
||
if channel == nil OR channel.state != OPEN { (nil, Error.RETRY) } | ||
// TODO: Maybe we shouldn't even enter handle loop for packets if the corresponding channel is not open! |
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 but I think here is the first time when we can make that determination.
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 I meant here is basically having supervisor logic that would decide when to call handleEvent based on event type, i.e., there would be some preconditions that are based on relayer state. For example, packet related events are preconditioned on channel and connections being open, all events are preconditioned on light client correctly installed, etc.
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.
Does this assume that the relayer keeps state for channel and connections? And the supervisor does not perform any queries to determine that. Trying to save on the number of queries :)
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.
Exactly. Supervisor will need anyway to keep some state (for example for pending packets so it can trigger timeouts), so why not keeping status of connections and channels, current block height and time, etc. It can save queries and potentially operates faster.
docs/spec/relayer/Relayer.md
Outdated
1. Determine destination chain (`chainB`) | ||
2. Updates (on `chainB`) the IBC client for `chainA` to a certain height `H` where `H >= h+1`. | ||
3. Create IBC datagram at height `H-1`. | ||
4. Submit the datagram from stage (2) to `chainB`. |
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.
4. Submit the datagram from stage (2) to `chainB`. | |
4. Submit the datagram from stage (3) to `chainB`. |
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 great! A few comments looking for modularizing a bit the checks so the pseudocode is easier to read, if possible.
|
||
if channel == nil OR channel.state != OPEN { (nil, Error.RETRY) } | ||
// TODO: Maybe we shouldn't even enter handle loop for packets if the corresponding channel is not open! |
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.
Does this assume that the relayer keeps state for channel and connections? And the supervisor does not perform any queries to determine that. Trying to save on the number of queries :)
// Fetch channelEnd from the chainA to be able to compute port and chain ids on destination chain | ||
channelA, proof, error = GetChannel(chainA, ev.port, ev.channel, ev.height) | ||
if error != nil { return (nil, error) } | ||
|
||
channelB, proof, error = | ||
GetChannel(chainB, channelA.counterpartyPortIdentifier, channelA.counterpartyChannelIdentifier, LATEST_HEIGHT) | ||
if error != nil { return (nil, error) } | ||
|
||
if channelB == nil OR channel.state != OPEN { (nil, Error.DROP) } | ||
// Note that we checked implicitly above that counterparty identifiers match each other | ||
|
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.
Are these channel retrievals and checks the same as for the SendPacket event above? If yes can we make a single function for this? If not maybe we cover the differences and why they are.
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.
Checks are similar, but error message is different. With recv packets we can retry on error (if connection and channel are not open) while for acks we should drop event in this case. We can make a function for this (and we should at the code level) but at the spec level maybe it's better making it more verbose so reading it is easier.
connectionId = channelB.connectionHops[0] | ||
connection, proof, error = GetConnection(chainB, connectionId, LATEST_HEIGHT) | ||
if error != nil { return (nil, error) } | ||
|
||
if connection == nil OR connection.state != OPEN { return (nil, Error.DROP) } |
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.
same question here.
packetCommitment, packetCommitmentProof, error = | ||
GetPacketCommitment(chainB, channelA.counterpartyPortIdentifier, | ||
channelA.counterpartyChannelIdentifier, ev.sequence, LATEST_HEIGHT) | ||
if error != nil { return (nil, error) } | ||
|
||
if packetCommitment == nil OR | ||
packetCommitment != hash(concat(ev.data, ev.timeoutHeight, ev.timeoutTimestamp)) { | ||
// invalid event; bad provider | ||
return (nil, Error.BADPROVIDER) | ||
} | ||
|
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.
same here
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 Zarko!
Add error handling and reorganise the spec
Fixes #234 and #237.