p2p/peer/
p2p_peer_actions.rs1use 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 #[action_event(level = debug)]
11 Discovered {
12 peer_id: PeerId,
13 dial_opts: Option<P2pConnectionOutgoingInitOpts>,
14 },
15 Ready { peer_id: PeerId, incoming: bool },
17 BestTipUpdate {
19 peer_id: PeerId,
20 best_tip: ArcBlockWithHash,
21 },
22 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 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}