snarkos_node_router/outbound.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::{PeerPoolHandling, Router, messages::Message};
17use snarkvm::prelude::Network;
18
19use std::net::SocketAddr;
20
21pub trait Outbound<N: Network> {
22 /// Returns a reference to the router.
23 fn router(&self) -> &Router<N>;
24
25 /// Returns `true` if the node is synced up to the latest block (within the given tolerance).
26 fn is_block_synced(&self) -> bool;
27
28 /// Returns the number of blocks this node is behind the greatest peer height,
29 /// or `None` if not connected to peers yet.
30 fn num_blocks_behind(&self) -> Option<u32>;
31
32 /// Returns the current sync speed in blocks per second.
33 fn get_sync_speed(&self) -> f64;
34
35 /// Sends the given message to every connected peer, excluding the sender and any specified peer IPs.
36 fn propagate(&self, message: Message<N>, excluded_peers: &[SocketAddr]) {
37 // TODO (howardwu): Serialize large messages once only.
38 // // Perform ahead-of-time, non-blocking serialization just once for applicable objects.
39 // if let Message::UnconfirmedSolution(ref mut message) = message {
40 // if let Ok(serialized_solution) = Data::serialize(message.solution.clone()).await {
41 // let _ = std::mem::replace(&mut message.solution, Data::Buffer(serialized_solution));
42 // } else {
43 // error!("Solution serialization is bugged");
44 // }
45 // } else if let Message::UnconfirmedTransaction(ref mut message) = message {
46 // if let Ok(serialized_transaction) = Data::serialize(message.transaction.clone()).await {
47 // let _ = std::mem::replace(&mut message.transaction, Data::Buffer(serialized_transaction));
48 // } else {
49 // error!("Transaction serialization is bugged");
50 // }
51 // }
52
53 // Prepare the peers to send to.
54 let connected_peers =
55 self.router().filter_connected_peers(|peer| !excluded_peers.contains(&peer.listener_addr));
56
57 // Iterate through all peers that are not the sender and excluded peers.
58 for addr in connected_peers.iter().map(|peer| peer.listener_addr) {
59 self.router().send(addr, message.clone());
60 }
61 }
62
63 /// Sends the given message to every connected validator, excluding the sender and any specified IPs.
64 fn propagate_to_validators(&self, message: Message<N>, excluded_peers: &[SocketAddr]) {
65 // TODO (howardwu): Serialize large messages once only.
66 // // Perform ahead-of-time, non-blocking serialization just once for applicable objects.
67 // if let Message::UnconfirmedSolution(ref mut message) = message {
68 // if let Ok(serialized_solution) = Data::serialize(message.solution.clone()).await {
69 // let _ = std::mem::replace(&mut message.solution, Data::Buffer(serialized_solution));
70 // } else {
71 // error!("Solution serialization is bugged");
72 // }
73 // } else if let Message::UnconfirmedTransaction(ref mut message) = message {
74 // if let Ok(serialized_transaction) = Data::serialize(message.transaction.clone()).await {
75 // let _ = std::mem::replace(&mut message.transaction, Data::Buffer(serialized_transaction));
76 // } else {
77 // error!("Transaction serialization is bugged");
78 // }
79 // }
80
81 // Prepare the peers to send to.
82 let connected_validators = self.router().filter_connected_peers(|peer| {
83 peer.node_type.is_validator() && !excluded_peers.contains(&peer.listener_addr)
84 });
85
86 // Iterate through all validators that are not the sender and excluded validators.
87 for listener_addr in connected_validators.iter().map(|peer| peer.listener_addr) {
88 self.router().send(listener_addr, message.clone());
89 }
90 }
91}