use crate::{Network, Result};
use bls::{PublicKeySet, PublicKeyShare};
use ed25519_dalek::PublicKey as Ed25519PublicKey;
use itertools::Itertools;
use serde::Serialize;
use sn_data_types::{PublicKey, Signature, SignatureShare};
use sn_messaging::TransientElderKey;
use sn_routing::SectionProofChain;
use std::{
collections::BTreeSet,
net::SocketAddr,
path::{Path, PathBuf},
};
use xor_name::{Prefix, XorName};
#[derive(Clone)]
pub enum NodeState {
Adult(AdultState),
Elder(ElderState),
}
impl NodeState {
pub fn node_id(&self) -> Ed25519PublicKey {
match self {
Self::Adult(state) => state.node_id,
Self::Elder(state) => state.node_id,
}
}
}
#[derive(Clone)]
pub struct AdultState {
info: NodeInfo,
prefix: Prefix,
node_name: XorName,
node_id: Ed25519PublicKey,
section_proof_chain: SectionProofChain,
elders: Vec<(XorName, SocketAddr)>,
adult_reader: AdultReader,
node_signing: NodeSigning,
}
impl AdultState {
#[allow(clippy::eval_order_dependence)]
pub async fn new(info: NodeInfo, network: Network) -> Result<Self> {
Ok(Self {
info,
prefix: network.our_prefix().await,
node_name: network.our_name().await,
node_id: network.public_key().await,
section_proof_chain: network.our_history().await,
elders: network.our_elder_addresses().await,
adult_reader: AdultReader::new(network.clone()),
node_signing: NodeSigning::new(network),
})
}
pub fn info(&self) -> &NodeInfo {
&self.info
}
pub fn node_name(&self) -> XorName {
self.node_name
}
pub fn node_id(&self) -> Ed25519PublicKey {
self.node_id
}
pub async fn sign_as_node<T: Serialize>(&self, data: &T) -> Result<Signature> {
self.node_signing.sign_as_node(&data).await
}
}
#[derive(Clone)]
pub struct ElderState {
info: NodeInfo,
prefix: Prefix,
node_name: XorName,
node_id: Ed25519PublicKey,
key_index: usize,
public_key_set: PublicKeySet,
section_proof_chain: SectionProofChain,
elders: Vec<(XorName, SocketAddr)>,
adult_reader: AdultReader,
interaction: NodeInteraction,
node_signing: NodeSigning,
}
impl ElderState {
#[allow(clippy::eval_order_dependence)]
pub async fn new(info: &NodeInfo, network: Network) -> Result<Self> {
Ok(Self {
info: info.clone(),
prefix: network.our_prefix().await,
node_name: network.our_name().await,
node_id: network.public_key().await,
key_index: network.our_index().await?,
public_key_set: network.public_key_set().await?,
section_proof_chain: network.our_history().await,
elders: network.our_elder_addresses().await,
adult_reader: AdultReader::new(network.clone()),
interaction: NodeInteraction::new(network.clone()),
node_signing: NodeSigning::new(network),
})
}
pub async fn send_to_client(&self, peer_addr: SocketAddr, bytes: Bytes) -> Result<()> {
self.interaction.send_to_client(peer_addr, bytes).await
}
pub async fn set_joins_allowed(&mut self, joins_allowed: bool) -> Result<()> {
self.interaction.set_joins_allowed(joins_allowed).await
}
pub async fn adults(&self) -> Vec<XorName> {
self.adult_reader.our_adults().await
}
pub async fn adults_sorted_by_distance_to(&self, name: &XorName, count: usize) -> Vec<XorName> {
self.adult_reader
.our_adults_sorted_by_distance_to(name, count)
.await
}
pub fn info(&self) -> &NodeInfo {
&self.info
}
pub fn prefix(&self) -> &Prefix {
&self.prefix
}
pub fn node_name(&self) -> XorName {
self.node_name
}
pub fn node_id(&self) -> Ed25519PublicKey {
self.node_id
}
pub fn key_index(&self) -> usize {
self.key_index
}
pub fn section_public_key(&self) -> PublicKey {
PublicKey::Bls(self.public_key_set().public_key())
}
pub fn public_key_set(&self) -> &PublicKeySet {
&self.public_key_set
}
pub fn public_key_share(&self) -> PublicKeyShare {
self.public_key_set.public_key_share(self.key_index)
}
pub fn section_proof_chain(&self) -> &SectionProofChain {
&self.section_proof_chain
}
pub async fn elder_names(&self) -> BTreeSet<&XorName> {
self.elders.iter().map(|(name, _)| name).collect()
}
pub async fn elders(&self) -> &Vec<(XorName, SocketAddr)> {
&self.elders
}
pub fn elders_sorted_by_distance_to(&self, name: &XorName) -> Vec<&(XorName, SocketAddr)> {
self.elders
.iter()
.sorted_by(|(lhs, _), (rhs, _)| name.cmp_distance(lhs, rhs))
.collect()
}
pub async fn sign_as_elder<T: Serialize>(&self, data: &T) -> Result<SignatureShare> {
let share = self
.node_signing
.sign_as_elder(data, &self.public_key_set().public_key())
.await?;
Ok(SignatureShare {
share,
index: self.key_index,
})
}
pub async fn sign_as_node<T: Serialize>(&self, data: &T) -> Result<Signature> {
self.node_signing.sign_as_node(&data).await
}
pub fn elder_key(&self) -> TransientElderKey {
TransientElderKey {
node_id: self.node_id,
bls_key: self.public_key_share(),
bls_share_index: self.key_index(),
bls_public_key_set: self.public_key_set().clone(),
}
}
}
#[derive(Clone)]
struct AdultReader {
network: Network,
}
impl AdultReader {
pub fn new(network: Network) -> Self {
Self { network }
}
pub async fn our_adults(&self) -> Vec<XorName> {
self.network.our_adults().await
}
pub async fn our_adults_sorted_by_distance_to(
&self,
name: &XorName,
count: usize,
) -> Vec<XorName> {
self.network
.our_adults_sorted_by_distance_to(name, count)
.await
}
}
#[derive(Clone)]
pub struct NodeSigning {
network: Network,
}
impl NodeSigning {
pub fn new(network: Network) -> Self {
Self { network }
}
pub async fn sign_as_node<T: Serialize>(&self, data: &T) -> Result<Signature> {
self.network.sign_as_node(&data).await
}
pub async fn sign_as_elder<T: Serialize>(
&self,
data: &T,
public_key: &bls::PublicKey,
) -> Result<bls::SignatureShare> {
self.network.sign_as_elder(data, public_key).await
}
}
use bytes::Bytes;
#[derive(Clone)]
pub struct NodeInteraction {
network: Network,
}
impl NodeInteraction {
pub fn new(network: Network) -> Self {
Self { network }
}
pub async fn send_to_client(&self, peer_addr: SocketAddr, bytes: Bytes) -> Result<()> {
self.network
.send_message_to_client(peer_addr, bytes)
.await?;
Ok(())
}
pub async fn set_joins_allowed(&mut self, joins_allowed: bool) -> Result<()> {
self.network.set_joins_allowed(joins_allowed).await
}
}
#[derive(Clone)]
pub struct NodeInfo {
pub genesis: bool,
pub node_id: PublicKey,
pub root_dir: PathBuf,
pub max_storage_capacity: u64,
pub reward_key: PublicKey,
}
impl NodeInfo {
pub fn path(&self) -> &Path {
self.root_dir.as_path()
}
}