diff --git a/src/states/bootstrapping.rs b/src/states/bootstrapping.rs index 1013693481..662c068aaa 100644 --- a/src/states/bootstrapping.rs +++ b/src/states/bootstrapping.rs @@ -6,7 +6,12 @@ // KIND, either express or implied. Please review the Licences for the specific language governing // permissions and limitations relating to use of the SAFE Network Software. -use super::{common::Base, Client, ProvingNode, RelocatingNode}; +use super::{ + client::{Client, ClientDetails}, + common::Base, + proving_node::{ProvingNode, ProvingNodeDetails}, + relocating_node::{RelocatingNode, RelocatingNodeDetails}, +}; use crate::{ cache::Cache, crust::CrustUser, @@ -49,15 +54,15 @@ pub enum TargetState { // State of Client or Node while bootstrapping. pub struct Bootstrapping { - pub(super) action_sender: RoutingActionSender, - pub(super) cache: Box, - pub(super) crust_service: Service, - pub(super) full_id: FullId, - pub(super) min_section_size: usize, - pub(super) timer: Timer, + action_sender: RoutingActionSender, bootstrap_blacklist: HashSet, bootstrap_connection: Option<(PublicId, u64)>, + cache: Box, + crust_service: Service, + full_id: FullId, + min_section_size: usize, target_state: TargetState, + timer: Timer, } impl Bootstrapping { @@ -94,16 +99,31 @@ impl Bootstrapping { }) } - pub fn into_target_state(self, proxy_public_id: PublicId, outbox: &mut EventBox) -> State { + pub fn into_target_state(self, proxy_pub_id: PublicId, outbox: &mut EventBox) -> State { match self.target_state { TargetState::Client { msg_expiry_dur } => State::Client(Client::from_bootstrapping( - self, - proxy_public_id, - msg_expiry_dur, + ClientDetails { + crust_service: self.crust_service, + full_id: self.full_id, + min_section_size: self.min_section_size, + msg_expiry_dur, + proxy_pub_id, + timer: self.timer, + }, outbox, )), TargetState::RelocatingNode => { - if let Some(node) = RelocatingNode::from_bootstrapping(self, proxy_public_id) { + let details = RelocatingNodeDetails { + action_sender: self.action_sender, + cache: self.cache, + crust_service: self.crust_service, + full_id: self.full_id, + min_section_size: self.min_section_size, + proxy_pub_id, + timer: self.timer, + }; + + if let Some(node) = RelocatingNode::from_bootstrapping(details) { State::RelocatingNode(node) } else { outbox.send_event(Event::RestartRequired); @@ -111,19 +131,23 @@ impl Bootstrapping { } } TargetState::ProvingNode { - ref old_full_id, - ref our_section, + old_full_id, + our_section, .. } => { - let old_full_id = old_full_id.clone(); - let our_section = our_section.clone(); - State::ProvingNode(ProvingNode::from_bootstrapping( - self, - proxy_public_id, + let details = ProvingNodeDetails { + action_sender: self.action_sender, + cache: self.cache, + crust_service: self.crust_service, + full_id: self.full_id, + min_section_size: self.min_section_size, old_full_id, our_section, - outbox, - )) + proxy_pub_id, + timer: self.timer, + }; + + State::ProvingNode(ProvingNode::from_bootstrapping(details, outbox)) } } } diff --git a/src/states/client.rs b/src/states/client.rs index 7fd592e60f..dbd95f4e13 100644 --- a/src/states/client.rs +++ b/src/states/client.rs @@ -6,10 +6,7 @@ // KIND, either express or implied. Please review the Licences for the specific language governing // permissions and limitations relating to use of the SAFE Network Software. -use super::{ - bootstrapping::Bootstrapping, - common::{proxied, Base, Bootstrapped, NotEstablished, USER_MSG_CACHE_EXPIRY_DURATION}, -}; +use super::common::{proxied, Base, Bootstrapped, NotEstablished, USER_MSG_CACHE_EXPIRY_DURATION}; use crate::{ ack_manager::{Ack, AckManager, UnacknowledgedMessage}, chain::SectionInfo, @@ -37,6 +34,15 @@ use std::{ /// Duration to wait before sending rate limit exceeded messages. pub const RATE_EXCEED_RETRY: Duration = Duration::from_millis(800); +pub struct ClientDetails { + pub crust_service: Service, + pub full_id: FullId, + pub min_section_size: usize, + pub msg_expiry_dur: Duration, + pub proxy_pub_id: PublicId, + pub timer: Timer, +} + /// A node connecting a user to the network, as opposed to a routing / data storage node. /// /// Each client has a _proxy_: a node through which all requests are routed. @@ -54,23 +60,18 @@ pub struct Client { } impl Client { - pub fn from_bootstrapping( - source: Bootstrapping, - proxy_pub_id: PublicId, - msg_expiry_dur: Duration, - outbox: &mut EventBox, - ) -> Self { + pub fn from_bootstrapping(details: ClientDetails, outbox: &mut EventBox) -> Self { let client = Client { ack_mgr: AckManager::new(), - crust_service: source.crust_service, - full_id: source.full_id, - min_section_size: source.min_section_size, - proxy_pub_id, + crust_service: details.crust_service, + full_id: details.full_id, + min_section_size: details.min_section_size, + proxy_pub_id: details.proxy_pub_id, routing_msg_filter: RoutingMessageFilter::new(), - timer: source.timer, + timer: details.timer, user_msg_cache: UserMessageCache::with_expiry_duration(USER_MSG_CACHE_EXPIRY_DURATION), resend_buf: Default::default(), - msg_expiry_dur, + msg_expiry_dur: details.msg_expiry_dur, }; debug!("{} State changed to Client.", client); diff --git a/src/states/establishing_node.rs b/src/states/establishing_node.rs index 711914f46d..656f259363 100644 --- a/src/states/establishing_node.rs +++ b/src/states/establishing_node.rs @@ -10,8 +10,7 @@ use super::{ common::{ proxied, Approved, Base, Bootstrapped, NotEstablished, Relocated, RelocatedNotEstablished, }, - node::Node, - proving_node::ProvingNode, + node::{Node, NodeDetails}, }; use crate::{ ack_manager::AckManager, @@ -39,52 +38,69 @@ use std::{ const POKE_TIMEOUT: Duration = Duration::from_secs(60); +pub struct EstablishingNodeDetails { + pub ack_mgr: AckManager, + pub cache: Box, + pub crust_service: Service, + pub full_id: FullId, + pub gen_pfx_info: GenesisPfxInfo, + pub min_section_size: usize, + pub msg_backlog: Vec, + pub notified_nodes: BTreeSet, + pub peer_mgr: PeerManager, + pub routing_msg_filter: RoutingMessageFilter, + pub timer: Timer, +} + pub struct EstablishingNode { - pub(super) ack_mgr: AckManager, - pub(super) cache: Box, - pub(super) chain: Chain, - pub(super) crust_service: Service, - pub(super) full_id: FullId, - pub(super) gen_pfx_info: GenesisPfxInfo, + ack_mgr: AckManager, + cache: Box, + chain: Chain, + crust_service: Service, + full_id: FullId, + gen_pfx_info: GenesisPfxInfo, /// Routing messages addressed to us that we cannot handle until we are established. - pub(super) msg_backlog: Vec, - pub(super) notified_nodes: BTreeSet, - pub(super) parsec_map: ParsecMap, - pub(super) peer_mgr: PeerManager, - pub(super) routing_msg_filter: RoutingMessageFilter, - pub(super) timer: Timer, + msg_backlog: Vec, + notified_nodes: BTreeSet, + parsec_map: ParsecMap, + peer_mgr: PeerManager, poke_timer_token: u64, + routing_msg_filter: RoutingMessageFilter, + timer: Timer, } impl EstablishingNode { pub fn from_proving_node( - source: ProvingNode, - gen_pfx_info: GenesisPfxInfo, + details: EstablishingNodeDetails, outbox: &mut EventBox, ) -> Result { - let public_id = *source.full_id.public_id(); - let poke_timer_token = source.timer.schedule(POKE_TIMEOUT); + let public_id = *details.full_id.public_id(); + let poke_timer_token = details.timer.schedule(POKE_TIMEOUT); - let parsec_map = ParsecMap::new(source.full_id.clone(), &gen_pfx_info); - let chain = Chain::new(source.min_section_size, public_id, gen_pfx_info.clone()); + let parsec_map = ParsecMap::new(details.full_id.clone(), &details.gen_pfx_info); + let chain = Chain::new( + details.min_section_size, + public_id, + details.gen_pfx_info.clone(), + ); let mut node = Self { - ack_mgr: source.ack_mgr, - cache: source.cache, + ack_mgr: details.ack_mgr, + cache: details.cache, chain, - crust_service: source.crust_service, - full_id: source.full_id, - gen_pfx_info, + crust_service: details.crust_service, + full_id: details.full_id, + gen_pfx_info: details.gen_pfx_info, msg_backlog: vec![], - notified_nodes: source.notified_nodes, + notified_nodes: details.notified_nodes, parsec_map, - peer_mgr: source.peer_mgr, - routing_msg_filter: source.routing_msg_filter, - timer: source.timer, + peer_mgr: details.peer_mgr, + routing_msg_filter: details.routing_msg_filter, + timer: details.timer, poke_timer_token, }; - node.init(source.msg_backlog, outbox)?; + node.init(details.msg_backlog, outbox)?; Ok(node) } @@ -108,7 +124,22 @@ impl EstablishingNode { old_pfx: Prefix, outbox: &mut EventBox, ) -> State { - match Node::from_establishing_node(self, sec_info, old_pfx, outbox) { + let details = NodeDetails { + ack_mgr: self.ack_mgr, + cache: self.cache, + chain: self.chain, + crust_service: self.crust_service, + full_id: self.full_id, + gen_pfx_info: self.gen_pfx_info, + msg_queue: self.msg_backlog.into_iter().collect(), + notified_nodes: self.notified_nodes, + parsec_map: self.parsec_map, + peer_mgr: self.peer_mgr, + routing_msg_filter: self.routing_msg_filter, + timer: self.timer, + }; + + match Node::from_establishing_node(details, sec_info, old_pfx, outbox) { Ok(node) => State::Node(node), Err(_) => State::Terminated, } diff --git a/src/states/node.rs b/src/states/node.rs index 75a5460cee..07292a5e76 100644 --- a/src/states/node.rs +++ b/src/states/node.rs @@ -6,10 +6,7 @@ // KIND, either express or implied. Please review the Licences for the specific language governing // permissions and limitations relating to use of the SAFE Network Software. -use super::{ - common::{Approved, Base, Bootstrapped, Relocated, USER_MSG_CACHE_EXPIRY_DURATION}, - establishing_node::EstablishingNode, -}; +use super::common::{Approved, Base, Bootstrapped, Relocated, USER_MSG_CACHE_EXPIRY_DURATION}; use crate::{ ack_manager::{Ack, AckManager}, cache::Cache, @@ -77,6 +74,21 @@ const CLIENT_BAN_DURATION: Duration = Duration::from_secs(2 * 60 * 60); /// Duration for which clients' IDs we disconnected from are retained. const DROPPED_CLIENT_TIMEOUT: Duration = Duration::from_secs(2 * 60 * 60); +pub struct NodeDetails { + pub ack_mgr: AckManager, + pub cache: Box, + pub chain: Chain, + pub crust_service: Service, + pub full_id: FullId, + pub gen_pfx_info: GenesisPfxInfo, + pub msg_queue: VecDeque, + pub notified_nodes: BTreeSet, + pub parsec_map: ParsecMap, + pub peer_mgr: PeerManager, + pub routing_msg_filter: RoutingMessageFilter, + pub timer: Timer, +} + pub struct Node { ack_mgr: AckManager, cacheable_user_msg_cache: UserMessageCache, @@ -144,22 +156,24 @@ impl Node { }; let parsec_map = ParsecMap::new(full_id.clone(), &gen_pfx_info); let chain = Chain::new(min_section_size, public_id, gen_pfx_info.clone()); + let peer_mgr = PeerManager::new(public_id, dev_config.disable_client_rate_limiter); - let mut node = Self::new( - AckManager::new(), + let details = NodeDetails { + ack_mgr: AckManager::new(), cache, chain, crust_service, full_id, gen_pfx_info, - true, - Default::default(), - Default::default(), + msg_queue: VecDeque::new(), + notified_nodes: BTreeSet::new(), parsec_map, - PeerManager::new(public_id, dev_config.disable_client_rate_limiter), - RoutingMessageFilter::new(), + peer_mgr, + routing_msg_filter: RoutingMessageFilter::new(), timer, - ); + }; + + let mut node = Self::new(details, true); if let Err(error) = node.crust_service.start_listening_tcp() { error!("{} - Failed to start listening: {:?}", node, error); @@ -172,65 +186,37 @@ impl Node { } pub fn from_establishing_node( - source: EstablishingNode, + details: NodeDetails, sec_info: SectionInfo, old_pfx: Prefix, outbox: &mut EventBox, ) -> Result { - let mut node = Self::new( - source.ack_mgr, - source.cache, - source.chain, - source.crust_service, - source.full_id, - source.gen_pfx_info, - false, - source.msg_backlog.into_iter().collect(), - source.notified_nodes, - source.parsec_map, - source.peer_mgr, - source.routing_msg_filter, - source.timer, - ); + let mut node = Self::new(details, false); node.init(sec_info, old_pfx, outbox)?; Ok(node) } - #[allow(clippy::too_many_arguments)] - fn new( - ack_mgr: AckManager, - cache: Box, - chain: Chain, - crust_service: Service, - full_id: FullId, - gen_pfx_info: GenesisPfxInfo, - is_first_node: bool, - msg_queue: VecDeque, - notified_nodes: BTreeSet, - parsec_map: ParsecMap, - peer_mgr: PeerManager, - routing_msg_filter: RoutingMessageFilter, - timer: Timer, - ) -> Self { + fn new(details: NodeDetails, is_first_node: bool) -> Self { let dev_config = config_handler::get_config().dev.unwrap_or_default(); + let timer = details.timer; let tick_timer_token = timer.schedule(TICK_TIMEOUT); let gossip_timer_token = timer.schedule(GOSSIP_TIMEOUT); let candidate_status_token = timer.schedule(CANDIDATE_STATUS_INTERVAL); let reconnect_peers_token = timer.schedule(RECONNECT_PEER_TIMEOUT); Self { - ack_mgr, + ack_mgr: details.ack_mgr, cacheable_user_msg_cache: UserMessageCache::with_expiry_duration( USER_MSG_CACHE_EXPIRY_DURATION, ), - crust_service: crust_service, - full_id: full_id.clone(), + crust_service: details.crust_service, + full_id: details.full_id.clone(), is_first_node, - msg_queue, - peer_mgr, - response_cache: cache, - routing_msg_filter, + msg_queue: details.msg_queue, + peer_mgr: details.peer_mgr, + response_cache: details.cache, + routing_msg_filter: details.routing_msg_filter, sig_accumulator: Default::default(), tick_timer_token: tick_timer_token, timer: timer, @@ -244,13 +230,13 @@ impl Node { dropped_clients: LruCache::with_expiry_duration(DROPPED_CLIENT_TIMEOUT), proxy_load_amount: 0, disable_resource_proof: dev_config.disable_resource_proof, - parsec_map, - gen_pfx_info, + parsec_map: details.parsec_map, + gen_pfx_info: details.gen_pfx_info, gossip_timer_token, - chain, + chain: details.chain, reconnect_peers: Default::default(), reconnect_peers_token, - notified_nodes, + notified_nodes: details.notified_nodes, } } diff --git a/src/states/proving_node.rs b/src/states/proving_node.rs index 4448967a7f..9110fa24e2 100644 --- a/src/states/proving_node.rs +++ b/src/states/proving_node.rs @@ -7,9 +7,8 @@ // permissions and limitations relating to use of the SAFE Network Software. use super::{ - bootstrapping::Bootstrapping, common::{proxied, Base, Bootstrapped, NotEstablished, Relocated, RelocatedNotEstablished}, - establishing_node::EstablishingNode, + establishing_node::{EstablishingNode, EstablishingNodeDetails}, }; use crate::{ ack_manager::AckManager, @@ -30,6 +29,7 @@ use crate::{ state_machine::Transition, time::Instant, timer::Timer, + types::RoutingActionSender, xor_name::XorName, Service, }; @@ -39,62 +39,71 @@ use std::{ fmt::{self, Display, Formatter}, }; +pub struct ProvingNodeDetails { + pub action_sender: RoutingActionSender, + pub cache: Box, + pub crust_service: Service, + pub full_id: FullId, + pub min_section_size: usize, + pub old_full_id: FullId, + pub our_section: (Prefix, BTreeSet), + pub proxy_pub_id: PublicId, + pub timer: Timer, +} + pub struct ProvingNode { - pub(super) ack_mgr: AckManager, - pub(super) cache: Box, - pub(super) crust_service: Service, - pub(super) full_id: FullId, - pub(super) min_section_size: usize, - /// Routing messages addressed to us that we cannot handle until we are approved. - pub(super) msg_backlog: Vec, - // TODO: notify without local state - pub(super) notified_nodes: BTreeSet, - pub(super) peer_mgr: PeerManager, - pub(super) routing_msg_filter: RoutingMessageFilter, - pub(super) timer: Timer, + ack_mgr: AckManager, + cache: Box, + crust_service: Service, /// Whether resource proof is disabled. disable_resource_proof: bool, + full_id: FullId, joining_prefix: Prefix, + min_section_size: usize, + /// Routing messages addressed to us that we cannot handle until we are approved. + msg_backlog: Vec, + // TODO: notify without local state + notified_nodes: BTreeSet, /// ID from before relocating. old_full_id: FullId, + peer_mgr: PeerManager, resource_prover: ResourceProver, + routing_msg_filter: RoutingMessageFilter, + timer: Timer, } impl ProvingNode { - pub fn from_bootstrapping( - source: Bootstrapping, - proxy_pub_id: PublicId, - old_full_id: FullId, - our_section: (Prefix, BTreeSet), - outbox: &mut EventBox, - ) -> Self { + pub fn from_bootstrapping(details: ProvingNodeDetails, outbox: &mut EventBox) -> Self { let dev_config = config_handler::get_config().dev.unwrap_or_default(); - let public_id = *source.full_id.public_id(); + let public_id = *details.full_id.public_id(); let mut peer_mgr = PeerManager::new(public_id, dev_config.disable_client_rate_limiter); - peer_mgr.insert_peer(Peer::new(proxy_pub_id, PeerState::Proxy)); + peer_mgr.insert_peer(Peer::new(details.proxy_pub_id, PeerState::Proxy)); - let challenger_count = our_section.1.len(); - let resource_prover = - ResourceProver::new(source.action_sender, source.timer.clone(), challenger_count); + let challenger_count = details.our_section.1.len(); + let resource_prover = ResourceProver::new( + details.action_sender, + details.timer.clone(), + challenger_count, + ); let mut node = Self { ack_mgr: AckManager::new(), - cache: source.cache, - crust_service: source.crust_service, - full_id: source.full_id, - min_section_size: source.min_section_size, + cache: details.cache, + crust_service: details.crust_service, + full_id: details.full_id, + min_section_size: details.min_section_size, msg_backlog: Vec::new(), notified_nodes: Default::default(), peer_mgr, routing_msg_filter: RoutingMessageFilter::new(), - timer: source.timer, + timer: details.timer, disable_resource_proof: dev_config.disable_resource_proof, - joining_prefix: our_section.0, - old_full_id, + joining_prefix: details.our_section.0, + old_full_id: details.old_full_id, resource_prover, }; - node.init(our_section.1, &proxy_pub_id, outbox); + node.init(details.our_section.1, &details.proxy_pub_id, outbox); node } @@ -140,7 +149,21 @@ impl ProvingNode { gen_pfx_info: GenesisPfxInfo, outbox: &mut EventBox, ) -> State { - match EstablishingNode::from_proving_node(self, gen_pfx_info, outbox) { + let details = EstablishingNodeDetails { + ack_mgr: self.ack_mgr, + cache: self.cache, + crust_service: self.crust_service, + full_id: self.full_id, + gen_pfx_info, + min_section_size: self.min_section_size, + msg_backlog: self.msg_backlog, + notified_nodes: self.notified_nodes, + peer_mgr: self.peer_mgr, + routing_msg_filter: self.routing_msg_filter, + timer: self.timer, + }; + + match EstablishingNode::from_proving_node(details, outbox) { Ok(node) => State::EstablishingNode(node), Err(_) => State::Terminated, } diff --git a/src/states/relocating_node.rs b/src/states/relocating_node.rs index 9775b7ca02..191f9fe7d2 100644 --- a/src/states/relocating_node.rs +++ b/src/states/relocating_node.rs @@ -39,6 +39,16 @@ use std::{ /// Total time to wait for `RelocateResponse`. const RELOCATE_TIMEOUT: Duration = Duration::from_secs(60 + RESOURCE_PROOF_DURATION.as_secs()); +pub struct RelocatingNodeDetails { + pub action_sender: RoutingActionSender, + pub cache: Box, + pub crust_service: Service, + pub full_id: FullId, + pub min_section_size: usize, + pub proxy_pub_id: PublicId, + pub timer: Timer, +} + pub struct RelocatingNode { action_sender: RoutingActionSender, ack_mgr: AckManager, @@ -56,19 +66,19 @@ pub struct RelocatingNode { } impl RelocatingNode { - pub fn from_bootstrapping(source: Bootstrapping, proxy_pub_id: PublicId) -> Option { - let relocation_timer_token = source.timer.schedule(RELOCATE_TIMEOUT); + pub fn from_bootstrapping(details: RelocatingNodeDetails) -> Option { + let relocation_timer_token = details.timer.schedule(RELOCATE_TIMEOUT); let mut node = Self { - action_sender: source.action_sender, + action_sender: details.action_sender, ack_mgr: AckManager::new(), - crust_service: source.crust_service, - full_id: source.full_id, - cache: source.cache, - min_section_size: source.min_section_size, - proxy_pub_id, + crust_service: details.crust_service, + full_id: details.full_id, + cache: details.cache, + min_section_size: details.min_section_size, + proxy_pub_id: details.proxy_pub_id, routing_msg_filter: RoutingMessageFilter::new(), relocation_timer_token, - timer: source.timer, + timer: details.timer, }; if let Err(error) = node.relocate() {