Skip to content

Commit daeb5a6

Browse files
authored
Merge pull request #1553 from wvanlint/dns_hostname
Adds DNS hostname to NetAddress
2 parents f3d5b94 + c30dcf1 commit daeb5a6

File tree

3 files changed

+151
-20
lines changed

3 files changed

+151
-20
lines changed

lightning/src/ln/channelmanager.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -2863,15 +2863,15 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
28632863

28642864
#[allow(dead_code)]
28652865
// Messages of up to 64KB should never end up more than half full with addresses, as that would
2866-
// be absurd. We ensure this by checking that at least 500 (our stated public contract on when
2866+
// be absurd. We ensure this by checking that at least 100 (our stated public contract on when
28672867
// broadcast_node_announcement panics) of the maximum-length addresses would fit in a 64KB
28682868
// message...
28692869
const HALF_MESSAGE_IS_ADDRS: u32 = ::core::u16::MAX as u32 / (NetAddress::MAX_LEN as u32 + 1) / 2;
28702870
#[deny(const_err)]
28712871
#[allow(dead_code)]
28722872
// ...by failing to compile if the number of addresses that would be half of a message is
2873-
// smaller than 500:
2874-
const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 500;
2873+
// smaller than 100:
2874+
const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 100;
28752875

28762876
/// Regenerates channel_announcements and generates a signed node_announcement from the given
28772877
/// arguments, providing them in corresponding events via
@@ -2888,13 +2888,13 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
28882888
/// tying these addresses together and to this node. If you wish to preserve user privacy,
28892889
/// addresses should likely contain only Tor Onion addresses.
28902890
///
2891-
/// Panics if `addresses` is absurdly large (more than 500).
2891+
/// Panics if `addresses` is absurdly large (more than 100).
28922892
///
28932893
/// [`get_and_clear_pending_msg_events`]: MessageSendEventsProvider::get_and_clear_pending_msg_events
28942894
pub fn broadcast_node_announcement(&self, rgb: [u8; 3], alias: [u8; 32], mut addresses: Vec<NetAddress>) {
28952895
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
28962896

2897-
if addresses.len() > 500 {
2897+
if addresses.len() > 100 {
28982898
panic!("More than half the message size was taken up by public addresses!");
28992899
}
29002900

lightning/src/ln/msgs.rs

+49-15
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};
43+
use util::ser::{Readable, Writeable, Writer, FixedLengthReader, HighZeroBytesDroppedVarInt, Hostname};
4444

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

@@ -442,6 +442,13 @@ pub enum NetAddress {
442442
/// The port on which the node is listening
443443
port: u16,
444444
},
445+
/// A hostname/port on which the peer is listening.
446+
Hostname {
447+
/// The hostname on which the node is listening.
448+
hostname: Hostname,
449+
/// The port on which the node is listening.
450+
port: u16,
451+
},
445452
}
446453
impl NetAddress {
447454
/// Gets the ID of this address type. Addresses in node_announcement messages should be sorted
@@ -452,6 +459,7 @@ impl NetAddress {
452459
&NetAddress::IPv6 {..} => { 2 },
453460
&NetAddress::OnionV2(_) => { 3 },
454461
&NetAddress::OnionV3 {..} => { 4 },
462+
&NetAddress::Hostname {..} => { 5 },
455463
}
456464
}
457465

@@ -462,11 +470,15 @@ impl NetAddress {
462470
&NetAddress::IPv6 { .. } => { 18 },
463471
&NetAddress::OnionV2(_) => { 12 },
464472
&NetAddress::OnionV3 { .. } => { 37 },
473+
// Consists of 1-byte hostname length, hostname bytes, and 2-byte port.
474+
&NetAddress::Hostname { ref hostname, .. } => { u16::from(hostname.len()) + 3 },
465475
}
466476
}
467477

468-
/// The maximum length of any address descriptor, not including the 1-byte type
469-
pub(crate) const MAX_LEN: u16 = 37;
478+
/// The maximum length of any address descriptor, not including the 1-byte type.
479+
/// This maximum length is reached by a hostname address descriptor:
480+
/// a hostname with a maximum length of 255, its 1-byte length and a 2-byte port.
481+
pub(crate) const MAX_LEN: u16 = 258;
470482
}
471483

