Skip to content
This repository has been archived by the owner on Jun 25, 2021. It is now read-only.

Commit

Permalink
feat: notify adult nodes with own section's adult list
Browse files Browse the repository at this point in the history
  • Loading branch information
maqi committed Apr 28, 2021
1 parent 4314a8a commit b4dddc0
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 20 deletions.
3 changes: 3 additions & 0 deletions examples/minimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,9 @@ async fn handle_event(index: usize, node: &mut Routing, event: Event) -> bool {
index, user, msg
),
Event::ClientLost(addr) => info!("Node #{} received ClientLost({:?})", index, addr),
Event::AdultsChanged(adult_list) => {
info!("Node #{} received AdultsChanged({:?})", index, adult_list)
}
}

true
Expand Down
3 changes: 3 additions & 0 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ pub enum Event {
},
/// Failed in sending a message to client, or connection to client is lost
ClientLost(SocketAddr),
/// Notify the current list of adult nodes, in case of churning.
AdultsChanged(BTreeSet<XorName>),
}

impl Debug for Event {
Expand Down Expand Up @@ -172,6 +174,7 @@ impl Debug for Event {
msg, user,
),
Self::ClientLost(addr) => write!(formatter, "ClientLost({:?})", addr),
Self::AdultsChanged(adult_list) => write!(formatter, "AdultsChanged({:?})", adult_list),
}
}
}
80 changes: 75 additions & 5 deletions src/routing/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1134,9 +1134,44 @@ impl Core {
return Ok(vec![]);
}

let old_adults: BTreeSet<_> = self
.section
.active_members()
.filter_map(|peer| {
if self.section.is_elder(peer.name()) {
None
} else {
Some(*peer.name())
}
})
.collect();

let snapshot = self.state_snapshot();
trace!(
"Updating knowledge of own section \n elders: {:?} \n members: {:?}",
section.elders_info(),
section.members()
);
self.section.merge(section)?;
self.network.merge(network, self.section.chain());

if !self.is_elder() {
let new_adults: BTreeSet<_> = self
.section
.active_members()
.filter_map(|peer| {
if self.section.is_elder(peer.name()) {
None
} else {
Some(*peer.name())
}
})
.collect();
if old_adults != new_adults {
self.send_event(Event::AdultsChanged(new_adults));
}
}

self.update_state(snapshot)
}

Expand Down Expand Up @@ -1662,6 +1697,8 @@ impl Core {
commands.extend(self.promote_and_demote_elders()?);
commands.push(self.send_node_approval(new_info, their_knowledge)?);

commands.extend(self.send_sync_to_adults()?);

self.print_network_stats();

Ok(commands)
Expand Down Expand Up @@ -1691,6 +1728,8 @@ impl Core {
commands.extend(self.relocate_peers(peer.name(), &signature)?);
commands.extend(self.promote_and_demote_elders()?);

commands.extend(self.send_sync_to_adults()?);

self.send_event(Event::MemberLeft {
name: *peer.name(),
age,
Expand Down Expand Up @@ -1877,7 +1916,6 @@ impl Core {
NodeElderChange::Promoted
} else if old.is_elder && !new.is_elder {
info!("Demoted");
self.section = self.section.trimmed(1);
self.network = Network::new();
self.section_keys_provider = SectionKeysProvider::new(KEY_CACHE_SIZE, None);
NodeElderChange::Demoted
Expand Down Expand Up @@ -1987,11 +2025,10 @@ impl Core {
.copied()
.partition(|peer| section.is_elder(peer.name()));

// Send the trimmed state to non-elders. The trimmed state contains only the latest
// section key and one key before that which is the key the recipients should know so they
// will be able to trust it.
// Send the trimmed state to non-elders. The trimmed state contains only the knowledge of
// own section.
let variant = Variant::Sync {
section: section.trimmed(2),
section: section.clone(),
network: Network::new(),
};
commands.push(send(variant, non_elders)?);
Expand All @@ -2004,6 +2041,39 @@ impl Core {
Ok(commands)
}

fn send_sync_to_adults(&mut self) -> Result<Vec<Command>> {
let send = |variant, recipients: Vec<_>| -> Result<_> {
trace!("Send {:?} to {:?}", variant, recipients);

let message =
Message::single_src(&self.node, DstLocation::Direct, variant, None, None)?;
let recipients: Vec<_> = recipients.iter().map(Peer::addr).copied().collect();

Ok(Command::send_message_to_nodes(
&recipients,
recipients.len(),
message.to_bytes(),
))
};

let mut commands = vec![];

let non_elders: Vec<_> = self
.section
.active_members()
.filter(|peer| !self.section.is_elder(peer.name()))
.copied()
.collect();

let variant = Variant::Sync {
section: self.section.clone(),
network: Network::new(),
};
commands.push(send(variant, non_elders)?);

Ok(commands)
}

fn send_relocate(&self, recipient: &Peer, details: RelocateDetails) -> Result<Vec<Command>> {
// We need to construct a proof that would be trusted by the destination section.
let known_key = self
Expand Down
5 changes: 2 additions & 3 deletions src/routing/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1403,14 +1403,13 @@ async fn handle_bounced_untrusted_sync() -> Result<()> {
let (elders_info, mut nodes) = create_elders_info();
let proven_elders_info = proven(sk2, elders_info.clone())?;
let section_full = Section::new(pk0, chain, proven_elders_info)?;
let section_trimmed = section_full.trimmed(2);

let (event_tx, _) = mpsc::unbounded_channel();
let node = nodes.remove(0);
let section_key_share = create_section_key_share(&sk2_set, 0);
let state = Core::new(
node.clone(),
section_full,
section_full.clone(),
Some(section_key_share),
event_tx,
);
Expand All @@ -1420,7 +1419,7 @@ async fn handle_bounced_untrusted_sync() -> Result<()> {
&node,
DstLocation::Direct,
Variant::Sync {
section: section_trimmed,
section: section_full,
network: Network::new(),
},
None,
Expand Down
13 changes: 1 addition & 12 deletions src/section/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,24 +173,13 @@ impl Section {
/// Update the member. Returns whether it actually changed anything.
pub fn update_member(&mut self, member_info: Proven<MemberInfo>) -> bool {
if !member_info.verify(&self.chain) {
error!("can't merge member {:?}", member_info.value);
return false;
}

self.members.update(member_info)
}

// Returns a trimmed version of this `Section` which contains only the elders info and the
// section chain truncated to the given length (the chain is truncated from the end, so it
// always contains the latest key). If `chain_len` is zero, it is silently replaced with one.
pub fn trimmed(&self, chain_len: usize) -> Self {
Self {
genesis_key: self.genesis_key,
elders_info: self.elders_info.clone(),
chain: self.chain.truncate(chain_len),
members: SectionPeers::default(),
}
}

pub fn chain(&self) -> &SectionChain {
&self.chain
}
Expand Down

0 comments on commit b4dddc0

Please sign in to comment.