|
21 | 21 | use std::{ |
22 | 22 | collections::{hash_map::Entry, HashMap, HashSet, VecDeque}, |
23 | 23 | num::NonZeroUsize, |
| 24 | + sync::Arc, |
24 | 25 | task::{Context, Poll}, |
25 | 26 | time::Duration, |
26 | 27 | }; |
27 | 28 |
|
28 | 29 | use libp2p_core::{ |
29 | | - multiaddr, multiaddr::Protocol, transport::PortUse, ConnectedPoint, Endpoint, Multiaddr, |
| 30 | + multiaddr::{self, Protocol}, |
| 31 | + transport::PortUse, |
| 32 | + ConnectedPoint, Endpoint, Multiaddr, |
30 | 33 | }; |
31 | | -use libp2p_identity::{PeerId, PublicKey}; |
| 34 | +use libp2p_identity::{Keypair, PeerId, PublicKey}; |
32 | 35 | use libp2p_swarm::{ |
33 | 36 | behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm}, |
34 | 37 | ConnectionDenied, ConnectionId, DialError, ExternalAddresses, ListenAddresses, |
@@ -117,8 +120,10 @@ pub struct Config { |
117 | 120 | /// Application-specific version of the protocol family used by the peer, |
118 | 121 | /// e.g. `ipfs/1.0.0` or `polkadot/1.0.0`. |
119 | 122 | protocol_version: String, |
120 | | - /// The public key of the local node. To report on the wire. |
121 | | - local_public_key: PublicKey, |
| 123 | + /// The key of the local node. Only the public key will be report on the wire. |
| 124 | + /// The behaviour will send signed [`PeerRecord`](libp2p_core::PeerRecord) in |
| 125 | + /// its identify message only when supplied with a keypair. |
| 126 | + local_key: Arc<KeyType>, |
122 | 127 | /// Name and version of the local peer implementation, similar to the |
123 | 128 | /// `User-Agent` header in the HTTP protocol. |
124 | 129 | /// |
@@ -156,12 +161,26 @@ pub struct Config { |
156 | 161 |
|
157 | 162 | impl Config { |
158 | 163 | /// Creates a new configuration for the identify [`Behaviour`] that |
159 | | - /// advertises the given protocol version and public key. |
| 164 | + /// advertises the given protocol version and public key. |
| 165 | + /// Use [`new_with_signed_peer_record`](Config::new_with_signed_peer_record) for |
| 166 | + /// `signedPeerRecord` support. |
160 | 167 | pub fn new(protocol_version: String, local_public_key: PublicKey) -> Self { |
| 168 | + Self::new_with_key(protocol_version, local_public_key) |
| 169 | + } |
| 170 | + |
| 171 | + /// Creates a new configuration for the identify [`Behaviour`] that |
| 172 | + /// advertises the given protocol version and public key. |
| 173 | + /// The private key will be used to sign [`PeerRecord`](libp2p_core::PeerRecord) |
| 174 | + /// for verifiable address advertisement. |
| 175 | + pub fn new_with_signed_peer_record(protocol_version: String, local_keypair: &Keypair) -> Self { |
| 176 | + Self::new_with_key(protocol_version, local_keypair) |
| 177 | + } |
| 178 | + |
| 179 | + fn new_with_key(protocol_version: String, key: impl Into<KeyType>) -> Self { |
161 | 180 | Self { |
162 | 181 | protocol_version, |
163 | 182 | agent_version: format!("rust-libp2p/{}", env!("CARGO_PKG_VERSION")), |
164 | | - local_public_key, |
| 183 | + local_key: Arc::new(key.into()), |
165 | 184 | interval: Duration::from_secs(5 * 60), |
166 | 185 | push_listen_addr_updates: false, |
167 | 186 | cache_size: 100, |
@@ -209,7 +228,7 @@ impl Config { |
209 | 228 |
|
210 | 229 | /// Get the local public key of the Config. |
211 | 230 | pub fn local_public_key(&self) -> &PublicKey { |
212 | | - &self.local_public_key |
| 231 | + self.local_key.public_key() |
213 | 232 | } |
214 | 233 |
|
215 | 234 | /// Get the agent version of the Config. |
@@ -380,7 +399,7 @@ impl NetworkBehaviour for Behaviour { |
380 | 399 | Ok(Handler::new( |
381 | 400 | self.config.interval, |
382 | 401 | peer, |
383 | | - self.config.local_public_key.clone(), |
| 402 | + self.config.local_key.clone(), |
384 | 403 | self.config.protocol_version.clone(), |
385 | 404 | self.config.agent_version.clone(), |
386 | 405 | remote_addr.clone(), |
@@ -413,7 +432,7 @@ impl NetworkBehaviour for Behaviour { |
413 | 432 | Ok(Handler::new( |
414 | 433 | self.config.interval, |
415 | 434 | peer, |
416 | | - self.config.local_public_key.clone(), |
| 435 | + self.config.local_key.clone(), |
417 | 436 | self.config.protocol_version.clone(), |
418 | 437 | self.config.agent_version.clone(), |
419 | 438 | // TODO: This is weird? That is the public address we dialed, |
@@ -670,6 +689,37 @@ impl PeerCache { |
670 | 689 | } |
671 | 690 | } |
672 | 691 |
|
| 692 | +#[derive(Debug, Clone)] |
| 693 | +#[allow(clippy::large_enum_variant)] |
| 694 | +pub(crate) enum KeyType { |
| 695 | + PublicKey(PublicKey), |
| 696 | + Keypair { |
| 697 | + keypair: Keypair, |
| 698 | + public_key: PublicKey, |
| 699 | + }, |
| 700 | +} |
| 701 | +impl From<PublicKey> for KeyType { |
| 702 | + fn from(value: PublicKey) -> Self { |
| 703 | + Self::PublicKey(value) |
| 704 | + } |
| 705 | +} |
| 706 | +impl From<&Keypair> for KeyType { |
| 707 | + fn from(value: &Keypair) -> Self { |
| 708 | + Self::Keypair { |
| 709 | + public_key: value.public(), |
| 710 | + keypair: value.clone(), |
| 711 | + } |
| 712 | + } |
| 713 | +} |
| 714 | +impl KeyType { |
| 715 | + pub(crate) fn public_key(&self) -> &PublicKey { |
| 716 | + match &self { |
| 717 | + KeyType::PublicKey(pubkey) => pubkey, |
| 718 | + KeyType::Keypair { public_key, .. } => public_key, |
| 719 | + } |
| 720 | + } |
| 721 | +} |
| 722 | + |
673 | 723 | #[cfg(test)] |
674 | 724 | mod tests { |
675 | 725 | use super::*; |
|
0 commit comments