472484
impl Writeable for NetAddress {
@@ -492,7 +504,12 @@ impl Writeable for NetAddress {
492504
checksum.write(writer)?;
493505
version.write(writer)?;
494506
port.write(writer)?;
495-
}
507+
},
508+
&NetAddress::Hostname { ref hostname, ref port } => {
509+
5u8.write(writer)?;
510+
hostname.write(writer)?;
511+
port.write(writer)?;
512+
},
496513
}
497514
Ok(())
498515
}
@@ -523,6 +540,12 @@ impl Readable for Result<NetAddress, u8> {
523540
port: Readable::read(reader)?,
524541
}))
525542
},
543+
5 => {
544+
Ok(Ok(NetAddress::Hostname {
545+
hostname: Readable::read(reader)?,
546+
port: Readable::read(reader)?,
547+
}))
548+
},
526549
_ => return Ok(Err(byte)),
527550
}
528551
}
@@ -1829,7 +1852,7 @@ mod tests {
18291852
use ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
18301853
use ln::msgs;
18311854
use ln::msgs::{FinalOnionHopData, OptionalField, OnionErrorPacket, OnionHopDataFormat};
1832-
use util::ser::{Writeable, Readable};
1855+
use util::ser::{Writeable, Readable, Hostname};
18331856

18341857
use bitcoin::hashes::hex::FromHex;
18351858
use bitcoin::util::address::Address;
@@ -1843,6 +1866,7 @@ mod tests {
18431866

18441867
use io::Cursor;
18451868
use prelude::*;
1869+
use core::convert::TryFrom;
18461870

18471871
#[test]
18481872
fn encoding_channel_reestablish_no_secret() {
@@ -1971,7 +1995,7 @@ mod tests {
19711995
do_encoding_channel_announcement(true, true);
19721996
}
19731997

1974-
fn do_encoding_node_announcement(unknown_features_bits: bool, ipv4: bool, ipv6: bool, onionv2: bool, onionv3: bool, excess_address_data: bool, excess_data: bool) {
1998+
fn do_encoding_node_announcement(unknown_features_bits: bool, ipv4: bool, ipv6: bool, onionv2: bool, onionv3: bool, hostname: bool, excess_address_data: bool, excess_data: bool) {
19751999
let secp_ctx = Secp256k1::new();
19762000
let (privkey_1, pubkey_1) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx);
19772001
let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101"));
@@ -2007,6 +2031,12 @@ mod tests {
20072031
port: 9735
20082032
});
20092033
}
2034+
if hostname {
2035+
addresses.push(msgs::NetAddress::Hostname {
2036+
hostname: Hostname::try_from(String::from("host")).unwrap(),
2037+
port: 9735,
2038+
});
2039+
}
20102040
let mut addr_len = 0;
20112041
for addr in &addresses {
20122042
addr_len += addr.len() + 1;
@@ -2047,6 +2077,9 @@ mod tests {
20472077
if onionv3 {
20482078
target_value.append(&mut hex::decode("04fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e00020102607").unwrap());
20492079
}
2080+
if hostname {
2081+
target_value.append(&mut hex::decode("0504686f73742607").unwrap());
2082+
}
20502083
if excess_address_data {
20512084
target_value.append(&mut hex::decode("216c280b5395a2546e7e4b2663e04f811622f15a4f92e83aa2e92ba2a573c139142c54ae63072a1ec1ee7dc0c04bde5c847806172aa05c92c22ae8e308d1d269").unwrap());
20522085
}
@@ -2058,15 +2091,16 @@ mod tests {
20582091

20592092
#[test]
20602093
fn encoding_node_announcement() {
2061-
do_encoding_node_announcement(true, true, true, true, true, true, true);
2062-
do_encoding_node_announcement(false, false, false, false, false, false, false);
2063-
do_encoding_node_announcement(false, true, false, false, false, false, false);
2064-
do_encoding_node_announcement(false, false, true, false, false, false, false);
2065-
do_encoding_node_announcement(false, false, false, true, false, false, false);
2066-
do_encoding_node_announcement(false, false, false, false, true, false, false);
2067-
do_encoding_node_announcement(false, false, false, false, false, true, false);
2068-
do_encoding_node_announcement(false, true, false, true, false, true, false);
2069-
do_encoding_node_announcement(false, false, true, false, true, false, false);
2094+
do_encoding_node_announcement(true, true, true, true, true, true, true, true);
2095+
do_encoding_node_announcement(false, false, false, false, false, false, false, false);
2096+
do_encoding_node_announcement(false, true, false, false, false, false, false, false);
2097+
do_encoding_node_announcement(false, false, true, false, false, false, false, false);
2098+
do_encoding_node_announcement(false, false, false, true, false, false, false, false);
2099+
do_encoding_node_announcement(false, false, false, false, true, false, false, false);
2100+
do_encoding_node_announcement(false, false, false, false, false, true, false, false);
2101+
do_encoding_node_announcement(false, false, false, false, false, false, true, false);
2102+
do_encoding_node_announcement(false, true, false, true, false, false, true, false);
2103+
do_encoding_node_announcement(false, false, true, false, true, false, false, false);
20702104
}
20712105

20722106
fn do_encoding_channel_update(direction: bool, disable: bool, htlc_maximum_msat: bool, excess_data: bool) {

lightning/src/util/ser.rs

+97
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ use io_extras::{copy, sink};
1616
use core::hash::Hash;
1717
use sync::Mutex;
1818
use core::cmp;
19+
use core::convert::TryFrom;
20+
use core::ops::Deref;
1921

2022
use bitcoin::secp256k1::{PublicKey, SecretKey};
2123
use bitcoin::secp256k1::constants::{PUBLIC_KEY_SIZE, SECRET_KEY_SIZE, COMPACT_SIGNATURE_SIZE};
@@ -935,6 +937,75 @@ impl Readable for String {
935937
}
936938
}
937939

940+
/// Represents a hostname for serialization purposes.
941+
/// Only the character set and length will be validated.
942+
/// The character set consists of ASCII alphanumeric characters, hyphens, and periods.
943+
/// Its length is guaranteed to be representable by a single byte.
944+
/// This serialization is used by BOLT 7 hostnames.
945+
#[derive(Clone, Debug, PartialEq)]
946+
pub struct Hostname(String);
947+
impl Hostname {
948+
/// Returns the length of the hostname.
949+
pub fn len(&self) -> u8 {
950+
(&self.0).len() as u8
951+
}
952+
}
953+
impl Deref for Hostname {
954+
type Target = String;
955+
956+
fn deref(&self) -> &Self::Target {
957+
&self.0
958+
}
959+
}
960+
impl From<Hostname> for String {
961+
fn from(hostname: Hostname) -> Self {
962+
hostname.0
963+
}
964+
}
965+
impl TryFrom<Vec<u8>> for Hostname {
966+
type Error = ();
967+
968+
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
969+
if let Ok(s) = String::from_utf8(bytes) {
970+
Hostname::try_from(s)
971+
} else {
972+
Err(())
973+
}
974+
}
975+
}
976+
impl TryFrom<String> for Hostname {
977+
type Error = ();
978+
979+
fn try_from(s: String) -> Result<Self, Self::Error> {
980+
if s.len() <= 255 && s.chars().all(|c|
981+
c.is_ascii_alphanumeric() ||
982+
c == '.' ||
983+
c == '-'
984+
) {
985+
Ok(Hostname(s))
986+
} else {
987+
Err(())
988+
}
989+
}
990+
}
991+
impl Writeable for Hostname {
992+
#[inline]
993+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
994+
self.len().write(w)?;
995+
w.write_all(self.as_bytes())
996+
}
997+
}
998+
impl Readable for Hostname {
999+
#[inline]
1000+
fn read<R: Read>(r: &mut R) -> Result<Hostname, DecodeError> {
1001+
let len: u8 = Readable::read(r)?;
1002+
let mut vec = Vec::with_capacity(len.into());
1003+
vec.resize(len.into(), 0);
1004+
r.read_exact(&mut vec)?;
1005+
Hostname::try_from(vec).map_err(|_| DecodeError::InvalidValue)
1006+
}
1007+
}
1008+
9381009
impl Writeable for Duration {
9391010
#[inline]
9401011
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
@@ -950,3 +1021,29 @@ impl Readable for Duration {
9501021
Ok(Duration::new(secs, nanos))
9511022
}
9521023
}
1024+
1025+
#[cfg(test)]
1026+
mod tests {
1027+
use core::convert::TryFrom;
1028+
use util::ser::{Readable, Hostname, Writeable};
1029+
1030+
#[test]
1031+
fn hostname_conversion() {
1032+
assert_eq!(Hostname::try_from(String::from("a-test.com")).unwrap().as_str(), "a-test.com");
1033+
1034+
assert!(Hostname::try_from(String::from("\"")).is_err());
1035+
assert!(Hostname::try_from(String::from("$")).is_err());
1036+
assert!(Hostname::try_from(String::from("⚡")).is_err());
1037+
let mut large_vec = Vec::with_capacity(256);
1038+
large_vec.resize(256, b'A');
1039+
assert!(Hostname::try_from(String::from_utf8(large_vec).unwrap()).is_err());
1040+
}
1041+
1042+
#[test]
1043+
fn hostname_serialization() {
1044+
let hostname = Hostname::try_from(String::from("test")).unwrap();
1045+
let mut buf: Vec<u8> = Vec::new();
1046+
hostname.write(&mut buf).unwrap();
1047+
assert_eq!(Hostname::read(&mut buf.as_slice()).unwrap().as_str(), "test");
1048+
}
1049+
}

0 commit comments

Comments
 (0)