MAID-1675: accumulate messages in the first hop #1213
Conversation
… sorted This resolves an issue where some lists of prefixes related to merging groups were not sorted, causing the merge test to fail sporadically.
r? @afck (maidsafe_highfive has picked a reviewer for you, use r? to override) |
} | ||
|
||
/// Appends the group list to the message, and removes all invalid signatures. | ||
pub fn add_group_list(&mut self, group_list: GroupList) { |
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.
Either add_group_list
and add_signature
should both check for whether the public key belongs to the group, or none of them should.
I'd vote for both.
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.
Ah - I missed that add_group_list()
was doing this.
The problem with checking is that we can receive the signatures and the actual SignedMessage
in random order, so when we receive a signature we maybe haven't added the group list yet, or vice-versa.
I suppose we could change the behaviour to fix the first case (e.g. have ability to call add_group_list()
multiple times for same group and only actually do the addition once - then we could call this when handling each incoming signature, or just pass the group list as an arg of add_signature/s()
), but I don't see a simple way round the "vice-versa" scenario.
I guess I'd be inclined to try and fix this in remove_invalid_signatures()
since when that's called we've definitely added the group and enough signatures. So I'd remove the check from here and instead add it to the existing check in remove_invalid_signatures()
. Does that sound OK?
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, that's fine.
(But checking it in add_signature
if there is a first group list would also work. Receiving the signatures before the message itself should already be handled correctly by the signature accumulator.)
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.
Right - of course!
I'll check it in add_signature()
then, since it dumps unneeded signatures earlier.
&hop_name, | ||
hop_msg.sent_to()) | ||
let HopMessage { mut content, route, sent_to, .. } = hop_msg; | ||
let hop_pub_ids = if let Some(group) = self.peer_mgr.routing_table().get_group(&hop_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.
We need to add our own name in there in case it's our own group.
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.
Well spotted.
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.
Thanks - although I'm the one who forgot this in the first place. 😁
/// The priority Crust should send this message with. | ||
pub fn priority(&self) -> u8 { | ||
self.content.priority() | ||
} | ||
|
||
/// Returns whether there are enough signatures from the sender. NOTE: to ensure only validated | ||
/// signatures are counted, first call `remove_invalid_signatures()`. |
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.
Is there any use for counting signatures including invalid ones? Maybe it would be a good idea to just call remove_invalid_signatures
in this function and not require callers to remember about it.
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.
The concern is the overhead of serialising the message each time remove_invalid_signatures()
is called.
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 see - makes sense.
self.content, | ||
self.public_id) | ||
self.signatures.len()) |
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 consider adding the list of names that signed the message, could be useful in debugging.
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.
Good point - I'll add that.
new_sent_to.clone(), | ||
target_peer_id)); | ||
let bytes = if send_sig { | ||
// Not our turn to send the full group message. Only send a hash. |
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.
The commend could probably use updating ;)
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.
Will do.
Authority::Client { .. } => true, | ||
} | ||
} | ||
|
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.
You can shortcut this (silly pattern, but still shorter):
if let *self == Authority::Client { .. } { true } else { false }
You could of course do the same with match
, unless an explicit match against other cases is required?
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.
Good point - I'll change to if let
.
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 personally find match
more readable (and easier to modify in the future if we add some other client type), but I won't argue ;)
This fixes an issue and adds a regression test for a bug in the 'impl_xorable_for_array' macro.
…ssage()' This fixes a bug which prevented any message from accumulating in the 'SignatureAccumulator'. It also adds a couple of basic unit tests for this struct, improves the debug output of 'RoutingTable' and implements 'Drop' for it so that all RTs will be logged in the case of a test panicking.
use std::time::Duration; | ||
use types::MessageId; | ||
use utils; | ||
use xor_name::XorName; | ||
|
||
/// The quroum, as a percentage of the group size. |
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.
Typo, should be quorum
. (My bad.)
src: Authority::ClientManager(name), | ||
dst: Authority::ClientManager(name), | ||
content: MessageContent::GetCloseGroup(MessageId::zero()), | ||
// Add a signature which will not correspond to an ID in the first group list. |
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 that comment should be a few lines further down, after creating the message.
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.
Yup - thanks.
.zip(env.other_ids.iter()) | ||
.foreach(|(signature_msg, full_id)| { | ||
let result = match *signature_msg { | ||
DirectMessage::MessageSignature(ref hash, ref sig) => { |
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.
Those ref
s are unnecessary, as the values are copied below anyway. (Or is this intentional, to make the copying more explicit?)
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.
No - they're just an oversight - I'll remove them.
&hop_name, | ||
hop_msg.sent_to()) | ||
let HopMessage { mut content, route, sent_to, .. } = hop_msg; | ||
let hop_pub_ids = if let Some(group) = self.peer_mgr.routing_table().get_group(&hop_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.
Thanks - although I'm the one who forgot this in the first place. 😁
// TODO - If the hop group is our own group, we should add our own ID in some cases here. | ||
// However, we can't always do this (e.g. the first node of a new network won't | ||
// handle any of the second node's requests since adding its own ID will stop it | ||
// from ever accumulating). |
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 the second node should only send the request as a ManagedNode
, and in that case we need to consider the message accumulated as soon as it has just one signature.
This causes 'core_tests::more_than_group_size_nodes()' to be ignored. Also addresses further review comments.
No description provided.