-
Notifications
You must be signed in to change notification settings - Fork 375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds DNS hostname to NetAddress #1553
Conversation
lightning/src/util/ser.rs
Outdated
type Error = ConversionError; | ||
|
||
fn try_from(s: String) -> Result<Self, Self::Error> { | ||
if s.is_ascii() && s.len() <= u8::MAX.into() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should also check that all characters are in the printable range (and maybe no spaces? probably no special chars? Dunno what's valid in DNS, we should check). With that in mind, maybe we should name the type something in reference to DNS?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems DNS permits any sequence of bytes but has a preferred format. I implemented the preferred format based on RFC 3696 and others linked there.
lightning/src/ln/msgs.rs
Outdated
@@ -442,6 +442,14 @@ pub enum NetAddress { | |||
/// The port on which the node is listening | |||
port: u16, | |||
}, | |||
/// A DNS hostname/port on which the peer is listening. | |||
DNSHostname { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we just call it hostname? DNS is kinda obvious? Am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjusted that, I was mainly mirroring the BOLT PR.
Nice, thanks! Looks like this is failing CI. |
9518a45
to
8892a48
Compare
lightning/src/util/ser.rs
Outdated
|
||
fn try_from(s: String) -> Result<Self, Self::Error> { | ||
// Regular expressions can't be used with no-std. | ||
let labels: Vec<&str> = s.split(".").collect(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be able to avoid the collect
here. In general, allocating a Vec
via collect
is not super trivial, and we should avoid it if at all possible, preferring to just keep and work with the generated iterator directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
lightning/src/util/errors.rs
Outdated
@@ -78,6 +78,10 @@ impl fmt::Debug for APIError { | |||
} | |||
} | |||
|
|||
/// Indicates an error on conversions by core::convert traits. | |||
#[derive(Debug)] | |||
pub struct ConversionError; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this worth it? If its just a dummy type can we not just use ()
instead? It seems basically as clear either way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I initially wanted to implement the Error
trait for boxing purposes but I wasn't sure if it made sense to do this conditionally only when the standard library is used. Changed to ()
but let me know if you prefer a type with an Error
trait instead.
Codecov Report
@@ Coverage Diff @@
## main #1553 +/- ##
==========================================
+ Coverage 90.96% 91.00% +0.03%
==========================================
Files 80 80
Lines 43610 44197 +587
Branches 43610 44197 +587
==========================================
+ Hits 39670 40221 +551
- Misses 3940 3976 +36
Continue to review full report at Codecov.
|
lightning/src/util/ser.rs
Outdated
// Trailing period for fully-qualified name. | ||
if bytes.len() == 0 { | ||
if !last_label || label_idx == 0 { | ||
break false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of breaking out of the loop with a validity flag, the structure here would be more readable if we just returned the error directly if something is invalid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
lightning/src/util/ser.rs
Outdated
let last_label; | ||
if let None = labels.peek() { | ||
last_label = true; | ||
} else { | ||
last_label = false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let last_label; | |
if let None = labels.peek() { | |
last_label = true; | |
} else { | |
last_label = false; | |
} | |
let last_label = labels.peek().is_none(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
lightning/src/util/ser.rs
Outdated
let valid_labels = loop { | ||
let label; | ||
match labels.next() { | ||
Some(x) => label = x, | ||
None => break true, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let valid_labels = loop { | |
let label; | |
match labels.next() { | |
Some(x) => label = x, | |
None => break true, | |
} | |
while let Some(label) = labels.next() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
lightning/src/util/ser.rs
Outdated
|
||
fn try_from(s: String) -> Result<Self, Self::Error> { | ||
let mut labels = s.split('.').peekable(); | ||
let mut label_idx = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of tracking the idx explicitly, maybe just wrap labels
with an .enumerate()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
lightning/src/util/ser.rs
Outdated
} | ||
} | ||
} | ||
impl TryFrom<&str> for Hostname { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This gives the (incorrect) impression that From<&str>
is relatively efficient, but its not. Its maybe simpler to force the user to do the String::from()
or .to_string()
explicitly themselves to communicate what's really going on here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true, removed this implementation.
It looks like somehow your rebase ended up reverting several recent PRs. |
Oops, sorry, it looks like the GitHub mobile app just...shows incorrect diffs sometimes? This basically LGTM, lets get another reviewer on it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically LGTM.
lightning/src/util/ser.rs
Outdated
#[derive(Clone, Debug, PartialEq)] | ||
pub struct Hostname(String); | ||
impl Hostname { | ||
/// Returns the length of the hostname with an appropriate return type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/with an appropriate return type//?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for having a go at this! Generally looks good, only a few nits and questions.
lightning/src/ln/msgs.rs
Outdated
@@ -442,6 +442,13 @@ pub enum NetAddress { | |||
/// The port on which the node is listening | |||
port: u16, | |||
}, | |||
/// A hostname/port on which the peer is listening. | |||
Hostname { | |||
/// The hostname on which the port is listening. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think "port" should be "node" or "peer"?
/// The hostname on which the port is listening. | |
/// The hostname on which the node is listening. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally LGTM.
One note: it's easier for reviewers to follow the changes if you do not immediately squash them, but leave individual commits.
Sorry for the delay, been a super busy week. Generally, now that we have all the logic for it, and now that I think about it a bit more, do we really need to do this much verification of a hostname? Like, yea, the DNS won't resolve if the hostname is just one long string, but what happens if users start shoving non-hostname things in the hostname field (ie treating it as a second node alias, listing some policy info, etc) - should we outright drop their gossip, or simply fail to connect to the hostname and try the IP addresses instead? I do think we should ensure the strong is ASCII, is all in the printable range (ie no control chars) but do we need to care about label length? |
@TheBlueMatt I agree, the concern of hostname validation can be left to DNS resolution and separated from the serialization concern here which was my original intent. I reverted back to the first approach with generic serialization prior to #1553 (comment). Extending this rationale, I would also be open to relaxing validation further and allowing any UTF-8 string within the length constraint (although this is not included in the BOLT). Libraries are able to handle Punycode encoding e.g. Out of curiosity, are terminal escape sequence injections the main concern with control characters? I am unsure about their severity for modern terminals. |
Hmm, there's two sides to this, though - we have to support reading hostnames in announcements and be kinda liberal there, but also want to be restrictive as to what users include as others may do strict validation. In theory we could split the two but I'm not sure it's really worth it - our users are developers, and can manage to just put a hostname.
Yea, you never know, users of our devlopers' software will grep things and pass them to dig and...boom. With that in mind I'd suggest we also reject chars like $, ", ', backtick, etc. Probably easiest to just accept alphanumeric plus . and -. If its easy its best to be as conservative as possible but not bother doing strict hostname validation so much as just strict character set validation. |
fc3c757
to
2767a41
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oooooooo-Kkkkkkkk. Thanks for sticking with me on this one, this LGTM as-is. Will let the other reviewers chime in, but feel free to squash down the fixups once they do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I just restarted the one stuck CI job.
Thanks for the review as well! Squashed down the fixups. |
Fixes a deserialization incompatibility introduced with lightningdevkit#1553.
Supports Bolt 7 DNS hostnames specified by lightning/bolts#911.