Skip to content

Commit d969b5b

Browse files
committed
Revert to generic short string serialization
1 parent ebfe709 commit d969b5b

File tree

2 files changed

+36
-79
lines changed

2 files changed

+36
-79
lines changed

lightning/src/ln/msgs.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use io_extras::read_to_end;
4040

4141
use util::events::MessageSendEventsProvider;
4242
use util::logger;
43-
use util::ser::{Readable, Writeable, Writer, FixedLengthReader, HighZeroBytesDroppedVarInt, Hostname};
43+
use util::ser::{Readable, Writeable, Writer, FixedLengthReader, HighZeroBytesDroppedVarInt, ShortAsciiString};
4444

4545
use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
4646

@@ -445,7 +445,7 @@ pub enum NetAddress {
445445
/// A hostname/port on which the peer is listening.
446446
Hostname {
447447
/// The hostname on which the node is listening.
448-
hostname: Hostname,
448+
hostname: ShortAsciiString,
449449
/// The port on which the node is listening.
450450
port: u16,
451451
},
@@ -1852,7 +1852,7 @@ mod tests {
18521852
use ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
18531853
use ln::msgs;
18541854
use ln::msgs::{FinalOnionHopData, OptionalField, OnionErrorPacket, OnionHopDataFormat};
1855-
use util::ser::{Writeable, Readable, Hostname};
1855+
use util::ser::{Writeable, Readable, ShortAsciiString};
18561856

18571857
use bitcoin::hashes::hex::FromHex;
18581858
use bitcoin::util::address::Address;
@@ -2033,7 +2033,7 @@ mod tests {
20332033
}
20342034
if hostname {
20352035
addresses.push(msgs::NetAddress::Hostname {
2036-
hostname: Hostname::try_from(String::from("host")).unwrap(),
2036+
hostname: ShortAsciiString::try_from(String::from("host")).unwrap(),
20372037
port: 9735,
20382038
});
20392039
}

lightning/src/util/ser.rs

Lines changed: 32 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -915,103 +915,67 @@ impl Readable for String {
915915
}
916916
}
917917

918-
/// Represents a hostname with validation for serialization purposes.
919-
/// The hostname follows the preferred form summarized in e.g. RFC 3696.
920-
/// Its length is guaranteed to be representable by a single byte.
918+
/// Represents a printable ASCII string whose length can be represented by a single byte.
921919
/// This serialization is used by BOLT 7 hostnames.
922920
#[derive(Clone, Debug, PartialEq)]
923-
pub struct Hostname(String);
924-
impl Hostname {
925-
/// Returns the length of the hostname.
921+
pub struct ShortAsciiString(String);
922+
impl ShortAsciiString {
923+
/// Returns the length of the short ASCII string.
926924
pub fn len(&self) -> u8 {
927925
(&self.0).len() as u8
928926
}
929927
}
930-
impl Deref for Hostname {
928+
impl Deref for ShortAsciiString {
931929
type Target = String;
932930

933931
fn deref(&self) -> &Self::Target {
934932
&self.0
935933
}
936934
}
937-
impl From<Hostname> for String {
938-
fn from(short_s: Hostname) -> Self {
935+
impl From<ShortAsciiString> for String {
936+
fn from(short_s: ShortAsciiString) -> Self {
939937
short_s.0
940938
}
941939
}
942-
/// An error returned when converting into a hostname.
943-
/// This conversion follows the preferred form summarized in e.g. RFC 3696.
944-
#[derive(Debug)]
945-
pub enum HostnameConversionError {
946-
/// The hostname exceeded 255 bytes.
947-
InvalidLength,
948-
/// A label exceeded 63 bytes.
949-
InvalidLabelLength,
950-
/// A zero length root label was found without it being the last label.
951-
InvalidRootLabel,
952-
/// An invalid character was found. Valid characters include only ASCII
953-
/// alphanumeric characters and hyphens. Hyphens are invalid at the
954-
/// beginning or end of a label.
955-
InvalidChar,
956-
}
957-
impl TryFrom<Vec<u8>> for Hostname {
958-
type Error = HostnameConversionError;
940+
impl TryFrom<Vec<u8>> for ShortAsciiString {
941+
type Error = ();
959942

960943
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
961944
if let Ok(s) = String::from_utf8(bytes) {
962-
Hostname::try_from(s)
945+
ShortAsciiString::try_from(s)
963946
} else {
964-
Err(HostnameConversionError::InvalidChar)
947+
Err(())
965948
}
966949
}
967950
}
968-
impl TryFrom<String> for Hostname {
969-
type Error = HostnameConversionError;
951+
impl TryFrom<String> for ShortAsciiString {
952+
type Error = ();
970953

971954
fn try_from(s: String) -> Result<Self, Self::Error> {
972-
if s.len() > 255 {
973-
return Err(HostnameConversionError::InvalidLength);
955+
if s.len() <= 255 && s.chars().all(|c|
956+
c.is_ascii() && !c.is_ascii_control()
957+
) {
958+
Ok(ShortAsciiString(s))
959+
} else {
960+
Err(())
974961
}
975-
let mut labels = s.split('.').enumerate().peekable();
976-
while let Some((label_idx, label)) = labels.next() {
977-
// Trailing zero length root label for fully-qualified name.
978-
let last_label = labels.peek().is_none();
979-
if label.len() == 0 {
980-
if !last_label || label_idx == 0 {
981-
return Err(HostnameConversionError::InvalidRootLabel);
982-
}
983-
}
984-
// Maximum label length from specification.
985-
if label.len() > 63 {
986-
return Err(HostnameConversionError::InvalidLabelLength);
987-
}
988-
for (byte_idx, byte) in label.as_bytes().iter().enumerate() {
989-
if !byte.is_ascii_alphanumeric() && *byte != b'-' {
990-
return Err(HostnameConversionError::InvalidChar);
991-
}
992-
if *byte == b'-' && (byte_idx == 0 || byte_idx == label.len() - 1) {
993-
return Err(HostnameConversionError::InvalidChar);
994-
}
995-
}
996-
};
997-
Ok(Hostname(s))
998962
}
999963
}
1000-
impl Writeable for Hostname {
964+
impl Writeable for ShortAsciiString {
1001965
#[inline]
1002966
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
1003967
self.len().write(w)?;
1004968
w.write_all(self.as_bytes())
1005969
}
1006970
}
1007-
impl Readable for Hostname {
971+
impl Readable for ShortAsciiString {
1008972
#[inline]
1009-
fn read<R: Read>(r: &mut R) -> Result<Hostname, DecodeError> {
973+
fn read<R: Read>(r: &mut R) -> Result<ShortAsciiString, DecodeError> {
1010974
let len: u8 = Readable::read(r)?;
1011975
let mut vec = Vec::with_capacity(len.into());
1012976
vec.resize(len.into(), 0);
1013977
r.read_exact(&mut vec)?;
1014-
Hostname::try_from(vec).map_err(|_| DecodeError::InvalidValue)
978+
ShortAsciiString::try_from(vec).map_err(|_| DecodeError::InvalidValue)
1015979
}
1016980
}
1017981

@@ -1034,30 +998,23 @@ impl Readable for Duration {
1034998
#[cfg(test)]
1035999
mod tests {
10361000
use core::convert::TryFrom;
1037-
use util::ser::{Readable, Hostname, Writeable};
1001+
use util::ser::{Readable, ShortAsciiString, Writeable};
10381002

10391003
#[test]
1040-
fn hostname_conversion() {
1041-
assert_eq!(Hostname::try_from(String::from("test")).unwrap().as_str(), "test");
1042-
assert_eq!(Hostname::try_from(String::from("test-1")).unwrap().as_str(), "test-1");
1043-
assert_eq!(Hostname::try_from(String::from("1-test")).unwrap().as_str(), "1-test");
1044-
assert_eq!(Hostname::try_from(String::from("test.com")).unwrap().as_str(), "test.com");
1045-
assert_eq!(Hostname::try_from(String::from("test.com.")).unwrap().as_str(), "test.com.");
1046-
assert_eq!(Hostname::try_from(String::from("a.test.com")).unwrap().as_str(), "a.test.com");
1047-
1048-
assert!(Hostname::try_from(String::from("⚡")).is_err());
1049-
assert!(Hostname::try_from(String::from("-end")).is_err());
1050-
assert!(Hostname::try_from(String::from("start-")).is_err());
1004+
fn short_ascii_string_conversion() {
1005+
assert_eq!(ShortAsciiString::try_from(String::from("test")).unwrap().as_str(), "test");
1006+
1007+
assert!(ShortAsciiString::try_from(String::from("⚡")).is_err());
10511008
let mut large_vec = Vec::with_capacity(256);
10521009
large_vec.resize(256, b'A');
1053-
assert!(Hostname::try_from(String::from_utf8(large_vec).unwrap()).is_err());
1010+
assert!(ShortAsciiString::try_from(String::from_utf8(large_vec).unwrap()).is_err());
10541011
}
10551012

10561013
#[test]
1057-
fn hostname_serialization() {
1058-
let short_s = Hostname::try_from(String::from("test")).unwrap();
1014+
fn short_ascii_string_serialization() {
1015+
let short_s = ShortAsciiString::try_from(String::from("test")).unwrap();
10591016
let mut buf: Vec<u8> = Vec::new();
10601017
short_s.write(&mut buf).unwrap();
1061-
assert_eq!(Hostname::read(&mut buf.as_slice()).unwrap().as_str(), "test");
1018+
assert_eq!(ShortAsciiString::read(&mut buf.as_slice()).unwrap().as_str(), "test");
10621019
}
10631020
}

0 commit comments

Comments
 (0)