1use crate::{
9 account_address::AccountAddress,
10 network_address::encrypted::{EncNetworkAddress, Key, KeyVersion},
11};
12use diem_crypto::{
13 traits::{CryptoMaterialError, ValidCryptoMaterialStringExt},
14 x25519,
15};
16#[cfg(any(test, feature = "fuzzing"))]
17use proptest::{collection::vec, prelude::*};
18#[cfg(any(test, feature = "fuzzing"))]
19use proptest_derive::Arbitrary;
20use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
21use std::{
22 convert::{Into, TryFrom},
23 fmt,
24 iter::IntoIterator,
25 net::{self, IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs},
26 num,
27 str::FromStr,
28 string::ToString,
29};
30use thiserror::Error;
31
32pub mod encrypted;
33
34const MAX_DNS_NAME_SIZE: usize = 255;
35
36#[derive(Clone, Eq, Hash, PartialEq)]
117pub struct NetworkAddress(Vec<Protocol>);
118
119#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
121#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
122pub enum Protocol {
123 Ip4(Ipv4Addr),
124 Ip6(Ipv6Addr),
125 Dns(DnsName),
126 Dns4(DnsName),
127 Dns6(DnsName),
128 Tcp(u16),
129 Memory(u16),
130 NoiseIK(x25519::PublicKey),
132 Handshake(u8),
136}
137
138#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize)]
157pub struct DnsName(String);
158
159#[derive(Error, Debug)]
161pub enum ParseError {
162 #[error("unknown protocol type: '{0}'")]
163 UnknownProtocolType(String),
164
165 #[error("unexpected end of protocol string")]
166 UnexpectedEnd,
167
168 #[error("error parsing ip4/ip6 address: {0}")]
169 ParseAddrError(#[from] net::AddrParseError),
170
171 #[error("error parsing integer: {0}")]
172 ParseIntError(#[from] num::ParseIntError),
173
174 #[error("error parsing x25519 public key: {0}")]
175 ParseX25519PubkeyError(#[from] CryptoMaterialError),
176
177 #[error("network address cannot be empty")]
178 EmptyProtocolString,
179
180 #[error("protocol string must start with '/'")]
181 InvalidProtocolString,
182
183 #[error("dns name cannot be empty")]
184 EmptyDnsNameString,
185
186 #[error("dns name cannot contain '/' characters")]
187 InvalidDnsNameCharacter,
188
189 #[error("dns name is too long: len: {0} bytes, max len: 255 bytes")]
190 DnsNameTooLong(usize),
191
192 #[error("error decrypting network address")]
193 DecryptError,
194
195 #[error("bcs error: {0}")]
196 BCSError(#[from] bcs::Error),
197}
198
199#[derive(Error, Debug)]
200#[error("network address cannot be empty")]
201pub struct EmptyError;
202
203impl NetworkAddress {
208 fn new(protocols: Vec<Protocol>) -> Self { Self(protocols) }
209
210 pub fn as_slice(&self) -> &[Protocol] { self.0.as_slice() }
211
212 pub fn push(mut self, proto: Protocol) -> Self {
213 self.0.push(proto);
214 self
215 }
216
217 pub fn extend_from_slice(mut self, protos: &[Protocol]) -> Self {
218 self.0.extend_from_slice(protos);
219 self
220 }
221
222 pub fn encrypt(
224 self, shared_val_netaddr_key: &Key, key_version: KeyVersion,
225 account: &AccountAddress, seq_num: u64, addr_idx: u32,
226 ) -> Result<EncNetworkAddress, ParseError> {
227 EncNetworkAddress::encrypt(
228 self,
229 shared_val_netaddr_key,
230 key_version,
231 account,
232 seq_num,
233 addr_idx,
234 )
235 }
236
237 pub fn append_prod_protos(
258 self, network_pubkey: x25519::PublicKey, handshake_version: u8,
259 ) -> Self {
260 self.push(Protocol::NoiseIK(network_pubkey))
261 .push(Protocol::Handshake(handshake_version))
262 }
263
264 pub fn is_diemnet_addr(&self) -> bool {
291 parse_diemnet_protos(self.as_slice()).is_some()
292 }
293
294 pub fn find_ip_addr(&self) -> Option<IpAddr> {
296 self.0.iter().find_map(|proto| match proto {
297 Protocol::Ip4(addr) => Some(IpAddr::V4(*addr)),
298 Protocol::Ip6(addr) => Some(IpAddr::V6(*addr)),
299 _ => None,
300 })
301 }
302
303 pub fn find_noise_proto(&self) -> Option<x25519::PublicKey> {
307 self.0.iter().find_map(|proto| match proto {
308 Protocol::NoiseIK(pubkey) => Some(*pubkey),
309 _ => None,
310 })
311 }
312
313 pub fn rotate_noise_public_key(
315 &mut self, to_replace: &x25519::PublicKey,
316 new_public_key: &x25519::PublicKey,
317 ) {
318 for protocol in self.0.iter_mut() {
319 if let Protocol::NoiseIK(public_key) = protocol {
321 if public_key == to_replace {
322 *protocol = Protocol::NoiseIK(*new_public_key);
323 }
324 }
325 }
326 }
327
328 #[cfg(any(test, feature = "fuzzing"))]
329 pub fn mock() -> Self { NetworkAddress::new(vec![Protocol::Memory(1234)]) }
330}
331
332impl IntoIterator for NetworkAddress {
333 type IntoIter = std::vec::IntoIter<Self::Item>;
334 type Item = Protocol;
335
336 fn into_iter(self) -> Self::IntoIter { self.0.into_iter() }
337}
338
339impl FromStr for NetworkAddress {
340 type Err = ParseError;
341
342 fn from_str(s: &str) -> Result<Self, Self::Err> {
343 if s.is_empty() {
344 return Err(ParseError::EmptyProtocolString);
345 }
346
347 let mut protocols = Vec::new();
348 let mut parts_iter = s.split('/');
349
350 if parts_iter.next() != Some("") {
352 return Err(ParseError::InvalidProtocolString);
353 }
354
355 while let Some(protocol_type) = parts_iter.next() {
357 protocols.push(Protocol::parse(protocol_type, &mut parts_iter)?);
358 }
359
360 Ok(NetworkAddress::new(protocols))
361 }
362}
363
364impl ToSocketAddrs for NetworkAddress {
365 type Iter = std::vec::IntoIter<SocketAddr>;
366
367 fn to_socket_addrs(&self) -> Result<Self::Iter, std::io::Error> {
368 if let Some(((ipaddr, port), _)) = parse_ip_tcp(self.as_slice()) {
369 Ok(vec![SocketAddr::new(ipaddr, port)].into_iter())
370 } else if let Some(((ip_filter, dns_name, port), _)) =
371 parse_dns_tcp(self.as_slice())
372 {
373 format!("{}:{}", dns_name, port).to_socket_addrs().map(|v| {
374 v.filter(|addr| ip_filter.matches(addr.ip()))
375 .collect::<Vec<_>>()
376 .into_iter()
377 })
378 } else {
379 Ok(vec![].into_iter())
380 }
381 }
382}
383
384impl TryFrom<Vec<Protocol>> for NetworkAddress {
385 type Error = EmptyError;
386
387 fn try_from(value: Vec<Protocol>) -> Result<Self, Self::Error> {
388 if value.is_empty() {
389 Err(EmptyError)
390 } else {
391 Ok(NetworkAddress::new(value))
392 }
393 }
394}
395
396impl From<Protocol> for NetworkAddress {
397 fn from(proto: Protocol) -> NetworkAddress {
398 NetworkAddress::new(vec![proto])
399 }
400}
401
402impl From<SocketAddr> for NetworkAddress {
403 fn from(sockaddr: SocketAddr) -> NetworkAddress {
404 let ip_proto = Protocol::from(sockaddr.ip());
405 let tcp_proto = Protocol::Tcp(sockaddr.port());
406 NetworkAddress::new(vec![ip_proto, tcp_proto])
407 }
408}
409
410impl fmt::Display for NetworkAddress {
411 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
412 for protocol in self.0.iter() {
413 protocol.fmt(f)?;
414 }
415 Ok(())
416 }
417}
418
419impl fmt::Debug for NetworkAddress {
420 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
421 fmt::Display::fmt(self, f)
422 }
423}
424
425impl Serialize for NetworkAddress {
426 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
427 where S: Serializer {
428 if serializer.is_human_readable() {
429 serializer.serialize_str(&self.to_string())
430 } else {
431 #[derive(Serialize)]
432 #[serde(rename = "NetworkAddress")]
433 struct Wrapper<'a>(#[serde(with = "serde_bytes")] &'a [u8]);
434
435 bcs::to_bytes(&self.as_slice())
436 .map_err(serde::ser::Error::custom)
437 .and_then(|v| Wrapper(&v).serialize(serializer))
438 }
439 }
440}
441
442impl<'de> Deserialize<'de> for NetworkAddress {
443 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
444 where D: Deserializer<'de> {
445 if deserializer.is_human_readable() {
446 let s = <String>::deserialize(deserializer)?;
447 NetworkAddress::from_str(s.as_str()).map_err(de::Error::custom)
448 } else {
449 #[derive(Deserialize)]
450 #[serde(rename = "NetworkAddress")]
451 struct Wrapper(#[serde(with = "serde_bytes")] Vec<u8>);
452
453 Wrapper::deserialize(deserializer)
454 .and_then(|v| bcs::from_bytes(&v.0).map_err(de::Error::custom))
455 .and_then(|v: Vec<Protocol>| {
456 NetworkAddress::try_from(v).map_err(de::Error::custom)
457 })
458 }
459 }
460}
461
462#[cfg(any(test, feature = "fuzzing"))]
463impl Arbitrary for NetworkAddress {
464 type Parameters = ();
465 type Strategy = BoxedStrategy<Self>;
466
467 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
468 vec(any::<Protocol>(), 1..10)
469 .prop_map(NetworkAddress::new)
470 .boxed()
471 }
472}
473
474#[cfg(any(test, feature = "fuzzing"))]
475pub fn arb_diemnet_addr() -> impl Strategy<Value = NetworkAddress> {
476 let arb_transport_protos = prop_oneof![
477 any::<u16>().prop_map(|port| vec![Protocol::Memory(port)]),
478 any::<(Ipv4Addr, u16)>().prop_map(|(addr, port)| vec![
479 Protocol::Ip4(addr),
480 Protocol::Tcp(port)
481 ]),
482 any::<(Ipv6Addr, u16)>().prop_map(|(addr, port)| vec![
483 Protocol::Ip6(addr),
484 Protocol::Tcp(port)
485 ]),
486 any::<(DnsName, u16)>().prop_map(|(name, port)| vec![
487 Protocol::Dns(name),
488 Protocol::Tcp(port)
489 ]),
490 any::<(DnsName, u16)>().prop_map(|(name, port)| vec![
491 Protocol::Dns4(name),
492 Protocol::Tcp(port)
493 ]),
494 any::<(DnsName, u16)>().prop_map(|(name, port)| vec![
495 Protocol::Dns6(name),
496 Protocol::Tcp(port)
497 ]),
498 ];
499 let arb_diemnet_protos =
500 any::<(x25519::PublicKey, u8)>().prop_map(|(pubkey, hs)| {
501 vec![Protocol::NoiseIK(pubkey), Protocol::Handshake(hs)]
502 });
503
504 (arb_transport_protos, arb_diemnet_protos).prop_map(
505 |(mut transport_protos, mut diemnet_protos)| {
506 transport_protos.append(&mut diemnet_protos);
507 NetworkAddress::new(transport_protos)
508 },
509 )
510}
511
512impl fmt::Display for Protocol {
517 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
518 use self::Protocol::*;
519 match self {
520 Ip4(addr) => write!(f, "/ip4/{}", addr),
521 Ip6(addr) => write!(f, "/ip6/{}", addr),
522 Dns(domain) => write!(f, "/dns/{}", domain),
523 Dns4(domain) => write!(f, "/dns4/{}", domain),
524 Dns6(domain) => write!(f, "/dns6/{}", domain),
525 Tcp(port) => write!(f, "/tcp/{}", port),
526 Memory(port) => write!(f, "/memory/{}", port),
527 NoiseIK(pubkey) => write!(
528 f,
529 "/ln-noise-ik/{}",
530 pubkey
531 .to_encoded_string()
532 .expect("ValidCryptoMaterialStringExt::to_encoded_string is infallible")
533 ),
534 Handshake(version) => write!(f, "/ln-handshake/{}", version),
535 }
536 }
537}
538
539fn parse_one<'a, T>(
540 args: &mut impl Iterator<Item = &'a str>,
541) -> Result<T, ParseError>
542where
543 T: FromStr,
544 T::Err: Into<ParseError>,
545{
546 let next_arg = args.next().ok_or(ParseError::UnexpectedEnd)?;
547 next_arg.parse().map_err(Into::into)
548}
549
550impl Protocol {
551 fn parse<'a>(
552 protocol_type: &str, args: &mut impl Iterator<Item = &'a str>,
553 ) -> Result<Protocol, ParseError> {
554 let protocol = match protocol_type {
555 "ip4" => Protocol::Ip4(parse_one(args)?),
556 "ip6" => Protocol::Ip6(parse_one(args)?),
557 "dns" => Protocol::Dns(parse_one(args)?),
558 "dns4" => Protocol::Dns4(parse_one(args)?),
559 "dns6" => Protocol::Dns6(parse_one(args)?),
560 "tcp" => Protocol::Tcp(parse_one(args)?),
561 "memory" => Protocol::Memory(parse_one(args)?),
562 "ln-noise-ik" => {
563 Protocol::NoiseIK(x25519::PublicKey::from_encoded_string(
564 args.next().ok_or(ParseError::UnexpectedEnd)?,
565 )?)
566 }
567 "ln-handshake" => Protocol::Handshake(parse_one(args)?),
568 unknown => {
569 return Err(ParseError::UnknownProtocolType(
570 unknown.to_string(),
571 ))
572 }
573 };
574 Ok(protocol)
575 }
576}
577
578impl From<IpAddr> for Protocol {
579 fn from(addr: IpAddr) -> Protocol {
580 match addr {
581 IpAddr::V4(addr) => Protocol::Ip4(addr),
582 IpAddr::V6(addr) => Protocol::Ip6(addr),
583 }
584 }
585}
586
587impl DnsName {
592 fn validate(s: &str) -> Result<(), ParseError> {
593 if s.is_empty() {
594 Err(ParseError::EmptyDnsNameString)
595 } else if s.as_bytes().len() > MAX_DNS_NAME_SIZE {
596 Err(ParseError::DnsNameTooLong(s.as_bytes().len()))
597 } else if s.contains('/') {
598 Err(ParseError::InvalidDnsNameCharacter)
599 } else {
600 Ok(())
601 }
602 }
603}
604
605impl From<DnsName> for String {
606 fn from(dns_name: DnsName) -> String { dns_name.0 }
607}
608
609impl AsRef<str> for DnsName {
610 fn as_ref(&self) -> &str { self.0.as_ref() }
611}
612
613impl TryFrom<String> for DnsName {
614 type Error = ParseError;
615
616 fn try_from(s: String) -> Result<Self, Self::Error> {
617 DnsName::validate(s.as_str()).map(|_| DnsName(s))
618 }
619}
620
621impl FromStr for DnsName {
622 type Err = ParseError;
623
624 fn from_str(s: &str) -> Result<Self, Self::Err> {
625 DnsName::validate(s).map(|_| DnsName(s.to_owned()))
626 }
627}
628
629impl fmt::Display for DnsName {
630 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) }
631}
632
633impl<'de> Deserialize<'de> for DnsName {
634 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
635 where D: Deserializer<'de> {
636 #[derive(Deserialize)]
637 #[serde(rename = "DnsName")]
638 struct DeserializeWrapper(String);
639
640 let wrapper = DeserializeWrapper::deserialize(deserializer)?;
641 let name = DnsName::try_from(wrapper.0).map_err(de::Error::custom)?;
642 Ok(name)
643 }
644}
645
646#[cfg(any(test, feature = "fuzzing"))]
647impl Arbitrary for DnsName {
648 type Parameters = ();
649 type Strategy = BoxedStrategy<Self>;
650
651 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
652 r"[^/\pC]{1,255}"
657 .prop_filter_map("string too long", |s| {
660 if s.as_bytes().len() > MAX_DNS_NAME_SIZE {
661 None
662 } else {
663 Some(DnsName(s))
664 }
665 })
666 .boxed()
667 }
668}
669
670pub fn parse_memory(protos: &[Protocol]) -> Option<(u16, &[Protocol])> {
677 protos
678 .split_first()
679 .and_then(|(first, suffix)| match first {
680 Protocol::Memory(port) => Some((*port, suffix)),
681 _ => None,
682 })
683}
684
685pub fn parse_ip_tcp(
688 protos: &[Protocol],
689) -> Option<((IpAddr, u16), &[Protocol])> {
690 use Protocol::*;
691
692 if protos.len() < 2 {
693 return None;
694 }
695
696 let (prefix, suffix) = protos.split_at(2);
697 match prefix {
698 [Ip4(ip), Tcp(port)] => Some(((IpAddr::V4(*ip), *port), suffix)),
699 [Ip6(ip), Tcp(port)] => Some(((IpAddr::V6(*ip), *port), suffix)),
700 _ => None,
701 }
702}
703
704#[derive(Copy, Clone, Debug, Eq, PartialEq)]
705pub enum IpFilter {
706 Any,
707 OnlyIp4,
708 OnlyIp6,
709}
710
711impl IpFilter {
712 pub fn matches(&self, ipaddr: IpAddr) -> bool {
713 match self {
714 IpFilter::Any => true,
715 IpFilter::OnlyIp4 => ipaddr.is_ipv4(),
716 IpFilter::OnlyIp6 => ipaddr.is_ipv6(),
717 }
718 }
719}
720
721pub fn parse_dns_tcp(
725 protos: &[Protocol],
726) -> Option<((IpFilter, &DnsName, u16), &[Protocol])> {
727 use Protocol::*;
728
729 if protos.len() < 2 {
730 return None;
731 }
732
733 let (prefix, suffix) = protos.split_at(2);
734 match prefix {
735 [Dns(name), Tcp(port)] => Some(((IpFilter::Any, name, *port), suffix)),
736 [Dns4(name), Tcp(port)] => {
737 Some(((IpFilter::OnlyIp4, name, *port), suffix))
738 }
739 [Dns6(name), Tcp(port)] => {
740 Some(((IpFilter::OnlyIp6, name, *port), suffix))
741 }
742 _ => None,
743 }
744}
745
746pub fn parse_tcp(protos: &[Protocol]) -> Option<((String, u16), &[Protocol])> {
747 use Protocol::*;
748
749 if protos.len() < 2 {
750 return None;
751 }
752
753 let (prefix, suffix) = protos.split_at(2);
754 match prefix {
755 [Ip4(ip), Tcp(port)] => Some(((ip.to_string(), *port), suffix)),
756 [Ip6(ip), Tcp(port)] => Some(((ip.to_string(), *port), suffix)),
757 [Dns(name), Tcp(port)] => Some(((name.to_string(), *port), suffix)),
758 [Dns4(name), Tcp(port)] => Some(((name.to_string(), *port), suffix)),
759 [Dns6(name), Tcp(port)] => Some(((name.to_string(), *port), suffix)),
760 _ => None,
761 }
762}
763
764pub fn parse_noise_ik(
767 protos: &[Protocol],
768) -> Option<(&x25519::PublicKey, &[Protocol])> {
769 match protos.split_first() {
770 Some((Protocol::NoiseIK(pubkey), suffix)) => Some((pubkey, suffix)),
771 _ => None,
772 }
773}
774
775pub fn parse_handshake(protos: &[Protocol]) -> Option<(u8, &[Protocol])> {
778 match protos.split_first() {
779 Some((Protocol::Handshake(version), suffix)) => {
780 Some((*version, suffix))
781 }
782 _ => None,
783 }
784}
785
786fn parse_diemnet_protos(protos: &[Protocol]) -> Option<&[Protocol]> {
790 let transport_suffix = parse_ip_tcp(protos)
797 .map(|x| x.1)
798 .or_else(|| parse_dns_tcp(protos).map(|x| x.1))
799 .or_else(|| {
800 if cfg!(test) {
801 parse_memory(protos).map(|x| x.1)
802 } else {
803 None
804 }
805 })?;
806
807 let auth_suffix = parse_noise_ik(transport_suffix).map(|x| x.1)?;
812
813 let handshake_suffix = parse_handshake(auth_suffix).map(|x| x.1)?;
816
817 if handshake_suffix.is_empty() {
820 Some(protos)
821 } else {
822 None
823 }
824}
825
826#[cfg(test)]
831mod test {
832 use super::*;
833 use anyhow::format_err;
834 use bcs::test_helpers::assert_canonical_encode_decode;
835
836 #[test]
837 fn test_network_address_display() {
838 use super::Protocol::*;
839 let addr = NetworkAddress::new(vec![Memory(1234), Handshake(0)]);
840 assert_eq!("/memory/1234/ln-handshake/0", addr.to_string());
841 }
842
843 #[test]
844 fn test_network_address_parse_success() {
845 use super::Protocol::*;
846
847 let pubkey_str =
848 "080e287879c918794170e258bfaddd75acac5b3e350419044655e4983a487120";
849 let pubkey =
850 x25519::PublicKey::from_encoded_string(pubkey_str).unwrap();
851 let noise_addr_str = format!(
852 "/dns/example.com/tcp/1234/ln-noise-ik/{}/ln-handshake/5",
853 pubkey_str
854 );
855
856 let test_cases = [
857 (
858 "/memory/1234/ln-handshake/0",
859 vec![Memory(1234), Handshake(0)],
860 ),
861 (
862 "/ip4/12.34.56.78/tcp/1234/ln-handshake/123",
863 vec![
864 Ip4(Ipv4Addr::new(12, 34, 56, 78)),
865 Tcp(1234),
866 Handshake(123),
867 ],
868 ),
869 (
870 "/ip6/::1/tcp/0",
871 vec![Ip6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), Tcp(0)],
872 ),
873 (
874 "/ip6/dead:beef::c0de/tcp/8080",
875 vec![
876 Ip6(Ipv6Addr::new(0xdead, 0xbeef, 0, 0, 0, 0, 0, 0xc0de)),
877 Tcp(8080),
878 ],
879 ),
880 (
881 "/dns/example.com/tcp/80",
882 vec![Dns(DnsName("example.com".to_owned())), Tcp(80)],
883 ),
884 (
885 &noise_addr_str,
886 vec![
887 Dns(DnsName("example.com".to_owned())),
888 Tcp(1234),
889 NoiseIK(pubkey),
890 Handshake(5),
891 ],
892 ),
893 ];
894
895 for (addr_str, expected_address) in &test_cases {
896 let actual_address = NetworkAddress::from_str(addr_str)
897 .map_err(|err| {
898 format_err!(
899 "failed to parse: input: '{}', err: {}",
900 addr_str,
901 err
902 )
903 })
904 .unwrap();
905 let expected_address =
906 NetworkAddress::new(expected_address.clone());
907 assert_eq!(actual_address, expected_address);
908 }
909 }
910
911 #[test]
912 fn test_network_address_parse_fail() {
913 let test_cases = [
914 "",
915 "/",
916 "/foobar",
917 "/tcp",
918 "tcp/1234",
919 "/tcp/1234/",
920 "/tcp/1234/foobar/5",
921 "/tcp/99999",
922 "/ip4/1.1.1",
923 "/ip4/1.1.1.1.",
924 "/ip4/1.1.1.1.1",
925 "/ip4/1.1.1.999.1",
926 ];
927
928 for &addr_str in &test_cases {
929 if let Ok(addr) = NetworkAddress::from_str(addr_str) {
930 panic!(
931 "parsing should fail: input: '{}', output: '{}'",
932 addr_str, addr
933 );
934 }
935 }
936 }
937
938 #[test]
939 fn test_parse_memory() {
940 let addr = NetworkAddress::from_str("/memory/123").unwrap();
941 let expected_suffix: &[Protocol] = &[];
942 assert_eq!(
943 parse_memory(addr.as_slice()).unwrap(),
944 (123, expected_suffix)
945 );
946
947 let addr = NetworkAddress::from_str("/memory/123/tcp/999").unwrap();
948 let expected_suffix: &[Protocol] = &[Protocol::Tcp(999)];
949 assert_eq!(
950 parse_memory(addr.as_slice()).unwrap(),
951 (123, expected_suffix)
952 );
953
954 let addr = NetworkAddress::from_str("/tcp/999/memory/123").unwrap();
955 assert_eq!(None, parse_memory(addr.as_slice()));
956 }
957
958 #[test]
959 fn test_parse_ip_tcp() {
960 let addr = NetworkAddress::from_str("/ip4/1.2.3.4/tcp/123").unwrap();
961 let expected_suffix: &[Protocol] = &[];
962 assert_eq!(
963 parse_ip_tcp(addr.as_slice()).unwrap(),
964 ((IpAddr::from_str("1.2.3.4").unwrap(), 123), expected_suffix)
965 );
966
967 let addr = NetworkAddress::from_str("/ip6/::1/tcp/123").unwrap();
968 let expected_suffix: &[Protocol] = &[];
969 assert_eq!(
970 parse_ip_tcp(addr.as_slice()).unwrap(),
971 ((IpAddr::from_str("::1").unwrap(), 123), expected_suffix)
972 );
973
974 let addr =
975 NetworkAddress::from_str("/ip6/::1/tcp/123/memory/999").unwrap();
976 let expected_suffix: &[Protocol] = &[Protocol::Memory(999)];
977 assert_eq!(
978 parse_ip_tcp(addr.as_slice()).unwrap(),
979 ((IpAddr::from_str("::1").unwrap(), 123), expected_suffix)
980 );
981
982 let addr = NetworkAddress::from_str("/tcp/999/memory/123").unwrap();
983 assert_eq!(None, parse_ip_tcp(addr.as_slice()));
984 }
985
986 #[test]
987 fn test_parse_dns_tcp() {
988 let dns_name = DnsName::from_str("example.com").unwrap();
989 let addr =
990 NetworkAddress::from_str("/dns/example.com/tcp/123").unwrap();
991 let expected_suffix: &[Protocol] = &[];
992 assert_eq!(
993 parse_dns_tcp(addr.as_slice()).unwrap(),
994 ((IpFilter::Any, &dns_name, 123), expected_suffix)
995 );
996
997 let addr =
998 NetworkAddress::from_str("/dns4/example.com/tcp/123").unwrap();
999 let expected_suffix: &[Protocol] = &[];
1000 assert_eq!(
1001 parse_dns_tcp(addr.as_slice()).unwrap(),
1002 ((IpFilter::OnlyIp4, &dns_name, 123), expected_suffix)
1003 );
1004
1005 let addr =
1006 NetworkAddress::from_str("/dns6/example.com/tcp/123").unwrap();
1007 let expected_suffix: &[Protocol] = &[];
1008 assert_eq!(
1009 parse_dns_tcp(addr.as_slice()).unwrap(),
1010 ((IpFilter::OnlyIp6, &dns_name, 123), expected_suffix)
1011 );
1012
1013 let addr =
1014 NetworkAddress::from_str("/dns/example.com/tcp/123/memory/44")
1015 .unwrap();
1016 let expected_suffix: &[Protocol] = &[Protocol::Memory(44)];
1017 assert_eq!(
1018 parse_dns_tcp(addr.as_slice()).unwrap(),
1019 ((IpFilter::Any, &dns_name, 123), expected_suffix)
1020 );
1021
1022 let addr = NetworkAddress::from_str("/tcp/999/memory/123").unwrap();
1023 assert_eq!(None, parse_dns_tcp(addr.as_slice()));
1024 }
1025
1026 #[test]
1027 fn test_parse_noise_ik() {
1028 let pubkey_str =
1029 "080e287879c918794170e258bfaddd75acac5b3e350419044655e4983a487120";
1030 let pubkey =
1031 x25519::PublicKey::from_encoded_string(pubkey_str).unwrap();
1032 let addr =
1033 NetworkAddress::from_str(&format!("/ln-noise-ik/{}", pubkey_str))
1034 .unwrap();
1035 let expected_suffix: &[Protocol] = &[];
1036 assert_eq!(
1037 parse_noise_ik(addr.as_slice()).unwrap(),
1038 (&pubkey, expected_suffix)
1039 );
1040
1041 let addr = NetworkAddress::from_str(&format!(
1042 "/ln-noise-ik/{}/tcp/999",
1043 pubkey_str
1044 ))
1045 .unwrap();
1046 let expected_suffix: &[Protocol] = &[Protocol::Tcp(999)];
1047 assert_eq!(
1048 parse_noise_ik(addr.as_slice()).unwrap(),
1049 (&pubkey, expected_suffix)
1050 );
1051
1052 let addr = NetworkAddress::from_str("/tcp/999/memory/123").unwrap();
1053 assert_eq!(None, parse_noise_ik(addr.as_slice()));
1054 }
1055
1056 #[test]
1057 fn test_parse_handshake() {
1058 let addr = NetworkAddress::from_str("/ln-handshake/0").unwrap();
1059 let expected_suffix: &[Protocol] = &[];
1060 assert_eq!(
1061 parse_handshake(addr.as_slice()).unwrap(),
1062 (0, expected_suffix),
1063 );
1064
1065 let addr = NetworkAddress::from_str("/ln-handshake/0/tcp/999").unwrap();
1066 let expected_suffix: &[Protocol] = &[Protocol::Tcp(999)];
1067 assert_eq!(
1068 parse_handshake(addr.as_slice()).unwrap(),
1069 (0, expected_suffix),
1070 );
1071
1072 let addr = NetworkAddress::from_str("/tcp/999/memory/123").unwrap();
1073 assert_eq!(None, parse_handshake(addr.as_slice()));
1074 }
1075
1076 proptest! {
1077 #[test]
1078 fn test_network_address_canonical_serialization(addr in any::<NetworkAddress>()) {
1079 assert_canonical_encode_decode(addr);
1080 }
1081
1082 #[test]
1083 fn test_network_address_display_roundtrip(addr in any::<NetworkAddress>()) {
1084 let addr_str = addr.to_string();
1085 let addr_parsed = NetworkAddress::from_str(&addr_str).unwrap();
1086 assert_eq!(addr, addr_parsed);
1087 }
1088
1089 #[test]
1090 fn test_is_diemnet_addr(addr in arb_diemnet_addr()) {
1091 assert!(addr.is_diemnet_addr(), "addr.is_diemnet_addr() = false; addr: '{}'", addr);
1092 }
1093
1094 #[test]
1095 fn test_is_not_diemnet_addr_with_trailing(
1096 addr in arb_diemnet_addr(),
1097 addr_suffix in any::<NetworkAddress>(),
1098 ) {
1099 let addr = addr.extend_from_slice(addr_suffix.as_slice());
1101 assert!(!addr.is_diemnet_addr(), "addr.is_diemnet_addr() = true; addr: '{}'", addr);
1102 }
1103 }
1104}