-
Notifications
You must be signed in to change notification settings - Fork 1
Add StaticRound
to eliminate some boilerplate when writing protocols
#117
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
Conversation
I have skimmed the code, so this is not a review. Thoughts:
Given the above I think we should provide either dynamic or static rounds, but not both. When we have a concrete use case that requires both dynamic and static we can re-assess. Is switching to only static rounds possible? It'd be interesting to see how |
For protocols themselves, yes, but evidence verification is not limited to one round and needs access to the message types from the previous rounds - so the user would have to manually transform them from some untyped form to typed messages. Although it is possible to automate deserialization (and the handling of its errors) - by making every This would need some kind of "routing" of round number -> boxed round type (not the round object, since we don't need the round state for that). This may be also used to simplify evidence checking for invalid messages (#82). |
8de19fb
to
0ef0c98
Compare
Pull Request Test Coverage Report for Build 17362353327Details
💛 - Coveralls |
Current roadblock: handling protocols where some nodes do not send or do not receive messages (e.g. KeyResharing). This means that the type of the round is not enough to determine whether a message is expected, it's also the state that's needed. In the n-of-n case the static rounds eliminate the need for |
dc0371a
to
fa2028b
Compare
2b67199
to
49bb410
Compare
733fd6b
to
9ff447c
Compare
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.
Another partial review.
@@ -217,6 +200,14 @@ impl Round<DinerId> for Round1 { | |||
|
|||
impl Round<DinerId> for Round2 { | |||
type Protocol = DiningCryptographersProtocol; | |||
type ProtocolError = NoProtocolErrors<Self>; |
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.
Naming nitpick: the associated type is in the singular, so it's a bit odd to assign a value whose name is plural. OTOH calling it "NoProtocolError" isn't great either. Not sure there is a great solution to be found here (idiomatically it should really be ()
but that isn't possible as we saw above).
Maybe DummyProtocolError
?
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.
A random thought I had:
I wonder how far we'd be able to get if we changed the Round
trait to make the type ProtocolError
take a impl core::error::Error
. Maybe then we could impl Round
with ()
as the error type when there are no errors, but then we'd need some clever trick to transform or cast the impl core::error::Error
into an actual ProtocolError
with all the methods and trait bounds we need.
I read through rust-lang/rust#99301 which seems to be about ways to access data from nested errors in a generic way. Seems a bit stuck though.
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.
Maybe we can instead rename the associated type to ProtocolErrors
?
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.
But wouldn't the plural on a type name imply that it is a collection of types of protocol errors?
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 tried to impl ProtocolError
for core::convert::Infallible
(described as "The error type for errors that can never happen." in the docs) and it kinda works if it wasn't for the ser/deser bounds on ProtocolError
. That's sort of what I was trying to hint at by saying "it'd be so nice if we could use a impl core::error::Error and then – handwaves – transfom/cast to concrete error types": we could have less bounds.
Anyway, all of this is nitpicking. The code is fine as-is, modulo perhaps the name.
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.
Maybe we can instead rename the associated type to
ProtocolErrors
?
This is better.
I still think it's awkward that there isn't a better way to do this but that has nothing to do with this PR.
@@ -217,6 +200,14 @@ impl Round<DinerId> for Round1 { | |||
|
|||
impl Round<DinerId> for Round2 { | |||
type Protocol = DiningCryptographersProtocol; | |||
type ProtocolError = NoProtocolErrors<Self>; |
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.
Maybe we can instead rename the associated type to
ProtocolErrors
?
This is better.
I still think it's awkward that there isn't a better way to do this but that has nothing to do with this PR.
Most of the stuff seems to be addressed, what's left is the naming. To summarize various comments, the problematic parts are:
|
For this, like for |
I don't have a strong opinion on this. The conservative option is to move it to |
Renamed
We still have to care, |
Still thinking about this. |
bddb986
to
36fa0f8
Compare
Riiiiight, but would a breaking change here automatically imply a major release? If it's in combinators then that would be the case for sure. If it's in |
Main changes:
Round
now uses associated types for messages, payloads, and artifacts. Fixes TypedRound
trait #65. Most dynamic parts (BoxedFormat
,ProtocolMessagePart
, serialization/deserialization of messages etc) are hidden from the user.Protocol
to correspondingRound
implementors. This allows one to keep the related logic (receive_message()
and evidence verification) together.Corollary changes:
synedrion
#113 are rendered unnecessary (e.g. map-downcast). Need to re-evaluate after this PR is merged.verify_*_is_invalid
methods #105, fixes Simplify invalid message evidence verification #82 (it now happens inDynRound
impl forRound
types).AssociatedData
is renamed toSharedData
and is now an associated type ofProtocol
instead ofProtocolError
. This helps Uniformize associated data and entry point inputs #89, but does not close it yet.ProtocolError
mandatesDisplay
#114 (ProtocolError
now usesdescription()
instead ofDisplay
)BoxedRound::new_dynamic
to justnew
#112 (fix included in this PR)#61 and #62 need to be reconsidered - while writing an extended/zipped protocol is easier with static rounds, the evidence verification is complicated since one needs to cast
EvidenceMessages
to the inner protocol type somehow.