p2p/peer/
p2p_peer_actions.rs

1use openmina_core::{block::ArcBlockWithHash, ActionEvent};
2use serde::{Deserialize, Serialize};
3
4use crate::{connection::outgoing::P2pConnectionOutgoingInitOpts, P2pState, PeerId};
5
6#[derive(Serialize, Deserialize, Debug, Clone, ActionEvent)]
7#[action_event(level = debug, fields(display(peer_id), debug(dial_opts), best_tip = display(&best_tip.hash), incoming))]
8pub enum P2pPeerAction {
9    /// Peer is discovered.
10    #[action_event(level = debug)]
11    Discovered {
12        peer_id: PeerId,
13        dial_opts: Option<P2pConnectionOutgoingInitOpts>,
14    },
15    /// Peer is ready.
16    Ready { peer_id: PeerId, incoming: bool },
17    /// Peer's best tip is updated.
18    BestTipUpdate {
19        peer_id: PeerId,
20        best_tip: ArcBlockWithHash,
21    },
22    /// Remove peer from state
23    Remove { peer_id: PeerId },
24}
25
26impl P2pPeerAction {
27    pub fn peer_id(&self) -> &PeerId {
28        match self {
29            Self::Discovered { peer_id, .. } => peer_id,
30            Self::Ready { peer_id, .. } => peer_id,
31            Self::BestTipUpdate { peer_id, .. } => peer_id,
32            Self::Remove { peer_id } => peer_id,
33        }
34    }
35}
36
37impl redux::EnablingCondition<P2pState> for P2pPeerAction {
38    fn is_enabled(&self, state: &P2pState, _time: redux::Timestamp) -> bool {
39        match self {
40            P2pPeerAction::Discovered { peer_id, .. } => {
41                peer_id != &state.my_id()
42                    && state
43                        .peers
44                        .get(peer_id)
45                        .is_none_or(|p| p.dial_opts.is_none())
46                    && state.peers.len() < state.config.limits.max_peers_in_state()
47            }
48            P2pPeerAction::Ready { peer_id, .. } => state
49                .peers
50                .get(peer_id)
51                .is_some_and(|p| p.status.is_connecting_success()),
52            P2pPeerAction::BestTipUpdate { peer_id, .. } => {
53                // TODO: don't enable if block inferior than existing peer's
54                // best tip.
55                state.get_ready_peer(peer_id).is_some()
56            }
57            P2pPeerAction::Remove { peer_id } => {
58                state.peers.len() > state.config.limits.min_peers_in_state()
59                    && state.peers.contains_key(peer_id)
60            }
61        }
62    }
63}