openmina_node_common/service/
p2p.rs

1use std::collections::BTreeMap;
2
3use node::{
4    core::channels::mpsc,
5    event_source::Event,
6    p2p::{
7        connection::outgoing::P2pConnectionOutgoingInitOpts,
8        identity::{EncryptableType, PublicKey},
9        webrtc::ConnectionAuth,
10        PeerId,
11    },
12};
13use rand::prelude::*;
14#[cfg(feature = "p2p-libp2p")]
15use sha3::digest::XofReader;
16
17pub use node::p2p::{service::*, service_impl::*};
18
19use crate::NodeService;
20
21impl webrtc::P2pServiceWebrtc for NodeService {
22    type Event = Event;
23
24    fn random_pick(
25        &mut self,
26        list: &[P2pConnectionOutgoingInitOpts],
27    ) -> Option<P2pConnectionOutgoingInitOpts> {
28        list.choose(&mut self.rng).cloned()
29    }
30
31    fn event_sender(&self) -> &mpsc::UnboundedSender<Self::Event> {
32        self.event_sender()
33    }
34
35    fn cmd_sender(&self) -> &mpsc::TrackedUnboundedSender<webrtc::Cmd> {
36        &self.p2p.webrtc.cmd_sender
37    }
38
39    fn peers(&mut self) -> &mut BTreeMap<PeerId, webrtc::PeerState> {
40        &mut self.p2p.webrtc.peers
41    }
42
43    fn encrypt<T: EncryptableType>(
44        &mut self,
45        other_pk: &PublicKey,
46        message: &T,
47    ) -> Result<T::Encrypted, Box<dyn std::error::Error>> {
48        let rng = &mut self.rng;
49        self.p2p.sec_key.encrypt(other_pk, rng, message)
50    }
51
52    fn decrypt<T: EncryptableType>(
53        &mut self,
54        other_pk: &PublicKey,
55        encrypted: &T::Encrypted,
56    ) -> Result<T, Box<dyn std::error::Error>> {
57        self.p2p.sec_key.decrypt(other_pk, encrypted)
58    }
59
60    #[cfg(not(feature = "p2p-webrtc"))]
61    fn auth_encrypt_and_send(
62        &mut self,
63        peer_id: PeerId,
64        other_pub_key: &PublicKey,
65        auth: ConnectionAuth,
66    ) {
67        let _ = (peer_id, other_pub_key, auth);
68    }
69
70    #[cfg(feature = "p2p-webrtc")]
71    fn auth_encrypt_and_send(
72        &mut self,
73        peer_id: PeerId,
74        other_pub_key: &PublicKey,
75        auth: ConnectionAuth,
76    ) {
77        let encrypted = auth.encrypt(&self.p2p.sec_key, other_pub_key, &mut self.rng);
78        Self::auth_send(self, peer_id, other_pub_key, encrypted);
79    }
80
81    fn auth_decrypt(
82        &mut self,
83        other_pub_key: &PublicKey,
84        auth: node::p2p::webrtc::ConnectionAuthEncrypted,
85    ) -> Option<ConnectionAuth> {
86        auth.decrypt(&self.p2p.sec_key, other_pub_key)
87    }
88}
89
90impl webrtc_with_libp2p::P2pServiceWebrtcWithLibp2p for NodeService {
91    #[cfg(feature = "p2p-libp2p")]
92    fn mio(&mut self) -> &mut mio::MioService {
93        &mut self.p2p.mio
94    }
95
96    fn connections(&self) -> std::collections::BTreeSet<PeerId> {
97        self.p2p.webrtc.peers.keys().copied().collect()
98    }
99}
100
101#[cfg(feature = "p2p-libp2p")]
102impl P2pCryptoService for NodeService {
103    fn generate_random_nonce(&mut self) -> [u8; 24] {
104        self.rng.gen()
105    }
106
107    fn ephemeral_sk(&mut self) -> [u8; 32] {
108        let mut r = [0; 32];
109        self.rng_ephemeral.read(&mut r);
110        r
111    }
112
113    fn static_sk(&mut self) -> [u8; 32] {
114        let mut r = [0; 32];
115        self.rng_static.read(&mut r);
116        r
117    }
118
119    fn sign_key(&mut self, key: &[u8; 32]) -> Vec<u8> {
120        // TODO: make deterministic
121        let msg = [b"noise-libp2p-static-key:", key.as_slice()].concat();
122        let sig = self.p2p.sec_key.sign(&msg);
123        let libp2p_sec_key = libp2p_identity::Keypair::try_from(self.p2p.sec_key.clone()).unwrap();
124
125        let mut payload = vec![];
126        payload.extend_from_slice(b"\x0a\x24");
127        payload.extend_from_slice(&libp2p_sec_key.public().encode_protobuf());
128        payload.extend_from_slice(b"\x12\x40");
129        payload.extend_from_slice(&sig.to_bytes());
130        payload
131    }
132
133    fn sign_publication(&mut self, publication: &[u8]) -> Vec<u8> {
134        self.p2p
135            .sec_key
136            .libp2p_pubsub_sign(publication)
137            .to_bytes()
138            .to_vec()
139    }
140
141    fn verify_publication(
142        &mut self,
143        pk: &libp2p_identity::PublicKey,
144        publication: &[u8],
145        sig: &[u8],
146    ) -> bool {
147        let msg: Vec<u8> = [b"libp2p-pubsub:", publication].concat();
148        pk.verify(&msg, sig)
149    }
150}