-
Notifications
You must be signed in to change notification settings - Fork 1
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
Logic fixes for rounds with partial echo #67
Conversation
Pull Request Test Coverage Report for Build 11864171410Details
💛 - Coveralls |
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'm struggling a bit to review this. The code seems all ok, modulo nitpicks, but I'm kind of stuck in my head on why we need this (despite the great PR description). E.g. in the partial_echo
test, how should I think about a real world scenario there? Would node 0 be like a "dealer" of some sort, broadcasting but not participating? And what would node 4 be, given it's not participating at all?
pub(crate) struct EchoRoundInfo<Verifier> { | ||
pub(crate) message_destinations: BTreeSet<Verifier>, | ||
pub(crate) expecting_messages_from: BTreeSet<Verifier>, | ||
pub(crate) expected_echos: BTreeSet<Verifier>, |
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 expecting_echos_from
for consistency with expecting_message_from
?
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 would be a little ambiguous I think. expected_echos
is the set of echos you're expecting to find in a pack that's sent to you (from any node), and expecting_echos_from
could be understood as the nodes that need to send the echo packs to you. These can be different.
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.
Hmm. Maybe just echoes
works then?
/// The default behavior: sends broadcasts and receives echoed messages, or does neither. | ||
/// | ||
/// That is, this node will be a part of the echo round if [`Round::make_echo_broadcast`] generates a message. | ||
Default, |
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.
Would Full
be a good name here? It doesn't fully capture the semantics but is at least a hint in the right direction whereas "default" doesn't mean anything unless the reader knows what the default is.
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.
Funny you should say that, Full
was the original name I had here :) But I changed it to Default
because it also covers the nodes which don't send or receive anything (node 4 in the test), where I wasn't sure Full
was intuitive.
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.
Full
isn't perfect, but gives a hint to the right understanding. I like it better than Default
.
We could go with a FullOrAbsent
but that reads very confusingly. :)
This is the exact scenario of what's happening during KeyResharing. There is a set of nodes that sends broadcasts, and there is a set of nodes that receives broadcasts, and these sets are not equal (maybe not even intersecting). The ones that send broadcasts are the old holders of key shares, and the receivers are the new holders. The assumption I'm making here is that only the "target" nodes will need to participate in the echo round, making sure they each received the same messages; the senders can do without.
The node 4 is just to cover all possibilities, that's something that doesn't happen during KeyResharing. |
manul/Cargo.toml
Outdated
@@ -20,6 +20,7 @@ rand_core = { version = "0.6.4", default-features = false } | |||
tracing = { version = "0.1", default-features = false } | |||
displaydoc = { version = "0.2", default-features = false } | |||
derive-where = "1" | |||
smallvec = { version = "1", default-features = false, features = ["serde"] } |
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.
There's an argument to prefer tinyvec
to smallvec
, given the former has a "no unsafe" policy (and the latter has had a few memory related bugs over the years).
Another tangential thought: RustCrypto use the hybrid_array so we probably have it in the dependency tree. I haven't looked into it but perhaps it can be used here too?
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.
hybrid_array
deals exclusively with stack arrays, I think.
manul/src/protocol/round.rs
Outdated
/// A round identifier. | ||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] |
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's too bad SmallVec isn't Copy
. :/
f7ac30f
to
437c803
Compare
Fixes #21
Imagine the following round configuration (which is possible during KeyResharing from
synedrion
):After we received the initial broadcasts, we want an echo round where the nodes 1, 2, 3 echo received messages to each other. That is:
(note that node 1 does not send its broadcast the second time; that would be pointless)
This requires adding another method to
Round
specifying the exact behavior of the node, since this information cannot be obtained from existing methods. This PR introducesRound::echo_round_participation()
andEchoRoundParticipation
enum.In most cases we can use the blanket implementation returning
EchoRoundParticipation
, which means that the node either sends and receives echo messages, or does neither. This means that we can deduce the properties of the echo round fromRound::message_destinations()
andRound::expecting_messages_from()
. The case where the node only sends echo messages (node 0), we don't need any additional info other than this fact. For the case where the node only receives echo messages (node 3), it needs additional info specifying which nodes actually participate in the echo round.Edit: another possible API here is to get rid of
EchoRoundParticipation
enum and instead have a method returningOption<BTreeSet<Id>>
.None
would cover bothDefault
andSend
, and we will distinguish between them by checking ifexpecting_messages_from()
is empty or not. Would that work?