From 979a2bd6a0d5659c6784a74906e7fc00936f53af Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 9 Jun 2023 15:50:25 -0400 Subject: [PATCH 1/4] linkspec: Implement HasRelayIds::display_relay_ids(). --- crates/tor-linkspec/semver.md | 1 + crates/tor-linkspec/src/traits.rs | 55 +++++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 crates/tor-linkspec/semver.md diff --git a/crates/tor-linkspec/semver.md b/crates/tor-linkspec/semver.md new file mode 100644 index 000000000..a5f4d7102 --- /dev/null +++ b/crates/tor-linkspec/semver.md @@ -0,0 +1 @@ +ADDED: display_relay_ids() on HasRelayIds. diff --git a/crates/tor-linkspec/src/traits.rs b/crates/tor-linkspec/src/traits.rs index 953ce8f45..fcdf310b9 100644 --- a/crates/tor-linkspec/src/traits.rs +++ b/crates/tor-linkspec/src/traits.rs @@ -119,6 +119,12 @@ pub trait HasRelayIds { } std::cmp::Ordering::Equal } + + /// Return a reference to this object suitable for formatting its + /// [`HasRelayIds`] members. + fn display_relay_ids(&self) -> DisplayRelayIds<'_, Self> { + DisplayRelayIds { inner: self } + } } impl HasRelayIds for T { @@ -130,6 +136,47 @@ impl HasRelayIds for T { } } +/// A helper type used to format the [`RelayId`](crate::RelayId)s in a +/// [`HasRelayIds`]. +#[derive(Clone)] +pub struct DisplayRelayIds<'a, T: HasRelayIds + ?Sized> { + /// The HasRelayIds that we're displaying. + inner: &'a T, +} +// Redactable must implement Debug. +impl<'a, T: HasRelayIds + ?Sized> std::fmt::Debug for DisplayRelayIds<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("DisplayRelayIds").finish_non_exhaustive() + } +} + +impl<'a, T: HasRelayIds + ?Sized> DisplayRelayIds<'a, T> { + /// Helper: output `self` in a possibly redacted way. + fn fmt_impl(&self, f: &mut fmt::Formatter<'_>, redact: bool) -> fmt::Result { + let mut iter = self.inner.identities(); + if let Some(ident) = iter.next() { + write!(f, "{}", ident.maybe_redacted(redact))?; + } + if redact { + return Ok(()); + } + for ident in iter { + write!(f, " {}", ident.maybe_redacted(redact))?; + } + Ok(()) + } +} +impl<'a, T: HasRelayIds + ?Sized> std::fmt::Display for DisplayRelayIds<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.fmt_impl(f, false) + } +} +impl<'a, T: HasRelayIds + ?Sized> Redactable for DisplayRelayIds<'a, T> { + fn display_redacted(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.fmt_impl(f, true) + } +} + /// An iterator over all of the relay identities held by a [`HasRelayIds`] #[derive(Clone)] pub struct RelayIdIter<'a, T: HasRelayIds + ?Sized> { @@ -280,12 +327,8 @@ impl<'a, T: ChanTarget> DisplayChanTarget<'a, T> { } } - for ident in self.inner.identities() { - write!(f, " {}", ident.maybe_redacted(redact))?; - if redact { - break; - } - } + write!(f, " ")?; + self.inner.display_relay_ids().fmt_impl(f, redact)?; write!(f, "]") } From a6ce079d4add585266e308fda0abed841a467f5e Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 9 Jun 2023 15:53:12 -0400 Subject: [PATCH 2/4] linkspec: implement Display/Redacted on RelayIds --- crates/tor-linkspec/src/owned.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/crates/tor-linkspec/src/owned.rs b/crates/tor-linkspec/src/owned.rs index a05d3a0e2..52b48dfb6 100644 --- a/crates/tor-linkspec/src/owned.rs +++ b/crates/tor-linkspec/src/owned.rs @@ -78,6 +78,17 @@ impl RelayIds { } } +impl std::fmt::Display for RelayIds { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.display_relay_ids()) + } +} +impl Redactable for RelayIds { + fn display_redacted(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.display_relay_ids().redacted()) + } +} + /// OwnedChanTarget is a summary of a [`ChanTarget`] that owns all of its /// members. #[derive(Debug, Clone, derive_builder::Builder)] @@ -323,4 +334,15 @@ mod test { assert_eq!(format!("{:?}", ct), format!("{:?}", ct2)); assert_eq!(format!("{:?}", ct), format!("{:?}", ct.clone())); } + + #[test] + fn format_relay_ids() { + let mut builder = RelayIds::builder(); + builder + .ed_identity([42; 32].into()) + .rsa_identity([45; 20].into()); + let ids = builder.build().unwrap(); + assert_eq!(format!("{}", ids), "ed25519:KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKio $2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d"); + assert_eq!(format!("{}", ids.redacted()), "Ki…"); + } } From a542a3e93f0887bcf2925f42628ae7927b6e8b00 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 9 Jun 2023 16:00:12 -0400 Subject: [PATCH 3/4] RelayId: Display the ID type on redacted identities. Formerly we would display just the first characters of the identity, without telling you what kind of ID it was. --- crates/tor-linkspec/src/ids.rs | 5 ++--- crates/tor-linkspec/src/owned.rs | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/tor-linkspec/src/ids.rs b/crates/tor-linkspec/src/ids.rs index 3afb36f8d..b2514817b 100644 --- a/crates/tor-linkspec/src/ids.rs +++ b/crates/tor-linkspec/src/ids.rs @@ -208,10 +208,9 @@ impl Redactable for RelayId { impl<'a> Redactable for RelayIdRef<'a> { fn display_redacted(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - use std::fmt::Display as _; match self { - RelayIdRef::Ed25519(k) => k.redacted().fmt(f), - RelayIdRef::Rsa(k) => k.redacted().fmt(f), + RelayIdRef::Ed25519(k) => write!(f, "ed25519:{}", k.redacted()), + RelayIdRef::Rsa(k) => write!(f, "${}", k.redacted()), } } diff --git a/crates/tor-linkspec/src/owned.rs b/crates/tor-linkspec/src/owned.rs index 52b48dfb6..879169a7f 100644 --- a/crates/tor-linkspec/src/owned.rs +++ b/crates/tor-linkspec/src/owned.rs @@ -343,6 +343,6 @@ mod test { .rsa_identity([45; 20].into()); let ids = builder.build().unwrap(); assert_eq!(format!("{}", ids), "ed25519:KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKio $2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d"); - assert_eq!(format!("{}", ids.redacted()), "Ki…"); + assert_eq!(format!("{}", ids.redacted()), "ed25519:Ki…"); } } From ddea52484924c0ae7c98d067d8858a5ff972eaa9 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 12 Jun 2023 11:39:45 -0400 Subject: [PATCH 4/4] linkspec: cleanup usage; change std::fmt to fmt. --- crates/tor-linkspec/src/traits.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/tor-linkspec/src/traits.rs b/crates/tor-linkspec/src/traits.rs index fcdf310b9..860eeac56 100644 --- a/crates/tor-linkspec/src/traits.rs +++ b/crates/tor-linkspec/src/traits.rs @@ -144,7 +144,7 @@ pub struct DisplayRelayIds<'a, T: HasRelayIds + ?Sized> { inner: &'a T, } // Redactable must implement Debug. -impl<'a, T: HasRelayIds + ?Sized> std::fmt::Debug for DisplayRelayIds<'a, T> { +impl<'a, T: HasRelayIds + ?Sized> fmt::Debug for DisplayRelayIds<'a, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("DisplayRelayIds").finish_non_exhaustive() } @@ -166,13 +166,13 @@ impl<'a, T: HasRelayIds + ?Sized> DisplayRelayIds<'a, T> { Ok(()) } } -impl<'a, T: HasRelayIds + ?Sized> std::fmt::Display for DisplayRelayIds<'a, T> { +impl<'a, T: HasRelayIds + ?Sized> fmt::Display for DisplayRelayIds<'a, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.fmt_impl(f, false) } } impl<'a, T: HasRelayIds + ?Sized> Redactable for DisplayRelayIds<'a, T> { - fn display_redacted(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn display_redacted(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.fmt_impl(f, true) } } @@ -340,11 +340,11 @@ impl<'a, T: ChanTarget> fmt::Display for DisplayChanTarget<'a, T> { } } -impl<'a, T: ChanTarget + std::fmt::Debug> safelog::Redactable for DisplayChanTarget<'a, T> { - fn display_redacted(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl<'a, T: ChanTarget + fmt::Debug> safelog::Redactable for DisplayChanTarget<'a, T> { + fn display_redacted(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.fmt_impl(f, true) } - fn debug_redacted(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn debug_redacted(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "ChanTarget({:?})", self.redacted().to_string()) } }