Skip to main content

snarkos_node/
node.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkOS library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use crate::{
17    BootstrapClient,
18    Client,
19    Prover,
20    Validator,
21    network::{NodeType, Peer, PeerPoolHandling},
22    router::Outbound,
23    traits::NodeInterface,
24};
25
26use snarkos_account::Account;
27use snarkos_utilities::{NodeDataDir, SignalHandler};
28
29use snarkvm::prelude::{
30    Address,
31    Header,
32    Ledger,
33    Network,
34    PrivateKey,
35    ViewKey,
36    block::Block,
37    store::helpers::{memory::ConsensusMemory, rocksdb::ConsensusDB},
38};
39
40use aleo_std::StorageMode;
41use anyhow::Result;
42
43#[cfg(feature = "locktick")]
44use locktick::parking_lot::RwLock;
45#[cfg(not(feature = "locktick"))]
46use parking_lot::RwLock;
47use std::{collections::HashMap, net::SocketAddr, sync::Arc};
48
49#[derive(Clone)]
50pub enum Node<N: Network> {
51    /// A validator is a full node, capable of validating blocks.
52    Validator(Arc<Validator<N, ConsensusDB<N>>>),
53    /// A prover is a light node, capable of producing proofs for consensus.
54    Prover(Arc<Prover<N, ConsensusMemory<N>>>),
55    /// A client node is a full node, capable of querying with the network.
56    Client(Arc<Client<N, ConsensusDB<N>>>),
57    /// A bootstrap client node is a light node dedicated to serving lists of peers.
58    BootstrapClient(BootstrapClient<N>),
59}
60
61impl<N: Network> Node<N> {
62    /// Initializes a new validator node.
63    pub async fn new_validator(
64        node_ip: SocketAddr,
65        bft_ip: Option<SocketAddr>,
66        rest_ip: Option<SocketAddr>,
67        rest_rps: u32,
68        account: Account<N>,
69        trusted_peers: &[SocketAddr],
70        trusted_validators: &[SocketAddr],
71        genesis: Block<N>,
72        cdn: Option<http::Uri>,
73        storage_mode: StorageMode,
74        node_data_dir: NodeDataDir,
75        trusted_peers_only: bool,
76        dev_txs: bool,
77        dev: Option<u16>,
78        signal_handler: Arc<SignalHandler>,
79    ) -> Result<Self> {
80        Ok(Self::Validator(Arc::new(
81            Validator::new(
82                node_ip,
83                bft_ip,
84                rest_ip,
85                rest_rps,
86                account,
87                trusted_peers,
88                trusted_validators,
89                genesis,
90                cdn,
91                storage_mode,
92                node_data_dir,
93                trusted_peers_only,
94                dev_txs,
95                dev,
96                signal_handler,
97            )
98            .await?,
99        )))
100    }
101
102    /// Initializes a new prover node.
103    pub async fn new_prover(
104        node_ip: SocketAddr,
105        account: Account<N>,
106        trusted_peers: &[SocketAddr],
107        genesis: Block<N>,
108        node_data_dir: NodeDataDir,
109        trusted_peers_only: bool,
110        dev: Option<u16>,
111        signal_handler: Arc<SignalHandler>,
112    ) -> Result<Self> {
113        Ok(Self::Prover(Arc::new(
114            Prover::new(
115                node_ip,
116                account,
117                trusted_peers,
118                genesis,
119                node_data_dir,
120                trusted_peers_only,
121                dev,
122                signal_handler,
123            )
124            .await?,
125        )))
126    }
127
128    /// Initializes a new client node.
129    pub async fn new_client(
130        node_ip: SocketAddr,
131        rest_ip: Option<SocketAddr>,
132        rest_rps: u32,
133        account: Account<N>,
134        trusted_peers: &[SocketAddr],
135        genesis: Block<N>,
136        cdn: Option<http::Uri>,
137        storage_mode: StorageMode,
138        node_data_dir: NodeDataDir,
139        trusted_peers_only: bool,
140        dev: Option<u16>,
141        signal_handler: Arc<SignalHandler>,
142    ) -> Result<Self> {
143        Ok(Self::Client(Arc::new(
144            Client::new(
145                node_ip,
146                rest_ip,
147                rest_rps,
148                account,
149                trusted_peers,
150                genesis,
151                cdn,
152                storage_mode,
153                node_data_dir,
154                trusted_peers_only,
155                dev,
156                signal_handler,
157            )
158            .await?,
159        )))
160    }
161
162    /// Initializes a new bootstrap client node.
163    pub async fn new_bootstrap_client(
164        listener_addr: SocketAddr,
165        account: Account<N>,
166        genesis_header: Header<N>,
167        dev: Option<u16>,
168    ) -> Result<Self> {
169        Ok(Self::BootstrapClient(BootstrapClient::new(listener_addr, account, genesis_header, dev).await?))
170    }
171
172    /// Returns the node type.
173    pub fn node_type(&self) -> NodeType {
174        match self {
175            Self::Validator(validator) => validator.node_type(),
176            Self::Prover(prover) => prover.node_type(),
177            Self::Client(client) => client.node_type(),
178            Self::BootstrapClient(_) => NodeType::BootstrapClient,
179        }
180    }
181
182    /// Returns the account private key of the node.
183    pub fn private_key(&self) -> &PrivateKey<N> {
184        match self {
185            Self::Validator(node) => node.private_key(),
186            Self::Prover(node) => node.private_key(),
187            Self::Client(node) => node.private_key(),
188            Self::BootstrapClient(node) => node.private_key(),
189        }
190    }
191
192    /// Returns the account view key of the node.
193    pub fn view_key(&self) -> &ViewKey<N> {
194        match self {
195            Self::Validator(node) => node.view_key(),
196            Self::Prover(node) => node.view_key(),
197            Self::Client(node) => node.view_key(),
198            Self::BootstrapClient(node) => node.view_key(),
199        }
200    }
201
202    /// Returns the account address of the node.
203    pub fn address(&self) -> Address<N> {
204        match self {
205            Self::Validator(node) => node.address(),
206            Self::Prover(node) => node.address(),
207            Self::Client(node) => node.address(),
208            Self::BootstrapClient(node) => node.address(),
209        }
210    }
211
212    /// Returns `true` if the node is in development mode.
213    pub fn is_dev(&self) -> bool {
214        match self {
215            Self::Validator(node) => node.is_dev(),
216            Self::Prover(node) => node.is_dev(),
217            Self::Client(node) => node.is_dev(),
218            Self::BootstrapClient(node) => node.is_dev(),
219        }
220    }
221
222    /// Returns a reference to the underlying peer pool.
223    pub fn peer_pool(&self) -> &RwLock<HashMap<SocketAddr, Peer<N>>> {
224        match self {
225            Self::Validator(validator) => validator.router().peer_pool(),
226            Self::Prover(prover) => prover.router().peer_pool(),
227            Self::Client(client) => client.router().peer_pool(),
228            Self::BootstrapClient(client) => client.peer_pool(),
229        }
230    }
231
232    /// Get the underlying ledger (if any).
233    pub fn ledger(&self) -> Option<&Ledger<N, ConsensusDB<N>>> {
234        match self {
235            Self::Validator(node) => Some(node.ledger()),
236            Self::Prover(_) => None,
237            Self::Client(node) => Some(node.ledger()),
238            Self::BootstrapClient(_) => None,
239        }
240    }
241
242    /// Returns `true` if the node is synced up to the latest block (within the given tolerance).
243    pub fn is_block_synced(&self) -> bool {
244        match self {
245            Self::Validator(node) => node.is_block_synced(),
246            Self::Prover(node) => node.is_block_synced(),
247            Self::Client(node) => node.is_block_synced(),
248            Self::BootstrapClient(_) => true,
249        }
250    }
251
252    /// Returns the number of blocks this node is behind the greatest peer height,
253    /// or `None` if not connected to peers yet.
254    pub fn num_blocks_behind(&self) -> Option<u32> {
255        match self {
256            Self::Validator(node) => node.num_blocks_behind(),
257            Self::Prover(node) => node.num_blocks_behind(),
258            Self::Client(node) => node.num_blocks_behind(),
259            Self::BootstrapClient(_) => Some(0),
260        }
261    }
262
263    /// Calculates the current sync speed in blocks per second.
264    /// Returns None if sync speed cannot be calculated (e.g., not syncing or insufficient data).
265    pub fn get_sync_speed(&self) -> f64 {
266        match self {
267            Self::Validator(node) => node.get_sync_speed(),
268            Self::Prover(node) => node.get_sync_speed(),
269            Self::Client(node) => node.get_sync_speed(),
270            Self::BootstrapClient(_) => 0.0,
271        }
272    }
273
274    /// Shuts down the node.
275    pub async fn shut_down(&self) {
276        match self {
277            Self::Validator(node) => node.shut_down().await,
278            Self::Prover(node) => node.shut_down().await,
279            Self::Client(node) => node.shut_down().await,
280            Self::BootstrapClient(node) => node.shut_down().await,
281        }
282    }
283
284    /// Waits until the node receives a signal.
285    pub async fn wait_for_signals(&self, signal_handler: &SignalHandler) {
286        match self {
287            Self::Validator(node) => node.wait_for_signals(signal_handler).await,
288            Self::Prover(node) => node.wait_for_signals(signal_handler).await,
289            Self::Client(node) => node.wait_for_signals(signal_handler).await,
290            Self::BootstrapClient(node) => node.wait_for_signals(signal_handler).await,
291        }
292    }
293}