diff --git a/substrate/client/network/src/service.rs b/substrate/client/network/src/service.rs index 89ddf6fafd..d9e970a61a 100644 --- a/substrate/client/network/src/service.rs +++ b/substrate/client/network/src/service.rs @@ -478,6 +478,18 @@ impl NetworkWorker { self.network_service.user_protocol_mut().on_block_finalized(hash, &header); } + /// Returns the local `PeerId`. + pub fn local_peer_id(&self) -> &PeerId { + Swarm::::local_peer_id(&self.network_service) + } + + /// Returns the list of addresses we are listening on. + /// + /// Does **NOT** include a trailing `/p2p/` with our `PeerId`. + pub fn listen_addresses(&self) -> impl Iterator { + Swarm::::listeners(&self.network_service) + } + /// Get network state. /// /// **Note**: Use this only for debugging. This API is unstable. There are warnings literally diff --git a/substrate/client/rpc-api/src/system/mod.rs b/substrate/client/rpc-api/src/system/mod.rs index 25f147b694..e66ac97a68 100644 --- a/substrate/client/rpc-api/src/system/mod.rs +++ b/substrate/client/rpc-api/src/system/mod.rs @@ -59,6 +59,17 @@ pub trait SystemApi { #[rpc(name = "system_health", returns = "Health")] fn system_health(&self) -> Receiver; + /// Returns the base58-encoded PeerId of the node. + #[rpc(name = "system_localPeerId", returns = "String")] + fn system_local_peer_id(&self) -> Receiver; + + /// Returns the multiaddresses that the local node is listening on + /// + /// The addresses include a trailing `/p2p/` with the local PeerId, and are thus suitable to + /// be passed to `system_addReservedPeer` or as a bootnode address for example. + #[rpc(name = "system_localListenAddresses", returns = "Vec")] + fn system_local_listen_addresses(&self) -> Receiver>; + /// Returns currently connected peers #[rpc(name = "system_peers", returns = "Vec>")] fn system_peers(&self) -> Receiver>>; diff --git a/substrate/client/rpc/src/system/mod.rs b/substrate/client/rpc/src/system/mod.rs index e18d4d09a1..84e06c20a6 100644 --- a/substrate/client/rpc/src/system/mod.rs +++ b/substrate/client/rpc/src/system/mod.rs @@ -41,6 +41,11 @@ pub struct System { pub enum Request { /// Must return the health of the network. Health(oneshot::Sender), + /// Must return the base58-encoded local `PeerId`. + LocalPeerId(oneshot::Sender), + /// Must return the string representation of the addresses we listen on, including the + /// trailing `/p2p/`. + LocalListenAddresses(oneshot::Sender>), /// Must return information about the peers we are connected to. Peers(oneshot::Sender::Number>>>), /// Must return the state of the network. @@ -96,6 +101,18 @@ impl SystemApi::Number> for Sy Receiver(Compat::new(rx)) } + fn system_local_peer_id(&self) -> Receiver { + let (tx, rx) = oneshot::channel(); + let _ = self.send_back.unbounded_send(Request::LocalPeerId(tx)); + Receiver(Compat::new(rx)) + } + + fn system_local_listen_addresses(&self) -> Receiver> { + let (tx, rx) = oneshot::channel(); + let _ = self.send_back.unbounded_send(Request::LocalListenAddresses(tx)); + Receiver(Compat::new(rx)) + } + fn system_peers(&self) -> Receiver::Number>>> { let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::Peers(tx)); diff --git a/substrate/client/rpc/src/system/tests.rs b/substrate/client/rpc/src/system/tests.rs index f0331f50ed..921d941a1c 100644 --- a/substrate/client/rpc/src/system/tests.rs +++ b/substrate/client/rpc/src/system/tests.rs @@ -55,6 +55,15 @@ fn api>>(sync: T) -> System { should_have_peers, }); }, + Request::LocalPeerId(sender) => { + let _ = sender.send("QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".to_string()); + }, + Request::LocalListenAddresses(sender) => { + let _ = sender.send(vec![ + "/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".to_string(), + "/ip4/127.0.0.1/tcp/30334/ws/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".to_string(), + ]); + }, Request::Peers(sender) => { let mut peers = vec![]; for _peer in 0..status.peers { @@ -208,6 +217,25 @@ fn system_health() { ); } +#[test] +fn system_local_peer_id_works() { + assert_eq!( + wait_receiver(api(None).system_local_peer_id()), + "QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".to_owned(), + ); +} + +#[test] +fn system_local_listen_addresses_works() { + assert_eq!( + wait_receiver(api(None).system_local_listen_addresses()), + vec![ + "/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".to_string(), + "/ip4/127.0.0.1/tcp/30334/ws/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".to_string(), + ] + ); +} + #[test] fn system_peers() { let peer_id = PeerId::random(); diff --git a/substrate/client/service/src/lib.rs b/substrate/client/service/src/lib.rs index 969453210e..f416d363de 100644 --- a/substrate/client/service/src/lib.rs +++ b/substrate/client/service/src/lib.rs @@ -373,6 +373,17 @@ fn build_network_future< should_have_peers, }); }, + sc_rpc::system::Request::LocalPeerId(sender) => { + let _ = sender.send(network.local_peer_id().to_base58()); + }, + sc_rpc::system::Request::LocalListenAddresses(sender) => { + let peer_id = network.local_peer_id().clone().into(); + let p2p_proto_suffix = sc_network::multiaddr::Protocol::P2p(peer_id); + let addresses = network.listen_addresses() + .map(|addr| addr.clone().with(p2p_proto_suffix.clone()).to_string()) + .collect(); + let _ = sender.send(addresses); + }, sc_rpc::system::Request::Peers(sender) => { let _ = sender.send(network.peers_debug_info().into_iter().map(|(peer_id, p)| sc_rpc::system::PeerInfo {