-
Notifications
You must be signed in to change notification settings - Fork 384
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
ICS3 handshake version negotiation problem #459
Comments
I see. Nice catch. I think this check is problematic anyways, since We can remove the
|
After further thoughts, the problem here seems more subtle.. In the current specification, due to the
Note that connOpenConfirm never needs to execute at any party. The basic problem is the symmetry of this protocol. It would be great if your suggestion above would fix it, but I'm not sure:
A principled fix would be to break this symmetry, preferably as early as possible in the handshake steps. For instance only one of the parties would be allowed to execute connOpenInit_ (may be based on simple lexicographical ordering). If only Alice can run connOpenInit, then no problem should ever arise. But I suspect this is not an option (?). A simpler fix (a hack) is to negotiate versions using an append-only set and then order those versions deterministically at each chain. If this sounds interesting, we can flesh out the exact details, but I would rather be in favor of the former solution. |
Yes, I agree. Per a separate discussion with Agoric we plan to revise the handshake so that the initiator can choose whether or not to fix the This doesn't address the split-brain problem you describe above, however. The only information we could rely on for some sort of asymmetry (e.g. lexicographical ordering) is the client state and/or identifiers, since the clients must already exist. Something along this line might be possible. Alternatively, we could add a fifth handshake datagram, which would allow confirming the version before marking the connection (thinking some more...) |
Ruminating on this ... the issue with adding an extra step to the handshake is that it will just result in a hung handshake (no progress) if versions are disagreed upon, since there is no way to reconcile them... |
if I understand correctly, the problem occurs when the local and counterparty versions intersection has more than one version. And, assuming a In general it seems that we need to specify a deterministic
could have a |
Yes; I think that would work, we just need to be careful that the relayer can't choose a different version, so both sides would need to enforce that |
Maybe we can get this without an extra handshake step.
Both lists are verified, and if the same |
... also, we should clearly articulate the symmetry of the handshake, ensure that it holds, and verify this property, it is quite useful. |
In the symmetric case there is no Why can't we do the "chain picks unique version from intersection..." on
agreed, hopefully we get a model for this (checking different solutions) soon. |
Yes, but that's fine because the second
Hmm, yes, that might work as well, we need to ensure that if both sides run steps 2 and 3 they still end up with the same version, but that should be possible to ensure by constraining the ranking function, I think. I think this logic is similar to what I proposed except that mutual cross-verification of version lists doesn't need to happen in the expected case, only the crossing-hellos case - so this is a bit more efficient, although slightly trickier to reason about.
💯 |
I like both solutions!
Agree. One logic is slightly simpler to understand, the other more to the point. Hopefully model checking will give us more certainty about their correctness.
Regarding this last part "If not, connection stays in INIT or TRYOPEN state," it will be useful to clarify that if versions do not intersect, then connection handshake hangs -- it's impossible to ensure liveness. So one of the assumptions of ICS3 that we should state clearly is that the sets of versions that the two handshaking chains provide (return values of |
PR ibc-rs/#211 documents our exploration of the solution candidates to fix this problem. In particular:
Next steps:
|
The most promising formulation of protocol symmetry is as follows: In the connection handshake, any party may attempt to take a protocol step (i.e., process a datagram from a relayer) based on any -- possibly outdated -- state of the other party. Not sure how clear this is. But it should capture the intuition that:
|
Interesting - this is not the sort of symmetry I had in mind, but it probably is a useful notion! The symmetry I had in mind is a symmetry between chains A and B, such that subsequent steps of a handshake "mirror" each other and A and B each perform the same computations and verify the same data on the other side - this is not a required property (and it is violated by "onTryDet", which is probably the handshake option we want to enact), but it is nice because it makes things simpler to reason about. For example, the version picking procedure in "onAckDet" is symmetric, since both chains verify the set of supported versions on the other chain and then run |
I see, neat! Not sure how to reconcile the fact that this symmetry property is "useful" and yet "violated" (by the "onTryDet" mode). The property I introduced above is satisfied by "onAckDet" and "onTryDet" but not as useful as this one... I guess we just leave this issue about symmetry in the backlog for the moment. |
Overview
It may be possible that the connection handshake protocol aborts at a chain during step connOpenTry if this chain previously executed step connOpenInit.
Execution example
Imagine the following scenario for establishing a connection between chains Alice and Bob, consisting of 4 steps:
chain Alice executes connOpenInit
ConnectionEnd
object where the fieldversion <- X
(X
is a list of versions that Alice supports, obtained fromgetCompatibleVersions()
)chain Bob executes connOpenInit
ConnectionEnd
object where the fieldversion <- Y
(Y
is the list of versions that Bob supports, obtained fromgetCompatibleVersions()
on Bob's side)a correct relayer constructs a connOpenTry datagram to further progress in the connection handshake
counterpartyVersions
in this datagram consists of listX
(again, this is the list of versions that Alice supports)chain Bob delivers and executes connOpenTry
ConnectionEnd
withversion === Y
(step 2 above)~~>
) fails:Further clarifications:
Bob aborts execution of connOpenTry only if
X =/= Y
, i.e., only if the two lists of versionsX
andY
returned fromgetCompatibleVersions()
are different at the two chains. If we assume that the two chains always return the same list of versions, then this handler should not abort, so there should not be a problem.Alice would also abort execution if she executes the connOpenTry handler by the same reasoning as above: Alice stores a
ConnectionEnd
object in the variableprevious
withversion === X
and she is comparing this againstY
.Fix
It seems that removing the verification
previous.version === version
would fix this problem.The text was updated successfully, but these errors were encountered: