ant_node/
lib.rs

1// Copyright 2024 MaidSafe.net limited.
2//
3// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
4// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
5// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
6// KIND, either express or implied. Please review the Licences for the specific language governing
7// permissions and limitations relating to use of the SAFE Network Software.
8
9//! Implementation of the Node in SAFE Network.
10
11// For quick_error
12#![recursion_limit = "256"]
13#![doc(
14    html_logo_url = "https://github.com/maidsafe/QA/raw/master/Images/maidsafe_logo.png",
15    html_favicon_url = "https://maidsafe.net/img/favicon.ico",
16    test(attr(deny(warnings)))
17)]
18// Turn on some additional warnings to encourage good style.
19#![warn(missing_docs, unreachable_pub, unused_results, clippy::unwrap_used)]
20#![allow(clippy::large_enum_variant)]
21#![allow(clippy::result_large_err)]
22
23#[macro_use]
24extern crate tracing;
25
26mod error;
27mod event;
28mod log_markers;
29#[cfg(feature = "open-metrics")]
30mod metrics;
31mod node;
32mod put_validation;
33#[cfg(feature = "extension-module")]
34mod python;
35mod quote;
36mod replication;
37#[allow(missing_docs)]
38pub mod spawn;
39#[allow(missing_docs)]
40pub mod utils;
41
42pub use self::{
43    error::{Error, PutValidationError},
44    event::{NodeEvent, NodeEventsChannel, NodeEventsReceiver},
45    log_markers::Marker,
46    node::{NodeBuilder, PERIODIC_REPLICATION_INTERVAL_MAX_S},
47};
48
49use crate::error::Result;
50use ant_evm::RewardsAddress;
51use ant_networking::{Network, SwarmLocalState};
52use ant_protocol::{get_port_from_multiaddr, NetworkAddress};
53use libp2p::{Multiaddr, PeerId};
54use std::{
55    collections::{BTreeMap, HashSet},
56    path::PathBuf,
57};
58use tokio::sync::watch;
59
60/// Once a node is started and running, the user obtains
61/// a `NodeRunning` object which can be used to interact with it.
62#[derive(Clone)]
63pub struct RunningNode {
64    shutdown_sender: watch::Sender<bool>,
65    network: Network,
66    node_events_channel: NodeEventsChannel,
67    root_dir_path: PathBuf,
68    rewards_address: RewardsAddress,
69}
70
71impl RunningNode {
72    /// Returns this node's `PeerId`
73    pub fn peer_id(&self) -> PeerId {
74        self.network.peer_id()
75    }
76
77    /// Returns the root directory path for the node.
78    ///
79    /// This will either be a value defined by the user, or a default location, plus the peer ID
80    /// appended. The default location is platform specific:
81    ///  - Linux: $HOME/.local/share/autonomi/node/<peer-id>
82    ///  - macOS: $HOME/Library/Application Support/autonomi/node/<peer-id>
83    ///  - Windows: C:\Users\<username>\AppData\Roaming\autonomi\node\<peer-id>
84    #[expect(rustdoc::invalid_html_tags)]
85    pub fn root_dir_path(&self) -> PathBuf {
86        self.root_dir_path.clone()
87    }
88
89    /// Returns a `SwarmLocalState` with some information obtained from swarm's local state.
90    pub async fn get_swarm_local_state(&self) -> Result<SwarmLocalState> {
91        let state = self.network.get_swarm_local_state().await?;
92        Ok(state)
93    }
94
95    /// Return the node's listening addresses.
96    pub async fn get_listen_addrs(&self) -> Result<Vec<Multiaddr>> {
97        let listeners = self.network.get_swarm_local_state().await?.listeners;
98        Ok(listeners)
99    }
100
101    /// Return the node's listening addresses with the peer id appended.
102    pub async fn get_listen_addrs_with_peer_id(&self) -> Result<Vec<Multiaddr>> {
103        let listeners = self.get_listen_addrs().await?;
104
105        let multi_addrs: Vec<Multiaddr> = listeners
106            .into_iter()
107            .filter_map(|listen_addr| listen_addr.with_p2p(self.peer_id()).ok())
108            .collect();
109
110        Ok(multi_addrs)
111    }
112
113    /// Return the node's listening port
114    pub async fn get_node_listening_port(&self) -> Result<u16> {
115        let listen_addrs = self.network.get_swarm_local_state().await?.listeners;
116        for addr in listen_addrs {
117            if let Some(port) = get_port_from_multiaddr(&addr) {
118                return Ok(port);
119            }
120        }
121        Err(Error::FailedToGetNodePort)
122    }
123
124    /// Returns the node events channel where to subscribe to receive `NodeEvent`s
125    pub fn node_events_channel(&self) -> &NodeEventsChannel {
126        &self.node_events_channel
127    }
128
129    /// Returns the list of all the RecordKeys held by the node
130    pub async fn get_all_record_addresses(&self) -> Result<HashSet<NetworkAddress>> {
131        #[allow(clippy::mutable_key_type)] // for Bytes in NetworkAddress
132        let addresses: HashSet<_> = self
133            .network
134            .get_all_local_record_addresses()
135            .await?
136            .keys()
137            .cloned()
138            .collect();
139        Ok(addresses)
140    }
141
142    /// Returns a map where each key is the ilog2 distance of that Kbucket and each value is a vector of peers in that
143    /// bucket.
144    pub async fn get_kbuckets(&self) -> Result<BTreeMap<u32, Vec<PeerId>>> {
145        let kbuckets = self.network.get_kbuckets().await?;
146        Ok(kbuckets)
147    }
148
149    /// Returns the node's reward address
150    pub fn reward_address(&self) -> &RewardsAddress {
151        &self.rewards_address
152    }
153
154    /// Shutdown the SwarmDriver loop and the node (NetworkEvents) loop.
155    pub fn shutdown(self) {
156        // Send the shutdown signal to the swarm driver and node loop
157        let _ = self.shutdown_sender.send(true);
158    }
159}