Add PeerId::random() (#661)

This commit is contained in:
Pierre Krieger
2018-11-20 13:44:36 +01:00
committed by GitHub
parent 080a75451f
commit b213fd7bd7
10 changed files with 92 additions and 39 deletions

View File

@ -477,7 +477,6 @@ mod tests {
use futures::future::{self}; use futures::future::{self};
use tests::dummy_muxer::{DummyMuxer, DummyConnectionState}; use tests::dummy_muxer::{DummyMuxer, DummyConnectionState};
use tests::dummy_handler::{Handler, InEvent, OutEvent, HandlerState}; use tests::dummy_handler::{Handler, InEvent, OutEvent, HandlerState};
use PublicKey;
use tokio::runtime::current_thread::Runtime; use tokio::runtime::current_thread::Runtime;
use tokio::runtime::Builder; use tokio::runtime::Builder;
use nodes::NodeHandlerEvent; use nodes::NodeHandlerEvent;
@ -490,7 +489,7 @@ mod tests {
#[test] #[test]
fn has_connection_is_false_before_a_connection_has_been_made() { fn has_connection_is_false_before_a_connection_has_been_made() {
let cs = TestCollectionStream::new(); let cs = TestCollectionStream::new();
let peer_id = PublicKey::Rsa((0 .. 128).map(|_| -> u8 { 1 }).collect()).into_peer_id(); let peer_id = PeerId::random();
assert!(!cs.has_connection(&peer_id)); assert!(!cs.has_connection(&peer_id));
} }
@ -503,7 +502,7 @@ mod tests {
#[test] #[test]
fn retrieving_a_peer_is_none_if_peer_is_missing_or_not_connected() { fn retrieving_a_peer_is_none_if_peer_is_missing_or_not_connected() {
let mut cs = TestCollectionStream::new(); let mut cs = TestCollectionStream::new();
let peer_id = PublicKey::Rsa((0 .. 128).map(|_| -> u8 { 1 }).collect()).into_peer_id(); let peer_id = PeerId::random();
assert!(cs.peer_mut(&peer_id).is_none()); assert!(cs.peer_mut(&peer_id).is_none());
let handler = Handler::default(); let handler = Handler::default();
@ -515,7 +514,7 @@ mod tests {
#[test] #[test]
fn collection_stream_reaches_the_nodes() { fn collection_stream_reaches_the_nodes() {
let mut cs = TestCollectionStream::new(); let mut cs = TestCollectionStream::new();
let peer_id = PublicKey::Rsa((0 .. 128).map(|_| -> u8 { 1 }).collect()).into_peer_id(); let peer_id = PeerId::random();
let mut muxer = DummyMuxer::new(); let mut muxer = DummyMuxer::new();
muxer.set_inbound_connection_state(DummyConnectionState::Pending); muxer.set_inbound_connection_state(DummyConnectionState::Pending);
@ -544,7 +543,7 @@ mod tests {
#[test] #[test]
fn accepting_a_node_yields_new_entry() { fn accepting_a_node_yields_new_entry() {
let mut cs = TestCollectionStream::new(); let mut cs = TestCollectionStream::new();
let peer_id = PublicKey::Rsa((0 .. 128).map(|_| -> u8 { 1 }).collect()).into_peer_id(); let peer_id = PeerId::random();
let fut = future::ok::<_, Void>((peer_id.clone(), DummyMuxer::new())); let fut = future::ok::<_, Void>((peer_id.clone(), DummyMuxer::new()));
cs.add_reach_attempt(fut, Handler::default()); cs.add_reach_attempt(fut, Handler::default());
@ -581,7 +580,7 @@ mod tests {
#[test] #[test]
fn events_in_a_node_reaches_the_collection_stream() { fn events_in_a_node_reaches_the_collection_stream() {
let cs = Arc::new(Mutex::new(TestCollectionStream::new())); let cs = Arc::new(Mutex::new(TestCollectionStream::new()));
let task_peer_id = PublicKey::Rsa((0 .. 128).map(|_| -> u8 { 1 }).collect()).into_peer_id(); let task_peer_id = PeerId::random();
let mut handler = Handler::default(); let mut handler = Handler::default();
handler.state = Some(HandlerState::Ready(Some(NodeHandlerEvent::Custom(OutEvent::Custom("init"))))); handler.state = Some(HandlerState::Ready(Some(NodeHandlerEvent::Custom(OutEvent::Custom("init")))));
@ -683,7 +682,7 @@ mod tests {
#[test] #[test]
fn task_closed_with_error_when_task_is_connected_yields_node_error() { fn task_closed_with_error_when_task_is_connected_yields_node_error() {
let cs = Arc::new(Mutex::new(TestCollectionStream::new())); let cs = Arc::new(Mutex::new(TestCollectionStream::new()));
let peer_id = PublicKey::Rsa((0 .. 128).map(|_| -> u8 { 1 }).collect()).into_peer_id(); let peer_id = PeerId::random();
let muxer = DummyMuxer::new(); let muxer = DummyMuxer::new();
let task_inner_fut = future::ok::<_, Void>((peer_id.clone(), muxer)); let task_inner_fut = future::ok::<_, Void>((peer_id.clone(), muxer));
let mut handler = Handler::default(); let mut handler = Handler::default();
@ -729,7 +728,7 @@ mod tests {
#[test] #[test]
fn task_closed_ok_when_task_is_connected_yields_node_closed() { fn task_closed_ok_when_task_is_connected_yields_node_closed() {
let cs = Arc::new(Mutex::new(TestCollectionStream::new())); let cs = Arc::new(Mutex::new(TestCollectionStream::new()));
let peer_id = PublicKey::Rsa((0 .. 128).map(|_| -> u8 { 1 }).collect()).into_peer_id(); let peer_id = PeerId::random();
let muxer = DummyMuxer::new(); let muxer = DummyMuxer::new();
let task_inner_fut = future::ok::<_, Void>((peer_id.clone(), muxer)); let task_inner_fut = future::ok::<_, Void>((peer_id.clone(), muxer));
let mut handler = Handler::default(); let mut handler = Handler::default();
@ -795,7 +794,7 @@ mod tests {
#[test] #[test]
fn interrupting_an_established_connection_is_err() { fn interrupting_an_established_connection_is_err() {
let cs = Arc::new(Mutex::new(TestCollectionStream::new())); let cs = Arc::new(Mutex::new(TestCollectionStream::new()));
let peer_id = PublicKey::Rsa((0 .. 128).map(|_| -> u8 { 1 }).collect()).into_peer_id(); let peer_id = PeerId::random();
let muxer = DummyMuxer::new(); let muxer = DummyMuxer::new();
let task_inner_fut = future::ok::<_, Void>((peer_id.clone(), muxer)); let task_inner_fut = future::ok::<_, Void>((peer_id.clone(), muxer));
let handler = Handler::default(); let handler = Handler::default();

View File

@ -467,13 +467,12 @@ mod tests {
use futures::future::{self, FutureResult}; use futures::future::{self, FutureResult};
use futures::sync::mpsc::{UnboundedReceiver, UnboundedSender}; use futures::sync::mpsc::{UnboundedReceiver, UnboundedSender};
use nodes::handled_node::NodeHandlerEvent; use nodes::handled_node::NodeHandlerEvent;
use rand::random;
use tests::dummy_handler::{Handler, HandlerState, InEvent, OutEvent, TestHandledNode}; use tests::dummy_handler::{Handler, HandlerState, InEvent, OutEvent, TestHandledNode};
use tests::dummy_muxer::{DummyMuxer, DummyConnectionState}; use tests::dummy_muxer::{DummyMuxer, DummyConnectionState};
use tokio::runtime::Builder; use tokio::runtime::Builder;
use tokio::runtime::current_thread::Runtime; use tokio::runtime::current_thread::Runtime;
use void::Void; use void::Void;
use {PeerId, PublicKey}; use PeerId;
type TestNodeTask = NodeTask< type TestNodeTask = NodeTask<
FutureResult<(PeerId, DummyMuxer), IoError>, FutureResult<(PeerId, DummyMuxer), IoError>,
@ -495,7 +494,7 @@ mod tests {
task_id: TaskId(123), task_id: TaskId(123),
inner_node: None, inner_node: None,
inner_fut: { inner_fut: {
let peer_id = PublicKey::Rsa((0 .. 2048).map(|_| -> u8 { random() }).collect()).into_peer_id(); let peer_id = PeerId::random();
Some(future::ok((peer_id, DummyMuxer::new()))) Some(future::ok((peer_id, DummyMuxer::new())))
}, },
} }
@ -576,7 +575,7 @@ mod tests {
} }
fn handled_nodes_tasks(&mut self) -> (TestHandledNodesTasks, Vec<TaskId>) { fn handled_nodes_tasks(&mut self) -> (TestHandledNodesTasks, Vec<TaskId>) {
let mut handled_nodes = HandledNodesTasks::new(); let mut handled_nodes = HandledNodesTasks::new();
let peer_id = PublicKey::Rsa((0 .. 2048).map(|_| -> u8 { random() }).collect()).into_peer_id(); let peer_id = PeerId::random();
let mut task_ids = Vec::new(); let mut task_ids = Vec::new();
for _i in 0..self.task_count { for _i in 0..self.task_count {
let fut = future::ok::<_, Void>((peer_id.clone(), self.muxer.clone())); let fut = future::ok::<_, Void>((peer_id.clone(), self.muxer.clone()));
@ -628,7 +627,7 @@ mod tests {
fn task_exits_when_node_is_done() { fn task_exits_when_node_is_done() {
let mut rt = Runtime::new().unwrap(); let mut rt = Runtime::new().unwrap();
let fut = { let fut = {
let peer_id = PublicKey::Rsa((0 .. 2048).map(|_| -> u8 { random() }).collect()).into_peer_id(); let peer_id = PeerId::random();
let mut muxer = DummyMuxer::new(); let mut muxer = DummyMuxer::new();
muxer.set_inbound_connection_state(DummyConnectionState::Closed); muxer.set_inbound_connection_state(DummyConnectionState::Closed);
muxer.set_outbound_connection_state(DummyConnectionState::Closed); muxer.set_outbound_connection_state(DummyConnectionState::Closed);

View File

@ -75,6 +75,16 @@ impl PeerId {
} }
} }
/// Generates a random peer ID from a cryptographically secure PRNG.
///
/// This is useful for randomly walking on a DHT, or for testing purposes.
#[inline]
pub fn random() -> PeerId {
PeerId {
multihash: multihash::Multihash::random(multihash::Hash::SHA2256)
}
}
/// Returns a raw bytes representation of this `PeerId`. /// Returns a raw bytes representation of this `PeerId`.
/// ///
/// Note that this is not the same as the public key of the peer. /// Note that this is not the same as the public key of the peer.
@ -179,4 +189,12 @@ mod tests {
let second: PeerId = peer_id.to_base58().parse().unwrap(); let second: PeerId = peer_id.to_base58().parse().unwrap();
assert_eq!(peer_id, second); assert_eq!(peer_id, second);
} }
#[test]
fn random_peer_id_is_valid() {
for _ in 0 .. 5000 {
let peer_id = PeerId::random();
assert_eq!(peer_id, PeerId::from_bytes(peer_id.clone().into_bytes()).unwrap());
}
}
} }

View File

@ -17,6 +17,7 @@ documentation = "https://docs.rs/multihash/"
[dependencies] [dependencies]
blake2 = { version = "0.7", default-features = false } blake2 = { version = "0.7", default-features = false }
rand = { version = "0.6", default-features = false, features = ["std"] }
sha1 = "0.5" sha1 = "0.5"
sha2 = { version = "0.7", default-features = false } sha2 = { version = "0.7", default-features = false }
tiny-keccak = "1.4" tiny-keccak = "1.4"

View File

@ -6,6 +6,7 @@
//! A `MultihashRef` is the same as a `Multihash`, except that it doesn't own its data. //! A `MultihashRef` is the same as a `Multihash`, except that it doesn't own its data.
extern crate blake2; extern crate blake2;
extern crate rand;
extern crate sha1; extern crate sha1;
extern crate sha2; extern crate sha2;
extern crate tiny_keccak; extern crate tiny_keccak;
@ -132,6 +133,28 @@ impl Multihash {
Ok(Multihash { bytes }) Ok(Multihash { bytes })
} }
/// Generates a random `Multihash` from a cryptographically secure PRNG.
pub fn random(hash: Hash) -> Multihash {
let mut buf = encode::u16_buffer();
let code = encode::u16(hash.code(), &mut buf);
let header_len = code.len() + 1;
let size = hash.size();
let mut output = Vec::new();
output.resize(header_len + size as usize, 0);
output[..code.len()].copy_from_slice(code);
output[code.len()] = size;
for b in output[header_len..].iter_mut() {
*b = rand::random();
}
Multihash {
bytes: output,
}
}
/// Returns the bytes representation of the multihash. /// Returns the bytes representation of the multihash.
#[inline] #[inline]
pub fn into_bytes(self) -> Vec<u8> { pub fn into_bytes(self) -> Vec<u8> {
@ -250,3 +273,24 @@ pub fn to_hex(bytes: &[u8]) -> String {
hex hex
} }
#[cfg(test)]
mod tests {
use {Hash, Multihash};
#[test]
fn rand_generates_valid_multihash() {
// Iterate over every possible hash function.
for code in 0 .. u16::max_value() {
let hash_fn = match Hash::from_code(code) {
Some(c) => c,
None => continue,
};
for _ in 0 .. 2000 {
let hash = Multihash::random(hash_fn);
assert_eq!(hash, Multihash::from_bytes(hash.clone().into_bytes()).unwrap());
}
}
}
}

View File

@ -523,9 +523,8 @@ mod tests {
use futures::{Future, Poll, Sink, StartSend, Stream}; use futures::{Future, Poll, Sink, StartSend, Stream};
use futures::sync::mpsc; use futures::sync::mpsc;
use kad_server::{self, KadIncomingRequest, KadConnecController}; use kad_server::{self, KadIncomingRequest, KadConnecController};
use libp2p_core::PublicKey; use libp2p_core::PeerId;
use protocol::{KadConnectionType, KadPeer}; use protocol::{KadConnectionType, KadPeer};
use rand;
// This struct merges a stream and a sink and is quite useful for tests. // This struct merges a stream and a sink and is quite useful for tests.
struct Wrapper<St, Si>(St, Si); struct Wrapper<St, Si>(St, Si);
@ -591,18 +590,12 @@ mod tests {
fn find_node_response() { fn find_node_response() {
let (controller_a, stream_events_a, _controller_b, stream_events_b) = build_test(); let (controller_a, stream_events_a, _controller_b, stream_events_b) = build_test();
let random_peer_id = { let random_peer_id = PeerId::random();
let buf = (0 .. 1024).map(|_| -> u8 { rand::random() }).collect::<Vec<_>>();
PublicKey::Rsa(buf).into_peer_id()
};
let find_node_fut = controller_a.find_node(&random_peer_id); let find_node_fut = controller_a.find_node(&random_peer_id);
let example_response = KadPeer { let example_response = KadPeer {
node_id: { node_id: PeerId::random(),
let buf = (0 .. 1024).map(|_| -> u8 { rand::random() }).collect::<Vec<_>>();
PublicKey::Rsa(buf).into_peer_id()
},
multiaddrs: Vec::new(), multiaddrs: Vec::new(),
connection_ty: KadConnectionType::Connected, connection_ty: KadConnectionType::Connected,
}; };

View File

@ -432,7 +432,7 @@ mod tests {
use self::libp2p_tcp_transport::TcpConfig; use self::libp2p_tcp_transport::TcpConfig;
use futures::{Future, Sink, Stream}; use futures::{Future, Sink, Stream};
use libp2p_core::{Transport, PeerId, PublicKey}; use libp2p_core::{Transport, PeerId};
use multihash::{encode, Hash}; use multihash::{encode, Hash};
use protocol::{KadConnectionType, KadMsg, KademliaProtocolConfig, KadPeer}; use protocol::{KadConnectionType, KadMsg, KademliaProtocolConfig, KadPeer};
use std::sync::mpsc; use std::sync::mpsc;
@ -454,12 +454,12 @@ mod tests {
key: encode(Hash::SHA2256, &[10, 11, 12]).unwrap(), key: encode(Hash::SHA2256, &[10, 11, 12]).unwrap(),
}); });
test_one(KadMsg::FindNodeReq { test_one(KadMsg::FindNodeReq {
key: PeerId::from_public_key(PublicKey::Rsa(vec![9, 12, 0, 245, 245, 201, 28, 95])) key: PeerId::random()
}); });
test_one(KadMsg::FindNodeRes { test_one(KadMsg::FindNodeRes {
closer_peers: vec![ closer_peers: vec![
KadPeer { KadPeer {
node_id: PeerId::from_public_key(PublicKey::Rsa(vec![93, 80, 12, 250])), node_id: PeerId::random(),
multiaddrs: vec!["/ip4/100.101.102.103/tcp/20105".parse().unwrap()], multiaddrs: vec!["/ip4/100.101.102.103/tcp/20105".parse().unwrap()],
connection_ty: KadConnectionType::Connected, connection_ty: KadConnectionType::Connected,
}, },
@ -471,14 +471,14 @@ mod tests {
test_one(KadMsg::GetProvidersRes { test_one(KadMsg::GetProvidersRes {
closer_peers: vec![ closer_peers: vec![
KadPeer { KadPeer {
node_id: PeerId::from_public_key(PublicKey::Rsa(vec![93, 80, 12, 250])), node_id: PeerId::random(),
multiaddrs: vec!["/ip4/100.101.102.103/tcp/20105".parse().unwrap()], multiaddrs: vec!["/ip4/100.101.102.103/tcp/20105".parse().unwrap()],
connection_ty: KadConnectionType::Connected, connection_ty: KadConnectionType::Connected,
}, },
], ],
provider_peers: vec![ provider_peers: vec![
KadPeer { KadPeer {
node_id: PeerId::from_public_key(PublicKey::Rsa(vec![12, 90, 1, 28])), node_id: PeerId::random(),
multiaddrs: vec!["/ip4/200.201.202.203/tcp/1999".parse().unwrap()], multiaddrs: vec!["/ip4/200.201.202.203/tcp/1999".parse().unwrap()],
connection_ty: KadConnectionType::NotConnected, connection_ty: KadConnectionType::NotConnected,
}, },
@ -487,7 +487,7 @@ mod tests {
test_one(KadMsg::AddProvider { test_one(KadMsg::AddProvider {
key: encode(Hash::SHA2256, &[9, 12, 0, 245, 245, 201, 28, 95]).unwrap(), key: encode(Hash::SHA2256, &[9, 12, 0, 245, 245, 201, 28, 95]).unwrap(),
provider_peer: KadPeer { provider_peer: KadPeer {
node_id: PeerId::from_public_key(PublicKey::Rsa(vec![5, 6, 7, 8])), node_id: PeerId::random(),
multiaddrs: vec!["/ip4/9.1.2.3/udp/23".parse().unwrap()], multiaddrs: vec!["/ip4/9.1.2.3/udp/23".parse().unwrap()],
connection_ty: KadConnectionType::Connected, connection_ty: KadConnectionType::Connected,
}, },

View File

@ -151,7 +151,7 @@ mod tests {
let temp_file = self::tempfile::NamedTempFile::new().unwrap(); let temp_file = self::tempfile::NamedTempFile::new().unwrap();
let peer_store = ::json_peerstore::JsonPeerstore::new(temp_file.path()).unwrap(); let peer_store = ::json_peerstore::JsonPeerstore::new(temp_file.path()).unwrap();
let peer_id = PeerId::from_public_key(PublicKey::Ed25519(vec![1, 2, 3])); let peer_id = PeerId::random();
let addr = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap(); let addr = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap();
peer_store peer_store

View File

@ -50,7 +50,7 @@
//! //!
//! // In this example we use a `MemoryPeerstore`, but you can easily swap it for another backend. //! // In this example we use a `MemoryPeerstore`, but you can easily swap it for another backend.
//! let mut peerstore = MemoryPeerstore::empty(); //! let mut peerstore = MemoryPeerstore::empty();
//! let peer_id = PeerId::from_public_key(PublicKey::Rsa(vec![1, 2, 3, 4])); //! let peer_id = PeerId::random();
//! //!
//! // Let's write some information about a peer. //! // Let's write some information about a peer.
//! { //! {

View File

@ -33,14 +33,13 @@ macro_rules! peerstore_tests {
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use {Peerstore, PeerAccess, PeerId}; use {Peerstore, PeerAccess, PeerId};
use libp2p_core::PublicKey;
use multiaddr::Multiaddr; use multiaddr::Multiaddr;
#[test] #[test]
fn initially_empty() { fn initially_empty() {
$($stmt;)* $($stmt;)*
let peer_store = $create_peerstore; let peer_store = $create_peerstore;
let peer_id = PeerId::from_public_key(PublicKey::Ed25519(vec![1, 2, 3])); let peer_id = PeerId::random();
assert_eq!(peer_store.peers().count(), 0); assert_eq!(peer_store.peers().count(), 0);
assert!(peer_store.peer(&peer_id).is_none()); assert!(peer_store.peer(&peer_id).is_none());
} }
@ -49,7 +48,7 @@ macro_rules! peerstore_tests {
fn set_then_get_addr() { fn set_then_get_addr() {
$($stmt;)* $($stmt;)*
let peer_store = $create_peerstore; let peer_store = $create_peerstore;
let peer_id = PeerId::from_public_key(PublicKey::Ed25519(vec![1, 2, 3])); let peer_id = PeerId::random();
let addr = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap(); let addr = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap();
peer_store.peer_or_create(&peer_id).add_addr(addr.clone(), Duration::from_millis(5000)); peer_store.peer_or_create(&peer_id).add_addr(addr.clone(), Duration::from_millis(5000));
@ -63,7 +62,7 @@ macro_rules! peerstore_tests {
// Add an already-expired address to a peer. // Add an already-expired address to a peer.
$($stmt;)* $($stmt;)*
let peer_store = $create_peerstore; let peer_store = $create_peerstore;
let peer_id = PeerId::from_public_key(PublicKey::Ed25519(vec![1, 2, 3])); let peer_id = PeerId::random();
let addr = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap(); let addr = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap();
peer_store.peer_or_create(&peer_id).add_addr(addr.clone(), Duration::from_millis(0)); peer_store.peer_or_create(&peer_id).add_addr(addr.clone(), Duration::from_millis(0));
@ -77,7 +76,7 @@ macro_rules! peerstore_tests {
fn clear_addrs() { fn clear_addrs() {
$($stmt;)* $($stmt;)*
let peer_store = $create_peerstore; let peer_store = $create_peerstore;
let peer_id = PeerId::from_public_key(PublicKey::Ed25519(vec![1, 2, 3])); let peer_id = PeerId::random();
let addr = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap(); let addr = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap();
peer_store.peer_or_create(&peer_id) peer_store.peer_or_create(&peer_id)
@ -92,7 +91,7 @@ macro_rules! peerstore_tests {
fn no_update_ttl() { fn no_update_ttl() {
$($stmt;)* $($stmt;)*
let peer_store = $create_peerstore; let peer_store = $create_peerstore;
let peer_id = PeerId::from_public_key(PublicKey::Ed25519(vec![1, 2, 3])); let peer_id = PeerId::random();
let addr1 = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap(); let addr1 = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap();
let addr2 = "/ip4/0.0.0.1/tcp/0".parse::<Multiaddr>().unwrap(); let addr2 = "/ip4/0.0.0.1/tcp/0".parse::<Multiaddr>().unwrap();
@ -113,7 +112,7 @@ macro_rules! peerstore_tests {
fn force_update_ttl() { fn force_update_ttl() {
$($stmt;)* $($stmt;)*
let peer_store = $create_peerstore; let peer_store = $create_peerstore;
let peer_id = PeerId::from_public_key(PublicKey::Ed25519(vec![1, 2, 3])); let peer_id = PeerId::random();
let addr1 = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap(); let addr1 = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap();
let addr2 = "/ip4/0.0.0.1/tcp/0".parse::<Multiaddr>().unwrap(); let addr2 = "/ip4/0.0.0.1/tcp/0".parse::<Multiaddr>().unwrap();