use crate::{peer::PeerUtils, Prefix, XorName};
use bls::PublicKey;
use sn_data_types::ReplicaPublicKeySet;
use sn_messaging::{
node::{ElderCandidates, Peer},
SectionAuthorityProvider,
};
use std::{
collections::{BTreeMap, BTreeSet},
net::SocketAddr,
};
pub trait ElderCandidatesUtils {
fn new<I: IntoIterator<Item = Peer>>(elders: I, prefix: Prefix) -> Self;
fn peers(&'_ self) -> Box<dyn Iterator<Item = Peer> + '_>;
fn position(&self, name: &XorName) -> Option<usize>;
}
impl ElderCandidatesUtils for ElderCandidates {
fn new<I>(elders: I, prefix: Prefix) -> Self
where
I: IntoIterator<Item = Peer>,
{
Self {
elders: elders
.into_iter()
.map(|peer| (*peer.name(), *peer.addr()))
.collect(),
prefix,
}
}
fn peers(&'_ self) -> Box<dyn Iterator<Item = Peer> + '_> {
Box::new(self.elders.iter().map(|(name, addr)| {
let mut peer = Peer::new(*name, *addr);
peer.set_reachable(true);
peer
}))
}
fn position(&self, name: &XorName) -> Option<usize> {
self.elders.keys().position(|other_name| other_name == name)
}
}
pub trait SectionAuthorityProviderUtils {
fn new<I: IntoIterator<Item = Peer>>(
elders: I,
prefix: Prefix,
pk_set: ReplicaPublicKeySet,
) -> Self;
fn from_elder_candidates(
elder_candidates: ElderCandidates,
pk_set: ReplicaPublicKeySet,
) -> SectionAuthorityProvider;
fn elder_candidates(&self) -> ElderCandidates;
fn peers(&'_ self) -> Box<dyn Iterator<Item = Peer> + '_>;
fn elder_count(&self) -> usize;
fn contains_elder(&self, name: &XorName) -> bool;
fn get_addr(&self, name: &XorName) -> Option<SocketAddr>;
fn names(&self) -> BTreeSet<XorName>;
fn elders(&self) -> BTreeMap<XorName, SocketAddr>;
fn addresses(&self) -> Vec<SocketAddr>;
fn prefix(&self) -> Prefix;
fn section_key(&self) -> PublicKey;
}
impl SectionAuthorityProviderUtils for SectionAuthorityProvider {
fn new<I>(elders: I, prefix: Prefix, pk_set: ReplicaPublicKeySet) -> Self
where
I: IntoIterator<Item = Peer>,
{
let elders = elders
.into_iter()
.map(|peer| (*peer.name(), *peer.addr()))
.collect();
Self {
prefix,
public_key_set: pk_set,
elders,
}
}
fn from_elder_candidates(
elder_candidates: ElderCandidates,
pk_set: ReplicaPublicKeySet,
) -> SectionAuthorityProvider {
let elders = elder_candidates
.elders
.iter()
.map(|(name, addr)| (*name, *addr))
.collect();
SectionAuthorityProvider {
prefix: elder_candidates.prefix,
public_key_set: pk_set,
elders,
}
}
fn elder_candidates(&self) -> ElderCandidates {
ElderCandidates {
elders: self.elders(),
prefix: self.prefix,
}
}
fn peers(&'_ self) -> Box<dyn Iterator<Item = Peer> + '_> {
Box::new(self.elders.iter().map(|(name, addr)| {
let mut peer = Peer::new(*name, *addr);
peer.set_reachable(true);
peer
}))
}
fn elder_count(&self) -> usize {
self.elders.len()
}
fn contains_elder(&self, name: &XorName) -> bool {
self.elders.contains_key(name)
}
fn get_addr(&self, name: &XorName) -> Option<SocketAddr> {
self.elders.get(name).copied()
}
fn names(&self) -> BTreeSet<XorName> {
self.elders.keys().copied().collect()
}
fn elders(&self) -> BTreeMap<XorName, SocketAddr> {
self.elders
.iter()
.map(|(name, addr)| (*name, *addr))
.collect()
}
fn addresses(&self) -> Vec<SocketAddr> {
self.elders.values().copied().collect()
}
fn prefix(&self) -> Prefix {
self.prefix
}
fn section_key(&self) -> PublicKey {
self.public_key_set.public_key()
}
}
#[cfg(test)]
pub(crate) mod test_utils {
use super::*;
use crate::routing::tests::SecretKeySet;
use crate::{ed25519, node::Node, MIN_ADULT_AGE, MIN_AGE};
use itertools::Itertools;
use std::{cell::Cell, net::SocketAddr};
use xor_name::Prefix;
pub(crate) fn gen_addr() -> SocketAddr {
thread_local! {
static NEXT_PORT: Cell<u16> = Cell::new(1000);
}
let port = NEXT_PORT.with(|cell| cell.replace(cell.get().wrapping_add(1)));
([192, 0, 2, 0], port).into()
}
pub(crate) fn gen_sorted_nodes(prefix: &Prefix, count: usize, age_diff: bool) -> Vec<Node> {
(0..count)
.map(|index| {
let age = if age_diff && index < count - 1 {
MIN_AGE + 2
} else {
MIN_ADULT_AGE
};
Node::new(
ed25519::gen_keypair(&prefix.range_inclusive(), age),
gen_addr(),
)
})
.sorted_by_key(|node| node.name())
.collect()
}
pub(crate) fn gen_section_authority_provider(
prefix: Prefix,
count: usize,
) -> (SectionAuthorityProvider, Vec<Node>, SecretKeySet) {
let nodes = gen_sorted_nodes(&prefix, count, false);
let elders = nodes
.iter()
.map(Node::peer)
.map(|mut peer| {
peer.set_reachable(true);
(*peer.name(), *peer.addr())
})
.collect();
let secret_key_set = SecretKeySet::random();
let section_auth = SectionAuthorityProvider::from_elder_candidates(
ElderCandidates { elders, prefix },
secret_key_set.public_keys(),
);
(section_auth, nodes, secret_key_set)
}
}