1use super::*;
17
18use snarkos_node_router::messages::{
19 BlockRequest,
20 DisconnectReason,
21 Message,
22 MessageCodec,
23 Ping,
24 Pong,
25 PuzzleRequest,
26 UnconfirmedTransaction,
27};
28use snarkos_node_tcp::{Connection, ConnectionSide, Tcp};
29use snarkvm::prelude::{Field, Network, Zero, block::Transaction};
30
31use std::{io, net::SocketAddr};
32
33impl<N: Network, C: ConsensusStorage<N>> P2P for Prover<N, C> {
34 fn tcp(&self) -> &Tcp {
36 self.router.tcp()
37 }
38}
39
40#[async_trait]
41impl<N: Network, C: ConsensusStorage<N>> Handshake for Prover<N, C> {
42 async fn perform_handshake(&self, mut connection: Connection) -> io::Result<Connection> {
44 let peer_addr = connection.addr();
46 let conn_side = connection.side();
47 let stream = self.borrow_stream(&mut connection);
48 let genesis_header = *self.genesis.header();
49 let restrictions_id = Field::zero(); self.router.handshake(peer_addr, stream, conn_side, genesis_header, restrictions_id).await?;
51
52 Ok(connection)
53 }
54}
55
56#[async_trait]
57impl<N: Network, C: ConsensusStorage<N>> OnConnect for Prover<N, C>
58where
59 Self: Outbound<N>,
60{
61 async fn on_connect(&self, peer_addr: SocketAddr) {
62 let Some(peer_ip) = self.router.resolve_to_listener(&peer_addr) else { return };
64 self.ping.on_peer_connected(peer_ip);
66 }
67}
68
69#[async_trait]
70impl<N: Network, C: ConsensusStorage<N>> Disconnect for Prover<N, C> {
71 async fn handle_disconnect(&self, peer_addr: SocketAddr) {
73 if let Some(peer_ip) = self.router.resolve_to_listener(&peer_addr) {
74 self.sync.remove_peer(&peer_ip);
75 self.router.remove_connected_peer(peer_ip);
76 }
77 }
78}
79
80#[async_trait]
81impl<N: Network, C: ConsensusStorage<N>> Reading for Prover<N, C> {
82 type Codec = MessageCodec<N>;
83 type Message = Message<N>;
84
85 fn codec(&self, _peer_addr: SocketAddr, _side: ConnectionSide) -> Self::Codec {
88 Default::default()
89 }
90
91 async fn process_message(&self, peer_addr: SocketAddr, message: Self::Message) -> io::Result<()> {
93 if let Err(error) = self.inbound(peer_addr, message).await {
95 if let Some(peer_ip) = self.router().resolve_to_listener(&peer_addr) {
96 warn!("Disconnecting from '{peer_addr}' - {error}");
97 self.router().send(peer_ip, Message::Disconnect(DisconnectReason::ProtocolViolation.into()));
98 self.router().disconnect(peer_ip);
100 }
101 }
102 Ok(())
103 }
104}
105
106#[async_trait]
107impl<N: Network, C: ConsensusStorage<N>> Routing<N> for Prover<N, C> {}
108
109impl<N: Network, C: ConsensusStorage<N>> Heartbeat<N> for Prover<N, C> {
110 fn handle_puzzle_request(&self) {
112 if let Some((sync_peers, _)) = self.sync.find_sync_peers() {
114 if let Some((peer_ip, _)) = sync_peers.into_iter().max_by_key(|(_, height)| *height) {
116 self.router().send(peer_ip, Message::PuzzleRequest(PuzzleRequest));
118 }
119 }
120 }
121}
122
123impl<N: Network, C: ConsensusStorage<N>> Outbound<N> for Prover<N, C> {
124 fn router(&self) -> &Router<N> {
126 &self.router
127 }
128
129 fn is_block_synced(&self) -> bool {
131 true
132 }
133
134 fn num_blocks_behind(&self) -> Option<u32> {
137 Some(0)
139 }
140}
141
142#[async_trait]
143impl<N: Network, C: ConsensusStorage<N>> Inbound<N> for Prover<N, C> {
144 fn is_valid_message_version(&self, message_version: u32) -> bool {
146 self.router().is_valid_message_version(message_version)
147 }
148
149 fn block_request(&self, peer_ip: SocketAddr, _message: BlockRequest) -> bool {
151 debug!("Disconnecting '{peer_ip}' for the following reason - {:?}", DisconnectReason::ProtocolViolation);
152 false
153 }
154
155 fn block_response(&self, peer_ip: SocketAddr, _blocks: Vec<Block<N>>) -> bool {
157 debug!("Disconnecting '{peer_ip}' for the following reason - {:?}", DisconnectReason::ProtocolViolation);
158 false
159 }
160
161 fn ping(&self, peer_ip: SocketAddr, message: Ping<N>) -> bool {
163 if let Some(block_locators) = message.block_locators {
165 if let Err(error) = self.sync.update_peer_locators(peer_ip, block_locators) {
167 warn!("Peer '{peer_ip}' sent invalid block locators: {error}");
168 return false;
169 }
170 }
171
172 self.router().send(peer_ip, Message::Pong(Pong { is_fork: Some(false) }));
174 true
175 }
176
177 fn pong(&self, peer_ip: SocketAddr, _message: Pong) -> bool {
179 self.ping.on_pong_received(peer_ip);
180 true
181 }
182
183 fn puzzle_request(&self, peer_ip: SocketAddr) -> bool {
185 debug!("Disconnecting '{peer_ip}' for the following reason - {:?}", DisconnectReason::ProtocolViolation);
186 false
187 }
188
189 fn puzzle_response(&self, peer_ip: SocketAddr, epoch_hash: N::BlockHash, header: Header<N>) -> bool {
191 let block_height = header.height();
193
194 info!(
195 "Puzzle (Block {block_height}, Coinbase Target {}, Proof Target {})",
196 header.coinbase_target(),
197 header.proof_target()
198 );
199
200 self.latest_epoch_hash.write().replace(epoch_hash);
202 self.latest_block_header.write().replace(header);
204
205 trace!("Received 'PuzzleResponse' from '{peer_ip}' (Block {block_height})");
206 true
207 }
208
209 async fn unconfirmed_solution(
211 &self,
212 peer_ip: SocketAddr,
213 serialized: UnconfirmedSolution<N>,
214 solution: Solution<N>,
215 ) -> bool {
216 let epoch_hash = *self.latest_epoch_hash.read();
218 let proof_target = self.latest_block_header.read().as_ref().map(|header| header.proof_target());
220
221 if let (Some(epoch_hash), Some(proof_target)) = (epoch_hash, proof_target) {
222 let puzzle = self.puzzle.clone();
224 let is_valid =
225 tokio::task::spawn_blocking(move || puzzle.check_solution(&solution, epoch_hash, proof_target)).await;
226
227 match is_valid {
228 Ok(Ok(())) => {
230 let message = Message::UnconfirmedSolution(serialized);
231 self.propagate(message, &[peer_ip]);
233 }
234 Ok(Err(_)) => {
235 trace!("Invalid solution '{}' for the proof target.", solution.id())
236 }
237 Err(error) => {
239 if let Some(height) = self.latest_block_header.read().as_ref().map(|header| header.height()) {
240 if height % N::NUM_BLOCKS_PER_EPOCH > 10 {
241 warn!("Failed to verify the solution - {error}")
242 }
243 }
244 }
245 }
246 }
247 true
248 }
249
250 async fn unconfirmed_transaction(
252 &self,
253 _peer_ip: SocketAddr,
254 _serialized: UnconfirmedTransaction<N>,
255 _transaction: Transaction<N>,
256 ) -> bool {
257 true
258 }
259}